From 17dbf17379e2e519fd6aea1e77b2ea1adfdfaba3 Mon Sep 17 00:00:00 2001 From: Marno van der Maas Date: Thu, 23 Jan 2025 11:38:37 +0000 Subject: [PATCH] Update lowrisc_ibex to lowrisc/cheriot-ibex@4bca0614 Update code from upstream repository https://github.com/lowrisc/cheriot-ibex.git to revision 4bca0614d5fc5ecec606bd91c87b350d177d53ea * Nix formatting (Marno van der Maas) * Feed RV32M through ibexc_top_tracing/ibexc_top (Greg Chadwick) * Switch to no bitmanip by default (Greg Chadwick) * RV32B parameter now passed in ibexc_top (Marno van der Maas) * Add UNOPTFLAT waiver to ibex_id_stage (Adrian Lees) * Patched prim_arbiter.vlt file (Adrian Lees) * Patch to add UNOPTFLAT waiver to prim_arbiter_ppc (Adrian Lees) * [rtl] Fix ICache scramble key valid input (Greg Chadwick) * [rtl] Enable use of ICache with ibexc_top (Greg Chadwick) * [util] Update check_tool_requirements.py (Gary Guo) * Update lowrisc_ip to lowRISC/opentitan@f235838a9e (Marno van der Maas) * Added patch to remove alert prim from all group (Marno van der Maas) * [vendor] Patch updated based on OpenTitan/36a2d3c (Marno van der Maas) * [dv] Alter cov_merge.tcl patch so icache coverage collection works (Greg Chadwick) * Add patch for lowrisc_ip (Harry Callahan) * [vendor] Update patch file based on upstream OpenTitan (Marno van der Maas) * Feed CHERI errors out to top module (Marno van der Maas) * Remove prim alert from build (Marno van der Maas) * Fix tracing (Marno van der Maas) * Update two port RAM for Sonata (Marno van der Maas) * Patch reading memory files taken from upstream (Marno van der Maas) * Various Verilator lint patches (Marno van der Maas) * Use ibexc_top since that is used in SAFE (Marno van der Maas) * Add FPGA primitives (Marno van der Maas) * Bump jinja2 from 3.1.4 to 3.1.5 in /dv/formal (dependabot[bot]) * Bump mako from 1.1.6 to 1.2.2 in /dv/formal (dependabot[bot]) * Formal verification flow for CHERIoT Ibex (mndstrmr) * fixed typos in previous commit (cheri_regfile) (kliuMsft) * fixed issue lowrisc/cheriot-ibex#59 (kliuMsft) * added support for the new cap bounds encoding (implict T8) and the corresponding top-level parameter CheriCapIT8 (kliuMsft) * Minor fixes in ibex_tracer for rv32 mode (kliuMsft) * Add default parameters to fix build under Xcelium (Greg Chadwick) * Update GitHub upload-artifact action to v4 (Nathaniel Wesley Filardo) * minor sv style cleanup (kliuMsft) * changes to align with ISA 1.0 release (kliuMsft) * Base correction only needs one bit (Marno van der Maas) * fixed rvfi_rd_addr for c.srai64 and c.slli64 (kliuMsft) * fixed bit extension instr decoding (issue lowrisc/cheriot-ibex#47) (kliuMsft) * fixed decoder for illegal_reg_cheri/rv32e generation in the case of use_rs3 instructions (kliuMsft) * PVIO needs 3 bit indexes not 4 (Marno van der Maas) * cheri_ex_err_info flop signals weren't used (Marno van der Maas) * added another yml (Nazerke Turtayeva) * adding files (Nazerke Turtayeva) Signed-off-by: Marno van der Maas --- vendor/lowrisc_ibex.lock.hjson | 2 +- .../.github/workflows/pr_trigger.yml | 2 +- vendor/lowrisc_ibex/.gitmodules | 0 vendor/lowrisc_ibex/dma-ip/DMA/dma-v3.sv | 562 +++++++++++ vendor/lowrisc_ibex/dma-ip/DMA/dma-v4.sv | 789 +++++++++++++++ vendor/lowrisc_ibex/dma-ip/DMA/dma.sv | 443 +++++++++ .../lowrisc_ibex/dma-ip/dvp_ibex_wrapper.yml | 175 ++++ vendor/lowrisc_ibex/dma-ip/hsp_encr_level.yml | 320 +++++++ vendor/lowrisc_ibex/dma-ip/ibex_memory.sv | 224 +++++ vendor/lowrisc_ibex/dma-ip/ibex_subsystem.yml | 137 +++ vendor/lowrisc_ibex/dma-ip/ibexc_obimux3w0.sv | 895 ++++++++++++++++++ .../dv/cheriot/fcov/core_ibex_fcov_if.sv | 60 +- .../dv/cheriot/scripts/compare_trace.py | 4 +- .../dv/cheriot/tb/cheriot_dv_pkg.sv | 8 +- vendor/lowrisc_ibex/dv/formal/.gitignore | 3 + vendor/lowrisc_ibex/dv/formal/Makefile | 90 ++ vendor/lowrisc_ibex/dv/formal/README.md | 44 + vendor/lowrisc_ibex/dv/formal/Sources.mk | 43 + vendor/lowrisc_ibex/dv/formal/automated.tcl | 40 + .../lowrisc_ibex/dv/formal/check/encodings.sv | 152 +++ .../lowrisc_ibex/dv/formal/check/peek/abs.sv | 145 +++ .../dv/formal/check/peek/alt_lsu.sv | 187 ++++ .../dv/formal/check/peek/capdti.sv | 185 ++++ .../dv/formal/check/peek/compare_helper.sv | 87 ++ .../dv/formal/check/peek/follower.sv | 132 +++ .../lowrisc_ibex/dv/formal/check/peek/mem.sv | 160 ++++ .../lowrisc_ibex/dv/formal/check/peek/pcc.sv | 32 + .../dv/formal/check/protocol/irqs.sv | 36 + .../dv/formal/check/protocol/mem.sv | 48 + .../dv/formal/check/spec_instance.sv | 97 ++ vendor/lowrisc_ibex/dv/formal/check/top.sv | 515 ++++++++++ .../lowrisc_ibex/dv/formal/ibex_formal.core | 32 + .../dv/formal/patches/ibex_top.diff | 31 + vendor/lowrisc_ibex/dv/formal/poetry.lock | 521 ++++++++++ vendor/lowrisc_ibex/dv/formal/pyproject.toml | 26 + vendor/lowrisc_ibex/dv/formal/spec/cheri.sv | 132 +++ .../lowrisc_ibex/dv/formal/spec/cull_funcs.py | 24 + .../dv/formal/spec/extract_funcs.py | 33 + .../dv/formal/spec/fix_pmp_bug.py | 34 + vendor/lowrisc_ibex/dv/formal/spec/main.sail | 112 +++ .../lowrisc_ibex/dv/formal/spec/spec_api.sv | 434 +++++++++ vendor/lowrisc_ibex/dv/formal/spec/stub.sv | 92 ++ .../dv/formal/spec/unreachable_loc_info.py | 22 + vendor/lowrisc_ibex/dv/formal/thm/btype.proof | 45 + vendor/lowrisc_ibex/dv/formal/thm/dti.proof | 47 + vendor/lowrisc_ibex/dv/formal/thm/ibex.proof | 391 ++++++++ vendor/lowrisc_ibex/dv/formal/thm/mem.proof | 212 +++++ vendor/lowrisc_ibex/dv/formal/thm/riscv.proof | 212 +++++ vendor/lowrisc_ibex/dv/formal/verify.tcl | 131 +++ vendor/lowrisc_ibex/flake.lock | 380 ++++++++ vendor/lowrisc_ibex/flake.nix | 163 ++++ .../lowrisc_ibex/nix/lowrisc_cheriot_sail.nix | 15 + vendor/lowrisc_ibex/nix/lowrisc_sail.nix | 23 + vendor/lowrisc_ibex/rtl/cheri_decoder.sv | 2 + vendor/lowrisc_ibex/rtl/cheri_ex.sv | 68 +- vendor/lowrisc_ibex/rtl/cheri_pkg.sv | 527 +++++++++-- vendor/lowrisc_ibex/rtl/cheri_regfile.sv | 18 +- vendor/lowrisc_ibex/rtl/cheri_stkz.sv | 8 +- vendor/lowrisc_ibex/rtl/cheri_trvk_stage.sv | 6 +- vendor/lowrisc_ibex/rtl/ibex_core.sv | 38 +- vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv | 3 +- vendor/lowrisc_ibex/rtl/ibex_decoder.sv | 11 +- vendor/lowrisc_ibex/rtl/ibex_id_stage.sv | 8 +- .../lowrisc_ibex/rtl/ibex_load_store_unit.sv | 19 +- vendor/lowrisc_ibex/rtl/ibex_lockstep.sv | 6 +- vendor/lowrisc_ibex/rtl/ibex_tracer.sv | 51 +- vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv | 1 + vendor/lowrisc_ibex/rtl/ibexc_top.sv | 9 +- vendor/lowrisc_ibex/rtl/ibexc_top_tracing.sv | 11 +- 69 files changed, 9307 insertions(+), 208 deletions(-) create mode 100644 vendor/lowrisc_ibex/.gitmodules create mode 100644 vendor/lowrisc_ibex/dma-ip/DMA/dma-v3.sv create mode 100644 vendor/lowrisc_ibex/dma-ip/DMA/dma-v4.sv create mode 100644 vendor/lowrisc_ibex/dma-ip/DMA/dma.sv create mode 100644 vendor/lowrisc_ibex/dma-ip/dvp_ibex_wrapper.yml create mode 100644 vendor/lowrisc_ibex/dma-ip/hsp_encr_level.yml create mode 100644 vendor/lowrisc_ibex/dma-ip/ibex_memory.sv create mode 100644 vendor/lowrisc_ibex/dma-ip/ibex_subsystem.yml create mode 100644 vendor/lowrisc_ibex/dma-ip/ibexc_obimux3w0.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/.gitignore create mode 100644 vendor/lowrisc_ibex/dv/formal/Makefile create mode 100644 vendor/lowrisc_ibex/dv/formal/README.md create mode 100644 vendor/lowrisc_ibex/dv/formal/Sources.mk create mode 100644 vendor/lowrisc_ibex/dv/formal/automated.tcl create mode 100644 vendor/lowrisc_ibex/dv/formal/check/encodings.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/abs.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/alt_lsu.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/capdti.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/compare_helper.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/follower.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/mem.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/peek/pcc.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/protocol/irqs.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/protocol/mem.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/spec_instance.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/check/top.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/ibex_formal.core create mode 100644 vendor/lowrisc_ibex/dv/formal/patches/ibex_top.diff create mode 100644 vendor/lowrisc_ibex/dv/formal/poetry.lock create mode 100644 vendor/lowrisc_ibex/dv/formal/pyproject.toml create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/cheri.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/cull_funcs.py create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/extract_funcs.py create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/fix_pmp_bug.py create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/main.sail create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/spec_api.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/stub.sv create mode 100644 vendor/lowrisc_ibex/dv/formal/spec/unreachable_loc_info.py create mode 100644 vendor/lowrisc_ibex/dv/formal/thm/btype.proof create mode 100644 vendor/lowrisc_ibex/dv/formal/thm/dti.proof create mode 100644 vendor/lowrisc_ibex/dv/formal/thm/ibex.proof create mode 100644 vendor/lowrisc_ibex/dv/formal/thm/mem.proof create mode 100644 vendor/lowrisc_ibex/dv/formal/thm/riscv.proof create mode 100644 vendor/lowrisc_ibex/dv/formal/verify.tcl create mode 100644 vendor/lowrisc_ibex/flake.lock create mode 100644 vendor/lowrisc_ibex/flake.nix create mode 100644 vendor/lowrisc_ibex/nix/lowrisc_cheriot_sail.nix create mode 100644 vendor/lowrisc_ibex/nix/lowrisc_sail.nix diff --git a/vendor/lowrisc_ibex.lock.hjson b/vendor/lowrisc_ibex.lock.hjson index 2572a83f2..f1b26adc1 100644 --- a/vendor/lowrisc_ibex.lock.hjson +++ b/vendor/lowrisc_ibex.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/lowrisc/cheriot-ibex.git - rev: adc4803d5d13cdf5a629b3f53fb4ce8d1ac38fe5 + rev: 4bca0614d5fc5ecec606bd91c87b350d177d53ea } } diff --git a/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml b/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml index b969698b2..a0b0ef933 100644 --- a/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml +++ b/vendor/lowrisc_ibex/.github/workflows/pr_trigger.yml @@ -19,7 +19,7 @@ jobs: # so we just save the file needed to do the review # in a context with proper access rights - name: Upload event file as artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: event.json path: event.json diff --git a/vendor/lowrisc_ibex/.gitmodules b/vendor/lowrisc_ibex/.gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/lowrisc_ibex/dma-ip/DMA/dma-v3.sv b/vendor/lowrisc_ibex/dma-ip/DMA/dma-v3.sv new file mode 100644 index 000000000..8947e157b --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/DMA/dma-v3.sv @@ -0,0 +1,562 @@ + +module dma import cheri_pkg::*; #( + parameter int unsigned RegisterCount = 6, + // check these values from dvp_ibex_core_wrapper + parameter int unsigned HeapBase = 32'h2000_0000, + parameter int unsigned TSMapBase = 32'h200f_0000, // 4kB default + parameter int unsigned TSMapTop = 32'h200f_2000, + parameter int unsigned TSMapSize = 2048, // 32-bit words + parameter bit CHERIoTEn = 1'b1, + parameter bit CheriPPLBC = 1'b1 +) ( + input clk_i, + input rstn_i, + + // OBI interface for configurations + input reg dma_conf_en_i, + input reg [31:0] dma_conf_addr_i, + + input reg [32:0] dma_conf_wdata_i, + input reg dma_conf_we_i, + + // todo: we assume we do not use it yet + input reg [3:0] dma_conf_be_i, + + // todo: this interface is not tested yet + output [32:0] dma_conf_rdata_o, + + output dma_conf_ready_o, + // todo: we assume we do not use it yet + output dma_conf_error_o, + + // interrupt interface + output reg dma_completion_intc_o, + + // Deliver to target + output reg dma_controller_req_o, + input dma_controller_gnt_i, + + output reg [31:0] dma_controller_addr_o, + // todo: we assume we do not use it yet + output reg [3:0] dma_controller_be_o, + output reg [32:0] dma_controller_wdata_o, + output reg dma_controller_we_o, + + // Read from source + input [32:0] dma_controller_rdata_i, + input dma_controller_rvalid_i, + // todo: we assume we do not use it yet + input dma_controller_error_i, + + // this interface is remained to connect to the + // temporary safety shadow map + // todo: but how to differentiate between cpu's tsmap outputs? + output logic dma_tsmap_cs_o, + output logic [15:0] dma_tsmap_addr_o, + input logic [31:0] dma_tsmap_rdata_i, + input logic tsmap_is_occupied_i, + + input logic snooped_tsmap_cs_i, + input logic [15:0] snooped_tsmap_addr_i, + input logic [31:0] snooped_tsmap_rdata_i +); + +// MMAP-able configuration registers +logic [RegisterCount-1:0][31:0] conf_registers, conf_registers_n; +// Capabilities are 66 bits at the hw, with tag bits +// being replicated at the beginning of each word +logic [65:0] source_capability, source_capability_n; +logic [65:0] target_capability, target_capability_n; + +///////////////////////////////////////////////////////// +// Register roles: +// +// Source and target capabilities are +// in separate registers and indexed at addresses +// 0, 1 and 2, 3 +// +// For the rest of offset, we save the configurations +// in the array of registers +// +// conf_registers[0] for DMA transfer length in bytes +// conf_registers[1] for DMA source stride value +// conf_registers[2] for DMA target stride value +// conf_registers[3] for DMA control register: +// - includes start('b0), endianness conversion('b1 and 2), reset ('b3) +// - start bit is meant to be set at the end while programming +// conf_registers[4] for DMA status register +// - first bit shows the halted status: 0 for idle, and 1 for running +// conf_registers[5] for free command from allocator() to DMA +// +///////////////////////////////////////////////////////// + +// Backpressure registers in case target is not available +logic [31:0] read_data_register, read_data_register_n; +// logic [31:0] write_register, write_register_n; + +// states are similar to each other +typedef enum logic [2:0] { IDLE, REQUEST_DATA, WAIT_FOR_DATA, SEND_DATA, ADDRESS_GEN, + RESTART, DMA_HALT_FOR_CHECK } state_t; + +state_t state, state_n; +state_t previous_state, previous_state_n; + +logic [31:0] read_data_ctr, read_data_ctr_n; + +// data is expected to be valid and delivered after single cycle +logic [31:0] read_status_reg, read_status_reg_n; +logic [31:0] source_offset, source_offset_n; +logic [31:0] target_offset, target_offset_n; + +// When allocator writes to this interface, +// we should halt the dma operation, to conduct checks +logic addresses_are_freed; + +// restarting dma if there is any request for it +logic restart_dma; +assign restart_dma = conf_registers[3][3]; + +/////////////////////////////////////////// +// Alternative 1: Following is the logic +// to check the revocation map when free() +// happens at the allocator +/////////////////////////////////////////// + +// need to stop the dma when the freed() region +// turns out to be dma addresses +logic force_stop; +logic first_request_send, first_request_send_n; +logic second_request_send, second_request_send_n; +logic checks_finished, checks_finished_delayed; + +// these are interface between the revoker and the dma +// todo: assign these values! +logic [31:0] dma_cap_placeholder; +logic [31:0] tsmap_ptr; +assign tsmap_ptr = (dma_cap_placeholder - HeapBase) >> 3; +assign dma_tsmap_addr_o = tsmap_ptr[15:5]; + +logic [4:0] bitpos; +assign bitpos = tsmap_ptr[4:0]; + +// todo: fail if the range is wrong later! +logic correct_range; +assign correct_range = (dma_tsmap_addr_o <= TSMapSize); + +logic clear_tag; +assign clear_tag = dma_tsmap_rdata_i[bitpos]; + +/////////////////////////////////////////// +// Alternative 2: Following is the logic +// to check the snooped tsmap operations +// for the similarity with dma addresses +// and the revocation status. +// +// todo: There are probably some wires that can +// be joined between alternatives, but +// we want to keep things separate for the +// evaluation +/////////////////////////////////////////// +logic snooped_addr_similar, snooped_addr_revoked; + +logic [31:0] source_address_base, source_address_tsmap; +logic [31:0] target_address_base, target_address_tsmap; + +assign source_address_base = (source_capability[31:0] - HeapBase) >> 3; +assign source_address_tsmap = source_address_base[15:5]; + +assign target_address_base = (target_capability[31:0] - HeapBase) >> 3; +assign target_address_tsmap = target_address_base[15:5]; + +logic [4:0] source_bitpos, target_bitpos; +assign source_bitpos = source_address_base[4:0]; +assign target_bitpos = target_address_base[4:0]; + +assign snooped_addr_similar = snooped_tsmap_cs_i ? + (source_address_tsmap == snooped_tsmap_addr_i) || + (target_address_tsmap == snooped_tsmap_addr_i) + : 0; + +assign snooped_addr_revoked = snooped_addr_similar && + (snooped_tsmap_rdata_i[source_bitpos] || + snooped_tsmap_rdata_i[target_bitpos]); + +/////////////////////////////////////////// +// Alternative 3: Here, we conduct the +// checks for capabilities at the HW +/////////////////////////////////////////// + +logic [PERMS_W-1:0] source_perms; +logic [PERMS_W-1:0] target_perms; + +assign source_perms = expand_perms(source_capability[63:58]); +assign target_perms = expand_perms(target_capability[63:58]); + +logic source_global, source_load; +logic target_global, target_store; + +assign source_global = source_perms[PERM_GL]; +assign source_load = source_perms[PERM_LD]; + +assign target_global = target_perms[PERM_GL]; +assign target_store = target_perms[PERM_SD]; + +logic source_unsealed, target_unsealed; + +assign source_unsealed = !(source_perms[PERM_US] & source_perms[PERM_SE]); +assign target_unsealed = !(target_perms[PERM_US] & target_perms[PERM_SE]); + +logic source_bounded, target_bounded; + +logic [TOP_W-1:0] source_top_addr, target_top_addr; +logic [BOT_W-1:0] source_base_addr, target_base_addr; +logic [EXP_W-1:0] source_exp_addr, target_exp_addr; +logic [31:0] source_address_generic, target_address_generic; + +assign source_top_addr = source_capability[41:33]; +assign source_base_addr = source_capability[50:42]; +assign source_exp_addr = source_capability[54:51]; +assign source_address_generic = source_capability[31:0]; + +assign target_top_addr = target_capability[41:33]; +assign target_base_addr = target_capability[50:42]; +assign target_exp_addr = target_capability[54:51]; +assign target_address_generic = target_capability[31:0]; + +logic [32:0] source_top_bound, target_top_bound; + +logic [3:0] source_cor, target_cor; +logic [1:0] source_top_cor, target_top_cor; +logic [8:0] source_mid_address, target_mid_address; + +assign source_mid_address = source_address_generic >> source_exp_addr; +assign target_mid_address = target_address_generic >> target_exp_addr; + +assign source_cor = update_temp_fields(source_top_addr, source_base_addr, + source_mid_address); +assign target_cor = update_temp_fields(target_top_addr, target_base_addr, + target_mid_address); + +assign source_top_cor = source_cor[3:2]; +assign target_top_cor = target_cor[3:2]; + +assign source_top_bound = get_bound33(source_top_addr, source_top_cor, + source_exp_addr, source_address_generic); + +assign target_top_bound = get_bound33(target_top_addr, target_top_cor, + target_exp_addr, target_address_generic); +logic [31:0] dma_length; +assign dma_length = conf_registers[0]; + +assign source_bounded = (source_top_bound >= (source_address_generic + dma_length)); +assign target_bounded = (target_top_bound >= (target_address_generic + dma_length)); + +logic source_address_valid, target_address_valid; + +// bit 65 and 32 of capability registers are for the valid tags +assign source_address_valid = source_capability[65] & source_global & + source_load & source_unsealed & source_bounded; + +assign target_address_valid = target_capability[65] & target_global & + target_store & target_unsealed & target_bounded; + +always_ff @( posedge clk_i ) begin : setReset + if (!rstn_i | restart_dma | force_stop | snooped_addr_revoked) begin + state <= IDLE; + previous_state <= IDLE; + read_data_register <= 0; + conf_registers <= 0; + source_capability <= 0; + target_capability <= 0; + read_data_ctr <= 0; + read_status_reg <= 0; + source_offset <= 0; + target_offset <= 0; + first_request_send <= 0; + second_request_send <= 0; + addresses_are_freed <= 0; + checks_finished_delayed <= 0; + end else if (!addresses_are_freed & conf_registers[5]) begin + // in order to avoid the repetitive check + // in the comb blocks assigning things here + previous_state <= state; + state <= DMA_HALT_FOR_CHECK; + addresses_are_freed <= conf_registers[5]; + checks_finished_delayed <= checks_finished; + end else begin + state <= state_n; + previous_state <= previous_state_n; + read_data_register <= read_data_register_n; + conf_registers <= conf_registers_n; + read_data_ctr <= read_data_ctr_n; + read_status_reg <= read_status_reg_n; + source_offset <= source_offset_n; + target_offset <= target_offset_n; + first_request_send <= first_request_send_n; + second_request_send <= second_request_send_n; + addresses_are_freed <= conf_registers[5]; + checks_finished_delayed <= checks_finished; + source_capability <= source_capability_n; + target_capability <= target_capability_n; + end +end + +////////////////////////////////////// +// Step 0: Configurations +////////////////////////////////////// + +// always ready to be written and read in IDLE +// assign dma_conf_ready_o = (state == IDLE) || (state == RESTART); +assign dma_conf_ready_o = 1'b1; +assign dma_conf_error_o = 0; + +// index of configuration registers decoded +logic [15:0] index; +assign index = dma_conf_addr_i[7:0] >> 2; + +// todo: we need to fix the decoding for read later +assign read_status_reg_n = (dma_conf_en_i & !dma_conf_we_i) + ? conf_registers[index] + : read_status_reg; + +assign dma_conf_rdata_o = read_status_reg; + +// we assume that software can always see the status via reading the registers, +// hence leave the responsibility to overwrite the dma configurations to the programmer. +// offset is 4, because the first two are for the capabilities +generate + for (genvar i=0; i < RegisterCount-3; i++) begin + assign conf_registers_n[i] = ((state == IDLE)) + ? (dma_conf_en_i && dma_conf_we_i && ((i+4) == index)) + ? dma_conf_wdata_i + : conf_registers[i] + : conf_registers[i]; + end +endgenerate + +// todo: we should be able to write to the control register any time +// to stop the process? +// todo: then we have to also decouple the byte swap bits +// to the second register to avoid the problem with control vs conf sync +assign conf_registers_n[3] = (dma_conf_en_i && dma_conf_we_i && (index == 7)) + ? dma_conf_wdata_i + : conf_registers[3]; + +// this register is written only internally from this hw +assign conf_registers_n[4] = conf_registers[4]; + +assign conf_registers_n[5] = (dma_conf_en_i && dma_conf_we_i && (index == 9)) + ? dma_conf_wdata_i + : (checks_finished) + ? 0 + : conf_registers[5]; + +always_comb begin : assignCapabilities + source_capability_n = source_capability; + target_capability_n = target_capability; + + if (state == IDLE) begin + // setting a source capability here + if (dma_conf_en_i && dma_conf_we_i) begin + if (index == 0) begin + source_capability_n[32:0] = dma_conf_wdata_i; + end else if (index == 1) begin + source_capability_n[65:33] = dma_conf_wdata_i; + end + + // setting a target capability here + if (index == 2) begin + target_capability_n[32:0] = dma_conf_wdata_i; + end else if (index == 3) begin + target_capability_n[65:33] = dma_conf_wdata_i; + end + end + end + +end + +/////////////////////////////////////////////////////// +// Step 1: Requesting and receiving a data from the source +/////////////////////////////////////////////////////// + +// todo: we assume we do not use it yet +assign dma_controller_be_o = 'hf; + +// increment in terms of 4's +// choose between the source and target addresses to +// read the data from vs to write the data to +assign dma_controller_addr_o = dma_controller_req_o + ? dma_controller_we_o + ? (target_capability[31:0] + target_offset) + : (source_capability[31:0] + source_offset) + : 0; + +assign read_data_register_n = (state == WAIT_FOR_DATA) & dma_controller_rvalid_i + ? dma_controller_rdata_i + : read_data_register; + +/////////////////////////////////////////////////////// +// Step 2: Sending a data to the target +/////////////////////////////////////////////////////// +logic target_data_valid; + +assign target_data_valid = dma_controller_req_o & dma_controller_we_o; + +logic two_byte_swap, four_byte_swap; + +assign two_byte_swap = conf_registers[3][1]; +assign four_byte_swap = conf_registers[3][2]; + +always_comb begin : assignTargetData + dma_controller_wdata_o = 0; + + if (target_data_valid) begin + if (two_byte_swap) begin + dma_controller_wdata_o = {16'b0, read_data_register[7:0], read_data_register[15:8]}; + end else if (four_byte_swap) begin + dma_controller_wdata_o = {read_data_register[7:0], read_data_register[15:8], + read_data_register[23:16], read_data_register[31:24]}; + end else begin + dma_controller_wdata_o = read_data_register; + end + end +end + +logic start_dma; +assign start_dma = conf_registers[3][0]; + +// for the start, we implement a simple DMA +// with single copy operation with one channel +always_comb begin : single_copy_FSM + state_n = state; + previous_state_n = previous_state; + + read_data_ctr_n = read_data_ctr; + + source_offset_n = read_data_ctr * (conf_registers[1] + 'b1); + target_offset_n = read_data_ctr * (conf_registers[2] + 'b1); + + dma_controller_req_o = 0; + dma_controller_we_o = 0; + + dma_completion_intc_o = 0; + + force_stop = 1'b0; + first_request_send_n = first_request_send; + second_request_send_n = second_request_send; + + dma_tsmap_cs_o = 0; + dma_cap_placeholder = 0; + + checks_finished = 0; + + case (state) + IDLE: begin + if (start_dma & source_address_valid & target_address_valid) begin + state_n = REQUEST_DATA; + end + end + REQUEST_DATA: begin + // check whether we already received the expected amount of data + // unless otherwise, keep receiving a data + + // gnt result should be available in the same cycle + dma_controller_req_o = 1'b1; + + if (read_data_ctr == dma_length) begin + read_data_ctr_n = 0; + state_n = RESTART; + dma_controller_req_o = 1'b0; + + // interrupt is high only single cycle + dma_completion_intc_o = 1'b1; + end else if (checks_finished_delayed) begin + if (!dma_controller_gnt_i) begin + checks_finished = 1'b1; + end else begin + state_n = WAIT_FOR_DATA; + end + end else if (read_data_ctr == (dma_length/2)) begin + // todo: ideally need to remove this condition later + // for free() to happen naturally + // just wait here, until addresses are freed happens + dma_controller_req_o = 1'b0; + end else if (dma_controller_gnt_i) begin + state_n = WAIT_FOR_DATA; + end + + end + WAIT_FOR_DATA: begin + // we will accept data, once it is valid irrespective + // of its ready status. + // this addtional cycle is to save the data to a register + // for avoiding back pressure + if (dma_controller_rvalid_i) begin + state_n = SEND_DATA; + end + end + SEND_DATA: begin + dma_controller_req_o = 1'b1; + dma_controller_we_o = 1'b1; + + if (dma_controller_gnt_i) begin + state_n = ADDRESS_GEN; + read_data_ctr_n = read_data_ctr_n + 'd4; + end + end + ADDRESS_GEN: begin + // this additional cycle is for address generation + // and to remove multiplication from the critical path + state_n = REQUEST_DATA; + end + RESTART: begin + if (restart_dma) begin + // the next dma can only launch + // when the previous one was resetted + state_n = IDLE; + end + end + DMA_HALT_FOR_CHECK: begin + if (clear_tag) begin + force_stop = 1'b1; + // technically this should be cleared on its own + // at the first reset/force_stop block above + state_n = IDLE; + first_request_send_n = 1'b0; + second_request_send_n = 1'b0; + end else if (first_request_send & second_request_send & !clear_tag) begin + // if both requests were sent and acknowledged + // and no clear tag request still + // we can switch back to the previous state + state_n = previous_state; + previous_state_n = IDLE; + first_request_send_n = 0; + second_request_send_n = 0; + checks_finished = 1'b1; + end else if (first_request_send & !clear_tag) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = target_capability[31:0]; + + if (!tsmap_is_occupied_i) begin + second_request_send_n = 1'b1; + end + + end else if(!first_request_send) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = source_capability[31:0]; + + if (!tsmap_is_occupied_i) begin + first_request_send_n = 1'b1; + end + + end + // todo: here make sure to alternate between + // the tests for the source and target addr + // todo: also we do not have any info about the + // actual capabilities, need to transfer them as well at the very beginning? + end + endcase +end + + +endmodule \ No newline at end of file diff --git a/vendor/lowrisc_ibex/dma-ip/DMA/dma-v4.sv b/vendor/lowrisc_ibex/dma-ip/DMA/dma-v4.sv new file mode 100644 index 000000000..bd5b6ea78 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/DMA/dma-v4.sv @@ -0,0 +1,789 @@ + +module dma import cheri_pkg::*; #( + parameter int unsigned SWRegisterCount = 11, + parameter int unsigned HWRegisterCount = 7, + // check these values from dvp_ibex_core_wrapper + parameter int unsigned HeapBase = 32'h2000_0000, + parameter int unsigned TSMapBase = 32'h200f_0000, // 4kB default + parameter int unsigned TSMapTop = 32'h200f_2000, + parameter int unsigned TSMapSize = 2048, // 32-bit words + parameter bit CHERIoTEn = 1'b1, + parameter bit CheriPPLBC = 1'b1 +) ( + input clk_i, + input rstn_i, + + // OBI interface for configurations + input reg dma_conf_en_i, + input reg [31:0] dma_conf_addr_i, + + input reg [32:0] dma_conf_wdata_i, + input reg dma_conf_we_i, + + // todo: we assume we do not use it yet + input reg [3:0] dma_conf_be_i, + + // todo: this interface is not tested yet + output [32:0] dma_conf_rdata_o, + + output dma_conf_ready_o, + // todo: we assume we do not use it yet + output dma_conf_error_o, + + // interrupt interface + output reg dma_completion_intc_o, + + // Deliver to target + output reg dma_controller_req_o, + input dma_controller_gnt_i, + + output reg [31:0] dma_controller_addr_o, + // todo: we assume we do not use it yet + output reg [3:0] dma_controller_be_o, + output reg [32:0] dma_controller_wdata_o, + output reg dma_controller_we_o, + + // Read from source + input [32:0] dma_controller_rdata_i, + input dma_controller_rvalid_i, + // todo: we assume we do not use it yet + input dma_controller_error_i, + + // this interface is remained to connect to the + // temporary safety shadow map + // todo: but how to differentiate between cpu's tsmap outputs? + output logic dma_tsmap_cs_o, + output logic [15:0] dma_tsmap_addr_o, + input logic [31:0] dma_tsmap_rdata_i, + input logic tsmap_is_occupied_i, + + input logic snooped_tsmap_cs_i, + input logic [15:0] snooped_tsmap_addr_i, + input logic [31:0] snooped_tsmap_rdata_i +); + +// MMAP-able configuration registers +logic [HWRegisterCount-1:0][31:0] conf_registers, conf_registers_n; +// Capabilities are 66 bits at the hw, with tag bits +// being replicated at the beginning of each word +logic [65:0] source_capability, source_capability_n; +logic [65:0] target_capability, target_capability_n; + +///////////////////////////////////////////////////////// +// Register roles: +// +// Source and target capabilities are +// in separate registers and indexed at addresses +// 0, 1 and 2, 3 +// +// For the rest of offset, we save the configurations +// in the array of registers +// +// conf_registers[0] for DMA transfer length in bytes +// conf_registers[1] for DMA source stride value +// conf_registers[2] for DMA target stride value +// conf_registers[3] for DMA byte swap value +// conf_registers[4] for DMA control register: +// - includes start('b0), endianness conversion('b1 and 2), reset ('b3) +// - start bit is meant to be set at the end while programming +// conf_registers[5] for DMA status register +// - first bit shows the halted status: 0 for idle, and 1 for running +// conf_registers[6] for free command from allocator() to DMA +// +///////////////////////////////////////////////////////// + +// states are similar to each other +typedef enum logic [2:0] { IDLE, REQUEST_DATA, WAIT_FOR_DATA, SEND_DATA, ADDRESS_GEN, + RESTART, DMA_HALT_FOR_CHECK } state_t; + +typedef enum logic [2:0] { CONF_IDLE, REQUEST_CONF, WAIT_FOR_CONF, + SEND_STATUS } conf_state_t; + +state_t state, state_n; +state_t previous_state, previous_state_n; +conf_state_t conf_state, conf_state_n; + +// differentiate between times when conf is arrived +// vs when it is written vs used +logic [1:0] new_descriptor_arrived, new_descriptor_arrived_n; +logic confs_written; +// should be reset only at the end of dma +logic confs_requested, confs_requested_n; + +// Backpressure registers in case target is not available +logic [31:0] read_data_register, read_data_register_n; +// logic [31:0] write_register, write_register_n; + +logic [31:0] read_data_ctr, read_data_ctr_n; +logic [31:0] conf_addr_ctr, conf_addr_ctr_n; + +// data is expected to be valid and delivered after single cycle +logic [31:0] source_offset, source_offset_n; +logic [31:0] target_offset, target_offset_n; + +// When allocator writes to this interface, +// we should halt the dma operation, to conduct checks +logic addresses_are_freed; + +// restarting dma if there is any request for it +logic restart_dma; + +logic [1:0] similar_descriptors, similar_descriptors_n; + +logic pause_for_reset_check; +assign pause_for_reset_check = confs_requested && (test_wire3); +logic reset_check_requested, reset_check_requested_n; + +// descriptor and output alternation logic +logic [65:0] descriptor_capability, descriptor_capability_n; +logic [31:0] descriptor_address_generic; + +assign descriptor_address_generic = descriptor_capability[31:0]; + +logic [31:0] descriptor_field_addr; +logic [32:0] descriptor_field_wdata; +logic descriptor_field_req_val; +logic descriptor_field_req_we; + +logic descriptor_address_valid; + +// todo: temporarily we put address_valid as high +// but eventually we have to do checks the values +// via the same procedure as capability registers earlier +assign descriptor_address_valid = 1'b1; + +// always ready to be written by allocator compartment only +// for the others we have separate checks +assign dma_conf_ready_o = 1'b1; +assign dma_conf_error_o = 0; + +// index of configuration registers decoded +logic [15:0] index, field_index; +assign index = dma_conf_addr_i[7:0] >> 2; +assign field_index = conf_addr_ctr[7:0] >> 2; + +assign dma_conf_rdata_o = 0; + +/////////////////////////////////////////// +// Alternative 1: Following is the logic +// to check the revocation map when free() +// happens at the allocator +/////////////////////////////////////////// + +// need to stop the dma when the freed() region +// turns out to be dma addresses +logic force_stop; +logic first_request_send, first_request_send_n; +logic second_request_send, second_request_send_n; +logic checks_finished, checks_finished_delayed; + +// these are interface between the revoker and the dma +// todo: assign these values! +logic [31:0] dma_cap_placeholder; +logic [31:0] tsmap_ptr; +assign tsmap_ptr = (dma_cap_placeholder - HeapBase) >> 3; +assign dma_tsmap_addr_o = tsmap_ptr[15:5]; + +logic [4:0] bitpos; +assign bitpos = tsmap_ptr[4:0]; + +// todo: fail if the range is wrong later! +logic correct_range; +assign correct_range = (dma_tsmap_addr_o <= TSMapSize); + +logic clear_tag; +assign clear_tag = dma_tsmap_rdata_i[bitpos]; + +/////////////////////////////////////////// +// Alternative 2: Following is the logic +// to check the snooped tsmap operations +// for the similarity with dma addresses +// and the revocation status. +// +// todo: There are probably some wires that can +// be joined between alternatives, but +// we want to keep things separate for the +// evaluation +/////////////////////////////////////////// +logic snooped_addr_similar, snooped_addr_revoked; + +logic [31:0] source_address_base, source_address_tsmap; +logic [31:0] target_address_base, target_address_tsmap; + +assign source_address_base = (source_capability[31:0] - HeapBase) >> 3; +assign source_address_tsmap = source_address_base[15:5]; + +assign target_address_base = (target_capability[31:0] - HeapBase) >> 3; +assign target_address_tsmap = target_address_base[15:5]; + +logic [4:0] source_bitpos, target_bitpos; +assign source_bitpos = source_address_base[4:0]; +assign target_bitpos = target_address_base[4:0]; + +assign snooped_addr_similar = snooped_tsmap_cs_i ? + (source_address_tsmap == snooped_tsmap_addr_i) || + (target_address_tsmap == snooped_tsmap_addr_i) + : 0; + +assign snooped_addr_revoked = snooped_addr_similar && + (snooped_tsmap_rdata_i[source_bitpos] || + snooped_tsmap_rdata_i[target_bitpos]); + +/////////////////////////////////////////// +// Alternative 3: Here, we conduct the +// checks for capabilities at the HW +/////////////////////////////////////////// + +// todo: put all these things into some kind of a module!! +// so that we can use it for capabilities or other stuff as well! +logic [PERMS_W-1:0] source_perms; +logic [PERMS_W-1:0] target_perms; + +assign source_perms = expand_perms(source_capability[63:58]); +assign target_perms = expand_perms(target_capability[63:58]); + +logic source_global, source_load; +logic target_global, target_store; + +assign source_global = source_perms[PERM_GL]; +assign source_load = source_perms[PERM_LD]; + +assign target_global = target_perms[PERM_GL]; +assign target_store = target_perms[PERM_SD]; + +logic source_unsealed, target_unsealed; + +assign source_unsealed = !(source_perms[PERM_US] & source_perms[PERM_SE]); +assign target_unsealed = !(target_perms[PERM_US] & target_perms[PERM_SE]); + +logic source_bounded, target_bounded; + +logic [TOP_W-1:0] source_top_addr, target_top_addr; +logic [BOT_W-1:0] source_base_addr, target_base_addr; +logic [EXP_W-1:0] source_exp_addr, target_exp_addr; +logic [31:0] source_address_generic, target_address_generic; + +assign source_top_addr = source_capability[41:33]; +assign source_base_addr = source_capability[50:42]; +assign source_exp_addr = source_capability[54:51]; +assign source_address_generic = source_capability[31:0]; + +assign target_top_addr = target_capability[41:33]; +assign target_base_addr = target_capability[50:42]; +assign target_exp_addr = target_capability[54:51]; +assign target_address_generic = target_capability[31:0]; + +logic [32:0] source_top_bound, target_top_bound; + +logic [3:0] source_cor, target_cor; +logic [1:0] source_top_cor, target_top_cor; +logic [8:0] source_mid_address, target_mid_address; + +assign source_mid_address = source_address_generic >> source_exp_addr; +assign target_mid_address = target_address_generic >> target_exp_addr; + +assign source_cor = update_temp_fields(source_top_addr, source_base_addr, + source_mid_address); +assign target_cor = update_temp_fields(target_top_addr, target_base_addr, + target_mid_address); + +assign source_top_cor = source_cor[3:2]; +assign target_top_cor = target_cor[3:2]; + +assign source_top_bound = get_bound33(source_top_addr, source_top_cor, + source_exp_addr, source_address_generic); + +assign target_top_bound = get_bound33(target_top_addr, target_top_cor, + target_exp_addr, target_address_generic); +logic [31:0] dma_length; +assign dma_length = conf_registers[0]; + +assign source_bounded = (source_top_bound >= (source_address_generic + dma_length)); +assign target_bounded = (target_top_bound >= (target_address_generic + dma_length)); + +logic source_address_valid, target_address_valid; + +// bit 65 and 32 of capability registers are for the valid tags +assign source_address_valid = source_capability[65] & source_global & + source_load & source_unsealed & source_bounded; + +assign target_address_valid = target_capability[65] & target_global & + target_store & target_unsealed & target_bounded; + +always_ff @( posedge clk_i ) begin : setReset + if (!rstn_i | restart_dma | force_stop | snooped_addr_revoked) begin + state <= IDLE; + previous_state <= IDLE; + conf_state <= CONF_IDLE; + new_descriptor_arrived <= 0; + confs_requested <= 0; + similar_descriptors <= 0; + reset_check_requested <= 0; + + conf_registers <= 0; + source_capability <= 0; + target_capability <= 0; + descriptor_capability <= 0; + + conf_addr_ctr <= 0; + read_data_register <= 0; + read_data_ctr <= 0; + source_offset <= 0; + target_offset <= 0; + + first_request_send <= 0; + second_request_send <= 0; + addresses_are_freed <= 0; + checks_finished_delayed <= 0; + end else if (!addresses_are_freed & conf_registers[6]) begin + // in order to avoid the repetitive check + // in the comb blocks assigning things here + previous_state <= state; + state <= DMA_HALT_FOR_CHECK; + conf_state <= conf_state_n; + addresses_are_freed <= conf_registers[6]; + checks_finished_delayed <= checks_finished; + end else if (pause_for_reset_check) begin + // here, we should just stay and pause where the state is + // until checks are finished + previous_state <= state; + state <= previous_state; + conf_state <= conf_state_n; + end else begin + state <= state_n; + previous_state <= previous_state_n; + conf_state <= conf_state_n; + new_descriptor_arrived <= new_descriptor_arrived_n; + confs_requested <= confs_requested_n; + similar_descriptors <= similar_descriptors_n; + reset_check_requested <= reset_check_requested_n; + + conf_registers <= conf_registers_n; + source_capability <= source_capability_n; + target_capability <= target_capability_n; + descriptor_capability <= descriptor_capability_n; + + conf_addr_ctr <= conf_addr_ctr_n; + read_data_register <= read_data_register_n; + read_data_ctr <= read_data_ctr_n; + source_offset <= source_offset_n; + target_offset <= target_offset_n; + + first_request_send <= first_request_send_n; + second_request_send <= second_request_send_n; + addresses_are_freed <= conf_registers[6]; + checks_finished_delayed <= checks_finished; + end +end + +////////////////////////////////////// +// Step 0: Requesting Configurations +// using the descriptor +////////////////////////////////////// + +always_comb begin : assignCapabilities + source_capability_n = source_capability; + target_capability_n = target_capability; + descriptor_capability_n = descriptor_capability; + + new_descriptor_arrived_n = new_descriptor_arrived; + + if (state == IDLE) begin + // setting a descriptor capability here + // receive the descriptor from the MMIO directly + // while the separate configurations are written after + // we request them + + // we can receive new descriptor only before + // we have not requested the actual configurations yet + if (!confs_requested && dma_conf_en_i && dma_conf_we_i) begin + if (index == 0) begin + descriptor_capability_n[32:0] = dma_conf_wdata_i; + new_descriptor_arrived_n[0] = !confs_requested; + end else if (index == 1) begin + descriptor_capability_n[65:33] = dma_conf_wdata_i; + new_descriptor_arrived_n[1] = !confs_requested; + end + end + + // now setup for the source + // and target capabilities + if (dma_controller_rvalid_i) begin + if (field_index == 0) begin + source_capability_n[32:0] = dma_controller_rdata_i; + end else if (field_index == 1) begin + source_capability_n[65:33] = dma_controller_rdata_i; + end + + // setting a target capability here + if (field_index == 2) begin + target_capability_n[32:0] = dma_controller_rdata_i; + end else if (field_index == 3) begin + target_capability_n[65:33] = dma_controller_rdata_i; + end + end + end + +end + +logic descriptor_equal1, descriptor_equal2; +assign descriptor_equal1 = (descriptor_capability[32:0] == dma_conf_wdata_i); +assign descriptor_equal2 = (descriptor_capability[65:33] == dma_conf_wdata_i); + +logic test_wire1, test_wire2, test_wire3; + +always_comb begin : conf_fetch_FSM + conf_state_n = conf_state; + + conf_addr_ctr_n = conf_addr_ctr; + + descriptor_field_req_val = 0; + descriptor_field_req_we = 0; + + descriptor_field_wdata = 0; + + descriptor_field_addr = descriptor_address_generic + conf_addr_ctr; + + confs_requested_n = confs_requested; + + restart_dma = 0; + confs_written = 0; + + similar_descriptors_n <= similar_descriptors; + + reset_check_requested_n = reset_check_requested; + + test_wire1 = 0; + test_wire2 = 0; + test_wire3 = 0; + + // this is where we set similar_descriptors field + // to initate the next conf request + if (confs_requested) begin + test_wire1 = 1; + // here, we never write a data to the new descriptor + // but just check whether descriptors are similar + if (dma_conf_en_i && dma_conf_we_i) begin + test_wire2 = 1; + if ((index == 0) && (descriptor_capability[32:0] == dma_conf_wdata_i)) begin + similar_descriptors_n = 1; + test_wire3 = 1; + end else if ((index == 1) && (descriptor_capability[65:33] == dma_conf_wdata_i)) begin + similar_descriptors_n = 1; + end + end + end + + case (conf_state) + CONF_IDLE: begin + if ((new_descriptor_arrived == 'd3) & descriptor_address_valid & !confs_requested) begin + conf_state_n = REQUEST_CONF; + confs_requested_n = 1'b1; + end else if (pause_for_reset_check) begin + conf_state_n = REQUEST_CONF; + descriptor_field_addr = descriptor_address_generic + ('d32); + reset_check_requested_n = 1'b1; + end + end + REQUEST_CONF: begin + // check whether we already received the expected amount of data + // unless otherwise, keep receiving a data + + // gnt result should be available in the same cycle + descriptor_field_req_val = 1'b1; + + // for conf FSM we need to go back to the IDLE state to + // request the new conf, however when we are at the dma transfer FSM, + // we do not have to to anything so we can just wait over there + if (!pause_for_reset_check && (conf_addr_ctr == ('d36))) begin + conf_addr_ctr_n = 0; + conf_state_n = SEND_STATUS; + descriptor_field_req_val = 1'b0; + end else if (pause_for_reset_check & !reset_check_requested) begin + conf_state_n = CONF_IDLE; + end else if (dma_controller_gnt_i) begin + conf_state_n = WAIT_FOR_CONF; + end + + end + WAIT_FOR_CONF: begin + // we will accept data, once it is valid irrespective + // of its ready status. + // this addtional cycle is to save the data to a register + // for avoiding back pressure + if (dma_controller_rvalid_i) begin + // no matter what is the restart value + // we clean up the descriptor comparison here as well + if (pause_for_reset_check & reset_check_requested) begin + conf_state_n = CONF_IDLE; + restart_dma = dma_controller_rdata_i[3]; + similar_descriptors_n = 'd0; + reset_check_requested_n = 0; + end else if (pause_for_reset_check & !reset_check_requested) begin + // thus if we are receiving one existing one conf, + // we can also unroll our current request and + // to re-request the same conf if addr is not incremented + conf_state_n = CONF_IDLE; + end else begin + conf_state_n = REQUEST_CONF; + conf_addr_ctr_n = conf_addr_ctr_n + 'd4; + end + + end + end + SEND_STATUS: begin + descriptor_field_req_val = 1'b1; + descriptor_field_req_we = 1'b1; + descriptor_field_wdata = 1'b1; + // this is to access the 9th field of the descriptor - status + // we let the write happen even we received a potential reset conf, + // as we already got all the confs in our registers + descriptor_field_addr = descriptor_address_generic + ('d36); + + if (dma_controller_gnt_i) begin + conf_state_n = CONF_IDLE; + confs_written = 1'b1; + end + end + endcase +end + +/////////////////////////////////////////// +// Step 0: Filling Configuration Registers +/////////////////////////////////////////// + +// we assume that software can always see the status via reading the registers, +// hence leave the responsibility to overwrite the dma configurations to the programmer. +// offset is 4, because the first two are for the capabilities +generate + for (genvar i=0; i < HWRegisterCount-1; i++) begin + assign conf_registers_n[i] = ((state == IDLE) && descriptor_address_valid && dma_controller_rvalid_i && ((i+4) == field_index)) + ? dma_controller_rdata_i + : conf_registers[i]; + end +endgenerate + +// this is for the notification write from the free() +assign conf_registers_n[6] = (dma_conf_en_i && dma_conf_we_i && (index == 4)) + ? dma_conf_wdata_i + : (checks_finished) + ? 0 + : conf_registers[6]; + +/////////////////////////////////////////// +// Step 0: Instantiating the dma transfer +// wires so that we can later manipulate +// between the data and conf requests +/////////////////////////////////////////// + +logic [31:0] dma_transfer_addr; +logic [32:0] dma_transfer_wdata; + +logic dma_transfer_req; +logic dma_transfer_we; + +// todo: we assume we do not use it yet +assign dma_controller_be_o = 'hf; +assign dma_controller_req_o = descriptor_field_req_val | dma_transfer_req; +assign dma_controller_we_o = descriptor_field_req_we | dma_transfer_we; + +assign dma_controller_addr_o = descriptor_field_req_val ? descriptor_field_addr : dma_transfer_addr; +assign dma_controller_wdata_o = descriptor_field_req_val ? descriptor_field_wdata : dma_transfer_wdata; + +/////////////////////////////////////////////////////// +// Step 1: Requesting and receiving a data from the source +/////////////////////////////////////////////////////// + +// increment in terms of 4's +// choose between the source and target addresses to +// read the data from vs to write the data to +assign dma_transfer_addr = dma_transfer_req + ? dma_transfer_we + ? (target_capability[31:0] + target_offset) + : (source_capability[31:0] + source_offset) + : 0; + +assign read_data_register_n = (state == WAIT_FOR_DATA) & dma_controller_rvalid_i + ? dma_controller_rdata_i + : read_data_register; + +/////////////////////////////////////////////////////// +// Step 2: Sending a data to the target +/////////////////////////////////////////////////////// +logic target_data_valid; + +assign target_data_valid = dma_transfer_req & dma_transfer_we; + +logic two_byte_swap, four_byte_swap; + +assign two_byte_swap = conf_registers[3][1]; +assign four_byte_swap = conf_registers[3][2]; + +always_comb begin : assignTargetData + dma_transfer_wdata = 0; + + if (target_data_valid) begin + if (two_byte_swap) begin + dma_transfer_wdata = {16'b0, read_data_register[7:0], read_data_register[15:8]}; + end else if (four_byte_swap) begin + dma_transfer_wdata = {read_data_register[7:0], read_data_register[15:8], + read_data_register[23:16], read_data_register[31:24]}; + end else begin + dma_transfer_wdata = read_data_register; + end + end +end + +logic start_dma; +assign start_dma = conf_registers[4][0] & confs_written; + +// for the start, we implement a simple DMA +// with single copy operation with one channel +always_comb begin : single_copy_FSM + state_n = state; + previous_state_n = previous_state; + + read_data_ctr_n = read_data_ctr; + + source_offset_n = read_data_ctr * (conf_registers[1] + 'b1); + target_offset_n = read_data_ctr * (conf_registers[2] + 'b1); + + dma_transfer_req = 0; + dma_transfer_we = 0; + + dma_completion_intc_o = 0; + + force_stop = 1'b0; + first_request_send_n = first_request_send; + second_request_send_n = second_request_send; + + dma_tsmap_cs_o = 0; + dma_cap_placeholder = 0; + + checks_finished = 0; + + case (state) + IDLE: begin + if (start_dma & source_address_valid & target_address_valid) begin + state_n = REQUEST_DATA; + end + end + REQUEST_DATA: begin + // check whether we already received the expected amount of data + // unless otherwise, keep receiving a data + + // gnt result should be available in the same cycle + dma_transfer_req = 1'b1; + + if (read_data_ctr == dma_length) begin + read_data_ctr_n = 0; + state_n = RESTART; + dma_transfer_req = 1'b0; + + // interrupt is high only single cycle + dma_completion_intc_o = 1'b1; + end else if (pause_for_reset_check) begin + // we pause here temporarily + dma_transfer_req = 0; + end else if (checks_finished_delayed) begin + // we hold this checks_finished signal high, until we receive gnt request + // in order to not fall into the deep pause in the condition below + if (!dma_controller_gnt_i) begin + checks_finished = 1'b1; + end else begin + state_n = WAIT_FOR_DATA; + end + // end else if (read_data_ctr == (dma_length/2)) begin + // // todo: ideally need to remove this condition later + // // for free() to happen naturally + // // just wait here, until addresses are freed happens + // dma_transfer_req = 1'b0; + end else if (dma_controller_gnt_i) begin + state_n = WAIT_FOR_DATA; + end + + end + WAIT_FOR_DATA: begin + // we will accept data, once it is valid irrespective + // of its ready status. + // this addtional cycle is to save the data to a register + // for avoiding back pressure + if (pause_for_reset_check) begin + // unroll our dma data requests, + // if might receive reset signal and checking for it + // but if there are malicious attacks, it might + // result in DoS at the HW? + state_n = REQUEST_DATA; + end else if (dma_controller_rvalid_i) begin + state_n = SEND_DATA; + end + end + SEND_DATA: begin + dma_transfer_req = 1'b1; + dma_transfer_we = 1'b1; + + if (pause_for_reset_check) begin + // unroll our dma data requests, + // if might receive reset signal and checking for it + // but if there are malicious attacks, it might + // result in DoS at the HW? + dma_transfer_req = 0; + dma_transfer_we = 0; + state_n = REQUEST_DATA; + end else if (dma_controller_gnt_i) begin + state_n = ADDRESS_GEN; + read_data_ctr_n = read_data_ctr_n + 'd4; + end + end + ADDRESS_GEN: begin + // this additional cycle is for address generation + // and to remove multiplication from the critical path + state_n = REQUEST_DATA; + end + RESTART: begin + if (restart_dma) begin + // the next dma can only launch + // when the previous one was resetted + state_n = IDLE; + end + end + DMA_HALT_FOR_CHECK: begin + if (clear_tag) begin + force_stop = 1'b1; + // technically this should be cleared on its own + // at the first reset/force_stop block above + state_n = IDLE; + first_request_send_n = 1'b0; + second_request_send_n = 1'b0; + end else if (first_request_send & second_request_send & !clear_tag) begin + // if both requests were sent and acknowledged + // and no clear tag request still + // we can switch back to the previous state + state_n = previous_state; + previous_state_n = IDLE; + first_request_send_n = 0; + second_request_send_n = 0; + checks_finished = 1'b1; + end else if (first_request_send & !clear_tag) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = target_capability[31:0]; + + if (!tsmap_is_occupied_i) begin + second_request_send_n = 1'b1; + end + + end else if(!first_request_send) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = source_capability[31:0]; + + if (!tsmap_is_occupied_i) begin + first_request_send_n = 1'b1; + end + + end + end + endcase +end + + +endmodule \ No newline at end of file diff --git a/vendor/lowrisc_ibex/dma-ip/DMA/dma.sv b/vendor/lowrisc_ibex/dma-ip/DMA/dma.sv new file mode 100644 index 000000000..3709e7970 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/DMA/dma.sv @@ -0,0 +1,443 @@ + +module dma import cheri_pkg::*; #( + parameter int unsigned RegisterCount = 10, + // check these values from dvp_ibex_core_wrapper + parameter int unsigned HeapBase = 32'h2000_0000, + parameter int unsigned TSMapBase = 32'h200f_0000, // 4kB default + parameter int unsigned TSMapTop = 32'h200f_2000, + parameter int unsigned TSMapSize = 2048, // 32-bit words + parameter bit CHERIoTEn = 1'b1, + parameter bit CheriPPLBC = 1'b1 +) ( + input clk_i, + input rstn_i, + + // OBI interface for configurations + input reg dma_conf_en_i, + input reg [31:0] dma_conf_addr_i, + + input reg [32:0] dma_conf_wdata_i, + input reg dma_conf_we_i, + + // todo: we assume we do not use it yet + input reg [3:0] dma_conf_be_i, + + // todo: this interface is not tested yet + output [32:0] dma_conf_rdata_o, + + output dma_conf_ready_o, + // todo: we assume we do not use it yet + output dma_conf_error_o, + + // interrupt interface + output reg dma_completion_intc_o, + + // Deliver to target + output reg dma_controller_req_o, + input dma_controller_gnt_i, + + output reg [31:0] dma_controller_addr_o, + // todo: we assume we do not use it yet + output reg [3:0] dma_controller_be_o, + output reg [32:0] dma_controller_wdata_o, + output reg dma_controller_we_o, + + // Read from source + input [32:0] dma_controller_rdata_i, + input dma_controller_rvalid_i, + // todo: we assume we do not use it yet + input dma_controller_error_i, + + // this interface is remained to connect to the + // temporary safety shadow map + // todo: but how to differentiate between cpu's tsmap outputs? + output logic dma_tsmap_cs_o, + output logic [15:0] dma_tsmap_addr_o, + input logic [31:0] dma_tsmap_rdata_i, + input logic tsmap_is_occupied_i, + + input logic snooped_tsmap_cs_i, + input logic [15:0] snooped_tsmap_addr_i, + input logic [31:0] snooped_tsmap_rdata_i +); + +// MMAP-able configuration registers +logic [RegisterCount-1:0][31:0] conf_registers, conf_registers_n; + +///////////////////////////////////////////////////////// +// Register roles: +// +// conf_registers[0] for DMA control register: +// - includes start('b0), endianness conversion('b1 and 2), reset ('b3) +// - start bit is meant to be set at the end while programming +// conf_registers[1] for DMA status register +// - first bit shows the halted status: 0 for idle, and 1 for running +// conf_registers[2] for DMA source address +// conf_registers[3] for DMA target address +// conf_registers[4] for DMA transfer length in bytes +// conf_registers[5] for DMA source stride value +// conf_registers[6] for DMA target stride value +// conf_registers[7] for DMA source capability +// conf_registers[8] for DMA target capability +// conf_registers[9] for free command from allocator() to DMA +// +///////////////////////////////////////////////////////// + +// Backpressure registers in case target is not available +logic [31:0] read_data_register, read_data_register_n; +// logic [31:0] write_register, write_register_n; + +// states are similar to each other +typedef enum logic [2:0] { IDLE, REQUEST_DATA, WAIT_FOR_DATA, SEND_DATA, ADDRESS_GEN, + RESTART, DMA_HALT_FOR_CHECK } state_t; + +state_t state, state_n; +state_t previous_state, previous_state_n; + +logic [31:0] read_data_ctr, read_data_ctr_n; + +// data is expected to be valid and delivered after single cycle +logic [31:0] read_status_reg, read_status_reg_n; +logic [31:0] source_offset, source_offset_n; +logic [31:0] target_offset, target_offset_n; + +// When allocator writes to this interface, +// we should halt the dma operation, to conduct checks +logic addresses_are_freed; + +// restarting dma if there is any request for it +logic restart_dma; +assign restart_dma = conf_registers[0][3]; + +/////////////////////////////////////////// +// Alternative 1: Following is the logic +// to check the revocation map when free() +// happens at the allocator +/////////////////////////////////////////// + +// need to stop the dma when the freed() region +// turns out to be dma addresses +logic force_stop; +logic first_request_send, first_request_send_n; +logic second_request_send, second_request_send_n; +logic checks_finished, checks_finished_delayed; + +// these are interface between the revoker and the dma +// todo: assign these values! +logic [31:0] dma_cap_placeholder; +logic [31:0] tsmap_ptr; +assign tsmap_ptr = (dma_cap_placeholder - HeapBase) >> 3; +assign dma_tsmap_addr_o = tsmap_ptr[15:5]; + +logic [4:0] bitpos; +assign bitpos = tsmap_ptr[4:0]; + +// todo: fail if the range is wrong later! +logic correct_range; +assign correct_range = (dma_tsmap_addr_o <= TSMapSize); + +logic clear_tag; +assign clear_tag = dma_tsmap_rdata_i[bitpos]; + +/////////////////////////////////////////// +// Alternative 2: Following is the logic +// to check the snooped tsmap operations +// for the similarity with dma addresses +// and the revocation status. +// +// todo: There are probably some wires that can +// be joined between alternatives, but +// we want to keep things separate for the +// evaluatiosn +/////////////////////////////////////////// +logic snooped_addr_similar, snooped_addr_revoked; + +logic [31:0] source_address_base, source_address_tsmap; +logic [31:0] target_address_base, target_address_tsmap; + +assign source_address_base = (conf_registers[2] - HeapBase) >> 3; +assign source_address_tsmap = source_address_base[15:5]; + +assign target_address_base = (conf_registers[3] - HeapBase) >> 3; +assign target_address_tsmap = target_address_base[15:5]; + +logic [4:0] source_bitpos, target_bitpos; +assign source_bitpos = source_address_base[4:0]; +assign target_bitpos = target_address_base[4:0]; + +assign snooped_addr_similar = snooped_tsmap_cs_i ? + (source_address_tsmap == snooped_tsmap_addr_i) || + (target_address_tsmap == snooped_tsmap_addr_i) + : 0; + +assign snooped_addr_revoked = snooped_addr_similar && + (snooped_tsmap_rdata_i[source_bitpos] || + snooped_tsmap_rdata_i[target_bitpos]); + +always_ff @( posedge clk_i ) begin : setReset + if (!rstn_i | restart_dma | force_stop | snooped_addr_revoked) begin + state <= IDLE; + previous_state <= IDLE; + read_data_register <= 0; + conf_registers <= 0; + read_data_ctr <= 0; + read_status_reg <= 0; + source_offset <= 0; + target_offset <= 0; + first_request_send <= 0; + second_request_send <= 0; + addresses_are_freed <= 0; + checks_finished_delayed <= 0; + end else if (!addresses_are_freed & conf_registers[9]) begin + // in order to avoid the repetitive check + // in the comb blocks assigning things here + previous_state <= state; + state <= DMA_HALT_FOR_CHECK; + addresses_are_freed <= conf_registers[9]; + checks_finished_delayed <= checks_finished; + end else begin + state <= state_n; + previous_state <= previous_state_n; + read_data_register <= read_data_register_n; + conf_registers <= conf_registers_n; + read_data_ctr <= read_data_ctr_n; + read_status_reg <= read_status_reg_n; + source_offset <= source_offset_n; + target_offset <= target_offset_n; + first_request_send <= first_request_send_n; + second_request_send <= second_request_send_n; + addresses_are_freed <= conf_registers[9]; + checks_finished_delayed <= checks_finished; + end +end + +////////////////////////////////////// +// Step 0: Configurations +////////////////////////////////////// + +// always ready to be written and read in IDLE +// assign dma_conf_ready_o = (state == IDLE) || (state == RESTART); +assign dma_conf_ready_o = 1'b1; +assign dma_conf_error_o = 0; + +// index of configuration registers decoded +logic [15:0] index; +assign index = dma_conf_addr_i[7:0] >> 2; + +assign read_status_reg_n = (dma_conf_en_i & !dma_conf_we_i) + ? conf_registers[index] + : read_status_reg; + +assign dma_conf_rdata_o = read_status_reg; + +logic [31:0] dma_length; +assign dma_length = conf_registers[4]; + +// we assume that software can always see the status via reading the registers, +// hence leave the responsibility to overwrite the dma configurations to the programmer +generate + for (genvar i=1; i < RegisterCount-1; i++) begin + assign conf_registers_n[i] = ((state == IDLE)) + ? (dma_conf_en_i && dma_conf_we_i && (i == index)) + ? dma_conf_wdata_i + : conf_registers[i] + : conf_registers[i]; + end +endgenerate + +// todo: we should be able to write to the control register any time +// to stop the process? +// todo: then we have to also decouple the byte swap bits +// to the second register to avoid the problem with control vs conf sync +assign conf_registers_n[0] = (dma_conf_en_i && dma_conf_we_i && (index == 0)) + ? dma_conf_wdata_i + : conf_registers[0]; + +assign conf_registers_n[9] = (dma_conf_en_i && dma_conf_we_i && (index == 9)) + ? dma_conf_wdata_i + : (checks_finished) + ? 0 + : conf_registers[9]; + +/////////////////////////////////////////////////////// +// Step 1: Requesting and receiving a data from the source +/////////////////////////////////////////////////////// + +// todo: we assume we do not use it yet +assign dma_controller_be_o = 'hf; + +// increment in terms of 4's +// choose between the source and target addresses to +// read the data from vs to write the data to +assign dma_controller_addr_o = dma_controller_req_o + ? dma_controller_we_o + ? (conf_registers[3] + target_offset) + : (conf_registers[2] + source_offset) + : 0; + +assign read_data_register_n = (state == WAIT_FOR_DATA) & dma_controller_rvalid_i + ? dma_controller_rdata_i + : read_data_register; + +/////////////////////////////////////////////////////// +// Step 2: Sending a data to the target +/////////////////////////////////////////////////////// +logic target_data_valid; + +assign target_data_valid = dma_controller_req_o & dma_controller_we_o; + +logic two_byte_swap, four_byte_swap; + +assign two_byte_swap = conf_registers[0][1]; +assign four_byte_swap = conf_registers[0][2]; + +always_comb begin : assignTargetData + dma_controller_wdata_o = 0; + + if (target_data_valid) begin + if (two_byte_swap) begin + dma_controller_wdata_o = {16'b0, read_data_register[7:0], read_data_register[15:8]}; + end else if (four_byte_swap) begin + dma_controller_wdata_o = {read_data_register[7:0], read_data_register[15:8], + read_data_register[23:16], read_data_register[31:24]}; + end else begin + dma_controller_wdata_o = read_data_register; + end + end +end + +// for the start, we implement a simple DMA +// with single copy operation with one channel +always_comb begin : single_copy_FSM + state_n = state; + previous_state_n = previous_state; + + read_data_ctr_n = read_data_ctr; + + source_offset_n = read_data_ctr * (conf_registers[5] + 'b1); + target_offset_n = read_data_ctr * (conf_registers[6] + 'b1); + + dma_controller_req_o = 0; + dma_controller_we_o = 0; + + dma_completion_intc_o = 0; + + force_stop = 1'b0; + first_request_send_n = first_request_send; + second_request_send_n = second_request_send; + + dma_tsmap_cs_o = 0; + dma_cap_placeholder = 0; + + checks_finished = 0; + + case (state) + IDLE: begin + if (conf_registers[0][0]) begin + state_n = REQUEST_DATA; + end + end + REQUEST_DATA: begin + // check whether we already received the expected amount of data + // unless otherwise, keep receiving a data + + // gnt result should be available in the same cycle + dma_controller_req_o = 1'b1; + + if (read_data_ctr == dma_length) begin + read_data_ctr_n = 0; + state_n = RESTART; + dma_controller_req_o = 1'b0; + + // interrupt is high only single cycle + dma_completion_intc_o = 1'b1; + end else if (checks_finished_delayed) begin + if (!dma_controller_gnt_i) begin + checks_finished = 1'b1; + end else begin + state_n = WAIT_FOR_DATA; + end + end else if (read_data_ctr == (dma_length/2)) begin + // todo: ideally need to remove this condition later + // for free() to happen naturally + // just wait here, until addresses are freed happens + dma_controller_req_o = 1'b0; + end else if (dma_controller_gnt_i) begin + state_n = WAIT_FOR_DATA; + end + + end + WAIT_FOR_DATA: begin + // we will accept data, once it is valid irrespective + // of its ready status. + // this addtional cycle is to save the data to a register + // for avoiding back pressure + if (dma_controller_rvalid_i) begin + state_n = SEND_DATA; + end + end + SEND_DATA: begin + dma_controller_req_o = 1'b1; + dma_controller_we_o = 1'b1; + + if (dma_controller_gnt_i) begin + state_n = ADDRESS_GEN; + read_data_ctr_n = read_data_ctr_n + 'd4; + end + end + ADDRESS_GEN: begin + // this additional cycle is for address generation + // and to remove multiplication from the critical path + state_n = REQUEST_DATA; + end + RESTART: begin + if (restart_dma) begin + // the next dma can only launch + // when the previous one was resetted + state_n = IDLE; + end + end + DMA_HALT_FOR_CHECK: begin + if (clear_tag) begin + force_stop = 1'b1; + // technically this should be cleared on its own + // at the first reset/force_stop block above + state_n = IDLE; + first_request_send_n = 1'b0; + second_request_send_n = 1'b0; + end else if (first_request_send & second_request_send & !clear_tag) begin + // if both requests were sent and acknowledged + // and no clear tag request still + // we can switch back to the previous state + state_n = previous_state; + previous_state_n = IDLE; + first_request_send_n = 0; + second_request_send_n = 0; + checks_finished = 1'b1; + end else if (first_request_send & !clear_tag) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = conf_registers[3]; + + if (!tsmap_is_occupied_i) begin + second_request_send_n = 1'b1; + end + + end else if(!first_request_send) begin + dma_tsmap_cs_o = 1'b1; + dma_cap_placeholder = conf_registers[2]; + + if (!tsmap_is_occupied_i) begin + first_request_send_n = 1'b1; + end + + end + // todo: here make sure to alternate between + // the tests for the source and target addr + // todo: also we do not have any info about the + // actual capabilities, need to transfer them as well at the very beginning? + end + endcase +end + + +endmodule \ No newline at end of file diff --git a/vendor/lowrisc_ibex/dma-ip/dvp_ibex_wrapper.yml b/vendor/lowrisc_ibex/dma-ip/dvp_ibex_wrapper.yml new file mode 100644 index 000000000..70be1c1b5 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/dvp_ibex_wrapper.yml @@ -0,0 +1,175 @@ + +dvp_ibex_wrapper: + pinlist: + - input clk_i + - input rstn_i + - input [3:0] fetch_enable_i + - input test_en_i + - input cheri_pmode_i + - input cheri_tsafe_en_i + + - input TCK_i + - input TMS_i + - input TDI_i + - input TRSTn_i + - output TDO_o + - output TDOoen_o + + - output IROM_EN_o + - output [31:0] IROM_ADDR_o + - output [32:0] IROM_WDATA_o + - output IROM_WE_o + - output [3:0] IROM_BE_o + - input [32:0] IROM_RDATA_i + - input IROM_READY_i + - input IROM_ERROR_i + + - output IRAM_EN_o + - output [31:0] IRAM_ADDR_o + - output [32:0] IRAM_WDATA_o + - output IRAM_WE_o + - output [3:0] IRAM_BE_o + - input [32:0] IRAM_RDATA_i + - input IRAM_READY_i + - input IRAM_ERROR_i + + - output DRAM_EN_o + - output [31:0] DRAM_ADDR_o + - output [32:0] DRAM_WDATA_o + - output DRAM_WE_o + - output [3:0] DRAM_BE_o + - input [32:0] DRAM_RDATA_i + - input DRAM_READY_i + - input DRAM_ERROR_i + + - output [3:0] AWID_o + - output [31:0] AWADDR_o + - output [7:0] AWLEN_o + - output [2:0] AWSIZE_o + - output [1:0] AWBURST_o + - output [1:0] AWLOCK_o + - output [2:0] AWPROT_o + - output AWVALID_o + - output [3:0] AWCACHE_o + - output [11:0] AWUSER_o + - input AWREADY_i + + - output [31:0] WDATA_o + - output [3:0] WSTRB_o + - output WLAST_o + - output WVALID_o + - input WREADY_i + + - input [3:0] BID_i + - input [1:0] BRESP_i + - input BVALID_i + - output BREADY_o + + - output [3:0] ARID_o + - output [31:0] ARADDR_o + - output [7:0] ARLEN_o + - output [2:0] ARSIZE_o + - output [1:0] ARBURST_o + - output [1:0] ARLOCK_o + - output [2:0] ARPROT_o + - output [3:0] ARCACHE_o + - output [11:0] ARUSER_o + - output ARVALID_o + - input ARREADY_i + + - input [3:0] RID_i + - input [31:0] RDATA_i + - input RLAST_i + - input [1:0] RRESP_i + - input RVALID_i + - output RREADY_o + + - output dvp_pclk_o + - output dvp_presetn_o + - output dvp_psel_o + - output dvp_penable_o + - output [31:0] dvp_paddr_o + - input [31:0] dvp_prdata_i + - output [31:0] dvp_pwdata_o + - output dvp_pwrite_o + - output [3:0] dvp_pstrb_o + - input dvp_pready_i + - input dvp_pslverr_i + + - input intctrl_irq_i + - input irq_external_i + - input irq_timer_i + - input [14:0] irq_fast_i + - input irq_nm_i + + - output tsmap_cs_o + - output [15:0] tsmap_addr_o + - input [31:0] tsmap_rdata_i + - output dma_tsmap_cs_o + - output [15:0] dma_tsmap_addr_o + - input [31:0] dma_tsmap_rdata_i + - input tsmap_is_occupied_i + - output tbre_done_o + - input [64:0] tbre_ctrl_vec_i + + - input snooped_tsmap_cs_i + - input [15:0] snooped_tsmap_addr_i + - input [31:0] snooped_tsmap_rdata_i + + - output dma_completion_intc_o + + include_list: + + file_list: + - "-f $PROJECT_PATH/$PROJECT_NAME/ip/dvp/ibexc/verilog/ibexc.f" + - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/memory/fpga_block_ram_byte_wr_model_dvp.sv" + - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/memory/fpga_block_ram_model_dvp.sv" + - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/memory/fpga_block_ram_2port_model_dvp.sv" + +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv_msftdbg/rom/msftDv_debug_rom.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv_msftdbg/verilog/msftDvIp_riscv_dmibus.sv" + + +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dm_pkg.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dm_csrs.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dmi_cdc.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dmi_intf.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dmi_jtag_tap.sv" +# - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/riscv-dbg/src/dmi_test.sv" + + instances: + dvp_ibex_core_wrapper: + inst_pre_code: + - "assign rstn_ibex = rstn & ~hartrst;" + inst_parameters: + - "DmHaltAddr 32'h0000_0800" + - "DmExceptionAddr 32'h0000_0808" + rtl: ip/dvp/ibexc/wrapper/dvp_ibex_core_wrapper.sv + pin_sub: + - "rstn rstn_ibex" + - "hart_id 32'h0000_0000" + - "boot_addr 32'h2000_0000" + + - "irq_software 1'b0" +# - "irq_external 1'b0" +# - "irq_fast 15'h0000" +# - "irq_nm 1'b0" + + - "scramble_key_valid 1'b0" + - "scramble_key 128'h0" + - "scramble_nonce 64'h0" + - "scan_rst 1'b0" + + - "instr_err 1'b0" + - "data_err 1'b0" + - "instr_rdata_intg 7'h0" + - "data_rdata_intg 7'h0" + + ibexc_obimux3w0: + rtl: ip/dvp/ibexc/ss_verilog/ibexc_obimux3w0.sv + + msftDvIp_riscv_debug: + yml: ip/dvp/riscv_msftdbg/yml/msftDvIp_riscv_debug.yml + + dma: + rtl: ip/dvip/rtl/DMA/dma-v4.sv \ No newline at end of file diff --git a/vendor/lowrisc_ibex/dma-ip/hsp_encr_level.yml b/vendor/lowrisc_ibex/dma-ip/hsp_encr_level.yml new file mode 100644 index 000000000..170ff82fb --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/hsp_encr_level.yml @@ -0,0 +1,320 @@ + + +hsp_encr_level: + pinlist: + - input hspclk_i + - input hsp_reset_nai + - input por_reset_nai + + - input gpio_hsp_uart_sin_i + - output hsp_gpio_uart_sout_o + + - output hsp_gpio_i2c_scl_oe_o + - output hsp_gpio_i2c_sda_oe_o + - input gpio_hsp_i2c_scl_i + - input gpio_hsp_i2c_sda_i + + - output irq_o + - output fiq_o + - output irqx0_o + - output irqx1_o + + - input sys_eth_irq_i + + - input [31:0] gpio_in + - output [31:0] gpio_out + - output [31:0] gpio_oen + + - input tbre_done_i + - output [64:0] tbre_ctrl_vec_o + + - input dma_completion_intc_i + +# - output cheri_pmode_o +# - output cheri_tsafe_en_o + + - axibus: + prefix: hsp_axi_mst_ + dir: output + idwidth: 4 + awidth: 64 + dwidth: 64 + len: 8 + swidth: 8 + uwidth: 12 + case: lower + + - axibus: + name: _m_ibex + dir: input + idwidth: 4 + awidth: 32 + dwidth: 32 + len: 8 + swidth: 4 + uwidth: 12 + case: lower + + file_list: + - "-f $PROJECT_PATH/$PROJECT_NAME/ip/vendor/uart/DW_apb_uart.lst" + - "-f $PROJECT_PATH/$PROJECT_NAME/ip/vendor/i2c/DW_apb_i2c.lst" +# - "-f $PROJECT_PATH/$PROJECT_NAME/ip/vendor/spi/DWC_ssi.lst" + + defines: + - AXI_MST_ID_SP 0 + - AXI_MST_ID_RP 1 + - AXI_MST_ID_CCS 2 + - AXI_MST_ID_SHA 3 + - AXI_MST_ID_PKA 4 + - AXI_MST_ID_AES 5 + - AXI_MST_ID_MSB 6 + + - HSP_GFC_APB_ADDR_WIDTH 15 + + - DMB_EXT_AWIDTH 64 + - DMB_EXT_AWIDTH 64 + - HSP_DMB_CFG_BEGIN 32'h8F0F0000 + - HSP_DMB_CFG_SIZE 4096 + - HSP_DMB_CFG_END 32'h8F0F1000 + - HSP_DMB_CFG_AWIDTH 12 + - HSP_DMB_CFG_DWIDTH 32 + - HSP_DMB_CFG_VALID_SEGMENTS 32'hfffc0000 + - HSP_DMB_BEGIN 32'h90000000 + - HSP_DMB_SIZE 32'h70000000 + - HSP_DMB_END 33'h100000000 + - HSP_DMB_AWIDTH 32 + - HSP_DMB_DWIDTH 32 + + - SERIOW 4 + - DFS_W 5 + - SSIC_MAX_XFER_SIZE 32 + - SSIC_ADDR_SLICE_LHS 7 + - SSIC_REG_DATA_WIDTH 32 + - CTRLR0_RS 20 + - SPI_CTRLR0_RS 17 + - SSIC_NUM_SLAVES 1 + + instances: + + hsp_encr_axi_fabric: + bus: + id_width: 4 + addr_width: 32 + data_width: 32 + len_width: 8 + type: axi + + mgrs: + m_ibex: + subs: + s_creg: + address: 0x8f000000:0x8f010000 + s_sram: + address: 0x8f020000:0x8f020800 + s_dmb: + address: 0x8f0f0000:0xffffffff + + inst_parameters: + - AXI_USER_WIDTH 12 + inst_pre_code: + - "assign clk = hspclk;" + - "assign rstn = hsp_reset_nai;" + + hsp_encr_apb_fabric: + bus: + id_width: 5 + addr_width: 32 + data_width: 32 + len_width: 8 + apb_ext: m_creg + axi_ext: s_creg + type: axi2apb + + subs: + tbre: + address: + - 32'h8f00_0000 32'h8f00_0100 + intc: + address: + - 32'h8f00_0600 32'h8f00_0640 + tmr0: + address: + - 32'h8f00_0800 32'h8f00_0840 + tmr1: + address: + - 32'h8f00_0840 32'h8f00_0880 + uart: + address: + - 32'h8f00_b000 32'h8f00_c000 + spi: + address: + - 32'h8f00_c000 32'h8f00_d000 + i2c: + address: + - 32'h8f00_d000 32'h8f00_e000 + gpio: + address: + - 32'h8f00_f000 32'h8f01_0000 + + + creg_intc: + module: msftDvIp_creg_intc + rtl: ip/dvip/rtl/Intc/verilog/msftDvIp_creg_intc.sv + inst_pre_code: + - "assign irqs[15:0] = 16'h0000;" + - "assign irqs[16] = sys_eth_irq;" + - "assign irqs[17] = tmr_irq0 | tmr_irq1;" + - "assign irqs[18] = dma_completion_intc_i;" + - "assign irqs[31:19] = 13'h0000;" + pin_sub: + - "psel psel_intc" + - "penable penable_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "pwrite pwrite_m_creg" + - "prdata prdata_intc" + - "pready pready_intc" + - "pslverr psuberr_intc" + + creg_timer0: + module: msftDvIp_creg_timer + rtl: ip/dvip/rtl/Timer/verilog/msftDvIp_creg_timer.sv + pin_sub: + - "psel psel_tmr0" + - "penable penable_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "pwrite pwrite_m_creg" + - "prdata prdata_tmr0" + - "pready pready_tmr0" + - "pslverr psuberr_tmr0" + - "irq tmr_irq0" + - "err tmr_err0" + - "sticky_err tmr_sticky_err0" + + creg_timer1: + module: msftDvIp_creg_timer + rtl: ip/dvip/rtl/Timer/verilog/msftDvIp_creg_timer.sv + pin_sub: + - "psel psel_tmr1" + - "penable penable_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "pwrite pwrite_m_creg" + - "prdata prdata_tmr1" + - "pready pready_tmr1" + - "pslverr psuberr_tmr1" + - "irq tmr_irq1" + - "err tmr_err1" + - "sticky_err tmr_sticky_err1" + + DW_apb_uart_wrapper: + rtl: ip/vendor/uart/DW_apb_uart_wrapper.v + pin_sub: + - "pclk clk" + - "presetn rstn" + - "sin gpio_hsp_uart_sin" + - "sout hsp_gpio_uart_sout" + - "scan_mode 1'b0" + - "pslverr_uart psuberr_uart" + + DW_apb_i2c_wrapper: + rtl: ip/vendor/i2c/DW_apb_i2c_wrapper.v + pin_sub: + - "pclk clk" + - "presetn rstn" + - "ic_clk clk" + - "ic_rst_n rstn" + - "psel psel_i2c" + - "penable penable_m_creg" + - "pwrite pwrite_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "prdata prdata_i2c" + - "pready pready_i2c" + - "pslverr psuberr_i2c" + - "ic_en " + - "ic_clk_in_a gpio_hsp_i2c_scl_i" + - "ic_data_in_a gpio_hsp_i2c_sda_i" + - "ic_clk_oe hsp_gpio_i2c_scl_oe" + - "ic_data_oe hsp_gpio_i2c_sda_oe" + +# DWC_ssi_wrapper: +# rtl: ip/vendor/spi/DWC_ssi_wrapper.v +# pin_sub: +# - "pclk clk" +# - "presetn rstn" +# - "psel psel_ssi" + + dmb: + rtl: ip/dmb/verilog/dmb.v + pin_sub: + - "dmb_axi_slv_awid awid_s_dmb[3:0]" + - "dmb_axi_slv_awlock awlock_s_dmb[0]" + - "dmb_axi_slv_aruser 12'h0" + - "dmb_axi_slv_awuser 12'h0" + #- "dmb_axi_slv_bid bid_s_dmb[3:0]" + - "dmb_axi_slv_arid arid_s_dmb[3:0]" + - "dmb_axi_slv_arlock arlock_s_dmb[0]" + #- "dmb_axi_slv_rid rid_s_dmb[3:0]" + - "dmb_ext_mst_awlock hsp_axi_mst_awlock[0]" + - "dmb_ext_mst_arlock hsp_axi_mst_arlock[0]" + - "r%dmb_axi_slv_(\\S+) \\1_s_dmb" + - "r%dmb_ext_mst_(\\S+) hsp_axi_mst_\\1" + - "hsp_reset_na hsp_reset_nai" + - "dmb_w_allowed 1'b1" + + shared_ram: + pin_sub: + - "s_axi_clk hspclk" + - "s_axi_rst_n hsp_reset_nai" + - "r%s_axi_(\\S+) \\1_s_sram" + module: msftDvIp_axi_mem_bit_write + inst_parameters: + - AXI_ADDR_WIDTH 32 + - AXI_DATA_WIDTH 32 + - AXI_ID_WIDTH 5 + - AXI_LEN_WIDTH 8 + - AXI_LOCK_WIDTH 2 + - "MEM_SIZE 'h200000" + rtl: ip/dvip/rtl/Memories/msftDvIp_axi_mem_bit_write.sv + +# cheri_por: +# rtl: subsystem/cheri0/verif/tb/rtl/cheri_por.sv +# pin_sub: +# - "psel psel_por" +# - "penable penable_m_creg" +# - "paddr paddr_m_creg" +# - "pwdata pwdata_m_creg" +# - "pwrite pwrite_m_creg" +# - "prdata prdata_por" +# - "pready pready_por" +# - "pslverr pslverr_por" + + msftDvIp_gpio: + rtl: ip/dvip/rtl/Gpio/verilog/msftDvIp_gpio.sv + pin_sub: + - "pclk hspclk" + - "prstn hsp_reset_nai" + - "psel psel_gpio" + - "penable penable_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "pwrite pwrite_m_creg" + - "prdata prdata_gpio" + - "pready pready_gpio" + - "pslverr psuberr_gpio" + + tbreRegs: + rtl: ip/dvip/rtl/tbreRegs/verilog/tbreRegs.sv + pin_sub: + - "pclk hspclk" + - "prstn hsp_reset_nai" + - "psel psel_tbre" + - "penable penable_m_creg" + - "paddr paddr_m_creg" + - "pwdata pwdata_m_creg" + - "pwrite pwrite_m_creg" + - "prdata prdata_tbre" + - "pready pready_tbre" + - "pslverr psuberr_tbre" diff --git a/vendor/lowrisc_ibex/dma-ip/ibex_memory.sv b/vendor/lowrisc_ibex/dma-ip/ibex_memory.sv new file mode 100644 index 000000000..da8e65a00 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/ibex_memory.sv @@ -0,0 +1,224 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + + +`include "dvp_ibex_defines.svh" + +module ibex_memory ( + + input clk_i, + input rstn_i, + + input IROM_EN_i, + input [31:0] IROM_ADDR_i, + output [32:0] IROM_RDATA_o, + output IROM_READY_o, + output IROM_ERROR_o, + input IROM_WE_i, + input [3:0] IROM_BE_i, + input [32:0] IROM_WDATA_i, + + input IRAM_EN_i, + input [31:0] IRAM_ADDR_i, + input [32:0] IRAM_WDATA_i, + input IRAM_WE_i, + input [3:0] IRAM_BE_i, + output [32:0] IRAM_RDATA_o, + output IRAM_READY_o, + output IRAM_ERROR_o, + + input DRAM_EN_i, + input [31:0] DRAM_ADDR_i, + input [32:0] DRAM_WDATA_i, + input DRAM_WE_i, + input [3:0] DRAM_BE_i, + output [32:0] DRAM_RDATA_o, + output DRAM_READY_o, + output DRAM_ERROR_o, + + input tsmap_cs_i, + input [15:0] tsmap_addr_i, + output [31:0] tsmap_rdata_o, + + input dma_tsmap_cs_i, + input [15:0] dma_tsmap_addr_i, + output [31:0] dma_tsmap_rdata_o, + output tsmap_is_occupied_o, + + output logic snooped_tsmap_cs_o, + output logic [15:0] snooped_tsmap_addr_o, + output logic [31:0] snooped_tsmap_rdata_o + +); + + +//=============================================== +// Internal Wires +//=============================================== +wire clk; +wire rstn; + +wire IROM_EN; +wire [31:0] IROM_ADDR; +wire [32:0] IROM_WDATA; +wire IROM_WE; +wire [3:0] IROM_BE; +wire [32:0] IROM_RDATA; + +wire irom_wren; + +wire IRAM_EN; +wire [31:0] IRAM_ADDR; +wire [32:0] IRAM_WDATA; +wire IRAM_WE; +wire [3:0] IRAM_BE; +wire [32:0] IRAM_RDATA; +wire IRAM_READY; +wire IRAM_ERROR; + +wire DRAM_EN; +wire [31:0] DRAM_ADDR; +wire [32:0] DRAM_WDATA; +wire DRAM_WE; +wire [3:0] DRAM_BE; +wire [32:0] DRAM_RDATA; +wire DRAM_READY; +wire DRAM_ERROR; + +//=============================================== +// IROM +//=============================================== +//fpga_block_ram_model_dvp #( +fpga_block_ram_byte_wr_model_dvp #( + .RAM_WIDTH (33), + .RAM_DEPTH ('h10000), + .INIT_FILE (`DVP_IROM_INIT_FILE) + ) irom ( + .clk (clk), + .cs (IROM_EN), + .dout (IROM_RDATA), + .addr (IROM_ADDR[17:2]), + .din (IROM_WDATA), + .we (IROM_WE & irom_wren), + .wstrb({ 1'b1, {8{IROM_BE[3]}}, {8{IROM_BE[2]}}, {8{IROM_BE[1]}}, {8{IROM_BE[0]}} }), + .ready () + ); + +//=============================================== +// IRAM +//=============================================== +fpga_block_ram_byte_wr_model_dvp #( + .RAM_WIDTH (33), + .RAM_DEPTH ('h20000), + .INIT_FILE ("") + ) iram ( + .clk (clk), + .cs (IRAM_EN), + .addr (IRAM_ADDR[18:2]), + .dout (IRAM_RDATA), + .din (IRAM_WDATA), + .we (IRAM_WE), + .wstrb({ 1'b1, {8{IRAM_BE[3]}}, {8{IRAM_BE[2]}}, {8{IRAM_BE[1]}}, {8{IRAM_BE[0]}} }), + .ready (IRAM_READY) + ); + +//=============================================== +// DRAM +//=============================================== + +//=============================================== +// Alternative 1 for safety at DMA controller +//=============================================== + +logic tsmap_cs; +logic [15:0] tsmap_addr, tsmap_addr_reg; +logic [31:0] tsmap_rdata; + +logic tsmap_is_occupied; +logic dma_tsmap_is_occupied; + +assign tsmap_cs = tsmap_cs_i || dma_tsmap_cs_i; +// cpu requests are always in the priority +assign tsmap_addr = tsmap_cs_i ? tsmap_addr_i : dma_tsmap_addr_i; + +// we are assuming that the result is available +// in the next cycle for the cpu +assign tsmap_is_occupied_o = tsmap_cs_i; + +// only the accurate should pass through, +// unless otherwise only 0 +assign tsmap_rdata_o = tsmap_is_occupied ? tsmap_rdata : 0; +assign dma_tsmap_rdata_o = dma_tsmap_is_occupied ? tsmap_rdata : 0; + +//=============================================== +// Alternative 2 for safety at DMA controller. +// Everything but the rdata are the delayed signals +// to keep the logic at the DMA simpler +//=============================================== +assign snooped_tsmap_cs_o = tsmap_is_occupied; +assign snooped_tsmap_addr_o = tsmap_addr_i; +assign snooped_tsmap_rdata_o = tsmap_rdata; + +always_ff @( posedge clk ) begin : assigning_Tsmap_Inp + if (!rstn) begin + tsmap_is_occupied <= 0; + dma_tsmap_is_occupied <= 0; + tsmap_addr_reg <= 0; + end else begin + tsmap_is_occupied <= tsmap_cs_i; + dma_tsmap_is_occupied <= (!tsmap_cs_i & dma_tsmap_cs_i); + tsmap_addr_reg <= tsmap_addr_i; + end +end + +fpga_block_ram_2port_model_dvp #( + .RAM_WIDTH (33), + .RAM_DEPTH ('h4000), + .INIT_FILE ("") + ) dram ( + .clk(clk), + .cs(DRAM_EN), + .dout(DRAM_RDATA), + .addr(DRAM_ADDR[15:2]), + .din(DRAM_WDATA), + .we(DRAM_WE), + .wstrb({ 1'b1, {8{DRAM_BE[3]}}, {8{DRAM_BE[2]}}, {8{DRAM_BE[1]}}, {8{DRAM_BE[0]}} }), + .ready(dram_rdy), + .cs2 (tsmap_cs), + .addr2(tsmap_addr[12:0]), + .dout2(tsmap_rdata) + ); + +//=============================================== +// Connect ports +//=============================================== +assign clk = clk_i; +assign rstn = rstn_i; + +assign IROM_EN = IROM_EN_i; +assign IROM_ADDR = IROM_ADDR_i; +assign IROM_RDATA_o = IROM_RDATA; +assign IROM_READY_o = 1'b1; +assign IROM_ERROR_o = 1'b0; +assign IROM_WDATA = IROM_WDATA_i; +assign IROM_WE = IROM_WE_i; +assign IROM_BE = IROM_BE_i; + +assign IRAM_EN = IRAM_EN_i; +assign IRAM_ADDR = IRAM_ADDR_i; +assign IRAM_WDATA = IRAM_WDATA_i; +assign IRAM_WE = IRAM_WE_i; +assign IRAM_BE = IRAM_BE_i; +assign IRAM_RDATA_o = IRAM_RDATA; +assign IRAM_READY_o = 1'b1; +assign IRAM_ERROR_o = 1'b0; + +assign DRAM_EN = DRAM_EN_i; +assign DRAM_ADDR = DRAM_ADDR_i; +assign DRAM_WDATA = DRAM_WDATA_i; +assign DRAM_WE = DRAM_WE_i; +assign DRAM_BE = DRAM_BE_i; +assign DRAM_RDATA_o = DRAM_RDATA; +assign DRAM_READY_o = 1'b1; +assign DRAM_ERROR_o = 1'b0; + +endmodule diff --git a/vendor/lowrisc_ibex/dma-ip/ibex_subsystem.yml b/vendor/lowrisc_ibex/dma-ip/ibex_subsystem.yml new file mode 100644 index 000000000..471dff266 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/ibex_subsystem.yml @@ -0,0 +1,137 @@ + + + +ibex_subsystem: + pinlist: + - input clk_i + - input rstn_i + - input [3:0] fetch_enable_i + - input test_en_i + - input cheri_pmode_i + - input cheri_tsafe_en_i + + - axibus: + name: _m_ibex + dir: output + idwidth: 4 + awidth: 32 + dwidth: 32 + len: 8 + swidth: 4 + uwidth: 12 + case: lower + +# - apbbus: +# name: _apb +# dir: output +# awidth: 32 +# dwidth: 32 +# case: lower + + - output txd_o + - input rxd_i + + - input [31:0] curr_PC_i + - input inst_val_i + - input [31:0] inst_reg_i + + - output [31:0] out0_o + - output [31:0] out1_o + - output [31:0] out2_o + - input [31:0] in0_i + + - output [31:0] dbg_gp_out_o + - input [31:0] dbg_gp_in_i + + - input TRSTn_o + - input TCK_o + - input TMS_o + - input TDI_i + - output TDO_o + - output TDOoen_o + + - input irq_external_i + - input irq_timer_i + - input [14:0] irq_fast_i + - input irq_nm_i + + - output tbre_done_o + - input [64:0] tbre_ctrl_vec_i + + - output dma_completion_intc_o + + include_list: + - "$PROJECT_PATH/$PROJECT_NAME/ip/dvp/ibex/tb" + + file_list: + + #bus: + # ibex_ss_axi_fabric: + # id_width: 4 + # addr_width: 32 + # data_width: 32 + # len_width: 8 + # type: axi +# +# masters: +# m_ibex: +# slaves: +# s_creg: +# address: 0x87000000:0x88000000 +# s_sram: +# address: 0x8f020000:0x8f020800 +# s_dmb: +# address: 0x8f0f0000:0xffffffff +# +# ss_apb: +# id_width: 4 +# addr_width: 32 +# data_width: 32 +# len_width: 8 +# apb_ext: m_creg +# axi_ext: s_creg +# type: axi2apb +# +# slaves: +# uart: +# address: +# - 32'h8f00_b000 32'h8f00_c000 +# spi: +# address: +# - 32'h8f00_c000 32'h8f00_d000 +# i2c: +# address: +# - 32'h8f00_d000 32'h8f00_e000 + + instances: +# dv_ohg_riscv_wrapper: +# rtl: ip/dv_subsystem/ip/riscv/rtl/riscv_wrapper/dv_ohg_riscv_wrapper.sv +# ibex_ss_axi_fabric: +# inst_parameters: +# yml: ./ibex_ss_axi_fabric.yml +# +# ss_apb: +# yml: ./ss_apb.yml + + ibex_memory: + rtl: ip/dvp/ibexc/memory/ibex_memory.sv + +# dvp_dmb: +# rtl: ip/dv_subsystem/ip/dvp/rtl/dvp_dmb/dvp_dmb.sv +# +# dv_periph_wrapper: +# pin_sub: +# - "r%axi_(\\S+)_[io] dv_axi_\\1" +# rtl: ip/dv_subsystem/ip/dvp/rtl/dv_periph_wrapper/dv_periph_wrapper.sv + +# ibex_periph: +# yml: ip/dvp/ibexc/yml/ibex_periph.yml + + dvp_ibex_wrapper: + yml: ip/dvp/ibexc/yml/dvp_ibex_wrapper.yml + pin_sub: + - "r%^AW(\\S+) aw\\1_m_ibex tolower" + - "r%^W(\\S+) w\\1_m_ibex tolower" + - "r%^B(\\S+) b\\1_m_ibex tolower" + - "r%^AR(\\S+) ar\\1_m_ibex tolower" + - "r%^R(\\S+) r\\1_m_ibex tolower" diff --git a/vendor/lowrisc_ibex/dma-ip/ibexc_obimux3w0.sv b/vendor/lowrisc_ibex/dma-ip/ibexc_obimux3w0.sv new file mode 100644 index 000000000..053256cc8 --- /dev/null +++ b/vendor/lowrisc_ibex/dma-ip/ibexc_obimux3w0.sv @@ -0,0 +1,895 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +// Parameters +// SIZE 4K = 12 +// SIZE 8K = 13 +// SIZE 16K = 14 +// SIZE 32K = 15 +// SIZE 64K = 16 +// SIZE 128K = 17 +// SIZE 256K = 18 +// SIZE 512K = 19 + + +// +// Master side mux +// + +module mstr_mux # ( + parameter DBGMEM_START_ADDRESS = 32'h0000_0000, + parameter DBGMEM_END_ADDRESS = 32'h0300_0000, + parameter IROM_START_ADDRESS = 32'h2000_0000, + parameter IROM_END_ADDRESS = 32'h2004_0000, + parameter IRAM_START_ADDRESS = 32'h2004_0000, + parameter IRAM_END_ADDRESS = 32'h200C_0000, + parameter DRAM_START_ADDRESS = 32'h200F_0000, + parameter DRAM_END_ADDRESS = 32'h2010_0000, + parameter DMA_START_ADDRESS = 32'h2020_0000, + parameter DMA_END_ADDRESS = 32'h2020_0040, + parameter nSLV = 6 + ) ( + input logic clk_i, + input logic rstn_i, + + // master side signals + input logic mstr_req_i, + output logic mstr_gnt_o, + input logic [31:0] mstr_addr_i, + input logic [3:0] mstr_be_i, + input logic [32:0] mstr_wdata_i, + input logic mstr_we_i, + output logic [32:0] mstr_rdata_o, + output logic mstr_rvalid_o, + output logic mstr_err_o, + + output logic [nSLV-1:0] slv_req_o, + output logic [31:0] slv_addr_o, + output logic [3:0] slv_be_o, + output logic [32:0] slv_wdata_o, + output logic slv_we_o, + input logic [nSLV-1:0] slv_gnt_i, + + input logic [nSLV-1:0][32:0] slv_rdata_i, + input logic [nSLV-1:0] slv_rvalid_i, + input logic [nSLV-1:0] slv_err_i + +); + +`define IS_DBG_IROM_ADDR(addr) (addr >= DBGMEM_START_ADDRESS && addr < DBGMEM_END_ADDRESS) +`define IS_IROM_ADDR(addr) (addr >= IROM_START_ADDRESS && addr < IROM_END_ADDRESS) +`define IS_IRAM_ADDR(addr) (addr >= IRAM_START_ADDRESS && addr < IRAM_END_ADDRESS) +`define IS_DRAM_ADDR(addr) (addr >= DRAM_START_ADDRESS && addr < DRAM_END_ADDRESS) +`define IS_DMA_ADDR(addr) (addr >= DMA_START_ADDRESS && addr < DMA_END_ADDRESS) + + logic [nSLV-1:0] pending_slv_resp; + logic [nSLV-1:0] slv_req_dec; + logic mstr_gnt; + logic rvalid_done, rvalid_done_q; + + assign mstr_gnt_o = mstr_gnt; + + assign mstr_gnt = |(slv_gnt_i & slv_req_o); // hold off gnt till the actuall slv_req_o is generated + + // slv_req generation + // if switching slaves, hold off req until the response from the previous slave is back to avoid conflicts + // + + assign rvalid_done = ((pending_slv_resp & slv_rvalid_i) != 0); + assign slv_req_o = ((pending_slv_resp == 0) || (pending_slv_resp == slv_req_dec) || rvalid_done) ? slv_req_dec : 0; + + // pass through + assign slv_addr_o = mstr_addr_i; + assign slv_be_o = mstr_be_i; + assign slv_we_o = mstr_we_i; + assign slv_wdata_o = mstr_wdata_i; + + always @(posedge clk_i or negedge rstn_i) + begin + if(~rstn_i) begin + pending_slv_resp <= 0; + end else begin + if(mstr_gnt) pending_slv_resp <= slv_req_dec; + else if (rvalid_done) pending_slv_resp <= 0; + end + end + + //======================================== + // Address Space Defines + //======================================== + + always_comb begin + int i; + + if (mstr_req_i && `IS_DBG_IROM_ADDR(mstr_addr_i)) + slv_req_dec = 'h1; + else if (mstr_req_i && `IS_IROM_ADDR(mstr_addr_i)) + slv_req_dec = 'h2; + else if (mstr_req_i && `IS_IRAM_ADDR(mstr_addr_i)) + slv_req_dec = 'h4; + else if (mstr_req_i && `IS_DRAM_ADDR(mstr_addr_i)) + slv_req_dec = 'h8; + else if (mstr_req_i && `IS_DMA_ADDR(mstr_addr_i)) + slv_req_dec = 'h20; + else if (mstr_req_i) + slv_req_dec = 'h10; // default choose AXI + else + slv_req_dec = 'h0; + + mstr_rdata_o = 33'h0; + for (i = 0; i < nSLV; i++) begin + if (pending_slv_resp[i]) mstr_rdata_o = slv_rdata_i[i]; + end + + end + + assign mstr_rvalid_o = |(pending_slv_resp & slv_rvalid_i); + assign mstr_err_o = |(pending_slv_resp & slv_err_i); + +endmodule + +// +// Slave side mux for TCM memories +// + +module slv_mem_mux # ( + parameter nMSTR = 4 + ) ( + input logic clk_i, + input logic rstn_i, + + // master side signals + input logic [nMSTR-1:0] mstr_req_i, + output logic [nMSTR-1:0] mstr_gnt_o, + input logic [nMSTR-1:0][31:0] mstr_addr_i, + input logic [nMSTR-1:0][3:0] mstr_be_i, + input logic [nMSTR-1:0][32:0] mstr_wdata_i, + input logic [nMSTR-1:0] mstr_we_i, + output logic [32:0] mstr_rdata_o, + output logic mstr_rvalid_o, + output logic mstr_err_o, + + output logic mem_en_o, + output logic [31:0] mem_addr_o, + output logic [32:0] mem_wdata_o, + output logic mem_we_o, + output logic [3:0] mem_be_o, + input logic [32:0] mem_rdata_i, + input logic mem_ready_i, + input logic mem_error_i +); + + logic [nMSTR-1:0] mstr_gnt; + logic rvalid; + + assign mstr_gnt_o = mstr_gnt; + assign mstr_rdata_o = mem_rdata_i; + assign mstr_rvalid_o = rvalid; + assign mstr_err_o = mem_error_i; + + // gnt by strict priority assignment - mst_req[0] == highest priority + for (genvar i = 0; i < nMSTR; i++) begin + logic [7:0] pri_mask; + assign pri_mask = 8'hff >> (8-i); // max 8 masters, should be enough + assign mstr_gnt[i] = mem_ready_i & mstr_req_i[i] & ~(|(mstr_req_i & pri_mask)); + end + + // mux for mem side controls + assign mem_en_o = |mstr_gnt; + + always_comb begin + int i; + + mem_addr_o = 32'h0; + mem_wdata_o = 33'h0; + mem_we_o = 1'b0; + mem_be_o = 4'h0; + + for (i = 0; i < nMSTR; i++) begin + mem_addr_o = mem_addr_o | (mstr_addr_i[i] & {32{mstr_gnt[i]}}); + mem_wdata_o = mem_wdata_o | (mstr_wdata_i[i] & {33{mstr_gnt[i]}}); + mem_we_o = mem_we_o | (mstr_we_i[i] & mstr_gnt[i]); + mem_be_o = mem_be_o | (mstr_be_i[i] & {4{mstr_gnt[i]}}); + end + + end + + always @(posedge clk_i or negedge rstn_i) begin + if(~rstn_i) begin + rvalid <= 1'b0; + end else begin + rvalid <= |mstr_gnt; + end + end + +endmodule + +// +// Slave side mux for the AXI bus +// + +module slv_axi_mux # ( + parameter AXI_ID = 4'h0, + parameter USER_BIT_WIDTH = 12, + parameter nMSTR = 4 + ) ( + input logic clk_i, + input logic rstn_i, + + // master side signals + input logic [nMSTR-1:0] mstr_req_i, + output logic [nMSTR-1:0] mstr_gnt_o, + input logic [nMSTR-1:0][31:0] mstr_addr_i, + input logic [nMSTR-1:0][3:0] mstr_be_i, + input logic [nMSTR-1:0][32:0] mstr_wdata_i, + input logic [nMSTR-1:0] mstr_we_i, + output logic [32:0] mstr_rdata_o, + output logic mstr_rvalid_o, + output logic mstr_err_o, + + output logic [3:0] AWID_o, + output logic [31:0] AWADDR_o, + output logic [7:0] AWLEN_o, + output logic [2:0] AWSIZE_o, + output logic [1:0] AWBURST_o, + output logic [1:0] AWLOCK_o, + output logic [2:0] AWPROT_o, + output logic [3:0] AWCACHE_o, + output logic [USER_BIT_WIDTH-1:0] AWUSER_o, + output logic AWVALID_o, + input logic AWREADY_i, + + output logic [31:0] WDATA_o, + output logic [3:0] WSTRB_o, + output logic WLAST_o, + output logic WVALID_o, + input logic WREADY_i, + + input logic [3:0] BID_i, + input logic [1:0] BRESP_i, + input logic BVALID_i, + output logic BREADY_o, + + output logic [3:0] ARID_o, + output logic [31:0] ARADDR_o, + output logic [7:0] ARLEN_o, + output logic [2:0] ARSIZE_o, + output logic [1:0] ARBURST_o, + output logic [1:0] ARLOCK_o, + output logic [2:0] ARPROT_o, + output logic [3:0] ARCACHE_o, + output logic [USER_BIT_WIDTH-1:0] ARUSER_o, + output logic ARVALID_o, + input logic ARREADY_i, + + input logic [3:0] RID_i, + input logic [31:0] RDATA_i, + input logic RLAST_i, + input logic [1:0] RRESP_i, + input logic RVALID_i, + output logic RREADY_o +); + + typedef enum {AXI_IDLE, AXI_ACC, AXI_RESP} axi_fsm_t; + + axi_fsm_t axi_fsm_q; + + logic [nMSTR-1:0] mstr_gnt, mstr_gnt_q; + logic axi_wr_done, w_done, aw_done; + logic axi_acc_done, axi_resp_done; + logic [31:0] axi_addr; + logic [32:0] axi_wdata; + logic axi_we, axi_we_q; + logic [3:0] axi_be; + + // Masters side outputs + assign mstr_gnt_o = (axi_fsm_q == AXI_ACC) & axi_acc_done; + assign mstr_rdata_o = RDATA_i; + assign mstr_rvalid_o = (axi_fsm_q == AXI_RESP) & axi_resp_done; + assign mstr_err_o = (axi_fsm_q == AXI_RESP) & ((axi_we_q & BRESP_i[1]) | (~axi_we_q & RRESP_i[1])); + + // AXI side outputs + assign AWID_o = AXI_ID; + assign AWADDR_o = axi_addr; + assign AWLEN_o = 8'h0; + assign AWSIZE_o = 2'h2; + assign AWBURST_o = 2'h1; + assign AWLOCK_o = 1'b0; + assign AWPROT_o = 3'h1; + assign AWCACHE_o = 4'h0; + assign AWUSER_o = {USER_BIT_WIDTH{1'b0}}; + assign AWVALID_o = (axi_fsm_q == AXI_ACC) & axi_we & ~aw_done; + + assign WDATA_o = axi_wdata; + assign WSTRB_o = axi_be; + assign WLAST_o = 1'b1; + assign WVALID_o = (axi_fsm_q == AXI_ACC) & axi_we & ~w_done; + + assign BREADY_o = 1'b1; + + assign ARID_o = AXI_ID; + assign ARADDR_o = axi_addr; + assign ARLEN_o = 8'h0; + assign ARSIZE_o = 2'h2; + assign ARBURST_o = 2'h1; + assign ARLOCK_o = 1'b0; + assign ARPROT_o = 3'h1; + assign ARCACHE_o = 4'h0; + assign ARUSER_o = {USER_BIT_WIDTH{1'b0}}; + assign ARVALID_o = (axi_fsm_q == AXI_ACC) & ~axi_we; + + assign RREADY_o = 1'b1; + + assign axi_wr_done = (AWREADY_i | aw_done) & (WREADY_i | w_done); + assign axi_acc_done = (~axi_we & ARREADY_i) | (axi_we & axi_wr_done); + assign axi_resp_done = (axi_we_q & BVALID_i) | (~axi_we_q & RVALID_i); + + // gnt by strict priority assignment - mst_req[0] == highest priority + for (genvar i = 0; i < nMSTR; i++) begin + logic [7:0] pri_mask; + assign pri_mask = 8'hff >> (8-i); // max 8 masters, should be enough + assign mstr_gnt[i] = mstr_req_i[i] & ~(|(mstr_req_i & pri_mask)); + end + + // mux for mem side controls + + always_comb begin + int i; + + axi_addr = 32'h0; + axi_wdata = 33'h0; + axi_we = 1'b0; + axi_be = 4'h0; + + for (i = 0; i < nMSTR; i++) begin + axi_addr = axi_addr | (mstr_addr_i[i] & {32{mstr_gnt_q[i]}}); + axi_wdata = axi_wdata | (mstr_wdata_i[i] & {33{mstr_gnt_q[i]}}); + axi_we = axi_we | (mstr_we_i[i] & mstr_gnt_q[i]); + axi_be = axi_be | (mstr_be_i[i] & {4{mstr_gnt_q[i]}}); + end + + end + + always @(posedge clk_i or negedge rstn_i) begin + if(~rstn_i) begin + mstr_gnt_q <= 0; + axi_we_q <= 1'b0; + aw_done <= 1'b0; + w_done <= 1'b0; + axi_fsm_q <= AXI_IDLE; + end else begin + + // let's do a simple sequential state machine since we don't really care about + // performance over AXI in FPGA + case (axi_fsm_q) + AXI_IDLE: + if (mstr_req_i != 0) begin + axi_fsm_q <= AXI_ACC; + mstr_gnt_q <= mstr_gnt; // latch gnt decision + w_done <= 1'b0; + aw_done <= 1'b0; + end + AXI_ACC: + begin + if (AWREADY_i) aw_done <= 1'b1; + if (WREADY_i) w_done <= 1'b1; + + if ((~axi_we & ARREADY_i) | (axi_we & axi_wr_done)) begin + axi_fsm_q <= AXI_RESP; + axi_we_q <= axi_we; // latch transaction type + end + end + AXI_RESP: + if (axi_resp_done) axi_fsm_q <= AXI_IDLE; + default: + axi_fsm_q <= AXI_IDLE; + endcase + end + end + +endmodule + + +module ibexc_obimux3w0 #( + parameter AXI_ID = 4'h0, + parameter USER_BIT_WIDTH = 12 + ) ( + input clk_i, + input rstn_i, + + input data_req_i, + output data_gnt_o, + input [31:0] data_addr_i, + input [3:0] data_be_i, + input [32:0] data_wdata_i, + input data_we_i, + + output [32:0] data_rdata_o, + output data_rvalid_o, + output data_error_o, + + input instr_req_i, + output instr_gnt_o, + input [31:0] instr_addr_i, + + output [32:0] instr_rdata_o, + output instr_rvalid_o, + output instr_error_o, + + input dbg_req_i, + output dbg_gnt_o, + input [31:0] dbg_addr_i, + input [3:0] dbg_be_i, + input [32:0] dbg_wdata_i, + input dbg_we_i, + + output [32:0] dbg_rdata_o, + output dbg_rvalid_o, + output dbg_error_o, + + output DBGMEM_EN_o, + output [31:0] DBGMEM_ADDR_o, + output [32:0] DBGMEM_WDATA_o, + output DBGMEM_WE_o, + output [3:0] DBGMEM_BE_o, + input [32:0] DBGMEM_RDATA_i, + input DBGMEM_READY_i, + input DBGMEM_ERROR_i, + + output IROM_EN_o, + output [31:0] IROM_ADDR_o, + output [32:0] IROM_WDATA_o, + output IROM_WE_o, + output [3:0] IROM_BE_o, + input [32:0] IROM_RDATA_i, + input IROM_READY_i, + input IROM_ERROR_i, + + output IRAM_EN_o, + output [31:0] IRAM_ADDR_o, + output [32:0] IRAM_WDATA_o, + output IRAM_WE_o, + output [3:0] IRAM_BE_o, + input [32:0] IRAM_RDATA_i, + input IRAM_READY_i, + input IRAM_ERROR_i, + + output DRAM_EN_o, + output [31:0] DRAM_ADDR_o, + output [32:0] DRAM_WDATA_o, + output DRAM_WE_o, + output [3:0] DRAM_BE_o, + input [32:0] DRAM_RDATA_i, + input DRAM_READY_i, + input DRAM_ERROR_i, + + output [3:0] AWID_o, + output [31:0] AWADDR_o, + output [7:0] AWLEN_o, + output [2:0] AWSIZE_o, + output [1:0] AWBURST_o, + output [1:0] AWLOCK_o, + output [2:0] AWPROT_o, + output [3:0] AWCACHE_o, + output [USER_BIT_WIDTH-1:0] AWUSER_o, + output AWVALID_o, + input AWREADY_i, + + output [31:0] WDATA_o, + output [3:0] WSTRB_o, + output WLAST_o, + output WVALID_o, + input WREADY_i, + + input [3:0] BID_i, + input [1:0] BRESP_i, + input BVALID_i, + output BREADY_o, + + output [3:0] ARID_o, + output [31:0] ARADDR_o, + output [7:0] ARLEN_o, + output [2:0] ARSIZE_o, + output [1:0] ARBURST_o, + output [1:0] ARLOCK_o, + output [2:0] ARPROT_o, + output [3:0] ARCACHE_o, + output [USER_BIT_WIDTH-1:0] ARUSER_o, + output ARVALID_o, + input ARREADY_i, + + input [3:0] RID_i, + input [31:0] RDATA_i, + input RLAST_i, + input [1:0] RRESP_i, + input RVALID_i, + output RREADY_o, + + // DMA Controller Interface + input dma_controller_req_i, + output dma_controller_gnt_o, + input [31:0] dma_controller_addr_i, + input [3:0] dma_controller_be_i, + input [32:0] dma_controller_wdata_i, + input dma_controller_we_i, + output [32:0] dma_controller_rdata_o, + output dma_controller_rvalid_o, + output dma_controller_error_o, + + output dma_conf_en_o, + output [31:0] dma_conf_addr_o, + output [32:0] dma_conf_wdata_o, + output dma_conf_we_o, + output [3:0] dma_conf_be_o, + input [32:0] dma_conf_rdata_i, + input dma_conf_ready_i, + input dma_conf_error_i + +); + + localparam nSLV = 6; + localparam nMSTR = 4; + + logic [nSLV-1:0] cpud_req; + logic [31:0] cpud_addr; + logic [3:0] cpud_be; + logic [32:0] cpud_wdata; + logic cpud_we; + logic [nSLV-1:0] cpud_gnt; + + logic [nSLV-1:0] cpui_req; + logic [31:0] cpui_addr; + logic [3:0] cpui_be; + logic [32:0] cpui_wdata; + logic cpui_we; + logic [nSLV-1:0] cpui_gnt; + + logic [nSLV-1:0] dbgm_req; + logic [31:0] dbgm_addr; + logic [3:0] dbgm_be; + logic [32:0] dbgm_wdata; + logic dbgm_we; + logic [nSLV-1:0] dbgm_gnt; + + logic [nSLV-1:0][32:0] s2m_rdata; + logic [nSLV-1:0] s2m_rvalid; + logic [nSLV-1:0] s2m_err; + + logic [nMSTR-1:0] dbgmem_req; + logic [nMSTR-1:0] dbgmem_gnt; + logic [32:0] dbgmem_rdata; + logic dbgmem_rvalid; + logic dbgmem_err; + + logic [nMSTR-1:0] irom_req; + logic [nMSTR-1:0] irom_gnt; + logic [32:0] irom_rdata; + logic irom_rvalid; + logic irom_err; + + logic [nMSTR-1:0] iram_req; + logic [nMSTR-1:0] iram_gnt; + logic [32:0] iram_rdata; + logic iram_rvalid; + logic iram_err; + + logic [nMSTR-1:0] dram_req; + logic [nMSTR-1:0] dram_gnt; + logic [32:0] dram_rdata; + logic dram_rvalid; + logic dram_err; + + logic [nMSTR-1:0] axi_req; + logic [nMSTR-1:0] axi_gnt; + logic [32:0] axi_rdata; + logic axi_rvalid; + logic axi_err; + + logic [nMSTR-1:0] dma_conf_req; + logic [nMSTR-1:0] dma_conf_gnt; + logic [32:0] dma_conf_rdata; + logic dma_conf_rvalid; + logic dma_conf_err; + + logic [nSLV-1:0] dma_stream_req; + logic [31:0] dma_stream_addr; + logic [3:0] dma_stream_be; + logic [32:0] dma_stream_wdata; + logic dma_stream_we; + logic [nSLV-1:0] dma_stream_gnt; + + logic [nMSTR-1:0][31:0] m2s_addr; + logic [nMSTR-1:0][3:0] m2s_be; + logic [nMSTR-1:0][32:0] m2s_wdata; + logic [nMSTR-1:0] m2s_we; + + assign cpud_gnt = {dma_conf_gnt[0], axi_gnt[0], dram_gnt[0], iram_gnt[0], irom_gnt[0], dbgmem_gnt[0]}; + assign cpui_gnt = {dma_conf_gnt[1], axi_gnt[1], dram_gnt[1], iram_gnt[1], irom_gnt[1], dbgmem_gnt[1]}; + assign dbgm_gnt = {dma_conf_gnt[2], axi_gnt[2], dram_gnt[2], iram_gnt[2], irom_gnt[2], dbgmem_gnt[2]}; + + assign dma_stream_gnt = {dma_conf_gnt[3], axi_gnt[3], dram_gnt[3], iram_gnt[3], irom_gnt[3], dbgmem_gnt[3]}; + + assign s2m_rdata = {dma_conf_rdata, axi_rdata, dram_rdata, iram_rdata, irom_rdata, dbgmem_rdata}; // shared + assign s2m_rvalid = {dma_conf_rvalid, axi_rvalid, dram_rvalid, iram_rvalid, irom_rvalid, dbgmem_rvalid} ; // shared + assign s2m_err = {dma_conf_err, axi_err, dram_err, iram_err, irom_err, dbgmem_err} ; // shared + + assign dbgmem_req = {dma_stream_req[0], dbgm_req[0], cpui_req[0], cpud_req[0]}; + assign irom_req = {dma_stream_req[1], dbgm_req[1], cpui_req[1], cpud_req[1]}; + assign iram_req = {dma_stream_req[2], dbgm_req[2], cpui_req[2], cpud_req[2]}; + assign dram_req = {dma_stream_req[3], dbgm_req[3], cpui_req[3], cpud_req[3]}; + assign axi_req = {dma_stream_req[4], dbgm_req[4], cpui_req[4], cpud_req[4]}; + assign dma_conf_req = {dma_stream_req[5], dbgm_req[5], cpui_req[5], cpud_req[5]}; + + assign m2s_addr = {dma_stream_addr, dbgm_addr, cpui_addr, cpud_addr}; // shared + assign m2s_be = {dma_stream_be, dbgm_be, cpui_be, cpud_be}; // shared + assign m2s_we = {dma_stream_we, dbgm_we, cpui_we, cpud_we}; // shared + assign m2s_wdata = {dma_stream_wdata, dbgm_wdata, cpui_wdata, cpud_wdata}; // shared + + // + // Master-side muxes + // + mstr_mux u_cpud_mstr_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (data_req_i), + .mstr_gnt_o (data_gnt_o), + .mstr_addr_i (data_addr_i), + .mstr_be_i (data_be_i), + .mstr_wdata_i (data_wdata_i), + .mstr_we_i (data_we_i), + .mstr_rdata_o (data_rdata_o), + .mstr_rvalid_o (data_rvalid_o), + .mstr_err_o (data_error_o), + .slv_req_o (cpud_req), + .slv_addr_o (cpud_addr), + .slv_be_o (cpud_be), + .slv_wdata_o (cpud_wdata), + .slv_we_o (cpud_we), + .slv_gnt_i (cpud_gnt), + .slv_rdata_i (s2m_rdata), + .slv_rvalid_i (s2m_rvalid), + .slv_err_i (s2m_err) + ); + + mstr_mux u_cpui_mstr_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (instr_req_i), + .mstr_gnt_o (instr_gnt_o), + .mstr_addr_i (instr_addr_i), + .mstr_be_i (4'b1111), + .mstr_wdata_i (33'h0), + .mstr_we_i (1'b0), + .mstr_rdata_o (instr_rdata_o), + .mstr_rvalid_o (instr_rvalid_o), + .mstr_err_o (instr_error_o), + .slv_req_o (cpui_req), + .slv_addr_o (cpui_addr), + .slv_be_o (cpui_be), + .slv_wdata_o (cpui_wdata), + .slv_we_o (cpui_we), + .slv_gnt_i (cpui_gnt), + .slv_rdata_i (s2m_rdata), + .slv_rvalid_i (s2m_rvalid), + .slv_err_i (s2m_err) + ); + + mstr_mux u_dbgm_mstr_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (dbg_req_i), + .mstr_gnt_o (dbg_gnt_o), + .mstr_addr_i (dbg_addr_i), + .mstr_be_i (dbg_be_i), + .mstr_wdata_i (dbg_wdata_i), + .mstr_we_i (dbg_we_i), + .mstr_rdata_o (dbg_rdata_o), + .mstr_rvalid_o (dbg_rvalid_o), + .mstr_err_o (dbg_error_o), + .slv_req_o (dbgm_req), + .slv_addr_o (dbgm_addr), + .slv_be_o (dbgm_be), + .slv_wdata_o (dbgm_wdata), + .slv_we_o (dbgm_we), + .slv_gnt_i (dbgm_gnt), + .slv_rdata_i (s2m_rdata), + .slv_rvalid_i (s2m_rvalid), + .slv_err_i (s2m_err) + ); + + // + // master interface comes from the dma controller + // slave interface should be fed into memory and axi devices + // + mstr_mux u_dma_mstr_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (dma_controller_req_i), + .mstr_gnt_o (dma_controller_gnt_o), + .mstr_addr_i (dma_controller_addr_i), + .mstr_be_i (dma_controller_be_i), + .mstr_wdata_i (dma_controller_wdata_i), + .mstr_we_i (dma_controller_we_i), + .mstr_rdata_o (dma_controller_rdata_o), + .mstr_rvalid_o (dma_controller_rvalid_o), + .mstr_err_o (dma_controller_error_o), + .slv_req_o (dma_stream_req), + .slv_addr_o (dma_stream_addr), + .slv_be_o (dma_stream_be), + .slv_wdata_o (dma_stream_wdata), + .slv_we_o (dma_stream_we), + .slv_gnt_i (dma_stream_gnt), + .slv_rdata_i (s2m_rdata), + .slv_rvalid_i (s2m_rvalid), + .slv_err_i (s2m_err) + ); + + // + // Slave-side muxes + // + slv_mem_mux u_dbg_mem_slv_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (dbgmem_req), + .mstr_gnt_o (dbgmem_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (dbgmem_rdata), + .mstr_rvalid_o (dbgmem_rvalid), + .mstr_err_o (dbgmem_err), + .mem_en_o (DBGMEM_EN_o), + .mem_addr_o (DBGMEM_ADDR_o), + .mem_wdata_o (DBGMEM_WDATA_o), + .mem_we_o (DBGMEM_WE_o), + .mem_be_o (DBGMEM_BE_o), + .mem_rdata_i (DBGMEM_RDATA_i), + .mem_ready_i (DBGMEM_READY_i), + .mem_error_i (DBGMEM_ERROR_i) + ); + + slv_mem_mux u_irom_slv_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (irom_req), + .mstr_gnt_o (irom_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (irom_rdata), + .mstr_rvalid_o (irom_rvalid), + .mstr_err_o (irom_err), + .mem_en_o (IROM_EN_o), + .mem_addr_o (IROM_ADDR_o), + .mem_wdata_o (IROM_WDATA_o), + .mem_we_o (IROM_WE_o), + .mem_be_o (IROM_BE_o), + .mem_rdata_i (IROM_RDATA_i), + .mem_ready_i (IROM_READY_i), + .mem_error_i (IROM_ERROR_i) + ); + + slv_mem_mux u_iram_slv_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (iram_req), + .mstr_gnt_o (iram_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (iram_rdata), + .mstr_rvalid_o (iram_rvalid), + .mstr_err_o (iram_err), + .mem_en_o (IRAM_EN_o), + .mem_addr_o (IRAM_ADDR_o), + .mem_wdata_o (IRAM_WDATA_o), + .mem_we_o (IRAM_WE_o), + .mem_be_o (IRAM_BE_o), + .mem_rdata_i (IRAM_RDATA_i), + .mem_ready_i (IRAM_READY_i), + .mem_error_i (IRAM_ERROR_i) + ); + + slv_mem_mux u_dram_slv_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (dram_req), + .mstr_gnt_o (dram_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (dram_rdata), + .mstr_rvalid_o (dram_rvalid), + .mstr_err_o (dram_err), + .mem_en_o (DRAM_EN_o), + .mem_addr_o (DRAM_ADDR_o), + .mem_wdata_o (DRAM_WDATA_o), + .mem_we_o (DRAM_WE_o), + .mem_be_o (DRAM_BE_o), + .mem_rdata_i (DRAM_RDATA_i), + .mem_ready_i (DRAM_READY_i), + .mem_error_i (IRAM_ERROR_i) + ); + + // + // master interface comes from the cpu + // slave interface should be fed into cpu back as well + // + slv_mem_mux u_dma_slv_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (dma_conf_req), + .mstr_gnt_o (dma_conf_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (dma_conf_rdata), + .mstr_rvalid_o (dma_conf_rvalid), + .mstr_err_o (dma_conf_err), + .mem_en_o (dma_conf_en_o), + .mem_addr_o (dma_conf_addr_o), + .mem_wdata_o (dma_conf_wdata_o), + .mem_we_o (dma_conf_we_o), + .mem_be_o (dma_conf_be_o), + .mem_rdata_i (dma_conf_rdata_i), + .mem_ready_i (dma_conf_ready_i), + .mem_error_i (dma_conf_error_i) + ); + + slv_axi_mux u_slv_axi_mux ( + .clk_i (clk_i), + .rstn_i (rstn_i), + .mstr_req_i (axi_req), + .mstr_gnt_o (axi_gnt), + .mstr_addr_i (m2s_addr), + .mstr_be_i (m2s_be), + .mstr_wdata_i (m2s_wdata), + .mstr_we_i (m2s_we), + .mstr_rdata_o (axi_rdata), + .mstr_rvalid_o (axi_rvalid), + .mstr_err_o (axi_err), + .AWID_o (AWID_o ), + .AWADDR_o (AWADDR_o ), + .AWLEN_o (AWLEN_o ), + .AWSIZE_o (AWSIZE_o ), + .AWBURST_o (AWBURST_o ), + .AWLOCK_o (AWLOCK_o ), + .AWPROT_o (AWPROT_o ), + .AWCACHE_o (AWCACHE_o ), + .AWUSER_o (AWUSER_o ), + .AWVALID_o (AWVALID_o ), + .AWREADY_i (AWREADY_i ), + .WDATA_o (WDATA_o ), + .WSTRB_o (WSTRB_o ), + .WLAST_o (WLAST_o ), + .WVALID_o (WVALID_o ), + .WREADY_i (WREADY_i ), + .BID_i (BID_i ), + .BRESP_i (BRESP_i ), + .BVALID_i (BVALID_i ), + .BREADY_o (BREADY_o ), + .ARID_o (ARID_o ), + .ARADDR_o (ARADDR_o ), + .ARLEN_o (ARLEN_o ), + .ARSIZE_o (ARSIZE_o ), + .ARBURST_o (ARBURST_o ), + .ARLOCK_o (ARLOCK_o ), + .ARPROT_o (ARPROT_o ), + .ARCACHE_o (ARCACHE_o ), + .ARUSER_o (ARUSER_o ), + .ARVALID_o (ARVALID_o ), + .ARREADY_i (ARREADY_i ), + .RID_i (RID_i ), + .RDATA_i (RDATA_i ), + .RLAST_i (RLAST_i ), + .RRESP_i (RRESP_i ), + .RVALID_i (RVALID_i ), + .RREADY_o (RREADY_o ) + ); + +endmodule + diff --git a/vendor/lowrisc_ibex/dv/cheriot/fcov/core_ibex_fcov_if.sv b/vendor/lowrisc_ibex/dv/cheriot/fcov/core_ibex_fcov_if.sv index 77c673967..0f4fff01e 100644 --- a/vendor/lowrisc_ibex/dv/cheriot/fcov/core_ibex_fcov_if.sv +++ b/vendor/lowrisc_ibex/dv/cheriot/fcov/core_ibex_fcov_if.sv @@ -152,7 +152,7 @@ interface core_ibex_fcov_if import ibex_pkg::*; import cheri_pkg::*; import cher id_instr_category = InstrCategoryCheriSCR; cheri_ops[CSET_ADDR], cheri_ops[CINC_ADDR], cheri_ops[CINC_ADDR_IMM], cheri_ops[CAUICGP],cheri_ops[CAUIPCC]: id_instr_category = InstrCategoryCheriAddr; - cheri_ops[CSET_BOUNDS_IMM], cheri_ops[CSET_BOUNDS], cheri_ops[CSET_BOUNDS_EX], cheri_ops[CRRL], cheri_ops[CRAM]: + cheri_ops[CSET_BOUNDS_IMM], cheri_ops[CSET_BOUNDS], cheri_ops[CSET_BOUNDS_EX], cheri_ops[CSET_BOUNDS_RNDN],cheri_ops[CRRL], cheri_ops[CRAM]: id_instr_category = InstrCategoryCheriBounds; cheri_ops[CCLEAR_TAG], cheri_ops[CMOVE_CAP], cheri_ops[CSEAL], cheri_ops[CUNSEAL], cheri_ops[CAND_PERM], cheri_ops[CSUB_CAP], cheri_ops[CIS_SUBSET], cheri_ops[CIS_EQUAL], cheri_ops[CSET_HIGH]: @@ -859,14 +859,14 @@ interface core_ibex_fcov_if import ibex_pkg::*; import cheri_pkg::*; import cher cp_cs1_sealed: coverpoint ((g_cheri_ex.u_cheri_ex.rf_fullcap_a.otype != 0) & (g_cheri_ex.u_cheri_ex.rf_fullcap_a.valid)); - cp_cs1_cor: coverpoint {g_cheri_ex.u_cheri_ex.rf_fullcap_a.base_cor, + cp_cs1_cor: coverpoint {g_cheri_ex.u_cheri_ex.rf_fullcap_a.base_cor, g_cheri_ex.u_cheri_ex.rf_fullcap_a.top_cor} { - bins bin0 = {4'b0000}; - bins bin1 = {4'b0001}; - // bins bin2 = {4'b0011}; // base_cor = 0, top_cor = -1, impossible case - bins bin3 = {4'b1100}; - // bins bin4 = {4'b1101}; // impossible case - bins bin5 = {4'b1111}; + bins bin0 = {3'b000}; + bins bin1 = {3'b001}; + // bins bin2 = {3'b011}; // base_cor = 0, top_cor = -1, impossible case + bins bin3 = {3'b100}; + // bins bin4 = {3'b101}; // impossible case + bins bin5 = {3'b111}; } cp_cs1_top: coverpoint g_cheri_ex.u_cheri_ex.rf_fullcap_a.top { @@ -999,14 +999,14 @@ interface core_ibex_fcov_if import ibex_pkg::*; import cheri_pkg::*; import cher cp_cs2_sealed: coverpoint ((g_cheri_ex.u_cheri_ex.rf_fullcap_b.otype != 0) & (g_cheri_ex.u_cheri_ex.rf_fullcap_b.valid)); - cp_cs2_cor: coverpoint {g_cheri_ex.u_cheri_ex.rf_fullcap_b.base_cor, + cp_cs2_cor: coverpoint {g_cheri_ex.u_cheri_ex.rf_fullcap_b.base_cor, g_cheri_ex.u_cheri_ex.rf_fullcap_b.top_cor} { - bins bin0 = {4'b0000}; - bins bin1 = {4'b0001}; - // bins bin2 = {4'b0011}; // base_cor = 0, top_cor = -1, impossible case - bins bin3 = {4'b1100}; - // bins bin4 = {4'b1101}; // impossible case - bins bin5 = {4'b1111}; + bins bin0 = {3'b000}; + bins bin1 = {3'b001}; + // bins bin2 = {3'b011}; // base_cor = 0, top_cor = -1, impossible case + bins bin3 = {3'b100}; + // bins bin4 = {3'b101}; // impossible case + bins bin5 = {3'b111}; } cp_cs2_top: coverpoint g_cheri_ex.u_cheri_ex.rf_fullcap_b.top { @@ -1080,14 +1080,14 @@ interface core_ibex_fcov_if import ibex_pkg::*; import cheri_pkg::*; import cher bins bin[] = {[0:7]}; // including reserved values for coverage } - cp_cd_cor: coverpoint {g_cheri_ex.u_cheri_ex.result_cap_o.base_cor, + cp_cd_cor: coverpoint {g_cheri_ex.u_cheri_ex.result_cap_o.base_cor, g_cheri_ex.u_cheri_ex.result_cap_o.top_cor} { - bins bin0 = {4'b0000}; - bins bin1 = {4'b0001}; - // bins bin2 = {4'b0011}; - bins bin3 = {4'b1100}; - // bins bin4 = {4'b1101}; - bins bin5 = {4'b1111}; + bins bin0 = {3'b000}; + bins bin1 = {3'b001}; + // bins bin2 = {3'b011}; + bins bin3 = {3'b100}; + // bins bin4 = {3'b101}; + bins bin5 = {3'b111}; } cp_cd_top: coverpoint g_cheri_ex.u_cheri_ex.result_cap_o.top { @@ -1253,15 +1253,15 @@ interface core_ibex_fcov_if import ibex_pkg::*; import cheri_pkg::*; import cher bins bin2 = {24}; } - cp_clc_mem_cap_cor: coverpoint {load_store_unit_i.lsu_dv_ext_i.fcov_clc_mem_cap.top_cor, - load_store_unit_i.lsu_dv_ext_i.fcov_clc_mem_cap.base_cor} iff + cp_clc_mem_cap_cor: coverpoint {load_store_unit_i.lsu_dv_ext_i.fcov_clc_mem_cap.base_cor, + load_store_unit_i.lsu_dv_ext_i.fcov_clc_mem_cap.top_cor} iff (~load_store_unit_i.data_we_q & load_store_unit_i.lsu_resp_valid_o) { - bins bin0 = {4'b0000}; - bins bin1 = {4'b0001}; - // bins bin2 = {4'b0011}; // base_cor = 0, top_cor = -1, impossible case - bins bin3 = {4'b1100}; - // bins bin4 = {4'b1101}; // impossible case - bins bin5 = {4'b1111}; + bins bin0 = {3'b000}; + bins bin1 = {3'b001}; + // bins bin2 = {3'b011}; // base_cor = 0, top_cor = -1, impossible case + bins bin3 = {3'b100}; + // bins bin4 = {3'b101}; // impossible case + bins bin5 = {3'b111}; } cp_cheri_fetch_tag_vio: coverpoint id_stage_i.instr_fetch_cheri_acc_vio_i iff diff --git a/vendor/lowrisc_ibex/dv/cheriot/scripts/compare_trace.py b/vendor/lowrisc_ibex/dv/cheriot/scripts/compare_trace.py index c9a11157b..67635bdc2 100755 --- a/vendor/lowrisc_ibex/dv/cheriot/scripts/compare_trace.py +++ b/vendor/lowrisc_ibex/dv/cheriot/scripts/compare_trace.py @@ -125,7 +125,7 @@ def parse_ibex_cap(cap_val, addr_val): top_cor = -1; if addrmi9 < base9 : - base_cor = -1; + base_cor = 1; else : base_cor = 0; @@ -134,7 +134,7 @@ def parse_ibex_cap(cap_val, addr_val): base = (base9 << exp); else: top = (top9 << exp) + (((addr_val >> (exp+9)) + top_cor) << (exp+9)); - base = (base9 << exp) + (((addr_val >> (exp+9)) + base_cor) << (exp+9)); + base = (base9 << exp) + (((addr_val >> (exp+9)) - base_cor) << (exp+9)); top &= 0x1ffffffff # convert to unsigned base &= 0xffffffff diff --git a/vendor/lowrisc_ibex/dv/cheriot/tb/cheriot_dv_pkg.sv b/vendor/lowrisc_ibex/dv/cheriot/tb/cheriot_dv_pkg.sv index b724f7f66..af76591bd 100644 --- a/vendor/lowrisc_ibex/dv/cheriot/tb/cheriot_dv_pkg.sv +++ b/vendor/lowrisc_ibex/dv/cheriot/tb/cheriot_dv_pkg.sv @@ -118,7 +118,7 @@ package cheriot_dv_pkg; full_cap_t result_cap; logic [EXP_W-1:0] tmp5; - logic [3:0] tmp4; + logic [2:0] tmp3; logic [CPERMS_W-1:0] cperms_mem; logic [BOT_W-1:0] addrmi9; logic valid_in; @@ -137,9 +137,9 @@ package cheriot_dv_pkg; cperms_mem = msw[CPERMS_LO+:CPERMS_W]; regcap.cperms = cperms_mem; addrmi9 = BOT_W'({1'b0, addr33[31:0]} >> regcap.exp); // ignore the tag valid bit - tmp4 = update_temp_fields(regcap.top, regcap.base, addrmi9); - regcap.top_cor = tmp4[3:2]; - regcap.base_cor = tmp4[1:0]; + tmp3 = update_temp_fields(regcap.top, regcap.base, addrmi9); + regcap.top_cor = tmp3[2:1]; + regcap.base_cor = tmp3[0]; regcap.rsvd = msw[RSVD_LO]; diff --git a/vendor/lowrisc_ibex/dv/formal/.gitignore b/vendor/lowrisc_ibex/dv/formal/.gitignore new file mode 100644 index 000000000..d8c5ed240 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/.gitignore @@ -0,0 +1,3 @@ +jgproject +jgproofs +build diff --git a/vendor/lowrisc_ibex/dv/formal/Makefile b/vendor/lowrisc_ibex/dv/formal/Makefile new file mode 100644 index 000000000..cd7ab2eae --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/Makefile @@ -0,0 +1,90 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +.DEFAULT_GOAL := all + +IBEX_ROOT=../.. + +SAIL=sail + +SAIL_RISCV_MODEL_DIR=${LOWRISC_CHERIOT_SAIL_SRC}/sail-riscv/model +CHERI=../../src + +include Sources.mk + +PSGEN_SRCS=thm/btype.proof thm/ibex.proof thm/mem.proof thm/riscv.proof thm/dti.proof +PSGEN_FLAGS=-root riscv -task + +SAIL_EXTRA_SRCS=../spec/main.sail + +SAIL_UNREACHABLE=translate lookup_TLB translate_tlb_miss translate_tlb_hit pt_walk +SAIL_UNREACHABLE+=pmpReadCfgReg pmpReadAddrReg pmpWriteCfg pmpWriteCfgReg pmpWriteAddr pmpWriteAddrReg mseccfgWrite +SAIL_UNREACHABLE+=pmpAddrRange pmpCheckRWX pmpCheckPerms pmpMatchAddr pmpMatchEntry accessToFault + +SAIL_EXTRACTED=encCapabilityToCapability capToEncCap bit_to_bool bool_to_bit to_bits zero_extend capBitsToCapability capBitsToEncCapability +SAIL_CULL=count_trailing_zeros + +SAIL_SV_FLAGS=-sv -sv-comb -sv-inregs -sv-outregs -sv-nostrings -sv-nopacked -sv-nomem -Oconstant_fold -memo-z3 \ + $(addprefix -sv-unreachable ,$(SAIL_UNREACHABLE)) \ + -sv-fun2wires 2:read_ram \ + -sv-fun2wires 2:write_ram \ + -sv-fun2wires wX \ + -sv-fun2wires wC \ + -sv-fun2wires __WriteRAM_Meta \ + -sv-fun2wires __ReadRAM_Meta \ + -sv-fun2wires mem_read_cap_revoked + +# Use fusesoc to resolve the tree of components, copy all resolved source files into the build/ directory, +# and then generate a filelist for jasper to ingest. +# Finally, apply a number of small RTL patches necessary to make the formal flow work. (see files in patches/) +# (Only patch the duplicated source files that fusesoc has copied into build/fusesoc/src, not the version-controlled originals) +# - Note. we use the 'vcs' fusesoc backend flow to generate the filelist. This is because fusesoc does not currently implement a +# JasperGold backend, but this is not an issue as the file-format generated by the vcs flow is compatible with jasper. +.PHONY: fusesoc +fusesoc: + mkdir -p build/fusesoc + fusesoc \ + --cores-root $(IBEX_ROOT) \ + run \ + --build-root build/fusesoc \ + --tool vcs \ + --setup \ + lowrisc:ibex:ibex_formal:0.1 + patch -p0 < patches/ibex_top.diff + +.PHONY: sv +sv: + mkdir -p build + cd build && $(SAIL) $(SAIL_SRCS) $(SAIL_EXTRA_SRCS) $(SAIL_SV_FLAGS) $(addprefix -sv_unreachable execute_,$(COMPRESSED_INSTRS)) -o ibexspec + python3 spec/fix_pmp_bug.py + python3 spec/unreachable_loc_info.py + python3 spec/extract_funcs.py $(SAIL_EXTRACTED) > build/extracted.sv + python3 spec/cull_funcs.py $(SAIL_CULL) + +.PHONY: extract +extract: + python3 spec/extract_funcs.py $(SAIL_EXTRACTED) > build/extracted.sv + +.PHONY: psgen +psgen: + mkdir -p build + psgen $(addprefix -path ,$(PSGEN_SRCS)) $(PSGEN_FLAGS) -sv-out build/psgen.sv -tcl-out build/psgen.tcl +.PHONY: jg +jg: fusesoc psgen sv + jg verify.tcl -allow_unsupported_OS -acquire_proj + +# The following default target is intended for regressions / unattended runs. +.PHONY: all +all: fusesoc psgen sv + jg automated.tcl -allow_unsupported_OS -acquire_proj -no_gui + +################################################################################ + +.PHONY: clean +clean: + rm -rf build/ + rm -rf jgproject/ + rm -rf jgproofs/ diff --git a/vendor/lowrisc_ibex/dv/formal/README.md b/vendor/lowrisc_ibex/dv/formal/README.md new file mode 100644 index 000000000..98c157826 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/README.md @@ -0,0 +1,44 @@ +# End to End Formal Verification against the Sail + +This is very much a WIP. It is however mostly just a CHERI version of the almost exactly identical work for Ibex. +All properties are believed to be conclusive, including wrap around. There is currently no liveness. + +Prerequisities (in your PATH): +- [The lowRISC fork of the Sail compiler](https://github.com/lowRISC/sail/tree/lowrisc) +- [psgen](https://github.com/mndstrmr/psgen) +- Nix (`https://zero-to-nix.com/start/install`) +- JasperGold + +Build instructions: +- `git submodule init` +- `make psgen` to build the SV for the proofs given in `thm/` +- `make sv` to build the SV translation of the Sail compiler. Will invoke `buildspec.py`, which can be configured to adjust which instructions are defined. By default all of them are, this is correct but slow. +- Make the changes to Ibex described in the RTL changes. +- `SAIL_DIR= jg verify.tcl` + +Nix build instructions: +- Clone this repository +- `cd dv/formal` +- `nix develop .#formal` +- `make` invokes JasperGold in batch-mode, and attempts to prove everything, which is meant for regressions. +- `make jg` invokes JasperGold interactively, halting after sourcing the contents of `verify.tcl`. + +You can see the different steps of the proof in the `Task Tree` tab. +Then, you can prove each step in order by right clicking on them and clicking `Prove Task`. +Some tasks may take longer than others and you can select specific properties in the `Property Table` and prove them individually by right clicking and selecting `Prove Property`. +Some steps require a lot of RAM and CPU so we recommend closing any other resource-heavy programs running on your computer. +We've had the proof complete using a machine with 128 GiB of RAM and 32 cores. +To avoid manually running each step you can also use the `prove_no_liveness` command inside the TCL command interface located below your session window. + + +## RTL Changes +- `ResetAll = 1` is required for now (instead of `ResetAll = Lockstep`) +- Disable clock gating + +## Exact Checks +This proves trace equivalence with the Sail as per `cheriot-sail`, note that this is a fork of the original CherIoT-Sail. +This work is very similar to that of Ibex, with the only difference being the inclusion of CHERI instructions. See the Ibex repo for a list of caveats. + +Note that in addition to what is listed in the Ibex repo, the following is not covered: +- Stack zeroing (including MSHWM and MSHWMB) +- Reservation/Revocation (see `check/top.sv` for the exact configuration) diff --git a/vendor/lowrisc_ibex/dv/formal/Sources.mk b/vendor/lowrisc_ibex/dv/formal/Sources.mk new file mode 100644 index 000000000..4e3ef7078 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/Sources.mk @@ -0,0 +1,43 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +SAIL_XLEN := riscv_xlen32.sail + +SAIL_CHECK_SRCS = riscv_addr_checks_common.sail $(CHERI)/cheri_addr_checks.sail $(CHERI)/cheri_misa_ext.sail +SAIL_DEFAULT_INST = riscv_insts_base.sail riscv_insts_cext.sail riscv_insts_mext.sail riscv_insts_zicsr.sail +SAIL_CHERI_INSTS = $(CHERI)/cheri_insts_begin.sail $(CHERI)/cheri_insts.sail $(CHERI)/cheri_insts_cext.sail $(CHERI)/cheri_insts_end.sail + +SAIL_SEQ_INST = $(SAIL_DEFAULT_INST) $(SAIL_CHERI_INSTS) riscv_jalr_seq.sail + +SAIL_SEQ_INST_SRCS = riscv_insts_begin.sail $(SAIL_SEQ_INST) riscv_insts_end.sail $(CHERI)/cheri_decode_ext.sail + +SAIL_SYS_SRCS = riscv_csr_map.sail +SAIL_SYS_SRCS += $(CHERI)/cheri_sys_exceptions.sail +SAIL_SYS_SRCS += riscv_sync_exception.sail riscv_csr_ext.sail riscv_sys_control.sail +SAIL_SYS_SRCS += $(SAIL_CHECK_SRCS) + +PRELUDE = prelude.sail $(SAIL_XLEN) $(CHERI)/cheri_prelude.sail $(CHERI)/cheri_types.sail $(CHERI)/cheri_cap_common.sail $(CHERI)/cheri_mem_metadata.sail prelude_mem.sail + +# SAIL_REGS_SRCS = riscv_reg_type.sail riscv_regs.sail riscv_pc_access.sail riscv_sys_regs.sail +SAIL_REGS_SRCS = $(CHERI)/cheri_reg_type.sail +SAIL_REGS_SRCS += riscv_csr_map.sail $(CHERI)/cheri_scr_map.sail +SAIL_REGS_SRCS += $(CHERI)/cheri_vmem_types.sail +SAIL_REGS_SRCS += riscv_regs.sail riscv_sys_regs.sail +SAIL_REGS_SRCS += riscv_pmp_regs.sail riscv_pmp_control.sail +SAIL_REGS_SRCS += $(CHERI)/cheri_sys_regs.sail $(CHERI)/cheri_regs.sail +SAIL_REGS_SRCS += $(CHERI)/cheri_pc_access.sail + +SAIL_ARCH_SRCS = $(PRELUDE) +SAIL_ARCH_SRCS += riscv_types_common.sail $(CHERI)/cheri_riscv_types.sail riscv_types.sail +SAIL_ARCH_SRCS += $(SAIL_REGS_SRCS) $(SAIL_SYS_SRCS) riscv_platform.sail +SAIL_ARCH_SRCS += riscv_mem.sail $(CHERI)/cheri_mem.sail + +SAIL_SRCS = $(addprefix $(SAIL_RISCV_MODEL_DIR)/,$(SAIL_ARCH_SRCS) $(SAIL_SEQ_INST_SRCS)) + +COMPRESSED_INSTRS=C_J C_JALR C_LW C_ADDIW C_LI C_ANDI C_BEQZ C_LD C_ILLEGAL C_AND C_JAL C_MV C_XOR \ + C_CSC C_CIncAddr16CSP C_ADD C_CSCSP C_EBREAK C_CLC C_SDSP C_ADDI4SPN C_CJR C_SW C_SUB \ + C_SWSP C_SRLI C_LDSP C_SD C_SRAI C_LUI C_OR C_SUBW C_CIncAddr4CSPN C_JR C_CJALR C_ADDI \ + C_ADDW C_BNEZ C_ADDI16SP C_NOP C_CJAL C_SLLI C_CLCSP diff --git a/vendor/lowrisc_ibex/dv/formal/automated.tcl b/vendor/lowrisc_ibex/dv/formal/automated.tcl new file mode 100644 index 000000000..b54a2897d --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/automated.tcl @@ -0,0 +1,40 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# The underlying commands and reports of this script are copyrighted by Cadence. +# We thank Cadence for granting permission to share our research to help +# promote and foster the next generation of innovators. +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +source verify.tcl + +prove_no_liveness + +report -task Step0 +report -task Step1 +report -task Step2 +report -task Step3 +report -task Step4 +report -task Step5 +report -task Step6 +report -task Step7 +report -task Step8 +report -task Step9 +report -task Step10 +report -task Step11 +report -task Step12 +report -task Step13 +report -task Step14 +report -task Step15 +report -task Step16 +report -task Step17 +report -task Step18 +report -task Step19 +report -task Step20 +report -task Step21 +report -task Step22 +report -task Step23 +report -task Step24 +report -task Step25 +report -task Step26 diff --git a/vendor/lowrisc_ibex/dv/formal/check/encodings.sv b/vendor/lowrisc_ibex/dv/formal/check/encodings.sv new file mode 100644 index 000000000..c5836fc91 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/encodings.sv @@ -0,0 +1,152 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +`ifndef CMP_INSNS +`define CMP_INSNS + +`define IS_ITYPE(idx) (`INSTR[6:0] == 7'b0010011 && `INSTR[14:12] == idx) +`define IS_ADDI `IS_ITYPE(3'b000) +`define IS_SLTI `IS_ITYPE(3'b010) +`define IS_SLTIU `IS_ITYPE(3'b011) +`define IS_XORI `IS_ITYPE(3'b100) +`define IS_ORI `IS_ITYPE(3'b110) +`define IS_ANDI `IS_ITYPE(3'b111) +`define IS_ANY_ITYPE ( \ + `IS_ADDI | `IS_SLTI | `IS_SLTIU | `IS_XORI | \ + `IS_ORI | `IS_ANDI \ +) + +`define IS_SLLI (`IS_ITYPE(3'b001) && `INSTR[31:25] == 7'b0000000) +`define IS_SRLI (`IS_ITYPE(3'b101) && `INSTR[31:25] == 7'b0000000) +`define IS_SRAI (`IS_ITYPE(3'b101) && `INSTR[31:25] == 7'b0100000) + +`define IS_SHIFTIOP (`IS_SLLI | `IS_SRLI | `IS_SRAI) + +`define IS_RTYPE_0(idx) \ + (`INSTR[6:0] == 7'b0110011 && `INSTR[31:25] == 7'b0000000 && `INSTR[14:12] == idx) +`define IS_RTYPE_1(idx) \ + (`INSTR[6:0] == 7'b0110011 && `INSTR[31:25] == 7'b0100000 && `INSTR[14:12] == idx) +`define IS_ADD `IS_RTYPE_0(3'b000) +`define IS_SUB `IS_RTYPE_1(3'b000) +`define IS_SLL `IS_RTYPE_0(3'b001) +`define IS_SLT `IS_RTYPE_0(3'b010) +`define IS_SLTU `IS_RTYPE_0(3'b011) +`define IS_XOR `IS_RTYPE_0(3'b100) +`define IS_SRL `IS_RTYPE_0(3'b101) +`define IS_SRA `IS_RTYPE_1(3'b101) +`define IS_OR `IS_RTYPE_0(3'b110) +`define IS_AND `IS_RTYPE_0(3'b111) + +`define IS_FENCETYPE(idx) ( \ + `INSTR[31:25] == 4'b0000 && `INSTR[19:15] == 5'b00000 && \ + `INSTR[11:0] == 12'b000000001111 && `INSTR[14:12] == idx) +`define IS_FENCE (`INSTR[31:28] == 4'b0 && `INSTR[19:0] == 20'b0001111) +`define IS_FENCEI (`INSTR == 32'h100f) + +`define IS_LOAD(idx) (`INSTR[6:0] == 7'b0000011 && `INSTR[14:12] == idx) +`define IS_LB `IS_LOAD(3'b000) +`define IS_LH `IS_LOAD(3'b001) +`define IS_LW `IS_LOAD(3'b010) +`define IS_LBU `IS_LOAD(3'b100) +`define IS_LHU `IS_LOAD(3'b101) +`define IS_LOADCAPIMM `IS_LOAD(3'b011) + +`define IS_STORE(idx) (`INSTR[6:0] == 7'b0100011 && `INSTR[14:12] == idx) +`define IS_SB `IS_STORE(3'b000) +`define IS_SH `IS_STORE(3'b001) +`define IS_SW `IS_STORE(3'b010) +`define IS_STORECAPIMM `IS_STORE(3'b011) + +`define IS_JAL (`INSTR[6:0] == 7'h6f) +`define IS_JALR (`INSTR[6:0] == 7'h67 && `INSTR[14:12] == 3'b0) + +`define IS_MTYPE(idx) \ + (`INSTR[6:0] == 7'b0110011 && `INSTR[31:25] == 7'b0000001 && `INSTR[14:12] == idx) +`define IS_MUL `IS_MTYPE(3'b000) +`define IS_MULH `IS_MTYPE(3'b001) +`define IS_MULHSH `IS_MTYPE(3'b010) +`define IS_MULHU `IS_MTYPE(3'b011) +`define IS_DIV `IS_MTYPE(3'b100) +`define IS_DIVU `IS_MTYPE(3'b101) +`define IS_REM `IS_MTYPE(3'b110) +`define IS_REMU `IS_MTYPE(3'b111) + +`define IS_CSR (`INSTR[6:0] == 7'b1110011 && (|`INSTR[13:12])) +`define CSR_ADDR (`INSTR[31:20]) + +`define IS_ECALL (`INSTR == 32'b00000000000000000000000001110011) +`define IS_EBREAK (`INSTR == 32'b00000000000100000000000001110011) +`define IS_LUI (`INSTR[6:0] == 7'b0110111) +`define IS_BTYPE (`INSTR[6:0] == 7'b1100011 && (`INSTR[13] -> `INSTR[14])) +`define IS_MRET (`INSTR == 32'b00110000001000000000000001110011) +`define IS_WFI (`INSTR == 32'b00010000010100000000000001110011) + +`define IS_CHERI_1(x) \ + (`INSTR[6:0] == 7'h5b && `INSTR[31:25] == 7'h7f && `INSTR[24:20] == x && `INSTR[14:12] == 3'h0) +`define IS_CHERI_2(x) (`INSTR[6:0] == 7'h5b && `INSTR[31:25] == x && `INSTR[14:12] == 3'h0) +`define IS_CHERI_3(x) (`INSTR[6:0] == 7'h5b && `INSTR[14:12] == x) +`define IS_CHERI_4(x) (`INSTR[6:0] == x) + +`define IS_CGETPERM `IS_CHERI_1(5'h0) +`define IS_CGETTYPE `IS_CHERI_1(5'h1) +`define IS_CGETBASE `IS_CHERI_1(5'h2) +`define IS_CGETLEN `IS_CHERI_1(5'h3) +`define IS_CGETTAG `IS_CHERI_1(5'h4) +`define IS_CGETADDR `IS_CHERI_1(5'hf) +`define IS_CGETTOP `IS_CHERI_1(5'h18) + +`define IS_CGET ( \ + `IS_CGETPERM | `IS_CGETTYPE | `IS_CGETBASE | `IS_CGETLEN | \ + `IS_CGETTAG | `IS_CGETADDR | `IS_CGETTOP \ +) + +`define IS_CSEAL `IS_CHERI_2(5'hb) +`define IS_CUNSEAL `IS_CHERI_2(5'hc) +`define IS_CANDPERM `IS_CHERI_2(5'hd) + +`define IS_CSEAL_ANDPERM (`IS_CSEAL | `IS_CUNSEAL | `IS_CANDPERM) + +`define IS_CSETADDR `IS_CHERI_2(5'h10) +`define IS_CINCADDR `IS_CHERI_2(5'h11) +`define IS_CINCADDRIMM `IS_CHERI_3(3'b001) + +`define IS_CSETADDRx (`IS_CSETADDR | `IS_CINCADDR | `IS_CINCADDRIMM) + +`define IS_CSETBOUNDS `IS_CHERI_2(5'h8) +`define IS_CSETBOUNDSEXACT `IS_CHERI_2(5'h9) +`define IS_CSETBOUNDSIMM `IS_CHERI_3(3'b010) +`define IS_CSETBOUNDSRNDN `IS_CHERI_2(5'b01010) +`define IS_CRRL `IS_CHERI_1(5'h8) +`define IS_CRAM `IS_CHERI_1(5'h9) + +`define IS_CSETBOUNDSx ( \ + `IS_CSETBOUNDS | `IS_CSETBOUNDSEXACT | `IS_CSETBOUNDSIMM | `IS_CSETBOUNDSRNDN | \ + `IS_CRRL | `IS_CRAM \ +) + +`define IS_CCLEARTAG `IS_CHERI_1(5'hb) +`define IS_CSUB `IS_CHERI_2(7'h14) +`define IS_CMOVE `IS_CHERI_1(5'ha) +`define IS_CCLRSUBMOV (`IS_CCLEARTAG | `IS_CSUB | `IS_CMOVE) + +`define IS_AUIPCC `IS_CHERI_4(7'h17) +`define IS_AUICGP `IS_CHERI_4(7'h7b) +`define IS_AUIC (`IS_AUIPCC | `IS_AUICGP) + +`define IS_CTESTSUBSET `IS_CHERI_2(7'h20) +`define IS_CSEQX `IS_CHERI_2(7'h21) +`define IS_CCMP (`IS_CTESTSUBSET | `IS_CSEQX) + +`define IS_CGETHIGH `IS_CHERI_1(5'h17) +`define IS_CSETHIGH `IS_CHERI_2(5'h16) +`define IS_CHIGH (`IS_CGETHIGH | `IS_CSETHIGH) + +`define IS_CSPECIALRW `IS_CHERI_2(7'h1) + +`define IS_CJAL (`INSTR[6:0] == 7'h6f) +`define IS_CJALR (`INSTR[6:0] == 7'h67 && `INSTR[14:12] == 3'b0) + +`endif diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/abs.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/abs.sv new file mode 100644 index 000000000..e729c94a9 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/abs.sv @@ -0,0 +1,145 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +This file implements the abstract state for Ibex, it maps Ibex types to Sail types. +pre_* is the pre_state, i.e. if an instruction is starting to run now, this is the architectural state that it observes. +post_* is the post_state, i.e. if an instruction starts in the next cycle, this is the architectural state that it will observe. +*/ + +/////////////// GPR Pre-State /////////////// + +t_Capability fwd_data; +assign fwd_data = regcap2sail(`CR.rf_wcap_fwd_wb, `CR.rf_wdata_fwd_wb); + + +for (genvar i = 0; i < 32; i++) begin: g_pre_regs + t_Capability rf_data; + assign rf_data = + revoke( + regcap2sail(`RF.rf_cap[i], `RF.rf_reg[i]), + (0 < i && i < 16 ? `RF.trvk_dec[i] : 1'b0) & `RF.trvk_en_i & `RF.trvk_clrtag_i + ); + assign pre_regs[i] = `CR.rf_write_wb && `CR.rf_waddr_wb == i && i > '0 ? fwd_data : rf_data; +end + +// FIXME: Redefined from ibex_cs_registers +typedef struct packed { + logic mie; + logic mpie; + priv_lvl_e mpp; + logic mprv; + logic tw; +} status_t; + +/////////////// CSR Pre-State /////////////// + +assign pre_pc = wbexc_handling_irq? `CR.pc_if:`CR.pc_id; +assign pre_nextpc = `CR.pc_id + (`CR.instr_is_compressed_id ? 2 : 4); +assign pre_priv = `CSR.priv_lvl_q == PRIV_LVL_M ? Machine : User; +assign pre_mstatus = '{ + mie: `CSR.mstatus_q.mie, + mpie: `CSR.mstatus_q.mpie, + tw: `CSR.mstatus_q.tw, + mprv: `CSR.mstatus_q.mprv, + mpp: `CSR.mstatus_q.mpp +}; +assign pre_mip = irqsToMInterrupts(`CSR.mip); +assign pre_nmi = irq_nm_i; +assign pre_nmi_mode = `IDC.nmi_mode_q; +assign pre_mie = irqsToMInterrupts(`CSR.mie_q); +assign pre_mcause = widenMCause(`CSR.mcause_q); +assign pre_mtval = `CSR.mtval_q; +assign pre_mscratch = `CSR.mscratch_q; +assign pre_mcounteren = '0; // ibex hardwires to zero +assign pre_mtvec = regcap2sail(`CSR.mtvec_cap, `CSR.mtvec_q); +assign pre_mepc = regcap2sail(`CSR.mepc_cap, `CSR.mepc_q); +assign pre_mtdc = regcap2sail(`CSRG.mtdc_cap, `CSRG.mtdc_data); +assign pre_mscratchc = regcap2sail(`CSRG.mscratchc_cap, `CSRG.mscratchc_data); +assign pre_pcc = pcc2sail(`CR.pcc_cap_r, pcc_address_q); +assign pre_mstack = '{ + mpie: `CSR.mstack_q.mpie, + mpp: `CSR.mstack_q.mpp, + mie: '0, + tw: '0, + mprv: '0 +}; +assign pre_mstack_cause = widenMCause(`CSR.mstack_cause_q); +assign pre_mstack_epc = `CSR.mstack_epc_q; +// assign pre_mshwm = `CSR.mshwm_q; +// assign pre_mshwmb = `CSR.mshwmb_q; + +/////////////// CSR Post-State /////////////// + +reg_cap_t mepc_cap_next; +always_comb begin + if (`CSR.csr_save_cause_i) + mepc_cap_next <= `CSRG.pcc_exc_cap; + else if (cheri_pmode_i & `CSR.mepc_en) + mepc_cap_next <= NULL_REG_CAP; + else if (`CSR.mepc_en_cheri) + mepc_cap_next <= `CSR.cheri_csr_wcap_i; + else + mepc_cap_next <= `CSR.mepc_cap; +end + +t_Capability csr_incoming_cap; +assign csr_incoming_cap = regcap2sail(`CSR.cheri_csr_wcap_i, `CSR.cheri_csr_wdata_i); + +// Bit 0 of fetch addr n is always cleared. +assign post_pc = `IF.branch_req ? {`IF.fetch_addr_n[31:1], 1'b0} : `CSR.pc_if_i; +assign post_nmi_mode = `IDC.nmi_mode_d; +assign post_mie = `CSR.mie_en ? irqsToMInterrupts(`CSR.mie_d) : pre_mie; +assign post_priv = `CSR.priv_lvl_d == PRIV_LVL_M ? Machine : User; +assign post_mstatus = `CSR.mstatus_en_combi ? '{ + mie: `CSR.mstatus_d_combi.mie, + mpie: `CSR.mstatus_d_combi.mpie, + tw: `CSR.mstatus_d_combi.tw, + mprv: `CSR.mstatus_d_combi.mprv, + mpp: `CSR.mstatus_d_combi.mpp +}:pre_mstatus; +assign post_mcause = `CSR.mcause_en ? widenMCause(`CSR.mcause_d) : pre_mcause; +assign post_mtval = `CSR.mtval_en ? `CSR.mtval_d : pre_mtval; +assign post_mscratch = `CSR.mscratch_en ? `CSR.csr_wdata_int : pre_mscratch; +assign post_mcounteren = '0; +assign post_mtvec = `CSR.mtvec_en_combi ? + regcap2sail(`CSR.mtvec_en_cheri ? `CSR.cheri_csr_wcap_i : `CSR.mtvec_cap, `CSR.mtvec_d_combi): + pre_mtvec; +assign post_mepc = `CSR.mepc_en_combi ? regcap2sail(mepc_cap_next, `CSR.mepc_d_combi) : pre_mepc; +assign post_mtdc = `CSRG.mtdc_en_cheri ? csr_incoming_cap : pre_mtdc; +assign post_mscratchc = `CSRG.mscratchc_en_cheri ? csr_incoming_cap : pre_mscratchc; +assign post_pcc = pcc2sail(`CSR.pcc_cap_d, pcc_address_d); +assign post_mstack = `CSR.mstack_en ? '{ + mpie: `CSR.mstack_d.mpie, + mpp: `CSR.mstack_d.mpp, + mie: '0, + tw: '0, + mprv: '0 +} : pre_mstack; +assign post_mstack_cause = `CSR.mstack_en ? widenMCause(`CSR.mstack_cause_d) : pre_mstack_cause; +assign post_mstack_epc = `CSR.mstack_en ? `CSR.mstack_epc_d : pre_mstack_epc; +// assign post_mshwm = `CSR.mshwm_en_combi ? `CSR.mshwm_d : pre_mshwm; +// assign post_mshwmb = `CSR.mshwmb_en ? {`CSR.csr_wdata_int[31:4], 4'h0} : pre_mshwmb; + +assign post_trvk_regs[0] = nullCap(); +for (genvar i = 1; i < 16; i++) begin: g_post_trvk_regs + assign post_trvk_regs[i] = + revoke(regcap2sail(`RF.rf_cap[i], `RF.rf_reg[i]), `RF.trvk_dec[i] & `RF.trvk_en_i & `RF.trvk_clrtag_i); +end + +/////////////// Encoders /////////////// + +function automatic logic [31:0] irqsToMInterrupts(irqs_t irqs); + return + (32'(irqs.irq_software) << 3) | + (32'(irqs.irq_timer) << 7) | + (32'(irqs.irq_external) << 11) | + (32'(irqs.irq_fast) << 16); +endfunction + +function automatic logic[31:0] widenMCause(logic [5:0] mcause); + return {mcause[5], 26'b0, mcause[4:0]}; +endfunction diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/alt_lsu.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/alt_lsu.sv new file mode 100644 index 000000000..6de381717 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/alt_lsu.sv @@ -0,0 +1,187 @@ +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Copyright lowRISC contributors. +// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// SPDX-License-Identifier: Apache-2.0 + + +/** + * Load Store Unit + * + * Load Store Unit, used to eliminate multiple access during processor stalls, + * and to align bytes and halfwords. + */ + +`include "prim_assert.sv" +`include "dv_fcov_macros.svh" + +module alt_lsu import ibex_pkg::*; import cheri_pkg::*; #( + parameter bit CHERIoTEn = 1'b1, + parameter bit MemCapFmt = 1'b0, + parameter bit CheriTBRE = 1'b0 +)( + input logic cheri_pmode_i, + + // data interface + input logic data_rvalid_i, + input logic data_err_i, + input logic [32:0] data_rdata_i, // kliu + + output reg_cap_t lsu_rcap_o, // kliu + output logic [32:0] lsu_rdata_o, // requested data -> to ID/EX + + // exception signals + input logic [31:8] rdata_q, + input logic [1:0] rdata_offset_q, + input logic [1:0] data_type_q, + input logic data_sign_ext_q, + input logic data_we_q, + input logic pmp_err_q, + input logic lsu_err_q, + input logic outstanding_resp_q, + input logic resp_is_cap_q, + input logic cheri_err_q, + input logic [3:0] resp_lc_clrperm_q, + input cap_rx_fsm_t cap_rx_fsm_q, + input logic cap_lsw_err_q, + input logic [32:0] cap_lsw_q +); + logic [32:0] data_rdata_ext; + + logic [32:0] rdata_w_ext; // word realignment for misaligned loads + logic [31:0] rdata_h_ext; // sign extension for half words + logic [31:0] rdata_b_ext; // sign extension for bytes + + logic data_or_pmp_err; + + ///////////////////// + // RData alignment // + ///////////////////// + + // take care of misaligned words + always_comb begin + unique case (rdata_offset_q) + 2'b00: rdata_w_ext = data_rdata_i[32:0]; + 2'b01: rdata_w_ext = {1'b0, data_rdata_i[ 7:0], rdata_q[31:8]}; + 2'b10: rdata_w_ext = {1'b0, data_rdata_i[15:0], rdata_q[31:16]}; + 2'b11: rdata_w_ext = {1'b0, data_rdata_i[23:0], rdata_q[31:24]}; + default: rdata_w_ext = data_rdata_i[32:0]; + endcase + end + + //////////////////// + // Sign extension // + //////////////////// + + // sign extension for half words + always_comb begin + unique case (rdata_offset_q) + 2'b00: begin + if (!data_sign_ext_q) begin + rdata_h_ext = {16'h0000, data_rdata_i[15:0]}; + end else begin + rdata_h_ext = {{16{data_rdata_i[15]}}, data_rdata_i[15:0]}; + end + end + + 2'b01: begin + if (!data_sign_ext_q) begin + rdata_h_ext = {16'h0000, data_rdata_i[23:8]}; + end else begin + rdata_h_ext = {{16{data_rdata_i[23]}}, data_rdata_i[23:8]}; + end + end + + 2'b10: begin + if (!data_sign_ext_q) begin + rdata_h_ext = {16'h0000, data_rdata_i[31:16]}; + end else begin + rdata_h_ext = {{16{data_rdata_i[31]}}, data_rdata_i[31:16]}; + end + end + + 2'b11: begin + if (!data_sign_ext_q) begin + rdata_h_ext = {16'h0000, data_rdata_i[7:0], rdata_q[31:24]}; + end else begin + rdata_h_ext = {{16{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]}; + end + end + + default: rdata_h_ext = {16'h0000, data_rdata_i[15:0]}; + endcase // case (rdata_offset_q) + end + + // sign extension for bytes + always_comb begin + unique case (rdata_offset_q) + 2'b00: begin + if (!data_sign_ext_q) begin + rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]}; + end else begin + rdata_b_ext = {{24{data_rdata_i[7]}}, data_rdata_i[7:0]}; + end + end + + 2'b01: begin + if (!data_sign_ext_q) begin + rdata_b_ext = {24'h00_0000, data_rdata_i[15:8]}; + end else begin + rdata_b_ext = {{24{data_rdata_i[15]}}, data_rdata_i[15:8]}; + end + end + + 2'b10: begin + if (!data_sign_ext_q) begin + rdata_b_ext = {24'h00_0000, data_rdata_i[23:16]}; + end else begin + rdata_b_ext = {{24{data_rdata_i[23]}}, data_rdata_i[23:16]}; + end + end + + 2'b11: begin + if (!data_sign_ext_q) begin + rdata_b_ext = {24'h00_0000, data_rdata_i[31:24]}; + end else begin + rdata_b_ext = {{24{data_rdata_i[31]}}, data_rdata_i[31:24]}; + end + end + + default: rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]}; + endcase // case (rdata_offset_q) + end + + // select word, half word or byte sign extended version + always_comb begin + unique case (data_type_q) + 2'b00: data_rdata_ext = rdata_w_ext; + 2'b01: data_rdata_ext = {1'b0, rdata_h_ext}; + 2'b10,2'b11: data_rdata_ext = {1'b0, rdata_b_ext}; + default: data_rdata_ext = rdata_w_ext; + endcase // case (data_type_q) + end + + ///////////// + // Outputs // + ///////////// + assign data_or_pmp_err = lsu_err_q | data_err_i | pmp_err_q | (cheri_pmode_i & + (cheri_err_q | (resp_is_cap_q & cap_lsw_err_q))); + + // output to register file + if (CHERIoTEn & ~MemCapFmt) begin : gen_memcap_rd_fmt0 + assign lsu_rdata_o = (cheri_pmode_i & resp_is_cap_q) ? cap_lsw_q : data_rdata_ext; + assign lsu_rcap_o = (resp_is_cap_q && data_rvalid_i && (cap_rx_fsm_q == CRX_WAIT_RESP2) && (~data_or_pmp_err)) ? + mem2regcap_fmt0(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : NULL_REG_CAP; + end else if (CHERIoTEn) begin : gen_memcap_rd_fmt1 + assign lsu_rdata_o = (cheri_pmode_i & resp_is_cap_q) ? mem2regaddr_fmt1(data_rdata_ext, cap_lsw_q, lsu_rcap_o): data_rdata_ext; + assign lsu_rcap_o = (resp_is_cap_q && data_rvalid_i && (cap_rx_fsm_q == CRX_WAIT_RESP2) && (~data_or_pmp_err)) ? + mem2regcap_fmt1(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : NULL_REG_CAP; + end else begin : gen_no_cap_rd + assign lsu_rdata_o = data_rdata_ext; + assign lsu_rcap_o = NULL_REG_CAP; + end +endmodule diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/capdti.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/capdti.sv new file mode 100644 index 000000000..1f09a519f --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/capdti.sv @@ -0,0 +1,185 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following implements the datatype invariant properties +for each major basic block. +*/ + +function automatic logic regCapSatsMemConstraint(reg_cap_t c, logic [31:0] a); + CapBoundBits bounds = getCapBoundsBitsRaw(c.exp, c.base, c.top, a); + return + (c.exp <= 5'd14 || c.exp == 5'd24) && + (c.valid -> ( + (bounds.top <= 33'h1_0000_0000) && + ((c.exp == 5'd24) -> ~c.base[9'd8]) && + ((c.exp <= 5'd14) -> (unsigned'(bounds.base) <= unsigned'(bounds.top))) + )); +endfunction + +function automatic logic pccCapSatsMemConstraint(pcc_cap_t c, logic [31:0] a); + return + (c.exp <= 5'd14 || c.exp == 5'd24) && + (c.valid -> ( + (c.top33 <= 33'h1_0000_0000) && + (c.exp <= 5'd14 -> unsigned'(c.base32) <= unsigned'(c.top33)) + )); +endfunction + +function automatic logic regCapSatsDTI(reg_cap_t c, logic [31:0] a); + CapBoundBits bounds = getCapBoundsBitsRaw(c.exp, c.base, c.top, a); + CapBoundCorBits cor = getCapBoundsCorBitsRaw(c.exp, c.base, c.top, a); + return ( + c.top_cor == cor.top_cor && c.base_cor == cor.base_cor && + regCapSatsMemConstraint(c, a) + ); +endfunction + +function automatic logic fullCapSatsDTI(full_cap_t c, logic [31:0] a); + CapBoundBits bounds = getCapBoundsBitsRaw(c.exp, c.base, c.top, a); + CapBoundCorBits cor = getCapBoundsCorBitsRaw(c.exp, c.base, c.top, a); + return ( + c.base_cor == cor.base_cor && c.top_cor == cor.top_cor && + regCapSatsMemConstraint(full2regcap(c), a) && + expand_perms(c.cperms) == c.perms + ); +endfunction + +function automatic logic pccCapSatsDTI(pcc_cap_t c, logic [31:0] a); + full_cap_t fullcap = pcc2fullcap(c); + CapBoundBits bounds = getCapBoundsBitsRaw(fullcap.exp, fullcap.base, fullcap.top, a); + return ( + pccCapSatsMemConstraint(c, a) && + expand_perms(c.cperms) == c.perms && + (c.base32 == bounds.base && c.top33 == bounds.top) + ); +endfunction + +function automatic logic fullCapSatsDTIStrong(full_cap_t c, logic [31:0] a); + CapBoundBits bounds = getCapBoundsBitsRaw(c.exp, c.base, c.top, a); + CapBoundCorBits cor = getCapBoundsCorBitsRaw(c.exp, c.base, c.top, a); + return ( + (c.base32 == bounds.base && c.top33 == bounds.top) && + c.base_cor == cor.base_cor && c.top_cor == cor.top_cor && + regCapSatsMemConstraint(full2regcap(c), a) && + expand_perms(c.cperms) == c.perms + ); +endfunction + +function automatic logic fullCapSatsDTIStrongNoCor(full_cap_t c, logic [31:0] a); + CapBoundBits bounds = getCapBoundsBitsRaw(c.exp, c.base, c.top, a); + return ( + (c.base32 == bounds.base && c.top33 == bounds.top) && + regCapSatsMemConstraint(full2regcap(c), a) && + expand_perms(c.cperms) == c.perms + ); +endfunction + +///////////////// Execute Block (stateless) ///////////////// + +logic ex_in_sats; +assign ex_in_sats = + regCapSatsDTI(`CE.fwd_wcap_i, `CE.fwd_wdata_i) && + regCapSatsDTI(`CE.rf_rcap_a_i, `CE.rf_rdata_a_i) && + regCapSatsDTI(`CE.rf_rcap_b_i, `CE.rf_rdata_b_i) && + regCapSatsDTI(`CE.lsu_rcap_i, `CE.lsu_rdata_i[31:0]) && + regCapSatsDTI(`CE.csr_rcap_i, `CE.csr_rdata_i) && + pccCapSatsDTI(`CE.pcc_cap_i, pcc_address_q); + +logic ex_out_csr_sats; +assign ex_out_csr_sats = regCapSatsDTI(`CE.csr_wcap_o, `CE.csr_wdata_o); + +logic ex_out_lsu_sats; +assign ex_out_lsu_sats = regCapSatsDTI(`CE.lsu_wcap_o, `CE.lsu_wdata_o[31:0]); + +logic ex_out_result_sats; +assign ex_out_result_sats = regCapSatsDTI(`CE.result_cap_o, `CE.result_data_o); + +logic ex_out_pcc_sats; +assign ex_out_pcc_sats = pccCapSatsDTI(`CE.pcc_cap_o, `CE.rf_rdata_a); + +logic ex_inner_sats; +assign ex_inner_sats = + fullCapSatsDTIStrong(`CE.rf_fullcap_a, `CE.rf_rdata_a) && + fullCapSatsDTIStrong(`CE.rf_fullcap_b, `CE.rf_rdata_b); + +///////////////// CSR Block ///////////////// + +`define DutCSRs(X) \ + `X(mtvec, `CSR.mtvec_cap, `CSR.mtvec_q) \ + `X(mepc, `CSR.mepc_cap, `CSR.mepc_q) \ + `X(mtdc, `CSRG.mtdc_cap, `CSRG.mtdc_data) \ + `X(mscratchc, `CSRG.mscratchc_cap, `CSRG.mscratchc_data) \ + `X(depc, `CSR.depc_cap, `CSR.depc_q) \ + `X(dscratch0, `CSR.dscratch0_cap, `CSR.dscratch0_q) \ + `X(dscratch1, `CSR.dscratch1_cap, `CSR.dscratch1_q) + +`define X(nm, cap, data) \ + logic csr_``nm``_sats; \ + assign csr_``nm``_sats = regCapSatsDTI(cap, data); +`DutCSRs(X) +`undef X + +logic csr_out_pcc_sats; +assign csr_out_pcc_sats = pccCapSatsDTI(`CSR.pcc_cap_o, pcc_address_q); + +logic csr_int; +`define X(nm, cap, data) csr_``nm``_sats && +assign csr_int = `DutCSRs(X) csr_out_pcc_sats; +`undef X + +logic csr_in; +assign csr_in = + csr_int && regCapSatsDTI(`CSR.cheri_csr_wcap_i, `CSR.cheri_csr_wdata_i) && + (`CSR.cheri_branch_req_i -> pccCapSatsDTI(`CSR.pcc_cap_i, pcc_address_d)); + +logic csr_out_rdata_sats; +assign csr_out_rdata_sats = regCapSatsDTI(`CSR.cheri_csr_rcap_o, `CSR.cheri_csr_rdata_o); + +// `define Y(nm, cap1, data1) \ +// DTI_CSR``nm: assert property (nm``_sats); +// `DutCSRs(Y) +// `undef Y + +///////////////// Writeback Block ///////////////// + +logic wb_in; +assign wb_in = regCapSatsDTI(`WB.cheri_rf_wcap_i, `WB.cheri_rf_wdata_i); + +logic wb_int; +assign wb_int = regCapSatsDTI(`WBG.cheri_rf_wcap_q, `WBG.cheri_rf_wdata_q); + +logic wb_in_lsu; +assign wb_in_lsu = regCapSatsDTI(`WB.rf_wcap_lsu_i, `WB.rf_wdata_lsu_i); + +logic wb_out; +assign wb_out = + regCapSatsDTI(`WB.rf_wcap_fwd_wb_o, `WB.rf_wdata_fwd_wb_o) && + regCapSatsDTI(`WB.rf_wcap_wb_o, `WB.rf_wdata_wb_o); + +// This is part of the DTI, which is true - meaning anything written to memory +// satisfies this, meaning anything loaded from memory would, hence this assumption is 'safe'. +// FIXME: This should really be on the raw capability bits, instead of the decoded capability. +MemConstraint: assume property (regCapSatsMemConstraint(`WB.rf_wcap_lsu_i, `WB.rf_wdata_lsu_i)); + +///////////////// RF Block (16 regs) ///////////////// + +`define RFC(i) regCapSatsDTI(`RF.rf_cap_q[i], `RF.rf_reg_q[i]) && + +// Splitting this up makes these properties prove faster +logic rf_group1, rf_group2, rf_all; + +assign rf_group1 = `RFC(1) `RFC(2) `RFC(3) `RFC(4) `RFC(5) `RFC(6) `RFC(7) `RFC(8) 1; +assign rf_group2 = `RFC(9) `RFC(10) `RFC(11) `RFC(12) `RFC(13) `RFC(14) `RFC(15) 1; +assign rf_all = rf_group1 & rf_group2; + +logic rf_in; +assign rf_in = regCapSatsDTI(`RF.wcap_a_i, `RF.wdata_a_i); + +logic rf_out_a; +assign rf_out_a = regCapSatsDTI(`RF.rcap_a_o, `RF.rdata_a_o); +logic rf_out_b; +assign rf_out_b = regCapSatsDTI(`RF.rcap_b_o, `RF.rdata_b_o); diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/compare_helper.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/compare_helper.sv new file mode 100644 index 000000000..154a2a8f7 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/compare_helper.sv @@ -0,0 +1,87 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +///////////////////////// Comparison ///////////////////////// +`define INSTR wbexc_decompressed_instr + +assign wbexc_is_load_instr = `IS_LB | `IS_LBU | `IS_LH | `IS_LHU | `IS_LW | `IS_LOADCAPIMM; +assign wbexc_is_store_instr = `IS_SB | `IS_SH | `IS_SW | `IS_STORECAPIMM; +assign wbexc_is_mem_instr = wbexc_is_load_instr | wbexc_is_store_instr; +assign wbexc_is_mem_cap_instr = `IS_LOADCAPIMM | `IS_STORECAPIMM; +assign wbexc_is_wfi = `IS_WFI & ~wbexc_fetch_err; +`undef INSTR + +`define INSTR `CR.instr_rdata_id +assign ex_is_mem_cap_instr = `IS_LOADCAPIMM | `IS_STORECAPIMM; +assign ex_is_load_instr = `IS_LB | `IS_LBU | `IS_LH | `IS_LHU | `IS_LW | `IS_LOADCAPIMM; +assign ex_is_store_instr = `IS_SB | `IS_SH | `IS_SW | `IS_STORECAPIMM; +assign ex_is_mem_instr = ex_is_load_instr | ex_is_store_instr; +assign ex_is_clc = `IS_LOADCAPIMM; + +assign ex_is_btype = `IS_BTYPE; +assign ex_is_jump = `IS_JAL | `IS_JALR; +assign ex_is_wfi = `IS_WFI; +assign ex_is_rtype = `IS_ADD | `IS_SUB | `IS_SLL | `IS_SLT | `IS_SLTU | `IS_XOR | `IS_SRL | `IS_SRA | `IS_OR | `IS_AND; +assign ex_is_div = `IS_DIV | `IS_DIVU | `IS_REM | `IS_REMU; +`undef INSTR + +t_Capability res_data; +assign res_data = regcap2sail(`WB.rf_wcap_wb_o, `WB.rf_wdata_wb_o); + +// real_write checks that there is a write and the dest reg is not x0 +logic dut_real_write, spec_real_write; +assign dut_real_write = `WB.rf_we_wb_o & (|`WB.rf_waddr_wb_o); +assign spec_real_write = wbexc_post_wX_en & (|wbexc_post_wX_addr); + +assign addr_match = dut_real_write == spec_real_write && + (spec_real_write -> `WB.rf_waddr_wb_o == wbexc_post_wX_addr); +assign data_match = (spec_real_write && dut_real_write) -> alas(wbexc_post_wX, res_data); +assign nowrite = ~dut_real_write & ~spec_real_write; + +assign finishing_executed = wbexc_finishing & ~wbexc_fetch_err; + +/* +Select CSRs based on the current state of the follower, in particular: +- In most cases we compare the CSRs that were about to written at the end of ID/EX to the CSRs from the spec also + from that time. It's unfortunate to do that now but not a huge hassle. +- In the case of an exception or WFI we compare the CSRs about to be written now with the CSRs from the spec at the end of ID/EX +- In the case of an IRQ we compare the the CSRs about to be written now with the CSRs from the spec now +*/ + +`define INSTR `CR.instr_rdata_id + +logic use_curr_dut, use_curr_spec; +assign use_curr_dut = wbexc_err | wbexc_handling_irq; +assign use_curr_spec = wbexc_handling_irq; + +`define X(c) assign wbexc_dut_cmp_post_``c = use_curr_dut ? post_``c : wbexc_dut_post_``c; +`X_EACH_CSR +`undef X + +`define X(c) assign wbexc_spec_cmp_post_``c = use_curr_spec ? spec_post_``c : wbexc_post_``c; +`X_EACH_CSR +`undef X + +`define X_DISABLE_PC +assign csrs_match = +`define X(c) alas(wbexc_spec_cmp_post_``c, wbexc_dut_cmp_post_``c) && + `X_EACH_CSR_C +`undef X +`define X(c) wbexc_spec_cmp_post_``c == wbexc_dut_cmp_post_``c && + `X_EACH_CSR_NC +`undef X + 1; +`undef X_DISABLE_PC + +`define X_DISABLE_PC +assign csrs_didnt_change = +`define X(c) pre_``c == wbexc_dut_post_``c && + `X_EACH_CSR +`undef X + 1; +`undef X_DISABLE_PC + +assign pc_match = wbexc_spec_cmp_post_pc == wbexc_dut_cmp_post_pc; diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/follower.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/follower.sv new file mode 100644 index 000000000..fda79c360 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/follower.sv @@ -0,0 +1,132 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following implements the pipeline follower. It is pretty simple given the pipeline is short. + +The top of this file contains signals to indicate when an instruction moves from a pipeline stage, +and when it does so on what terms. + +We record both the spec post state and the implementation CSR post state as soon as the instruction moves on from ID/EX. +The latter is stored so that we can make comparisons at the same time, independent of when the instruction retires. We +probably could do this earlier in the cases where no exception occurs, but that would require special treatment for +exception vs non-exception cases. In fairness there is already a difference, but that's only a case split which can be unified. +*/ + +`define INSTR `CR.instr_rdata_id + +assign ex_success = `ID.instr_done; +assign ex_err = `IDC.exc_req_d; +assign ex_kill = `ID.wb_exception | ~`ID.controller_run; +// Note that this only kills instructions because e.g. of a jump ahead of it or an exception + +assign exc_finishing = `IDC.ctrl_fsm_cs == `IDC.FLUSH; +assign wbexc_handling_irq = `IDC.ctrl_fsm_cs == `IDC.IRQ_TAKEN; + +assign wb_finishing = wbexc_is_wfi? wfi_will_finish:`CR.instr_done_wb; + +assign wfi_will_finish = `IDC.ctrl_fsm_cs == `IDC.FLUSH; + +assign wbexc_err = wbexc_ex_err | + `IDC.wb_exception_o | + ((`IDC.ctrl_fsm_cs == `IDC.FLUSH) & ~wbexc_csr_pipe_flush); + +assign wbexc_finishing = + wbexc_exists & (wbexc_err ? exc_finishing : wb_finishing); + +assign instr_will_progress = (~wbexc_exists | wbexc_finishing) & ~ex_kill & (ex_success | ex_err); + +always_comb begin + if (`CR.instr_new_id) begin + ex_has_branched_d = 1'b0; + end else begin + ex_has_branched_d = ex_has_branched_q; + end + + ex_has_branched_d = ex_has_branched_d | (`IF.branch_req && ~ex_kill && `IDC.ctrl_fsm_cs == `IDC.DECODE); +end + +always @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + wbexc_exists <= 1'b0; + idex_has_compressed_instr <= 1'b0; + ex_has_branched_q <= 1'b0; + wbexc_csr_pipe_flush <= 1'b0; + end else begin + if (wbexc_finishing) begin + wbexc_exists <= 1'b0; + end + + ex_has_branched_q <= ex_has_branched_d; + if (instr_will_progress) begin + ex_has_branched_q <= 1'b0; + wbexc_post_wX <= spec_post_wX; + wbexc_post_wX_addr <= spec_post_wX_addr; + wbexc_post_wX_en <= spec_post_wX_en; + + `define X(n) wbexc_post_``n <= spec_post_``n; + `X_EACH_CSR + `undef X + + `define X(n) wbexc_dut_post_``n <= post_``n; + `X_EACH_CSR + `undef X + + wbexc_instr <= idex_compressed_instr; + wbexc_decompressed_instr <= `CR.instr_rdata_id; + wbexc_compressed_illegal <= `CR.illegal_c_insn_id; + wbexc_exists <= 1'b1; + wbexc_ex_err <= ex_err; + wbexc_fetch_err <= `ID.instr_fetch_err_i; + wbexc_post_int_err <= spec_int_err; + wbexc_illegal <= `CR.illegal_insn_id; + wbexc_pc <= `CR.pc_id; + wbexc_csr_pipe_flush <= `IDC.csr_pipe_flush; + wbexc_is_checkable_csr <= ex_is_checkable_csr; + + wbexc_spec_mem_read_fst_rdata <= spec_mem_read_fst_rdata; + wbexc_spec_mem_read_snd_rdata <= spec_mem_read_snd_rdata; + wbexc_spec_mem_read_tag <= spec_mem_read_tag; + wbexc_mem_had_snd_req <= mem_gnt_snd_q | mem_gnt_snd_d; + + wbexc_spec_mem_revoke_en <= spec_mem_revoke_en; + wbexc_spec_mem_revoke_addr <= spec_mem_revoke_addr; + wbexc_spec_mem_revoke <= spec_mem_revoke; + end + + if (`IF.if_id_pipe_reg_we) begin + idex_compressed_instr <= `IF.if_instr_rdata; + idex_has_compressed_instr <= 1'b1; + end + end +end + +assign spec_en = wbexc_handling_irq | instr_will_progress; + +always @(posedge clk_i) begin + if (~rst_ni) begin + has_spec_past = 1'b0; + spec_past_has_reg = 32'b0; + end else if (spec_en) begin + has_spec_past = `IS_CSR -> ex_is_checkable_csr; + + if (spec_post_wX_en) begin + spec_past_regs[spec_post_wX_addr] = spec_post_wX; + spec_past_has_reg[spec_post_wX_addr] = 1'b1; + end + if (`IS_CSR & ~ex_is_checkable_csr) begin + // Clear out everything, since we don't know what has been written to any more + // We could be stricter but there's little point in doing so. + spec_past_has_reg = 32'b0; + end + + `define X(n) spec_past_``n = spec_post_``n; + `X_EACH_CSR + `undef X + end + end + +`undef INSTR diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/mem.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/mem.sv new file mode 100644 index 000000000..bf538ddb6 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/mem.sv @@ -0,0 +1,160 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +This file implements the tracking of ibex memory. It (by assumption) sets data_rvalid_i to the corresponding value that was +sent to the spec. The interpretation of the signals used is justified in the proofs. +*/ + +logic has_snd_req; +assign has_snd_req = mem_gnt_snd_d | (mem_gnt_fst_q & `CR.data_req_out); + +logic outstanding_resp; +assign outstanding_resp = `CR.outstanding_load_wb | `CR.outstanding_store_wb; + +/* +Some definitions: +- An 'early response' is a response made to a memory instruction before the instruction has progressed to the WB stage, + i.e. while it is still in the ID/EX stage. This is only possible for multi-request instructions, and only one + early response can be made. +- A 'late response' is a response received during the WB stage. There can be at most one late response, since + if a memory instruction sends two requests, it won't go to WB until it has sent one request. +Responses are given in the order they are requested, so it suffices to check if WB is waiting on a response. +*/ +logic early_resp, late_resp; +assign early_resp = data_rvalid_i & ~outstanding_resp; +assign late_resp = data_rvalid_i & outstanding_resp; + +// If we receive an early response, give it the data sent to the spec directly +LoadMemEarlyResp: assume property ( + early_resp |-> data_rdata_i == {spec_mem_read_tag, spec_mem_read_fst_rdata} +); + +// If we have a late response, and this is the first response send the low spec data +LoadMemLateRespFirst: assume property ( + late_resp & ~wbexc_mem_had_snd_req |-> data_rdata_i == {wbexc_spec_mem_read_tag, wbexc_spec_mem_read_fst_rdata} +); + +// If we have a late response, and this is the second response, send the high spec data +LoadMemLateRespSecond: assume property ( + late_resp & wbexc_mem_had_snd_req |-> data_rdata_i == {wbexc_spec_mem_read_tag, wbexc_spec_mem_read_snd_rdata} +); + +// The spec read data cannot change while an instruction is running, only when there is a new one +// Note these values are undriven, they are not from the spec as the name would suggest +SpecReadDataKeep: assume property (~instr_will_progress |=> + $stable(spec_mem_read_fst_rdata) && $stable(spec_mem_read_snd_rdata) && $stable(spec_mem_read_tag) +); + +logic[31:0] tsmap_heap_relative_ptr; +assign tsmap_heap_relative_ptr = spec_mem_revoke_addr - HeapBase; + +logic[31:0] wbexc_tsmap_heap_relative_ptr; +logic[4:0] wbexc_tsmap_rdata_bit_idx; +logic[31:0] wbexc_tsmap_addr; +assign wbexc_tsmap_heap_relative_ptr = wbexc_spec_mem_revoke_addr - HeapBase; +assign wbexc_tsmap_rdata_bit_idx = wbexc_tsmap_heap_relative_ptr[7:3]; +assign wbexc_tsmap_addr = wbexc_tsmap_heap_relative_ptr[31:8]; + +TRVKValue: assume property ( + $past(wbexc_tsmap_addr, 2) == tsmap_addr_o + |-> + tsmap_rdata_i[$past(wbexc_tsmap_rdata_bit_idx, 2)] == $past(wbexc_spec_mem_revoke, 2) +); + +TRVKZeroOutsideRange: assume property ( + spec_mem_revoke_en & (tsmap_heap_relative_ptr[31:8] >= TSMapSize) |-> ~spec_mem_revoke +); + +assign mem_gnt_fst_d = mem_gnt_fst_q | data_gnt_i; +assign mem_gnt_snd_d = mem_gnt_snd_q | (data_gnt_i & mem_gnt_fst_q); + +assign mem_req_fst_d = data_req_o & ~mem_gnt_fst_q; +assign mem_req_snd_d = data_req_o & mem_gnt_fst_q; + +always @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni | instr_will_progress) begin + mem_gnt_fst_q <= 1'b0; + mem_gnt_snd_q <= 1'b0; + end else begin + mem_gnt_fst_q <= mem_gnt_fst_d; + mem_gnt_snd_q <= mem_gnt_snd_d; + end +end + +assign mem_resp_d = mem_resp_q | (data_rvalid_i & ~outstanding_mem); + +always @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni | instr_will_progress) begin + mem_resp_q <= 1'b0; + end else begin + mem_resp_q <= mem_resp_d; + end +end + +`define ALT_LSU_STATE_COPY \ + .cheri_pmode_i, \ + .data_rvalid_i(1'b1), \ + .data_err_i(1'b0), \ + .data_we_q(`LSU.data_we_q), \ + .pmp_err_q(`LSU.pmp_err_q), \ + .lsu_err_q(`LSU.lsu_err_q), \ + .outstanding_resp_q(`LSU.outstanding_resp_q), \ + .resp_is_cap_q(`LSU.resp_is_cap_q), \ + .cheri_err_q(`LSU.cheri_err_q), \ + .resp_lc_clrperm_q(`LSU.resp_lc_clrperm_q), \ + .cap_lsw_err_q(`LSU.cap_lsw_err_q), \ + .lsu_rcap_o(), + +alt_lsu #(.CHERIoTEn(1'b1), .MemCapFmt(1'b0), .CheriTBRE(1'b0)) alt_lsu_late_i ( + .cap_rx_fsm_q(`LSU.cap_rx_fsm_q), + .data_rdata_i( + ~wbexc_mem_had_snd_req ? + {wbexc_spec_mem_read_tag, wbexc_spec_mem_read_fst_rdata} : + {wbexc_spec_mem_read_tag, wbexc_spec_mem_read_snd_rdata} + ), + `ALT_LSU_STATE_COPY + .data_type_q(`LSU.data_type_q), + .rdata_offset_q(`LSU.rdata_offset_q), + .data_sign_ext_q(`LSU.data_sign_ext_q), + .rdata_q(`LSU.rdata_q), + .cap_lsw_q(`LSU.cap_lsw_q) +); + +t_Capability alt_lsu_late_res; +assign alt_lsu_late_res = regcap2sail(alt_lsu_late_i.lsu_rcap_o, alt_lsu_late_i.lsu_rdata_o[31:0]); + +alt_lsu #(.CHERIoTEn(1'b1), .MemCapFmt(1'b0), .CheriTBRE(1'b0)) alt_lsu_very_early_i ( + .cap_rx_fsm_q(`LSU.resp_is_cap_q ? CRX_WAIT_RESP2 : CRX_IDLE), + .data_rdata_i( + ~(`LSU.split_misaligned_access | ex_is_mem_cap_instr) ? + {spec_mem_read_tag, spec_mem_read_fst_rdata} : + {spec_mem_read_tag, spec_mem_read_snd_rdata} + ), + `ALT_LSU_STATE_COPY + .data_type_q(`LSU.lsu_type_i), + .data_sign_ext_q(`LSU.lsu_sign_ext_i), + .rdata_offset_q(`LSU.data_offset), + .rdata_q(spec_mem_read_fst_rdata[31:8]), + .cap_lsw_q({spec_mem_read_tag, spec_mem_read_fst_rdata}) +); + +t_Capability alt_lsu_very_early_res; +assign alt_lsu_very_early_res = regcap2sail(alt_lsu_very_early_i.lsu_rcap_o, alt_lsu_very_early_i.lsu_rdata_o[31:0]); + +alt_lsu #(.CHERIoTEn(1'b1), .MemCapFmt(1'b0), .CheriTBRE(1'b0)) alt_lsu_early_i ( + .cap_rx_fsm_q(`LSU.cap_rx_fsm_q), + .data_rdata_i({spec_mem_read_tag, spec_mem_read_snd_rdata}), + `ALT_LSU_STATE_COPY + .data_type_q(`LSU.data_type_q), + .data_sign_ext_q(`LSU.data_sign_ext_q), + .rdata_offset_q(`LSU.rdata_offset_q), + .rdata_q(`LSU.rdata_q), + .cap_lsw_q(`LSU.cap_lsw_q) +); + +t_Capability alt_lsu_early_res; +assign alt_lsu_early_res = regcap2sail(alt_lsu_early_i.lsu_rcap_o, alt_lsu_early_i.lsu_rdata_o[31:0]); diff --git a/vendor/lowrisc_ibex/dv/formal/check/peek/pcc.sv b/vendor/lowrisc_ibex/dv/formal/check/peek/pcc.sv new file mode 100644 index 000000000..02e2f2faf --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/peek/pcc.sv @@ -0,0 +1,32 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following implements PCC.address. As per the Sail, PCC.address != PC, but it is also not +needed if you are willing to store the bounds in the decompressed form, as cheriot-ibex does. +This creates a problem for DTI checks, so we track PCC.address here. This code is the data mirror +for the code in ibex_cs_registers.sv. It is more or less identical. +*/ + +always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + pcc_address_q <= 0; + end else begin + pcc_address_q <= pcc_address_d; + end +end + +always_comb begin + if (`CSR.csr_save_cause_i) begin + pcc_address_d = `CSR.mtvec_q; + end else if (`CSR.csr_restore_mret_i) begin + pcc_address_d = `CSR.mepc_q; + end else if (`CSR.cheri_branch_req_i) begin + pcc_address_d = `CE.rf_rdata_a; + end else begin + pcc_address_d = pcc_address_q; + end +end diff --git a/vendor/lowrisc_ibex/dv/formal/check/protocol/irqs.sv b/vendor/lowrisc_ibex/dv/formal/check/protocol/irqs.sv new file mode 100644 index 000000000..53821f6a1 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/protocol/irqs.sv @@ -0,0 +1,36 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following give the protocol that IRQs must follow. +*/ + +typedef struct packed { + logic irq_software; + logic irq_timer; + logic irq_external; + logic [14:0] irq_fast; + logic irq_nmi; +} extended_irqs_t; + +extended_irqs_t extended_mip; +assign extended_mip.irq_software = irq_software_i; +assign extended_mip.irq_timer = irq_timer_i; +assign extended_mip.irq_external = irq_external_i; +assign extended_mip.irq_fast = irq_fast_i; +assign extended_mip.irq_nmi = irq_nm_i; + +// IRQs must remain active until they are cleared by some MMIO memory request +// The alternative is that IRQs disappear after just one cycle or something +MIPFair: assume property ( + $past(extended_mip) == ($past(extended_mip) & extended_mip) || data_gnt_i +); + +`define WFI_BOUND 20 +// If we are asleep we must eventually wake up. This is validated by the WFIStart assumption, +// which ensures that this is actually possible. We make the time bounded instead of s_eventually +// for conclusivity purposes. +WFIWakeUp: assume property (`IDC.ctrl_fsm_cs == SLEEP |-> ##[0:`WFI_BOUND] `IDC.irq_pending_i); diff --git a/vendor/lowrisc_ibex/dv/formal/check/protocol/mem.sv b/vendor/lowrisc_ibex/dv/formal/check/protocol/mem.sv new file mode 100644 index 000000000..33274ba75 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/protocol/mem.sv @@ -0,0 +1,48 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following describes the protocol for the memory interface to Ibex, as defined by the documentation. + +In this case all responses must be within bounded time. Removing the bound +leaves some properties inconclusive. +*/ + +// Sail does not specify these +NoDataErr: assume property (~data_err_i); +NoInstrErr: assume property (~instr_err_i); + +`define TIME_LIMIT 5 + +interface mem_assume_t( + input logic req_o, + input logic gnt_i, + input logic rvalid_i +); + logic [7:0] outstanding_reqs_q; + logic [7:0] outstanding_reqs; + assign outstanding_reqs = outstanding_reqs_q + gnt_i - rvalid_i; + + always @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) + outstanding_reqs_q <= 8'h0; + else + outstanding_reqs_q <= outstanding_reqs; + end + + // 1. Only send an rvalid if there is an outstanding request, but not in this cycle + MemValidBounded: assume property (outstanding_reqs_q == 8'b0 |-> ~rvalid_i); + // 2. Grants can only be sent when they are requested + MemGntOnRequest: assume property (~req_o |-> ~gnt_i); + + // Grants must respond within TIME_LIMIT cycles + GntBound: assume property (req_o |-> ##[0:`TIME_LIMIT] gnt_i); + // RValid takes no more than TIME_LIMIT cycles + MemValidTimer: assume property (outstanding_reqs != 0 |-> ##[0:`TIME_LIMIT] rvalid_i); +endinterface + +mem_assume_t instr_mem_assume(instr_req_o, instr_gnt_i, instr_rvalid_i); +mem_assume_t data_mem_assume(data_req_o, data_gnt_i, data_rvalid_i); diff --git a/vendor/lowrisc_ibex/dv/formal/check/spec_instance.sv b/vendor/lowrisc_ibex/dv/formal/check/spec_instance.sv new file mode 100644 index 000000000..9e87dcbda --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/spec_instance.sv @@ -0,0 +1,97 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +The following instantiates the specification via the spec api. It also chooses the mode for the spec to run in (see main.sail +for more on that). + +It just wires up the pre_* state to the spec_post* state. +*/ + +always_comb begin + if (wbexc_handling_irq) main_mode = MAIN_IRQ; + else if (`ID.instr_fetch_err_i) main_mode = MAIN_IFERR; + else main_mode = MAIN_IDEX; +end + +// Some registers are not driven. Only those that have reg_driven[i] high are +// given real values, the rest are left free (i.e. the spec cannot depend on +// them). For wraparound purposes it does not matter what reg_driven[i] is: +// - If too many registers are driven they all must pass checks anyway (since +// they are checked as inputs) +// - If too few registers are driven instructions will fail to be spec +// conformant +// Note that while it again does not matter how they are defined, but only +// registers matching one of `CR.rf_raddr_{a, b} can be driven. + +logic [31:0] reg_driven; +assign reg_driven[0] = 1'b0; + +for (genvar i = 1; i < 32; i++) begin: g_regs_cut + t_Capability free; // Undriven + // csr_cheri_asr err is a corner case where a CSR instruction (which + // depends on register a) might fail to execute due to the PCC missing + // some permissions, meaning it does not actually depend on register a. + assign reg_driven[i] = (`CR.rf_raddr_a == i && `CR.rf_ren_a && ~`IDC.csr_cheri_asr_err) || (`CR.rf_raddr_b == i && `CR.rf_ren_b); + assign pre_regs_cut[i] = reg_driven[i] ? pre_regs[i] : free; +end + +spec_api #( + .NREGS(32) +) spec_api_i ( + .int_err_o(spec_int_err), + .main_mode(main_mode), + + .insn_bits(idex_compressed_instr), + + .regs_i(pre_regs_cut), + + .wx_o(spec_post_wX), + .wx_addr_o(spec_post_wX_addr), + .wx_en_o(spec_post_wX_en), + + .mvendor_id_i(CSR_MVENDORID_CHERI_VALUE), + .march_id_i(CSR_MARCHID_CHERI_VALUE), + .mimp_id_i(CSR_MIMPID_VALUE), + .mhart_id_i(hart_id_i), + .mconfigptr_i(), + + .misa_i(`CSR.MISA_VALUE), + .mip_i(pre_mip), + .nextpc_i(pre_nextpc), + + .nmi_i(pre_nmi), + + // Unused + .mseccfg_i(), + .mseccfg_o(), + + `define X(n) .n``_i(pre_``n), .n``_o(spec_post_``n), + `X_EACH_CSR + `undef X + + .mem_read_o(spec_mem_read), + .mem_read_snd_gran_o(spec_mem_read_snd), + .mem_read_fst_addr_o(spec_mem_read_fst_addr), + .mem_read_snd_addr_o(spec_mem_read_snd_addr), + .mem_read_fst_rdata_i(spec_mem_read_fst_rdata), + .mem_read_snd_rdata_i(spec_mem_read_snd_rdata), + .mem_read_tag_i(spec_mem_read_tag), + + .mem_revoke_en_o(spec_mem_revoke_en), + .mem_revoke_granule_o(spec_mem_revoke_addr), + .mem_revoke_i(spec_mem_revoke), + + .mem_write_o(spec_mem_write), + .mem_write_snd_gran_o(spec_mem_write_snd), + .mem_write_fst_addr_o(spec_mem_write_fst_addr), + .mem_write_snd_addr_o(spec_mem_write_snd_addr), + .mem_write_fst_wdata_o(spec_mem_write_fst_wdata), + .mem_write_snd_wdata_o(spec_mem_write_snd_wdata), + .mem_write_fst_be_o(spec_mem_write_fst_be), + .mem_write_snd_be_o(spec_mem_write_snd_be), + .mem_write_tag_o(spec_mem_write_tag) +); diff --git a/vendor/lowrisc_ibex/dv/formal/check/top.sv b/vendor/lowrisc_ibex/dv/formal/check/top.sv new file mode 100644 index 000000000..3e230edb9 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/check/top.sv @@ -0,0 +1,515 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +This is the top module. Everything else in check will be included into this file. +This module contains the ibex instance, the specification instance and the assertions +(included via the built psgen file). + +It has the same ports as the ibex top. +*/ + +// Preprocessor decoding of instructions +`include "encodings.sv" + +`define CR ibex_top_i.u_ibex_core +`define CSR `CR.cs_registers_i +`define CSRG `CSR.gen_scr +`define CSRP `CSR.g_pmp_registers +`define LSU `CR.load_store_unit_i +`define ID `CR.id_stage_i +`define IDG `ID.gen_stall_mem +`define IDC `ID.controller_i +`define WB `CR.wb_stage_i +`define WBG `WB.g_writeback_stage +`define RF ibex_top_i.gen_regfile_cheriot.register_file_i +`define IF `CR.if_stage_i +`define IFP `IF.gen_prefetch_buffer.prefetch_buffer_i +`define IFF `IFP.fifo_i +`define MULT `CR.ex_block_i.gen_multdiv_fast.multdiv_i +`define MULTG `MULT.gen_mult_fast +`define CE `CR.g_cheri_ex.u_cheri_ex +`define TRVK `CR.g_trvk_stage.cheri_trvk_stage_i + +module top import ibex_pkg::*; #( + parameter int unsigned DmHaltAddr = 32'h1A110800, + parameter int unsigned DmExceptionAddr = 32'h1A110808, + parameter bit SecureIbex = 1'b0, + parameter bit WritebackStage = 1'b1, + parameter bit RV32E = 1'b1, + parameter int unsigned PMPNumRegions = 4, + parameter int unsigned HeapBase = 32'h2001_0000, + parameter int unsigned TSMapSize = 1024 // 32-bit words +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, // enable all clock gates for testing + input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i, + + input logic cheri_pmode_i, + input logic cheri_tsafe_en_i, + + input logic [31:0] hart_id_i, + input logic [31:0] boot_addr_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic [6:0] instr_rdata_intg_i, + input logic instr_err_i, + + // Data memory interface + output logic data_req_o, + output logic data_is_cap_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [32:0] data_wdata_o, + output logic [6:0] data_wdata_intg_o, + input logic [32:0] data_rdata_i, + input logic [6:0] data_rdata_intg_i, + input logic data_err_i, + + // TS map memory interface + output logic tsmap_cs_o, + output logic [15:0] tsmap_addr_o, + input logic [31:0] tsmap_rdata_i, + input logic [6:0] tsmap_rdata_intg_i, + input logic [127:0] mmreg_corein_i, + output logic [63:0] mmreg_coreout_o, + + // Interrupt inputs + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [14:0] irq_fast_i, + input logic irq_nm_i, // non-maskeable interrupt + + // Scrambling Interface + input logic scramble_key_valid_i, + input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i, + input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i, + output logic scramble_req_o, + + // Debug Interface + input logic debug_req_i, + output crash_dump_t crash_dump_o, + output logic double_fault_seen_o, + + // CPU Control Signals + input fetch_enable_t fetch_enable_i, + output logic alert_minor_o, + output logic alert_major_internal_o, + output logic alert_major_bus_o, + output logic core_sleep_o, + + // DFT bypass controls + input logic scan_rst_ni +); + +default clocking @(posedge clk_i); endclocking + +ibex_top #( + .DmHaltAddr(DmHaltAddr), + .DmExceptionAddr(DmExceptionAddr), + .SecureIbex(SecureIbex), + .WritebackStage(WritebackStage), + .RV32E(RV32E), + .CheriTBRE(1'b1), // Include it, but don't let it run (see assumption 6 below) + .CheriStkZ(1'b0), + .BranchTargetALU(1'b1), + .TSMapSize(TSMapSize), + .HeapBase(HeapBase) +) ibex_top_i(.*); + +// Core constraints +// 1. We do not allow going into debug mode +NotDebug: assume property (!ibex_top_i.u_ibex_core.debug_mode & !debug_req_i & !`CSR.csr_dbg_tclr_fault_o); +// 2. The boot address is constant +ConstantBoot: assume property (boot_addr_i == $past(boot_addr_i)); +// 3. Always fetch enable +FetchEnable: assume property (fetch_enable_i == IbexMuBiOn); +// 4. CHERI pure mode enable, with temporal safety +CheriConfig: assume property (cheri_pmode_i & cheri_tsafe_en_i); +// 5. Never start doing TBRE +TBRENoGo: assume property (~mmreg_corein_i[64]); // This is tbre_ctrl.go + +// See protocol/* for further assumptions + +///////////////////////////////// Declarations ///////////////////////////////// + +// Helpful macros to define each CSR and their types + +// Note: does not include mcycle, since it's not that meaningful to check it +`define X_EACH_CSR_C \ + `X(pcc) \ + `X(mtvec) \ + `X(mtdc) \ + `X(mscratchc) \ + `X(mepc) + +`define X_EACH_CSR_NC \ + `ifndef X_DISABLE_PC `X(pc) `endif \ + `X(priv) \ + `X(mstatus) \ + `X(mie) \ + `X(mcause) \ + `X(mtval) \ + `X(mscratch) \ + `X(mcounteren) \ + `X(nmi_mode) \ + `X(mstack) \ + `X(mstack_epc) \ + `X(mstack_cause) + + // `X(mshwmb) \ + // `X(mshwm) + +`define X_EACH_CSR `X_EACH_CSR_C `X_EACH_CSR_NC + +`define X_EACH_CSR_TYPED \ + logic [31:0] `X(pc); \ + t_Privilege `X(priv); \ + mstatus_t `X(mstatus); \ + logic [31:0] `X(mie); \ + logic [31:0] `X(mcause); \ + t_Capability `X(pcc); \ + logic [31:0] `X(mtval); \ + t_Capability `X(mtvec); \ + logic [31:0] `X(mscratch); \ + t_Capability `X(mepc); \ + t_Capability `X(mscratchc); \ + t_Capability `X(mtdc); \ + logic [63:0] `X(mcycle); \ + logic [31:0] `X(mcounteren); \ + logic `X(nmi_mode); \ + mstatus_t `X(mstack); \ + logic [31:0] `X(mstack_epc); \ + logic [31:0] `X(mstack_cause); + + // logic [31:0] `X(mshwmb); \ + // logic [31:0] `X(mshwm); \ + +////////////////////// Abstract State ////////////////////// +logic [31:0] pcc_address_d, pcc_address_q; + +t_Capability pre_regs[31:0]; +t_Capability pre_regs_cut[31:1]; // This is the direct input to the spec, it contains only at most 2 registers +logic [31:0] pre_nextpc; +logic [31:0] pre_mip; + +`define X(n) pre_``n +`X_EACH_CSR_TYPED +`undef X + +`define X(n) post_``n +`X_EACH_CSR_TYPED +`undef X +t_Capability post_trvk_regs[15:0]; + +////////////////////// Following ////////////////////// + +logic ex_is_wfi, ex_is_rtype, ex_is_div; +logic ex_is_btype, ex_is_jump; +logic ex_is_mem_cap_instr; +logic ex_is_mem_instr, ex_is_load_instr, ex_is_store_instr; +logic ex_has_branched_d, ex_has_branched_q; +logic ex_is_clc; +logic [31:0] ex_branch_dst; +assign ex_branch_dst = `CR.branch_decision ? `CR.branch_target_ex : pre_nextpc; + +logic outstanding_mem; +assign outstanding_mem = `ID.outstanding_load_wb_i || `ID.outstanding_store_wb_i; + +logic has_resp_waiting_q, has_resp_waiting_d; +assign has_resp_waiting_q = data_mem_assume.outstanding_reqs_q != 8'h0; +assign has_resp_waiting_d = data_mem_assume.outstanding_reqs != 8'h0; + +logic has_one_resp_waiting_q, has_one_resp_waiting_d; +assign has_one_resp_waiting_q = data_mem_assume.outstanding_reqs_q == 8'h1; +assign has_one_resp_waiting_d = data_mem_assume.outstanding_reqs == 8'h1; + +logic has_two_resp_waiting_q, has_two_resp_waiting_d; +assign has_two_resp_waiting_q = data_mem_assume.outstanding_reqs_q == 8'h2; +assign has_two_resp_waiting_d = data_mem_assume.outstanding_reqs == 8'h2; + +logic wbexc_is_load_instr, wbexc_is_store_instr; +logic wbexc_is_mem_instr; +logic wbexc_is_mem_cap_instr; + +logic [31:0] idex_compressed_instr; +logic idex_has_compressed_instr; + +logic wbexc_post_int_err; +t_Capability wbexc_post_wX; +logic [5:0] wbexc_post_wX_addr; +logic wbexc_post_wX_en; + +`define X(n) wbexc_post_``n +`X_EACH_CSR_TYPED +`undef X + +logic [31:0] wbexc_spec_mem_read_fst_rdata; +logic [31:0] wbexc_spec_mem_read_snd_rdata; +logic wbexc_spec_mem_read_tag; + +t_Capability wbexc_spec_mem_read_cap; +assign wbexc_spec_mem_read_cap = capBitsToCapability(wbexc_spec_mem_read_tag, {wbexc_spec_mem_read_snd_rdata, wbexc_spec_mem_read_fst_rdata}); +CapBoundBits wbexc_spec_mem_read_cap_bounds; +assign wbexc_spec_mem_read_cap_bounds = getCapBoundsBitsRaw( + wbexc_spec_mem_read_cap.E, + wbexc_spec_mem_read_cap.B, + wbexc_spec_mem_read_cap.T, + wbexc_spec_mem_read_cap.address +); + +logic wbexc_spec_mem_revoke_en; +logic[31:0] wbexc_spec_mem_revoke_addr; +logic wbexc_spec_mem_revoke; + + +`define X(n) wbexc_dut_post_``n +`X_EACH_CSR_TYPED +`undef X + +logic [31:0] wbexc_instr; // original potentially compressed +logic [31:0] wbexc_decompressed_instr; // post decompression +logic wbexc_is_compressed; + +logic [31:0] wbexc_pc; + +logic mem_gnt_fst_d; // We are having or have had the first gnt +logic mem_gnt_fst_q; // We have had the first gnt before now +logic mem_gnt_snd_d; // We are having or have had the second gnt +logic mem_gnt_snd_q; // We have had the second gnt before now + +logic mem_req_fst_d; // We are having the first req +logic mem_req_snd_d; // We are having the second req + +logic mem_resp_d; // We are having for have had an rvalid for EX +logic mem_resp_q; // We have had an rvalid for EX + +logic wbexc_mem_had_snd_req; // During ID/EX there was a second request + +logic lsu_had_first_resp; +assign lsu_had_first_resp = (`LSU.ls_fsm_cs == `LSU.WAIT_GNT && `LSU.split_misaligned_access) || (`LSU.lsu_is_cap_i && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP2); + +////////////////////// Wrap signals ////////////////////// + +logic spec_en; +logic has_spec_past; + +t_Capability spec_past_regs[31:0]; +logic [31:0] spec_past_has_reg; +`define X(n) spec_past_``n +`X_EACH_CSR_TYPED +`undef X + +////////////////////// Pipeline signals ////////////////////// + +logic ex_success; // Execute stage succeeding +logic ex_err; // Execute stage erroring +logic ex_kill; // Execute stage killed +logic exc_finishing; // Exception finishing +logic wb_finishing; // WB finishing +logic wbexc_finishing; // WB/EXC finishing +logic wbexc_exists; // Instruction in WB/EXC +logic wbexc_ex_err; // EXC has an execute error +logic wbexc_fetch_err; // EXC has a fetch error +logic wbexc_illegal; // EXC has an illegal instruction +logic wbexc_compressed_illegal; // EXC has an illegal instruction +logic wbexc_err; // EXC has an error +logic instr_will_progress; // Instruction will finish EX +logic wbexc_is_wfi; +logic wfi_will_finish; +logic wbexc_has_prev; // The next instruction should start with the state given +logic wbexc_csr_pipe_flush; +logic wbexc_handling_irq; + +////////////////////// CSR selection ////////////////////// + +// WBEXC CSR dut post state +`define X(n) wbexc_dut_cmp_post_``n +`X_EACH_CSR_TYPED +`undef X + +// WBEXC CSR spec post state +`define X(n) wbexc_spec_cmp_post_``n +`X_EACH_CSR_TYPED +`undef X + +////////////////////// Spec Post ////////////////////// + +t_Capability spec_post_wX; +logic [4:0] spec_post_wX_addr; +logic spec_post_wX_en; + +`define X(n) spec_post_``n +`X_EACH_CSR_TYPED +`undef X + +logic spec_int_err; +t_MainMode main_mode; + +logic spec_fetch_err; +assign spec_fetch_err = + (main_mode == MAIN_IFERR && spec_api_i.main_result == MAINRES_OK) || + spec_api_i.main_result == MAINRES_IFERR_1 || spec_api_i.main_result == MAINRES_IFERR_2; + +logic spec_mem_read; +logic spec_mem_read_snd; +logic [31:0] spec_mem_read_fst_addr; +logic [31:0] spec_mem_read_snd_addr; +logic [31:0] spec_mem_read_fst_rdata; // Undriven +logic [31:0] spec_mem_read_snd_rdata; // Undriven +logic spec_mem_read_tag; // Undriven + +t_Capability spec_mem_read_cap; +assign spec_mem_read_cap = capBitsToCapability(spec_mem_read_tag, {spec_mem_read_snd_rdata, spec_mem_read_fst_rdata}); + +logic spec_mem_revoke_en; +logic[31:0] spec_mem_revoke_addr; +logic spec_mem_revoke; // Undriven + +logic spec_mem_write; +logic spec_mem_write_snd; +logic [31:0] spec_mem_write_fst_addr; +logic [31:0] spec_mem_write_snd_addr; +logic [31:0] spec_mem_write_fst_wdata; +logic [31:0] spec_mem_write_snd_wdata; +logic [3:0] spec_mem_write_fst_be; +logic [3:0] spec_mem_write_snd_be; +logic spec_mem_write_tag; + +logic spec_mem_en; +logic spec_mem_en_snd; +logic [31:0] spec_mem_fst_addr; +logic [31:0] spec_mem_snd_addr; + +assign spec_mem_en = spec_mem_read | spec_mem_write; +assign spec_mem_en_snd = spec_mem_read_snd | spec_mem_write_snd; +assign spec_mem_fst_addr = spec_mem_read ? spec_mem_read_fst_addr : spec_mem_write_fst_addr; +assign spec_mem_snd_addr = spec_mem_read ? spec_mem_read_snd_addr : spec_mem_write_snd_addr; + +logic [31:0] fst_mask, snd_mask; +assign fst_mask = { + {8{spec_mem_write_fst_be[3]}}, {8{spec_mem_write_fst_be[2]}}, + {8{spec_mem_write_fst_be[1]}}, {8{spec_mem_write_fst_be[0]}} +}; +assign snd_mask = { + {8{spec_mem_write_snd_be[3]}}, {8{spec_mem_write_snd_be[2]}}, + {8{spec_mem_write_snd_be[1]}}, {8{spec_mem_write_snd_be[0]}} +}; + +logic fst_mem_cmp; +assign fst_mem_cmp = (spec_mem_write == data_we_o) && (spec_mem_read == ~data_we_o) && + (data_addr_o == spec_mem_fst_addr) && + (data_we_o -> + (data_wdata_o & fst_mask) == (spec_mem_write_fst_wdata & fst_mask)); +logic snd_mem_cmp; +assign snd_mem_cmp = (spec_mem_write_snd == data_we_o) && (spec_mem_read_snd == ~data_we_o) && + (data_addr_o == spec_mem_snd_addr) && + (data_we_o -> + (data_wdata_o & snd_mask) == (spec_mem_write_snd_wdata & snd_mask)); + +////////////////////// Compare ////////////////////// + +logic addr_match; // Register write index match +logic data_match; // Register write data match +logic nowrite; // Neither spec nor dut writing to RF +logic csrs_match; // CSR match +logic csrs_didnt_change; +logic pc_match; // PC match +logic finishing_executed; // Finishing normal case + +`define INSTR `CR.instr_rdata_id + +logic wbexc_is_checkable_csr; +logic ex_is_checkable_csr; +assign ex_is_checkable_csr = ~( + // Performance counters and such, not specified in Sail + ((CSR_MHPMCOUNTER3H <= `CSR_ADDR) && (`CSR_ADDR <= CSR_MHPMCOUNTER31H)) | + ((CSR_MHPMCOUNTER3 <= `CSR_ADDR) && (`CSR_ADDR <= CSR_MHPMCOUNTER31)) | + ((CSR_MHPMEVENT3 <= `CSR_ADDR) && (`CSR_ADDR <= CSR_MHPMEVENT31)) | + (`CSR_ADDR == CSR_MCYCLE) | (`CSR_ADDR == CSR_MCYCLEH) | + (`CSR_ADDR == CSR_MCOUNTINHIBIT) | + (`CSR_ADDR == CSR_MINSTRET) | (`CSR_ADDR == CSR_MINSTRETH) | + + // Ibex but not Sail: + (`CSR_ADDR == CSR_SECURESEED) | + (`CSR_ADDR == CSR_CPUCTRL) | + (`CSR_ADDR == CSR_CDBG_CTRL) | + + // Sail but not Ibex: + (`CSR_ADDR == 12'h30a) | // MENVCFG + (`CSR_ADDR == 12'h31a) | // MENVCFGH + (`CSR_ADDR == 12'h310) | // MSTATUSH + (`CSR_ADDR == 12'hF15) | // MCONFIGPTR + + // Specified to be illegal in Sail but isn't in Ibex: + (CSR_PMPCFG0 <= `CSR_ADDR && `CSR_ADDR <= CSR_PMPCFG3) | + (CSR_PMPADDR0 <= `CSR_ADDR && `CSR_ADDR <= CSR_PMPADDR15) | + + // We don't verify stkz + (`CSR_ADDR == CSR_MSHWM) | (`CSR_ADDR == CSR_MSHWMB) +); + +////////////////////// Decompression Invariant Defs ////////////////////// + +logic [31:0] decompressed_instr; +logic decompressed_instr_illegal; +ibex_compressed_decoder decompression_assertion_decoder( + .clk_i, + .rst_ni, + .valid_i(1'b1), + .instr_i(idex_compressed_instr), + .instr_o(decompressed_instr), + .is_compressed_o(), + .illegal_instr_o(decompressed_instr_illegal), + .cheri_pmode_i +); + +logic [31:0] decompressed_instr_2; +logic decompressed_instr_illegal_2; +ibex_compressed_decoder decompression_assertion_decoder_2( + .clk_i, + .rst_ni, + .valid_i(1'b1), + .instr_i(wbexc_instr), + .instr_o(decompressed_instr_2), + .is_compressed_o(wbexc_is_compressed), + .illegal_instr_o(decompressed_instr_illegal_2), + .cheri_pmode_i +); + +////////////////////// IRQ + Memory Protocols ////////////////////// +`include "protocol/irqs.sv" +`include "protocol/mem.sv" + +////////////////////// Following ////////////////////// +`include "peek/pcc.sv" // PCC.address +`include "peek/abs.sv" // Abstract state +`include "peek/capdti.sv" // Capability DTI +`include "peek/mem.sv" // Memory tracking +`include "peek/follower.sv" // Pipeline follower +`include "spec_instance.sv" // Instantiate the specification + +////////////////////// Proof helpers /////////////////////// +`include "peek/compare_helper.sv" + +////////////////////// Proof ////////////////////// +`undef INSTR +`define INSTR wbexc_decompressed_instr +`include "../build/psgen.sv" + +endmodule diff --git a/vendor/lowrisc_ibex/dv/formal/ibex_formal.core b/vendor/lowrisc_ibex/dv/formal/ibex_formal.core new file mode 100644 index 000000000..c07a71ed6 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/ibex_formal.core @@ -0,0 +1,32 @@ +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:ibex:ibex_formal:0.1" +description: "Ibex, a small RV32 CPU core" + +filesets: + files_rtl: + depend: + - lowrisc:ibex:ibex_pkg + - lowrisc:ibex:ibex_core + - lowrisc:prim:buf + - lowrisc:prim:clock_gating + - lowrisc:prim:secded + - lowrisc:prim:assert + - lowrisc:prim:ram_1p_pkg + - lowrisc:prim_generic:buf + - lowrisc:prim_generic:clock_gating + files: + - ../../rtl/ibex_register_file_ff.sv # generic FF-based + - ../../rtl/ibex_register_file_fpga.sv # FPGA + - ../../rtl/ibex_register_file_latch.sv # ASIC + - ../../rtl/cheri_regfile.sv # generic FF-based + - ../../rtl/ibex_top.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl + toplevel: ibex_top diff --git a/vendor/lowrisc_ibex/dv/formal/patches/ibex_top.diff b/vendor/lowrisc_ibex/dv/formal/patches/ibex_top.diff new file mode 100644 index 000000000..5558311fa --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/patches/ibex_top.diff @@ -0,0 +1,31 @@ +--- build/fusesoc/rtl/ibex_top.sv 2024-08-25 12:49:31.975238123 +0100 ++++ build/fusesoc/rtl/ibex_top.sv 2024-08-25 12:51:45.786743599 +0100 +@@ -166,7 +166,7 @@ + ); + + localparam bit Lockstep = SecureIbex; +- localparam bit ResetAll = Lockstep; ++ localparam bit ResetAll = 1; + localparam bit DummyInstructions = SecureIbex; + localparam bit RegFileECC = SecureIbex; + localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; +@@ -244,12 +244,13 @@ + assign clock_en = core_busy_q | debug_req_i | irq_pending | irq_nm_i; + assign core_sleep_o = ~clock_en; + +- prim_clock_gating core_clock_gate_i ( +- .clk_i (clk_i), +- .en_i (clock_en), +- .test_en_i(test_en_i), +- .clk_o (clk) +- ); ++ assign clk = clk_i; ++ // prim_clock_gating core_clock_gate_i ( ++ // .clk_i (clk_i), ++ // .en_i (clock_en), ++ // .test_en_i(test_en_i), ++ // .clk_o (clk) ++ // ); + + //////////////////////// + // Core instantiation // diff --git a/vendor/lowrisc_ibex/dv/formal/poetry.lock b/vendor/lowrisc_ibex/dv/formal/poetry.lock new file mode 100644 index 000000000..adb6b3b35 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/poetry.lock @@ -0,0 +1,521 @@ +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. + +[[package]] +name = "anytree" +version = "2.8.0" +description = "Powerful and Lightweight Python Tree Data Structure.." +optional = false +python-versions = "*" +files = [ + {file = "anytree-2.8.0-py2.py3-none-any.whl", hash = "sha256:14c55ac77492b11532395049a03b773d14c7e30b22aa012e337b1e983de31521"}, + {file = "anytree-2.8.0.tar.gz", hash = "sha256:3f0f93f355a91bc3e6245319bf4c1d50e3416cc7a35cc1133c1ff38306bbccab"}, +] + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +dev = ["check-manifest"] +test = ["coverage"] + +[[package]] +name = "attrs" +version = "24.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, +] + +[package.extras] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] + +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +optional = false +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + +[[package]] +name = "edalize" +version = "0.4.0" +description = "Library for interfacing EDA tools such as simulators, linters or synthesis tools, using a common interface" +optional = false +python-versions = ">=3.6, <4" +files = [] +develop = false + +[package.dependencies] +Jinja2 = ">=3" + +[package.extras] +reporting = ["pandas", "pyparsing"] + +[package.source] +type = "git" +url = "https://github.com/lowRISC/edalize.git" +reference = "v0.4.0" +resolved_reference = "2a70c4421db186b4ec91c770addc89ec83f3818b" + +[[package]] +name = "fusesoc" +version = "0.4" +description = "FuseSoC is a package manager and a set of build tools for HDL (Hardware Description Language) code." +optional = false +python-versions = ">=3.6, <4" +files = [] +develop = false + +[package.dependencies] +edalize = ">=0.2.3" +pyparsing = "*" +pyyaml = "*" +simplesat = ">=0.8.0" + +[package.source] +type = "git" +url = "https://github.com/lowRISC/fusesoc.git" +reference = "ot-0.4" +resolved_reference = "e20b92898f6d14574cca8d636a841845b0817585" + +[[package]] +name = "hjson" +version = "3.1.0" +description = "Hjson, a user interface for JSON." +optional = false +python-versions = "*" +files = [ + {file = "hjson-3.1.0-py3-none-any.whl", hash = "sha256:65713cdcf13214fb554eb8b4ef803419733f4f5e551047c9b711098ab7186b89"}, + {file = "hjson-3.1.0.tar.gz", hash = "sha256:55af475a27cf83a7969c808399d7bccdec8fb836a07ddbd574587593b9cdcf75"}, +] + +[[package]] +name = "jinja2" +version = "3.1.5" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, + {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.23.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "mako" +version = "1.2.2" +description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Mako-1.2.2-py3-none-any.whl", hash = "sha256:8efcb8004681b5f71d09c983ad5a9e6f5c40601a6ec469148753292abc0da534"}, + {file = "Mako-1.2.2.tar.gz", hash = "sha256:3724869b363ba630a272a5f89f68c070352137b8fd1757650017b7e06fda163f"}, +] + +[package.dependencies] +MarkupSafe = ">=0.9.2" + +[package.extras] +babel = ["Babel"] +lingua = ["lingua"] +testing = ["pytest"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "okonomiyaki" +version = "1.4.0" +description = "Self-contained library to deal with metadata in Enthought-specific egg and runtime archives" +optional = false +python-versions = ">=2.7" +files = [ + {file = "okonomiyaki-1.4.0-py2.py3-none-any.whl", hash = "sha256:174af185f866fc42fdb58b2d6c7107d870f795e3f404b9c6278f8e62f87f0f83"}, + {file = "okonomiyaki-1.4.0.tar.gz", hash = "sha256:508008004a12e09f565d8b4e4145bd7500787fdd6810d898fdc8e5c61a3f41e5"}, +] + +[package.dependencies] +attrs = ">=16.1.0" +distro = {version = "*", markers = "sys_platform == \"linux\" or sys_platform == \"linux2\""} +jsonschema = ">=2.5.1" +six = ">=1.9.0" +zipfile2 = ">=0.0.12" + +[package.extras] +test = ["distro", "haas", "hypothesis", "mock", "packaging (>=20.0)", "testfixtures"] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "rpds-py" +version = "0.20.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, + {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, + {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, + {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, + {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, + {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, + {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, + {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, + {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, + {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, + {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, + {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, + {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, + {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, +] + +[[package]] +name = "simplesat" +version = "0.8.2" +description = "Simple SAT solvers for use in Enstaller" +optional = false +python-versions = "*" +files = [ + {file = "simplesat-0.8.2-py2.py3-none-any.whl", hash = "sha256:76dd637db54c998badb988baafbc2bd4cc6689364580588487bc2634a6ab55fd"}, + {file = "simplesat-0.8.2.tar.gz", hash = "sha256:1943f32735b03b048e20953a0145b2b61d2eb7a9dcc471a74f214afe9fa8d858"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +okonomiyaki = ">=0.16.6" +six = ">=1.10.0" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "wheel" +version = "0.41.2" +description = "A built-package format for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "wheel-0.41.2-py3-none-any.whl", hash = "sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8"}, + {file = "wheel-0.41.2.tar.gz", hash = "sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)", "setuptools (>=65)"] + +[[package]] +name = "zipfile2" +version = "0.0.12" +description = "An improved ZipFile class." +optional = false +python-versions = "*" +files = [ + {file = "zipfile2-0.0.12-py2.py3-none-any.whl", hash = "sha256:b9adf577d825461480e485027116c035f666b72ac3911af71aa93da6e0579eb8"}, + {file = "zipfile2-0.0.12.tar.gz", hash = "sha256:7376f7c968717ac895ef862da913e790cf1b518caf56c4822c04684c46a8a608"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "14a00393e1cccbe6d5a88ef3ca73455868d56017f41bda6075f4fa73b2862d47" diff --git a/vendor/lowrisc_ibex/dv/formal/pyproject.toml b/vendor/lowrisc_ibex/dv/formal/pyproject.toml new file mode 100644 index 000000000..a4c2df9f1 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/pyproject.toml @@ -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 + +[tool.poetry] +name = "ibex" +version = "0.0.0" +description = "Ibex" +authors = [] +license = "Apache 2.0" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +packaging = "23.1" +anytree = "2.8.0" +hjson = "3.1.0" +mako = "1.2.2" +pyyaml = "6.0" +wheel = "0.41.2" +edalize = { git = "https://github.com/lowRISC/edalize.git", tag = "v0.4.0"} +fusesoc = { git = "https://github.com/lowRISC/fusesoc.git", tag = "ot-0.4" } + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/vendor/lowrisc_ibex/dv/formal/spec/cheri.sv b/vendor/lowrisc_ibex/dv/formal/spec/cheri.sv new file mode 100644 index 000000000..14b7073dc --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/cheri.sv @@ -0,0 +1,132 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +import cheri_pkg::*; + +function automatic t_Capability dataCap(logic [31:0] address); + return '{ + B: '0, + E: '0, + T: '0, + access_system_regs: '0, + address: address, + zglobal: '0, + otype: '0, + perm_user0: '0, + permit_execute: '0, + permit_load: '0, + permit_load_global: '0, + permit_load_mutable: '0, + permit_load_store_cap: '0, + permit_seal: '0, + permit_store: '0, + permit_store_local_cap: '0, + permit_unseal: '0, + reserved: '0, + tag: '0 + }; +endfunction + +function automatic t_Capability nullCap(); + return dataCap(32'b0); +endfunction + +function automatic t_Capability encodeDecodePermsOf(t_Capability capability); + return encCapabilityToCapability(capability.tag, capToEncCap(capability)); +endfunction + +function automatic t_Capability regcap2sail(reg_cap_t capability, logic [31:0] address); + logic [63:0] bits; + bits = {reg2memcap_fmt0(capability)[31:0], address}; + return capBitsToCapability(capability.valid, bits); +endfunction + +function automatic t_Capability fullcap2sail(full_cap_t capability, logic [31:0] address); + return regcap2sail(full2regcap(capability), address); +endfunction + +function automatic t_Capability pcc2sail(pcc_cap_t capability, logic [31:0] address); + return fullcap2sail(pcc2fullcap(capability), address); +endfunction + +// 'at least as strict', i.e. the DUT may clear a tag the spec wouldn't +function automatic logic alas(t_Capability spec, t_Capability dut); + if (!dut.tag) spec.tag = 1'b0; + return dut == spec; +endfunction + +function automatic t_Capability revoke(t_Capability cap, logic strip); + if (strip) cap.tag = 1'b0; + return cap; +endfunction + +function automatic t_Capability onlySealingPerms(t_Capability cap); + cap.access_system_regs = '0; + cap.zglobal = '0; + cap.permit_execute = '0; + cap.permit_load = '0; + cap.permit_load_global = '0; + cap.permit_load_mutable = '0; + cap.permit_load_store_cap = '0; + cap.permit_store = '0; + cap.permit_store_local_cap = '0; + return cap; +endfunction + +// The following are used only by the DTI: + +typedef struct packed { + logic [31:0] base; + logic [32:0] top; +} CapBoundBits; + +typedef struct packed { + logic base_cor; + logic [1:0] top_cor; +} CapBoundCorBits; + +function automatic CapBoundBits getCapBoundsBitsRaw(logic [4:0] E, logic [8:0] B, logic [8:0] T, logic [31:0] a); + logic[TOP_W-1:0] a_mid = {a >> E}[TOP_W-1:0]; + logic a_hi = a_mid < B; + logic t_hi = T < B; + logic [31:0] base_cor = 0 - a_hi; + logic [31:0] top_cor = t_hi - a_hi; + logic [31:0] a_top = a >> (E + TOP_W); + + logic [31:0] base = {a_top + signed'(base_cor), B}[ADDR_W-1:0]; + logic[ADDR_W:0] top = {a_top + signed'(top_cor), T}[ADDR_W:0]; + base <<= E; + top <<= E; + + return '{base, top}; +endfunction + +function automatic CapBoundCorBits getCapBoundsCorBitsRaw(logic [4:0] E, logic [8:0] B, logic [8:0] T, logic [31:0] a); + logic [1:0] base2, top2; + + logic[TOP_W-1:0] a_mid = {a >> E}[TOP_W-1:0]; + logic a_hi = a_mid < B; + logic t_hi = T < B; + logic base_cor = a_hi; + logic [31:0] top_cor = t_hi - a_hi; + + return '{base_cor, top_cor[1:0]}; +endfunction + +function automatic logic[1:0] getRegCapTopCor(reg_cap_t c, logic [31:0] a); + logic[TOP_W-1:0] a_mid = {a >> c.exp}[TOP_W-1:0]; + logic a_hi = a_mid < c.base; + logic t_hi = c.top < c.base; + logic [31:0] top_cor = t_hi - a_hi; + return top_cor; +endfunction + +function automatic logic getRegCapBaseCor(reg_cap_t c, logic [31:0] a); + logic[TOP_W-1:0] a_mid = {a >> c.exp}[TOP_W-1:0]; + logic a_hi = a_mid < c.base; + logic t_hi = c.top < c.base; + return a_hi; +endfunction diff --git a/vendor/lowrisc_ibex/dv/formal/spec/cull_funcs.py b/vendor/lowrisc_ibex/dv/formal/spec/cull_funcs.py new file mode 100644 index 000000000..584c175c3 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/cull_funcs.py @@ -0,0 +1,24 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +import sys +import re + +names = sys.argv[1:] + +with open("build/ibexspec.sv", "r") as f: + c = f.read() + +for func_name in names: + m = re.search(r"^(\s*)function automatic .+ " + func_name + r"\(.*\);", c, re.MULTILINE) + assert m is not None + end = c.index("endfunction", m.start()) + assert end >= 0 + + c = c[0:m.start()] + c[end + 11:] + +with open("build/ibexspec.sv", "w") as f: + f.write(c) diff --git a/vendor/lowrisc_ibex/dv/formal/spec/extract_funcs.py b/vendor/lowrisc_ibex/dv/formal/spec/extract_funcs.py new file mode 100644 index 000000000..1c960a15c --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/extract_funcs.py @@ -0,0 +1,33 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +import sys +import re + +names = sys.argv[1:] + +with open("build/ibexspec.sv", "r") as f: + c = f.read() + +constants = { + "cap_max_E_bits": "5'h18" +} + +for func_name in names: + m = re.search(r"^(\s*)function automatic .+ " + func_name + r"\(.*\);", c, re.MULTILINE) + assert m is not None + end = c.index("endfunction", m.start()) + assert end >= 0 + + func = c[m.start():end + 11][1:] + func = "\n".join(line[len(m[1]) - 1:] for line in func.split("\n")) + + for k in constants: + func = re.sub(r"\b" + k + r"\b", constants[k], func) + func = func.replace("sail_reached_unreachable = 1;", "").replace("sail_reached_unreachable_loc = `__LINE__;", "") + + print(func) + print() diff --git a/vendor/lowrisc_ibex/dv/formal/spec/fix_pmp_bug.py b/vendor/lowrisc_ibex/dv/formal/spec/fix_pmp_bug.py new file mode 100644 index 000000000..e4b567836 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/fix_pmp_bug.py @@ -0,0 +1,34 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +''' +Fixes an issue where the Sail -> SV compiler references t_Pmpcfg_ent (in sail_genlib_ibexspec.sv) before it defines it (in ibexspec.sv) +by just moving that definition. +''' + +S = """ +typedef struct { + logic [7:0] bits; +} t_Pmpcfg_ent; +""" + +T = """ +typedef logic [127:0] sail_int; +""" + +with open("build/ibexspec.sv", "r") as f: + c = f.read() + +c = c.replace(S, "") + +with open("build/ibexspec.sv", "w") as f: + f.write(c) + +with open("build/sail_genlib_ibexspec.sv", "r") as f: + c = f.read() + +with open("build/sail_genlib_ibexspec.sv", "w") as f: + f.write(S + "\n" + c) diff --git a/vendor/lowrisc_ibex/dv/formal/spec/main.sail b/vendor/lowrisc_ibex/dv/formal/spec/main.sail new file mode 100644 index 000000000..fa36ab0a3 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/main.sail @@ -0,0 +1,112 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +This file contains the main function which is 'invoked' by the system verilog. +main is equivalent to the Sail step function, it has some differences however: +1. It uses the decompress function as created by gen_compressed_shortcircuit.py +2. It can operate in one of three modes, based on what it has been told to do by the SV. + This is done for a couple of reasons: + 1. It's difficult to compare IRQ handling, since ibex takes them later than the Sail would. This is OK since it's not really + fair to enforce that IRQs are handled between any two specific instructions, so long as it is eventually. + 2. The three modes are a useful case analysis we can make. This means that to prove correctness of an I-Type instruction, for example, we + can more easily seperate out the check for instruction fetch correctness, which makes things faster and avoids repeated work. +*/ + +union FetchResult = { + F_Ext_Error : ext_fetch_addr_error, /* For extensions */ + F_Base : word, /* Base ISA */ + F_RVC : half, /* Compressed ISA */ + F_Error : (ExceptionType, xlenbits) /* standard exception and PC */ +} + +function isRVC(h : bits(16)) -> bool = ~ (h[1 .. 0] == 0b11) + +// modified version of what one can find in riscv_fetch.sail +val altFetch : (bits(16), bits(16)) -> FetchResult +function altFetch(ilo: bits(16), ihi: bits(16)) -> FetchResult = + match ext_fetch_check_pc(PC, PC) { + Ext_FetchAddr_Error(e) => F_Ext_Error(e), + Ext_FetchAddr_OK(use_pc) => { + if (use_pc[0] != bitzero | (use_pc[1] != bitzero & (~ (haveRVC())))) + then F_Error(E_Fetch_Addr_Align(), PC) + else if isRVC(ilo) + then F_RVC(ilo) + else { + /* fetch PC check for the next instruction granule */ + PC_hi : xlenbits = PC + 2; + match ext_fetch_check_pc(PC, PC_hi) { + Ext_FetchAddr_Error(e) => F_Ext_Error(e), + Ext_FetchAddr_OK(use_pc_hi) => F_Base(append(ihi, ilo)) + } + } + } + } + + +enum MainMode = { MAIN_IDEX, MAIN_IFERR, MAIN_IRQ } +enum MainResult = { MAINRES_OK, MAINRES_IFERR_1, MAINRES_IFERR_2, MAINRES_NOIFERR, MAINRES_IRQ, MAINRES_NOIRQ } + +function main(insn_bits, mode) : (bits(32), MainMode) -> MainResult = { + let insn = if isRVC(insn_bits[15..0]) then { + instbits = 0x0000 @ insn_bits[15..0]; + ext_decode_compressed(insn_bits[15..0]) + } else { + instbits = insn_bits; + ext_decode(insn_bits) + }; + + let irq = dispatchInterrupt(cur_privilege); + let f : FetchResult = altFetch(insn_bits[15..0], insn_bits[31..16]); + + let res : MainResult = match mode { + MAIN_IDEX => { + match decompress(insn) { + Some(decompressed) => { + let _ = execute(decompressed); + }, + None() => () + }; + + match f { + F_Ext_Error(e) => MAINRES_IFERR_1, + F_Error(e, addr) => MAINRES_IFERR_2, + F_RVC(h) => MAINRES_OK, + F_Base(w) => MAINRES_OK + } + }, + MAIN_IFERR => { + match f { + F_Ext_Error(e) => { + ext_handle_fetch_check_error(e); + MAINRES_OK + }, + F_Error(e, addr) => { + handle_mem_exception(addr, e); + MAINRES_OK + }, + F_RVC(h) => MAINRES_NOIFERR, + F_Base(w) => MAINRES_NOIFERR + } + }, + MAIN_IRQ => { + match irq { + Some(intr, fast, priv) => { + handle_interrupt(intr, fast, priv); + MAINRES_OK + }, + None() => MAINRES_NOIRQ + } + } + }; + + // FIXME: This is a bit unsatisfying. https://github.com/microsoft/cheriot-ibex/issues/11#issuecomment-2057580605 + if nextPCC.E == cap_max_E_bits then { + nextPCC.B[8] = bitzero; + }; + + res +} diff --git a/vendor/lowrisc_ibex/dv/formal/spec/spec_api.sv b/vendor/lowrisc_ibex/dv/formal/spec/spec_api.sv new file mode 100644 index 000000000..feae038f2 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/spec_api.sv @@ -0,0 +1,434 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +typedef struct packed { + logic mie; + logic mpie; + logic tw; + logic mprv; + logic [1:0] mpp; +} mstatus_t; + +module spec_api #( + parameter int unsigned NREGS = 32, + parameter int unsigned PMPNumRegions = 4 +) ( + input t_MainMode main_mode, + + input t_Capability regs_i[31:1], + + output logic wx_en_o, + output t_Capability wx_o, + output logic [4:0] wx_addr_o, + + input logic [31:0] nextpc_i, + input logic [31:0] pc_i, + output logic [31:0] pc_o, + + input logic [31:0] misa_i, + input logic [31:0] mip_i, + + input logic nmi_i, + input logic nmi_mode_i, + output logic nmi_mode_o, + input mstatus_t mstack_i, + output mstatus_t mstack_o, + input logic [31:0] mstack_cause_i, + output logic [31:0] mstack_cause_o, + input logic [31:0] mstack_epc_i, + output logic [31:0] mstack_epc_o, + + input logic [31:0] mvendor_id_i, + input logic [31:0] march_id_i, + input logic [31:0] mimp_id_i, + input logic [31:0] mhart_id_i, + input logic [31:0] mconfigptr_i, + + input logic [31:0] mseccfg_i, + output logic [31:0] mseccfg_o, + input logic [7:0] pmp_cfg_i[PMPNumRegions], + output logic [7:0] pmp_cfg_o[PMPNumRegions], + input logic [31:0] pmp_addr_i[PMPNumRegions], + output logic [31:0] pmp_addr_o[PMPNumRegions], + + input logic [31:0] mie_i, + output logic [31:0] mie_o, + input t_Privilege priv_i, + output t_Privilege priv_o, + input mstatus_t mstatus_i, + output mstatus_t mstatus_o, + input logic [31:0] mcause_i, + output logic [31:0] mcause_o, + input logic [63:0] mcycle_i, + output logic [63:0] mcycle_o, + input logic [31:0] mtval_i, + output logic [31:0] mtval_o, + input t_Capability mtvec_i, + output t_Capability mtvec_o, + input logic [31:0] mscratch_i, + output logic [31:0] mscratch_o, + input t_Capability mepc_i, + output t_Capability mepc_o, + input logic [31:0] mshwmb_i, + output logic [31:0] mshwmb_o, + input logic [31:0] mshwm_i, + output logic [31:0] mshwm_o, + input logic [31:0] mcounteren_i, + output logic [31:0] mcounteren_o, + input t_Capability pcc_i, + output t_Capability pcc_o, + input t_Capability mscratchc_i, + output t_Capability mscratchc_o, + input t_Capability mtdc_i, + output t_Capability mtdc_o, + + input logic [31:0] insn_bits, + output logic int_err_o, + + output logic mem_read_o, + output logic mem_read_snd_gran_o, + output logic[31:0] mem_read_fst_addr_o, + output logic[31:0] mem_read_snd_addr_o, + input logic[31:0] mem_read_fst_rdata_i, + input logic[31:0] mem_read_snd_rdata_i, + input logic mem_read_tag_i, + + output logic mem_revoke_en_o, + output logic[31:0] mem_revoke_granule_o, + input logic mem_revoke_i, + + output logic mem_write_o, + output logic mem_write_snd_gran_o, + output logic[31:0] mem_write_fst_addr_o, + output logic[31:0] mem_write_snd_addr_o, + output logic[31:0] mem_write_fst_wdata_o, + output logic[31:0] mem_write_snd_wdata_o, + output logic [3:0] mem_write_fst_be_o, + output logic [3:0] mem_write_snd_be_o, + output logic mem_write_tag_o +); + +bit wC_sail_invoke[0:0]; +logic [63:0] wC_sail_invoke_arg_0[0:0]; +t_Capability wC_sail_invoke_arg_1[0:0]; +logic wX_sail_invoke[0:0]; +logic [63:0] wX_sail_invoke_arg_0[0:0]; +logic [31:0] wX_sail_invoke_arg_1[0:0]; +assign wx_en_o = wX_sail_invoke[0] | wC_sail_invoke[0]; +assign wx_addr_o = wX_sail_invoke[0] ? wX_sail_invoke_arg_0[0][4:0] : wC_sail_invoke_arg_0[0][4:0]; +assign wx_o = wX_sail_invoke[0] ? dataCap(wX_sail_invoke_arg_1[0]) : encodeDecodePermsOf(wC_sail_invoke_arg_1[0]); + +logic write_ram_sail_invoke[1:0]; +logic [31:0] write_ram_sail_invoke_arg_1[1:0]; +logic [31:0] write_ram_sail_invoke_arg_2[1:0]; +logic [3:0] write_ram_sail_invoke_arg_3[1:0]; +assign mem_write_o = write_ram_sail_invoke[0]; +assign mem_write_snd_gran_o = write_ram_sail_invoke[1]; +assign mem_write_fst_addr_o = write_ram_sail_invoke_arg_1[0]; +assign mem_write_snd_addr_o = write_ram_sail_invoke_arg_1[1]; +assign mem_write_fst_wdata_o = write_ram_sail_invoke_arg_2[0]; +assign mem_write_snd_wdata_o = write_ram_sail_invoke_arg_2[1]; +assign mem_write_fst_be_o = write_ram_sail_invoke_arg_3[0]; +assign mem_write_snd_be_o = write_ram_sail_invoke_arg_3[1]; + +logic read_ram_sail_invoke[1:0]; +logic [31:0] read_ram_sail_invoke_ret[1:0]; +logic [31:0] read_ram_sail_invoke_arg_1[1:0]; +assign mem_read_o = read_ram_sail_invoke[0]; +assign mem_read_snd_gran_o = read_ram_sail_invoke[1]; +assign mem_read_fst_addr_o = read_ram_sail_invoke_arg_1[0]; +assign mem_read_snd_addr_o = read_ram_sail_invoke_arg_1[1]; +assign read_ram_sail_invoke_ret[0] = mem_read_fst_rdata_i; +assign read_ram_sail_invoke_ret[1] = mem_read_snd_rdata_i; + + +bit mem_read_cap_revoked_sail_invoke[0:0]; +bit mem_read_cap_revoked_sail_invoke_ret[0:0]; +logic [31:0] mem_read_cap_revoked_sail_invoke_arg_0[0:0]; +assign mem_revoke_en_o = mem_read_cap_revoked_sail_invoke[0]; +assign mem_revoke_granule_o = mem_read_cap_revoked_sail_invoke_arg_0[0]; +assign mem_read_cap_revoked_sail_invoke_ret[0] = mem_revoke_i; + +bit __WriteRAM_Meta_sail_invoke_arg_2[0:0]; +assign mem_write_tag_o = __WriteRAM_Meta_sail_invoke_arg_2[0]; +bit __ReadRAM_Meta_sail_invoke_ret[0:0]; +assign __ReadRAM_Meta_sail_invoke_ret[0] = mem_read_tag_i; + +t_MainResult main_result; + +t_Mstatus mstatus_out; +assign mstatus_o.mie = mstatus_out.bits[3]; +assign mstatus_o.mpie = mstatus_out.bits[7]; +assign mstatus_o.tw = mstatus_out.bits[21]; +assign mstatus_o.mprv = mstatus_out.bits[17]; +assign mstatus_o.mpp = mstatus_out.bits[12:11]; + +t_Mcause mcause_out; +assign mcause_o = mcause_out.bits; + +t_Minterrupts mie_out; +assign mie_o = mie_out.bits; + +t_Counteren mcounteren_out; +assign mcounteren_o = mcounteren_out.bits; + +t_Pmpcfg_ent pmpcfg_n_in[63:0]; +logic [31:0] pmpaddr_n_in[63:0]; +t_Pmpcfg_ent pmpcfg_n_out[63:0]; +logic [31:0] pmpaddr_n_out[63:0]; +for (genvar i = 0; i < 64; i++) begin: g_pmp_bind + if (i < PMPNumRegions) begin: g_pmp_bind_real + assign pmpcfg_n_in[i] = '{bits: pmp_cfg_i[i]}; + assign pmpaddr_n_in[i] = pmp_addr_i[i]; + + assign pmp_cfg_o[i] = pmpcfg_n_out[i].bits[7:0]; + assign pmp_addr_o[i] = pmpaddr_n_out[i]; + end else begin: g_pmp_bind_zero + // These shouldn't ever be used anyway + assign pmpcfg_n_in[i] = '{bits: 0}; + assign pmpaddr_n_in[i] = 0; + end +end + +t_Mseccfg_ent mseccfg_out; +assign mseccfg_o = mseccfg_out.bits; + +t_Mcause mstack_cause_out; +t_Mstatus mstack_out; +assign mstack_cause_o = mstack_cause_out.bits; +assign mstack_o.mie = mstack_out.bits[3]; +assign mstack_o.mpie = mstack_out.bits[7]; +assign mstack_o.tw = mstack_out.bits[21]; +assign mstack_o.mprv = mstack_out.bits[17]; +assign mstack_o.mpp = mstack_out.bits[12:11]; + +sail_ibexspec spec_i( + .cur_inst_in(insn_bits), + .cur_inst_out(), + .cur_privilege_in(priv_i), + .cur_privilege_out(priv_o), + .instbits_in(insn_bits), + .instbits_out(), + .marchid_in(march_id_i), + .marchid_out(), + .mcause_in('{bits: mcause_i}), + .mcause_out, + .mconfigptr_in(mconfigptr_i), + .mconfigptr_out(), + .mcounteren_in('{ bits: mcounteren_i }), + .mcounteren_out, + .mcountinhibit_in(), + .mcountinhibit_out(), + .mcycle_in(mcycle_i), + .mcycle_out(mcycle_o), + .medeleg_in('{bits: 32'h0}), + .medeleg_out(), + .menvcfg_in('{bits: 32'h0}), + .menvcfg_out(), + .MEPCC_in(mepc_i), + .MEPCC_out(mepc_o), + .mhartid_in(mhart_id_i), + .mhartid_out(), + .mideleg_in(), + .mideleg_out(), + .mie_in('{bits: mie_i}), + .mie_out, + .mimpid_in(mimp_id_i), + .mimpid_out(), + .minstret_in(), + .minstret_out(), + .minstret_increment_in(), + .minstret_increment_out(), + .mip_in('{bits: mip_i}), + .mip_out(), + .nmi_in(nmi_i), + .nmi_mode_in(nmi_mode_i), + .nmi_mode_out(nmi_mode_o), + .mstack_in('{bits: + (32'(mstack_i.mie) << 3) | + (32'(mstack_i.mpie) << 7) | + (32'(mstack_i.tw) << 21) | + (32'(mstack_i.mprv) << 17) | + (32'(mstack_i.mpp) << 11) + }), + .mstack_out, + .mstack_epc_in(mstack_epc_i), + .mstack_epc_out(mstack_epc_o), + .mstack_cause_in('{bits: mstack_cause_i}), + .mstack_cause_out, + .misa_in('{bits: misa_i}), + .misa_out(), + .mscratch_in(mscratch_i), + .mscratch_out(mscratch_o), + .MScratchC_in(mscratchc_i), + .MScratchC_out(mscratchc_o), + .MTDC_in(mtdc_i), + .MTDC_out(mtdc_o), + .mstatus_in('{bits: + (32'(mstatus_i.mie) << 3) | + (32'(mstatus_i.mpie) << 7) | + (32'(mstatus_i.tw) << 21) | + (32'(mstatus_i.mprv) << 17) | + (32'(mstatus_i.mpp) << 11) + }), + .mstatus_out, + .mstatush_in('{bits: 32'b0}), + .mstatush_out(), + .mtval_in(mtval_i), + .mtval_out(mtval_o), + .MTCC_in(mtvec_i), + .MTCC_out(mtvec_o), + .MSHWMB_in(mshwmb_i), + .MSHWMB_out(mshwmb_o), + .MSHWM_in(mshwm_i), + .MSHWM_out(mshwm_o), + .mvendorid_in(mvendor_id_i), + .mvendorid_out(), + .nextPC_in(nextpc_i), + .nextPC_out(pc_o), + .nextPCC_in(pcc_i), + .nextPCC_out(pcc_o), + .PC_in(pc_i), + .PC_out(), + .PCC_in(pcc_i), + .PCC_out(), + .mseccfg_in('{bits: mseccfg_i}), + .mseccfg_out, + .mseccfgh_in(32'h0), + .mseccfgh_out(), + .pmpaddr_n_in, + .pmpaddr_n_out, + .pmpcfg_n_in, + .pmpcfg_n_out, + .scause_in(), + .scause_out(), + .scounteren_in(), + .scounteren_out(), + .sedeleg_in(), + .sedeleg_out(), + .senvcfg_in(), + .senvcfg_out(), + .sepc_in(), + .sepc_out(), + .sideleg_in(), + .sideleg_out(), + .sscratch_in(), + .sscratch_out(), + .stval_in(), + .stval_out(), + .stvec_in(), + .stvec_out(), + .tselect_in(), + .tselect_out(), + .x1_in(regs_i[1]), + .x1_out(), + .x2_in(regs_i[2]), + .x2_out(), + .x3_in(regs_i[3]), + .x3_out(), + .x4_in(regs_i[4]), + .x4_out(), + .x5_in(regs_i[5]), + .x5_out(), + .x6_in(regs_i[6]), + .x6_out(), + .x7_in(regs_i[7]), + .x7_out(), + .x8_in(regs_i[8]), + .x8_out(), + .x9_in(regs_i[9]), + .x9_out(), + .x10_in(regs_i[10]), + .x10_out(), + .x11_in(regs_i[11]), + .x11_out(), + .x12_in(regs_i[12]), + .x12_out(), + .x13_in(regs_i[13]), + .x13_out(), + .x14_in(regs_i[14]), + .x14_out(), + .x15_in(regs_i[15]), + .x15_out(), + .x16_in(regs_i[16]), + .x16_out(), + .x17_in(regs_i[17]), + .x17_out(), + .x18_in(regs_i[18]), + .x18_out(), + .x19_in(regs_i[19]), + .x19_out(), + .x20_in(regs_i[20]), + .x20_out(), + .x21_in(regs_i[21]), + .x21_out(), + .x22_in(regs_i[22]), + .x22_out(), + .x23_in(regs_i[23]), + .x23_out(), + .x24_in(regs_i[24]), + .x24_out(), + .x25_in(regs_i[25]), + .x25_out(), + .x26_in(regs_i[26]), + .x26_out(), + .x27_in(regs_i[27]), + .x27_out(), + .x28_in(regs_i[28]), + .x28_out(), + .x29_in(regs_i[29]), + .x29_out(), + .x30_in(regs_i[30]), + .x30_out(), + .x31_in(regs_i[31]), + .x31_out(), + + .wX_sail_invoke, + .wX_sail_invoke_ret(), + .wX_sail_invoke_arg_0, + .wX_sail_invoke_arg_1, + + .wC_sail_invoke, + .wC_sail_invoke_ret(), + .wC_sail_invoke_arg_0, + .wC_sail_invoke_arg_1, + + .write_ram_sail_invoke, + .write_ram_sail_invoke_ret(), + .write_ram_sail_invoke_arg_0(), + .write_ram_sail_invoke_arg_1, + .write_ram_sail_invoke_arg_2, + .write_ram_sail_invoke_arg_3, + + .read_ram_sail_invoke, + .read_ram_sail_invoke_ret, + .read_ram_sail_invoke_arg_0(), + .read_ram_sail_invoke_arg_1, + + .mem_read_cap_revoked_sail_invoke, + .mem_read_cap_revoked_sail_invoke_ret, + .mem_read_cap_revoked_sail_invoke_arg_0, + + .__ReadRAM_Meta_sail_invoke(), + .__ReadRAM_Meta_sail_invoke_ret, + .__ReadRAM_Meta_sail_invoke_arg_0(), + .__ReadRAM_Meta_sail_invoke_arg_1(), + .__WriteRAM_Meta_sail_invoke(), + .__WriteRAM_Meta_sail_invoke_ret(), + .__WriteRAM_Meta_sail_invoke_arg_0(), + .__WriteRAM_Meta_sail_invoke_arg_1(), + .__WriteRAM_Meta_sail_invoke_arg_2, + + .main_result(main_result), + .insn_bits(insn_bits), + .mode(main_mode) +); + +assign int_err_o = spec_i.sail_reached_unreachable | + spec_i.sail_have_exception | + (main_result != MAINRES_OK); + +endmodule diff --git a/vendor/lowrisc_ibex/dv/formal/spec/stub.sv b/vendor/lowrisc_ibex/dv/formal/spec/stub.sv new file mode 100644 index 000000000..bba79644b --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/stub.sv @@ -0,0 +1,92 @@ +// Copyright lowRISC contributors. +// Copyright 2024 University of Oxford, see also CREDITS.md. +// Licensed under the Apache License, Version 2.0 (see LICENSE for details). +// Original Author: Louis-Emile Ploix +// SPDX-License-Identifier: Apache-2.0 + +/* +Provides stubs (mostly) for the native functions the Sail expects to see, mostly +handling config stuff. +*/ + +function automatic logic[127:0] sail_emod_int(logic[127:0] x, logic[127:0] y); + // This one is unsigned, but the rest should be signed + return x % y; +endfunction + +function automatic logic[127:0] sail_pow_int(logic[127:0] x, logic[127:0] y); + // These are Sail integers, so operations on them should be signed + return signed'(x) ** signed'(y); +endfunction + +function automatic logic[127:0] sail_tmod_int(logic[127:0] x, logic[127:0] y); + return signed'(x) % signed'(y); +endfunction + +function automatic logic[127:0] sail_tdiv_int(logic[127:0] x, logic[127:0] y); + return signed'(x) / signed'(y); +endfunction + +function automatic sail_bits sail_shift_bits_left(sail_bits x, sail_bits y); + return {x.size, x.bits << y.bits}; +endfunction + +function automatic sail_bits sail_shift_bits_right(sail_bits x, sail_bits y); + return {x.size, x.bits >> y.bits}; +endfunction + +function automatic logic [127:0] count_trailing_zeros(sail_bits num); + for (int i = 0; i < 64; i++) begin + if (num.bits[i] == 1'b1) begin + return i; + end + end + return num.size; +endfunction + +function automatic sail_unit sail_decimal_string_of_bits(logic [11:0] x); + return SAIL_UNIT; +endfunction +function automatic logic sail_elf_tohost(sail_unit u); return 0; endfunction +function automatic logic sail_get_config_print_mem(sail_unit u); return 0; endfunction +function automatic logic sail_get_config_print_platform(sail_unit u); return 0; endfunction +function automatic logic sail_get_config_print_reg(sail_unit u); return 0; endfunction +function automatic logic sail_get_config_print_instr(sail_unit u); return 0; endfunction +function automatic logic sail_get_config_print_exception(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_clint_base(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_clint_size(sail_unit u); return 0; endfunction +function automatic logic sail_plat_enable_dirty_update(sail_unit u); return 0; endfunction +function automatic logic sail_plat_enable_misaligned_access(sail_unit u); return 1; endfunction +function automatic logic sail_plat_enable_pmp(sail_unit u); return 0; endfunction +function automatic sail_unit sail_platform_barrier(t_barrier_kind k); return SAIL_UNIT; endfunction +function automatic sail_unit sail_platform_write_mem_ea( + t_write_kind a, logic [63:0] b, sail_bits c, logic [127:0] d +); return SAIL_UNIT; endfunction +function automatic logic[15:0] sail_plat_get_16_random_bits(sail_unit u); return 0; endfunction +function automatic logic sail_plat_htif_tohost(sail_unit u); return 0; endfunction +function automatic logic sail_plat_mtval_has_illegal_inst_bits(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_ram_base(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_ram_size(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_rom_base(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_rom_size(sail_unit u); return 0; endfunction +function automatic sail_unit sail_plat_term_write(logic[7:0] u); return SAIL_UNIT; endfunction +function automatic sail_unit sail_print_mem_access(sail_unit u); return SAIL_UNIT; endfunction +function automatic sail_unit sail_print_platform(sail_unit u); return SAIL_UNIT; endfunction +function automatic sail_unit sail_print_reg(sail_unit u); return SAIL_UNIT; endfunction +function automatic sail_unit sail_string_of_int(logic[127:0] u); return SAIL_UNIT; endfunction +function automatic logic sail_sys_enable_fdext(sail_unit u); return 0; endfunction +function automatic logic sail_sys_enable_rvc(sail_unit u); return 1; endfunction +function automatic logic sail_sys_enable_writable_misa(sail_unit u); return 0; endfunction +function automatic logic sail_sys_enable_zfinx(sail_unit u); return 0; endfunction +function automatic sail_unit sail_cancel_reservation(sail_unit u); return SAIL_UNIT; endfunction +function automatic logic[31:0] sail_plat_uart_base(sail_unit u); return 0; endfunction +function automatic logic[31:0] sail_plat_uart_size(sail_unit u); return 0; endfunction +function automatic logic[6:0] sail_sys_pmp_count(sail_unit u); return 7'd0; endfunction +function automatic logic[6:0] sail_sys_pmp_max_count(sail_unit u); return 7'd0; endfunction +function automatic sail_unit sail_load_reservation(logic[31:0] u); return SAIL_UNIT; endfunction +function automatic logic sail_speculate_conditional(sail_unit u); return 0; endfunction +function automatic logic[63:0] sail_sys_pmp_grain(sail_unit u); return 0; endfunction +function automatic logic sail_sys_enable_writable_fiom(sail_unit u); return 0; endfunction +function automatic logic sail_plat_mtval_has_ebreak_pc(sail_unit u); return 1'h1; endfunction +function automatic logic[1:0] sail_plat_illegal_mpp_default(sail_unit u); return 2'b11; endfunction +function automatic logic sail_plat_has_internal_interrupts(sail_unit u); return 1'b0; endfunction diff --git a/vendor/lowrisc_ibex/dv/formal/spec/unreachable_loc_info.py b/vendor/lowrisc_ibex/dv/formal/spec/unreachable_loc_info.py new file mode 100644 index 000000000..c10d6113b --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/spec/unreachable_loc_info.py @@ -0,0 +1,22 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +with open("build/ibexspec.sv", "r") as f: + c = f.read() + +c = c.replace( + "sail_reached_unreachable = 1;", + "begin sail_reached_unreachable = 1; sail_reached_unreachable_loc = `__LINE__; end" +).replace( + "sail_reached_unreachable = 0;", + "begin sail_reached_unreachable = 0; sail_reached_unreachable_loc = -1; end" +).replace( + "bit sail_reached_unreachable;", + "bit sail_reached_unreachable;\n\tlogic [31:0] sail_reached_unreachable_loc;" +) + +with open("build/ibexspec.sv", "w") as f: + f.write(c) diff --git a/vendor/lowrisc_ibex/dv/formal/thm/btype.proof b/vendor/lowrisc_ibex/dv/formal/thm/btype.proof new file mode 100644 index 000000000..5472158a3 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/thm/btype.proof @@ -0,0 +1,45 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +lemma btype + in (instr_will_progress & ex_is_btype & ~ex_err) + FinishFirstCycle: have (`ID.instr_first_cycle) + / + BInd: + graph_induction +rev + cond (`CR.instr_valid_id & ex_is_btype & ~ex_err & ~ex_kill) + inv nobranch (~ex_has_branched_d) + inv eq (ex_has_branched_d == `CR.branch_decision && post_pc == ex_branch_dst) + + entry (`CR.instr_new_id) -> stall oma progress + + node stall nobranch (`ID.stall_ld_hz | `ID.stall_cheri_trvk) => stall oma progress + node oma eq (`IDG.outstanding_memory_access & ~(`ID.stall_ld_hz | `ID.stall_cheri_trvk)) => oma progress + split_bool (`CR.branch_decision) + node progress eq (instr_will_progress) + / + in (instr_will_progress & ex_is_btype & ~ex_err) + NoBranch: have (~`CR.branch_decision |-> spec_post_pc == pre_nextpc) + Branch: have (`CR.branch_decision |-> spec_post_pc == `CR.branch_target_ex) + +lemma jump + in (instr_will_progress & `IDC.jump_set_i & ~ex_err) + FinishFirstCycle: have (`ID.instr_first_cycle) + / + JInd: + graph_induction +rev + cond (`CR.instr_valid_id & `IDC.jump_set_i & ~ex_err & ~ex_kill) + inv nobranch (~ex_has_branched_d) + inv eq (ex_has_branched_d && post_pc[31:1] == `CR.branch_target_ex[31:1]) + + entry (`CR.instr_new_id) -> stall oma progress + + node stall nobranch (`ID.stall_ld_hz | `ID.stall_cheri_trvk) => stall oma progress + node oma eq (`IDG.outstanding_memory_access & ~(`ID.stall_ld_hz | `ID.stall_cheri_trvk)) => oma progress + node progress eq (instr_will_progress) + / + in (instr_will_progress & `IDC.jump_set_i & ~ex_err) + Branch: have (spec_post_pc[31:1] == `CR.branch_target_ex[31:1]) diff --git a/vendor/lowrisc_ibex/dv/formal/thm/dti.proof b/vendor/lowrisc_ibex/dv/formal/thm/dti.proof new file mode 100644 index 000000000..7a730c532 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/thm/dti.proof @@ -0,0 +1,47 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +lemma dti + SingleWbSource: have ($onehot0(`WB.rf_wdata_wb_mux_we)) + + / + + Ex: in (`CE.cheri_exec_id_i && ex_in_sats) + Csr: have (ex_out_csr_sats) + Lsu: have (ex_out_lsu_sats) + Result: have (ex_out_result_sats) + Pcc: have (`CE.branch_req_o |-> ex_out_pcc_sats) + + Csr: block + each X mtvec:(mtvec) mepc:(mepc) mtdc:(mtdc) mscratchc:(mscratchc) depc:(depc) dscratch0:(dscratch0) dscratch1:(dscratch1) + have (csr_in |=> csr_``X``_sats) + PccIn: have (csr_in |=> csr_out_pcc_sats) + Out: have (csr_int |-> csr_out_rdata_sats && csr_out_pcc_sats) + + Wb: block + Int: have (wb_in && wb_int |=> wb_int) + LsuIn: have (wb_in_lsu) + Ext: have (wb_int && wb_in_lsu |-> wb_out) + + Rf: in (rf_all) + A: have (rf_out_a) + B: have (rf_out_b) + Int1: have (rf_in |=> rf_group1) + Int2: have (rf_in |=> rf_group2) + + / + + Ex: block + have (ex_out_csr_sats && ex_out_lsu_sats && ex_out_result_sats && (`CE.branch_req_o -> ex_out_pcc_sats)) + Inner: have (ex_inner_sats) + + Csr: block + have (csr_int) + Pcc: have (csr_out_pcc_sats) + + Wb: have (wb_int) + + Rf: have (rf_all) diff --git a/vendor/lowrisc_ibex/dv/formal/thm/ibex.proof b/vendor/lowrisc_ibex/dv/formal/thm/ibex.proof new file mode 100644 index 000000000..e21a22468 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/thm/ibex.proof @@ -0,0 +1,391 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +lemma ibex + NotDataIndTiming: have (~`CSR.data_ind_timing_o) + + PrivMorUMpp: have ((`CSR.mstatus_q.mpp == PRIV_LVL_U) || (`CSR.mstatus_q.mpp == PRIV_LVL_M)) + PrivMorUCur: have ((`CSR.priv_lvl_q == PRIV_LVL_U) || (`CSR.priv_lvl_q == PRIV_LVL_M)) + NoFinishingIRQ: have (wbexc_finishing |-> ~wbexc_handling_irq) + + PCBit0: have (~`CR.pc_id[0]) + MEPCCBit0: have (~`CSR.mepc_q[0]) + MtvecBit1: have (~pre_mtvec.address[1]) + EBreakIntoDebug: have (~`IDC.ebreak_into_debug) + NoEnterDebugMode: have (~`IDC.enter_debug_mode) + IfBusErr: have (`IF.if_id_pipe_reg_we |-> ~`IF.if_instr_bus_err) + + MemGnt: have (mem_gnt_snd_q |-> mem_gnt_fst_q) + + block + MTCCNotSealed: have (`CSR.mtvec_cap.valid -> `CSR.mtvec_cap.otype == 3'b0) + MTCCPermitExecute: have (`CSR.mtvec_cap.valid -> `CSR.mtvec_cap.cperms[4:3] == 2'b01) + / + PCCNotSealed: have (`CSR.pcc_cap_o.valid -> `CSR.pcc_cap_o.otype == 3'b0) + PCCPermitExecute: have (`CSR.pcc_cap_o.valid -> `CSR.pcc_cap_o.perms[PERM_EX]) + + WfiKill: have (wbexc_exists & wbexc_is_wfi |-> ex_kill) + ErrKill: have (wbexc_exists & wbexc_err |-> ex_kill) + + ReqRequiresInstr: have (data_req_o |-> idex_has_compressed_instr) + ReqRequiresNotIllegal: have (data_req_o |-> ~`CR.illegal_insn_id & ~`CR.illegal_c_insn_id) + + AluInstrMatch: have (`CR.instr_rdata_id == `CR.instr_rdata_alu_id) + + IdExNotReq: have (~ex_is_mem_instr -> ~data_req_o) + IdExNotMemMuteIncr: have (`CR.instr_valid_id & ~ex_is_mem_instr -> ~`ID.lsu_addr_incr_req_i & ~`ID.lsu_req_done_i) + ExecNoSpecialReq: have (`ID.instr_executing & ~instr_will_progress |-> ~`IDC.special_req) + StallIdFSM1: have (`ID.instr_executing && `ID.id_fsm_d != 0 |-> ~instr_will_progress) + + ClockEn: have (instr_will_progress |-> ibex_top_i.clock_en) + EnWbProgress: have (`WB.en_wb_i |-> instr_will_progress) + ErrFast: have (wbexc_exists & wbexc_err |-> $past(instr_will_progress) | $past(instr_will_progress, 2)) + DoneFin: have (`WBG.wb_done & `WBG.wb_valid_q & ~wbexc_err |-> wbexc_finishing) + ValidExists: have (`WBG.wb_valid_q |-> wbexc_exists) + + WbexcErrMonotonic: have (wbexc_exists & wbexc_err & ~instr_will_progress & ~wbexc_finishing |=> wbexc_err) + + NonCompressedMatch: have (wbexc_finishing && wbexc_instr[1:0] == 2'b11 |-> wbexc_instr == wbexc_decompressed_instr) + CompressedMatch: have (idex_has_compressed_instr |-> idex_compressed_instr[15:0] == `CR.instr_rdata_c_id) + + PostFlushNoInstr: have (`IDC.ctrl_fsm_cs == `IDC.FLUSH |=> ~`CR.instr_valid_id) + + DecompressionIllegalIdEx: have (idex_has_compressed_instr |-> decompressed_instr_illegal == `CR.illegal_c_insn_id) + DecompressionMatchIdEx: have (idex_has_compressed_instr & ~`CR.illegal_insn_id & ~`CR.illegal_c_insn_id |-> decompressed_instr == `CR.instr_rdata_id) + DecompressionIllegalWbexc: have (wbexc_exists |-> decompressed_instr_illegal_2 == wbexc_compressed_illegal) + DecompressionMatchWbexc: have (wbexc_exists & ~wbexc_illegal & ~wbexc_compressed_illegal |-> decompressed_instr_2 == wbexc_decompressed_instr) + + HasCompressed: have (`CR.instr_valid_id |-> idex_has_compressed_instr) + LSUInstrStable: have (`LSU.ls_fsm_cs != 0 |-> $stable(`CR.instr_rdata_id)) + + NoneIdleIsDecode: have (`LSU.ls_fsm_cs != 0 |-> `IDC.ctrl_fsm_cs == 5) + LSUFinishWaitRvalidMisGntsDone: have (`LSU.ls_fsm_cs == 4 && data_rvalid_i |-> instr_will_progress) + LSUFinishWaitRvalidMis: have (`LSU.ls_fsm_cs == 2 && data_rvalid_i && data_gnt_i |-> instr_will_progress) + LSUFinishWaitGnt: have (`LSU.ls_fsm_cs == 3 && data_gnt_i |-> instr_will_progress) + LSUFinishFast: have (`LSU.ls_fsm_cs == 0 && data_gnt_i && `LSU.ls_fsm_ns == 0 |-> instr_will_progress) + + WBOutstandingNoReq: have (outstanding_mem & ~`LSU.lsu_resp_valid_o |-> ~data_req_o) + + NotIdleReqDec: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> `ID.lsu_req_dec | `CE.is_cap) + NotIdleNoExErr: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ~ex_err) + + ProgressNoWbStall: have (instr_will_progress |-> ~`IDC.stall_wb_i) + + NoStoreWb: have (`WBG.wb_instr_type_q == WB_INSTR_STORE |-> ~`WB.rf_we_wb_o) + WbInstrDefined: have (`WBG.wb_instr_type_q != 2'b11) + + SpecPastReg: have (wbexc_exists & wbexc_post_wX_en |-> spec_past_regs[wbexc_post_wX_addr] == wbexc_post_wX) + + SpecPastWbexc: + each X Priv:(priv) Mstatus:(mstatus) Mie:(mie) Mcause:(mcause) Mtval:(mtval) \ + Mscratch:(mscratch) Mcounteren:(mcounteren) Pc:(pc) \ + Mtvec:(mtvec) Mepc:(mepc) MscratchC:(mscratchc) Pcc:(pcc) Mtdc:(mtdc) + have (wbexc_exists |-> spec_past_``X == wbexc_post_``X) + + RfWriteWb: have (`CR.rf_write_wb & wbexc_finishing |-> `WB.rf_we_wb_o) + + CtrlWbexc: have (wbexc_exists |-> `IDC.ctrl_fsm_cs == `IDC.DECODE || `IDC.ctrl_fsm_cs == `IDC.FLUSH) + ProgressDecode: have (instr_will_progress |-> `IDC.ctrl_fsm_cs == `IDC.DECODE) + + BranchedProg: have (ex_has_branched_d & ~instr_will_progress |=> ex_has_branched_d) + + IDCFsmAny: have (`IDC.ctrl_fsm_cs inside {`IDC.RESET, `IDC.BOOT_SET, `IDC.WAIT_SLEEP, `IDC.SLEEP, `IDC.FIRST_FETCH, `IDC.DECODE, `IDC.IRQ_TAKEN, `IDC.FLUSH}) + IDCFsmNotBoot: have (##3 ~(`IDC.ctrl_fsm_cs inside {`IDC.RESET, `IDC.BOOT_SET})) + + MemInstrEx: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ex_is_mem_instr) + MemInstrWbLoad: have (`WB.outstanding_load_wb_o |-> wbexc_is_load_instr) + MemInstrWbStore: have (`WB.outstanding_store_wb_o |-> wbexc_is_store_instr) + MemClockEn: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ibex_top_i.core_busy_q) + + MemInstrWbWrite: have ( + wbexc_exists & wbexc_is_store_instr & ~wbexc_err |-> + ~`WBG.rf_we_wb_q & ~`WBG.cheri_rf_we_q & ~`WBG.wb_cheri_load_q & (`WBG.wb_instr_type_q != WB_INSTR_LOAD) + ) + + LsuCheriErrEx: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ~`LSU.cheri_err_q) + + TRVKOpValid: have ( + ((`TRVK.cpu_op_valid_q[0] & (|`TRVK.trsv_addr_q[0])) -> ~`RF.reg_rdy_vec[`TRVK.trsv_addr_q[0]]) & + ((`TRVK.cpu_op_valid_q[1] & (|`TRVK.trsv_addr_q[1])) -> ~`RF.reg_rdy_vec[`TRVK.trsv_addr_q[1]]) & + ((`TRVK.cpu_op_valid_q[2] & (|`TRVK.trsv_addr_q[2])) -> ~`RF.reg_rdy_vec[`TRVK.trsv_addr_q[2]]) + ) + TRVKOutstandingCLC: have ( + `TRVK.cpu_op_active && (|`WBG.rf_waddr_wb_q) |-> ~`RF.reg_rdy_vec[`WBG.rf_waddr_wb_q] + ) + TRVKSecondOutstanding: have ( + `WB.outstanding_load_wb_o |-> + ((`TRVK.cpu_op_valid_q[0] & (|`TRVK.trsv_addr_q[0])) -> (~`WBG.rf_waddr_wb_q != (|`TRVK.trsv_addr_q[0]))) & + ((`TRVK.cpu_op_valid_q[1] & (|`TRVK.trsv_addr_q[1])) -> (~`WBG.rf_waddr_wb_q != (|`TRVK.trsv_addr_q[1]))) & + ((`TRVK.cpu_op_valid_q[2] & (|`TRVK.trsv_addr_q[2])) -> (~`WBG.rf_waddr_wb_q != (|`TRVK.trsv_addr_q[2]))) + ) + CPUOpActiveNoErr: have (wbexc_exists & ~wbexc_err |-> `IS_LOADCAPIMM == `TRVK.cpu_op_active) + CPUOpActiveErr: have (wbexc_exists & wbexc_err & `TRVK.cpu_op_active |-> `IS_LOADCAPIMM ##1 ~`TRVK.cpu_op_active) + TRSVAddr: have (wbexc_exists & ~wbexc_err & `IS_LOADCAPIMM |-> `TRVK.trsv_addr == `WB.rf_waddr_wb_o) + TRSVAddrLow: have (`TRVK.cpu_op_active |-> ~`TRVK.trsv_addr[4]) + + LsuWeq: block + Ex: have (`LSU.ls_fsm_cs != `LSU.IDLE && mem_gnt_fst_q |-> ex_is_store_instr == `LSU.data_we_q) + / + Wb: have (outstanding_mem |-> wbexc_is_store_instr == `LSU.data_we_q) + + block + LSUEmpty: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ~wbexc_exists & ~ex_kill) + LSUValidInstr: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ~`ID.instr_fetch_err_i & `ID.instr_valid_i & ~`ID.illegal_insn_o) + / + LSUEnd: have (`LSU.lsu_req_done_o |-> instr_will_progress) + LSUNotTRSV: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> ~`ID.stall_cheri_trvk) + + NoTBRE: have (~`CE.lsu_tbre_sel_i & ~`LSU.req_is_tbre_q & ~`LSU.tbre_req_good & ~`CR.tbre_lsu_req) + + / + + Memory: graph_induction +rev + inv idle ( + ~`LSU.handle_misaligned_q && + `CR.lsu_resp_valid == outstanding_mem && + (`LSU.cap_rx_fsm_q == CRX_IDLE || (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP2 && data_rvalid_i)) + ) + inv idle_active ( + data_mem_assume.outstanding_reqs == data_gnt_i && + ~`LSU.handle_misaligned_q && + `CR.lsu_resp_valid == outstanding_mem && + (`LSU.cap_rx_fsm_q == CRX_IDLE || (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP2 && data_rvalid_i)) + ) + inv wait_gnt_mis ( + $stable(data_addr_o) && ~has_resp_waiting_q && ~`LSU.lsu_cheri_err_i && + `LSU.cap_rx_fsm_q == CRX_IDLE && ~ex_is_mem_cap_instr + ) + inv wait_gnt ( + $stable(data_addr_o) && ~has_resp_waiting_q && ~`LSU.lsu_cheri_err_i && + `LSU.cap_rx_fsm_q == CRX_IDLE && ~ex_is_mem_cap_instr + ) + inv wait_rvalid_mis ( + ($stable(`LSU.ls_fsm_cs) -> $stable(data_addr_o)) && + has_one_resp_waiting_q && ~`LSU.lsu_cheri_err_i && + `LSU.cap_rx_fsm_q == CRX_IDLE && ~ex_is_mem_cap_instr + ) + inv wait_rvalid_mis_gnts_done ( + $stable(data_addr_o) && + has_two_resp_waiting_q && ~`LSU.lsu_cheri_err_i && + `LSU.cap_rx_fsm_q == CRX_IDLE && ~ex_is_mem_cap_instr && + ~`LSU.handle_misaligned_q + ) + inv wait_gnt1 ( + $stable(data_addr_o) && ~has_resp_waiting_q && ~`LSU.lsu_cheri_err_i && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP1 && ex_is_mem_cap_instr && + ~`LSU.handle_misaligned_q + ) + inv wait_gnt2 ( + ($stable(`LSU.ls_fsm_cs) -> $stable(data_addr_o)) && + has_one_resp_waiting_q && ~`LSU.lsu_cheri_err_i && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP1 && ex_is_mem_cap_instr && + ~`LSU.handle_misaligned_q + ) + inv wait_gnt2_direct ( + ($stable(`LSU.ls_fsm_cs) -> $stable(data_addr_o)) && + ~has_resp_waiting_q && ~`LSU.lsu_cheri_err_i && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP2 && ex_is_mem_cap_instr && + ~`LSU.handle_misaligned_q + ) + inv wait_resp ( + $stable(data_addr_o) && has_two_resp_waiting_q && ~`LSU.lsu_cheri_err_i && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP1 && ex_is_mem_cap_instr && + ~`LSU.handle_misaligned_q + ) + + inv step ( + `LSU.ls_fsm_ns == `LSU.IDLE && + (`CR.instr_type_wb != WB_INSTR_OTHER || `CR.cheri_load_id || `CR.cheri_store_id) && + has_one_resp_waiting_d && + (ex_is_mem_cap_instr -> (`LSU.cap_rx_fsm_d == CRX_WAIT_RESP2)) && + (~ex_is_mem_cap_instr -> (`LSU.cap_rx_fsm_d == CRX_IDLE)) && + ~`LSU.handle_misaligned_d + ) + inv wait ( + outstanding_mem && has_one_resp_waiting_q && ~`LSU.lsu_req_i && wbexc_exists && + (wbexc_is_mem_cap_instr -> (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP2)) && + (~wbexc_is_mem_cap_instr -> (`LSU.cap_rx_fsm_q == CRX_IDLE)) && + ~`LSU.handle_misaligned_q && ~`LSU.cheri_err_q + ) + inv end ( + outstanding_mem && has_one_resp_waiting_q && wbexc_exists && + (wbexc_is_mem_cap_instr -> (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP2)) && + (~wbexc_is_mem_cap_instr -> (`LSU.cap_rx_fsm_q == CRX_IDLE)) && + ~`LSU.handle_misaligned_q && ~`LSU.cheri_err_q + ) + + entry ($rose(rst_ni)) -> idle + + node idle idle (`LSU.ls_fsm_cs == `LSU.IDLE && data_mem_assume.outstanding_reqs == data_gnt_i) + edge idle => idle + edge idle -> idle_active + + node idle_active idle_active (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req && ~`CR.lsu_cheri_err) + edge idle_active => wait_rvalid_mis wait_gnt_mis wait_gnt wait_gnt1 wait_gnt2 + edge idle_active -> step + + node wait_gnt_mis wait_gnt_mis (`LSU.ls_fsm_cs == `LSU.WAIT_GNT_MIS) + edge wait_gnt_mis => wait_gnt_mis wait_rvalid_mis + + node wait_rvalid_mis wait_rvalid_mis (`LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS) + edge wait_rvalid_mis => wait_rvalid_mis wait_rvalid_mis_gnts_done wait_gnt + edge wait_rvalid_mis -> step + + node wait_gnt wait_gnt (`LSU.ls_fsm_cs == `LSU.WAIT_GNT) + edge wait_gnt => wait_gnt + edge wait_gnt -> step + + node wait_rvalid_mis_gnts_done wait_rvalid_mis_gnts_done (`LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS_GNTS_DONE) + edge wait_rvalid_mis_gnts_done => wait_rvalid_mis_gnts_done + edge wait_rvalid_mis_gnts_done -> step + + node wait_gnt1 wait_gnt1 (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT1) + edge wait_gnt1 => wait_gnt1 wait_gnt2 + edge wait_gnt1 -> step + + node wait_gnt2 wait_gnt2 (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT2 && has_one_resp_waiting_q) + edge wait_gnt2 => wait_gnt2 wait_gnt2_direct wait_resp + edge wait_gnt2 -> step + + node wait_gnt2_direct wait_gnt2_direct (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT2 && ~has_resp_waiting_q) + edge wait_gnt2_direct => wait_gnt2_direct + edge wait_gnt2_direct -> step + + node wait_resp wait_resp (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_RESP) + edge wait_resp => wait_resp + edge wait_resp -> step + + node step step (`LSU.lsu_req_done_o & ~`LSU.lsu_cheri_err_i) + edge step => wait end + + node wait wait (has_resp_waiting_q && ~`CR.lsu_resp_valid && `LSU.ls_fsm_cs == `LSU.IDLE && ~instr_will_progress) + edge wait => wait end + + node end end (`CR.lsu_resp_valid && `LSU.ls_fsm_cs == `LSU.IDLE && data_rvalid_i) + edge end -> idle + / + NoMemAccessNoRValid: have (`LSU.lsu_resp_valid_o -> outstanding_mem) + StallNoChangeA: have (`LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(`ID.rf_rdata_a_fwd) & $stable(`CE.rf_rcap_a)) + StallNoChangeB: have (data_we_o && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(`ID.rf_rdata_b_fwd) & $stable(`CE.rf_rcap_a)) + + BecameDecodeIsInstrStart: have (`IDC.ctrl_fsm_cs == `IDC.DECODE && !$stable(`IDC.ctrl_fsm_cs) |-> ~`ID.instr_valid_i | `CR.instr_new_id) + BecameDecodeIsEmptyWbexc: have (`IDC.ctrl_fsm_cs == `IDC.DECODE && !$stable(`IDC.ctrl_fsm_cs) |-> ~wbexc_exists) + FetchErrIsErr: have (wbexc_fetch_err & wbexc_exists |-> wbexc_err & `IDC.instr_fetch_err) + + MemOpRequiresValid: have (`LSU.ls_fsm_cs != `LSU.IDLE || `CR.lsu_req |-> `ID.instr_valid_i) + + MultEndState: have (instr_will_progress |=> `MULTG.mult_state_q == `MULTG.ALBL) + + DataWeOutstanding: have (outstanding_mem |-> `ID.outstanding_store_wb_i == `LSU.data_we_q) + TRVKMutex: have ((`RF.we_a_i & `RF.trvk_en_i & (|`RF.we_a_dec)) -> (`RF.trvk_dec != `RF.we_a_dec)) + DTI: lemma dti + + / + + MemErrKind: have (finishing_executed && wbexc_is_mem_instr && ~wbexc_illegal && wbexc_err |-> `IDC.store_err_q | `IDC.load_err_q) + MemErrStructure: have (finishing_executed && wbexc_is_mem_instr && ~wbexc_illegal && wbexc_err |-> $past(instr_will_progress, 2) | $past(data_rvalid_i)) + MemNoErrStructure: have (finishing_executed && wbexc_is_mem_instr && ~wbexc_illegal && ~wbexc_err |-> data_rvalid_i) + + WbexcMemErrKindLoad: have (`IDC.load_err_q |-> wbexc_exists & wbexc_is_load_instr) + WbexcMemErrKindStore: have (`IDC.store_err_q |-> wbexc_exists & wbexc_is_store_instr) + + WbexcNotMemMuteLSU: have (~wbexc_is_mem_instr -> ~`CR.rf_we_lsu & ~`CR.lsu_resp_valid & ~`CR.lsu_load_err & ~`CR.lsu_store_err) + WbexcNotMemMuteMemErr: have (~wbexc_is_mem_instr -> ~`IDC.load_err_q & ~`IDC.store_err_q) + StallIdFSM2: have (`ID.instr_executing && ~instr_will_progress |=> `ID.instr_executing) + NewIdFSM: have (`CR.instr_new_id |-> `ID.id_fsm_q == 0) + PreNextPcMatch: have (instr_will_progress & ~ex_has_branched_d & ~`IDC.instr_fetch_err -> pre_nextpc == `CR.pc_if) + StallNoChangeLsuWData: have ((data_we_o && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(`LSU.lsu_wdata_i))) + + # These properties take some time to prove, but do prove with low proof effort + SpecStableLoad: have (ex_is_load_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_read)) + SpecStableLoadSnd: have (ex_is_load_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_read_snd)) + SpecStableLoadAddr: have (ex_is_load_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_read_fst_addr)) + SpecStableLoadSndAddr: have (ex_is_load_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_read_snd_addr)) + + SpecStableStore: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write)) + SpecStableStoreSnd: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write_snd)) + SpecStableStoreAddr: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write_fst_addr)) + SpecStableStoreSndAddr: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write_snd_addr)) + SpecStableStoreData: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write_fst_wdata)) + SpecStableStoreSndData: have (ex_is_store_instr && `LSU.ls_fsm_cs != `LSU.IDLE && ($past(`LSU.ls_fsm_cs) != `LSU.IDLE || $past(`LSU.lsu_req_i)) |-> $stable(spec_mem_write_snd_wdata)) + + LoadNotSpecWrite: have (ex_is_load_instr |-> ~spec_mem_write) + StoreNotSpecRead: have (ex_is_store_instr |-> ~spec_mem_read) + + FirstCycleNoGnt: have (`ID.instr_first_cycle |-> ~mem_gnt_fst_q) + MemStartFirstCycle: have (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req |-> `ID.instr_first_cycle) + DivInstrStable: have (`MULT.md_state_q != `MULT.MD_IDLE |-> $stable(`CR.instr_rdata_id) && `CR.instr_valid_id && (~`ID.stall_multdiv -> `MULT.md_state_q == `MULT.MD_FINISH) && `MULTG.mult_state_q == `MULTG.ALBL && `MULT.div_en_internal && (~wbexc_exists | wbexc_finishing)) + + InstrReqCount: have ( + (instr_mem_assume.outstanding_reqs_q == 2) == (`IFP.rdata_outstanding_q[1] && `IFP.rdata_outstanding_q[0]) && + (instr_mem_assume.outstanding_reqs_q == 1) == (~`IFP.rdata_outstanding_q[1] && `IFP.rdata_outstanding_q[0]) && + (instr_mem_assume.outstanding_reqs_q == 0) == (~`IFP.rdata_outstanding_q[1] && ~`IFP.rdata_outstanding_q[0]) + ) + + FetchErrRoot: have (`ID.instr_valid_i && (`IDC.ctrl_fsm_cs == `IDC.FLUSH -> ~$past(`IDC.csr_pipe_flush)) |-> spec_fetch_err == `ID.instr_fetch_err_i) + / + + MepcEn: have (`CSR.mepc_en |-> instr_will_progress | wbexc_finishing | wbexc_handling_irq) + DivNoKill: have (`MULT.md_state_q != `MULT.MD_IDLE |-> ~ex_kill) + + RTypeFirstCycle: have (`CR.instr_valid_id & ex_is_rtype |-> `ID.instr_first_cycle_id_o) + + DataMemGntMaxDelay: have (data_req_o |-> ##[0:`TIME_LIMIT] data_gnt_i) + DataMemRvalidMaxDelay: have (data_gnt_i |=> ##[0:`TIME_LIMIT] data_rvalid_i) + InstrMemGntMaxDelay: have (instr_req_o |-> ##[0:`TIME_LIMIT] instr_gnt_i) + InstrMemRvalidMaxDelay: have (instr_gnt_i |=> ##[0:`TIME_LIMIT] instr_rvalid_i) + + NormalMainResMatch: have (`ID.instr_valid_i && ~ex_kill && main_mode == MAIN_IDEX |-> spec_api_i.main_result == MAINRES_OK) + FetchErrMainResMatch: have (`ID.instr_valid_i && ~ex_kill && main_mode == MAIN_IFERR |-> spec_api_i.main_result == MAINRES_OK) + IRQMainResMatch: have (wbexc_handling_irq && main_mode == MAIN_IRQ |-> spec_api_i.main_result == MAINRES_OK) + + NoStallBranch: have (`ID.instr_valid_i & `ID.stall_id & ~`ID.branch_set_raw & ~`ID.jump_set_raw & ~`IDC.cheri_branch_req_i |-> ~ex_has_branched_d) + FirstCycleHold: have (`ID.instr_valid_i & ~`ID.instr_executing |-> `ID.id_fsm_q == `ID.FIRST_CYCLE) + + ReqNotOutstanding: have (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req |-> ~`LSU.resp_wait) + / + SpecEnUnreach: have (spec_en |-> ~spec_int_err) + +lemma live + DivMiddleStep: have (`MULT.md_state_q == `MULT.MD_COMP && $stable(`MULT.md_state_q) |-> `MULT.div_counter_q == $past(`MULT.div_counter_q) - 1) + IF: have (always (##[0:10] `IF.if_instr_valid)) + PCSet: have (`CR.pc_set |-> ##[0:10] ~`CR.pc_set) + / + + DivStart: have (`CR.instr_new_id & `CR.instr_valid_id & ex_is_div |-> ##[0:7] (`MULT.div_counter_q == 5'd31 && `MULT.md_state_q == `MULT.MD_COMP) | instr_will_progress | (ex_kill & `CR.instr_valid_id)) + DivMiddle: have (`MULT.div_counter_q == 5'd31 && `MULT.md_state_q == `MULT.MD_COMP |-> ##30 `MULT.div_counter_q == 5'd1 && `MULT.md_state_q == `MULT.MD_COMP) + DivEnd: have (`MULT.div_counter_q == 5'd1 && `MULT.md_state_q == `MULT.MD_COMP |-> ##3 instr_will_progress) + + WFIStart: have (instr_will_progress & ex_is_wfi & ~ex_err |-> ##[0:5] `IDC.ctrl_fsm_cs == `IDC.SLEEP) + WFIMiddle: have (`IDC.ctrl_fsm_cs == `IDC.SLEEP |-> ##[0:20] `IDC.ctrl_fsm_cs == `IDC.SLEEP && `IDC.ctrl_fsm_ns == `IDC.FIRST_FETCH) + WFIEnd: have (`IDC.ctrl_fsm_cs == `IDC.SLEEP && `IDC.ctrl_fsm_ns == `IDC.FIRST_FETCH |-> ##[0:5] `IF.id_in_ready_i) + + NewProgNormal: have (`CR.instr_new_id & `CR.instr_valid_id & ~ex_is_div & ~ex_is_mem_instr |-> ##[0:5] (instr_will_progress | (ex_kill & `CR.instr_valid_id))) + NewProgMem: have (`CR.instr_new_id & `CR.instr_valid_id & ex_is_mem_instr |-> ##[0:10] (instr_will_progress | (ex_kill & `CR.instr_valid_id))) + + ProgReadyNormal: have (instr_will_progress & (~ex_is_wfi | ex_err) |-> ##[0:5] `IF.id_in_ready_i) + ProgReadyWFI: have (instr_will_progress & ex_is_wfi & ~ex_err |-> ##[0:30] `IF.id_in_ready_i) + KillReady: have (ex_kill & `CR.instr_valid_id |-> ##[1:35] `IF.id_in_ready_i && ~wbexc_exists && ~`CR.instr_valid_id) + + ReadyNew: have (`IF.id_in_ready_i |-> ##[1:11] `CR.instr_new_id & `CR.instr_valid_id) + Initial: have ($rose(rst_ni) |-> ##[1:15] `CR.instr_new_id & `CR.instr_valid_id) + FlushedNoKill: have (`CR.instr_new_id & `CR.instr_valid_id & ~wbexc_exists |-> ~ex_kill until_with instr_will_progress) + / + ReadyFlushed: have (`IF.id_in_ready_i && ~wbexc_exists && ~`CR.instr_valid_id |-> ##[1:11] `CR.instr_new_id & `CR.instr_valid_id & ~wbexc_exists) + / + DivNew1: have (`CR.instr_new_id & `CR.instr_valid_id & ex_is_div |-> ##[0:37] ((`MULT.div_counter_q == 5'd1 && `MULT.md_state_q == `MULT.MD_COMP) | instr_will_progress | (ex_kill & `CR.instr_valid_id))) + / + NewProgDiv: have (`CR.instr_new_id & `CR.instr_valid_id & ex_is_div |-> ##[0:40] (instr_will_progress | (ex_kill & `CR.instr_valid_id))) + ProgReady: have (instr_will_progress |-> ##[0:30] `IF.id_in_ready_i) + / + NewProg: have (`CR.instr_new_id & `CR.instr_valid_id |-> ##[0:40] (instr_will_progress | (ex_kill & `CR.instr_valid_id))) + / + FlushedProg: have (`CR.instr_new_id & `CR.instr_valid_id & ~wbexc_exists |-> ##[0:40] instr_will_progress) + / + KillSpecEn: have (ex_kill & `CR.instr_valid_id |-> ##[0:86] spec_en) + / + NewReady: have (`CR.instr_new_id & `CR.instr_valid_id |-> ##[0:75] `IF.id_in_ready_i) + NewSpecEn: have (`CR.instr_new_id & `CR.instr_valid_id |-> ##[0:40+86] spec_en) + / + NewLoop: have (`CR.instr_new_id & `CR.instr_valid_id |-> ##[1:86] `CR.instr_new_id & `CR.instr_valid_id) + / + New: have (always (##[1:86] `CR.instr_new_id & `CR.instr_valid_id)) diff --git a/vendor/lowrisc_ibex/dv/formal/thm/mem.proof b/vendor/lowrisc_ibex/dv/formal/thm/mem.proof new file mode 100644 index 000000000..56a53e40e --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/thm/mem.proof @@ -0,0 +1,212 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +lemma mem + MemNotWFI: have (wbexc_exists && wbexc_is_mem_instr |-> ~wbexc_is_wfi) + MemFin: have (finishing_executed && wbexc_is_mem_instr && ~wbexc_err |-> data_rvalid_i) + + RespWait: have (wbexc_exists && wbexc_is_mem_instr && ~wbexc_err && ~data_rvalid_i |-> `LSU.ls_fsm_cs == `LSU.IDLE && ~`LSU.lsu_req_i) + + CapResp: have (`LSU.ls_fsm_cs != `LSU.IDLE || (outstanding_mem & ~wbexc_err) || data_rvalid_i |-> + ((wbexc_exists && ~wbexc_err && (`IS_LOADCAPIMM | `IS_STORECAPIMM)) || (`LSU.ls_fsm_cs != `LSU.IDLE && ex_is_mem_cap_instr)) == `LSU.resp_is_cap_q + ) + CapLSWErr: have (~`LSU.cap_lsw_err_q) + + EarlyLSUCtrlMatch: have ( + `LSU.ls_fsm_cs != `LSU.IDLE & spec_post_wX_en & mem_gnt_fst_q |-> + `LSU.rdata_offset_q == `LSU.data_offset && `LSU.data_type_q == `LSU.lsu_type_i && `LSU.data_sign_ext_q == `LSU.lsu_sign_ext_i && `LSU.data_we_q == `LSU.lsu_we_i + ) + + HadSndReqCap: have (instr_will_progress & ex_is_mem_cap_instr & ~ex_err & ~`LSU.lsu_cheri_err_i |=> wbexc_mem_had_snd_req) + HadSndReqNotCap: have (instr_will_progress & ex_is_mem_instr & ~ex_is_mem_cap_instr & ~ex_err & ~`LSU.lsu_cheri_err_i |=> wbexc_mem_had_snd_req == $past(`LSU.split_misaligned_access)) + + LateLSUCheriErr: have (wbexc_exists & wbexc_is_load_instr & ~wbexc_err & wbexc_post_wX_en |-> ~`LSU.cheri_err_q) + + PMPErr: have (~`LSU.pmp_err_q) + + NonCapFSM: have (~ex_is_mem_cap_instr |-> `LSU.ls_fsm_cs != `LSU.CTX_WAIT_GNT1 && `LSU.ls_fsm_cs != `LSU.CTX_WAIT_GNT2 && `LSU.ls_fsm_cs != `LSU.CTX_WAIT_RESP) + + MisStates: have (`LSU.ls_fsm_cs == `LSU.WAIT_GNT_MIS || `LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS || `LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS_GNTS_DONE |-> `LSU.split_misaligned_access) + + + CapFsm: graph_induction + cond (ex_is_mem_cap_instr && (`LSU.ls_fsm_cs != `LSU.IDLE || (`CR.lsu_req && ~`CR.lsu_cheri_err))) + + entry (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req && ~`CR.lsu_cheri_err) -> idle_active + + node idle_active (`LSU.cap_rx_fsm_q == CRX_IDLE || (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP2 && data_rvalid_i)) (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req && ~`CR.lsu_cheri_err) + edge idle_active => wait_gnt1 wait_gnt2 wait_gnt2_done + + node wait_gnt1 (`LSU.cap_rx_fsm_q == CRX_WAIT_RESP1 && ~`CR.lsu_cheri_err) (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT1) + edge wait_gnt1 => wait_gnt1 wait_gnt2 wait_gnt2_done + + node wait_gnt2 (~`CR.lsu_cheri_err) (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT2 && `LSU.cap_rx_fsm_d == CRX_WAIT_RESP1) + edge wait_gnt2 => wait_gnt2 wait_gnt2_done wait_resp + edge wait_gnt2 -> step + + # waitgnt2done step is bound dependent (Hp (12)) + node wait_gnt2_done (~`CR.lsu_cheri_err) (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT2 && `LSU.cap_rx_fsm_d == CRX_WAIT_RESP2) + edge wait_gnt2_done => wait_gnt2_done + edge wait_gnt2_done -> step + + node wait_resp (~`CR.lsu_cheri_err && `LSU.cap_rx_fsm_q == CRX_WAIT_RESP1) (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_RESP) + edge wait_resp => wait_resp + edge wait_resp -> step + + node step (`LSU.cap_rx_fsm_d == CRX_WAIT_RESP2) (`LSU.lsu_req_done_o && ~`CR.lsu_cheri_err) +exit + + MemSpec: graph_induction +rev + cond (ex_is_mem_instr && (`LSU.ls_fsm_cs != `LSU.IDLE || (`CR.lsu_req && ~`CR.lsu_cheri_err))) + + inv fst_req (mem_req_fst_d && fst_mem_cmp && ~mem_gnt_fst_q && ~`CR.lsu_cheri_err) + inv fst_req_1 (mem_req_fst_d && fst_mem_cmp && ~mem_gnt_fst_q && ~`CR.lsu_cheri_err && ~spec_mem_read_snd && ~spec_mem_write_snd) + inv fst_req_2 (mem_req_fst_d && fst_mem_cmp && ~mem_gnt_fst_q && ~`CR.lsu_cheri_err && (spec_mem_read_snd | spec_mem_write_snd)) + inv snd_req (mem_req_snd_d && snd_mem_cmp && ~`CR.lsu_cheri_err && (spec_mem_read_snd | spec_mem_write_snd)) + inv req_done (~data_req_o && ~`CR.lsu_cheri_err && mem_gnt_snd_q && (spec_mem_read_snd | spec_mem_write_snd)) + + entry (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req && ~`CR.lsu_cheri_err) -> idle_active + + node idle_active fst_req (`LSU.ls_fsm_cs == `LSU.IDLE && `CR.lsu_req && ~`CR.lsu_cheri_err) + edge idle_active => wait_rvalid_mis wait_gnt_mis wait_gnt wait_gnt1 wait_gnt2 + edge idle_active -> step + + node wait_gnt_mis fst_req_2 (`LSU.ls_fsm_cs == `LSU.WAIT_GNT_MIS) + edge wait_gnt_mis => wait_gnt_mis wait_rvalid_mis + + node wait_rvalid_mis snd_req (`LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS) + edge wait_rvalid_mis => wait_rvalid_mis wait_rvalid_mis_gnts_done wait_gnt_split + edge wait_rvalid_mis -> step + + node wait_gnt_split snd_req (`LSU.ls_fsm_cs == `LSU.WAIT_GNT && `LSU.split_misaligned_access) + edge wait_gnt_split => wait_gnt_split + edge wait_gnt_split -> step + + node wait_gnt fst_req_1 (`LSU.ls_fsm_cs == `LSU.WAIT_GNT && ~`LSU.split_misaligned_access) + edge wait_gnt => wait_gnt + edge wait_gnt -> step + + node wait_rvalid_mis_gnts_done req_done (`LSU.ls_fsm_cs == `LSU.WAIT_RVALID_MIS_GNTS_DONE) + edge wait_rvalid_mis_gnts_done => wait_rvalid_mis_gnts_done + edge wait_rvalid_mis_gnts_done -> step + + node wait_gnt1 fst_req_2 (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT1) + edge wait_gnt1 => wait_gnt1 wait_gnt2 + edge wait_gnt1 -> step + + node wait_gnt2 snd_req (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_GNT2) + edge wait_gnt2 => wait_gnt2 wait_resp + edge wait_gnt2 -> step + + node wait_resp req_done (`LSU.ls_fsm_cs == `LSU.CTX_WAIT_RESP) + edge wait_resp => wait_resp + edge wait_resp -> step + + node step (1) (`LSU.lsu_req_done_o && ~`CR.lsu_cheri_err) +exit + / + LSULateRespFinishing: have (late_resp |-> wbexc_finishing || wbexc_err) + LSUEarlyRequestSplit: have (early_resp |-> has_snd_req) + LSUHold: have (data_req_o & ~data_gnt_i |=> data_addr_o == $past(data_addr_o) && data_we_o == $past(data_we_o)) + LSUHoldWrite: have (data_req_o & ~data_gnt_i & data_we_o |=> data_be_o == $past(data_be_o) && data_wdata_o == $past(data_wdata_o)) + LSUMaxTwoReqs: have (mem_gnt_snd_q |-> ~data_gnt_i) + LSU2ndReqStep: have (data_req_o & $past(data_gnt_i) & ~$past(instr_will_progress) |-> data_we_o == $past(data_we_o) && data_addr_o == $past(data_addr_o) + 4) + LSUInternalHold: have (`LSU.data_req_o && ~data_gnt_i && ~`LSU.pmp_err_q |=> $stable(data_addr_o)) + + NoMem: have (~ex_is_mem_instr & instr_will_progress |-> ~mem_gnt_fst_d) + + AltLSUVeryEarly: have (`LSU.ls_fsm_cs != `LSU.IDLE & spec_post_wX_en & ~lsu_had_first_resp |-> alas(spec_post_wX, revoke(alt_lsu_very_early_res, spec_mem_revoke_en & spec_mem_revoke))) + ExceptionMaintain: have (`LSU.lsu_req_i && ~spec_mem_read & ~spec_mem_write |-> instr_will_progress ##1 wbexc_err) + FastErrSignalCap: have (finishing_executed & ~wbexc_illegal & wbexc_err & (`IS_LOADCAPIMM | `IS_STORECAPIMM) |-> + ($past(`CE.is_load_cap, 2) | $past(`CE.is_store_cap, 2)) & $past(`CE.cheri_lsu_err, 2) & $past(`CE.cheri_exec_id_i, 2) + ) + FastErrSignalNoCap: have (finishing_executed & ~wbexc_illegal & wbexc_err & wbexc_is_mem_instr & ~(`IS_LOADCAPIMM | `IS_STORECAPIMM) |-> + $past(`CE.rv32_lsu_req_i, 2) & $past(`CE.rv32_lsu_err, 2) + ) + FinalCapAltLSUVeryEarly: have ( + `LSU.ls_fsm_cs != `LSU.IDLE && ex_is_clc && ~lsu_had_first_resp |-> + onlySealingPerms(revoke(spec_mem_read_cap, `LSU.resp_lc_clrperm_q[3])) + == onlySealingPerms(alt_lsu_very_early_res) + ) + / + PCMaintainEx: have (`ID.instr_valid_i & ex_is_mem_instr & ~ex_err & ~ex_kill |-> pre_nextpc == post_pc) + AltLSUEarly: have (`LSU.ls_fsm_cs != `LSU.IDLE & spec_post_wX_en & lsu_had_first_resp |-> alas(spec_post_wX, revoke(alt_lsu_early_res, spec_mem_revoke_en & spec_mem_revoke))) + ClrPerm: have (`LSU.ls_fsm_cs != `LSU.IDLE |-> `CE.cheri_lsu_lc_clrperm == `LSU.resp_lc_clrperm_q) + FinalCapAltLSUEarly: have ( + `LSU.ls_fsm_cs != `LSU.IDLE && ex_is_clc && lsu_had_first_resp |-> + onlySealingPerms(revoke(spec_mem_read_cap, `LSU.resp_lc_clrperm_q[3])) + == onlySealingPerms(alt_lsu_early_res) + ) + / + AltLSU: have (wbexc_exists & wbexc_is_load_instr & ~wbexc_err & wbexc_post_wX_en |-> alas(wbexc_post_wX, revoke(alt_lsu_late_res, wbexc_spec_mem_revoke_en & wbexc_spec_mem_revoke))) + CSRMaintain: have (wbexc_exists & wbexc_is_mem_instr & ~wbexc_err |-> csrs_match) + CSRNoChange: have (wbexc_exists & wbexc_is_mem_instr & ~wbexc_err |-> csrs_didnt_change) + PCNoChangeNoBranch: have (wbexc_exists & wbexc_is_mem_instr & ~wbexc_err & ~ex_has_branched_d |-> (`ID.instr_valid_i ? pre_pc : `CR.pc_if) == wbexc_dut_post_pc) + PCNoChangeBranch: have (wbexc_exists & wbexc_is_mem_instr & ~wbexc_err & ex_has_branched_d |-> pre_pc == wbexc_dut_post_pc) + PCMaintainWb: have (wbexc_exists & wbexc_is_mem_instr & ~wbexc_err |-> wbexc_post_pc == wbexc_dut_post_pc) + LoadAddrMaintain: have (wbexc_exists & wbexc_is_load_instr & ~wbexc_err |-> wbexc_post_wX_en && `WBG.rf_waddr_wb_q == wbexc_post_wX_addr) + StoreAddrMaintain: have (wbexc_exists & wbexc_is_store_instr & ~wbexc_err |-> ~wbexc_post_wX_en & ~`WBG.rf_we_wb_q & ~`WBG.cheri_rf_we_q) + + ReadOrWrite: have (`ID.instr_valid_i & ex_is_mem_instr & ~ex_kill & (spec_mem_read | spec_mem_write) |-> ~`IDC.illegal_insn_d) + + RevokeEnCheckPasses: have ( + wbexc_exists & `IS_LOADCAPIMM & ~wbexc_err |-> + wbexc_spec_mem_revoke_en == ( + wbexc_spec_mem_read_cap.tag & + ~`LSU.resp_lc_clrperm_q[3] & + ~(wbexc_spec_mem_read_cap.permit_seal | wbexc_spec_mem_read_cap.permit_unseal | wbexc_spec_mem_read_cap.perm_user0) + ) + ) + RevokeAddrMatch: have ( + wbexc_exists & `IS_LOADCAPIMM & wbexc_spec_mem_revoke_en |-> + wbexc_spec_mem_revoke_addr == (wbexc_spec_mem_read_cap_bounds.base & ~32'b111) + ) + RevokeRangeCheck: have ( + wbexc_exists & `IS_LOADCAPIMM & wbexc_spec_mem_revoke_en & wbexc_spec_mem_revoke |-> + (wbexc_spec_mem_revoke_addr - HeapBase) >> 8 < TSMapSize + ) + + FinalCapAltLSU: have ( + wbexc_exists & ~wbexc_err & `IS_LOADCAPIMM |-> + onlySealingPerms(revoke(wbexc_spec_mem_read_cap, `LSU.resp_lc_clrperm_q[3])) + == onlySealingPerms(alt_lsu_late_res) + ) + / + RevokeMatch: have ( + `IS_LOADCAPIMM & wbexc_finishing & ~wbexc_err |-> ##3 + `RF.trvk_en_i && + `RF.trvk_clrtag_i == ($past(wbexc_spec_mem_revoke_en, 3) & $past(wbexc_spec_mem_revoke, 3)) + ) + +lemma load + cond (ex_is_load_instr) + + NoWe: have (spec_mem_read |-> ~data_we_o) + En: have (data_req_o |-> spec_mem_read) + / + SndEn: have (mem_req_snd_d |-> spec_mem_read_snd) + / + FstAddr: have (mem_req_fst_d |-> spec_mem_read_fst_addr == data_addr_o) + SndAddr: have (mem_req_snd_d |-> spec_mem_read_snd_addr == data_addr_o) + / + End: in (instr_will_progress) + Fst: have (spec_mem_read |-> mem_gnt_fst_d) + Snd: have (spec_mem_read_snd |-> mem_gnt_snd_d) + +lemma store + cond (ex_is_store_instr) + + We: have (spec_mem_write |-> data_we_o) + En: have (data_req_o |-> spec_mem_write) + / + SndEn: have (mem_req_snd_d |-> spec_mem_write_snd) + / + FstAddr: have (mem_req_fst_d |-> spec_mem_write_fst_addr == data_addr_o) + FstWData: have (mem_req_fst_d |-> (spec_mem_write_fst_wdata & fst_mask) == (data_wdata_o & fst_mask)) + SndAddr: have (mem_req_snd_d |-> spec_mem_write_snd_addr == data_addr_o) + SndWData: have (mem_req_snd_d |-> (spec_mem_write_snd_wdata & snd_mask) == (data_wdata_o & snd_mask)) + / + End: in (instr_will_progress) + Fst: have (spec_mem_write |-> mem_gnt_fst_d) + Snd: have (spec_mem_write_snd |-> mem_gnt_snd_d) diff --git a/vendor/lowrisc_ibex/dv/formal/thm/riscv.proof b/vendor/lowrisc_ibex/dv/formal/thm/riscv.proof new file mode 100644 index 000000000..4a1667673 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/thm/riscv.proof @@ -0,0 +1,212 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +def csr_split + each X Priv:(priv) Mstatus:(mstatus) Mie:(mie) Mcause:(mcause) Mtval:(mtval) \ + Mscratch:(mscratch) Mcounteren:(mcounteren) NMIMode:(nmi_mode) \ + MStack:(mstack) MStackCause:(mstack_cause) MStackEpc:(mstack_epc) + have (wbexc_spec_cmp_post_``X == wbexc_dut_cmp_post_``X) + + each X Mtvec:(mtvec) Mepc:(mepc) MscratchC:(mscratchc) Pcc:(pcc) Mtdc:(mtdc) + have (alas(wbexc_spec_cmp_post_``X, wbexc_dut_cmp_post_``X)) + +def spec_compliant_raw_csr_split + Addr: have (addr_match) + Data: have (data_match) + PC: have (pc_match) + use csr_split + +def spec_compliant_raw + Addr: have (addr_match) + Data: have (data_match) + CSR: have (csrs_match) + PC: have (pc_match) + +def spec_compliant + cond (finishing_executed & ~wbexc_illegal) + use spec_compliant_raw + +def spec_compliant_no_err + cond (finishing_executed & ~wbexc_illegal) + NoErr: have (~wbexc_err) + / + use spec_compliant_raw + +def structure_fast + cond (finishing_executed & ~wbexc_illegal) + Fast: have ($past(instr_will_progress)) + +def structure_fast_err + cond (finishing_executed & ~wbexc_illegal & wbexc_err) + Fast: have ($past(instr_will_progress)) + +def structure_fast_cheri + cond (finishing_executed & ~wbexc_illegal) + FastErr: have (wbexc_err |-> $past(instr_will_progress, 2)) + FastNormal: have (~wbexc_err |-> $past(instr_will_progress)) + +lemma riscv + Ibex: lemma ibex + + / + + Base: + in I:(`IS_ADDI | `IS_SLTI | `IS_SLTIU | `IS_XORI | `IS_ORI | `IS_ANDI) \ + R:(`IS_ADD | `IS_SUB | `IS_SLL | `IS_SLT | `IS_SLTU | `IS_XOR | `IS_SRL | `IS_SRA | `IS_OR | `IS_AND) \ + Shift:(`IS_SHIFTIOP) \ + Lui:(`IS_LUI) \ + Fence:(`IS_FENCE) FenceI:(`IS_FENCEI) + use structure_fast + / + use spec_compliant_no_err + + Cheri: + in CGet:(`IS_CGET) CSeal:(`IS_CSEAL_ANDPERM) CAddr:(`IS_CSETADDRx) CBounds:(`IS_CSETBOUNDSx) \ + CMov:(`IS_CCLRSUBMOV) AUIC:(`IS_AUIC) CCmp:(`IS_CCMP) CHigh:(`IS_CHIGH) + use structure_fast + / + use spec_compliant_no_err + + CheriJump: + in CJal:(`IS_CJAL) CJalR:(`IS_CJALR) + use structure_fast_cheri + / + use spec_compliant + + CheriCSR: + in (`IS_CSPECIALRW) + use structure_fast_cheri + / + use spec_compliant + + MType: + in Mul:(`IS_MUL) MulH:(`IS_MULH) MulHSH:(`IS_MULHSH) MulHU:(`IS_MULHU) Div:(`IS_DIV) DivU:(`IS_DIVU) Rem:(`IS_REM) RemU:(`IS_REMU) + use spec_compliant_no_err + + CSR: + in (`IS_CSR & wbexc_is_checkable_csr) + use structure_fast + / + use spec_compliant + split_bool Err:(wbexc_err) + + BType: + in (`IS_BTYPE) + lemma btype + use structure_fast + / + use spec_compliant + + JAL: + in (`IS_JAL) + lemma jump + use structure_fast + / + use spec_compliant + + Special: + in ECall:(`IS_ECALL) EBreak:(`IS_EBREAK) MRet:(`IS_MRET) WFI:(`IS_WFI) + use structure_fast + / + use spec_compliant + + Mem: block + FastErr: have (finishing_executed & ~wbexc_illegal & wbexc_err & wbexc_is_mem_instr |-> $past(instr_will_progress, 2)) + lemma mem + / + Load: lemma load + Store: lemma store + / + in L:(wbexc_is_load_instr & (`IS_LOADCAPIMM -> wbexc_err)) S:(wbexc_is_store_instr) + cond (finishing_executed & ~wbexc_illegal) + use spec_compliant_raw + split_bool Err:(wbexc_err) + in CLC:(`IS_LOADCAPIMM & ~wbexc_err) + cond (finishing_executed & ~wbexc_illegal) + Addr: have (addr_match) + CSR: have (csrs_match) + PC: have (pc_match) + DataNoTRVK: have (`WB.rf_waddr_wb_o == 5'b0 or ~res_data.tag |-> data_match) + DataTRVK: have (`WB.rf_waddr_wb_o != 5'b0 and res_data.tag |-> ##3 alas($past(wbexc_post_wX, 3), post_trvk_regs[$past(`WB.rf_waddr_wb_o, 3)])) + + + IRQ: in (wbexc_handling_irq) + # FIXME: Check RF + PC: have (pc_match) + CSR: have (csrs_match) + + Illegal: in (wbexc_illegal & wbexc_finishing & ~wbexc_fetch_err & (`IS_CSR -> wbexc_is_checkable_csr)) + Fast: have ($past(instr_will_progress)) + / + use spec_compliant_raw + + FetchErr: in (wbexc_finishing & wbexc_fetch_err) + Fast: have ($past(instr_will_progress)) + / + use spec_compliant_raw + + / + + # Liveness: lemma live + + Top: in (wbexc_finishing & (`IS_CSR -> wbexc_is_checkable_csr) & (`IS_LOADCAPIMM -> wbexc_err)) + use spec_compliant_raw + + / + + RegMatch: + each i 1:(1) 2:(2) 3:(3) 4:(4) 5:(5) 6:(6) 7:(7) 8:(8) 9:(9) 10:(10) 11:(11) 12:(12) 13:(13) 14:(14) \ + 15:(15) 16:(16) 17:(17) 18:(18) 19:(19) 20:(20) 21:(21) 22:(22) 23:(23) 24:(24) 25:(25) 26:(26) \ + 27:(27) 28:(28) 29:(29) 30:(30) 31:(31) + have ((~`CR.rf_write_wb || `CR.rf_waddr_wb != i) & spec_past_has_reg[i] & `RF.reg_rdy_o[i] |-> alas(spec_past_regs[i], pre_regs[i])) + + SpecPastNoWbexc: + in (has_spec_past & ~wbexc_exists) + each X Priv:(priv) Mstatus:(mstatus) Mie:(mie) Mcause:(mcause) Mtval:(mtval) \ + Mscratch:(mscratch) Mcounteren:(mcounteren) NMIMode:(nmi_mode) \ + MStack:(mstack) MStackCause:(mstack_cause) MStackEpc:(mstack_epc) + have (spec_past_``X == pre_``X) + + each X Mtvec:(mtvec) Mepc:(mepc) MscratchC:(mscratchc) Pcc:(pcc) Mtdc:(mtdc) + have (alas(spec_past_``X, pre_``X)) + + SleepSpecPastPC: have (has_spec_past & (`IDC.ctrl_fsm_cs == `IDC.WAIT_SLEEP || `IDC.ctrl_fsm_cs == `IDC.SLEEP) |-> spec_past_pc == `CR.pc_if) + + SpecPastInvalidPC: have (has_spec_past & wbexc_exists & ~ex_kill & ~`ID.instr_valid_i |-> spec_past_pc == `CR.pc_if) + / + SpecPastNoWbexcPC: have (has_spec_past & ~wbexc_exists |-> spec_past_pc == (`ID.instr_valid_i ? pre_pc : `CR.pc_if)) + / + + Wrap: in (spec_en) + each X Priv:(priv) Mstatus:(mstatus) Mie:(mie) Mcause:(mcause) Mtval:(mtval) \ + Mscratch:(mscratch) Mcounteren:(mcounteren) Pc:(pc) NMIMode:(nmi_mode) \ + MStack:(mstack) MStackCause:(mstack_cause) MStackEpc:(mstack_epc) + have (has_spec_past |-> spec_past_``X == pre_``X) + + each X Mtvec:(mtvec) Mepc:(mepc) MscratchC:(mscratchc) Pcc:(pcc) Mtdc:(mtdc) + have (has_spec_past |-> alas(spec_past_``X, pre_``X)) + + RegA: have (reg_driven[`CR.rf_raddr_a] && spec_past_has_reg[`CR.rf_raddr_a] |-> alas(spec_past_regs[`CR.rf_raddr_a], pre_regs_cut[`CR.rf_raddr_a])) + RegB: have (reg_driven[`CR.rf_raddr_b] && spec_past_has_reg[`CR.rf_raddr_b] |-> alas(spec_past_regs[`CR.rf_raddr_b], pre_regs_cut[`CR.rf_raddr_b])) + + # Live: have (always (##[1:157 + 2*`WFI_BOUND + 17*`TIME_LIMIT] spec_en)) + + Mem: + block + En: have (data_req_o |-> spec_mem_en) + SndEn: have (mem_req_snd_d |-> spec_mem_en_snd) + + We: have (data_req_o |-> data_we_o == spec_mem_write && data_we_o == ~spec_mem_read) + + FstAddr: have (mem_req_fst_d |-> spec_mem_fst_addr == data_addr_o) + SndAddr: have (mem_req_snd_d |-> spec_mem_snd_addr == data_addr_o) + + FstWData: have (mem_req_fst_d & data_we_o |-> (spec_mem_write_fst_wdata & fst_mask) == (data_wdata_o[31:0] & fst_mask)) + SndWData: have (mem_req_snd_d & data_we_o |-> (spec_mem_write_snd_wdata & snd_mask) == (data_wdata_o[31:0] & snd_mask)) + WTag: have (mem_req_fst_d & data_we_o |-> spec_mem_write_tag == data_wdata_o[32]) + + FstEnd: have (spec_en & spec_mem_en |-> mem_gnt_fst_d) + SndEnd: have (spec_en & spec_mem_en_snd |-> mem_gnt_snd_d) diff --git a/vendor/lowrisc_ibex/dv/formal/verify.tcl b/vendor/lowrisc_ibex/dv/formal/verify.tcl new file mode 100644 index 000000000..f86b18182 --- /dev/null +++ b/vendor/lowrisc_ibex/dv/formal/verify.tcl @@ -0,0 +1,131 @@ +# Copyright lowRISC contributors. +# Copyright 2024 University of Oxford, see also CREDITS.md. +# Licensed under the Apache License, Version 2.0 (see LICENSE for details). +# The underlying commands and reports of this script are copyrighted by Cadence. +# We thank Cadence for granting permission to share our research to help +# promote and foster the next generation of innovators. +# Original Author: Louis-Emile Ploix +# SPDX-License-Identifier: Apache-2.0 + +clear -all + +set_prove_cache_path jgproofs +set_prove_cache on +set_prove_cache_mode coi + +set_prove_per_property_time_limit 10s + +# Load all Ibex RTL, using the filelist generated by fusesoc +analyze -sv12 +define+SYNTHESIS -f_relative_to_file_location build/fusesoc/default-vcs/lowrisc_ibex_ibex_formal_0.1.scr + +set sail_lib_dir $env(LOWRISC_SAIL_SRC)/lib/sv + +analyze -sv12 -incdir $sail_lib_dir build/ibexspec.sv +analyze -sv12 spec/stub.sv +analyze -sv12 build/extracted.sv +analyze -sv12 spec/cheri.sv + +analyze -sv12 spec/spec_api.sv + +# analyze -sv12 bound/binder.sv +# analyze -sv12 bound/if.sv + +analyze -sv12 check/peek/alt_lsu.sv +analyze -sv12 check/top.sv + +elaborate -top top -disable_auto_bbox +clock clk_i +reset ~rst_ni + +set_proofgrid_max_local_jobs 10 +set_proofgrid_per_engine_max_local_jobs 8 + +# AMcustom1 +custom_engine -add -code hT3N1rhP11/52HrFRS21ROp2LOjVTgPvT8L8BGXHgLhaIuqtT4nARFjUqrBL+7pLmaTOzBepZW/Jm8SSrHDybSQtoNiO3y43wk+dEoWlsZizu97Fih6O6lPVG/LpWP5SsUPwlGagLNa1FKEFvwVXyX7//8prySbvSxIHXr5er+z4RAEA + +# AMcustom2 +custom_engine -add -code hT3Ng7hP/feYQOTDZ3qhYOwGAM51eA+J/FjkM5shLioAsqhgLR4Ft+O1BuKG6ilQ83B9tLXSmmqwm7g9AQA + +# Ncustom3 +custom_engine -add -code hT3OXrhPByJp3TrFSTLhUmMH4KVtJgmTCnNDF46yMXOKY48m4LS5nE7yBzFjA7kDuwO/GhGUpEPiky3p3wmPn3dJZHxFMsafSoObRzSC+tn7sEY0WbTdZ/FV4hL3MYH/b1CIUvXSWR4wqEoVLsmMOD4xIPT4lI1LO6ZCO7PnnWQuLwetnvKlrXx6wCW/A+x+enqslg1YPobi4wEF/EvbzOvcTYdJvl2s4H2yZg2b2ofAVN5WvhWk1HoBAA + +# ADcustom4 +custom_engine -add -code hT3Nv7hPv1752HrFRa2kROx2f/ECJeZB2AZsLdlO8VwmIuqtT4nIDFXclhg+O+o+DMmQCekbheGk0kK28laA9gaOFDXsQp29J3X615HY1IPHJWd6FUFvCHjO+p1k652b5JJvZlShNpGlGSXAiQe/mEAj6tEBAA + +# Ncustom5 +custom_engine -add -code hT3Ng7hPPfiYQOTDZ3qhYOwGAM51eA+J/FjkM5shLioAsqhgLR4Ft+O1BuKG6ilQ83B9tLXSl+CwjiTMAQA + +# Mpcustom6 +custom_engine -add -code hT3NZbhP9fmY2AbBQnsjfOxn6c+6e6yL+/e8fZFmaQrnlgEA + +proc assume_mtypes {} { + assume -from_assert {Step11::top.MType_*_NoErr Step12::top.MType_*_Data Step12::top.MType_*_CSR Step12::top.MType_*_PC Step12::top.MType_*_Addr} +} + +proc prove_hps {task regex} { + set props [get_property_list -task $task -include "disabled 0 type assert name $regex" -exclude "status proven"] + set len [llength $props] + for {set i 0} {$i <[llength $props]} {incr i 10} { + for {set j 0} {$j < 10 && ($i + $j) < $len} {incr j} { + set idx [expr {$i + $j}] + prove -bg -property [lindex $props $idx] -engine_mode Hp + } + prove -wait + } +} + +# TODO: Add liveness checking +proc prove_no_liveness {} { + assume_mtypes + + prove -task Step0 + prove -bg -task Step1 + prove -bg -task Step2 + prove -wait + prove -bg -task Step3 + prove -bg -task Step4 + prove -bg -task Step5 + prove -wait + prove_hps Step6 * + prove -bg -task Step7 + prove -wait + prove -bg -property {Step8::*SpecStable*} -engine_mode Hp + prove -bg -property {Step8::top.Ibex_FetchErrRoot} + # FIXME: ^ Failing to prove possibly + prove -bg -property {Step8::top.Ibex_PreNextPcMatch} + prove -wait + prove -task Step8 + prove -bg -task Step9 + prove -bg -task Step10 + prove -wait + prove_hps Step11 *MemSpec* + prove_hps Step11 *CapFsm* + prove -property {Step11::*.Mem_*} + prove_hps Step11 * + prove -property {Step12::*.BType_* Step12::*.JAL_*} + prove -property {Step12::*.Mem_*} + # FIXME: Illegal is slow + prove_hps Step12 * + prove -bg -property {Step13::*.Mem_* Step13::*.BType* Step13::*.JAL_*} + prove -bg -property {Step13::*Shift_Data} + prove -wait + prove_hps Step13 * + prove -task Step14 + prove -task Step15 + prove -task Step16 + prove -bg -task Step17 + prove -bg -task Step18 + prove -bg -task Step19 + prove -wait + prove -bg -task Step20 + prove -bg -task Step21 + prove -wait + prove_hps Step22 * + prove_hps Step23 * + prove_hps Step24 * + prove -bg -task Step25 + prove -bg -task Step26 + prove -wait +} + +source build/psgen.tcl diff --git a/vendor/lowrisc_ibex/flake.lock b/vendor/lowrisc_ibex/flake.lock new file mode 100644 index 000000000..7fa20fcfd --- /dev/null +++ b/vendor/lowrisc_ibex/flake.lock @@ -0,0 +1,380 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gomod2nix": { + "inputs": { + "flake-utils": [ + "psgen", + "flake-utils" + ], + "nixpkgs": [ + "psgen", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1717050755, + "narHash": "sha256-C9IEHABulv2zEDFA+Bf0E1nmfN4y6MIUe5eM2RCrDC0=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "31b6d2e40b36456e792cd6cf50d5a8ddd2fa59a1", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "lowrisc-nix": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "poetry2nix": "poetry2nix", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1727867828, + "narHash": "sha256-AKL2sRyc/e9uxokam/TDNPADzkhG+SQTfoaQ1wWjVKE=", + "owner": "lowrisc", + "repo": "lowrisc-nix", + "rev": "764a76080cff9a22a3fc31c0f35c01c1532d6eee", + "type": "github" + }, + "original": { + "owner": "lowrisc", + "repo": "lowrisc-nix", + "type": "github" + } + }, + "lowrisc_cheriot_sail": { + "flake": false, + "locked": { + "lastModified": 1736265471, + "narHash": "sha256-suOmvnFPpdH2fA/UpdMNVfE3GJh8yNzcekMy0Xv4aEA=", + "ref": "formal", + "rev": "7bc3904957cd20337973ea7b63af3838eae4d93c", + "revCount": 471, + "submodules": true, + "type": "git", + "url": "https://github.com/lowrisc/cheriot-sail" + }, + "original": { + "ref": "formal", + "submodules": true, + "type": "git", + "url": "https://github.com/lowrisc/cheriot-sail" + } + }, + "lowrisc_sail": { + "flake": false, + "locked": { + "lastModified": 1719847350, + "narHash": "sha256-KOjNg6Av//KLp4/aQEIVCe157ac90lyZ6CZArPIWL8o=", + "owner": "lowrisc", + "repo": "sail", + "rev": "3f317060d2800c88432cc1309255a7c674bcab41", + "type": "github" + }, + "original": { + "owner": "lowrisc", + "ref": "lowrisc", + "repo": "sail", + "type": "github" + } + }, + "mkshell-minimal": { + "locked": { + "lastModified": 1700988624, + "narHash": "sha256-KJyiF67zVYOBkNltKhJATfSj+gfRFX9dSFIWDEBy2nQ=", + "owner": "viperML", + "repo": "mkshell-minimal", + "rev": "6b0868be06da900b5fe6ece05616b84e3cbd7944", + "type": "github" + }, + "original": { + "owner": "viperML", + "repo": "mkshell-minimal", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "lowrisc-nix", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703863825, + "narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "5163432afc817cf8bd1f031418d1869e4c9d5547", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-github-actions_2": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1720066371, + "narHash": "sha256-uPlLYH2S0ACj0IcgaK9Lsf4spmJoGejR9DotXiXSBZQ=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "622f829f5fe69310a866c8a6cd07e747c44ef820", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1727672256, + "narHash": "sha256-9/79hjQc9+xyH+QxeMcRsA6hDyw6Z9Eo1/oxjvwirLk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1719f27dd95fd4206afb9cec9f415b539978827e", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-24.05", + "type": "indirect" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": [ + "lowrisc-nix", + "flake-utils" + ], + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "lowrisc-nix", + "nixpkgs" + ], + "systems": "systems_2", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1723854676, + "narHash": "sha256-+BrHfNuXrqeE7PoV6xDaoh0joYiJkvTTCIV0fFR3THw=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d650118bce34c0238b9b54f23f7f173f9e4db867", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "poetry2nix_2": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nix-github-actions": "nix-github-actions_2", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_3", + "treefmt-nix": "treefmt-nix_2" + }, + "locked": { + "lastModified": 1727711975, + "narHash": "sha256-zkkL5gw+TNXhVO2zpeH70TKh2dSzUbkBbO6gKHO37s0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "ef877b8e159b23f36ebc39155021657bed744a68", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "psgen": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "gomod2nix": "gomod2nix", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723038779, + "narHash": "sha256-L/toJC6lyeVJy2Uswse8aCrhdt0mTxDfn8t0NpNVn/I=", + "owner": "mndstrmr", + "repo": "psgen", + "rev": "2d0c1e0690cf6c3b9b1bf4f51bccab4698f4e21f", + "type": "github" + }, + "original": { + "owner": "mndstrmr", + "repo": "psgen", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "lowrisc-nix": "lowrisc-nix", + "lowrisc_cheriot_sail": "lowrisc_cheriot_sail", + "lowrisc_sail": "lowrisc_sail", + "mkshell-minimal": "mkshell-minimal", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix_2", + "psgen": "psgen" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "lowrisc-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724034091, + "narHash": "sha256-b1g7w0sw+MDAhUAeCoX1vlTghsqcDZkxr+k9OZmxPa8=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "c7d36e0947826e0751a5214ffe82533fbc909bc0", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "id": "systems", + "type": "indirect" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "id": "systems", + "type": "indirect" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "lowrisc-nix", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1719749022, + "narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1727431250, + "narHash": "sha256-uGRlRT47ecicF9iLD1G3g43jn2e+b5KaMptb59LHnvM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "879b29ae9a0378904fbbefe0dadaed43c8905754", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/vendor/lowrisc_ibex/flake.nix b/vendor/lowrisc_ibex/flake.nix new file mode 100644 index 000000000..f4a297962 --- /dev/null +++ b/vendor/lowrisc_ibex/flake.nix @@ -0,0 +1,163 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +{ + description = "Nix Flake for Ibex development and testing."; + + inputs = { + nixpkgs.url = "nixpkgs/nixos-24.05"; + flake-utils.url = "github:numtide/flake-utils"; + + poetry2nix = { + url = "github:nix-community/poetry2nix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + mkshell-minimal.url = "github:viperML/mkshell-minimal"; + + lowrisc-nix = { + url = "github:lowrisc/lowrisc-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + + psgen = { + url = "github:mndstrmr/psgen"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + lowrisc_sail = { + url = "github:lowrisc/sail?ref=lowrisc"; + flake = false; + }; + lowrisc_cheriot_sail = { + url = "git+https://github.com/lowrisc/cheriot-sail?ref=formal&submodules=1"; + flake = false; + }; + }; + + # The lowRISC public nix-cache contains builds of nix packages used by lowRISC, primarily coming from github:lowRISC/lowrisc-nix. + nixConfig = { + extra-substituters = ["https://nix-cache.lowrisc.org/public/"]; + extra-trusted-public-keys = ["nix-cache.lowrisc.org-public-1:O6JLD0yXzaJDPiQW1meVu32JIDViuaPtGDfjlOopU7o="]; + }; + + outputs = inputs @ {self, ...}: let + # System types to support. + supportedSystems = with inputs.flake-utils.lib.system; [ + x86_64-linux + ]; + + # The .#formal shellHook always checks for jg on the path. + # Should we check for a given version of the tool as well? + check_jg_version = false; + expected_jaspergold_version = "2021.12 FCS 64 bits"; + in + inputs.flake-utils.lib.eachSystem supportedSystems ( + system: let + pkgs = import inputs.nixpkgs { + inherit system; + }; + inherit (pkgs) lib; + + mkshell-minimal = inputs.mkshell-minimal pkgs; + + # lowRISC fork of the Sail repository. The SAIL -> SV flow is used to generate the reference model. + lowrisc_sail = import ./nix/lowrisc_sail.nix { + inherit pkgs; + src = inputs.lowrisc_sail; + }; + + # RISCV Sail model with changes for Ibex + lowrisc_cheriot_sail.src = + (import ./nix/lowrisc_cheriot_sail.nix { + inherit pkgs; + src = inputs.lowrisc_cheriot_sail; + }) + .src; + + # Create a python package set suitable for the formal flow + # - The file dv/formal/pyproject.toml defines the package set for this environment + # - Using the fusesoc .core files in this repo requires a lowrisc-fork of fusesoc, so this + # file specifies the forked repository. Most other python package dependencies are in + # support of fusesoc. + formal_python_env = let + poetry2nix = inputs.poetry2nix.lib.mkPoetry2Nix {inherit pkgs;}; + lowriscPoetryOverrides = inputs.lowrisc-nix.lib.poetryOverrides {inherit pkgs;}; + in + poetry2nix.mkPoetryEnv { + projectDir = ./dv/formal; + overrides = [ + lowriscPoetryOverrides + poetry2nix.defaultPoetryOverrides + ]; + }; + in { + packages = { + # Export the package for the lowrisc fork of the sail compiler. This allows us + # to re-use its build environment. + inherit lowrisc_sail; + }; + devShells = rec { + formal = mkshell-minimal { + packages = + [ + inputs.psgen.packages.${system}.default + lowrisc_sail + formal_python_env + ] + ++ (with pkgs; [ + gnumake + patch + ]); + shellHook = let + # The formal environment has an untracked external requirement on Cadence JasperGold. + # Add a check here which will prevent launching the devShell if JasperGold is not found on the user's path. + # TODO: Is this robust? Do we want to check available features? + check_jg = + '' + if ! command -v jg &>/dev/null; then + echo "JasperGold not found on path. Not launching devShell." + exit 1 + fi + '' + + lib.optionalString check_jg_version '' + jg_version=$(jg -version -allow_unsupported_OS) + if [[ $jg_version != "${expected_jaspergold_version}" ]]; then + echo "Incorrect JasperGold version found on path." + echo "Expected \"${expected_jaspergold_version}\", Got \"$jg_version\"." + echo "Not launching devShell." + exit 1 + fi + ''; + in '' + ${check_jg} + # The following environment variables are used by the formal build scripts to pick up the locations + # of the external source-file dependencies. + # The can be re-exported manually for development (see .#formal-dev) + export LOWRISC_SAIL_SRC=${lowrisc_sail.src} + export LOWRISC_CHERIOT_SAIL_SRC=${lowrisc_cheriot_sail.src} + ''; + }; + + formal-dev = formal.overrideAttrs (prev: { + shellHook = + prev.shellHook + + '' + cat << EOF + ====================================================================================== + This is a development shell, by default it is identical to the full formal shell. + In order to use a local version of psgen or Sail, just prepend to the current path now: + export PATH=:\$PATH + For updates to Sail also update LOWRISC_SAIL_SRC: + export LOWRISC_SAIL_SRC= + In order to use a local version of sail-riscv update LOWRISC_CHERIOT_SAIL_SRC: + export LOWRISC_CHERIOT_SAIL_SRC= + ====================================================================================== + EOF + ''; + }); + }; + } + ); +} diff --git a/vendor/lowrisc_ibex/nix/lowrisc_cheriot_sail.nix b/vendor/lowrisc_ibex/nix/lowrisc_cheriot_sail.nix new file mode 100644 index 000000000..b0184ec62 --- /dev/null +++ b/vendor/lowrisc_ibex/nix/lowrisc_cheriot_sail.nix @@ -0,0 +1,15 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# CHERIoT Sail model with changes for Ibex +{ + pkgs, + src, +}: +pkgs.sail-riscv-rv32.overrideAttrs { + pname = "lowrisc_cheriot_sail"; + inherit src; + + # The upstream patches does not apply to our older version of riscv_sail. + patches = []; +} diff --git a/vendor/lowrisc_ibex/nix/lowrisc_sail.nix b/vendor/lowrisc_ibex/nix/lowrisc_sail.nix new file mode 100644 index 000000000..b5dc15d23 --- /dev/null +++ b/vendor/lowrisc_ibex/nix/lowrisc_sail.nix @@ -0,0 +1,23 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# Override the upstream sail package definition to use the lowRISC fork +{ + pkgs, + src, +}: +pkgs.ocamlPackages.sail.overrideAttrs (prev: { + pname = "lowrisc_sail"; + inherit src; + + # The lowRISC fork is older than upstream, and requires additional dependencies + # from those specified upsteam to build. Add them here. + propagatedBuildInputs = + prev.propagatedBuildInputs + ++ (with pkgs.ocamlPackages; [ + menhirLib + ]) + ++ (with pkgs; [ + z3 + ]); +}) diff --git a/vendor/lowrisc_ibex/rtl/cheri_decoder.sv b/vendor/lowrisc_ibex/rtl/cheri_decoder.sv index 8b2686fce..113c95f95 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_decoder.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_decoder.sv @@ -55,6 +55,7 @@ module cheri_decoder import cheri_pkg::*; # ( cheri_operator_o[CCSR_RW] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h01); cheri_operator_o[CSET_BOUNDS] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h08); cheri_operator_o[CSET_BOUNDS_EX] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h09); + cheri_operator_o[CSET_BOUNDS_RNDN]= cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h0a); cheri_operator_o[CSEAL] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h0b); cheri_operator_o[CUNSEAL] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h0c); cheri_operator_o[CAND_PERM] = cheri_opcode_en_i && (func3_op==0) && (func7_op==7'h0d); @@ -82,6 +83,7 @@ module cheri_decoder import cheri_pkg::*; # ( cheri_operator_o[CINC_ADDR_IMM] = cheri_opcode_en_i && (func3_op == 1); cheri_operator_o[CSET_BOUNDS_IMM] = cheri_opcode_en_i && (func3_op == 2); + cheri_operator_o[CAUIPCC] = cheri_auipcc_en_i; cheri_operator_o[CAUICGP] = cheri_auicgp_en_i; cheri_operator_o[CJALR] = cheri_jalr_en_i; diff --git a/vendor/lowrisc_ibex/rtl/cheri_ex.sv b/vendor/lowrisc_ibex/rtl/cheri_ex.sv index 615c00a13..c8e03021e 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_ex.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_ex.sv @@ -7,12 +7,13 @@ module cheri_ex import cheri_pkg::*; #( parameter bit WritebackStage = 1'b0, parameter bit MemCapFmt = 1'b0, - parameter int unsigned HeapBase = '0, - parameter int unsigned TSMapBase = '0, - parameter int unsigned TSMapSize = '0, + parameter int unsigned HeapBase = 32'h2001_0000, + parameter int unsigned TSMapBase = 32'h2002_f000, + parameter int unsigned TSMapSize = 1024, parameter bit CheriPPLBC = 1'b1, parameter bit CheriSBND2 = 1'b0, - parameter bit CheriStkZ = 1'b1 + parameter bit CheriStkZ = 1'b1, + parameter bit CheriCapIT8 = 1'b0 )( // Clock and Reset input logic clk_i, @@ -195,7 +196,7 @@ module cheri_ex import cheri_pkg::*; #( logic lc_cglg, lc_csdlm, lc_ctag; logic [31:0] pc_id_nxt; - full_cap_t setaddr1_outcap, setbounds_outcap; + full_cap_t setaddr1_outcap, setbounds_outcap, setbounds_rndn_outcap; logic [15:0] cheri_wb_err_info_q, cheri_wb_err_info_d; logic set_bounds_done; @@ -356,8 +357,10 @@ module cheri_ex import cheri_pkg::*; #( cheri_operator_i[CGET_HIGH]: begin logic [65:0] tmp66; - tmp66 = MemCapFmt ? reg2mem_fmt1(rf_rcap_a, rf_rdata_a) : - {reg2memcap_fmt0(rf_rcap_a), 1'b0, rf_rdata_a[31:0]}; + tmp66 = MemCapFmt ? (CheriCapIT8 ? reg2mem_it8_fmt1(rf_rcap_a, rf_rdata_a) : + reg2mem_fmt1(rf_rcap_a, rf_rdata_a)) : + (CheriCapIT8 ? {reg2memcap_it8_fmt0(rf_rcap_a), 1'b0, rf_rdata_a[31:0]} : + {reg2memcap_fmt0(rf_rcap_a), 1'b0, rf_rdata_a[31:0]}); result_data_o = tmp66[64:33]; result_cap_o = NULL_REG_CAP; cheri_rf_we_raw = 1'b1; @@ -382,11 +385,15 @@ module cheri_ex import cheri_pkg::*; #( end cheri_operator_i[CAND_PERM]: // cd <-- cs1; cd.perm <-- cd.perm & rs2 begin + logic [PERMS_W-1:0] pmask; result_data_o = rf_rdata_a; tfcap = rf_fullcap_a; tfcap.perms = tfcap.perms & rf_rdata_b[PERMS_W-1:0]; tfcap.cperms = compress_perms(tfcap.perms, tfcap.cperms[5:4]); - tfcap.valid = tfcap.valid & ~is_cap_sealed(rf_fullcap_a); + // for sealed caps, clear tag unless perm mask (excluding GL) == all '1' + pmask = rf_rdata_b[PERMS_W-1:0]; + pmask[PERM_GL] = 1'b1; + tfcap.valid = tfcap.valid & (~is_cap_sealed(rf_fullcap_a) | (&pmask)); result_cap_o = full2regcap(tfcap); cheri_rf_we_raw = 1'b1; cheri_ex_valid_raw = 1'b1; @@ -395,7 +402,8 @@ module cheri_ex import cheri_pkg::*; #( begin // this only works for memcap_fmt0 for now QQQ result_data_o = rf_rdata_a; - result_cap_o = mem2regcap_fmt0({1'b0, rf_rdata_b}, {1'b0, rf_rdata_a}, 4'h0); + result_cap_o = CheriCapIT8 ? mem2regcap_it8_fmt0({1'b0, rf_rdata_b}, {1'b0, rf_rdata_a}, 4'h0) : + mem2regcap_fmt0({1'b0, rf_rdata_b}, {1'b0, rf_rdata_a}, 4'h0); cheri_rf_we_raw = 1'b1; cheri_ex_valid_raw = 1'b1; end @@ -422,11 +430,11 @@ module cheri_ex import cheri_pkg::*; #( cheri_ex_valid_raw = 1'b1; end (cheri_operator_i[CSET_BOUNDS] | cheri_operator_i[CSET_BOUNDS_IMM] | cheri_operator_i[CSET_BOUNDS_EX] | - cheri_operator_i[CRRL] | cheri_operator_i[CRAM]): + cheri_operator_i[CRRL] | cheri_operator_i[CRAM] | cheri_operator_i[CSET_BOUNDS_RNDN]): begin // cd <-- cs1; cd.base <-- cs1.address, cd.len <-- rs2 or imm12 logic instr_fault; - tfcap = setbounds_outcap; + tfcap = cheri_operator_i[CSET_BOUNDS_RNDN] ? setbounds_rndn_outcap : setbounds_outcap; tfcap.valid = tfcap.valid & ~is_cap_sealed(rf_fullcap_a); if (cheri_operator_i[CRRL]) begin @@ -443,7 +451,7 @@ module cheri_ex import cheri_pkg::*; #( cheri_ex_valid_raw = set_bounds_done; instr_fault = csr_dbg_tclr_fault_i & rf_fullcap_a.valid & ~result_cap_o.valid & (cheri_operator_i[CSET_BOUNDS] | cheri_operator_i[CSET_BOUNDS_IMM] | - cheri_operator_i[CSET_BOUNDS_EX]); + cheri_operator_i[CSET_BOUNDS_EX] | cheri_operator_i[CSET_BOUNDS_RNDN]); cheri_rf_we_raw = ~instr_fault; cheri_wb_err_raw = instr_fault; end @@ -580,7 +588,9 @@ module cheri_ex import cheri_pkg::*; #( // if branch prediction works) result_data_o = pc_id_nxt; seal_type = csr_mstatus_mie_i ? OTYPE_SENTRY_IE_BKWD : OTYPE_SENTRY_ID_BKWD; - tfcap = seal_cap(setaddr1_outcap, seal_type); + //tfcap = seal_cap(setaddr1_outcap, seal_type); + tfcap = (rf_waddr_i == 5'h1) ? seal_cap(setaddr1_outcap, seal_type) : + setaddr1_outcap; result_cap_o = full2regcap(tfcap); // problem with instr_fault: the pcc_cap.valid check causing timing issue on instr_addr_o @@ -715,7 +725,7 @@ module cheri_ex import cheri_pkg::*; #( full_cap_t tfcap3; // set_bounds - if (cheri_operator_i[CSET_BOUNDS]) begin + if (cheri_operator_i[CSET_BOUNDS] | cheri_operator_i[CSET_BOUNDS_RNDN]) begin newlen = rf_rdata_b; req_exact = 1'b0; tfcap3 = rf_fullcap_a; @@ -742,9 +752,13 @@ module cheri_ex import cheri_pkg::*; #( tmp_addr = 0; end - bound_req1 = prep_bound_req (tmp_addr, newlen); + bound_req1 = CheriCapIT8 ? prep_bound_req_it8 (tfcap3, tmp_addr, newlen) : + prep_bound_req (tfcap3, tmp_addr, newlen); setbounds_outcap = set_bounds(tfcap3, tmp_addr, bound_req1, req_exact); + + setbounds_rndn_outcap = CheriCapIT8 ? set_bounds_rndn_it8(tfcap3, tmp_addr, bound_req2) : + set_bounds_rndn(tfcap3, tmp_addr, bound_req2); end assign set_bounds_done = 1'b1; @@ -833,8 +847,11 @@ module cheri_ex import cheri_pkg::*; #( logic cs2_otype_45; // generate the address used to check top bound violation - if (cheri_operator_i[CSEAL] | cheri_operator_i[CUNSEAL]) + if (cheri_operator_i[CSEAL]) base_chkaddr = rf_rdata_b; // cs2.address + else if (cheri_operator_i[CUNSEAL]) + // inCapBounds(cs2_val, zero_extend(cs1_val.otype), 1) + base_chkaddr = {28'h0, decode_otype(rf_fullcap_a.otype, rf_fullcap_a.perms[PERM_EX])}; else if (cheri_operator_i[CIS_SUBSET]) base_chkaddr = rf_fullcap_b.base32; // cs2.base32 else // CLC/CSC @@ -901,22 +918,21 @@ module cheri_ex import cheri_pkg::*; #( perm_vio_vec[PVIO_SEAL] = is_cap_sealed(rf_fullcap_a); perm_vio_vec[PVIO_SD] = ~rf_fullcap_a.perms[PERM_SD]; perm_vio_vec[PVIO_SC] = (~rf_fullcap_a.perms[PERM_MC] && rf_fullcap_b.valid); - perm_vio_vec[PVIO_ALIGN] = (cheri_ls_chkaddr[2:0] != 0); + perm_vio_vec[PVIO_ALIGN] = (cheri_ls_chkaddr[2:0] != 0); perm_vio_slc = ~rf_fullcap_a.perms[PERM_SL] && rf_fullcap_b.valid && - (~rf_fullcap_b.perms[PERM_GL] | cs2_otype_45) ; + (~rf_fullcap_b.perms[PERM_GL]) ; end else if (cheri_operator_i[CSEAL]) begin cs2_bad_type = rf_fullcap_a.perms[PERM_EX] ? ((rf_rdata_b[31:3]!=0)||(rf_rdata_b[2:0]==0)) : ((|rf_rdata_b[31:4]) || (rf_rdata_b[3:0] <= 8)); // cs2.addr check : ex: 0-7, non-ex: 9-15 - perm_vio_vec[PVIO_TAG] = ~rf_fullcap_a.valid || ~rf_fullcap_b.valid; + perm_vio_vec[PVIO_TAG] = ~rf_fullcap_b.valid; perm_vio_vec[PVIO_SEAL] = is_cap_sealed(rf_fullcap_a) || is_cap_sealed(rf_fullcap_b) || (~rf_fullcap_b.perms[PERM_SE]) || cs2_bad_type; end else if (cheri_operator_i[CUNSEAL]) begin - perm_vio_vec[PVIO_TAG] = ~rf_fullcap_a.valid || ~rf_fullcap_b.valid; + perm_vio_vec[PVIO_TAG] = ~rf_fullcap_b.valid; perm_vio_vec[PVIO_SEAL] = (~is_cap_sealed(rf_fullcap_a)) || is_cap_sealed(rf_fullcap_b) || - (rf_rdata_b != {28'h0, decode_otype(rf_fullcap_a.otype, rf_fullcap_a.perms[PERM_EX])}) || - (~rf_fullcap_b.perms[PERM_US]); + (~rf_fullcap_b.perms[PERM_US]); end else if (cheri_operator_i[CJALR]) begin perm_vio_vec[PVIO_TAG] = ~rf_fullcap_a.valid; perm_vio_vec[PVIO_SEAL] = (is_cap_sealed(rf_fullcap_a) && (cheri_imm12_i != 0)) || @@ -1108,26 +1124,26 @@ module cheri_ex import cheri_pkg::*; #( // debug signal for FPGA only // logic [15:0] dbg_status; - logic [67:0] dbg_cs1_vec, dbg_cs2_vec, dbg_cd_vec; + logic [66:0] dbg_cs1_vec, dbg_cs2_vec, dbg_cd_vec; assign dbg_status = {4'h0, instr_is_rv32lsu_i, rv32_lsu_req_i, rv32_lsu_we_i, rv32_lsu_err, cheri_exec_id_i, cheri_lsu_err, rf_fullcap_a.valid, result_cap_o.valid, addr_bound_vio, perm_vio, addr_bound_vio_rv32, perm_vio_rv32}; - assign dbg_cs1_vec = {rf_fullcap_a.top_cor, rf_fullcap_a.base_cor, // 67:64 + assign dbg_cs1_vec = {rf_fullcap_a.top_cor, rf_fullcap_a.base_cor, // 66:64 rf_fullcap_a.exp, // 63:59 rf_fullcap_a.top, rf_fullcap_a.base, // 58:41 rf_fullcap_a.otype, rf_fullcap_a.cperms, // 40:32 rf_rdata_a}; // 31:0 - assign dbg_cs2_vec = {rf_fullcap_b.top_cor, rf_fullcap_b.base_cor, // 67:64 + assign dbg_cs2_vec = {rf_fullcap_b.top_cor, rf_fullcap_b.base_cor, // 66:64 rf_fullcap_b.exp, // 63:59 rf_fullcap_b.top, rf_fullcap_b.base, // 58:41 rf_fullcap_b.otype, rf_fullcap_b.cperms, // 40:32 rf_rdata_b}; // 31:0 - assign dbg_cd_vec = {result_cap_o.top_cor, result_cap_o.base_cor, // 67:64 + assign dbg_cd_vec = {result_cap_o.top_cor, result_cap_o.base_cor, // 66:64 result_cap_o.exp, // 63:59 result_cap_o.top, result_cap_o.base, // 58:41 result_cap_o.otype, result_cap_o.cperms, // 40:32 diff --git a/vendor/lowrisc_ibex/rtl/cheri_pkg.sv b/vendor/lowrisc_ibex/rtl/cheri_pkg.sv index fb18181bc..a0f4c42e0 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_pkg.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_pkg.sv @@ -9,22 +9,24 @@ package cheri_pkg; // bit field widths parameter int unsigned ADDR_W = 32; - parameter int unsigned TOP_W = 9; + parameter int unsigned TOP_W = 9; + parameter int unsigned TOP8_W = 8; // IT8 encoding only parameter int unsigned BOT_W = 9; parameter int unsigned CEXP_W = 4; + parameter int unsigned CEXP5_W = 5; // IT8 encoding only parameter int unsigned EXP_W = 5; parameter int unsigned OTYPE_W = 3; parameter int unsigned CPERMS_W = 6; - parameter int unsigned PERMS_W = 13; + parameter int unsigned PERMS_W = 12; - parameter int unsigned REGCAP_W = 38; + parameter int unsigned REGCAP_W = 37; parameter bit [4:0] RESETEXP = 24; parameter int unsigned UPPER_W = 24; - parameter bit [3:0] RESETCEXP = 15; + parameter bit [4:0] RESETCEXP = 15; // only used in non-IT8 encoding // bit index of PERMS field - // U1 U0 SE US EX SR MC LD SL LM SD LG GL + // U0 SE US EX SR MC LD SL LM SD LG GL parameter int unsigned PERM_GL = 0; // global flag parameter int unsigned PERM_LG = 1; // load global parameter int unsigned PERM_SD = 2; // store @@ -37,8 +39,6 @@ package cheri_pkg; parameter int unsigned PERM_US = 9; // unseal parameter int unsigned PERM_SE = 10; // seal parameter int unsigned PERM_U0 = 11; // - parameter int unsigned PERM_U1 = 12; // -// parameter int unsigned PERM_U2 = 13; // temp workaround parameter logic [2:0] OTYPE_SENTRY_IE_BKWD = 3'd5; parameter logic [2:0] OTYPE_SENTRY_ID_BKWD = 3'd4; @@ -51,7 +51,7 @@ package cheri_pkg; typedef struct packed { logic valid; logic [1:0] top_cor; - logic [1:0] base_cor; + logic base_cor; logic [EXP_W-1 :0] exp; // expanded logic [TOP_W-1 :0] top; logic [BOT_W-1 :0] base; @@ -68,7 +68,7 @@ package cheri_pkg; logic [OTYPE_W-1 :0] otype; logic [PERMS_W-1: 0] perms; logic [1:0] top_cor; - logic [1:0] base_cor; + logic base_cor; logic [TOP_W-1 :0] top; logic [BOT_W-1 :0] base; logic [CPERMS_W-1:0] cperms; @@ -92,6 +92,9 @@ package cheri_pkg; logic [32:0] top33req; logic [EXP_W-1:0] exp1; logic [EXP_W-1:0] exp2; + logic [EXP_W:0] explen; + logic [EXP_W:0] expb; // this can be 32 so must be 6-bit + logic in_bound; } bound_req_t; parameter reg_cap_t NULL_REG_CAP = '{0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -241,9 +244,9 @@ package cheri_pkg; return result; endfunction - // obtain 32-bit representation of top/base + // obtain 32-bit representation of top function automatic logic[32:0] get_bound33(logic [TOP_W-1:0] top, logic [1:0] cor, - logic [EXP_W-1:0] exp, logic [31:0] addr); + logic [EXP_W-1:0] exp, logic [31:0] addr); logic [32:0] t1, t2, mask, cor_val; if (cor[1]) @@ -287,21 +290,21 @@ package cheri_pkg; endfunction // update the top/base correction for a cap - function automatic logic [3:0] update_temp_fields(logic [TOP_W-1:0] top, logic [BOT_W-1:0] base, + function automatic logic [2:0] update_temp_fields(logic [TOP_W-1:0] top, logic [BOT_W-1:0] base, logic [BOT_W-1:0] addrmi); logic top_hi, addr_hi; - logic [3:0] res4; + logic [2:0] res3; top_hi = (top < base); addr_hi = (addrmi < base); // top_cor - res4[3:2] = (top_hi == addr_hi)? 2'b00 : ((top_hi && (!addr_hi))? 2'b01 : 2'b11); + res3[2:1] = (top_hi == addr_hi)? 2'b00 : ((top_hi && (!addr_hi))? 2'b01 : 2'b11); // base_cor - res4[1:0] = (addr_hi) ? 2'b11 : 0; + res3[0] = (addr_hi) ? 1 : 0; - return res4; + return res3; endfunction // set address of a capability @@ -313,7 +316,7 @@ package cheri_pkg; full_cap_t out_cap; logic [32:0] tmp33; logic [32-TOP_W:0] tmp24, mask24; - logic [3:0] tmp4; + logic [2:0] tmp3; logic [BOT_W-1:0] ptrmi9; logic top_lt; @@ -328,23 +331,50 @@ package cheri_pkg; out_cap.valid = 1'b0; ptrmi9 = BOT_W'(newptr >> in_cap.exp); - tmp4 = update_temp_fields(out_cap.top, out_cap.base, ptrmi9); - out_cap.top_cor = tmp4[3:2]; - out_cap.base_cor = tmp4[1:0]; + tmp3 = update_temp_fields(out_cap.top, out_cap.base, ptrmi9); + out_cap.top_cor = tmp3[2:1]; + out_cap.base_cor = tmp3[0]; return out_cap; endfunction + // + // utility functions + // - // utility function // return the size (bit length) of input number without leading zeros function automatic logic [5:0] get_size(logic [31:0] din); logic [5:0] count; - logic [31:0] a32, b32; + logic [31:0] a32; int i; a32 = {din[31], 31'h0}; for (i = 30; i >= 0; i--) a32[i] = a32[i+1] | din[i]; + count = thermo_dec32(a32); + + return count; + endfunction + + // return the exp of a 32-bit input (by count trailing zeros) + function automatic logic [5:0] count_tz (logic [31:0] din); + logic [5:0] count; + logic [31:0] a32, b32; + int i; + + a32 = {31'h0, din[0]}; + for (i = 1; i < 32; i++) a32[i] = a32[i-1] | din[i]; + // count = a32[31] ? thermo_dec32(~a32) : 0; // if input all zero, return 0 + count = thermo_dec32(~a32); // if input all zero, return 32 + + return count; + endfunction + + // this simply count the number of 1's in a thermoeter-encoded input vector + // (32-N zeros followed by N ones) + // + function automatic logic [5:0] thermo_dec32(logic [31:0] a32); + logic [5:0] count; + logic [31:0] b32; if (a32[31]) count = 32; else begin @@ -366,17 +396,45 @@ package cheri_pkg; // set bounds (top/base/exp/addr) of a capability // break up into 2 parts to enable 2-cycle option - function automatic bound_req_t prep_bound_req (logic [31:0] addr, logic [31:0] length); + function automatic bound_req_t prep_bound_req (full_cap_t in_cap, logic [31:0] addr, logic [31:0] length); bound_req_t result; logic [5:0] size_result; result.top33req = {1'b0, addr} + {1'b0, length}; // "requested" 33-bit top + result.expb = count_tz(addr); + result.explen = get_size({9'h0, length[31:9]}); // length exp without saturation - size_result = get_size({9'h0, length[31:9]}); + size_result = result.explen; result.exp1 = (size_result >= 6'(RESETCEXP)) ? EXP_W'(RESETEXP) : EXP_W'(size_result); + size_result += 1; result.exp2 = (size_result >= 6'(RESETCEXP)) ? EXP_W'(RESETEXP) : EXP_W'(size_result); + // move this to prep_bound_req to share with set_bounds_rndown + // should be ok to fit this in cycle 1 since it is a straight compare + result.in_bound = ~((result.top33req > in_cap.top33) || (addr < in_cap.base32)); + + return result; + endfunction + + function automatic bound_req_t prep_bound_req_it8 (full_cap_t in_cap, logic [31:0] addr, logic [31:0] length); // IT8 encoding + bound_req_t result; + logic [4:0] size_result; + logic gt24; + logic [4:0] limit24_mask; + + result.top33req = {1'b0, addr} + {1'b0, length}; // "requested" 33-bit top + result.expb = count_tz(addr); + result.explen = get_size({9'h0, length[31:9]}); // length exp without saturation, max 23 + + // since explen <= 23, exp1 and exp must be <= 24. No need for saturation logic + result.exp1 = result.explen; + result.exp2 = result.explen + 1; + + // move this to prep_bound_req to share with set_bounds_rndown + // should be ok to fit this in cycle 1 since it is a straight compare + result.in_bound = ~((result.top33req > in_cap.top33) || (addr < in_cap.base32)); + return result; endfunction @@ -384,19 +442,21 @@ package cheri_pkg; bound_req_t bound_req, logic req_exact); full_cap_t out_cap; - logic [EXP_W-1:0] exp1, exp2, expr; + logic [EXP_W-1:0] exp1, exp2; logic [32:0] top33req; logic [BOT_W:0] base1, base2, top1, top2, len1, len2; logic [32:0] mask1, mask2; logic ovrflw, topoff1, topoff2, topoff; logic baseoff1, baseoff2, baseoff; logic tophi1, tophi2, tophi; + logic in_bound; out_cap = in_cap; top33req = bound_req.top33req; exp1 = bound_req.exp1; exp2 = bound_req.exp2; + in_bound = bound_req.in_bound; // 1st path mask1 = {33{1'b1}} << exp1; @@ -450,7 +510,7 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas // Note the new base == addr >> exp, so addr_hi == FALSE, thus base_cor == 0 // as such, top_cor can only be either either 0 or +1; out_cap.top_cor = tophi ? 2'b00 : 2'b01; - out_cap.base_cor = 2'b00; + out_cap.base_cor = 1'b0; if (req_exact & (topoff | baseoff)) out_cap.valid = 1'b0; @@ -458,12 +518,100 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas // also compare address >= old base 32 to handle exp=24 case // exp = 24 case: can have addr < base (not covered by representibility checking); // other exp cases: always addr >= base when out_cap.tag == 1 - if ((top33req > in_cap.top33) || (addr < in_cap.base32)) + if (~in_bound) out_cap.valid = 1'b0; return out_cap; endfunction + function automatic full_cap_t set_bounds_rndn (full_cap_t in_cap, logic[31:0] addr, + bound_req_t bound_req); + full_cap_t out_cap; + + logic [EXP_W:0] explen, expb, exp_final; + logic [32:0] top33req; + logic in_bound; + logic el_gt_eb, el_gt_14, eb_gt_14; + logic tophi; + + out_cap = in_cap; + + top33req = bound_req.top33req; + explen = bound_req.explen; + expb = bound_req.expb; + in_bound = bound_req.in_bound; + + el_gt_eb = (explen > expb); + el_gt_14 = (explen > 14); + eb_gt_14 = (expb > 14); + + // final exp = min(14, e_l, e_b) + exp_final = (el_gt_eb & !eb_gt_14) ? expb : (el_gt_14 ? 14 : explen); + + // if (el_gt_eb & eb_gt_14) exp_final = 14; // min(14, min(e_l, e_b)), el > eb, eb > 14 + // else if (el_gt_eb) exp_final = expb; // min(14, min(e_l, e_b)), el > eb, eb <= 14 + // else if (el_gt_14) exp_final = 14; // min(14, min(e_l, e_b)), el <= eb, el > 14 + // else exp_final = explen; // e_l, el <= eb, el <= 14 + + out_cap.exp = exp_final; + out_cap.base = (BOT_W)'(addr >> exp_final); + + out_cap.top = (el_gt_eb | el_gt_14) ? ((BOT_W)'(out_cap.base-1)) : + ((BOT_W)'(top33req >> exp_final)); + + if (~in_bound) out_cap.valid = 1'b0; + + // top/base correction values + // Note the new base == addr >> exp, so addr_hi == FALSE, thus base_cor == 0 + // as such, top_cor can only be either either 0 or +1; + tophi = (out_cap.top >= out_cap.base); + out_cap.top_cor = tophi ? 2'b00 : 2'b01; + out_cap.base_cor = 2'b00; + + return out_cap; + endfunction + + + function automatic full_cap_t set_bounds_rndn_it8 (full_cap_t in_cap, logic[31:0] addr, // IT8 encoding + bound_req_t bound_req); + full_cap_t out_cap; + + logic [EXP_W:0] explen, expb, exp_final; + logic [32:0] top33req; + logic in_bound; + logic el_gt_eb; + logic tophi; + + out_cap = in_cap; + + top33req = bound_req.top33req; + explen = bound_req.explen; + expb = bound_req.expb; + in_bound = bound_req.in_bound; + + el_gt_eb = (explen > expb); + + exp_final = (el_gt_eb) ? expb : explen; + + out_cap.exp = exp_final; + out_cap.base = (BOT_W)'(addr >> exp_final); + + out_cap.top = (el_gt_eb) ? ((BOT_W)'(out_cap.base-1)) : ((BOT_W)'(top33req >> exp_final)); + + if (~in_bound) out_cap.valid = 1'b0; + + // top/base correction values + // Note the new base == addr >> exp, so addr_hi == FALSE, thus base_cor == 0 + // as such, top_cor can only be either either 0 or +1; + tophi = (out_cap.top >= out_cap.base); + out_cap.top_cor = tophi ? 2'b00 : 2'b01; + out_cap.base_cor = 2'b00; + + return out_cap; + endfunction + + + // seal/unseal related functions function automatic full_cap_t seal_cap (full_cap_t in_cap, logic [OTYPE_W-1:0] new_otype); full_cap_t out_cap; @@ -519,7 +667,7 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas full_cap.rsvd = reg_cap.rsvd; full_cap.top33 = get_bound33(reg_cap.top, reg_cap.top_cor, reg_cap.exp, addr); - full_cap.base32 = 32'(get_bound33(reg_cap.base, reg_cap.base_cor, reg_cap.exp, addr)); + full_cap.base32 = get_bound33(reg_cap.base, {2{reg_cap.base_cor}}, reg_cap.exp, addr); // full_cap = update_bounds(full_cap, addr); // for some reason this increases area full_cap.maska = 0; @@ -562,7 +710,7 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas pcc_fullcap.otype = in_pcap.otype; pcc_fullcap.perms = in_pcap.perms; pcc_fullcap.top_cor = 2'b0; // will be updated by set_address() - pcc_fullcap.base_cor = 2'b0; + pcc_fullcap.base_cor = 1'b0; pcc_fullcap.top = TOP_W'(in_pcap.top33 >> (in_pcap.exp)); pcc_fullcap.base = BOT_W'(in_pcap.base32 >> (in_pcap.exp)); pcc_fullcap.cperms = in_pcap.cperms; @@ -611,14 +759,16 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas localparam integer RSVD_LO = 31; localparam integer CPERMS_LO = 25; localparam integer OTYPE_LO = 22; - localparam integer CEXP_LO = 18; + localparam integer CEXP_LO = 18; + localparam integer CEXP5_LO = 17; // IT8 encoding only localparam integer TOP_LO = 9; localparam integer BASE_LO = 0; - + + // mem2reg, cap meta data, original cap bound encoding, memfmt0 function automatic reg_cap_t mem2regcap_fmt0 (logic [32:0] msw, logic [32:0] addr33, logic [3:0] clrperm); reg_cap_t regcap; logic [EXP_W-1:0] tmp5; - logic [3:0] tmp4; + logic [2:0] tmp3; logic [CPERMS_W-1:0] cperms_mem; logic [BOT_W-1:0] addrmi9; logic sealed; @@ -639,9 +789,66 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas cperms_mem = msw[CPERMS_LO+:CPERMS_W]; regcap.cperms = mask_clcperms(cperms_mem, clrperm, regcap.valid, sealed); addrmi9 = BOT_W'({1'b0, addr33[31:0]} >> regcap.exp); // ignore the tag valid bit - tmp4 = update_temp_fields(regcap.top, regcap.base, addrmi9); - regcap.top_cor = tmp4[3:2]; - regcap.base_cor = tmp4[1:0]; + tmp3 = update_temp_fields(regcap.top, regcap.base, addrmi9); + regcap.top_cor = tmp3[2:1]; + regcap.base_cor = tmp3[0]; + + regcap.rsvd = msw[RSVD_LO]; + + return regcap; + + endfunction + + // mem2reg, cap meta data, IT8 encoding, memfmt0 + function automatic reg_cap_t mem2regcap_it8_fmt0 (logic [32:0] msw, logic [32:0] addr33, logic [3:0] clrperm); // IT8 + reg_cap_t regcap; + logic [EXP_W-1:0] cexp; + logic [TOP_W-2:0] top8, base8; + logic [TOP_W-1:0] top9, base9; + logic denorm, ltop, btop, ttop, tcin; + logic top_hi, addr_hi; + logic [2:0] res3; + + logic [CPERMS_W-1:0] cperms_mem; + logic [BOT_W-1:0] addrmi9; + logic sealed; + logic valid_in; + + valid_in = msw[32] & addr33[32]; + regcap.valid = valid_in & ~clrperm[3]; + + cexp = msw[CEXP5_LO+:CEXP5_W]; + denorm = (cexp == 0); + + btop = msw[BASE_LO+BOT_W-1]; + base8 = msw[BASE_LO+:(BOT_W-1)]; + top8 = msw[TOP_LO+:(TOP_W-1)]; + + tcin = (top8 < base8); // can actually merge it with t_hi in update_temp_fields QQQ + ltop = ~denorm; + ttop = ltop ^ tcin ^ btop; + + regcap.exp = cexp ^ {5{~denorm}}; // this is the ^0b11111 part + top9 = {ttop, top8}; + base9 = {btop, base8}; + regcap.top = top9; + regcap.base = base9; + + regcap.otype = msw[OTYPE_LO+:OTYPE_W]; + + sealed = (regcap.otype != OTYPE_UNSEALED); + cperms_mem = msw[CPERMS_LO+:CPERMS_W]; + regcap.cperms = mask_clcperms(cperms_mem, clrperm, regcap.valid, sealed); + addrmi9 = BOT_W'({1'b0, addr33[31:0]} >> regcap.exp); // ignore the tag valid bit + + // update temp fields + // tmp3 = update_temp_fields(regcap.top, regcap.base, addrmi9); + // top_hi = (top < base); + top_hi = (btop ^ ttop) ? ~ttop : tcin; + addr_hi = (addrmi9 < base9); + + regcap.top_cor = (top_hi == addr_hi)? 2'b00 : ((top_hi && (!addr_hi))? 2'b01 : 2'b11); + regcap.base_cor = (addr_hi) ? 1'b1 : 1'b0; regcap.rsvd = msw[RSVD_LO]; @@ -649,6 +856,7 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas endfunction + // reg to mem, meta data, original cap bound encoding, memfmt0 function automatic logic[32:0] reg2memcap_fmt0 (reg_cap_t regcap); logic [32:0] msw; @@ -666,14 +874,43 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas endfunction + // reg to mem, meta data, IT8 encoding, memfmt0 + function automatic logic[32:0] reg2memcap_it8_fmt0 (reg_cap_t regcap); // IT8 + + logic [32:0] msw; + logic denorm, ltop, cor; + logic [9:0] top10, base10, len10; + + cor = (regcap.top_cor == {2{regcap.base_cor}}); + top10 = {~cor, regcap.top}; + base10 = {1'b0, regcap.base}; + len10 = top10 - base10; + ltop = len10[9] | len10[8]; + + denorm = (regcap.exp == 0) && ~ltop; + + msw[32] = regcap.valid; + + msw[CEXP5_LO+:CEXP5_W] = regcap.exp ^ {5{~denorm}}; + msw[TOP_LO+:(TOP_W-1)] = regcap.top[7:0]; + msw[BASE_LO+:BOT_W] = regcap.base ; + msw[OTYPE_LO+:OTYPE_W] = regcap.otype ; + msw[CPERMS_LO+:CPERMS_W] = regcap.cperms; + msw[RSVD_LO] = regcap.rsvd; + + return msw; + + endfunction + // // pack/unpack the cap+addr between reg and memory - // format 1: lsw32 = GL+ EXP+B+T+A addr, msw33 = rest of the fields + // format 1: lsw32 = RSVD+EXP+T+B+A9, msw32 = CPERMS+OTYPE+A23 // + // mem to reg, meta data, original cap bound encoding, memfmt1 function automatic reg_cap_t mem2regcap_fmt1 (logic [32:0] msw, logic [32:0] lsw, logic [3:0] clrperm); reg_cap_t regcap; - logic [3:0] tmp4; + logic [2:0] tmp3; logic sealed; logic [8:0] addrmi9; logic [CPERMS_W-1:0] cperms_mem; @@ -695,36 +932,99 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas regcap.cperms = mask_clcperms(cperms_mem, clrperm, regcap.valid, sealed); regcap.rsvd = lsw[31]; - tmp4 = update_temp_fields(regcap.top, regcap.base, addrmi9); - regcap.top_cor = tmp4[3:2]; - regcap.base_cor = tmp4[1:0]; + tmp3 = update_temp_fields(regcap.top, regcap.base, addrmi9); + regcap.top_cor = tmp3[2:1]; + regcap.base_cor = tmp3[0]; return regcap; endfunction - function automatic logic[32:0] mem2regaddr_fmt1 (logic [32:0] msw, logic [32:0] lsw, reg_cap_t reg_cap); + + // mem to reg, meta data, IT8 encoding, memfmt1 + function automatic reg_cap_t mem2regcap_it8_fmt1 (logic [32:0] msw, logic [32:0] lsw, logic [3:0] clrperm); // xyz + reg_cap_t regcap; + logic [EXP_W-1:0] cexp; + logic [TOP_W-2:0] top8, base8; + logic [TOP_W-1:0] top9, base9; + logic denorm, ltop, btop, ttop, tcin; + logic top_hi, addr_hi; + logic [2:0] res3; + + logic sealed; + logic [8:0] addrmi9; + logic [CPERMS_W-1:0] cperms_mem; + logic valid_in; + + + // lsw is now EXP+T+B+A + valid_in = msw[32] & lsw[32]; + regcap.valid = valid_in & ~clrperm[3]; + + cexp = lsw[30:26]; + denorm = (cexp == 0); + + btop = lsw[17]; + base8 = lsw[16:9]; + top8 = lsw[25:18]; + + tcin = (top8 < base8); // can actually merge it with t_hi in update_temp_fields QQQ + ltop = ~denorm; + ttop = ltop ^ tcin ^ btop; + + regcap.exp = cexp ^ {5{~denorm}}; // this is the ^0b11111 part + top9 = {ttop, top8}; + base9 = {btop, base8}; + regcap.top = top9; + regcap.base = base9; + + // (regcap.exp >= RESETEXP); + addrmi9 = (regcap.exp[4] & regcap.exp[3]) ? {1'b0, lsw[8:1]} : lsw[8:0]; + + regcap.otype = msw[25:23]; + sealed = (regcap.otype != OTYPE_UNSEALED); + + // cperms_mem = {lsw[31], msw[31:26]}; + cperms_mem = msw[31:26]; + regcap.cperms = mask_clcperms(cperms_mem, clrperm, regcap.valid, sealed); + regcap.rsvd = lsw[31]; + + // tmp3 = update_temp_fields(regcap.top, regcap.base, addrmi9); + top_hi = (btop ^ ttop) ? ~ttop : tcin; + addr_hi = (addrmi9 < base9); + + regcap.top_cor = (top_hi == addr_hi)? 2'b00 : ((top_hi && (!addr_hi))? 2'b01 : 2'b11); + regcap.base_cor = (addr_hi) ? 1'b1 : 1'b0; + + return regcap; + + endfunction + + // mem to reg, addr32, both original and IT8 encoding, memfmt1 + function automatic logic[32:0] mem2regaddr_fmt1 (logic [32:0] msw, logic [32:0] lsw, reg_cap_t regcap); // xyz logic [32:0] addr33; logic [31:0] addrmi, addrhi, addrlo; logic [31:0] mask1, mask2; - if (reg_cap.exp == RESETEXP) begin + // (regcap.exp >= RESETEXP) + if (regcap.exp[4] & regcap.exp[3]) begin addrhi = 32'h0; addrmi = {lsw[8:0], 23'h0}; addrlo = {9'h0, msw[22:0]}; end else begin - addrmi = {23'h0, lsw[8:0]} << reg_cap.exp; - mask1 = {32{1'b1}} << reg_cap.exp; + addrmi = {23'h0, lsw[8:0]} << regcap.exp; + mask1 = {32{1'b1}} << regcap.exp; mask2 = mask1 << 9; addrhi = ({9'h0, msw[22:0]} << 9) & mask2; addrlo = {9'h0, msw[22:0]} & (~mask1); end - addr33 = {lsw[32], addrhi | addrmi |addrlo}; + addr33 = {lsw[32], addrhi | addrmi | addrlo}; return addr33; endfunction + // reg to mem, original cap bound encoding, memfmt1 function automatic logic[65:0] reg2mem_fmt1 (reg_cap_t reg_cap, logic[31:0] addr); logic [32:0] msw, lsw; @@ -755,6 +1055,46 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas endfunction + // reg to mem, IT8 encoding, memfmt1 + function automatic logic[65:0] reg2mem_it8_fmt1 (reg_cap_t regcap, logic[31:0] addr); // xyz + + logic [32:0] msw, lsw; + logic [31:0] mask1, mask2; + logic denorm, ltop, cor; + logic [9:0] top10, base10, len10; + + cor = (regcap.top_cor == {2{regcap.base_cor}}); + top10 = {~cor, regcap.top}; + base10 = {1'b0, regcap.base}; + len10 = top10-base10; + ltop = len10[9] | len10[8]; + + denorm = (regcap.exp == 0) && ~ltop; + + msw[32] = regcap.valid; + msw[31:26] = regcap.cperms[5:0]; + msw[25:23] = regcap.otype; + lsw[32] = regcap.valid ; + lsw[31] = regcap.rsvd; + lsw[30:26] = regcap.exp ^ {5{~denorm}} ; + lsw[25:18] = regcap.top[7:0]; + lsw[17:9] = regcap.base; + + // (regcap.exp >= RESETEXP) + if (regcap.exp[4] & regcap.exp[3]) begin + msw[22:0] = addr[22:0]; + lsw[8:0] = addr[31:23]; + end else begin + mask1 = {32{1'b1}} << regcap.exp; + mask2 = mask1 << 9; + msw[22:0] = 23'((addr & ~mask1) | ((addr & mask2) >> 9)); + lsw[8:0] = 9'(addr >> regcap.exp); + end + + return {msw, lsw}; + + endfunction + // simply cast regcap to a 38-bit vector. // we can do this with systemverilog casting but let's be explicit here function automatic logic [REGCAP_W-1:0] reg2vec (reg_cap_t regcap); @@ -762,8 +1102,8 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas logic [REGCAP_W-1:0] vec_out; vec_out[REGCAP_W-1] = regcap.valid ; - vec_out[35+:2] = regcap.top_cor; - vec_out[33+:2] = regcap.base_cor; + vec_out[34+:2] = regcap.top_cor; + vec_out[33+:1] = regcap.base_cor; vec_out[28+:EXP_W] = regcap.exp; vec_out[19+:TOP_W] = regcap.top ; vec_out[10+:BOT_W] = regcap.base ; @@ -778,15 +1118,15 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas reg_cap_t regcap; - regcap.valid = vec_in[REGCAP_W-1]; - regcap.top_cor = vec_in[35+:2]; - regcap.base_cor = vec_in[33+:2]; - regcap.exp = vec_in[28+:EXP_W]; - regcap.top = vec_in[19+:TOP_W]; - regcap.base = vec_in[10+:BOT_W]; - regcap.otype = vec_in[7+:OTYPE_W]; - regcap.rsvd = vec_in[6+:1]; - regcap.cperms = vec_in[0+:CPERMS_W]; + regcap.valid = vec_in[REGCAP_W-1]; + regcap.top_cor = vec_in[34+:2]; + regcap.base_cor = vec_in[33+:1]; + regcap.exp = vec_in[28+:EXP_W]; + regcap.top = vec_in[19+:TOP_W]; + regcap.base = vec_in[10+:BOT_W]; + regcap.otype = vec_in[7+:OTYPE_W]; + regcap.rsvd = vec_in[6+:1]; + regcap.cperms = vec_in[0+:CPERMS_W]; return regcap; endfunction @@ -803,6 +1143,16 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas return is_equal; endfunction + + // clear tag of a regcap if needed, otherwise simply pass through + function automatic reg_cap_t and_regcap_tag (reg_cap_t in_cap, logic tag_mask); + reg_cap_t out_cap; + + out_cap = in_cap; + out_cap.valid = in_cap.valid & tag_mask; + return out_cap; + + endfunction // parameters and constants @@ -810,38 +1160,39 @@ $display("--- set_bounds: b1 = %x, t1 = %x, b2 = %x, t2 = %x", base1, top1, bas parameter int OPDW = 36; // Must >= number of cheri operator/instructions we support typedef enum logic [5:0] { - CGET_PERM = 6'h00, - CGET_TYPE = 6'h01, - CGET_BASE = 6'h02, - CGET_LEN = 6'h03, - CGET_TAG = 6'h04, - CGET_TOP = 6'h05, - CGET_HIGH = 6'h06, - CGET_ADDR = 6'h07, - CSEAL = 6'h08, - CUNSEAL = 6'h09, - CAND_PERM = 6'h0a, - CSET_ADDR = 6'h0b, - CINC_ADDR = 6'h0c, - CINC_ADDR_IMM = 6'h0d, - CSET_BOUNDS = 6'h0e, - CSET_BOUNDS_EX = 6'h0f, - CSET_BOUNDS_IMM = 6'h10, - CIS_SUBSET = 6'h11, - CIS_EQUAL = 6'h12, - CMOVE_CAP = 6'h13, - CSUB_CAP = 6'h14, - CCLEAR_TAG = 6'h15, - CLOAD_CAP = 6'h16, - CSET_HIGH = 6'h17, - CSTORE_CAP = 6'h18, - CCSR_RW = 6'h19, - CJALR = 6'h1a, - CJAL = 6'h1b, - CAUIPCC = 6'h1c, - CAUICGP = 6'h1d, - CRRL = 6'h1e, - CRAM = 6'h1f + CGET_PERM = 6'h00, + CGET_TYPE = 6'h01, + CGET_BASE = 6'h02, + CGET_LEN = 6'h03, + CGET_TAG = 6'h04, + CGET_TOP = 6'h05, + CGET_HIGH = 6'h06, + CGET_ADDR = 6'h07, + CSEAL = 6'h08, + CUNSEAL = 6'h09, + CAND_PERM = 6'h0a, + CSET_ADDR = 6'h0b, + CINC_ADDR = 6'h0c, + CINC_ADDR_IMM = 6'h0d, + CSET_BOUNDS = 6'h0e, + CSET_BOUNDS_EX = 6'h0f, + CSET_BOUNDS_IMM = 6'h10, + CIS_SUBSET = 6'h11, + CIS_EQUAL = 6'h12, + CMOVE_CAP = 6'h13, + CSUB_CAP = 6'h14, + CCLEAR_TAG = 6'h15, + CLOAD_CAP = 6'h16, + CSET_HIGH = 6'h17, + CSTORE_CAP = 6'h18, + CCSR_RW = 6'h19, + CJALR = 6'h1a, + CJAL = 6'h1b, + CAUIPCC = 6'h1c, + CAUICGP = 6'h1d, + CRRL = 6'h1e, + CRAM = 6'h1f, + CSET_BOUNDS_RNDN = 6'h20 } cheri_op_e; typedef enum logic [4:0] { diff --git a/vendor/lowrisc_ibex/rtl/cheri_regfile.sv b/vendor/lowrisc_ibex/rtl/cheri_regfile.sv index 2649f4db7..379cd8355 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_regfile.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_regfile.sv @@ -94,14 +94,18 @@ module cheri_regfile import cheri_pkg::*; #( if (RegFileECC) begin : g_reg_par logic [6:0] wdata_par; + logic trvk_clr_we; - assign wdata_par = wdata_a_i[DataWidth-1:DataWidth-7]; + assign trvk_clr_we = CheriPPLBC & trvk_dec[i] & trvk_en_i & trvk_clrtag_i; + assign wdata_par = wdata_a_i[DataWidth-1:DataWidth-7]; // split reset of data and parity to detect spurious reset (fault protection) always_ff @(posedge clk_i or negedge par_rst_ni) begin if (!par_rst_ni) begin rf_reg_par_q[i] <= DefParBits[i]; - end else if (RegFileECC & CheriPPLBC & trvk_dec[i] & trvk_en_i & trvk_clrtag_i) begin + end else if (trvk_clr_we && we_a_dec[i]) begin + rf_reg_par_q[i] <= wdata_par ^ TrvkParIncr; + end else if (trvk_clr_we) begin // update parity bits rf_reg_par_q[i] <= rf_reg_par_q[i] ^ TrvkParIncr; end else if (we_a_dec[i]) begin @@ -132,12 +136,18 @@ module cheri_regfile import cheri_pkg::*; #( // capability meta data (MSW) for (genvar i = 1; i < NCAPS; i++) begin : g_cap_flops + logic trvk_clr_we; + + assign trvk_clr_we = CheriPPLBC & trvk_dec[i] & trvk_en_i & trvk_clrtag_i; + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rf_cap_q[i] <= NULL_REG_CAP; - end else if (CheriPPLBC & trvk_dec[i] & trvk_en_i & trvk_clrtag_i) begin + end else if (trvk_clr_we && we_a_dec[i]) begin + rf_cap_q[i] <= and_regcap_tag(wcap_a_i, 1'b0); + end else if (trvk_clr_we) begin // prioritize revocation (later in pipeline) - rf_cap_q[i].valid <= 1'b0; + rf_cap_q[i] <= and_regcap_tag(rf_cap_q[i], 1'b0); end else if (we_a_dec[i]) begin rf_cap_q[i] <= wcap_a_i; end diff --git a/vendor/lowrisc_ibex/rtl/cheri_stkz.sv b/vendor/lowrisc_ibex/rtl/cheri_stkz.sv index dc45acbd5..ba6ce15f0 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_stkz.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_stkz.sv @@ -82,7 +82,7 @@ module cheri_stkz import cheri_pkg::*; ( always_comb begin - logic [3:0] tmp4; + logic [2:0] tmp3; logic [8:0] addrmi9; if ((stkz_fsm_q == STKZ_IDLE) && stkz_start) @@ -106,9 +106,9 @@ module cheri_stkz import cheri_pkg::*; ( // note we only start an zeroization if addr > base32 so no need for representability check ztop_rcap_nxt = ztop_rcap; addrmi9 = {stkz_ptrw_nxt, 2'b00} >> ztop_rcap.exp; - tmp4 = update_temp_fields(ztop_rcap.top, ztop_rcap.base, addrmi9); - ztop_rcap_nxt.top_cor = tmp4[3:2]; - ztop_rcap_nxt.base_cor = tmp4[1:0]; + tmp3 = update_temp_fields(ztop_rcap.top, ztop_rcap.base, addrmi9); + ztop_rcap_nxt.top_cor = tmp3[2:1]; + ztop_rcap_nxt.base_cor = tmp3[0]; ztop_rcap_nxt.valid = ztop_rcap.valid & ~stkz_done; end diff --git a/vendor/lowrisc_ibex/rtl/cheri_trvk_stage.sv b/vendor/lowrisc_ibex/rtl/cheri_trvk_stage.sv index 0f4b539df..55726d7cd 100644 --- a/vendor/lowrisc_ibex/rtl/cheri_trvk_stage.sv +++ b/vendor/lowrisc_ibex/rtl/cheri_trvk_stage.sv @@ -5,8 +5,8 @@ /* verilator lint_off UNUSED */ module cheri_trvk_stage #( - parameter int unsigned HeapBase = '0, - parameter int unsigned TSMapSize = '0 + parameter int unsigned HeapBase = 32'h2001_0000, + parameter int unsigned TSMapSize = 1024 ) ( // Clock and Reset input logic clk_i, @@ -57,7 +57,7 @@ module cheri_trvk_stage #( logic [2:1] range_ok_q; - assign base32 = 32'(get_bound33(in_cap_q.base, in_cap_q.base_cor, in_cap_q.exp, in_data_q)); + assign base32 = get_bound33(in_cap_q.base, {2{in_cap_q.base_cor}}, in_cap_q.exp, in_data_q); assign tsmap_ptr = (base32 - HeapBase) >> 3; /* verilator lint_off WIDTH */ diff --git a/vendor/lowrisc_ibex/rtl/ibex_core.sv b/vendor/lowrisc_ibex/rtl/ibex_core.sv index 9cba5ceca..e07cde4a6 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_core.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_core.sv @@ -50,16 +50,17 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #( // CHERIoT paramters parameter bit CHERIoTEn = 1'b1, parameter int unsigned DataWidth = 33, - parameter int unsigned HeapBase = '0, - parameter int unsigned TSMapBase = '0, - parameter int unsigned TSMapSize = '0, + parameter int unsigned HeapBase = 32'h2001_0000, + parameter int unsigned TSMapBase = 32'h2002_f000, + parameter int unsigned TSMapSize = 1024, parameter bit MemCapFmt = 1'b0, parameter bit CheriPPLBC = 1'b1, parameter bit CheriSBND2 = 1'b0, parameter bit CheriTBRE = 1'b1, parameter bit CheriStkZ = 1'b1, parameter int unsigned MMRegDinW = 128, - parameter int unsigned MMRegDoutW = 64 + parameter int unsigned MMRegDoutW = 64, + parameter bit CheriCapIT8 = 1'b0 ) ( // Clock and Reset input logic clk_i, @@ -880,7 +881,8 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #( .TSMapSize (TSMapSize), .CheriPPLBC (CheriPPLBC), .CheriSBND2 (CheriSBND2), - .CheriStkZ (CheriStkZ) + .CheriStkZ (CheriStkZ), + .CheriCapIT8 (CheriCapIT8) ) u_cheri_ex ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -1144,7 +1146,8 @@ module ibex_core import ibex_pkg::*; import cheri_pkg::*; #( ibex_load_store_unit #( .CHERIoTEn(CHERIoTEn), .MemCapFmt(MemCapFmt), - .CheriTBRE(CheriTBRE) + .CheriTBRE(CheriTBRE), + .CheriCapIT8(CheriCapIT8) ) load_store_unit_i ( .clk_i (clk_i), .rst_ni(rst_ni), @@ -1717,9 +1720,9 @@ end logic rvfi_ext_stage_debug_req [RVFI_STAGES+1]; logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES]; - - logic rvfi_stage_valid_d [RVFI_STAGES]; + + logic insn_c_hint; assign rvfi_valid = rvfi_stage_valid [RVFI_STAGES-1]; assign rvfi_order = rvfi_stage_order [RVFI_STAGES-1]; @@ -1737,7 +1740,6 @@ end assign rvfi_rs1_rcap = rvfi_stage_rs1_rcap [RVFI_STAGES-1]; assign rvfi_rs2_rcap = rvfi_stage_rs2_rcap [RVFI_STAGES-1]; assign rvfi_rs3_rdata = rvfi_stage_rs3_rdata[RVFI_STAGES-1]; - assign rvfi_rd_addr = rvfi_stage_rd_addr [RVFI_STAGES-1]; assign rvfi_rd_wdata = rvfi_stage_rd_wdata [RVFI_STAGES-1]; assign rvfi_rd_wcap = rvfi_stage_rd_wcap [RVFI_STAGES-1]; assign rvfi_pc_rdata = rvfi_stage_pc_rdata [RVFI_STAGES-1]; @@ -1751,6 +1753,24 @@ end assign rvfi_mem_rcap = rvfi_stage_mem_rcap[RVFI_STAGES-1]; assign rvfi_mem_wcap = rvfi_stage_mem_wcap[RVFI_STAGES-1]; + // for HINT instructions like c.srai64/c.slli64, force rvfi_rd_addr output to 0 to match sail implementation + assign rvfi_rd_addr = insn_c_hint ? 0 : rvfi_stage_rd_addr [RVFI_STAGES-1]; + + always_comb begin + if ((rvfi_insn[1:0] == 2'b01) && (rvfi_insn[15:13] == 3'b100) && (rvfi_insn[11:10] == 2'b00) && // c.srli64 + ({rvfi_insn[12], rvfi_insn[6:2]} == 6'h0) && + (rvfi_rs1_addr == rvfi_rd_addr) && (rvfi_rs1_rdata == rvfi_rd_wdata)) + insn_c_hint = 1'b1; + else if ((rvfi_insn[1:0] == 2'b01) && (rvfi_insn[15:13] == 3'b100) && (rvfi_insn[11:10] == 2'b01) && // c.srai64 + ({rvfi_insn[12], rvfi_insn[6:2]} == 6'h0) && + (rvfi_rs1_addr == rvfi_rd_addr) && (rvfi_rs1_rdata == rvfi_rd_wdata)) + insn_c_hint = 1'b1; + else + insn_c_hint = 1'b0; + + + end + assign rvfi_rd_addr_wb = rf_waddr_wb; assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu; // this doesn't look right but ok assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu; diff --git a/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv index 6089620f4..4bd0d1bd9 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv @@ -1015,7 +1015,8 @@ module ibex_cs_registers import cheri_pkg::*; #( .rd_error_o() ); - logic cheri_exception_code = mcause_q == 6'h1C; + logic cheri_exception_code; + assign cheri_exception_code = mcause_q == 6'h1C; // Bounds violation assign cheri_err_o[0] = cheri_exception_code ? (mtval_q[4:0] == 5'h01) : 1'b0; // Tag violation diff --git a/vendor/lowrisc_ibex/rtl/ibex_decoder.sv b/vendor/lowrisc_ibex/rtl/ibex_decoder.sv index b0f9f61a1..0ccfd8229 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_decoder.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_decoder.sv @@ -67,6 +67,7 @@ module ibex_decoder import cheri_pkg::*; #( // register file output ibex_pkg::rf_wd_sel_e rf_wdata_sel_o, // RF write data selection output logic rf_we_o, // write enable for regfile + output logic rf_we_or_load_o, output logic [4:0] rf_raddr_a_o, output logic [4:0] rf_raddr_b_o, output logic [4:0] rf_waddr_o, @@ -234,12 +235,15 @@ module ibex_decoder import cheri_pkg::*; #( // rf_we from decoder doesn't cover memory load case (where regfile write signal comes from LSU response) logic rf_we_or_load; assign rf_we_or_load = rf_we | (opcode == OPCODE_LOAD); + + assign rf_we_or_load_o = rf_we_or_load; if (RV32E) begin : gen_rv32e_reg_check_active //assign illegal_reg_rv32e = ((rf_raddr_a_o[4] & (alu_op_a_mux_sel_o == OP_A_REG_A)) | // (rf_raddr_b_o[4] & (alu_op_b_mux_sel_o == OP_B_REG_B)) | assign illegal_reg_rv32e = ((rf_raddr_a_o[4] & rf_ren_a_o) | (rf_raddr_b_o[4] & rf_ren_b_o) | + (instr_rs3[4] & use_rs3_d & rf_ren_a_o) | (rf_waddr_o[4] & rf_we_or_load)); end else begin : gen_rv32e_reg_check_inactive assign illegal_reg_rv32e = 1'b0; @@ -249,6 +253,7 @@ module ibex_decoder import cheri_pkg::*; #( assign illegal_reg_cheri = cheri_pmode_i & ((raddr_a[4] & rf_ren_a_o) | (raddr_b[4] & rf_ren_b_o) | + (instr_rs3[4] & use_rs3_d & rf_ren_a_o) | (instr_rd[4] & rf_we_or_load )); end else begin : gen_cheri_reg_check_inactive assign illegal_reg_cheri = 1'b0; @@ -499,7 +504,8 @@ module ibex_decoder import cheri_pkg::*; #( end 5'b0_1001, // bclri 5'b0_0101, // bseti - 5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // binvi + // 5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // binvi + 5'b0_1101: illegal_insn = (RV32B != RV32BNone) ? (instr[26:25] != 2'b00) : 1'b1; // binvi 5'b0_0001: begin if (instr[26] == 1'b0) begin // shfl illegal_insn = (RV32B == RV32BOTEarlGrey || RV32B == RV32BFull) ? 1'b0 : 1'b1; @@ -541,7 +547,8 @@ module ibex_decoder import cheri_pkg::*; #( illegal_insn = (RV32B == RV32BOTEarlGrey || RV32B == RV32BFull) ? 1'b0 : 1'b1; end 5'b0_1100, // rori - 5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // bexti + // 5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? 1'b0 : 1'b1; // bexti + 5'b0_1001: illegal_insn = (RV32B != RV32BNone) ? (instr[26:25] != 2'b00) : 1'b1; // bexti 5'b0_1101: begin if (RV32B == RV32BOTEarlGrey || RV32B == RV32BFull) begin diff --git a/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv index d39490ab0..b7c60d150 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv @@ -274,6 +274,7 @@ module ibex_id_stage import cheri_pkg::*; #( logic rf_we_dec, rf_we_raw; logic rf_ren_a, rf_ren_b; logic rf_ren_a_dec, rf_ren_b_dec; + logic rf_we_or_load; // Read enables should only be asserted for valid and legal instructions assign rf_ren_a = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_a_dec; @@ -511,6 +512,7 @@ module ibex_id_stage import cheri_pkg::*; #( // register file .rf_wdata_sel_o(rf_wdata_sel), .rf_we_o (rf_we_dec), + .rf_we_or_load_o(rf_we_or_load), .rf_raddr_a_o(rf_raddr_a_o), .rf_raddr_b_o(rf_raddr_b_o), @@ -1115,14 +1117,14 @@ module ibex_id_stage import cheri_pkg::*; #( assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz); - logic rf_we_valid; - assign rf_we_valid = rf_we_dec & instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o; + logic rf_we_or_load_valid; + assign rf_we_or_load_valid = rf_we_or_load & instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o; assign stall_cheri_trvk = (CHERIoTEn & cheri_pmode_i & CheriPPLBC) ? ((rf_ren_a && ~rf_reg_rdy_i[rf_raddr_a_o]) | (rf_ren_b && ~rf_reg_rdy_i[rf_raddr_b_o]) | - (rf_we_valid && ~rf_reg_rdy_i[rf_waddr_id_o])) : + (rf_we_or_load_valid && ~rf_reg_rdy_i[rf_waddr_id_o])) : 1'b0; assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER : diff --git a/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv b/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv index e4100e4a3..4d15a66be 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_load_store_unit.sv @@ -19,9 +19,10 @@ `include "dv_fcov_macros.svh" module ibex_load_store_unit import ibex_pkg::*; import cheri_pkg::*; #( - parameter bit CHERIoTEn = 1'b1, - parameter bit MemCapFmt = 1'b0, - parameter bit CheriTBRE = 1'b0 + parameter bit CHERIoTEn = 1'b1, + parameter bit MemCapFmt = 1'b0, + parameter bit CheriTBRE = 1'b0, + parameter bit CheriCapIT8 = 1'b0 )( input logic clk_i, input logic rst_ni, @@ -217,7 +218,8 @@ module ibex_load_store_unit import ibex_pkg::*; import cheri_pkg::*; #( if (~MemCapFmt) begin : gen_memcap_wr_fmt0 always_comb begin if (CHERIoTEn & cheri_pmode_i & lsu_is_cap_i && (ls_fsm_cs == CTX_WAIT_GNT2)) - data_wdata = reg2memcap_fmt0(lsu_wcap_i); + data_wdata = CheriCapIT8 ? reg2memcap_it8_fmt0(lsu_wcap_i): + reg2memcap_fmt0(lsu_wcap_i); else if (CHERIoTEn & cheri_pmode_i & lsu_is_cap_i) data_wdata = lsu_wdata_i; else begin @@ -232,7 +234,8 @@ module ibex_load_store_unit import ibex_pkg::*; import cheri_pkg::*; #( end end else begin : gen_memcap_wr_fmt1 logic [65:0] mem_capaddr; - assign mem_capaddr = reg2mem_fmt1(lsu_wcap_i, lsu_wdata_i); + assign mem_capaddr = CheriCapIT8 ? reg2mem_it8_fmt1(lsu_wcap_i, lsu_wdata_i) : + reg2mem_fmt1(lsu_wcap_i, lsu_wdata_i); always_comb begin if (CHERIoTEn & lsu_is_cap_i && (ls_fsm_cs == CTX_WAIT_GNT2)) @@ -713,11 +716,13 @@ module ibex_load_store_unit import ibex_pkg::*; import cheri_pkg::*; #( if (CHERIoTEn & ~MemCapFmt) begin : gen_memcap_rd_fmt0 assign lsu_rdata_o = (cheri_pmode_i & resp_is_cap_q) ? cap_lsw_q : data_rdata_ext; assign lsu_rcap_o = (resp_is_cap_q && data_rvalid_i && (cap_rx_fsm_q == CRX_WAIT_RESP2) && (~data_or_pmp_err)) ? - mem2regcap_fmt0(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : NULL_REG_CAP; + (CheriCapIT8 ? mem2regcap_it8_fmt0(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : + mem2regcap_fmt0(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q)) : NULL_REG_CAP; end else if (CHERIoTEn) begin : gen_memcap_rd_fmt1 assign lsu_rdata_o = (cheri_pmode_i & resp_is_cap_q) ? mem2regaddr_fmt1(data_rdata_ext, cap_lsw_q, lsu_rcap_o): data_rdata_ext; assign lsu_rcap_o = (resp_is_cap_q && data_rvalid_i && (cap_rx_fsm_q == CRX_WAIT_RESP2) && (~data_or_pmp_err)) ? - mem2regcap_fmt1(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : NULL_REG_CAP; + (CheriCapIT8 ? mem2regcap_it8_fmt1(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q) : + mem2regcap_fmt1(data_rdata_i, cap_lsw_q, resp_lc_clrperm_q)) : NULL_REG_CAP; end else begin : gen_no_cap_rd assign lsu_rdata_o = data_rdata_ext; assign lsu_rcap_o = NULL_REG_CAP; diff --git a/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv b/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv index c0b2fe338..2ec4e4f9d 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv @@ -38,9 +38,9 @@ module ibex_lockstep import ibex_pkg::*; import cheri_pkg::*; #( // CHERIoT paramters parameter bit CHERIoTEn = 1'b1, parameter int unsigned DataWidth = 33, - parameter int unsigned HeapBase = '0, - parameter int unsigned TSMapBase = '0, - parameter int unsigned TSMapSize = '0, + parameter int unsigned HeapBase = 32'h2001_0000, + parameter int unsigned TSMapBase = 32'h2002_f000, + parameter int unsigned TSMapSize = 1024, parameter bit MemCapFmt = 1'b0, parameter bit CheriPPLBC = 1'b1, parameter bit CheriSBND2 = 1'b0, diff --git a/vendor/lowrisc_ibex/rtl/ibex_tracer.sv b/vendor/lowrisc_ibex/rtl/ibex_tracer.sv index b12e5833e..4b8b325e1 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_tracer.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_tracer.sv @@ -40,7 +40,8 @@ */ module ibex_tracer import cheri_pkg::*; # ( - parameter int unsigned DataWidth = 32 + parameter int unsigned DataWidth = 32, + parameter bit CheriCapIT8 = 1'b0 ) ( input logic clk_i, input logic rst_ni, @@ -133,6 +134,7 @@ module ibex_tracer import cheri_pkg::*; # ( function automatic void printbuffer_dumpline(); string rvfi_insn_str; string disp_str; + logic [32:0] tmp33; if (file_handle == 32'h0) begin string file_name_base = "trace_core"; @@ -164,13 +166,15 @@ module ibex_tracer import cheri_pkg::*; # ( $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata); end if ((data_accessed & CS1) != 0) begin - $fwrite(file_handle, " %s:0x%08x+0x%09x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata, reg2memcap_fmt0(rvfi_rs1_rcap)); + tmp33 = CheriCapIT8 ? reg2memcap_it8_fmt0(rvfi_rs1_rcap) : reg2memcap_fmt0(rvfi_rs1_rcap); + $fwrite(file_handle, " %s:0x%08x+0x%09x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata, tmp33); end if ((data_accessed & RS2) != 0) begin $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata); end if ((data_accessed & CS2) != 0) begin - $fwrite(file_handle, " %s:0x%08x+0x%09x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata, reg2memcap_fmt0(rvfi_rs2_rcap)); + tmp33 = CheriCapIT8 ? reg2memcap_it8_fmt0(rvfi_rs2_rcap) : reg2memcap_fmt0(rvfi_rs2_rcap); + $fwrite(file_handle, " %s:0x%08x+0x%09x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata, tmp33); end if ((data_accessed & RS3) != 0) begin $fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata); @@ -180,7 +184,8 @@ module ibex_tracer import cheri_pkg::*; # ( end if ((data_accessed & CD) != 0) begin - $fwrite(file_handle, " %s=0x%08x+0x%09x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata, reg2memcap_fmt0(rvfi_rd_wcap)); + tmp33 = CheriCapIT8 ? reg2memcap_it8_fmt0(rvfi_rd_wcap) : reg2memcap_fmt0(rvfi_rd_wcap); + $fwrite(file_handle, " %s=0x%08x+0x%09x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata, tmp33); end if ((data_accessed & MEM) != 0) begin @@ -200,10 +205,13 @@ module ibex_tracer import cheri_pkg::*; # ( if ((data_accessed & MEMC) != 0) begin $fwrite(file_handle, " PA:0x%08x", rvfi_mem_addr); - if (rvfi_mem_wmask != 0) - $fwrite(file_handle, " store:0x%09x+0x%09x", rvfi_mem_wdata, reg2memcap_fmt0(rvfi_mem_wcap)); - else - $fwrite(file_handle, " load:0x%09x+0x%09x", rvfi_mem_rdata, reg2memcap_fmt0(rvfi_mem_rcap)); + if (rvfi_mem_wmask != 0) begin + tmp33 = CheriCapIT8 ? reg2memcap_it8_fmt0(rvfi_mem_wcap) : reg2memcap_fmt0(rvfi_mem_wcap); + $fwrite(file_handle, " store:0x%09x+0x%09x", rvfi_mem_wdata, tmp33); + end else begin + tmp33 = CheriCapIT8 ? reg2memcap_it8_fmt0(rvfi_mem_rcap) : reg2memcap_fmt0(rvfi_mem_rcap); + $fwrite(file_handle, " load:0x%09x+0x%09x", rvfi_mem_rdata, tmp33); + end end $fwrite(file_handle, "\n"); @@ -746,8 +754,13 @@ module ibex_tracer import cheri_pkg::*; # ( // C.LWSP imm = {rvfi_insn[3:2], rvfi_insn[12], rvfi_insn[6:4], 2'b00}; end - data_accessed = CS1 | RD | MEM; - decoded_str = $sformatf("%s\tx%0d,%0d(c%0d)", mnemonic, rvfi_rd_addr, imm, rvfi_rs1_addr); + if (cheri_pmode_i) begin + data_accessed = CS1 | RD | MEM; + decoded_str = $sformatf("%s\tx%0d,%0d(c%0d)", mnemonic, rvfi_rd_addr, imm, rvfi_rs1_addr); + end else begin + data_accessed = RS1 | RD | MEM; + decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr, imm, rvfi_rs1_addr); + end end endfunction @@ -773,8 +786,13 @@ module ibex_tracer import cheri_pkg::*; # ( // C.SWSP imm = {rvfi_insn[8:7], rvfi_insn[12:9], 2'b00}; end - data_accessed = CS1 | RS2 | MEM; - decoded_str = $sformatf("%s\tx%0d,%0d(c%0d)", mnemonic, rvfi_rs2_addr, imm, rvfi_rs1_addr); + if (cheri_pmode_i) begin + data_accessed = CS1 | RS2 | MEM; + decoded_str = $sformatf("%s\tx%0d,%0d(c%0d)", mnemonic, rvfi_rs2_addr, imm, rvfi_rs1_addr); + end else begin + data_accessed = RS1 | RS2 | MEM; + decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rvfi_rs2_addr, imm, rvfi_rs1_addr); + end end endfunction @@ -967,7 +985,11 @@ module ibex_tracer import cheri_pkg::*; # ( // We cannot use rvfi_pc_wdata for conditional jumps. imm = rvfi_insn[31:12]; data_accessed = CD; - decoded_str = $sformatf("%s\tc%0d, 0x%0x", "CH.auipcc", rvfi_rd_addr, imm); + if (cheri_pmode_i) begin + decoded_str = $sformatf("%s\tc%0d,0x%0x", "CH.auipcc", rvfi_rd_addr, imm); + end else begin + decoded_str = $sformatf("%s\tx%0d,0x%0x", "auipc", rvfi_rd_addr, imm); + end endfunction @@ -978,7 +1000,7 @@ module ibex_tracer import cheri_pkg::*; # ( // We cannot use rvfi_pc_wdata for conditional jumps. imm = rvfi_insn[31:12]; data_accessed = CD | CS1; - decoded_str = $sformatf("%s\tc%0d, 0x%0x", "CH.auicgp", rvfi_rd_addr, imm); + decoded_str = $sformatf("%s\tc%0d,0x%0x", "CH.auicgp", rvfi_rd_addr, imm); endfunction @@ -1362,6 +1384,7 @@ module ibex_tracer import cheri_pkg::*; # ( INSN_CHINCADDRIMM: decode_cheri_cd_cs1_imm_insn("CH.cincaddrimm"); INSN_CHSETBOUNDS: decode_cheri_cd_cs1_rs2_insn("CH.csetbounds"); INSN_CHSETBOUNDSEX: decode_cheri_cd_cs1_rs2_insn("CH.csetboundsexact"); + INSN_CHSETBOUNDSRNDN: decode_cheri_cd_cs1_rs2_insn("CH.csetboundsrounddown"); INSN_CHSETBOUNDSIMM: decode_cheri_cd_cs1_imm_insn("CH.csetboundsimm"); INSN_CHCLEARTAG: decode_cheri_cd_cs1_insn("CH.ccleartag"); diff --git a/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv b/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv index a79d88579..811a22fba 100644 --- a/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv +++ b/vendor/lowrisc_ibex/rtl/ibex_tracer_pkg.sv @@ -359,6 +359,7 @@ package ibex_tracer_pkg; parameter logic [31:0] INSN_CHINCADDRIMM = {12'h?, 5'h?, 3'b001, 5'h?, {OPCODE_CHERI} }; parameter logic [31:0] INSN_CHSETBOUNDS = {7'h08, 10'h?, 3'b000, 5'h?, {OPCODE_CHERI} }; parameter logic [31:0] INSN_CHSETBOUNDSEX = {7'h09, 10'h?, 3'b000, 5'h?, {OPCODE_CHERI} }; + parameter logic [31:0] INSN_CHSETBOUNDSRNDN = {7'h0a, 10'h?, 3'b000, 5'h?, {OPCODE_CHERI} }; parameter logic [31:0] INSN_CHSETBOUNDSIMM = {12'h?, 5'h?, 3'b010, 5'h?, {OPCODE_CHERI} }; parameter logic [31:0] INSN_CHCLEARTAG = {7'h7f, 5'hb, 5'h?, 3'b000, 5'h?, {OPCODE_CHERI} }; parameter logic [31:0] INSN_CHCRRL = {7'h7f, 5'h8, 5'h?, 3'b000, 5'h?, {OPCODE_CHERI} }; diff --git a/vendor/lowrisc_ibex/rtl/ibexc_top.sv b/vendor/lowrisc_ibex/rtl/ibexc_top.sv index e725f7fdb..081a0b5b4 100644 --- a/vendor/lowrisc_ibex/rtl/ibexc_top.sv +++ b/vendor/lowrisc_ibex/rtl/ibexc_top.sv @@ -27,6 +27,7 @@ module ibexc_top import ibex_pkg::*; import cheri_pkg::*; #( parameter int unsigned MHPMCounterWidth = 40, parameter bit RV32E = 1'b0, parameter rv32b_e RV32B = RV32BNone, + parameter rv32m_e RV32M = RV32MFast, parameter bit WritebackStage = 1'b1, parameter bit BranchPredictor = 1'b0, parameter bit SecureIbex = 1'b0, // placeholder for TB compatbility @@ -42,6 +43,7 @@ module ibexc_top import ibex_pkg::*; import cheri_pkg::*; #( parameter bit CheriStkZ = 1'b1, parameter int unsigned MMRegDinW = 128, parameter int unsigned MMRegDoutW = 64, + parameter bit CheriCapIT8 = 1'b0, parameter bit ICache = 1'b0 ) ( // Clock and Reset @@ -258,8 +260,8 @@ module ibexc_top import ibex_pkg::*; import cheri_pkg::*; #( .MHPMCounterNum (MHPMCounterNum ), .MHPMCounterWidth (MHPMCounterWidth), .RV32E (RV32E), - .RV32M (RV32MFast), - .RV32B (RV32BNone), + .RV32M (RV32M), + .RV32B (RV32B), .BranchTargetALU (1'b1), .ICache (ICache), .ICacheECC (1'b0), @@ -290,7 +292,8 @@ module ibexc_top import ibex_pkg::*; import cheri_pkg::*; #( .CheriTBRE (CheriTBRE), .CheriStkZ (CheriStkZ), .MMRegDinW (MMRegDinW), - .MMRegDoutW (MMRegDoutW) + .MMRegDoutW (MMRegDoutW), + .CheriCapIT8 (CheriCapIT8) ) u_ibex_core ( .clk_i (clk), .rst_ni (rst_ni), diff --git a/vendor/lowrisc_ibex/rtl/ibexc_top_tracing.sv b/vendor/lowrisc_ibex/rtl/ibexc_top_tracing.sv index f89489bc0..81d89a8e6 100644 --- a/vendor/lowrisc_ibex/rtl/ibexc_top_tracing.sv +++ b/vendor/lowrisc_ibex/rtl/ibexc_top_tracing.sv @@ -14,18 +14,20 @@ module ibexc_top_tracing import ibex_pkg::*; import cheri_pkg::*; #( parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808, parameter bit RV32E = 1'b0, + parameter rv32m_e RV32M = RV32MFast, + parameter rv32b_e RV32B = RV32BNone, parameter bit CheriTBRE = 1'b1, parameter bit CheriStkZ = 1'b1, parameter bit DbgTriggerEn = 1'b1, parameter int unsigned DbgHwBreakNum = 4, parameter int unsigned MHPMCounterNum = 0, - parameter rv32b_e RV32B = RV32BFull, parameter int unsigned HeapBase = 32'h2001_0000, parameter int unsigned TSMapBase = 32'h2004_0000, // 4kB default parameter int unsigned TSMapSize = 1024, // in words parameter int unsigned MMRegDinW = 128, parameter int unsigned MMRegDoutW = 64, - parameter int unsigned DataWidth = 33, // this enables testbench to use defparam to override + parameter int unsigned DataWidth = 33, // this enables testbench to use defparam to override + parameter bit CheriCapIT8 = 1'b0, parameter bit ICache = 1'b0 ) ( // Clock and Reset @@ -155,6 +157,7 @@ module ibexc_top_tracing import ibex_pkg::*; import cheri_pkg::*; #( .DbgTriggerEn (DbgTriggerEn), .DbgHwBreakNum (DbgHwBreakNum), .RV32E (RV32E), + .RV32M (RV32M), .RV32B (RV32B), .WritebackStage (1'b1), .BranchPredictor (1'b0), @@ -170,6 +173,7 @@ module ibexc_top_tracing import ibex_pkg::*; import cheri_pkg::*; #( .CheriStkZ (CheriStkZ), .MMRegDinW (MMRegDinW), .MMRegDoutW (MMRegDoutW), + .CheriCapIT8 (CheriCapIT8), .ICache (ICache) ) u_ibex_top ( .clk_i, @@ -274,7 +278,8 @@ module ibexc_top_tracing import ibex_pkg::*; import cheri_pkg::*; #( // synthesis translate_off `ifdef RVFI ibex_tracer #( - .DataWidth (DataWidth) + .DataWidth (DataWidth), + .CheriCapIT8 (CheriCapIT8) ) u_ibex_tracer ( .clk_i, .rst_ni,