Showing preview only (3,165K chars total). Download the full file or copy to clipboard to get everything.
Repository: cliffordwolf/riscv-formal
Branch: main
Commit: a5443540f965
Files: 282
Total size: 3.0 MB
Directory structure:
gitextract_1qfjctmx/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── COPYING
├── CodeOfConduct
├── README.md
├── bus/
│ ├── rvfi_bus_axi4.sv
│ └── rvfi_bus_util.sv
├── checks/
│ ├── genchecks.py
│ ├── rvfi_bus_dmem_check.sv
│ ├── rvfi_bus_dmem_fault_check.sv
│ ├── rvfi_bus_dmem_io_order_check.sv
│ ├── rvfi_bus_dmem_io_read_check.sv
│ ├── rvfi_bus_dmem_io_read_fault_check.sv
│ ├── rvfi_bus_dmem_io_write_check.sv
│ ├── rvfi_bus_dmem_io_write_fault_check.sv
│ ├── rvfi_bus_imem_check.sv
│ ├── rvfi_bus_imem_fault_check.sv
│ ├── rvfi_causal_check.sv
│ ├── rvfi_causal_io_check.sv
│ ├── rvfi_causal_mem_check.sv
│ ├── rvfi_channel.sv
│ ├── rvfi_cover_check.sv
│ ├── rvfi_csr_ill_check.sv
│ ├── rvfi_csrc_any_check.sv
│ ├── rvfi_csrc_const_check.sv
│ ├── rvfi_csrc_hpm_check.sv
│ ├── rvfi_csrc_inc_check.sv
│ ├── rvfi_csrc_upcnt_check.sv
│ ├── rvfi_csrc_zero_check.sv
│ ├── rvfi_csrw_check.sv
│ ├── rvfi_dmem_check.sv
│ ├── rvfi_fault_check.sv
│ ├── rvfi_hang_check.sv
│ ├── rvfi_ill_check.sv
│ ├── rvfi_imem_check.sv
│ ├── rvfi_insn_check.sv
│ ├── rvfi_liveness_check.sv
│ ├── rvfi_macros.py
│ ├── rvfi_macros.vh
│ ├── rvfi_pc_bwd_check.sv
│ ├── rvfi_pc_fwd_check.sv
│ ├── rvfi_reg_check.sv
│ ├── rvfi_testbench.sv
│ └── rvfi_unique_check.sv
├── cores/
│ ├── VexRiscv/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── VexRiscv.v
│ │ ├── checks.cfg
│ │ ├── disasm.py
│ │ ├── dmemcheck.sby
│ │ ├── dmemcheck.sv
│ │ ├── imemcheck.sby
│ │ ├── imemcheck.sv
│ │ └── wrapper.sv
│ ├── nerv/
│ │ ├── .gitignore
│ │ ├── COPYING
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── axi_cache/
│ │ │ ├── .gitignore
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── axi_ram.v
│ │ │ ├── checks_axi.cfg
│ │ │ ├── checks_internal.cfg
│ │ │ ├── firmware.c
│ │ │ ├── nerv_axi_cache.sv
│ │ │ ├── nerv_axi_cache_dcache.sv
│ │ │ ├── nerv_axi_cache_icache.sv
│ │ │ ├── testbench_axi.sv
│ │ │ ├── testbench_internal.sv
│ │ │ ├── verify_axi.sby
│ │ │ ├── verify_axi.sv
│ │ │ ├── wrapper_axi.sv
│ │ │ └── wrapper_internal.sv
│ │ ├── cexdata.sh
│ │ ├── checks.cfg
│ │ ├── disasm.py
│ │ ├── examples/
│ │ │ └── icebreaker/
│ │ │ ├── .gitignore
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── firmware.c
│ │ │ ├── firmware.s
│ │ │ ├── icebreaker.pcf
│ │ │ ├── sections.lds
│ │ │ ├── testbench.gtkw
│ │ │ ├── testbench.sv
│ │ │ └── top.v
│ │ ├── firmware.c
│ │ ├── firmware.s
│ │ ├── imemcheck.sby
│ │ ├── imemcheck.sv
│ │ ├── nerv.sv
│ │ ├── nervsoc.sv
│ │ ├── sections.lds
│ │ ├── testbench.gtkw
│ │ ├── testbench.sv
│ │ ├── trace.gtkw
│ │ ├── vectors.s
│ │ └── wrapper.sv
│ ├── picorv32/
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── cexdata.sh
│ │ ├── checks.cfg
│ │ ├── checks.gtkw
│ │ ├── complete.sby
│ │ ├── complete.sv
│ │ ├── cover.sby
│ │ ├── cover.sv
│ │ ├── disasm.py
│ │ ├── dmemcheck.sv
│ │ ├── equiv.sh
│ │ ├── honest.sby
│ │ ├── honest.sv
│ │ ├── imemcheck.sv
│ │ ├── testbugs.sh
│ │ └── wrapper.sv
│ ├── rocket/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── cexdata.sh
│ │ ├── checks.gtkw
│ │ ├── cover.gtkw
│ │ ├── cover.sby
│ │ ├── cover.sv
│ │ ├── coverage.sby
│ │ ├── coverage.sv
│ │ ├── decode.sh
│ │ ├── disasm.py
│ │ ├── generate.sh
│ │ ├── muldivlen.py
│ │ ├── muldivlen.sby
│ │ ├── muldivlen.sv
│ │ ├── rocketrvfi.sv
│ │ ├── testbench.cc
│ │ ├── testbench.sh
│ │ └── wrapper.sv
│ └── serv/
│ ├── .gitignore
│ ├── README.md
│ ├── cexdata.sh
│ ├── checks.cfg
│ ├── cover.gtkw
│ ├── cover.sby
│ ├── cover.sv
│ ├── disasm.py
│ ├── generate.sh
│ ├── sbram.sv
│ └── wrapper.sv
├── docs/
│ ├── config.md
│ ├── csrs.md
│ ├── examplebugs.md
│ ├── procedure.md
│ ├── quickstart.md
│ ├── references.md
│ └── rvfi.md
├── insns/
│ ├── generate.py
│ ├── insn_add.v
│ ├── insn_addi.v
│ ├── insn_addiw.v
│ ├── insn_addw.v
│ ├── insn_and.v
│ ├── insn_andi.v
│ ├── insn_auipc.v
│ ├── insn_beq.v
│ ├── insn_bge.v
│ ├── insn_bgeu.v
│ ├── insn_blt.v
│ ├── insn_bltu.v
│ ├── insn_bne.v
│ ├── insn_c_add.v
│ ├── insn_c_addi.v
│ ├── insn_c_addi16sp.v
│ ├── insn_c_addi4spn.v
│ ├── insn_c_addiw.v
│ ├── insn_c_addw.v
│ ├── insn_c_and.v
│ ├── insn_c_andi.v
│ ├── insn_c_beqz.v
│ ├── insn_c_bnez.v
│ ├── insn_c_j.v
│ ├── insn_c_jal.v
│ ├── insn_c_jalr.v
│ ├── insn_c_jr.v
│ ├── insn_c_ld.v
│ ├── insn_c_ldsp.v
│ ├── insn_c_li.v
│ ├── insn_c_lui.v
│ ├── insn_c_lw.v
│ ├── insn_c_lwsp.v
│ ├── insn_c_mv.v
│ ├── insn_c_or.v
│ ├── insn_c_sd.v
│ ├── insn_c_sdsp.v
│ ├── insn_c_slli.v
│ ├── insn_c_srai.v
│ ├── insn_c_srli.v
│ ├── insn_c_sub.v
│ ├── insn_c_subw.v
│ ├── insn_c_sw.v
│ ├── insn_c_swsp.v
│ ├── insn_c_xor.v
│ ├── insn_div.v
│ ├── insn_divu.v
│ ├── insn_divuw.v
│ ├── insn_divw.v
│ ├── insn_jal.v
│ ├── insn_jalr.v
│ ├── insn_lb.v
│ ├── insn_lbu.v
│ ├── insn_ld.v
│ ├── insn_lh.v
│ ├── insn_lhu.v
│ ├── insn_lui.v
│ ├── insn_lw.v
│ ├── insn_lwu.v
│ ├── insn_mul.v
│ ├── insn_mulh.v
│ ├── insn_mulhsu.v
│ ├── insn_mulhu.v
│ ├── insn_mulw.v
│ ├── insn_or.v
│ ├── insn_ori.v
│ ├── insn_rem.v
│ ├── insn_remu.v
│ ├── insn_remuw.v
│ ├── insn_remw.v
│ ├── insn_sb.v
│ ├── insn_sd.v
│ ├── insn_sh.v
│ ├── insn_sll.v
│ ├── insn_slli.v
│ ├── insn_slliw.v
│ ├── insn_sllw.v
│ ├── insn_slt.v
│ ├── insn_slti.v
│ ├── insn_sltiu.v
│ ├── insn_sltu.v
│ ├── insn_sra.v
│ ├── insn_srai.v
│ ├── insn_sraiw.v
│ ├── insn_sraw.v
│ ├── insn_srl.v
│ ├── insn_srli.v
│ ├── insn_srliw.v
│ ├── insn_srlw.v
│ ├── insn_sub.v
│ ├── insn_subw.v
│ ├── insn_sw.v
│ ├── insn_xor.v
│ ├── insn_xori.v
│ ├── isa_rv32i.txt
│ ├── isa_rv32i.v
│ ├── isa_rv32ic.txt
│ ├── isa_rv32ic.v
│ ├── isa_rv32im.txt
│ ├── isa_rv32im.v
│ ├── isa_rv32imc.txt
│ ├── isa_rv32imc.v
│ ├── isa_rv64i.txt
│ ├── isa_rv64i.v
│ ├── isa_rv64ic.txt
│ ├── isa_rv64ic.v
│ ├── isa_rv64im.txt
│ ├── isa_rv64im.v
│ ├── isa_rv64imc.txt
│ └── isa_rv64imc.v
├── monitor/
│ └── generate.py
└── tests/
├── coverage/
│ ├── .gitignore
│ ├── coverage.sby
│ ├── coverage.sv
│ ├── generate.py
│ ├── riscv_rv32i_insn.v
│ ├── riscv_rv32ic_insn.v
│ ├── riscv_rv64i_insn.v
│ └── riscv_rv64ic_insn.v
├── semantics/
│ ├── .gitignore
│ ├── Makefile
│ ├── cexformat.py
│ ├── makejob.py
│ └── top.sv
└── spike/
├── .gitignore
├── common.h
└── generate.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
name: ci
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: '30 1 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: YosysHQ/setup-oss-cad-suite@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run checks
run: |
cd cores/nerv
make check -j$(nproc)
cd ../picorv32
wget -O picorv32.v https://raw.githubusercontent.com/YosysHQ/picorv32/master/picorv32.v
python3 ../../checks/genchecks.py
make -C checks -j$(nproc)
================================================
FILE: .gitignore
================================================
/cores/.gitignore
================================================
FILE: COPYING
================================================
Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: CodeOfConduct
================================================
Contributor Covenant Code of Conduct
Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at contact@yosyshq.com. All complaints
will be reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. The project team is obligated
to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at http://contributor-covenant.org/version/1/4/
================================================
FILE: README.md
================================================
RISC-V Formal Verification Framework
====================================
**This is work in progress. The interfaces described here are likely to change as the project matures.**
About
-----
`riscv-formal` is a framework for formal verification of RISC-V processors.
It consists of the following components:
- A processor-independent formal description of the RISC-V ISA
- A set of formal testbenches for each processor supported by the framework
- The specification for the [RISC-V Formal Interface (RVFI)](docs/rvfi.md) that must be implemented by a processor core to interface with `riscv-formal`.
- Some auxiliary proofs and scripts, for example to prove correctness of the ISA spec agains riscv-isa-sim.
See [cores/picorv32/](cores/picorv32/) for example bindings for the PicoRV32 processor core.
A processor core usually will implement RVFI as an optional feature that is only enabled for verification. Sequential equivalence check can be used to prove equivalence of the processor versions with and without RVFI.
The current focus is on implementing formal models of all instructions from the RISC-V RV32I and RV64I ISAs, and formally verifying those models against the models used in the RISC-V "Spike" ISA simulator.
`riscv-formal` uses the FOSS SymbiYosys formal verification flow. All properties are expressed using immediate assertions/assumptions for maximal compatibility with other tools.
Table of contents
-----------------
- [Quickstart Guide](docs/quickstart.md)
- [The RVFI Interface Specification](docs/rvfi.md)
- [RISC-V Formal CSR Sematics](docs/csrs.md)
- [Configuration macros used by riscv-formal](docs/config.md)
- [The riscv-formal Verification Procedure](docs/procedure.md)
- [Examples of bugs found with riscv-formal](docs/examplebugs.md)
- [References and related work](docs/references.md)
Configuring a new RISC-V processor
----------------------------------
1. Create a `riscv-formal/cores/<core-name>/` directory
2. Write a wrapper module that instantiates the core under test and abstracts models of necessary
peripherals (usually just memory)
- Use the [RVFI helper macros](docs/config.md#rvfi_wires-rvfi_outputs-rvfi_inputs-rvfi_conn)
`RVFI_OUTPUTS` and `RVFI_CONN` for quickly defining wrapper connections
- See [picorv32/wrapper.sv](cores/picorv32/wrapper.sv) for a simple example wrapper
3. Write a `checks.cfg` config file for the new core
- See [nerv/checks.cfg](cores/nerv/checks.cfg) for an example utilising most of the checks
- Refer to [The riscv-formal Verification Procedure](docs/procedure.md) for a complete guide on
available checks, and a more detailed view of using `genchecks.py`
4. Generate checks with `python3 ../../checks/genchecks.py` from the `<core-name>` directory
- Checks are generated in `riscv-formal/cores/<core-name>/checks`
5. Run checks with `make -C checks j$(nproc)`
### Notes
- The [quickstart guide](docs/quickstart.md) goes through the process of running riscv-formal with
some of the included cores. It is recommended to follow this guide before adding a new core.
- See [picorv32/Makefile](cores/picorv32/Makefile) for an example makefile to manage generation and
execution of checks.
- Out of tree generation with `genchecks.py` is not currently supported.
- Refer to [docs/config.md](docs/config.md) and [docs/procedure.md](docs/procedure.md) for a
breakdown of how to use riscv-formal checks without using `genchecks.py`.
- The [cover check](docs/procedure.md#cover) can be used to help determine the depth needed for the
core to reach certain states as needed for other checks.
================================================
FILE: bus/rvfi_bus_axi4.sv
================================================
// RVFI_BUS observer for AXI4 interfaces
//
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: When a W transfer happens before the corresponding AW transfer, the
// data appears on the RVFI_BUS signals starting with the cycle of that AW
// transfer, processing at most one W transfer per cycle. This can cause the
// whole burst to be delayed, potentially also delaying the processing of a
// following burst's W transfers even when that burst's AW transfer arrived for
// the first W transfer.
//
// An alternative that could process the W transfers before the AW transfers
// would have to let the solver guess the write addresses. This could cause
// spurious writes to appear that cause an assertion violation in a cycle
// before the actual AW transfer arrives that would constrain the guessed write
// address to be correctly guessed, as the AW transfer cycle is never
// considered by the solver due to the assertion being violated prior to
// reaching that.
//
// Hence, delaying the processing of W transfers until the corresponding AW
// transfer happens is less likely to cause false positives for most reasonable
// properties to check. In any case, writes appear on the RVFI_BUS signals in
// the exact same order as they appear on the AXI bus. When all AW transfers
// are guaranteed to arrive in time for their their first W transfer, the
// writes also appear on the same cycle as the W transfers carrying the data.
module rvfi_bus_axi4_observer_write #(
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ADDRESS_WIDTH = 32,
parameter AXI_ID_WIDTH = 1,
parameter AXI_AWUSER_WIDTH = 1,
parameter AXI_WUSER_WIDTH = 1,
parameter AXI_BUSER_WIDTH = 1,
parameter AXI_ID_MASK = 0,
parameter AXI_ID = 0,
parameter IGNORE_PROT_DATA_INSN = 0,
parameter DEPTH = 2,
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8
) (
input clock,
input reset,
// Write Address Channel (AW)
input [AXI_ID_WIDTH-1:0] axi_awid,
input [AXI_ADDRESS_WIDTH-1:0] axi_awaddr,
input [3:0] axi_awregion,
input [7:0] axi_awlen,
input [2:0] axi_awsize,
input [1:0] axi_awburst,
input axi_awlock,
input [3:0] axi_awcache,
input [2:0] axi_awprot,
input [3:0] axi_awqos,
input [AXI_AWUSER_WIDTH-1:0] axi_awuser,
input axi_awvalid,
input axi_awready,
// Write Data Channel (W)
input [AXI_DATA_WIDTH-1:0] axi_wdata,
input [AXI_STRB_WIDTH-1:0] axi_wstrb,
input axi_wlast,
input [AXI_WUSER_WIDTH-1:0] axi_wuser,
input axi_wvalid,
input axi_wready,
// Write Response Channel (B)
input [AXI_ID_WIDTH-1:0] axi_bid,
input [1:0] axi_bresp,
input [AXI_BUSER_WIDTH-1:0] axi_buser,
input axi_bvalid,
input axi_bready
`RVFI_BUS_CHANNEL_OUTPUTS
);
wire aw_transfer = axi_awvalid && axi_awready;
wire w_transfer = axi_wvalid && axi_wready;
wire b_transfer = axi_bvalid && axi_bready;
wire [AXI_ID_WIDTH-1:0] out_awid;
wire [AXI_ADDRESS_WIDTH-1:0] out_awaddr;
wire [7:0] out_awlen;
wire [2:0] out_awsize;
wire [1:0] out_awburst;
wire [2:0] out_awprot;
wire [AXI_DATA_WIDTH-1:0] out_wdata;
wire [AXI_STRB_WIDTH-1:0] out_wstrb;
wire out_wlast;
wire aw_fifo_in_ready, aw_fifo_out_valid;
wire w_fifo_in_ready, w_fifo_out_valid;
wire fut_b_fifo_in_ready, fut_b_fifo_out_valid;
`rvformal_rand_reg [1:0] rand_bresp;
wire [1:0] out_aw_bresp;
wire [1:0] out_bresp;
rvfi_bus_util_fifo #(
.DEPTH(DEPTH),
.WIDTH(AXI_ID_WIDTH + AXI_ADDRESS_WIDTH + 8 + 3 + 2 + 3 + 2)
) aw_fifo (
.clock(clock),
.reset(reset),
.in_data( {axi_awid, axi_awaddr, axi_awlen, axi_awsize, axi_awburst, axi_awprot, rand_bresp}),
.out_data({out_awid, out_awaddr, out_awlen, out_awsize, out_awburst, out_awprot, out_aw_bresp}),
.in_valid(aw_transfer),
.in_ready(aw_fifo_in_ready),
.out_ready(w_fifo_out_valid && out_wlast),
.out_valid(aw_fifo_out_valid)
);
rvfi_bus_util_fifo #(
.DEPTH(DEPTH),
.WIDTH(AXI_DATA_WIDTH + AXI_STRB_WIDTH + 1)
) w_fifo (
.clock(clock),
.reset(reset),
.in_data( {axi_wdata, axi_wstrb, axi_wlast}),
.out_data({out_wdata, out_wstrb, out_wlast}),
.in_valid(w_transfer),
.in_ready(w_fifo_in_ready),
.out_ready(aw_fifo_out_valid),
.out_valid(w_fifo_out_valid)
);
// We enqueue a guessed bresp value when we see an AW transfer and dequeue
// it when we see a B transfer, then assuming we made a correct guess.
// This doesn't have the same problem described in the note above, as the B
// channel is read by the AXI manager and any reasonable property of the
// AXI manager regarding the B response cannot fail before the AXI manager
// actually reads that response.
rvfi_bus_util_fifo #(
.DEPTH(DEPTH),
.WIDTH(2)
) fut_b_fifo (
.clock(clock),
.reset(reset),
.in_data( {rand_bresp}),
.out_data({out_bresp}),
.in_valid(aw_transfer),
.in_ready(fut_b_fifo_in_ready),
.out_ready(b_transfer),
.out_valid(fut_b_fifo_out_valid)
);
always @(posedge clock) begin
if (!reset) begin
if (aw_transfer)
DEPTH_too_small_AW: assert (aw_fifo_in_ready);
if (aw_transfer)
DEPTH_too_small_B: assert (fut_b_fifo_in_ready);
if (w_transfer)
DEPTH_too_small_W: assert (w_fifo_in_ready);
end
end
reg [7:0] burst_counter;
reg [AXI_ADDRESS_WIDTH-1:0] burst_offset;
always @(posedge clock) begin
if (w_fifo_out_valid && aw_fifo_out_valid) begin
if (!reset)
assert (out_wlast == (burst_counter == out_awlen));
if (out_wlast) begin
burst_counter <= 0;
burst_offset <= 0;
end else begin
burst_counter <= burst_counter + 1'b1;
burst_offset <= burst_offset + (1'b1 << out_awsize);
end
end
if (reset) begin
burst_counter <= 0;
burst_offset <= 0;
end
end
// Mask of address bits that can change between transfers of the same burst
// given the current burst type. This is used to compute the unaligned
// transfer address.
reg [AXI_ADDRESS_WIDTH-1:0] burst_mask;
// Log2 of the burst length, used to compute the burst mask for the WRAP
// burst type.
reg [2:0] burst_len_log2;
// Current transfer address, not aligned.
//
// When unaligned, it stays unaligned for the entire burst and always
// increments by the burst size. This means that transfers past the initial
// can include bytes below this address down to the next size aligned
// address.
wire [AXI_ADDRESS_WIDTH-1:0] unaligned_addr =
( burst_mask & (out_awaddr + burst_offset)) |
(~burst_mask & out_awaddr);
// Current transfer address, aligned to the burst size.
wire [AXI_ADDRESS_WIDTH-1:0] size_aligned_addr =
unaligned_addr & ('1 << out_awsize);
// Current transfer address, aligned to the bus width.
wire [AXI_ADDRESS_WIDTH-1:0] bus_aligned_addr =
unaligned_addr & ~(AXI_DATA_WIDTH/8 - 1);
// Mask of data bytes/strobe bits that are active given the current
// transfer address and burst size.
wire [AXI_DATA_WIDTH/8-1:0] size_mask =
(~('1 << (1 << out_awsize))) << (size_aligned_addr ^ bus_aligned_addr);
// Mask of data bytes/strobe bits that are active given the current
// misalignment (subset of size_mask). After the initial transfer in a
// burst, this is always the same as size_mask, as the transfer includes
// the remaining bytes that did not fit into the previous transfer.
wire [AXI_DATA_WIDTH/8-1:0] alignment_mask =
burst_counter ? size_mask : size_mask & (size_mask << (unaligned_addr ^ size_aligned_addr));
always @* begin
case (out_awlen)
8'h00: burst_len_log2 = 0;
8'h01: burst_len_log2 = 1;
8'h03: burst_len_log2 = 2;
8'h07: burst_len_log2 = 3;
8'h0f: burst_len_log2 = 4;
default: begin
burst_len_log2 = 0;
AWLEN_invalid_for_AWBURST: assert (reset || !aw_fifo_out_valid || out_awburst != 2'b10);
end
endcase
case (out_awburst)
// FIXED
2'b00: burst_mask = '0;
// INCR
2'b01: burst_mask = '1;
// WRAP
2'b10: burst_mask = ~('1 << (out_awsize + burst_len_log2));
// reserved
default: begin
burst_mask = '0;
AWBURST_invalid: assert (reset || !aw_fifo_out_valid);
end
endcase
end
// The AXI spec says that the wstrb bits are restricted by the burst size
// and alignment.
//
// Choosing to pass on invalid wstrb bits or to implicitly clear them could
// hide bugs in designs that do produce such invalid strobe bits, so we are
// checking this here.
always @(posedge clock) begin
if (!reset && rvfi_bus_valid)
WSTRB_invalid: assert (!(out_wstrb & ~alignment_mask));
end
always @(posedge clock) begin
if (!reset) begin
if (b_transfer) begin
unexpected_B_transfer: assert (fut_b_fifo_out_valid);
// Only assume this when we can actually pull a not-yet
// constrained value from the FIFO, so that this assumption
// cannot hide any AXI signalling errors.
assume ((out_bresp == axi_bresp) || !fut_b_fifo_out_valid);
end
end
end
`ifdef RISCV_FORMAL_BUS
initial begin
BUSLEN_too_small: assert (AXI_DATA_WIDTH <= `RISCV_FORMAL_BUSLEN);
XLEN_too_small: assert (AXI_ADDRESS_WIDTH <= `RISCV_FORMAL_XLEN);
end
`endif
assign rvfi_bus_rdata = '0;
assign rvfi_bus_wdata = out_wdata;
assign rvfi_bus_wmask = out_wstrb;
assign rvfi_bus_addr = bus_aligned_addr;
assign rvfi_bus_insn = !IGNORE_PROT_DATA_INSN && out_awprot[2];
assign rvfi_bus_data = IGNORE_PROT_DATA_INSN || !out_awprot[2];
assign rvfi_bus_rmask = 0;
assign rvfi_bus_fault = out_aw_bresp[1];
assign rvfi_bus_valid = w_fifo_out_valid && aw_fifo_out_valid && ((out_awid & AXI_ID_MASK) == AXI_ID);
endmodule
module rvfi_bus_axi4_observer_read #(
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ADDRESS_WIDTH = 32,
parameter AXI_ID_WIDTH = 1,
parameter AXI_ARUSER_WIDTH = 1,
parameter AXI_RUSER_WIDTH = 1,
parameter AXI_ID_MASK = 0,
parameter AXI_ID = 0,
parameter DEPTH = 2,
parameter IGNORE_PROT_DATA_INSN = 0
) (
input clock,
input reset,
// Read Address Channel (AR)
input [AXI_ID_WIDTH-1:0] axi_arid,
input [AXI_ADDRESS_WIDTH-1:0] axi_araddr,
input [3:0] axi_arregion,
input [7:0] axi_arlen,
input [2:0] axi_arsize,
input [1:0] axi_arburst,
input axi_arlock,
input [3:0] axi_arcache,
input [2:0] axi_arprot,
input [3:0] axi_arqos,
input [AXI_ARUSER_WIDTH-1:0] axi_aruser,
input axi_arvalid,
input axi_arready,
// Read Data Channel (R)
input [AXI_ID_WIDTH-1:0] axi_rid,
input [AXI_DATA_WIDTH-1:0] axi_rdata,
input [1:0] axi_rresp,
input axi_rlast,
input [AXI_RUSER_WIDTH-1:0] axi_ruser,
input axi_rvalid,
input axi_rready
`RVFI_BUS_CHANNEL_OUTPUTS
);
wire ar_transfer = axi_arvalid && axi_arready;
wire r_transfer = axi_rvalid && axi_rready;
wire ar_transfer_match = ar_transfer && ((axi_arid & AXI_ID_MASK) == AXI_ID);
wire r_transfer_match = r_transfer && ((axi_rid & AXI_ID_MASK) == AXI_ID);
wire [AXI_ADDRESS_WIDTH-1:0] out_araddr;
wire [7:0] out_arlen;
wire [2:0] out_arsize;
wire [1:0] out_arburst;
wire [2:0] out_arprot;
wire fifo_in_ready, fifo_out_valid;
rvfi_bus_util_fifo #(
.DEPTH(DEPTH),
.WIDTH(AXI_ADDRESS_WIDTH + 8 + 3 + 2 + 3)
) aw_fifo (
.clock(clock),
.reset(reset),
.in_data( {axi_araddr, axi_arlen, axi_arsize, axi_arburst, axi_arprot}),
.out_data({out_araddr, out_arlen, out_arsize, out_arburst, out_arprot}),
.in_valid(ar_transfer_match),
.in_ready(fifo_in_ready),
.out_ready(r_transfer_match && axi_rlast),
.out_valid(fifo_out_valid)
);
always @(posedge clock) begin
if (!reset) begin
if (ar_transfer_match)
DEPTH_too_small: assert (fifo_in_ready);
if (r_transfer_match)
unexpected_R_transfer: assert (fifo_out_valid);
end
end
reg [7:0] burst_counter;
reg [AXI_ADDRESS_WIDTH-1:0] burst_offset;
always @(posedge clock) begin
if (r_transfer_match) begin
if (!reset)
RLAST_invalid: assert (axi_rlast == (burst_counter == out_arlen));
if (axi_rlast) begin
burst_counter <= 0;
burst_offset <= 0;
end else begin
burst_counter <= burst_counter + 1'b1;
burst_offset <= burst_offset + (1 << out_arsize);
end
end
if (reset) begin
burst_counter <= 0;
burst_offset <= 0;
end
end
// Mask of address bits that can change between transfers of the same burst
// given the current burst type. This is used to compute the unaligned
// transfer address.
reg [AXI_ADDRESS_WIDTH-1:0] burst_mask;
// Log2 of the burst length, used to compute the burst mask for the WRAP
// burst type.
reg [2:0] burst_len_log2;
// Current transfer address, not aligned.
//
// When unaligned, it stays unaligned for the entire burst and always
// increments by the burst size. This means that transfers past the initial
// can include bytes below this address down to the next size aligned
// address.
wire [AXI_ADDRESS_WIDTH-1:0] unaligned_addr =
( burst_mask & (out_araddr + burst_offset)) |
(~burst_mask & out_araddr);
// Current transfer address, aligned to the burst size.
wire [AXI_ADDRESS_WIDTH-1:0] size_aligned_addr =
unaligned_addr & ('1 << out_arsize);
// Current transfer address, aligned to the bus width.
wire [AXI_ADDRESS_WIDTH-1:0] bus_aligned_addr =
unaligned_addr & ~(AXI_DATA_WIDTH/8 - 1);
// Mask of data bytes/strobe bits that are active given the current
// transfer address and burst size.
wire [AXI_DATA_WIDTH/8-1:0] size_mask =
(~('1 << (1 << out_arsize))) << (size_aligned_addr ^ bus_aligned_addr);
// Mask of data bytes/strobe bits that are active given the current
// misalignment (subset of size_mask). After the initial transfer in a
// burst, this is always the same as size_mask, as the transfer includes
// the remaining bytes that did not fit into the previous transfer.
wire [AXI_DATA_WIDTH/8-1:0] alignment_mask =
burst_counter ? size_mask : size_mask & (size_mask << (unaligned_addr ^ size_aligned_addr));
always @* begin
case (out_arlen)
8'h00: burst_len_log2 = 0;
8'h01: burst_len_log2 = 1;
8'h03: burst_len_log2 = 2;
8'h07: burst_len_log2 = 3;
8'h0f: burst_len_log2 = 4;
default: begin
burst_len_log2 = 0;
ARLEN_invalid_for_ARBURST: assert (reset || !fifo_out_valid || out_arburst != 2'b10);
end
endcase
case (out_arburst)
// FIXED
2'b00: burst_mask = '0;
// INCR
2'b01: burst_mask = '1;
// WRAP
2'b10: burst_mask = ~('1 << (out_arsize + burst_len_log2));
// reserved
default: begin
burst_mask = '0;
ARBURST_invalid: assert (reset || !fifo_out_valid);
end
endcase
end
`ifdef RISCV_FORMAL_BUS
initial begin
BUSLEN_too_small: assert (AXI_DATA_WIDTH <= `RISCV_FORMAL_BUSLEN);
XLEN_too_small: assert (AXI_ADDRESS_WIDTH <= `RISCV_FORMAL_XLEN);
end
`endif
assign rvfi_bus_rdata = axi_rdata;
assign rvfi_bus_wdata = '0;
assign rvfi_bus_addr = bus_aligned_addr;
assign rvfi_bus_rmask = alignment_mask;
assign rvfi_bus_insn = IGNORE_PROT_DATA_INSN || out_arprot[2];
assign rvfi_bus_data = IGNORE_PROT_DATA_INSN || !out_arprot[2];
assign rvfi_bus_wmask = 0;
assign rvfi_bus_fault = axi_rresp[1];
assign rvfi_bus_valid = r_transfer_match;
endmodule
module rvfi_bus_axi4_abstract_read #(
parameter AXI_ADDRESS_WIDTH = 32,
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ID_WIDTH = 1,
parameter AXI_ARUSER_WIDTH = 1,
parameter AXI_RUSER_WIDTH = 1,
parameter DEPTH = 2
) (
input wire clock,
input wire reset,
// Read Address Channel (AR)
input wire [AXI_ID_WIDTH-1:0] axi_arid,
input wire [AXI_ADDRESS_WIDTH-1:0] axi_araddr,
input wire [3:0] axi_arregion,
input wire [7:0] axi_arlen,
input wire [2:0] axi_arsize,
input wire [1:0] axi_arburst,
input wire axi_arlock,
input wire [3:0] axi_arcache,
input wire [2:0] axi_arprot,
input wire [3:0] axi_arqos,
input wire [AXI_ARUSER_WIDTH-1:0] axi_aruser,
input wire axi_arvalid,
output var axi_arready,
// Read Data Channel (R)
output var [AXI_ID_WIDTH-1:0] axi_rid,
output var [AXI_DATA_WIDTH-1:0] axi_rdata,
output var [1:0] axi_rresp,
output var axi_rlast,
output var [AXI_RUSER_WIDTH-1:0] axi_ruser,
output var axi_rvalid,
input wire axi_rready
);
`rvformal_rand_reg rand_arready;
`rvformal_rand_reg [AXI_ID_WIDTH-1:0] rand_rid;
`rvformal_rand_reg [AXI_DATA_WIDTH-1:0] rand_rdata;
`rvformal_rand_reg [1:0] rand_rresp;
`rvformal_rand_reg rand_rlast;
`rvformal_rand_reg [AXI_RUSER_WIDTH-1:0] rand_ruser;
`rvformal_rand_reg rand_rvalid;
logic reset_q;
// Read Address Channel (AR)
logic [AXI_ID_WIDTH-1:0] axi_arid_q;
logic [AXI_ADDRESS_WIDTH-1:0] axi_araddr_q;
logic [3:0] axi_arregion_q;
logic [7:0] axi_arlen_q;
logic [2:0] axi_arsize_q;
logic [1:0] axi_arburst_q;
logic axi_arlock_q;
logic [3:0] axi_arcache_q;
logic [2:0] axi_arprot_q;
logic [3:0] axi_arqos_q;
logic [AXI_ARUSER_WIDTH-1:0] axi_aruser_q;
logic axi_arvalid_q;
logic axi_arready_q;
// Read Data Channel (R)
logic [AXI_ID_WIDTH-1:0] axi_rid_q;
logic [AXI_DATA_WIDTH-1:0] axi_rdata_q;
logic [1:0] axi_rresp_q;
logic axi_rlast_q;
logic [AXI_RUSER_WIDTH-1:0] axi_ruser_q;
logic axi_rvalid_q;
logic axi_rready_q;
always @(posedge clock) begin
reset_q <= reset;
axi_arid_q <= axi_arid;
axi_araddr_q <= axi_araddr;
axi_arregion_q <= axi_arregion;
axi_arlen_q <= axi_arlen;
axi_arsize_q <= axi_arsize;
axi_arburst_q <= axi_arburst;
axi_arlock_q <= axi_arlock;
axi_arcache_q <= axi_arcache;
axi_arprot_q <= axi_arprot;
axi_arqos_q <= axi_arqos;
axi_aruser_q <= axi_aruser;
axi_arvalid_q <= axi_arvalid;
axi_arready_q <= axi_arready;
axi_rid_q <= axi_rid;
axi_rdata_q <= axi_rdata;
axi_rresp_q <= axi_rresp;
axi_rlast_q <= axi_rlast;
axi_ruser_q <= axi_ruser;
axi_rvalid_q <= axi_rvalid;
axi_rready_q <= axi_rready;
end
wire logic ar_transfer = axi_arvalid && axi_arready;
wire logic ar_transfer_q = axi_arvalid_q && axi_arready_q;
wire logic r_transfer = axi_rvalid && axi_rready;
wire logic r_transfer_q = axi_rvalid_q && axi_rready_q;
wire logic r_new = axi_rvalid && (!axi_rvalid_q || axi_rready_q);
wire logic r_stable = axi_rvalid_q && !axi_rvalid_q;
assign axi_arready = rand_arready;
assign axi_rid = r_stable ? axi_rid_q : rand_rid;
assign axi_rdata = r_stable ? axi_rdata_q : rand_rdata;
assign axi_rresp = r_stable ? axi_rresp_q : rand_rresp;
assign axi_rlast = r_stable ? axi_rlast_q : rand_rlast;
assign axi_ruser = r_stable ? axi_ruser_q : rand_ruser;
assign axi_rvalid = r_stable ? axi_rvalid_q : rand_rvalid;
logic [AXI_ID_WIDTH-1:0] read_id [0:DEPTH];
logic [AXI_ID_WIDTH-1:0] read_id_q [0:DEPTH];
logic [7:0] read_len [0:DEPTH];
logic [7:0] read_len_q [0:DEPTH];
logic [DEPTH:0] ar_mask;
logic [DEPTH:0] ar_mask_q;
logic matched;
logic last_read;
always @* begin
for (int i = 0; i <= DEPTH; i++) begin
read_id[i] = read_id_q[i];
read_len[i] = read_len_q[i];
end
matched = 0;
last_read = 0;
ar_mask = 0;
if (!reset) begin
ar_mask = ar_mask_q;
if (ar_transfer_q) begin
// insert new read burst
assume(!ar_mask[0]);
for (int i = 0; i <= DEPTH; i++) begin
if (!ar_mask[i]) begin
read_id[i] = axi_arid_q;
read_len[i] = axi_arlen_q;
end
end
ar_mask = (ar_mask << 1) | 1'b1;
end
if (r_new) begin
// update oldest read burst with a matching id, removing it
// when it is completed
for (int i = DEPTH; i >= 0; i--) begin
if (!matched && ar_mask[i] && read_id[i] == axi_rid) begin
matched = 1;
if (read_len[i] > 0) begin
read_len[i] -= 1;
end else begin
last_read = 1;
end
end
if (last_read) begin
if (i > 0) begin
read_len[i] = read_len[i - 1];
end
end
end
assume (matched);
assume (axi_rlast == last_read);
if (last_read) begin
ar_mask >>= 1;
end
end
end
end
always @(posedge clock) begin
for (int i = 0; i <= DEPTH; i++) begin
read_id_q[i] <= read_id[i];
read_len_q[i] <= read_len[i];
end
ar_mask_q <= ar_mask;
end
endmodule
module rvfi_bus_axi4_abstract_write #(
parameter AXI_ADDRESS_WIDTH = 32,
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ID_WIDTH = 1,
parameter AXI_AWUSER_WIDTH = 1,
parameter AXI_WUSER_WIDTH = 1,
parameter AXI_BUSER_WIDTH = 1,
parameter DEPTH = 2,
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8
) (
input wire clock,
input wire reset,
// Write Address Channel (AW)
input wire [AXI_ID_WIDTH-1:0] axi_awid,
input wire [AXI_ADDRESS_WIDTH-1:0] axi_awaddr,
input wire [3:0] axi_awregion,
input wire [7:0] axi_awlen,
input wire [2:0] axi_awsize,
input wire [1:0] axi_awburst,
input wire axi_awlock,
input wire [3:0] axi_awcache,
input wire [2:0] axi_awprot,
input wire [3:0] axi_awqos,
input wire [AXI_AWUSER_WIDTH-1:0] axi_awuser,
input wire axi_awvalid,
output var axi_awready,
// Write Data Channel (W)
input wire [AXI_DATA_WIDTH-1:0] axi_wdata,
input wire [AXI_STRB_WIDTH-1:0] axi_wstrb,
input wire axi_wlast,
input wire [AXI_WUSER_WIDTH-1:0] axi_wuser,
input wire axi_wvalid,
output var axi_wready,
// Write Response Channel (B)
output var [AXI_ID_WIDTH-1:0] axi_bid,
output var [1:0] axi_bresp,
output var [AXI_BUSER_WIDTH-1:0] axi_buser,
output var axi_bvalid,
input wire axi_bready
);
`rvformal_rand_reg rand_awready;
`rvformal_rand_reg rand_wready;
`rvformal_rand_reg [AXI_ID_WIDTH-1:0] rand_bid;
`rvformal_rand_reg [1:0] rand_bresp;
`rvformal_rand_reg [AXI_BUSER_WIDTH-1:0] rand_buser;
`rvformal_rand_reg rand_bvalid;
logic reset_q;
// Write Address Channel (AW)
logic [AXI_ID_WIDTH-1:0] axi_awid_q;
logic [AXI_ADDRESS_WIDTH-1:0] axi_awaddr_q;
logic [3:0] axi_awregion_q;
logic [7:0] axi_awlen_q;
logic [2:0] axi_awsize_q;
logic [1:0] axi_awburst_q;
logic axi_awlock_q;
logic [3:0] axi_awcache_q;
logic [2:0] axi_awprot_q;
logic [3:0] axi_awqos_q;
logic [AXI_AWUSER_WIDTH-1:0] axi_awuser_q;
logic axi_awvalid_q;
logic axi_awready_q;
// Write Data Channel (W)
logic [AXI_DATA_WIDTH-1:0] axi_wdata_q;
logic [AXI_STRB_WIDTH-1:0] axi_wstrb_q;
logic axi_wlast_q;
logic [AXI_WUSER_WIDTH-1:0] axi_wuser_q;
logic axi_wvalid_q;
logic axi_wready_q;
// Write Response Channel (B)
logic [AXI_ID_WIDTH-1:0] axi_bid_q;
logic [1:0] axi_bresp_q;
logic [AXI_BUSER_WIDTH-1:0] axi_buser_q;
logic axi_bvalid_q;
logic axi_bready_q;
always @(posedge clock) begin
reset_q <= reset;
axi_awid_q <= axi_awid;
axi_awaddr_q <= axi_awaddr;
axi_awregion_q <= axi_awregion;
axi_awlen_q <= axi_awlen;
axi_awsize_q <= axi_awsize;
axi_awburst_q <= axi_awburst;
axi_awlock_q <= axi_awlock;
axi_awcache_q <= axi_awcache;
axi_awprot_q <= axi_awprot;
axi_awqos_q <= axi_awqos;
axi_awuser_q <= axi_awuser;
axi_awvalid_q <= axi_awvalid;
axi_awready_q <= axi_awready;
axi_wdata_q <= axi_wdata;
axi_wstrb_q <= axi_wstrb;
axi_wlast_q <= axi_wlast;
axi_wuser_q <= axi_wuser;
axi_wvalid_q <= axi_wvalid;
axi_wready_q <= axi_wready;
axi_bid_q <= axi_bid;
axi_bresp_q <= axi_bresp;
axi_buser_q <= axi_buser;
axi_bvalid_q <= axi_bvalid;
axi_bready_q <= axi_bready;
end
wire logic aw_transfer = axi_awvalid && axi_awready;
wire logic aw_transfer_q = axi_awvalid_q && axi_awready_q;
wire logic w_transfer = axi_wvalid && axi_wready;
wire logic w_transfer_q = axi_wvalid_q && axi_wready_q;
wire logic b_transfer = axi_bvalid && axi_bready;
wire logic b_transfer_q = axi_bvalid_q && axi_bready_q;
wire logic b_stable = axi_bvalid_q && !axi_bready_q;
wire logic b_new = axi_bvalid && (!axi_bvalid_q || axi_bready_q);
assign axi_awready = rand_awready;
assign axi_wready = rand_wready;
assign axi_bid = b_stable ? axi_bid_q : rand_bid;
assign axi_bresp = b_stable ? axi_bresp_q : rand_bresp;
assign axi_buser = b_stable ? axi_buser_q : rand_buser;
assign axi_bvalid = b_stable ? axi_bvalid_q : rand_bvalid;
logic [AXI_ID_WIDTH-1:0] write_id [0:DEPTH];
logic [AXI_ID_WIDTH-1:0] write_id_q [0:DEPTH];
logic [DEPTH:0] aw_mask;
logic [DEPTH:0] aw_mask_q;
logic [DEPTH:0] wlast_mask;
logic [DEPTH:0] wlast_mask_q;
logic matched;
always @* begin
for (int i = 0; i <= DEPTH; i++) begin
write_id[i] = write_id_q[i];
end
aw_mask = 0;
wlast_mask = 0;
matched = 0;
if (!reset) begin
aw_mask = aw_mask_q;
wlast_mask = wlast_mask_q;
if (aw_transfer_q) begin
assume (!aw_mask[0]);
for (int i = 0; i <= DEPTH; i++) begin
if (!aw_mask[i]) begin
write_id[i] = axi_awid_q;
end
end
aw_mask = (aw_mask << 1) | 1'b1;
end
if (w_transfer_q && axi_wlast_q) begin
assume (wlast_mask[0] == 0);
wlast_mask = (wlast_mask << 1) | 1'b1;
end
if (b_new) begin
for (int i = DEPTH; i >= 0; i--) begin
if (!matched && aw_mask[i] && wlast_mask[i] && write_id[i] == axi_bid) begin
matched = 1;
end
if (matched) begin
if (i > 0) begin
write_id[i] = write_id[i-1];
end
end
end
assume (matched);
aw_mask = aw_mask >> 1;
wlast_mask = wlast_mask >> 1;
end
end
end
always @(posedge clock) begin
aw_mask_q <= aw_mask;
wlast_mask_q <= wlast_mask;
for (int i = 0; i <= DEPTH; i++) begin
write_id_q[i] <= write_id[i];
end
end
endmodule
================================================
FILE: bus/rvfi_bus_util.sv
================================================
// Utility code for RVFI_BUS observers
//
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_util_fifo_stage #(
parameter WIDTH = 8
) (
input clock,
input reset,
input in_valid,
output in_ready,
input [WIDTH-1:0] in_data,
output out_valid,
input out_ready,
output [WIDTH-1:0] out_data
);
reg [WIDTH-1:0] buffered;
reg buffer_valid;
wire in_txn = in_valid && in_ready;
wire out_txn = out_valid && out_ready;
assign out_data = buffer_valid ? buffered : in_data;
assign in_ready = out_ready || !buffer_valid;
assign out_valid = in_valid || buffer_valid;
always @(posedge clock) begin
if (reset) begin
buffer_valid <= 0;
end else begin
if (in_txn != out_txn)
buffer_valid <= in_txn;
end
if (in_txn)
buffered <= in_data;
end
endmodule
module rvfi_bus_util_fifo #(
parameter WIDTH = 8,
parameter DEPTH = 3
) (
input clock,
input reset,
input in_valid,
output in_ready,
input [WIDTH-1:0] in_data,
output out_valid,
input out_ready,
output [WIDTH-1:0] out_data
);
wire [WIDTH-1:0] stage_data [0:DEPTH];
wire [DEPTH:0] stage_valid;
wire [DEPTH:0] stage_ready;
genvar i;
generate for (i = 0; i < DEPTH; i = i + 1) begin
rvfi_bus_util_fifo_stage #(.WIDTH(WIDTH)) stage (
.clock(clock),
.reset(reset),
.in_data(stage_data[i]),
.out_data(stage_data[i+1]),
.in_valid(stage_valid[i]),
.out_valid(stage_valid[i+1]),
.in_ready(stage_ready[i]),
.out_ready(stage_ready[i+1])
);
end endgenerate
assign stage_valid[0] = in_valid;
assign stage_data[0] = in_data;
assign in_ready = stage_ready[0];
assign out_valid = stage_valid[DEPTH];
assign stage_ready[DEPTH] = out_ready;
assign out_data = stage_data[DEPTH];
endmodule
================================================
FILE: checks/genchecks.py
================================================
#!/usr/bin/env python3
#
# Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import os, sys, shutil, re
from functools import reduce
nret = 1
isa = "rv32i"
ilen = 32
xlen = 32
buslen = 32
nbus = 1
csrs = set()
custom_csrs = set()
illegal_csrs = set()
csr_tests = {}
csr_spec = None
compr = False
depths = list()
groups = [None]
blackbox = False
cfgname = "checks"
basedir = f"{os.getcwd()}/../.."
corename = os.getcwd().split("/")[-1]
solver = "boolector"
dumpsmt2 = False
abspath = False
sbycmd = "sby"
config = dict()
mode = "bmc"
if len(sys.argv) > 1:
assert len(sys.argv) == 2
cfgname = sys.argv[1]
print(f"Reading {cfgname}.cfg.")
with open(f"{cfgname}.cfg", "r") as f:
cfgsection = None
cfgsubsection = None
for line in f:
line = line.strip()
if line.startswith("#"):
continue
if line.startswith("[") and line.endswith("]"):
cfgsection = line.lstrip("[").rstrip("]")
cfgsubsection = None
if cfgsection.startswith("assume ") or cfgsection == "assume":
cfgsubsection = cfgsection.split()[1:]
cfgsection = "assume"
continue
if cfgsection is not None:
if cfgsubsection is None:
if cfgsection not in config:
config[cfgsection] = ""
config[cfgsection] += f"{line}\n"
else:
if cfgsection not in config:
config[cfgsection] = []
config[cfgsection].append((cfgsubsection, line))
if "options" in config:
for line in config["options"].split("\n"):
line = line.split()
if len(line) == 0:
continue
elif line[0] == "nret":
assert len(line) == 2
nret = int(line[1])
elif line[0] == "isa":
assert len(line) == 2
isa = line[1]
elif line[0] == "blackbox":
assert len(line) == 1
blackbox = True
elif line[0] == "solver":
assert len(line) == 2
solver = line[1]
elif line[0] == "dumpsmt2":
assert len(line) == 1
dumpsmt2 = True
elif line[0] == "abspath":
assert len(line) == 1
abspath = True
elif line[0] == "mode":
assert len(line) == 2
assert(line[1] in ("bmc", "prove", "cover"))
mode = line[1]
elif line[0] == "buslen":
assert len(line) == 2
buslen = int(line[1])
elif line[0] == "nbus":
assert len(line) == 2
nbus = int(line[1])
elif line[0] == "csr_spec":
assert len(line) == 2
csr_spec = line[1]
else:
print(line)
assert 0
if "64" in isa:
xlen = 64
if "c" in isa:
compr = True
def add_csr_tests(name, test_str):
# use regex to split by spaces, unless those spaces are inside quotation marks
# e.g. const="32'h dead_beef" is one match not two
# const="32'h 0"_mask="32'h dead_beef" is also one match
tests = re.findall("((?:\S*?\"[^\"]*\")+|\S+)", test_str)
csr_tests[name] = tests
def add_csr(csr_str):
try:
(name, tests) = csr_str.split(maxsplit=1)
add_csr_tests(name, tests)
except ValueError: # no tests
name = csr_str.strip()
csrs.add(name)
return name
def mask_bits(test: str, bits: "list[int]", mask_len: int, invert=False):
mask = reduce(lambda x, y: x | 1<<y, bits, 0)
fstring = f"{test}_mask={'~' if invert else ''}{mask_len}'b{{:0{mask_len}b}}"
return fstring.format(mask)
if csr_spec == "1.12":
spec_csrs = {
"mvendorid" : ["const"],
"marchid" : ["const"],
"mimpid" : ["const"],
"mhartid" : ["const"],
"mconfigptr" : ["const"],
# All reserved bits should be 0
"mstatus" : [mask_bits("zero",
[0, 2, 4, *range(23, 31)] + ([31, *range(38, 63)] if xlen==64 else []),
xlen)],
"misa" : [mask_bits("zero",
[6, 10, 11, 14, 17, 19, 22, 24, 25, *range(26, xlen-2)],
xlen)],
"mie" : None,
"mtvec" : None,
"mscratch" : ["any"],
"mepc" : None,
"mcause" : None,
"mtval" : None,
"mip" : None,
"mcycle" : ["inc"],
"minstret" : ["inc"],
}
spec_csrs.update({f"mhpmcounter{i}" : None for i in range(3, 32)})
spec_csrs.update({f"mhpmevent{i}" : None for i in range(3, 32)})
restricted_csrs = {
"medeleg" : ("s", "302", None),
"mideleg" : ("s", "303", None),
"mcounteren" : ("u", "306", None),
"mstatush" : ("32", "310", [mask_bits("zero", [4, 5], xlen, invert=True)]),
"mtinst" : ("h", "34A", None),
"mtval2" : ("h", "34B", None),
"menvcfg" : ("u", "30A", None),
"menvcfgh" : ("u", "31A", None), # u-mode only *and* 32bit only
}
for (name, data) in restricted_csrs.items():
if data[0] in isa:
spec_csrs[name] = data[2]
else:
illegal_csrs.add(
(data[1], "m", "rw"),
)
for (name, tests) in spec_csrs.items():
csrs.add(name)
if tests:
csr_tests[name] = tests
if "csrs" in config:
for line in config["csrs"].split("\n"):
if line:
add_csr(line)
if "custom_csrs" in config:
for line in config["custom_csrs"].split("\n"):
try:
(addr, levels, csr_str) = line.split(maxsplit=2)
except ValueError: # no csr
continue
name = add_csr(csr_str)
custom_csrs.add((name, int(addr, base=16), levels))
if "illegal_csrs" in config:
for line in config["illegal_csrs"].split("\n"):
line = tuple(line.split())
if len(line) == 0:
continue
assert len(line) == 3
illegal_csrs.add(line)
if "groups" in config:
groups += config["groups"].split()
print(f"Creating {cfgname} directory.")
shutil.rmtree(cfgname, ignore_errors=True)
os.mkdir(cfgname)
def hfmt(text, **kwargs):
lines = []
for line in text.split("\n"):
match = re.match(r"^\s*: ?(.*)", line)
if match:
line = match.group(1)
elif line.strip() == "":
continue
lines.append(re.sub(r"@([a-zA-Z0-9_]+)@",
lambda match: str(kwargs[match.group(1)]), line))
return lines
def print_hfmt(f, text, **kwargs):
for line in hfmt(text, **kwargs):
print(line, file=f)
hargs = dict()
hargs["basedir"] = basedir
hargs["core"] = corename
hargs["nret"] = nret
hargs["xlen"] = xlen
hargs["ilen"] = ilen
hargs["buslen"] = buslen
hargs["nbus"] = nbus
hargs["append"] = 0
hargs["mode"] = mode
if "cover" in config:
hargs["cover"] = config["cover"]
instruction_checks = set()
consistency_checks = set()
if solver == "bmc3":
hargs["engine"] = "abc bmc3"
hargs["ilang_file"] = f"{corename}-gates.il"
elif solver == "btormc":
hargs["engine"] = "btor btormc"
hargs["ilang_file"] = f"{corename}-hier.il"
else:
hargs["engine"] = f"smtbmc {'--dumpsmt2 ' if dumpsmt2 else ''}{solver}"
hargs["ilang_file"] = f"{corename}-hier.il"
def test_disabled(check):
if "filter-checks" in config:
for line in config["filter-checks"].split("\n"):
line = line.strip().split()
if len(line) == 0: continue
assert len(line) == 2 and line[0] in ["-", "+"]
if re.match(line[1], check):
return line[0] == "-"
return False
def get_depth_cfg(patterns):
ret = None
if "depth" in config:
for line in config["depth"].split("\n"):
line = line.strip().split()
if len(line) == 0:
continue
for pat in patterns:
if re.fullmatch(line[0], pat):
ret = [int(s) for s in line[1:]]
return ret
def print_custom_csrs(sby_file):
fstrings = {
"inputs": " ,input [`RISCV_FORMAL_NRET * `RISCV_FORMAL_XLEN - 1 : 0] rvfi_csr_{csr}_{signal} \\",
"wires": " (* keep *) wire [`RISCV_FORMAL_NRET * `RISCV_FORMAL_XLEN - 1 : 0] rvfi_csr_{csr}_{signal}; \\",
"conn": " ,.rvfi_csr_{csr}_{signal} (rvfi_csr_{csr}_{signal}) \\",
"channel": " wire [`RISCV_FORMAL_XLEN - 1 : 0] csr_{csr}_{signal} = rvfi_csr_{csr}_{signal} [(_idx)*(`RISCV_FORMAL_XLEN) +: `RISCV_FORMAL_XLEN]; \\",
"signals": "`RISCV_FORMAL_CHANNEL_SIGNAL(`RISCV_FORMAL_NRET, `RISCV_FORMAL_XLEN, csr_{csr}_{signal}) \\",
"outputs": " ,output [`RISCV_FORMAL_NRET * `RISCV_FORMAL_XLEN - 1 : 0] rvfi_csr_{csr}_{signal} \\",
"indices": " localparam [11:0] csr_{level}index_{name} = 12'h{index:03X}; \\"
}
for (macro, fstring) in fstrings.items():
if macro == "channel":
print(f"`define RISCV_FORMAL_CUSTOM_CSR_{macro.upper()}(_idx) \\" , file=sby_file)
else:
print(f"`define RISCV_FORMAL_CUSTOM_CSR_{macro.upper()} \\", file=sby_file)
for custom_csr in custom_csrs:
name = custom_csr[0]
addr = custom_csr[1]
levels = custom_csr[2]
if macro == "indices":
for level in ["m", "s", "u"]:
if level in levels:
macro_string = fstring.format(level=level, name=name, index=addr)
else:
macro_string = fstring.format(level=level, name=name, index=0xfff)
print(macro_string, file=sby_file)
else:
for signal in ["rmask", "wmask", "rdata", "wdata"]:
macro_string = fstring.format(csr=name, signal=signal)
print(macro_string, file=sby_file)
print("", file=sby_file)
# ------------------------------ Instruction Checkers ------------------------------
def check_insn(grp, insn, chanidx, csr_mode=False, illegal_csr=False):
pf = "" if grp is None else grp+"_"
if illegal_csr:
(ill_addr, ill_modes, ill_rw) = insn
insn = f"12'h{int(ill_addr, base=16):03X}"
check = f"{pf}csr_ill_{ill_addr}_ch{chanidx:d}"
depth_cfg = get_depth_cfg([f"{pf}csr_ill", f"{pf}csr_ill_ch{chanidx:d}", f"{pf}csr_ill_{ill_addr}", f"{pf}csr_ill_{ill_addr}_ch{chanidx:d}"])
else:
if csr_mode:
check = "csrw"
else:
check = "insn"
depth_cfg = get_depth_cfg([f"{pf}{check}", f"{pf}{check}_ch{chanidx:d}", f"{pf}{check}_{insn}", f"{pf}{check}_{insn}_ch{chanidx:d}"])
check = f"{pf}{check}_{insn}_ch{chanidx:d}"
if depth_cfg is None: return
assert len(depth_cfg) == 1
if test_disabled(check): return
instruction_checks.add(check)
hargs["insn"] = insn
hargs["checkch"] = check
hargs["channel"] = f"{chanidx:d}"
hargs["depth"] = depth_cfg[0]
hargs["depth_plus"] = depth_cfg[0] + 1
hargs["skip"] = depth_cfg[0]
with open(f"{cfgname}/{check}.sby", "w") as sby_file:
print_hfmt(sby_file, """
: [options]
: mode @mode@
: expect pass,fail
: append @append@
: depth @depth_plus@
: skip @skip@
:
: [engines]
: @engine@
:
: [script]
""", **hargs)
if "script-defines" in config:
print_hfmt(sby_file, config["script-defines"], **hargs)
sv_files = [f"{check}.sv"]
if "verilog-files" in config:
sv_files += hfmt(config["verilog-files"], **hargs)
vhdl_files = []
if "vhdl-files" in config:
vhdl_files += hfmt(config["vhdl-files"], **hargs)
if len(sv_files):
print(f"read -sv {' '.join(sv_files)}", file=sby_file)
if len(vhdl_files):
print(f"read -vhdl {' '.join(vhdl_files)}", file=sby_file)
if "script-sources" in config:
print_hfmt(sby_file, config["script-sources"], **hargs)
print_hfmt(sby_file, """
: prep -flatten -nordff -top rvfi_testbench
""", **hargs)
if "script-link" in config:
print_hfmt(sby_file, config["script-link"], **hargs)
print_hfmt(sby_file, """
: chformal -early
:
: [files]
: @basedir@/checks/rvfi_macros.vh
: @basedir@/checks/rvfi_channel.sv
: @basedir@/checks/rvfi_testbench.sv
""", **hargs)
if illegal_csr:
print_hfmt(sby_file, """
: @basedir@/checks/rvfi_csr_ill_check.sv
""", **hargs)
elif csr_mode:
print_hfmt(sby_file, """
: @basedir@/checks/rvfi_csrw_check.sv
""", **hargs)
else:
print_hfmt(sby_file, """
: @basedir@/checks/rvfi_insn_check.sv
: @basedir@/insns/insn_@insn@.v
""", **hargs)
print_hfmt(sby_file, """
:
: [file defines.sv]
: `define RISCV_FORMAL
: `define RISCV_FORMAL_NRET @nret@
: `define RISCV_FORMAL_XLEN @xlen@
: `define RISCV_FORMAL_ILEN @ilen@
: `define RISCV_FORMAL_RESET_CYCLES 1
: `define RISCV_FORMAL_CHECK_CYCLE @depth@
: `define RISCV_FORMAL_CHANNEL_IDX @channel@
""", **hargs)
if "assume" in config:
print("`define RISCV_FORMAL_ASSUME", file=sby_file)
if mode == "prove":
print("`define RISCV_FORMAL_UNBOUNDED", file=sby_file)
for csr in sorted(csrs):
print(f"`define RISCV_FORMAL_CSR_{csr.upper()}", file=sby_file)
if csr_mode and insn in ("mcycle", "minstret"):
print("`define RISCV_FORMAL_CSRWH", file=sby_file)
if illegal_csr:
print_hfmt(sby_file, """
: `define RISCV_FORMAL_CHECKER rvfi_csr_ill_check
: `define RISCV_FORMAL_ILL_CSR_ADDR @insn@
""", **hargs)
if 'm' in ill_modes:
print("`define RISCV_FORMAL_ILL_MMODE", file=sby_file)
if 's' in ill_modes:
print("`define RISCV_FORMAL_ILL_SMODE", file=sby_file)
if 'u' in ill_modes:
print("`define RISCV_FORMAL_ILL_UMODE", file=sby_file)
if 'r' in ill_rw:
print("`define RISCV_FORMAL_ILL_READ", file=sby_file)
if 'w' in ill_rw:
print("`define RISCV_FORMAL_ILL_WRITE", file=sby_file)
elif csr_mode:
print_hfmt(sby_file, """
: `define RISCV_FORMAL_CHECKER rvfi_csrw_check
: `define RISCV_FORMAL_CSRW_NAME @insn@
""", **hargs)
else:
print_hfmt(sby_file, """
: `define RISCV_FORMAL_CHECKER rvfi_insn_check
: `define RISCV_FORMAL_INSN_MODEL rvfi_insn_@insn@
""", **hargs)
if custom_csrs:
print_custom_csrs(sby_file)
if blackbox:
print("`define RISCV_FORMAL_BLACKBOX_REGS", file=sby_file)
if compr:
print("`define RISCV_FORMAL_COMPRESSED", file=sby_file)
if "defines" in config:
print_hfmt(sby_file, config["defines"], **hargs)
print_hfmt(sby_file, """
: `include "rvfi_macros.vh"
:
: [file @checkch@.sv]
: `include "defines.sv"
: `include "rvfi_channel.sv"
: `include "rvfi_testbench.sv"
""", **hargs)
if illegal_csr:
print_hfmt(sby_file, """
: `include "rvfi_csr_ill_check.sv"
""", **hargs)
elif csr_mode:
print_hfmt(sby_file, """
: `include "rvfi_csrw_check.sv"
""", **hargs)
else:
print_hfmt(sby_file, """
: `include "rvfi_insn_check.sv"
: `include "insn_@insn@.v"
""", **hargs)
if "assume" in config:
print("", file=sby_file)
print("[file assume_stmts.vh]", file=sby_file)
for pat, line in config["assume"]:
enabled = True
for p in pat:
if p.startswith("!"):
p = p[1:]
enabled = False
else:
enabled = True
if re.match(p, check):
enabled = not enabled
break
if enabled:
print(line, file=sby_file)
for grp in groups:
with open(f"../../insns/isa_{isa}.txt") as isa_file:
for insn in isa_file:
for chanidx in range(nret):
check_insn(grp, insn.strip(), chanidx)
for csr in sorted(csrs):
for chanidx in range(nret):
check_insn(grp, csr, chanidx, csr_mode=True)
for ill_csr in sorted(illegal_csrs, key=lambda csr: csr[0]):
for chanidx in range(nret):
check_insn(grp, ill_csr, chanidx, illegal_csr=True)
# ------------------------------ Consistency Checkers ------------------------------
def check_cons(grp, check, chanidx=None, start=None, trig=None, depth=None, csr_mode=False, csr_test=None, bus_mode=False):
pf = "" if grp is None else grp+"_"
if csr_mode:
csr_name = check
if csr_test is not None:
# Check for provided mask
mask_idx = csr_test.find("_mask")
if mask_idx >= 0:
try:
csr_mask = str(csr_test[mask_idx:]).split('=', maxsplit=1)[1].strip('"')
except IndexError: # no value provided
print(csr_test)
assert 0
csr_test = csr_test[:mask_idx]
if csr_test.startswith("const"):
try:
constval = str(csr_test).split('=', maxsplit=1)[1].strip('"')
except IndexError: # no value provided
constval = "rdata_shadow"
check = f"{pf}csrc_const_{csr_name}"
check_name = f"csrc_const"
elif csr_test.startswith("hpm"):
try:
hpmevent = str(csr_test).split('=', maxsplit=1)[1].strip('"')
except IndexError: # no value provided
pass
hpmcounter = str(csr_name).replace("event", "counter")
if hpmcounter not in csrs:
csrs.add(hpmcounter)
check = f"{pf}csrc_hpm_{csr_name}"
check_name = f"csrc_hpm"
else:
check = f"{pf}csrc_{csr_test}_{csr_name}"
check_name =f"csrc_{csr_test}"
else:
check = f"{pf}csrc_{csr_name}"
check_name = "csrc"
hargs["check"] = check_name
if chanidx is not None:
depth_cfg = get_depth_cfg([f"{pf}{check_name}", check, f"{pf}{check_name}_ch{chanidx:d}", f"{check}_ch{chanidx:d}"])
hargs["channel"] = f"{chanidx:d}"
check = f"{check}_ch{chanidx:d}"
else:
depth_cfg = get_depth_cfg([f"{check_name}", check])
else:
hargs["check"] = check
check = pf + check
if chanidx is not None:
depth_cfg = get_depth_cfg([check, f"{check}_ch{chanidx:d}"])
hargs["channel"] = f"{chanidx:d}"
check = f"{check}_ch{chanidx:d}"
else:
depth_cfg = get_depth_cfg([check])
if depth_cfg is None: return
if start is not None:
start = depth_cfg[start]
else:
start = 1
if trig is not None:
trig = depth_cfg[trig]
if depth is not None:
depth = depth_cfg[depth]
hargs["start"] = start
hargs["depth"] = depth
hargs["depth_plus"] = depth + 1
hargs["skip"] = depth
hargs["checkch"] = check
hargs["xmode"] = hargs["mode"]
if check == "cover" or "csrc_hpm" in check: hargs["xmode"] = "cover"
if test_disabled(check): return
consistency_checks.add(check)
with open(f"{cfgname}/{check}.sby", "w") as sby_file:
print_hfmt(sby_file, """
: [options]
: mode @xmode@
: expect pass,fail
: append @append@
: depth @depth_plus@
: skip @skip@
:
: [engines]
: @engine@
:
: [script]
""", **hargs)
if "script-defines" in config:
print_hfmt(sby_file, config["script-defines"], **hargs)
if (f"script-defines {hargs['check']}") in config:
print_hfmt(sby_file, config[f"script-defines {hargs['check']}"], **hargs)
sv_files = [f"{check}.sv"]
if "verilog-files" in config:
sv_files += hfmt(config["verilog-files"], **hargs)
vhdl_files = []
if "vhdl-files" in config:
vhdl_files += hfmt(config["vhdl-files"], **hargs)
if len(sv_files):
print(f"read -sv {' '.join(sv_files)}", file=sby_file)
if len(vhdl_files):
print(f"read -vhdl {' '.join(vhdl_files)}", file=sby_file)
if "script-sources" in config:
print_hfmt(sby_file, config["script-sources"], **hargs)
print_hfmt(sby_file, """
: prep -flatten -nordff -top rvfi_testbench
""", **hargs)
if "script-link" in config:
print_hfmt(sby_file, config["script-link"], **hargs)
print_hfmt(sby_file, """
: chformal -early
:
: [files]
: @basedir@/checks/rvfi_macros.vh
: @basedir@/checks/rvfi_channel.sv
: @basedir@/checks/rvfi_testbench.sv
: @basedir@/checks/rvfi_@check@_check.sv
:
: [file defines.sv]
""", **hargs)
print_hfmt(sby_file, """
: `define RISCV_FORMAL
: `define RISCV_FORMAL_NRET @nret@
: `define RISCV_FORMAL_XLEN @xlen@
: `define RISCV_FORMAL_ILEN @ilen@
: `define RISCV_FORMAL_CHECKER rvfi_@check@_check
: `define RISCV_FORMAL_RESET_CYCLES @start@
: `define RISCV_FORMAL_CHECK_CYCLE @depth@
""", **hargs)
if "assume" in config:
print("`define RISCV_FORMAL_ASSUME", file=sby_file)
if mode == "prove":
print("`define RISCV_FORMAL_UNBOUNDED", file=sby_file)
for csr in sorted(csrs):
print(f"`define RISCV_FORMAL_CSR_{csr.upper()}", file=sby_file)
if csr_mode:
localdict = locals()
if "constval" in localdict:
print(f"`define RISCV_FORMAL_CSRC_CONSTVAL {constval}", file=sby_file)
if "hpmevent" in localdict:
print(f"`define RISCV_FORMAL_CSRC_HPMEVENT {hpmevent}", file=sby_file)
if "hpmcounter" in localdict:
print(f"`define RISCV_FORMAL_CSRC_HPMCOUNTER {hpmcounter}", file=sby_file)
if "csr_mask" in localdict:
print(f"`define RISCV_FORMAL_CSRC_MASK {csr_mask}", file=sby_file)
print(f"`define RISCV_FORMAL_CSRC_NAME {csr_name}", file=sby_file)
if custom_csrs:
print_custom_csrs(sby_file)
if blackbox and hargs["check"] != "liveness":
print("`define RISCV_FORMAL_BLACKBOX_ALU", file=sby_file)
if blackbox and hargs["check"] != "reg":
print("`define RISCV_FORMAL_BLACKBOX_REGS", file=sby_file)
if chanidx is not None:
print(f"`define RISCV_FORMAL_CHANNEL_IDX {chanidx:d}", file=sby_file)
if trig is not None:
print(f"`define RISCV_FORMAL_TRIG_CYCLE {trig:d}", file=sby_file)
if bus_mode:
print_hfmt(sby_file, """
: `define RISCV_FORMAL_BUS
: `define RISCV_FORMAL_NBUS @nbus@
: `define RISCV_FORMAL_BUSLEN @buslen@
""", **hargs)
if hargs["check"] in ("liveness", "hang"):
print("`define RISCV_FORMAL_FAIRNESS", file=sby_file)
if "defines" in config:
print_hfmt(sby_file, config["defines"], **hargs)
if (f"defines {hargs['check']}") in config:
print_hfmt(sby_file, config[f"defines {hargs['check']}"], **hargs)
print_hfmt(sby_file, """
: `include "rvfi_macros.vh"
:
: [file @checkch@.sv]
: `include "defines.sv"
: `include "rvfi_channel.sv"
: `include "rvfi_testbench.sv"
: `include "rvfi_@check@_check.sv"
""", **hargs)
if check == pf+"cover":
print_hfmt(sby_file, """
:
: [file cover_stmts.vh]
: @cover@
""", **hargs)
if "assume" in config:
print("", file=sby_file)
print("[file assume_stmts.vh]", file=sby_file)
for pat, line in config["assume"]:
enabled = True
for p in pat:
if p.startswith("!"):
p = p[1:]
enabled = False
else:
enabled = True
if re.match(p, check):
enabled = not enabled
break
if enabled:
print(line, file=sby_file)
for grp in groups:
for i in range(nret):
check_cons(grp, "reg", chanidx=i, start=0, depth=1)
check_cons(grp, "pc_fwd", chanidx=i, start=0, depth=1)
check_cons(grp, "pc_bwd", chanidx=i, start=0, depth=1)
check_cons(grp, "liveness", chanidx=i, start=0, trig=1, depth=2)
check_cons(grp, "unique", chanidx=i, start=0, trig=1, depth=2)
check_cons(grp, "causal", chanidx=i, start=0, depth=1)
check_cons(grp, "causal_mem", chanidx=i, start=0, depth=1)
check_cons(grp, "causal_io", chanidx=i, start=0, depth=1)
check_cons(grp, "ill", chanidx=i, depth=0)
check_cons(grp, "fault", chanidx=i, depth=0)
check_cons(grp, "bus_imem", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_imem_fault", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_fault", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_io_read", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_io_read_fault", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_io_write", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_io_write_fault", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "bus_dmem_io_order", chanidx=i, start=0, depth=1, bus_mode=True)
check_cons(grp, "hang", start=0, depth=1)
check_cons(grp, "cover", start=0, depth=1)
for csr in sorted(csrs):
for chanidx in range(nret):
for csr_test in csr_tests.get(csr, [None]):
check_cons(grp, csr, chanidx, start=0, depth=1, csr_mode=True, csr_test=csr_test)
# ------------------------------ Makefile ------------------------------
def checks_key(check):
if "sort" in config:
for index, line in enumerate(config["sort"].split("\n")):
if re.fullmatch(line.strip(), check):
return f"{index:04d}-{check}"
if check.startswith("insn_"):
return f"9999-{check}"
return f"9998-{check}"
with open(f"{cfgname}/makefile", "w") as mkfile:
print("all:", end="", file=mkfile)
checks = list(sorted(consistency_checks | instruction_checks, key=checks_key))
for check in checks:
print(f" {check}", end="", file=mkfile)
print(file=mkfile)
for check in checks:
print(f"{check}: {check}/status", file=mkfile)
print(f"{check}/status:", file=mkfile)
if abspath:
print(f"\t{sbycmd} $(shell pwd)/{check}.sby", file=mkfile)
else:
print(f"\t{sbycmd} {check}.sby", file=mkfile)
print(f".PHONY: {check}", file=mkfile)
print(f"Generated {len(consistency_checks) + len(instruction_checks)} checks.")
================================================
FILE: checks/rvfi_bus_dmem_check.sv
================================================
// external bus: check data reads
//
// Note: This only checks the data on the core side, so it is valid even with
// caches between the checked bus and core. It also checks that the first bus
// read of the checked data makes it to the core, but does not check that any
// writes make it to the bus nor that any other bus-side data makes it to the
// core.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
`ifndef RISCV_FORMAL_FAULT_WIDTH
`define RISCV_FORMAL_FAULT_WIDTH 1
`endif
module rvfi_bus_dmem_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] dmem_addr;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] dmem_data;
reg [ `RISCV_FORMAL_XLEN-1:0] dmem_shadow;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_wmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_wdata;
reg [`RISCV_FORMAL_XLEN-1:0] bus_shadow;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
dmem_shadow <= dmem_data;
bus_shadow <= dmem_data;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
bus_wmask = rvfi_bus_wmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_wdata = rvfi_bus_wdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == dmem_addr + j) begin
if (bus_rmask[i]) begin
assume (bus_rdata[i*8 +: 8] == bus_shadow[j*8 +: 8]);
end
if (bus_wmask[i]) begin
bus_shadow[j*8 +: 8] = bus_wdata[i*8 +: 8];
end
end
if (((bus_addr + i) | (`RISCV_FORMAL_FAULT_WIDTH - 1)) == ((dmem_addr + j) | (`RISCV_FORMAL_FAULT_WIDTH - 1))) begin
if (bus_rmask[i] || bus_wmask[i]) begin
assume (!rvfi_bus_fault[channel_idx]);
end
end
end
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx] && rvfi_mem_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN] == dmem_addr && `rvformal_addr_valid(dmem_addr)) begin
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
if (channel_idx == `RISCV_FORMAL_CHANNEL_IDX &&
check && rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 + i]
) begin
cover (1);
assert (dmem_shadow[i*8 +: 8] == rvfi_mem_rdata[i*8 +: 8]);
end
if (rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 + i]) begin
dmem_shadow[i*8 +: 8] = rvfi_mem_wdata[i*8 +: 8];
end
end
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_fault_check.sv
================================================
// external bus: check faulting data reads
//
// Note: This only checks the data on the core side, so it is valid even with
// caches between the checked bus and core. It also checks that the first bus
// read of the checked data makes it to the core, but does not check that any
// writes make it to the bus nor that any other bus-side data makes it to the
// core.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_fault_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] dmem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_wmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
`ifdef RISCV_FORMAL_MEM_FAULT
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_fault_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_fault_wmask;
`endif
integer channel_idx, i, j;
always @(posedge clock) begin
if (!reset) begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
bus_wmask = rvfi_bus_wmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_wdata = rvfi_bus_wdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == dmem_addr + j) begin
if (bus_rmask[i]) begin
assume (rvfi_bus_fault[channel_idx]);
end
if (bus_wmask[i]) begin
assume (rvfi_bus_fault[channel_idx]);
end
end
end
end
cover (rvfi_bus_fault[channel_idx]);
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`ifdef RISCV_FORMAL_MEM_FAULT
mem_fault_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_fault_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`endif
if (rvfi_valid[channel_idx] && mem_addr == dmem_addr && `rvformal_addr_valid(dmem_addr)) begin
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
if (check && channel_idx == `RISCV_FORMAL_CHANNEL_IDX) begin
`ifndef RISCV_FORMAL_MEM_FAULT
cover (1);
`endif
assert (!mem_rmask[i]);
assert (!mem_wmask[i]);
`ifdef RISCV_FORMAL_MEM_FAULT
cover (mem_fault_rmask[i]);
cover (mem_fault_wmask[i]);
if (mem_fault_rmask[i] || mem_fault_wmask[i]) begin
assert (rvfi_mem_fault[channel_idx]);
end
`endif
end
end
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_io_order_check.sv
================================================
// external bus: check i/o access ordering
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_io_order_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr_0;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr_1;
`rvformal_rand_const_reg check_write_0;
`rvformal_rand_const_reg check_fault_0;
`rvformal_rand_const_reg check_write_1;
`rvformal_rand_const_reg check_fault_1;
(* keep *) reg bus_0_prev, bus_0_current, bus_1_current, bus_seq_seen;
(* keep *) reg [`RISCV_FORMAL_NBUS-1:0] bus_is_io;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_wmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
(* keep *) reg fault;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] prev_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] prev_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] prev_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] prev_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] prev_wmask;
(* keep *) reg prev_fault;
(* keep *) reg core_has_prev;
(* keep *) reg core_0_match;
(* keep *) reg core_1_match;
reg [ `RISCV_FORMAL_XLEN - 1:0] bus_byte_addr;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
bus_0_current = 0;
bus_0_prev = 0;
bus_1_current = 0;
bus_seq_seen = 0;
core_has_prev = 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
bus_wmask = rvfi_bus_wmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_wdata = rvfi_bus_wdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
bus_is_io[channel_idx] = 0;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
bus_byte_addr = bus_addr + i;
if (`rvformal_addr_io(bus_byte_addr) && (bus_rmask[i] || bus_wmask[i])) begin
bus_is_io[channel_idx] = 1;
end
end
if (bus_is_io[channel_idx]) begin
bus_1_current = 0;
bus_0_prev = bus_0_current;
bus_0_current = 0;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
if ((bus_addr + i == check_addr_0) && (check_fault_0 == rvfi_bus_fault[channel_idx]) && (check_write_0 ? bus_wmask[i] : bus_rmask[i])) begin
bus_0_current = 1;
end
if ((bus_addr + i == check_addr_1) && (check_fault_1 == rvfi_bus_fault[channel_idx]) && (check_write_1 ? bus_wmask[i] : bus_rmask[i])) begin
bus_1_current = 1;
end
end
if (bus_1_current && bus_0_prev) begin
bus_seq_seen = 1;
cover (1);
end
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`ifdef RISCV_FORMAL_MEM_FAULT
fault = rvfi_mem_fault[channel_idx];
if (fault) begin
mem_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
end
`else
fault = 0;
`endif
core_0_match = 0;
core_1_match = 0;
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i=i+1) begin
if ((prev_addr + i == check_addr_0) && (check_fault_0 == prev_fault) && (check_write_0 ? prev_wmask[i] : prev_rmask[i])) begin
core_0_match = core_has_prev;
end
if ((mem_addr + i == check_addr_1) && (check_fault_1 == fault) && (check_write_1 ? mem_wmask[i] : mem_rmask[i])) begin
core_1_match = 1;
end
end
if (
check && rvfi_valid[channel_idx] &&
channel_idx == `RISCV_FORMAL_CHANNEL_IDX &&
`rvformal_addr_io(mem_addr) &&
core_0_match && core_1_match
) begin
cover (1);
assert (bus_seq_seen);
end
if (rvfi_valid[channel_idx] && `rvformal_addr_io(mem_addr) && (mem_rmask || mem_wmask)) begin
// This check would need to be extended to handle potential instructions that
// simultaneously read and write. This assertion makes sure this check doesn't
// silently miss any issues should such instructions be added.
assert (!(mem_rmask && mem_wmask));
core_has_prev = 1;
prev_addr = mem_addr;
prev_rdata = mem_rdata;
prev_rmask = mem_rmask;
prev_wdata = mem_wdata;
prev_wmask = mem_wmask;
prev_fault = fault;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_io_read_check.sv
================================================
// external bus: check i/o reads
//
// This checks that a retired non-faulting load is contained in a single read
// transaction on the external bus. It doesn't check any relationships bitween
// multiple instructions or bus transactions. See the inline comment for
// details on loads that are not as wide as the bus.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_io_read_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_rdata;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_rmask;
reg bus_read_seen, bus_read_matches;
reg core_read_matches;
reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_match_mask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
bus_read_seen <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
// This allows the read to appear anywhere in the bus data as long as it fits
// into a single transaction. It also allows reading adjacent bytes in the same
// transaction. Different busses handle narrow reads differently, so as a
// generic check we don't prescribe any particular behavior.
check_match_mask = 0;
bus_read_matches = 1;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == check_addr + j && check_rmask[i]) begin
if (bus_rmask[i] && bus_rdata[i*8 +: 8] == check_rdata[j*8 +: 8]) begin
check_match_mask[j] = 1;
end else begin
bus_read_matches = 0;
end
end
end
end
if (bus_read_matches && check_match_mask == check_rmask && !rvfi_bus_fault[channel_idx]) begin
bus_read_seen = 1;
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
core_read_matches = check_rmask && mem_addr == check_addr && mem_rmask == check_rmask
`ifdef RISCV_FORMAL_MEM_FAULT
&& !rvfi_mem_fault[channel_idx]
`endif
;
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i=i+1) begin
if (mem_rmask[i] && mem_rdata[i*8 +: 8] != check_rdata[i*8 +: 8]) begin
core_read_matches = 0;
end
end
if (check && rvfi_valid[channel_idx] && core_read_matches && `rvformal_addr_io(check_addr)) begin
cover (1);
assert (bus_read_seen);
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_io_read_fault_check.sv
================================================
// external bus: check i/o read faults
//
// This checks that a retired faulting load is contained in a single read
// transaction on the external bus. It doesn't check any relationships bitween
// multiple instructions or bus transactions. See the inline comment for
// details on loads that are not as wide as the bus.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_io_read_fault_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_rmask;
reg bus_read_seen, bus_read_matches;
reg core_read_matches;
reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_match_mask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_rdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
bus_read_seen <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
// This allows the read to appear anywhere in the bus data as long as it fits
// into a single transaction. It also allows reading adjacent bytes in the same
// transaction. Different busses handle narrow reads differently, so as a
// generic check we don't prescribe any particular behavior.
check_match_mask = 0;
bus_read_matches = 1;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == check_addr + j && check_rmask[i]) begin
if (bus_rmask[i]) begin
check_match_mask[j] = 1;
end else begin
bus_read_matches = 0;
end
end
end
end
if (bus_read_matches && check_match_mask == check_rmask && rvfi_bus_fault[channel_idx]) begin
bus_read_seen = 1;
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
core_read_matches = check_rmask && mem_addr == check_addr && mem_rmask == check_rmask && rvfi_mem_fault[channel_idx];
if (check && rvfi_valid[channel_idx] && core_read_matches && `rvformal_addr_io(check_addr)) begin
cover (1);
assert (bus_read_seen);
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_io_write_check.sv
================================================
// external bus: check i/o writes
//
// This checks that a retired non-faulting store is contained in a single read
// transaction on the external bus. It doesn't check any relationships bitween
// multiple instructions or bus transactions. See the inline comment for
// details on stores that are not as wide as the bus.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_io_write_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_wdata;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_wmask;
reg bus_write_seen, bus_write_matches;
reg core_write_matches;
reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_match_mask;
reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_match_mask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_wmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
bus_write_seen <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_wmask = rvfi_bus_wmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_wdata = rvfi_bus_wdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
// This allows the write to appear anywhere in the bus data as long as it fits
// into a single transaction. Unlike for reads, we don't allow writing
// additional adjacent bytes.
check_match_mask = 0;
bus_match_mask = 0;
bus_write_matches = 1;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == check_addr + j && check_wmask[i]) begin
if (bus_wmask[i] && bus_wdata[i*8 +: 8] == check_wdata[j*8 +: 8]) begin
check_match_mask[j] = 1;
bus_match_mask[i] = 1;
end else begin
bus_write_matches = 0;
end
end
end
end
if (bus_write_matches && bus_match_mask == bus_wmask && check_match_mask == check_wmask && !rvfi_bus_fault[channel_idx]) begin
bus_write_seen = 1;
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
core_write_matches = check_wmask && mem_addr == check_addr && mem_wmask == check_wmask
`ifdef RISCV_FORMAL_MEM_FAULT
&& !rvfi_mem_fault[channel_idx]
`endif
;
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i=i+1) begin
if (mem_wmask[i] && mem_wdata[i*8 +: 8] != check_wdata[i*8 +: 8]) begin
core_write_matches = 0;
end
end
if (check && rvfi_valid[channel_idx] && core_write_matches && `rvformal_addr_io(check_addr)) begin
cover (1);
assert (bus_write_seen);
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_dmem_io_write_fault_check.sv
================================================
// external bus: check i/o write faults
//
// This checks that a retired faulting store is contained in a single read
// transaction on the external bus. It doesn't check any relationships bitween
// multiple instructions or bus transactions. See the inline comment for
// details on stores that are not as wide as the bus.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_dmem_io_write_fault_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_addr;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN - 1:0] check_wdata;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_wmask;
reg bus_write_seen, bus_write_matches;
reg core_write_matches;
reg [`RISCV_FORMAL_XLEN/8 - 1:0] check_match_mask;
reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_match_mask;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
(* keep *) reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_wmask;
(* keep *) reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_wdata;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
bus_write_seen <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_data[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_wmask = rvfi_bus_wmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_wdata = rvfi_bus_wdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
// This allows the write to appear anywhere in the bus data as long as it fits
// into a single transaction. Unlike for reads, we don't allow writing
// additional adjacent bytes.
check_match_mask = 0;
bus_match_mask = 0;
bus_write_matches = 1;
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1) begin
for (j = 0; j < `RISCV_FORMAL_XLEN/8; j=j+1) begin
if (bus_addr + i == check_addr + j && check_wmask[i]) begin
if (bus_wmask[i] && bus_wdata[i*8 +: 8] == check_wdata[j*8 +: 8]) begin
check_match_mask[j] = 1;
bus_match_mask[i] = 1;
end else begin
bus_write_matches = 0;
end
end
end
end
if (bus_write_matches && bus_match_mask == bus_wmask && check_match_mask == check_wmask && rvfi_bus_fault[channel_idx]) begin
bus_write_seen = 1;
end
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
core_write_matches = check_wmask && mem_addr == check_addr && mem_wmask == check_wmask && rvfi_mem_fault[channel_idx];
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i=i+1) begin
if (mem_wmask[i] && mem_wdata[i*8 +: 8] != check_wdata[i*8 +: 8]) begin
core_write_matches = 0;
end
end
if (check && rvfi_valid[channel_idx] && core_write_matches && `rvformal_addr_io(check_addr)) begin
cover (1);
assert (bus_write_seen);
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_imem_check.sv
================================================
// external bus: check instruction memory reads
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
`ifndef RISCV_FORMAL_FAULT_WIDTH
`define RISCV_FORMAL_FAULT_WIDTH 1
`endif
module rvfi_bus_imem_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] imem_addr;
`rvformal_rand_const_reg [15:0] imem_data;
reg [`RISCV_FORMAL_XLEN-1:0] pc;
reg [`RISCV_FORMAL_ILEN-1:0] insn;
reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_insn[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1)
for (j = 0; j < 2; j=j+1) begin
if (bus_rmask[i] && bus_addr + i == imem_addr + j) begin
assume (imem_data[j*8 +: 8] == bus_rdata[i*8 +: 8]);
end
if (bus_rmask[i] && ((bus_addr + i) | (`RISCV_FORMAL_FAULT_WIDTH - 1)) == ((imem_addr + j) | (`RISCV_FORMAL_FAULT_WIDTH - 1))) begin
assume (!rvfi_bus_fault[channel_idx]);
end
end
end
end
if (check) begin
if (rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]) begin
pc = rvfi_pc_rdata[`RISCV_FORMAL_CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
insn = rvfi_insn[`RISCV_FORMAL_CHANNEL_IDX*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
if (`rvformal_addr_valid(pc) && pc == imem_addr) begin
cover (1);
assert (insn[15:0] == imem_data);
end;
if (insn[1:0] == 2'b11 && `rvformal_addr_valid(pc+2) && pc+2 == imem_addr) begin
cover (1);
assert (insn[31:16] == imem_data);
end;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_bus_imem_fault_check.sv
================================================
// external bus: check faulting instruction memory reads
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_bus_imem_fault_check (
input clock, reset, check,
`RVFI_INPUTS
`RVFI_BUS_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] imem_addr;
reg [`RISCV_FORMAL_XLEN-1:0] pc;
reg [`RISCV_FORMAL_ILEN-1:0] insn;
reg [ `RISCV_FORMAL_XLEN - 1:0] bus_addr;
reg [`RISCV_FORMAL_BUSLEN/8 - 1:0] bus_rmask;
reg [`RISCV_FORMAL_BUSLEN - 1:0] bus_rdata;
integer channel_idx, i, j;
always @(posedge clock) begin
if (reset) begin
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NBUS; channel_idx=channel_idx+1) begin
if (rvfi_bus_valid[channel_idx] && rvfi_bus_insn[channel_idx]) begin
bus_addr = rvfi_bus_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
bus_rmask = rvfi_bus_rmask[channel_idx*`RISCV_FORMAL_BUSLEN/8 +: `RISCV_FORMAL_BUSLEN/8];
bus_rdata = rvfi_bus_rdata[channel_idx*`RISCV_FORMAL_BUSLEN +: `RISCV_FORMAL_BUSLEN];
for (i = 0; i < `RISCV_FORMAL_BUSLEN/8; i=i+1)
for (j = 0; j < 2; j=j+1) begin
if (bus_rmask[i] && bus_addr + i == imem_addr + j) begin
assume (rvfi_bus_fault[channel_idx]);
end
end
cover (rvfi_bus_fault[channel_idx]);
end
end
if (check) begin
if (rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]) begin
pc = rvfi_pc_rdata[`RISCV_FORMAL_CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
insn = rvfi_insn[`RISCV_FORMAL_CHANNEL_IDX*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
if (`rvformal_addr_valid(pc) && pc == imem_addr) begin
cover (1);
assert (rvfi_trap[`RISCV_FORMAL_CHANNEL_IDX]);
assert (insn == 0);
`ifdef RISCV_FORMAL_MEM_FAULT
assert (rvfi_mem_fault[`RISCV_FORMAL_CHANNEL_IDX]);
`endif
end;
if (`rvformal_addr_valid(pc+2) && pc+2 == imem_addr) begin
cover (1);
assert (rvfi_trap[`RISCV_FORMAL_CHANNEL_IDX]);
assert (insn == 0);
`ifdef RISCV_FORMAL_MEM_FAULT
assert (rvfi_mem_fault[`RISCV_FORMAL_CHANNEL_IDX]);
`endif
end;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_causal_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_causal_check (
input clock, reset, check,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [63:0] insn_order;
`rvformal_rand_const_reg [4:0] register_index;
reg found_non_causal = 0;
integer channel_idx;
always @(posedge clock) begin
if (reset) begin
found_non_causal = 0;
end else begin
if (check) begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_CHANNEL_IDX; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx] && rvfi_order[64*channel_idx +: 64] > insn_order &&
(register_index == rvfi_rs1_addr[channel_idx*5 +: 5] ||
register_index == rvfi_rs2_addr[channel_idx*5 +: 5])) begin
found_non_causal = 1;
end
end
assume(register_index != 0);
assume(rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]);
assume((register_index == rvfi_rd_addr[`RISCV_FORMAL_CHANNEL_IDX*5 +: 5]));
assume(insn_order == rvfi_order[64*`RISCV_FORMAL_CHANNEL_IDX +: 64]);
assert(!found_non_causal);
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx] && rvfi_order[64*channel_idx +: 64] > insn_order &&
(register_index == rvfi_rs1_addr[channel_idx*5 +: 5] ||
register_index == rvfi_rs2_addr[channel_idx*5 +: 5])) begin
found_non_causal = 1;
end
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_causal_io_check.sv
================================================
// check that no i/o memory accesses are retired in a non-causal order
//
// This checks that no i/o memory accesses are retired out of order. It uses
// the RISCV_FORMAL_IOADDR(addr) macro to determine whether a memory location
// is considered to be an i/o address.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_causal_io_check (
input clock, reset, check,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [63:0] insn_order;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
reg found_non_causal = 0;
reg performs_io = 0;
reg [ `RISCV_FORMAL_XLEN - 1:0] byte_addr;
integer channel_idx;
integer i;
always @(posedge clock) begin
if (reset) begin
found_non_causal = 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`ifdef RISCV_FORMAL_MEM_FAULT
if (rvfi_mem_fault[channel_idx]) begin
mem_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
end
`endif
performs_io = 0;
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
byte_addr = mem_addr + i;
if (`rvformal_addr_io(byte_addr)) begin
performs_io |= mem_rmask[i] | mem_wmask[i];
end
end
if (check && channel_idx == `RISCV_FORMAL_CHANNEL_IDX) begin
assume (rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]);
assume (performs_io);
assume (insn_order == rvfi_order[64*`RISCV_FORMAL_CHANNEL_IDX +: 64]);
cover (1);
assert (!found_non_causal);
end
if (rvfi_valid[channel_idx] && rvfi_order[64*channel_idx +: 64] > insn_order && performs_io) begin
found_non_causal = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_causal_mem_check.sv
================================================
// check that no memory accesses are retired in a non-causal order
//
// This checks that no read of a memory location is retired before the write of
// the to-be-read value.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_causal_mem_check (
input clock, reset, check,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [63:0] insn_order;
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] check_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN - 1:0] mem_addr;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_rmask;
(* keep *) reg [ `RISCV_FORMAL_XLEN/8 - 1:0] mem_wmask;
reg found_non_causal = 0;
reg reads_check_addr;
reg writes_check_addr;
integer channel_idx;
integer i;
always @(posedge clock) begin
if (reset) begin
found_non_causal = 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
mem_addr = rvfi_mem_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`ifdef RISCV_FORMAL_MEM_FAULT
if (rvfi_mem_fault[channel_idx]) begin
mem_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
mem_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
end
`endif
reads_check_addr = 0;
writes_check_addr = 0;
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
if (mem_addr + i == check_addr) begin
reads_check_addr |= mem_rmask[i];
writes_check_addr |= mem_wmask[i];
end
end
if (check && channel_idx == `RISCV_FORMAL_CHANNEL_IDX) begin
assume (rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]);
assume (writes_check_addr);
assume (insn_order == rvfi_order[64*`RISCV_FORMAL_CHANNEL_IDX +: 64]);
cover (1);
assert (!found_non_causal);
end
if (rvfi_valid[channel_idx] && rvfi_order[64*channel_idx +: 64] > insn_order && reads_check_addr) begin
found_non_causal = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_channel.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_channel (
`RVFI_INPUTS
);
parameter CHANNEL_IDX = 0;
(* keep *) wire valid = rvfi_valid [CHANNEL_IDX];
(* keep *) wire [ 63 : 0] order = rvfi_order [CHANNEL_IDX*64 +: 64];
(* keep *) wire [`RISCV_FORMAL_ILEN - 1 : 0] insn = rvfi_insn [CHANNEL_IDX*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
(* keep *) wire trap = rvfi_trap [CHANNEL_IDX];
(* keep *) wire halt = rvfi_halt [CHANNEL_IDX];
(* keep *) wire intr = rvfi_intr [CHANNEL_IDX];
(* keep *) wire [ 1 : 0] mode = rvfi_mode [CHANNEL_IDX*2 +: 2];
(* keep *) wire [ 1 : 0] ixl = rvfi_ixl [CHANNEL_IDX*2 +: 2];
(* keep *) wire [ 4 : 0] rs1_addr = rvfi_rs1_addr [CHANNEL_IDX*5 +: 5];
(* keep *) wire [ 4 : 0] rs2_addr = rvfi_rs2_addr [CHANNEL_IDX*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs1_rdata = rvfi_rs1_rdata[CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs2_rdata = rvfi_rs2_rdata[CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [ 4 : 0] rd_addr = rvfi_rd_addr [CHANNEL_IDX*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rd_wdata = rvfi_rd_wdata [CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_rdata = rvfi_pc_rdata [CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_wdata = rvfi_pc_wdata [CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_addr = rvfi_mem_addr [CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_rmask = rvfi_mem_rmask[CHANNEL_IDX*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_wmask = rvfi_mem_wmask[CHANNEL_IDX*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_rdata = rvfi_mem_rdata[CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_wdata = rvfi_mem_wdata[CHANNEL_IDX*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
endmodule
================================================
FILE: checks/rvfi_cover_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_cover_check (
input clock, reset, check,
`RVFI_INPUTS
);
`ifdef RISCV_FORMAL_ROLLBACK
(* keep *) integer cnt_rollback;
integer cnt_rollback_q;
always @(posedge clock) begin
cnt_rollback_q <= cnt_rollback;
end
always @* begin
if (reset)
cnt_rollback = 0;
else
cnt_rollback = cnt_rollback_q + rvfi_rollback_valid;
end
`endif
genvar channel_idx;
generate for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin:channel
`RVFI_GETCHANNEL(channel_idx)
(* keep *) integer cnt_insns;
(* keep *) integer cnt_trap_insns;
(* keep *) integer cnt_intr_insns;
(* keep *) integer cnt_norm_insns;
`ifdef RISCV_FORMAL_ROLLBACK
// "arb" = after rollback
(* keep *) integer arb_cnt_insns;
(* keep *) integer arb_cnt_trap_insns;
(* keep *) integer arb_cnt_intr_insns;
(* keep *) integer arb_cnt_norm_insns;
`endif
integer cnt_insns_q;
integer cnt_trap_insns_q;
integer cnt_intr_insns_q;
integer cnt_norm_insns_q;
`ifdef RISCV_FORMAL_ROLLBACK
integer arb_cnt_insns_q;
integer arb_cnt_trap_insns_q;
integer arb_cnt_intr_insns_q;
integer arb_cnt_norm_insns_q;
`endif
always @(posedge clock) begin
cnt_insns_q <= cnt_insns;
cnt_trap_insns_q <= cnt_trap_insns;
cnt_intr_insns_q <= cnt_intr_insns;
cnt_norm_insns_q <= cnt_norm_insns;
`ifdef RISCV_FORMAL_ROLLBACK
arb_cnt_insns_q <= arb_cnt_insns;
arb_cnt_trap_insns_q <= arb_cnt_trap_insns;
arb_cnt_intr_insns_q <= arb_cnt_intr_insns;
arb_cnt_norm_insns_q <= arb_cnt_norm_insns;
`endif
end
always @* begin
if (reset) begin
cnt_insns = 0;
cnt_trap_insns = 0;
cnt_intr_insns = 0;
cnt_norm_insns = 0;
`ifdef RISCV_FORMAL_ROLLBACK
arb_cnt_insns = 0;
arb_cnt_trap_insns = 0;
arb_cnt_intr_insns = 0;
arb_cnt_norm_insns = 0;
`endif
end else begin
cnt_insns = cnt_insns_q + valid;
cnt_trap_insns = cnt_trap_insns_q + (valid && trap);
cnt_intr_insns = cnt_intr_insns_q + (valid && intr);
cnt_norm_insns = cnt_norm_insns_q + (valid && !{trap,intr});
`ifdef RISCV_FORMAL_ROLLBACK
arb_cnt_insns = arb_cnt_insns_q + (valid && cnt_rollback);
arb_cnt_trap_insns = arb_cnt_trap_insns_q + (valid && cnt_rollback && trap);
arb_cnt_intr_insns = arb_cnt_intr_insns_q + (valid && cnt_rollback && intr);
arb_cnt_norm_insns = arb_cnt_norm_insns_q + (valid && cnt_rollback && !{trap,intr});
`endif
end
end
end endgenerate
`include "cover_stmts.vh"
endmodule
================================================
FILE: checks/rvfi_csr_ill_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csr_ill_check (
input clock, reset, check,
`RVFI_INPUTS
);
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
always @* begin
if (!reset && check) begin
assume (csr_insn_valid);
assume (csr_insn_addr == `RISCV_FORMAL_ILL_CSR_ADDR);
if ( (0
`ifdef RISCV_FORMAL_ILL_MMODE
|| rvfi.mode == 3
`endif
`ifdef RISCV_FORMAL_ILL_SMODE
|| rvfi.mode == 1
`endif
`ifdef RISCV_FORMAL_ILL_UMODE
|| rvfi.mode == 0
`endif
) && (0
`ifdef RISCV_FORMAL_ILL_WRITE
|| csr_write
`endif
`ifdef RISCV_FORMAL_ILL_READ
|| csr_read
`endif
) ) begin
assert (rvfi.trap);
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_any_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_any_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_insn_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRC_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRC_NAME)
`endif
);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
`ifdef RISCV_FORMAL_CSRC_MASK
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata) & `RISCV_FORMAL_CSRC_MASK;
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata) & `RISCV_FORMAL_CSRC_MASK;
`else
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
`endif //RISCV_FORMAL_CSRC_MASK
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
wire [31:0] csr_rsval = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
// Setup for reg testing
`rvformal_rand_const_reg [63:0] insn_order;
reg [`RISCV_FORMAL_XLEN-1:0] rsval_shadow = 0;
reg [`RISCV_FORMAL_XLEN-1:0] wdata_shadow = 0;
reg csr_written = 0;
reg [1:0] csr_mode_shadow = 0;
always @(posedge clock) begin
if (reset) begin
rsval_shadow = 0;
wdata_shadow = 0;
csr_written = 0;
csr_mode_shadow = 0;
end else begin
if (check) begin
`ifdef RISCV_FORMAL_CSRC_MASK
assume ((rsval_shadow & `RISCV_FORMAL_CSRC_MASK) == rsval_shadow);
`endif
if (csr_written && csr_read_valid && csr_insn_under_test) begin
case (csr_mode_shadow)
2'b 00 /* None */,
2'b 01 /* RW */: begin
assert(rsval_shadow == csr_insn_rdata || csr_insn_rdata == wdata_shadow);
assert(rsval_shadow == wdata_shadow);
end
// Currently not testing set/clear from rsval
2'b 10 /* RS */,
2'b 11 /* RC */: begin assert(csr_insn_rdata == wdata_shadow); end
endcase
end
end else begin
if (csr_write_valid && csr_insn_under_test) begin
rsval_shadow = csr_rsval;
wdata_shadow = csr_insn_wdata;
csr_written = 1;
csr_mode_shadow = csr_mode;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_const_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_const_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_insn_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRC_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRC_NAME)
`endif
);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
`ifdef RISCV_FORMAL_CSRC_MASK
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata) & `RISCV_FORMAL_CSRC_MASK;
`else
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
`endif //RISCV_FORMAL_CSRC_MASK
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
// Setup for reg testing
reg [`RISCV_FORMAL_XLEN-1:0] wdata_shadow = 0;
reg [`RISCV_FORMAL_XLEN-1:0] rdata_shadow = 0;
reg csr_written = 0;
always @(posedge clock) begin
if (reset) begin
wdata_shadow = 0;
csr_written = 0;
end else begin
if (check) begin
if (csr_written && csr_read_valid && csr_insn_under_test) begin
assert(csr_insn_rdata == `RISCV_FORMAL_CSRC_CONSTVAL);
end
end else begin
if (csr_write_valid && csr_insn_under_test) begin
rdata_shadow = csr_insn_rdata;
wdata_shadow = csr_insn_wdata;
csr_written = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_hpm_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_hpm_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_hpmcounter_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_HPMCOUNTER)
|| csr_insn_addr == `csr_mindexh(`RISCV_FORMAL_CSRC_HPMCOUNTER));
wire csr_hpmevent_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME));
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
wire [`RISCV_FORMAL_XLEN-1:0] hpmcounter_rdata = `csrget(`RISCV_FORMAL_CSRC_HPMCOUNTER, rdata);
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
wire [31:0] csr_rsval = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
// Setup for reg testing
`rvformal_rand_const_reg [63:0] insn_order;
reg [31:0] csr_hpmcounter_shadow = 0;
reg csr_hpmevent_written;
always @(posedge clock) begin
if (reset) begin
csr_hpmcounter_shadow = 0;
csr_hpmevent_written = 0;
end else begin
// No writes of CSR under test allowed
assume (!(csr_write_valid && csr_hpmcounter_under_test));
if (csr_hpmevent_written) begin
// event CSR should hold the desired event
assume (csr_insn_rdata == `RISCV_FORMAL_CSRC_HPMEVENT);
// counter CSR should eventually increase
cover (hpmcounter_rdata > csr_hpmcounter_shadow);
end
if (csr_write_valid && csr_hpmevent_under_test) begin
csr_hpmcounter_shadow = hpmcounter_rdata;
csr_hpmevent_written = 1;
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_inc_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_inc_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_insn_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRC_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRC_NAME)
`endif
);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
wire [31:0] csr_rsval = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
// Setup for reg testing
`rvformal_rand_const_reg [63:0] insn_order;
reg [`RISCV_FORMAL_XLEN-1:0] wdata_shadow = 0;
reg [`RISCV_FORMAL_XLEN-1:0] rdata_shadow = 0;
reg csr_written = 0;
reg csr_read_shadowed = 0;
always @(posedge clock) begin
if (reset) begin
wdata_shadow = 0;
rdata_shadow = 0;
csr_written = 0;
csr_read_shadowed = 0;
end else begin
// no writes without read that could decrease the value manually
if (csr_write_valid) assume(csr_read_valid);
if (check) begin
assume(csr_read_shadowed);
if (csr_read_shadowed && csr_read_valid && csr_insn_under_test) begin
assert(csr_insn_rdata >= rdata_shadow || (csr_written && csr_insn_rdata >= wdata_shadow));
end
end else begin
csr_written = 0;
if (csr_read_valid && csr_insn_under_test) begin
if (csr_write_valid) begin
assume(csr_insn_wdata[`RISCV_FORMAL_XLEN-1] == 0);
wdata_shadow = csr_insn_wdata;
csr_written = 1;
end
rdata_shadow = csr_insn_rdata;
csr_read_shadowed = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_upcnt_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_upcnt_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_insn_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRC_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRC_NAME)
`endif
);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
wire [31:0] csr_rsval = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
// Setup for reg testing
`rvformal_rand_const_reg [63:0] insn_order;
reg [`RISCV_FORMAL_XLEN-1:0] rdata_shadow = 0;
reg csr_event_written = 0;
reg csr_read_shadowed = 0;
always @(posedge clock) begin
if (reset) begin
rdata_shadow = 0;
csr_event_written = 0;
csr_read_shadowed = 0;
end else begin
// No writes of CSR under test allowed
assume (!(csr_write_valid && csr_insn_under_test));
if (check) begin
assume(csr_read_shadowed);
if (csr_read_valid && csr_insn_under_test) begin
assert(csr_insn_rdata > rdata_shadow);
end
end else begin
if (csr_read_valid && csr_insn_under_test) begin
assume(csr_insn_rdata[31:0] < 'h F000_0000); // no overflow
rdata_shadow = csr_insn_rdata;
csr_read_shadowed = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrc_zero_check.sv
================================================
// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrc_zero_check (
input clock, reset, check,
`RVFI_INPUTS
);
// Setup for csrs
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire csr_insn_under_test = (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRC_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRC_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRC_NAME)
`endif
);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRC_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRC_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRC_NAME, wdata);
`ifdef RISCV_FORMAL_CSRC_MASK
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata) & `RISCV_FORMAL_CSRC_MASK;
`else
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRC_NAME, rdata);
`endif //RISCV_FORMAL_CSRC_MASK
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
wire csr_write_valid = csr_write && csr_insn_valid;
wire csr_read_valid = csr_read && csr_insn_valid;
wire [1:0] csr_mode = rvfi.insn[13:12];
wire [31:0] csr_rsval = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
// Setup for reg testing
`rvformal_rand_const_reg [63:0] insn_order;
reg [`RISCV_FORMAL_XLEN-1:0] wdata_shadow = 0;
reg csr_written = 0;
always @(posedge clock) begin
if (reset) begin
wdata_shadow = 0;
csr_written = 0;
end else begin
if (check) begin
if (csr_written && csr_read_valid && csr_insn_under_test) begin
assert(csr_insn_rdata == 0);
assume(wdata_shadow != 0);
end
end else begin
if (csr_write_valid && csr_insn_under_test) begin
// simplify things by only testing reg write, and not set/clear
assume(csr_mode == 0 || csr_mode == 1);
wdata_shadow = csr_insn_wdata;
csr_written = 1;
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_csrw_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_csrw_check (
input clock, reset, check,
`RVFI_INPUTS
);
`RVFI_CHANNEL(rvfi, `RISCV_FORMAL_CHANNEL_IDX)
localparam [11:0] csr_none = 12'hFFF;
`RVFI_INDICES
`define quoted(txt) txt
`define csrget(_name, _type) rvfi.csr_``_name```quoted(_``_type)
`define csr_mindex(_name) csr_mindex_``_name
`define csr_sindex(_name) csr_sindex_``_name
`define csr_uindex(_name) csr_uindex_``_name
`define csr_mindexh(_name) csr_mindex_``_name```quoted(h)
`define csr_sindexh(_name) csr_sindex_``_name```quoted(h)
`define csr_uindexh(_name) csr_uindex_``_name```quoted(h)
wire csr_insn_valid = rvfi.valid && (rvfi.insn[6:0] == 7'b 1110011) && (rvfi.insn[13:12] != 0) && ((rvfi.insn >> 16 >> 16) == 0);
wire [11:0] csr_insn_addr = rvfi.insn[31:20];
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_arg = rvfi.insn[14] ? rvfi.insn[19:15] : rvfi.rs1_rdata;
`ifdef RISCV_FORMAL_CSRWH
wire csr_hi = rvfi.ixl == 1 && (csr_insn_addr == `csr_mindexh(`RISCV_FORMAL_CSRW_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindexh(`RISCV_FORMAL_CSRW_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindexh(`RISCV_FORMAL_CSRW_NAME)
`endif
);
wire [63:0] csr_insn_rmask_full = `csrget(`RISCV_FORMAL_CSRW_NAME, rmask);
wire [63:0] csr_insn_wmask_full = `csrget(`RISCV_FORMAL_CSRW_NAME, wmask);
wire [63:0] csr_insn_rdata_full = `csrget(`RISCV_FORMAL_CSRW_NAME, rdata);
wire [63:0] csr_insn_wdata_full = `csrget(`RISCV_FORMAL_CSRW_NAME, wdata);
wire [63:0] csr_insn_changed_full = csr_insn_wmask_full & (~csr_insn_rmask_full | (csr_insn_rmask_full & (csr_insn_rdata_full ^ csr_insn_wdata_full)));
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = (csr_hi ? csr_insn_rmask_full >> 32 : csr_insn_rmask_full) & (rvfi.ixl == 1 ? 'h FFFF_FFFF : -1);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = (csr_hi ? csr_insn_wmask_full >> 32 : csr_insn_wmask_full) & (rvfi.ixl == 1 ? 'h FFFF_FFFF : -1);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = (csr_hi ? csr_insn_rdata_full >> 32 : csr_insn_rdata_full) & (rvfi.ixl == 1 ? 'h FFFF_FFFF : -1);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = (csr_hi ? csr_insn_wdata_full >> 32 : csr_insn_wdata_full) & (rvfi.ixl == 1 ? 'h FFFF_FFFF : -1);
`else
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rmask = `csrget(`RISCV_FORMAL_CSRW_NAME, rmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wmask = `csrget(`RISCV_FORMAL_CSRW_NAME, wmask);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_rdata = `csrget(`RISCV_FORMAL_CSRW_NAME, rdata);
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_wdata = `csrget(`RISCV_FORMAL_CSRW_NAME, wdata);
`endif
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_smask =
/* CSRRW, CSRRWI */ (rvfi.insn[13:12] == 1) ? csr_insn_arg :
/* CSRRS, CSRRSI */ (rvfi.insn[13:12] == 2) ? csr_insn_arg : 0;
wire [`RISCV_FORMAL_XLEN-1:0] csr_insn_cmask =
/* CSRRW, CSRRWI */ (rvfi.insn[13:12] == 1) ? ~csr_insn_arg :
/* CSRCS, CSRRCI */ (rvfi.insn[13:12] == 3) ? csr_insn_arg : 0;
wire csr_write = !rvfi.insn[13] || rvfi.insn[19:15];
wire csr_read = rvfi.insn[11:7] != 0;
reg csr_illacc;
always @* begin
csr_illacc = 0;
case (csr_insn_addr[11:8])
/* User CSRs */
4'b 00_00, 4'b 01_00, 4'b 10_00: begin // read/write
end
4'b 11_00: begin // read-only
if (csr_write) csr_illacc = 1;
end
/* Supervisor CSRs */
4'b 00_01, 4'b 01_01, 4'b 10_01: begin // read/write
if (rvfi.mode < 1) csr_illacc = 1;
end
4'b 11_01: begin // read-only
if (rvfi.mode < 1) csr_illacc = 1;
if (csr_write) csr_illacc = 1;
end
/* Reserved CSRs */
4'b 00_10, 4'b 01_10, 4'b 10_10, 4'b 11_10: begin
end
/* Machine CSRs */
4'b 00_11, 4'b 01_11, 4'b 10_11: begin // read/write
if (rvfi.mode < 3) csr_illacc = 1;
end
4'b 11_11: begin // read-only
if (rvfi.mode < 3) csr_illacc = 1;
if (csr_write) csr_illacc = 1;
end
endcase
end
wire [`RISCV_FORMAL_XLEN-1:0] effective_csr_insn_wmask = csr_insn_rmask | csr_insn_wmask;
wire [`RISCV_FORMAL_XLEN-1:0] effective_csr_insn_wdata = (csr_insn_wdata & csr_insn_wmask) | (csr_insn_rdata & ~csr_insn_wmask);
wire [`RISCV_FORMAL_XLEN-1:0] spec_pc_wdata = rvfi.pc_rdata + 4;
wire insn_pma_x;
`ifdef RISCV_FORMAL_PMA_MAP
`RISCV_FORMAL_PMA_MAP insn_pma (
.address(rvfi.pc_rdata),
.log2len(rvfi.insn[1:0] == 2'b11 ? 2'd2 : 2'd1),
.X(insn_pma_x)
);
`else
assign insn_pma_x = 1;
`endif
integer i;
always @* begin
if (!reset && check) begin
assume (csr_insn_valid);
assume (csr_insn_addr != csr_none);
assume (csr_insn_addr == `csr_mindex(`RISCV_FORMAL_CSRW_NAME)
`ifdef RISCV_FORMAL_SMODE
|| csr_insn_addr == `csr_sindex(`RISCV_FORMAL_CSRW_NAME)
`endif
`ifdef RISCV_FORMAL_UMODE
|| csr_insn_addr == `csr_uindex(`RISCV_FORMAL_CSRW_NAME)
`endif
`ifdef RISCV_FORMAL_CSRWH
|| csr_hi
`endif
);
if (!`rvformal_addr_valid(rvfi.pc_rdata) || !insn_pma_x || csr_illacc) begin
assert (rvfi.trap);
assert (rvfi.rd_addr == 0);
assert (rvfi.rd_wdata == 0);
end else begin
assert (!rvfi.trap);
assert (rvfi.rd_addr == rvfi.insn[11:7]);
assert (`rvformal_addr_eq(rvfi.pc_wdata, spec_pc_wdata));
if (rvfi.rd_addr == 0) begin
assert (rvfi.rd_wdata == 0);
end else begin
assert (csr_insn_rmask == {`RISCV_FORMAL_XLEN{1'b1}});
assert (csr_insn_rdata == rvfi.rd_wdata);
end
assert (((csr_insn_smask | csr_insn_cmask) & ~effective_csr_insn_wmask) == 0);
assert ((csr_insn_smask & ~effective_csr_insn_wdata) == 0);
assert ((csr_insn_cmask & effective_csr_insn_wdata) == 0);
`ifdef RISCV_FORMAL_CSRWH
if (csr_hi) begin
assert (csr_insn_changed_full[31:0] == 0);
end else if (rvfi.ixl == 1) begin
assert (csr_insn_changed_full[63:32] == 0);
end
`endif
end
assert (rvfi.mem_wmask == 0);
end
end
endmodule
================================================
FILE: checks/rvfi_dmem_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_dmem_check (
input clock, reset, enable,
output [`RISCV_FORMAL_XLEN-1:0] dmem_addr,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] dmem_addr_randval;
assign dmem_addr = dmem_addr_randval;
reg [`RISCV_FORMAL_XLEN-1:0] dmem_shadow;
reg [`RISCV_FORMAL_XLEN/8-1:0] dmem_written = 0;
integer channel_idx;
integer i;
always @(posedge clock) begin
if (reset) begin
dmem_written <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx] && rvfi_mem_addr[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN] == dmem_addr && `rvformal_addr_valid(dmem_addr)) begin
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
if (enable && rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 + i] && dmem_written[i])
assert(dmem_shadow[i*8 +: 8] == rvfi_mem_rdata[i*8 +: 8]);
if (rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 + i]) begin
dmem_shadow[i*8 +: 8] = rvfi_mem_wdata[i*8 +: 8];
dmem_written[i] = 1;
end
end
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_fault_check.sv
================================================
// check handling of memory faults
//
// This checks that a dynamically occuring memory fault causes a trap and that
// the mcause csr correctly reports the cause of the trap.
//
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_fault_check (
input clock, reset, check,
`RVFI_INPUTS
);
`ifdef RISCV_FORMAL_CHANNEL_IDX
localparam integer channel_idx = `RISCV_FORMAL_CHANNEL_IDX;
`else
genvar channel_idx;
generate for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin:channel
`endif
(* keep *) wire valid = !reset && rvfi_valid[channel_idx];
(* keep *) wire [`RISCV_FORMAL_ILEN - 1 : 0] insn = rvfi_insn [channel_idx*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
(* keep *) wire trap = rvfi_trap [channel_idx];
(* keep *) wire mem_fault = rvfi_mem_fault[channel_idx];
(* keep *) wire halt = rvfi_halt [channel_idx];
(* keep *) wire intr = rvfi_intr [channel_idx];
(* keep *) wire [ 4 : 0] rs1_addr = rvfi_rs1_addr [channel_idx*5 +: 5];
(* keep *) wire [ 4 : 0] rs2_addr = rvfi_rs2_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs1_rdata = rvfi_rs1_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs2_rdata = rvfi_rs2_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [ 4 : 0] rd_addr = rvfi_rd_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rd_wdata = rvfi_rd_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_rdata = rvfi_pc_rdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_wdata = rvfi_pc_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_fault_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_fault_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`ifdef RISCV_FORMAL_CSR_MCAUSE
(* keep *) wire [`RISCV_FORMAL_XLEN-1:0] csr_mcause_wmask = rvfi_csr_mcause_wmask[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN-1:0] csr_mcause_wdata = rvfi_csr_mcause_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
`endif
wire rfault = |mem_fault_rmask;
wire wfault = |mem_fault_wmask;
wire ifault = !(rfault || wfault);
always @* begin
if (!reset && check) begin
assume(valid);
if (mem_fault) begin
assert (trap);
assert (rd_addr == 0);
assert (rd_wdata == 0);
assert (mem_wmask == 0);
cover (rfault);
cover (wfault);
cover (ifault);
if (ifault) begin
assert (insn == 0);
end else begin
assert (insn != 0);
end
`ifdef RISCV_FORMAL_CSR_MCAUSE
if (wfault) begin
assert (&csr_mcause_wmask);
assert (csr_mcause_wdata == 7);
end else if (rfault) begin
assert (&csr_mcause_wmask);
assert (csr_mcause_wdata == 5);
end else if (ifault) begin
assert (&csr_mcause_wmask);
assert (csr_mcause_wdata == 1);
end
`endif
else begin end
end else begin
assert (mem_fault_rmask == 0);
assert (mem_fault_wmask == 0);
end
end
end
`ifndef RISCV_FORMAL_CHANNEL_IDX
end endgenerate
`endif
endmodule
================================================
FILE: checks/rvfi_hang_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_hang_check (
input clock, reset, trig, check,
`RVFI_INPUTS
);
reg okay = 0;
integer channel_idx;
always @(posedge clock) begin
if (reset) begin
okay <= 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx])
okay <= 1;
end
if (check) begin
assert(okay);
end
end
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx]) begin
assume(!rvfi_halt[channel_idx]);
assume(rvfi_insn[(channel_idx+1)*`RISCV_FORMAL_ILEN-1 : channel_idx*`RISCV_FORMAL_ILEN] != 32'b 0001000_00101_00000_000_00000_1110011); // WFI
`ifdef RISCV_FORMAL_WAITINSN
assume(!(`RISCV_FORMAL_WAITINSN(rvfi_insn[(channel_idx+1)*`RISCV_FORMAL_ILEN-1 : channel_idx*`RISCV_FORMAL_ILEN])));
`endif
end
end
end
endmodule
================================================
FILE: checks/rvfi_ill_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_ill_check (
input clock, reset, check,
`RVFI_INPUTS
);
`ifdef RISCV_FORMAL_CHANNEL_IDX
localparam integer channel_idx = `RISCV_FORMAL_CHANNEL_IDX;
`else
genvar channel_idx;
generate for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin:channel
`endif
(* keep *) wire valid = !reset && rvfi_valid[channel_idx];
(* keep *) wire [`RISCV_FORMAL_ILEN - 1 : 0] insn = rvfi_insn [channel_idx*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
(* keep *) wire trap = rvfi_trap [channel_idx];
(* keep *) wire halt = rvfi_halt [channel_idx];
(* keep *) wire intr = rvfi_intr [channel_idx];
(* keep *) wire [ 4 : 0] rs1_addr = rvfi_rs1_addr [channel_idx*5 +: 5];
(* keep *) wire [ 4 : 0] rs2_addr = rvfi_rs2_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs1_rdata = rvfi_rs1_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs2_rdata = rvfi_rs2_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [ 4 : 0] rd_addr = rvfi_rd_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rd_wdata = rvfi_rd_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_rdata = rvfi_pc_rdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_wdata = rvfi_pc_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
always @* begin
cover(!reset && check && valid && insn == 0);
if (!reset && check) begin
assume(valid);
assume(insn == 0);
assert(trap);
assert(rd_addr == 0);
assert(rd_wdata == 0);
assert(mem_wmask == 0);
end
end
`ifndef RISCV_FORMAL_CHANNEL_IDX
end endgenerate
`endif
endmodule
================================================
FILE: checks/rvfi_imem_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_imem_check (
input clock, reset, enable,
output [`RISCV_FORMAL_XLEN-1:0] imem_addr,
output [15:0] imem_data,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [`RISCV_FORMAL_XLEN-1:0] imem_addr_randval;
`rvformal_rand_const_reg [15:0] imem_data_randval;
assign imem_addr = imem_addr_randval;
assign imem_data = imem_data_randval;
reg [`RISCV_FORMAL_XLEN-1:0] pc;
reg [`RISCV_FORMAL_ILEN-1:0] insn;
integer channel_idx;
integer i;
always @(posedge clock) begin
if (reset) begin
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (enable && rvfi_valid[channel_idx]) begin
pc = rvfi_pc_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
insn = rvfi_insn[channel_idx*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
if (`rvformal_addr_valid(pc) && pc == imem_addr)
assert(insn[15:0] == imem_data);
if (insn[1:0] == 2'b11 && `rvformal_addr_valid(pc+2) && pc+2 == imem_addr)
assert(insn[31:16] == imem_data);
end
end
end
end
endmodule
================================================
FILE: checks/rvfi_insn_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_insn_check (
input clock, reset, check,
`RVFI_INPUTS
);
`ifdef RISCV_FORMAL_CHANNEL_IDX
localparam integer channel_idx = `RISCV_FORMAL_CHANNEL_IDX;
`else
genvar channel_idx;
generate for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin:channel
`endif
(* keep *) wire valid = !reset && rvfi_valid[channel_idx];
(* keep *) wire [`RISCV_FORMAL_ILEN - 1 : 0] insn = rvfi_insn [channel_idx*`RISCV_FORMAL_ILEN +: `RISCV_FORMAL_ILEN];
(* keep *) wire trap = rvfi_trap [channel_idx];
(* keep *) wire halt = rvfi_halt [channel_idx];
(* keep *) wire intr = rvfi_intr [channel_idx];
(* keep *) wire [ 4 : 0] rs1_addr = rvfi_rs1_addr [channel_idx*5 +: 5];
(* keep *) wire [ 4 : 0] rs2_addr = rvfi_rs2_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs1_rdata = rvfi_rs1_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs2_rdata = rvfi_rs2_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [ 4 : 0] rd_addr = rvfi_rd_addr [channel_idx*5 +: 5];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rd_wdata = rvfi_rd_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_rdata = rvfi_pc_rdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] pc_wdata = rvfi_pc_wdata [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_addr = rvfi_mem_addr [channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_rmask = rvfi_mem_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_wmask = rvfi_mem_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_rdata = rvfi_mem_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] mem_wdata = rvfi_mem_wdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
`ifdef RISCV_FORMAL_MEM_FAULT
(* keep *) wire mem_fault = rvfi_mem_fault[channel_idx];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_fault_rmask = rvfi_mem_fault_rmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] mem_fault_wmask = rvfi_mem_fault_wmask[channel_idx*`RISCV_FORMAL_XLEN/8 +: `RISCV_FORMAL_XLEN/8];
`endif
`ifdef RISCV_FORMAL_CSR_MISA
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] csr_misa_rdata = rvfi_csr_misa_rdata[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] csr_misa_rmask = rvfi_csr_misa_rmask[channel_idx*`RISCV_FORMAL_XLEN +: `RISCV_FORMAL_XLEN];
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] spec_csr_misa_rmask;
`endif
(* keep *) wire spec_valid;
(* keep *) wire spec_trap;
(* keep *) wire [ 4 : 0] spec_rs1_addr;
(* keep *) wire [ 4 : 0] spec_rs2_addr;
(* keep *) wire [ 4 : 0] spec_rd_addr;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] spec_rd_wdata;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] spec_pc_wdata;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] spec_mem_addr;
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] spec_mem_rmask;
(* keep *) wire [`RISCV_FORMAL_XLEN/8 - 1 : 0] spec_mem_wmask;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] spec_mem_wdata;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs1_rdata_or_zero = spec_rs1_addr != 0 ? rs1_rdata : 0;
(* keep *) wire [`RISCV_FORMAL_XLEN - 1 : 0] rs2_rdata_or_zero = spec_rs2_addr != 0 ? rs2_rdata : 0;
`RISCV_FORMAL_INSN_MODEL insn_spec (
.rvfi_valid (valid ),
.rvfi_insn (insn ),
.rvfi_pc_rdata (pc_rdata ),
.rvfi_rs1_rdata (rs1_rdata_or_zero ),
.rvfi_rs2_rdata (rs2_rdata_or_zero ),
.rvfi_mem_rdata (mem_rdata ),
`ifdef RISCV_FORMAL_CSR_MISA
.rvfi_csr_misa_rdata (csr_misa_rdata ),
.spec_csr_misa_rmask (spec_csr_misa_rmask),
`endif
.spec_valid (spec_valid ),
.spec_trap (spec_trap ),
.spec_rs1_addr (spec_rs1_addr ),
.spec_rs2_addr (spec_rs2_addr ),
.spec_rd_addr (spec_rd_addr ),
.spec_rd_wdata (spec_rd_wdata ),
.spec_pc_wdata (spec_pc_wdata ),
.spec_mem_addr (spec_mem_addr ),
.spec_mem_rmask (spec_mem_rmask ),
.spec_mem_wmask (spec_mem_wmask ),
.spec_mem_wdata (spec_mem_wdata )
);
wire insn_pma_x, mem_pma_r, mem_pma_w;
wire [1:0] mem_log2len =
((spec_mem_rmask | spec_mem_wmask) & 8'b 1111_0000) ? 3 :
((spec_mem_rmask | spec_mem_wmask) & 8'b 0000_1100) ? 2 :
((spec_mem_rmask | spec_mem_wmask) & 8'b 0000_0010) ? 1 : 0;
`ifdef RISCV_FORMAL_PMA_MAP
`RISCV_FORMAL_PMA_MAP insn_pma (
.address(pc_rdata),
.log2len(insn[1:0] == 2'b11 ? 2'd2 : 2'd1),
.X(insn_pma_x)
);
`RISCV_FORMAL_PMA_MAP mem_pma (
.address(spec_mem_addr),
.log2len(mem_log2len),
.R(mem_pma_r),
.W(mem_pma_w)
);
`else
assign insn_pma_x = 1;
assign mem_pma_r = 1;
assign mem_pma_w = 1;
`endif
`ifdef RISCV_FORMAL_MEM_FAULT
wire mem_access_fault = mem_fault ||
`else
wire mem_access_fault =
`endif
(spec_mem_rmask && !mem_pma_r) || (spec_mem_wmask && !mem_pma_w) ||
((spec_mem_rmask || spec_mem_wmask) && !`rvformal_addr_valid(spec_mem_addr));
integer i;
always @* begin
if (!reset) begin
cover(spec_valid);
cover(spec_valid && !trap);
cover(check && spec_valid);
cover(check && spec_valid && !trap);
end
if (!reset && check) begin
assume(spec_valid);
if (!`rvformal_addr_valid(pc_rdata) || !insn_pma_x || mem_access_fault) begin
assert(trap);
assert(rd_addr == 0);
assert(rd_wdata == 0);
assert(mem_wmask == 0);
`ifdef RISCV_FORMAL_MEM_FAULT
if (mem_fault) begin
assert(mem_rmask == 0);
assert(spec_mem_wmask || spec_mem_rmask);
assert(`rvformal_addr_eq(spec_mem_addr, mem_addr));
assert(mem_fault_wmask == spec_mem_wmask);
assert((mem_fault_rmask & spec_mem_rmask) == spec_mem_rmask);
end
`endif
end else begin
`ifdef RISCV_FORMAL_CSR_MISA
assert((spec_csr_misa_rmask & csr_misa_rmask) == spec_csr_misa_rmask);
`endif
if (rs1_addr == 0)
assert(rs1_rdata == 0);
if (rs2_addr == 0)
assert(rs2_rdata == 0);
if (!spec_trap) begin
if (spec_rs1_addr != 0)
assert(spec_rs1_addr == rs1_addr);
if (spec_rs2_addr != 0)
assert(spec_rs2_addr == rs2_addr);
assert(spec_rd_addr == rd_addr);
assert(spec_rd_wdata == rd_wdata);
assert(`rvformal_addr_eq(spec_pc_wdata, pc_wdata));
if (spec_mem_wmask || spec_mem_rmask) begin
assert(`rvformal_addr_eq(spec_mem_addr, mem_addr));
end
for (i = 0; i < `RISCV_FORMAL_XLEN/8; i = i+1) begin
if (spec_mem_wmask[i]) begin
assert(mem_wmask[i]);
assert(spec_mem_wdata[i*8 +: 8] == mem_wdata[i*8 +: 8]);
end else if (mem_wmask[i]) begin
assert(mem_rmask[i]);
assert(mem_rdata[i*8 +: 8] == mem_wdata[i*8 +: 8]);
end
if (spec_mem_rmask[i]) begin
assert(mem_rmask[i]);
end
end
end
assert(spec_trap == trap);
end
end
end
`ifndef RISCV_FORMAL_CHANNEL_IDX
end endgenerate
`endif
endmodule
================================================
FILE: checks/rvfi_liveness_check.sv
================================================
// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
module rvfi_liveness_check (
input clock, reset, trig, check,
`RVFI_INPUTS
);
`rvformal_rand_const_reg [63:0] insn_order;
reg found_next_insn = 0;
integer channel_idx;
always @(posedge clock) begin
if (reset) begin
found_next_insn = 0;
end else begin
for (channel_idx = 0; channel_idx < `RISCV_FORMAL_NRET; channel_idx=channel_idx+1) begin
if (rvfi_valid[channel_idx] && rvfi_order[64*channel_idx +: 64] == insn_order+1) begin
found_next_insn = 1;
end
end
if (trig) begin
assume(rvfi_valid[`RISCV_FORMAL_CHANNEL_IDX]);
assume(!rvfi_halt[`RISCV_FORMAL_CHANNEL_IDX]);
assume(insn_order == rvfi_order[64*`RISCV_FORMAL_CHANNEL_IDX +: 64]);
end
if (check) begin
assert(found_next_insn);
end
end
end
endmodule
================================================
FILE: checks/rvfi_macros.py
================================================
#!/usr/bin/env python3
#
# Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from dataclasses import dataclass, field
from typing import Optional, List, Tuple
@dataclass
class Group:
name: str
signals: List[Tuple[str, str]]
channels: Optional[str] = None
condition: Optional[str] = None
nosep: bool = False
csr_conn32: bool = False
append: List['Group'] = field(default_factory=list)
def __post_init__(self):
self._cw = max((len(width) for width, name in self.signals), default=0)
self._cn = max((len(name) for width, name in self.signals), default=0)
self._has_conn32 = self.csr_conn32 or any(g._has_conn32 for g in self.append)
def bitrange(self, width, no_channel=False):
if no_channel or self.channels is None:
if str(width).strip() == '1':
return f"[{'':>{self._cw}} 0 : 0]"
else:
return f"[{width:>{self._cw}} - 1 : 0]"
elif str(width).strip() == '1':
return f"[{self.channels} {'':>{self._cw}} - 1 : 0]"
else:
return f"[{self.channels} * {width:>{self._cw}} - 1 : 0]"
def channel_idx(self, width):
if str(width).strip() == '1':
return f"[ _idx {'':>{self._cw}} +: {width:>{self._cw}}]"
else:
return f"[(_idx)*({width:>{self._cw}}) +: {width:>{self._cw}}]"
def macro_name(self, s, extra=""):
if self.name.upper() == self.name:
if s == "channel":
return f"{self.name}_GETCHANNEL{extra.upper()}(_idx)"
elif s == "channel_conn":
return f"{self.name}_CHANNEL_CONN{extra.upper()}(_idx)"
else:
return f"{self.name}_{s.upper()}{extra.upper()}"
else:
if s == "channel":
return f"{self.name}_channel{extra}(_idx)"
elif s == "channel_conn":
return f"{self.name}_channel_conn{extra}(_idx)"
else:
return f"{self.name}_{s}{extra}"
def macro_name_nosep(self, s):
if self.nosep:
return self.macro_name(s, extra="_nosep")
else:
return self.macro_name(s)
def commas(self, parts, suffix=()):
if (self.condition and not self.nosep) or len(parts) < 2:
return " \\\n ".join([", \\\n ".join(parts), *suffix])
else:
first, *parts = parts
return " \\\n ".join([first, ", \\\n ".join(parts), *suffix])
def high_name(self, name):
parts = name.split('_')
parts[-2] += 'h'
return '_'.join(parts)
def print_macros(self):
if self.condition:
print(f"`ifdef {self.condition}")
print(self.commas([f"`define {self.macro_name('wires')}"], [
f"(* keep *) wire {self.bitrange(width)} rvfi_{name:<{self._cn}};"
for width, name in self.signals
] + [
"`" + group.macro_name('wires') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('outputs')}"] + [
f"output {self.bitrange(width)} rvfi_{name:<{self._cn}}"
for width, name in self.signals
], [
"`" + group.macro_name('outputs') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('channel_outputs')}"] + [
f"output {self.bitrange(width, no_channel=True)} rvfi_{name:<{self._cn}}"
for width, name in self.signals
], [
"`" + group.macro_name('channel_outputs') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('inputs')}"] + [
f"input {self.bitrange(width)} rvfi_{name:<{self._cn}}"
for width, name in self.signals
], [
"`" + group.macro_name('inputs') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('channel_inputs')}"] + [
f"input {self.bitrange(width, no_channel=True)} rvfi_{name:<{self._cn}}"
for width, name in self.signals
], [
"`" + group.macro_name('channel_inputs') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('conn')}"] + [
f".rvfi_{name:<{self._cn}} (rvfi_{name:<{self._cn}})"
for width, name in self.signals
], [
"`" + group.macro_name('conn') for group in self.append
]))
print(self.commas([f"`define {self.macro_name_nosep('channel_conn')}"] + [
f".rvfi_{name:<{self._cn}} (rvfi_{name:<{self._cn}} {self.channel_idx(width)})"
for width, name in self.signals
], [
"`" + group.macro_name('channel_conn') for group in self.append
]))
if self.csr_conn32:
cn = self._cn + self.csr_conn32
print(self.commas([f"`define {self.macro_name_nosep('conn32')}"] + [
f".rvfi_{name:<{cn}} (rvfi_{name:<{self._cn}}[31: 0])"
for width, name in self.signals
] + [
f".rvfi_{self.high_name(name):<{cn}} (rvfi_{name:<{self._cn}}[63:32])"
for width, name in self.signals
], [
"`" + group.macro_name('conn32') for group in self.append
]))
elif self._has_conn32:
print(self.commas([f"`define {self.macro_name_nosep('conn32')}"] + [
f".rvfi_{name:<{self._cn}} (rvfi_{name:<{self._cn}})"
for width, name in self.signals
], [
"`" + group.macro_name('conn32' if group._has_conn32 else 'conn') for group in self.append
]))
if self.channels:
print(self.commas([f"`define {self.macro_name('channel')}"], [
f"wire {self.bitrange(width, True)} {name:<{self._cn}} = "
f"rvfi_{name:<{self._cn}} {self.channel_idx(width)};"
for width, name in self.signals
] + [
"`" + group.macro_name('channel') for group in self.append if group.channels
]))
print(self.commas([f"`define {self.macro_name('signals')}"], [
f"`RISCV_FORMAL_CHANNEL_SIGNAL({self.channels}, {width:>{self._cw}}, {name:<{self._cn}})"
for width, name in self.signals
] + [
"`" + group.macro_name('signals') for group in self.append if group.channels
]))
if self.nosep:
print(f"`define {self.macro_name('outputs')} , `{self.macro_name_nosep('outputs')}")
print(f"`define {self.macro_name('inputs')} , `{self.macro_name_nosep('inputs')}")
print(f"`define {self.macro_name('conn')} , `{self.macro_name_nosep('conn')}")
print(f"`define {self.macro_name('channel_outputs')} , `{self.macro_name_nosep('channel_outputs')}")
print(f"`define {self.macro_name('channel_inputs')} , `{self.macro_name_nosep('channel_inputs')}")
print(f"`define {self.macro_name('channel_conn')} , `{self.macro_name_nosep('channel_conn')}")
if self._has_conn32:
print(f"`define {self.macro_name('conn32')}")
if self.condition:
print("`else")
print(f"`define {self.macro_name('wires')}")
print(f"`define {self.macro_name('outputs')}")
print(f"`define {self.macro_name('inputs')}")
print(f"`define {self.macro_name('conn')}")
if self._has_conn32:
print(f"`define {self.macro_name('conn32')}")
if self.channels:
print(f"`define {self.macro_name('channel')}")
print("`endif")
if self.name.upper() == self.name:
print("")
print(f"`define {self.name}_CHANNEL(_name, _idx) \\")
print("generate if(1) begin:_name \\")
print(f" `{self.name}_GETCHANNEL(_idx) \\")
print("end endgenerate")
return self
@dataclass
class Csr:
len: str
name: str
mindex: Optional[int] = None
sindex: Optional[int] = None
uindex: Optional[int] = None
hmindex: Optional[int] = None
hsindex: Optional[int] = None
huindex: Optional[int] = None
csrs = [
Csr("xlen", "fflags", None, None, None),
Csr("xlen", "frm", None, None, None),
Csr("xlen", "fcsr", None, None, None),
Csr("xlen", "mvendorid", 0xF11, None, None),
Csr("xlen", "marchid", 0xF12, None, None),
Csr("xlen", "mimpid", 0xF13, None, None),
Csr("xlen", "mhartid", 0xF14, None, None),
Csr("xlen", "mconfigptr", 0xF15, None, None),
Csr("xlen", "mstatus", 0x300, None, None),
Csr("xlen", "mstatush", 0x310, None, None),
Csr("xlen", "misa", 0x301, None, None),
Csr("xlen", "medeleg", 0x302, None, None),
Csr("xlen", "mideleg", 0x303, None, None),
Csr("xlen", "mie", 0x304, None, None),
Csr("xlen", "mtvec", 0x305, None, None),
Csr("xlen", "mcounteren", 0x306, None, None),
Csr("xlen", "mscratch", 0x340, None, None),
Csr("xlen", "mepc", 0x341, None, None),
Csr("xlen", "mcause", 0x342, None, None),
Csr("xlen", "mtval", 0x343, None, None),
Csr("xlen", "mip", 0x344, None, None),
Csr("xlen", "mtinst", 0x34A, None, None),
Csr("xlen", "mtval2", 0x34B, None, None),
Csr("xlen", "mcountinhibit", 0x320, None, None),
Csr("xlen", "menvcfg", 0x30A, None, None),
Csr("xlen", "menvcfgh", 0x31A, None, None),
*(
Csr("xlen", f"pmpcfg{i}", 0x3A0 + i, None, None)
for i in range(16)
),
*(
Csr("xlen", f"pmpaddr{i}", 0x3B0 + i, None, None)
for i in range(64)
),
*(
Csr("xlen", f"mhpmevent{i}", 0x320 + i, None, None)
for i in range(3, 32)
),
Csr("64", "mcycle", 0xB00, None, 0xC00,
0xB80, None, 0xC80),
Csr("64", "time", None, None, 0xC01,
None, None, 0xC01),
Csr("64", "minstret", 0xB02, None, 0xC02,
0xB82, None, 0xC82),
*(
Csr("64", f"mhpmcounter{i}", 0xB00 + i, None, 0xC00 + i,
0xB80 + i, None, 0xC80 + i)
for i in range(3, 32)
),
]
print("// Generated by rvfi_macros.py")
print("")
print("`ifdef YOSYS")
print("`define rvformal_rand_reg rand reg")
print("`define rvformal_rand_const_reg rand const reg")
print("`else")
print("`ifdef SIMULATION")
print("`define rvformal_rand_reg reg")
print("`define rvformal_rand_const_reg reg")
print("`else")
print("`define rvformal_rand_reg wire")
print("`define rvformal_rand_const_reg reg")
print("`endif")
print("`endif")
print("")
print("`ifndef RISCV_FORMAL_VALIDADDR")
print("`define RISCV_FORMAL_VALIDADDR(addr) 1")
print("`endif")
print("")
print("`ifndef RISCV_FORMAL_IOADDR")
print("`define RISCV_FORMAL_IOADDR(addr) 1")
print("`endif")
print("")
print("`define rvformal_addr_valid(a) (`RISCV_FORMAL_VALIDADDR(a))")
print("`define rvformal_addr_io(a) (`rvformal_addr_valid(a) && (`RISCV_FORMAL_IOADDR(a)))")
print("`define rvformal_addr_eq(a, b) ((`rvformal_addr_valid(a) == `rvformal_addr_valid(b)) && (!`rvformal_addr_valid(a) || (a == b)))")
print("`define rvformal_addr_eq_io(a, b) (`rvformal_addr_io(a) ? `rvformal_addr_io(b) : `rvformal_addr_eq(a, b))")
print("")
csr_groups = []
def csr_index(index):
if index is None:
return "12'hFFF"
else:
return f"12'h{index:03X}"
for csr in csrs:
width = {"64": "64", "xlen": "`RISCV_FORMAL_XLEN"}[csr.len]
csr_groups.append(Group(
condition=f"RISCV_FORMAL_CSR_{csr.name.upper()}",
name=f"rvformal_csr_{csr.name}",
channels="`RISCV_FORMAL_NRET",
csr_conn32=csr.len == "64",
signals=[
(width, f"csr_{csr.name}_rmask"),
(width, f"csr_{csr.name}_wmask"),
(width, f"csr_{csr.name}_rdata"),
(width, f"csr_{csr.name}_wdata"),
]
).print_macros())
print(f"`define rvformal_csr_{csr.name}_indices \\")
print(f"localparam [11:0] csr_mindex_{csr.name} = {csr_index(csr.mindex)}; \\")
print(f"localparam [11:0] csr_sindex_{csr.name} = {csr_index(csr.sindex)}; \\")
print(f"localparam [11:0] csr_uindex_{csr.name} = {csr_index(csr.uindex)}; \\")
if csr.len == "64":
print(f"localparam [11:0] csr_mindex_{csr.name}h = {csr_index(csr.hmindex)}; \\")
print(f"localparam [11:0] csr_sindex_{csr.name}h = {csr_index(csr.hsindex)}; \\")
print(f"localparam [11:0] csr_uindex_{csr.name}h = {csr_index(csr.huindex)}; \\")
print()
print("`define RVFI_INDICES \\")
for csr in csrs:
print(f"`rvformal_csr_{csr.name}_indices \\")
print("`rvformal_custom_csr_indices")
print()
# Do not print this group, we'll use user macros when defined instead
custom_csr = Group(name="rvformal_custom_csr", signals=[], channels="`RISCV_FORMAL_NRET",)
for macro in ["inputs", "wires", "conn", "channel", "signals", "outputs", "indices"]:
print(f"`ifdef RISCV_FORMAL_CUSTOM_CSR_{macro.upper()}")
if (macro == "channel"):
print(f"`define rvformal_custom_csr_{macro}(_idx) `RISCV_FORMAL_CUSTOM_CSR_{macro.upper()}(_idx)")
print(f"`else")
print(f"`define rvformal_custom_csr_{macro}(_idx)")
else:
print(f"`define rvformal_custom_csr_{macro} `RISCV_FORMAL_CUSTOM_CSR_{macro.upper()}")
print(f"`else")
print(f"`define rvformal_custom_csr_{macro}")
print(f"`endif")
group_rollback = Group(
condition="RISCV_FORMAL_ROLLBACK",
name="rvformal_rollback",
signals=[
(" 1", "rollback_valid"),
("64", "rollback_order"),
]
).print_macros()
group_extamo = Group(
condition="RISCV_FORMAL_EXTAMO",
name="rvformal_extamo",
channels="`RISCV_FORMAL_NRET",
signals=[
("1", "mem_extamo"),
]
).print_macros()
group_fault = Group(
condition="RISCV_FORMAL_MEM_FAULT",
name="rvformal_mem_fault",
channels="`RISCV_FORMAL_NRET",
signals=[
(" 1 ", "mem_fault"),
("`RISCV_FORMAL_XLEN/8", "mem_fault_rmask"),
("`RISCV_FORMAL_XLEN/8", "mem_fault_wmask"),
]
).print_macros()
rvfi = Group(
name="RVFI",
channels="`RISCV_FORMAL_NRET",
signals=[
(" 1 ", "valid "),
(" 64 ", "order "),
("`RISCV_FORMAL_ILEN ", "insn "),
(" 1 ", "trap "),
(" 1 ", "halt "),
(" 1 ", "intr "),
(" 2 ", "mode "),
(" 2 ", "ixl "),
(" 5 ", "rs1_addr "),
(" 5 ", "rs2_addr "),
("`RISCV_FORMAL_XLEN ", "rs1_rdata"),
gitextract_1qfjctmx/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── COPYING
├── CodeOfConduct
├── README.md
├── bus/
│ ├── rvfi_bus_axi4.sv
│ └── rvfi_bus_util.sv
├── checks/
│ ├── genchecks.py
│ ├── rvfi_bus_dmem_check.sv
│ ├── rvfi_bus_dmem_fault_check.sv
│ ├── rvfi_bus_dmem_io_order_check.sv
│ ├── rvfi_bus_dmem_io_read_check.sv
│ ├── rvfi_bus_dmem_io_read_fault_check.sv
│ ├── rvfi_bus_dmem_io_write_check.sv
│ ├── rvfi_bus_dmem_io_write_fault_check.sv
│ ├── rvfi_bus_imem_check.sv
│ ├── rvfi_bus_imem_fault_check.sv
│ ├── rvfi_causal_check.sv
│ ├── rvfi_causal_io_check.sv
│ ├── rvfi_causal_mem_check.sv
│ ├── rvfi_channel.sv
│ ├── rvfi_cover_check.sv
│ ├── rvfi_csr_ill_check.sv
│ ├── rvfi_csrc_any_check.sv
│ ├── rvfi_csrc_const_check.sv
│ ├── rvfi_csrc_hpm_check.sv
│ ├── rvfi_csrc_inc_check.sv
│ ├── rvfi_csrc_upcnt_check.sv
│ ├── rvfi_csrc_zero_check.sv
│ ├── rvfi_csrw_check.sv
│ ├── rvfi_dmem_check.sv
│ ├── rvfi_fault_check.sv
│ ├── rvfi_hang_check.sv
│ ├── rvfi_ill_check.sv
│ ├── rvfi_imem_check.sv
│ ├── rvfi_insn_check.sv
│ ├── rvfi_liveness_check.sv
│ ├── rvfi_macros.py
│ ├── rvfi_macros.vh
│ ├── rvfi_pc_bwd_check.sv
│ ├── rvfi_pc_fwd_check.sv
│ ├── rvfi_reg_check.sv
│ ├── rvfi_testbench.sv
│ └── rvfi_unique_check.sv
├── cores/
│ ├── VexRiscv/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── VexRiscv.v
│ │ ├── checks.cfg
│ │ ├── disasm.py
│ │ ├── dmemcheck.sby
│ │ ├── dmemcheck.sv
│ │ ├── imemcheck.sby
│ │ ├── imemcheck.sv
│ │ └── wrapper.sv
│ ├── nerv/
│ │ ├── .gitignore
│ │ ├── COPYING
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── axi_cache/
│ │ │ ├── .gitignore
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── axi_ram.v
│ │ │ ├── checks_axi.cfg
│ │ │ ├── checks_internal.cfg
│ │ │ ├── firmware.c
│ │ │ ├── nerv_axi_cache.sv
│ │ │ ├── nerv_axi_cache_dcache.sv
│ │ │ ├── nerv_axi_cache_icache.sv
│ │ │ ├── testbench_axi.sv
│ │ │ ├── testbench_internal.sv
│ │ │ ├── verify_axi.sby
│ │ │ ├── verify_axi.sv
│ │ │ ├── wrapper_axi.sv
│ │ │ └── wrapper_internal.sv
│ │ ├── cexdata.sh
│ │ ├── checks.cfg
│ │ ├── disasm.py
│ │ ├── examples/
│ │ │ └── icebreaker/
│ │ │ ├── .gitignore
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── firmware.c
│ │ │ ├── firmware.s
│ │ │ ├── icebreaker.pcf
│ │ │ ├── sections.lds
│ │ │ ├── testbench.gtkw
│ │ │ ├── testbench.sv
│ │ │ └── top.v
│ │ ├── firmware.c
│ │ ├── firmware.s
│ │ ├── imemcheck.sby
│ │ ├── imemcheck.sv
│ │ ├── nerv.sv
│ │ ├── nervsoc.sv
│ │ ├── sections.lds
│ │ ├── testbench.gtkw
│ │ ├── testbench.sv
│ │ ├── trace.gtkw
│ │ ├── vectors.s
│ │ └── wrapper.sv
│ ├── picorv32/
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── cexdata.sh
│ │ ├── checks.cfg
│ │ ├── checks.gtkw
│ │ ├── complete.sby
│ │ ├── complete.sv
│ │ ├── cover.sby
│ │ ├── cover.sv
│ │ ├── disasm.py
│ │ ├── dmemcheck.sv
│ │ ├── equiv.sh
│ │ ├── honest.sby
│ │ ├── honest.sv
│ │ ├── imemcheck.sv
│ │ ├── testbugs.sh
│ │ └── wrapper.sv
│ ├── rocket/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── cexdata.sh
│ │ ├── checks.gtkw
│ │ ├── cover.gtkw
│ │ ├── cover.sby
│ │ ├── cover.sv
│ │ ├── coverage.sby
│ │ ├── coverage.sv
│ │ ├── decode.sh
│ │ ├── disasm.py
│ │ ├── generate.sh
│ │ ├── muldivlen.py
│ │ ├── muldivlen.sby
│ │ ├── muldivlen.sv
│ │ ├── rocketrvfi.sv
│ │ ├── testbench.cc
│ │ ├── testbench.sh
│ │ └── wrapper.sv
│ └── serv/
│ ├── .gitignore
│ ├── README.md
│ ├── cexdata.sh
│ ├── checks.cfg
│ ├── cover.gtkw
│ ├── cover.sby
│ ├── cover.sv
│ ├── disasm.py
│ ├── generate.sh
│ ├── sbram.sv
│ └── wrapper.sv
├── docs/
│ ├── config.md
│ ├── csrs.md
│ ├── examplebugs.md
│ ├── procedure.md
│ ├── quickstart.md
│ ├── references.md
│ └── rvfi.md
├── insns/
│ ├── generate.py
│ ├── insn_add.v
│ ├── insn_addi.v
│ ├── insn_addiw.v
│ ├── insn_addw.v
│ ├── insn_and.v
│ ├── insn_andi.v
│ ├── insn_auipc.v
│ ├── insn_beq.v
│ ├── insn_bge.v
│ ├── insn_bgeu.v
│ ├── insn_blt.v
│ ├── insn_bltu.v
│ ├── insn_bne.v
│ ├── insn_c_add.v
│ ├── insn_c_addi.v
│ ├── insn_c_addi16sp.v
│ ├── insn_c_addi4spn.v
│ ├── insn_c_addiw.v
│ ├── insn_c_addw.v
│ ├── insn_c_and.v
│ ├── insn_c_andi.v
│ ├── insn_c_beqz.v
│ ├── insn_c_bnez.v
│ ├── insn_c_j.v
│ ├── insn_c_jal.v
│ ├── insn_c_jalr.v
│ ├── insn_c_jr.v
│ ├── insn_c_ld.v
│ ├── insn_c_ldsp.v
│ ├── insn_c_li.v
│ ├── insn_c_lui.v
│ ├── insn_c_lw.v
│ ├── insn_c_lwsp.v
│ ├── insn_c_mv.v
│ ├── insn_c_or.v
│ ├── insn_c_sd.v
│ ├── insn_c_sdsp.v
│ ├── insn_c_slli.v
│ ├── insn_c_srai.v
│ ├── insn_c_srli.v
│ ├── insn_c_sub.v
│ ├── insn_c_subw.v
│ ├── insn_c_sw.v
│ ├── insn_c_swsp.v
│ ├── insn_c_xor.v
│ ├── insn_div.v
│ ├── insn_divu.v
│ ├── insn_divuw.v
│ ├── insn_divw.v
│ ├── insn_jal.v
│ ├── insn_jalr.v
│ ├── insn_lb.v
│ ├── insn_lbu.v
│ ├── insn_ld.v
│ ├── insn_lh.v
│ ├── insn_lhu.v
│ ├── insn_lui.v
│ ├── insn_lw.v
│ ├── insn_lwu.v
│ ├── insn_mul.v
│ ├── insn_mulh.v
│ ├── insn_mulhsu.v
│ ├── insn_mulhu.v
│ ├── insn_mulw.v
│ ├── insn_or.v
│ ├── insn_ori.v
│ ├── insn_rem.v
│ ├── insn_remu.v
│ ├── insn_remuw.v
│ ├── insn_remw.v
│ ├── insn_sb.v
│ ├── insn_sd.v
│ ├── insn_sh.v
│ ├── insn_sll.v
│ ├── insn_slli.v
│ ├── insn_slliw.v
│ ├── insn_sllw.v
│ ├── insn_slt.v
│ ├── insn_slti.v
│ ├── insn_sltiu.v
│ ├── insn_sltu.v
│ ├── insn_sra.v
│ ├── insn_srai.v
│ ├── insn_sraiw.v
│ ├── insn_sraw.v
│ ├── insn_srl.v
│ ├── insn_srli.v
│ ├── insn_srliw.v
│ ├── insn_srlw.v
│ ├── insn_sub.v
│ ├── insn_subw.v
│ ├── insn_sw.v
│ ├── insn_xor.v
│ ├── insn_xori.v
│ ├── isa_rv32i.txt
│ ├── isa_rv32i.v
│ ├── isa_rv32ic.txt
│ ├── isa_rv32ic.v
│ ├── isa_rv32im.txt
│ ├── isa_rv32im.v
│ ├── isa_rv32imc.txt
│ ├── isa_rv32imc.v
│ ├── isa_rv64i.txt
│ ├── isa_rv64i.v
│ ├── isa_rv64ic.txt
│ ├── isa_rv64ic.v
│ ├── isa_rv64im.txt
│ ├── isa_rv64im.v
│ ├── isa_rv64imc.txt
│ └── isa_rv64imc.v
├── monitor/
│ └── generate.py
└── tests/
├── coverage/
│ ├── .gitignore
│ ├── coverage.sby
│ ├── coverage.sv
│ ├── generate.py
│ ├── riscv_rv32i_insn.v
│ ├── riscv_rv32ic_insn.v
│ ├── riscv_rv64i_insn.v
│ └── riscv_rv64ic_insn.v
├── semantics/
│ ├── .gitignore
│ ├── Makefile
│ ├── cexformat.py
│ ├── makejob.py
│ └── top.sv
└── spike/
├── .gitignore
├── common.h
└── generate.py
SYMBOL INDEX (115 symbols across 12 files)
FILE: checks/genchecks.py
function add_csr_tests (line 137) | def add_csr_tests(name, test_str):
function add_csr (line 144) | def add_csr(csr_str):
function mask_bits (line 153) | def mask_bits(test: str, bits: "list[int]", mask_len: int, invert=False):
function hfmt (line 239) | def hfmt(text, **kwargs):
function print_hfmt (line 251) | def print_hfmt(f, text, **kwargs):
function test_disabled (line 282) | def test_disabled(check):
function get_depth_cfg (line 292) | def get_depth_cfg(patterns):
function print_custom_csrs (line 304) | def print_custom_csrs(sby_file):
function check_insn (line 338) | def check_insn(grp, insn, chanidx, csr_mode=False, illegal_csr=False):
function check_cons (line 549) | def check_cons(grp, check, chanidx=None, start=None, trig=None, depth=No...
function checks_key (line 821) | def checks_key(check):
FILE: checks/rvfi_macros.py
class Group (line 20) | class Group:
method __post_init__ (line 29) | def __post_init__(self):
method bitrange (line 34) | def bitrange(self, width, no_channel=False):
method channel_idx (line 45) | def channel_idx(self, width):
method macro_name (line 51) | def macro_name(self, s, extra=""):
method macro_name_nosep (line 67) | def macro_name_nosep(self, s):
method commas (line 73) | def commas(self, parts, suffix=()):
method high_name (line 80) | def high_name(self, name):
method print_macros (line 85) | def print_macros(self):
class Csr (line 198) | class Csr:
function csr_index (line 293) | def csr_index(index):
FILE: cores/nerv/axi_cache/firmware.c
function putc (line 20) | void putc(int c)
function do_exit (line 26) | void do_exit()
function puts (line 32) | void puts(char *s)
function print_num (line 40) | void print_num(unsigned p)
function main (line 58) | int main()
FILE: cores/nerv/examples/icebreaker/firmware.c
function delay (line 22) | void delay(uint32_t count)
function main (line 29) | int main()
FILE: cores/nerv/firmware.c
function putc (line 20) | void putc(int c)
function puts (line 26) | void puts(char *s)
function main (line 31) | int main()
FILE: cores/rocket/disasm.py
function usage (line 11) | def usage():
FILE: cores/rocket/testbench.cc
function sc_time_stamp (line 7) | double sc_time_stamp()
function main (line 12) | int main(int argc, char **argv, char **env)
FILE: insns/generate.py
function header (line 48) | def header(f, insn, isa_mode=False):
function assign (line 105) | def assign(f, sig, val):
function misa_check (line 111) | def misa_check(f, mask, ialign16=False):
function footer (line 128) | def footer(f):
function format_r (line 151) | def format_r(f):
function format_ra (line 162) | def format_ra(f):
function format_i (line 175) | def format_i(f):
function format_i_shift (line 185) | def format_i_shift(f):
function format_s (line 196) | def format_s(f):
function format_sb (line 206) | def format_sb(f):
function format_u (line 216) | def format_u(f):
function format_uj (line 224) | def format_uj(f):
function format_cr (line 232) | def format_cr(f):
function format_ci (line 241) | def format_ci(f):
function format_ci_sp (line 250) | def format_ci_sp(f):
function format_ci_lui (line 259) | def format_ci_lui(f):
function format_ci_sri (line 268) | def format_ci_sri(f):
function format_ci_sli (line 278) | def format_ci_sli(f):
function format_ci_andi (line 287) | def format_ci_andi(f):
function format_ci_lsp (line 297) | def format_ci_lsp(f, numbytes):
function format_cl (line 311) | def format_cl(f, numbytes):
function format_css (line 326) | def format_css(f, numbytes):
function format_cs (line 340) | def format_cs(f, numbytes):
function format_cs_alu (line 355) | def format_cs_alu(f):
function format_ciw (line 365) | def format_ciw(f):
function format_cb (line 374) | def format_cb(f):
function format_cj (line 383) | def format_cj(f):
function insn_lui (line 392) | def insn_lui(insn="lui", misa=0):
function insn_auipc (line 407) | def insn_auipc(insn="auipc", misa=0):
function insn_jal (line 422) | def insn_jal(insn="jal", misa=0):
function insn_jalr (line 439) | def insn_jalr(insn="jalr", misa=0):
function insn_b (line 457) | def insn_b(insn, funct3, expr, misa=0):
function insn_l (line 475) | def insn_l(insn, funct3, numbytes, signext, misa=0):
function insn_s (line 519) | def insn_s(insn, funct3, numbytes, misa=0):
function insn_imm (line 555) | def insn_imm(insn, funct3, expr, wmode=False, misa=0):
function insn_shimm (line 582) | def insn_shimm(insn, funct6, funct3, expr, wmode=False, misa=0):
function insn_alu (line 611) | def insn_alu(insn, funct7, funct3, expr, alt_add=None, alt_sub=None, sha...
function insn_amo (line 656) | def insn_amo(insn, funct5, funct3, expr, misa=MISA_A):
function insn_c_addi4spn (line 705) | def insn_c_addi4spn(insn="c_addi4spn", misa=MISA_C):
function insn_c_l (line 722) | def insn_c_l(insn, funct3, numbytes, signext, misa=MISA_C):
function insn_c_s (line 766) | def insn_c_s(insn, funct3, numbytes, misa=MISA_C):
function insn_c_addi (line 801) | def insn_c_addi(insn="c_addi", wmode=False, misa=MISA_C):
function insn_c_jal (line 825) | def insn_c_jal(insn, funct3, link, misa=MISA_C):
function insn_c_li (line 842) | def insn_c_li(insn="c_li", misa=MISA_C):
function insn_c_addi16sp (line 858) | def insn_c_addi16sp(insn="c_addi16sp", misa=MISA_C):
function insn_c_lui (line 875) | def insn_c_lui(insn="c_lui", misa=MISA_C):
function insn_c_sri (line 891) | def insn_c_sri(insn, funct2, expr, misa=MISA_C):
function insn_c_andi (line 908) | def insn_c_andi(insn="c_andi", misa=MISA_C):
function insn_c_alu (line 925) | def insn_c_alu(insn, funct6, funct2, expr, wmode=False, misa=MISA_C):
function insn_c_b (line 949) | def insn_c_b(insn, funct3, expr, misa=MISA_C):
function insn_c_sli (line 966) | def insn_c_sli(insn, expr, misa=MISA_C):
function insn_c_lsp (line 983) | def insn_c_lsp(insn, funct3, numbytes, signext, misa=MISA_C):
function insn_c_ssp (line 1027) | def insn_c_ssp(insn, funct3, numbytes, misa=MISA_C):
function insn_c_jalr (line 1063) | def insn_c_jalr(insn, funct4, link, misa=MISA_C):
function insn_c_mvadd (line 1082) | def insn_c_mvadd(insn, funct4, add, misa=MISA_C):
function isa_propagate_pair (line 1284) | def isa_propagate_pair(from_isa, to_isa):
function isa_propagate (line 1291) | def isa_propagate(suffix):
FILE: monitor/generate.py
function usage (line 21) | def usage():
function print_rewrite_file (line 601) | def print_rewrite_file(filename):
FILE: tests/coverage/generate.py
function handle_isa (line 3) | def handle_isa(isa):
FILE: tests/semantics/cexformat.py
function usage (line 8) | def usage():
function prvalue (line 58) | def prvalue(name, nbits):
FILE: tests/spike/common.h
function load_uint16 (line 5) | struct mmu_t
function load_uint32 (line 22) | uint32_t load_uint32(uint64_t a) {
function load_uint64 (line 28) | uint64_t load_uint64(uint64_t a) {
function store_uint8 (line 34) | void store_uint8(uint64_t a, uint8_t d) {
function store_uint16 (line 39) | void store_uint16(uint64_t a, uint16_t d) {
function store_uint32 (line 44) | void store_uint32(uint64_t a, uint32_t d) {
function store_uint64 (line 49) | void store_uint64(uint64_t a, uint64_t d) {
function load_int8 (line 54) | int8_t load_int8(uint64_t a) {
function load_int16 (line 58) | int16_t load_int16(uint64_t a) {
function load_int32 (line 62) | int32_t load_int32(uint64_t a) {
function load_int64 (line 66) | int64_t load_int64(uint64_t a) {
type sreg_t (line 73) | typedef int64_t sreg_t;
type reg_t (line 74) | typedef uint64_t reg_t;
type freg_t (line 75) | typedef uint64_t freg_t;
type insn_bits_t (line 115) | typedef uint64_t insn_bits_t;
function class (line 116) | class insn_t
type dcsr_t (line 214) | typedef struct
type state_t (line 265) | struct state_t
Condensed preview — 282 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,247K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 594,
"preview": "name: ci\non:\n push:\n pull_request:\n workflow_dispatch:\n schedule:\n - cron: '30 1 * * *'\n\njobs:\n build:\n runs-"
},
{
"path": ".gitignore",
"chars": 18,
"preview": "/cores/.gitignore\n"
},
{
"path": "COPYING",
"chars": 757,
"preview": "Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n\nPermission to use, copy, modify, and/or distribute this soft"
},
{
"path": "CodeOfConduct",
"chars": 3086,
"preview": "Contributor Covenant Code of Conduct\n\nOur Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\n"
},
{
"path": "README.md",
"chars": 3611,
"preview": "\nRISC-V Formal Verification Framework\n====================================\n\n**This is work in progress. The interfaces d"
},
{
"path": "bus/rvfi_bus_axi4.sv",
"chars": 31993,
"preview": "// RVFI_BUS observer for AXI4 interfaces\n//\n// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>\n//\n// Pe"
},
{
"path": "bus/rvfi_bus_util.sv",
"chars": 2571,
"preview": "// Utility code for RVFI_BUS observers\n//\n// Copyright (C) 2023 Jannis Harder <jix@yosyshq.com> <me@jix.one>\n//\n// Perm"
},
{
"path": "checks/genchecks.py",
"chars": 29670,
"preview": "#!/usr/bin/env python3\n#\n# Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n#\n# Permission to use, copy, modif"
},
{
"path": "checks/rvfi_bus_dmem_check.sv",
"chars": 4051,
"preview": "// external bus: check data reads\n//\n// Note: This only checks the data on the core side, so it is valid even with\n// ca"
},
{
"path": "checks/rvfi_bus_dmem_fault_check.sv",
"chars": 4677,
"preview": "// external bus: check faulting data reads\n//\n// Note: This only checks the data on the core side, so it is valid even w"
},
{
"path": "checks/rvfi_bus_dmem_io_order_check.sv",
"chars": 6463,
"preview": "// external bus: check i/o access ordering\n//\n// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n// Copyright"
},
{
"path": "checks/rvfi_bus_dmem_io_read_check.sv",
"chars": 4311,
"preview": "// external bus: check i/o reads\n//\n// This checks that a retired non-faulting load is contained in a single read\n// tra"
},
{
"path": "checks/rvfi_bus_dmem_io_read_fault_check.sv",
"chars": 3982,
"preview": "// external bus: check i/o read faults\n//\n// This checks that a retired faulting load is contained in a single read\n// t"
},
{
"path": "checks/rvfi_bus_dmem_io_write_check.sv",
"chars": 4349,
"preview": "// external bus: check i/o writes\n//\n// This checks that a retired non-faulting store is contained in a single read\n// t"
},
{
"path": "checks/rvfi_bus_dmem_io_write_fault_check.sv",
"chars": 4314,
"preview": "// external bus: check i/o write faults\n//\n// This checks that a retired faulting store is contained in a single read\n//"
},
{
"path": "checks/rvfi_bus_imem_check.sv",
"chars": 2955,
"preview": "// external bus: check instruction memory reads\n//\n// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n// Copy"
},
{
"path": "checks/rvfi_bus_imem_fault_check.sv",
"chars": 2923,
"preview": "// external bus: check faulting instruction memory reads\n//\n// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com"
},
{
"path": "checks/rvfi_causal_check.sv",
"chars": 2150,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_causal_io_check.sv",
"chars": 2962,
"preview": "// check that no i/o memory accesses are retired in a non-causal order\n//\n// This checks that no i/o memory accesses are"
},
{
"path": "checks/rvfi_causal_mem_check.sv",
"chars": 2952,
"preview": "// check that no memory accesses are retired in a non-causal order\n//\n// This checks that no read of a memory location i"
},
{
"path": "checks/rvfi_channel.sv",
"chars": 3384,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_cover_check.sv",
"chars": 3275,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_csr_ill_check.sv",
"chars": 1776,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_any_check.sv",
"chars": 4049,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_const_check.sv",
"chars": 3266,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_hpm_check.sv",
"chars": 3387,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_inc_check.sv",
"chars": 3609,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_upcnt_check.sv",
"chars": 3348,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrc_zero_check.sv",
"chars": 3422,
"preview": "// Copyright (C) 2023 Krystine Dawn Sherwin <krystinedawn@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or di"
},
{
"path": "checks/rvfi_csrw_check.sv",
"chars": 6612,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_dmem_check.sv",
"chars": 1915,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_fault_check.sv",
"chars": 5170,
"preview": "// check handling of memory faults\n//\n// This checks that a dynamically occuring memory fault causes a trap and that\n// "
},
{
"path": "checks/rvfi_hang_check.sv",
"chars": 1687,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_ill_check.sv",
"chars": 3513,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_imem_check.sv",
"chars": 1858,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_insn_check.sv",
"chars": 8763,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_liveness_check.sv",
"chars": 1563,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_macros.py",
"chars": 17107,
"preview": "#!/usr/bin/env python3\n#\n# Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n#\n# Permission to use, copy, modif"
},
{
"path": "checks/rvfi_macros.vh",
"chars": 780023,
"preview": "// Generated by rvfi_macros.py\n\n`ifdef YOSYS\n`define rvformal_rand_reg rand reg\n`define rvformal_rand_const_reg rand con"
},
{
"path": "checks/rvfi_pc_bwd_check.sv",
"chars": 2214,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_pc_fwd_check.sv",
"chars": 2183,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_reg_check.sv",
"chars": 2598,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_testbench.sv",
"chars": 2932,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "checks/rvfi_unique_check.sv",
"chars": 1574,
"preview": "// Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n//\n// Permission to use, copy, modify, and/or distribute t"
},
{
"path": "cores/VexRiscv/.gitignore",
"chars": 80,
"preview": "cover\ncomplete\n/checks/\n/dmemcheck/\n/imemcheck/\n/picorv32.v\n/disasm.s\n/disasm.o\n"
},
{
"path": "cores/VexRiscv/README.md",
"chars": 1197,
"preview": "\nriscv-formal proofs for VexRiscv\n================================\n\n### Current state:\nTest a simple VexRiscv configurat"
},
{
"path": "cores/VexRiscv/VexRiscv.v",
"chars": 219476,
"preview": "// Generator : SpinalHDL v1.6.4 git head : 598c18959149eb18e5eee5b0aa3eef01ecaa41a1\n// Component : VexRiscv\n// Git ha"
},
{
"path": "cores/VexRiscv/checks.cfg",
"chars": 382,
"preview": "\n[options]\nisa rv32i\n\n[depth]\ninsn 20\nreg 15 30\npc_fwd 10 30\npc_bwd 10 30\nliveness 1 1"
},
{
"path": "cores/VexRiscv/disasm.py",
"chars": 1327,
"preview": "#!/usr/bin/env python3\n\nfrom Verilog_VCD.Verilog_VCD import parse_vcd\nfrom os import system\nfrom sys import argv\n\nrvfi_v"
},
{
"path": "cores/VexRiscv/dmemcheck.sby",
"chars": 344,
"preview": "[options]\nmode bmc\nappend 0\ntbtop testbench.uut\ndepth 22\n\n[engines]\nsmtbmc --presat --unroll boolector\n\n[script]\nread_ve"
},
{
"path": "cores/VexRiscv/dmemcheck.sv",
"chars": 2831,
"preview": "`define RISCV_FORMAL\n`define RISCV_FORMAL_NRET 1\n`define RISCV_FORMAL_XLEN 32\n`define RISCV_FORMAL_ILEN 32\n`define RISCV"
},
{
"path": "cores/VexRiscv/imemcheck.sby",
"chars": 343,
"preview": "[options]\nmode bmc\nappend 0\ntbtop testbench.uut\ndepth 22\n\n[engines]\nsmtbmc --presat --unroll boolector\n\n[script]\nread_ve"
},
{
"path": "cores/VexRiscv/imemcheck.sv",
"chars": 2395,
"preview": "`define RISCV_FORMAL\n`define RISCV_FORMAL_NRET 1\n`define RISCV_FORMAL_XLEN 32\n`define RISCV_FORMAL_ILEN 32\n`include \"rvf"
},
{
"path": "cores/VexRiscv/wrapper.sv",
"chars": 2793,
"preview": "module rvfi_wrapper (\n\tinput clock,\n\tinput reset,\n\t`RVFI_OUTPUTS\n);\n\t(* keep *) wire trap;\n\n\n\t(* keep *)"
},
{
"path": "cores/nerv/.gitignore",
"chars": 106,
"preview": "/checks/\n/cexdata/\n/testbench.vcd\n/firmware.elf\n/firmware.hex\n/disasm.o\n/disasm.s\n/testbench\n/gtkwave.log\n"
},
{
"path": "cores/nerv/COPYING",
"chars": 853,
"preview": "NERV -- Naive Educational RISC-V Processor\n\nCopyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\nCopyright (C) 202"
},
{
"path": "cores/nerv/Makefile",
"chars": 1899,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 N. Engelhardt <nak@yosyshq.com>\n# Copyright (C) "
},
{
"path": "cores/nerv/README.md",
"chars": 1167,
"preview": "NERV - Naive Educational RISC-V Processor\n=========================================\n\nNERV is a very simple single-stage "
},
{
"path": "cores/nerv/axi_cache/.gitignore",
"chars": 95,
"preview": "/SVA-AXI4-FVIP\n/checks_axi\n/checks_internal\n*.vcd\n*.hex\n*.elf\ntestbench_internal\ntestbench_axi\n"
},
{
"path": "cores/nerv/axi_cache/Makefile",
"chars": 3124,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 N. Engelhardt <nak@yosyshq.com>\n# Copyright (C) "
},
{
"path": "cores/nerv/axi_cache/README.md",
"chars": 2455,
"preview": "# Caches for NERV using an AXI interface\n\n\n## Contents\n\n### Cache Implementation\n\nSplit across [`nerv_axi_cache.sv`](./n"
},
{
"path": "cores/nerv/axi_cache/axi_ram.v",
"chars": 13270,
"preview": "// Modified to comment out the timescale directive\n/*\n\nCopyright (c) 2018 Alex Forencich\n\nPermission is hereby granted, "
},
{
"path": "cores/nerv/axi_cache/checks_axi.cfg",
"chars": 2105,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n# Copyrig"
},
{
"path": "cores/nerv/axi_cache/checks_internal.cfg",
"chars": 1535,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n# Copyrig"
},
{
"path": "cores/nerv/axi_cache/firmware.c",
"chars": 1730,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/axi_cache/nerv_axi_cache.sv",
"chars": 32216,
"preview": "// Direct mapped, write-back/write-allocate AXI cache for the NERV core.\n//\n// Copyright (C) 2023 Jannis Harder <jix@yo"
},
{
"path": "cores/nerv/axi_cache/nerv_axi_cache_dcache.sv",
"chars": 8687,
"preview": "// Direct mapped, write-back/write-allocate AXI cache for the NERV core.\n//\n// Copyright (C) 2023 Jannis Harder <jix@yo"
},
{
"path": "cores/nerv/axi_cache/nerv_axi_cache_icache.sv",
"chars": 6763,
"preview": "// Direct mapped, write-back/write-allocate AXI cache for the NERV core.\n//\n// Copyright (C) 2023 Jannis Harder <jix@yo"
},
{
"path": "cores/nerv/axi_cache/testbench_axi.sv",
"chars": 9041,
"preview": "// Testbench using the AXI4 interface\n/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 N. En"
},
{
"path": "cores/nerv/axi_cache/testbench_internal.sv",
"chars": 5638,
"preview": "// Testbench using the internal bus side interface\n/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C"
},
{
"path": "cores/nerv/axi_cache/verify_axi.sby",
"chars": 2488,
"preview": "[tasks]\nprove\ncover\n\n[options]\nprove: mode prove\ncover: mode cover\n\n# The cache's AXI interface is too simple to cover e"
},
{
"path": "cores/nerv/axi_cache/verify_axi.sv",
"chars": 2433,
"preview": "`default_nettype none\n\nmodule resetgen(input wire clock, input wire reset, input wire axi_arvalid, input wire axi_arread"
},
{
"path": "cores/nerv/axi_cache/wrapper_axi.sv",
"chars": 9324,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n * "
},
{
"path": "cores/nerv/axi_cache/wrapper_internal.sv",
"chars": 6736,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n * "
},
{
"path": "cores/nerv/cexdata.sh",
"chars": 1849,
"preview": "#!/bin/bash\n#\n# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.c"
},
{
"path": "cores/nerv/checks.cfg",
"chars": 2122,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n#\n# Permi"
},
{
"path": "cores/nerv/disasm.py",
"chars": 2190,
"preview": "#!/usr/bin/env python3\n#\n# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 Claire Xenia Wolf <clair"
},
{
"path": "cores/nerv/examples/icebreaker/.gitignore",
"chars": 70,
"preview": "/testbench.vcd\n/firmware.elf\n/firmware.hex\n/testbench\n/*.log\n/design.*"
},
{
"path": "cores/nerv/examples/icebreaker/Makefile",
"chars": 2085,
"preview": "# NERV -- Naive Educational RISC-V Processor\n#\n# Copyright (C) 2020 N. Engelhardt <nak@yosyshq.com>\n# Copyright (C) "
},
{
"path": "cores/nerv/examples/icebreaker/README.md",
"chars": 482,
"preview": "# SOC example for iCEBreaker\n\n\n\n# Demo\n\nCounts on the 8 LEDs.\n\n```\nmake prog\n```\n\n#"
},
{
"path": "cores/nerv/examples/icebreaker/firmware.c",
"chars": 1124,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Miodrag Milanovic <miodrag@yosyshq.com>\n *\n"
},
{
"path": "cores/nerv/examples/icebreaker/firmware.s",
"chars": 1917,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/examples/icebreaker/icebreaker.pcf",
"chars": 1498,
"preview": "# 12 MHz clock\nset_io -nowarn CLK 35\n\n# RS232\nset_io -nowarn RX 6\nset_io -nowarn TX 9\n\n# LEDs a"
},
{
"path": "cores/nerv/examples/icebreaker/sections.lds",
"chars": 2395,
"preview": "MEMORY\n{\n FLASH(xr) : ORIGIN = 0x00000000, LENGTH = 0x001000\n RAM (rw) : ORIGIN = 0x00000000, LENGTH "
},
{
"path": "cores/nerv/examples/icebreaker/testbench.gtkw",
"chars": 1226,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.108 (w)1999-2020 BSI\n[*] Tue Nov 3 15:34:10 2020\n[*]\n[dumpfile] \"/home/matt/work/symbioti"
},
{
"path": "cores/nerv/examples/icebreaker/testbench.sv",
"chars": 1441,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 N. Engelhardt <nak@yosyshq.com>\n *\n * Perm"
},
{
"path": "cores/nerv/examples/icebreaker/top.v",
"chars": 1403,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Miodrag Milanovic <miodrag@yosyshq.com>\n *\n"
},
{
"path": "cores/nerv/firmware.c",
"chars": 1047,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/firmware.s",
"chars": 2178,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/imemcheck.sby",
"chars": 532,
"preview": "[options]\nmode prove\ndepth 10\n\n[engines]\nsmtbmc bitwuzla\n\n[script]\nread -sv defines.sv rvfi_imem_check.sv imemcheck.sv n"
},
{
"path": "cores/nerv/imemcheck.sv",
"chars": 2310,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/nerv.sv",
"chars": 48277,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/nervsoc.sv",
"chars": 2339,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/nerv/sections.lds",
"chars": 2505,
"preview": "MEMORY\n{\n /* the memory in the testbench is 64k in size;\n * set LENGTH=48k and leave at least 16k for stack */\n "
},
{
"path": "cores/nerv/testbench.gtkw",
"chars": 3269,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.107 (w)1999-2020 BSI\n[*] Tue Oct 20 19:25:31 2020\n[*]\n[dumpfile] \"/home/claire/Work/riscv-"
},
{
"path": "cores/nerv/testbench.sv",
"chars": 3613,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 N. Engelhardt <nak@yosyshq.com>\n *\n * Perm"
},
{
"path": "cores/nerv/trace.gtkw",
"chars": 3918,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.107 (w)1999-2020 BSI\n[*] Wed Oct 21 17:13:34 2020\n[*]\n[dumpfile] \"(null)\"\n[savefile] \"/hom"
},
{
"path": "cores/nerv/vectors.s",
"chars": 3322,
"preview": "/*\n* Copyright 2019 ETH Zürich and University of Bologna\n*\n* Licensed under the Apache License, Version 2.0 (the \"Licens"
},
{
"path": "cores/nerv/wrapper.sv",
"chars": 3883,
"preview": "/*\n * NERV -- Naive Educational RISC-V Processor\n *\n * Copyright (C) 2020 Claire Xenia Wolf <claire@yosyshq.com>\n *\n "
},
{
"path": "cores/picorv32/.gitignore",
"chars": 239,
"preview": "/cover/\n/complete/\n/honest/\n/checks/\n/testbug[0-9][0-9][0-9].cfg\n/testbug[0-9][0-9][0-9]/\n/testbugs.mk\n/cexdata-[0-9][0-"
},
{
"path": "cores/picorv32/Makefile",
"chars": 357,
"preview": "\npicorv32.v:\n\twget -O picorv32.v https://raw.githubusercontent.com/YosysHQ/picorv32/master/picorv32.v\n\nchecks: picorv32."
},
{
"path": "cores/picorv32/README.md",
"chars": 348,
"preview": "\nriscv-formal proofs for picorv32\n================================\n\nQuickstart guide:\n\nFirst install Yosys, SBY, and the"
},
{
"path": "cores/picorv32/cexdata.sh",
"chars": 938,
"preview": "#!/bin/bash\n\nset -ex\ncexdata=\"cexdata-$(date '+%Y%m%d')\"\n\nrm -rf $cexdata\nmkdir $cexdata\n\nfor x in {checks,testbug[0-9]["
},
{
"path": "cores/picorv32/checks.cfg",
"chars": 766,
"preview": "[options]\nisa rv32imc\n\n[depth]\ninsn 20\nreg 15 25\npc_fwd 10 30\npc_bwd 10 30\nliveness 1 "
},
{
"path": "cores/picorv32/checks.gtkw",
"chars": 1974,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI\n[*] Wed Sep 13 00:29:24 2017\n[*]\n[dumpfile] \"(null)\"\n[savefile] \"/home"
},
{
"path": "cores/picorv32/complete.sby",
"chars": 886,
"preview": "[options]\nmode bmc\naigsmt z3\ndepth 20\n\n[engines]\nabc bmc3\n\n[script]\nverilog_defines -D DEBUGNETS\nverilog_defines -D RISC"
},
{
"path": "cores/picorv32/complete.sv",
"chars": 2223,
"preview": "module testbench (\n\tinput clk,\n\n\tinput mem_ready,\n\toutput mem_valid,\n\toutput mem_instr,\n\toutput [3"
},
{
"path": "cores/picorv32/cover.sby",
"chars": 453,
"preview": "[options]\nmode cover\ndepth 100\n\n[engines]\nsmtbmc boolector\n\n[script]\nverilog_defines -D RISCV_FORMAL\nverilog_defines -D "
},
{
"path": "cores/picorv32/cover.sv",
"chars": 1994,
"preview": "module testbench (\n\tinput clk,\n\n\tinput mem_ready,\n\toutput mem_valid,\n\toutput mem_instr,\n\toutput [3"
},
{
"path": "cores/picorv32/disasm.py",
"chars": 1327,
"preview": "#!/usr/bin/env python3\n\nfrom Verilog_VCD.Verilog_VCD import parse_vcd\nfrom os import system\nfrom sys import argv\n\nrvfi_v"
},
{
"path": "cores/picorv32/dmemcheck.sv",
"chars": 1608,
"preview": "module testbench (\n\tinput clk,\n\n\tinput mem_ready,\n\toutput mem_valid,\n\toutput mem_instr,\n\toutput [3"
},
{
"path": "cores/picorv32/equiv.sh",
"chars": 572,
"preview": "#!/bin/bash\nset -ex\nyosys -p '\n\tread_verilog picorv32.v\n\tchparam -set COMPRESSED_ISA 0 -set BARREL_SHIFTER 1 picorv32\n\tp"
},
{
"path": "cores/picorv32/honest.sby",
"chars": 526,
"preview": "[options]\nmode bmc\naigsmt z3\ndepth 30\n\n[engines]\nabc bmc3\n\n[script]\nverilog_defines -D DEBUGNETS\nverilog_defines -D RISC"
},
{
"path": "cores/picorv32/honest.sv",
"chars": 1289,
"preview": "module testbench (\n\tinput clk,\n\n\tinput mem_ready,\n\toutput mem_valid,\n\toutput mem_instr,\n\toutput [3"
},
{
"path": "cores/picorv32/imemcheck.sv",
"chars": 1372,
"preview": "module testbench (\n\tinput clk,\n\n\tinput mem_ready,\n\toutput mem_valid,\n\toutput mem_instr,\n\toutput [3"
},
{
"path": "cores/picorv32/testbugs.sh",
"chars": 489,
"preview": "#!/bin/bash\n\nset -ex\n\necho \"all: checks\" > testbugs.mk\necho \"checks::\" >> testbugs.mk\necho \"\t\\$(MAKE) -C checks\" >> test"
},
{
"path": "cores/picorv32/wrapper.sv",
"chars": 1554,
"preview": "module rvfi_wrapper (\n\tinput clock,\n\tinput reset,\n\t`RVFI_OUTPUTS\n);\n\t(* keep *) wire trap;\n\n\t(* keep *) "
},
{
"path": "cores/rocket/.gitignore",
"chars": 300,
"preview": "/riscv-tools\n/riscv-tools-build\n/rocket-chip\n/rocket-syn\n/cover\n/coverage\n/checks\n/checks.cfg\n/testbench\n/testbench.v\n/t"
},
{
"path": "cores/rocket/README.md",
"chars": 1203,
"preview": "\nriscv-formal proofs for rocket-chip\n===================================\n\nQuickstart guide:\n\nFirst install Yosys, SymbiY"
},
{
"path": "cores/rocket/cexdata.sh",
"chars": 1921,
"preview": "#!/bin/bash\n\nset -ex\ncexdata=\"cexdata-$(date '+%Y%m%d')\"\n\nrm -rf $cexdata\nmkdir $cexdata\n\nwhile read dir; do echo \"$dir\t"
},
{
"path": "cores/rocket/checks.gtkw",
"chars": 1589,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI\n[*] Tue Sep 12 08:17:07 2017\n[*]\n[dumpfile] \"/home/claire/Work/riscv-f"
},
{
"path": "cores/rocket/cover.gtkw",
"chars": 1510,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.89 (w)1999-2018 BSI\n[*] Wed Mar 28 21:36:23 2018\n[*]\n[dumpfile] \"/home/claire/Work/riscv-f"
},
{
"path": "cores/rocket/cover.sby",
"chars": 724,
"preview": "[options]\nmode cover\ntbtop uut.rocket\ndepth 55\n\n[engines]\nsmtbmc boolector\n\n[script]\nverilog_defines -D RISCV_FORMAL\nver"
},
{
"path": "cores/rocket/cover.sv",
"chars": 3942,
"preview": "module testbench (\n\tinput clk, reset\n);\n\t`RVFI_WIRES\n\n\t`RVFI_CHANNEL(rvfi_ch0, 0)\n\t`RVFI_CHANNEL(rvfi_ch1, 1)\n\n`ifdef YO"
},
{
"path": "cores/rocket/coverage.sby",
"chars": 774,
"preview": "[options]\nmode bmc\ntbtop uut.rocket\ndepth 20\nappend 2\n\n[engines]\nsmtbmc boolector\n\n[script]\nverilog_defines -D RISCV_FOR"
},
{
"path": "cores/rocket/coverage.sv",
"chars": 1940,
"preview": "module testbench (\n\tinput clk, reset\n);\n\t`RVFI_WIRES\n\n\t`RVFI_CHANNEL(rvfi_ch0, 0)\n\t`RVFI_CHANNEL(rvfi_ch1, 1)\n\n`ifdef YO"
},
{
"path": "cores/rocket/decode.sh",
"chars": 372,
"preview": "#!/bin/bash\nriscv=riscv32\ncase \"$1\" in\n\t-a) mopt=\"-M numeric\"; shift;;\n\t-n) mopt=\"-M no-aliases\"; shift;;\n\t-an) mopt=\"\";"
},
{
"path": "cores/rocket/disasm.py",
"chars": 4171,
"preview": "#!/usr/bin/env python3\n\nfrom Verilog_VCD.Verilog_VCD import parse_vcd\nfrom os import system\nfrom sys import argv, exit\nf"
},
{
"path": "cores/rocket/generate.sh",
"chars": 6452,
"preview": "#!/bin/sh\n\nset -ex\n\nexport CONFIG=DefaultConfigWithRVFIMonitors\nexport MAKEFLAGS=\"-j$(nproc)\"\nexport RISCV=$PWD/riscv-to"
},
{
"path": "cores/rocket/muldivlen.py",
"chars": 797,
"preview": "#!/usr/bin/env python3\n\nimport os\nfrom Verilog_VCD.Verilog_VCD import parse_vcd\n\nlines = list()\n\nfor i in range(100):\n "
},
{
"path": "cores/rocket/muldivlen.sby",
"chars": 387,
"preview": "[tasks]\ncheck\ncover\n\n[options]\ncheck: mode bmc\ncover: mode cover\ndepth 100\n\n[engines]\nsmtbmc yices\n\n[script]\nread_verilo"
},
{
"path": "cores/rocket/muldivlen.sv",
"chars": 3744,
"preview": "module muldivlen (\n\tinput clock\n);\n\t// MulDiv inputs\n\t(* keep *) rand reg io_req_valid;\n\t(* keep *) rand co"
},
{
"path": "cores/rocket/rocketrvfi.sv",
"chars": 7141,
"preview": "module RocketTileWithRVFI (\n\tinput clock,\n\tinput reset,\n\t`RVFI_OUTPUTS,\n\n\tinput intsink_sync_0,\n"
},
{
"path": "cores/rocket/testbench.cc",
"chars": 594,
"preview": "#include \"Vtestbench.h\"\n#include \"verilated.h\"\n#include \"verilated_vcd_c.h\"\n\nint timer = 0;\n\ndouble sc_time_stamp()\n{\n\tr"
},
{
"path": "cores/rocket/testbench.sh",
"chars": 1126,
"preview": "#!/bin/bash\n\nset -ex\n\nuse_iverilog=false\ntracetb=insncheck/insn_sw_ch0/engine_0/trace_tb.v\n\negrep -v 'UUT.(core.rvfi_|co"
},
{
"path": "cores/rocket/wrapper.sv",
"chars": 16854,
"preview": "`define XLEN_BYTES (`RISCV_FORMAL_XLEN == 32 ? 4 : 8)\n\nmodule rvfi_wrapper (\n\tinput clock,\n\tinput reset,"
},
{
"path": "cores/serv/.gitignore",
"chars": 67,
"preview": "/checks\n/cover\n/serv-src\n/cexdata\n/cexdata.zip\n/disasm.s\n/disasm.o\n"
},
{
"path": "cores/serv/README.md",
"chars": 462,
"preview": "riscv-formal proofs for SErial RiscV (SERV)\n===========================================\n\nQuickstart guide:\n\nFirst instal"
},
{
"path": "cores/serv/cexdata.sh",
"chars": 1190,
"preview": "#!/bin/bash\n\nset -ex\n\nrm -rf cexdata\nmkdir cexdata\n\nwhile read dir; do echo \"$dir\t$(git -C $dir log -n1 --oneline)\"; \\\n\t"
},
{
"path": "cores/serv/checks.cfg",
"chars": 999,
"preview": "[options]\nisa rv32i\nnret 1\n\n[depth]\ninsn 80\nreg 1 80\npc_fwd 1 80\npc_bwd 1 80\nliveness"
},
{
"path": "cores/serv/cover.gtkw",
"chars": 1066,
"preview": "[*]\n[*] GTKWave Analyzer v3.3.89 (w)1999-2018 BSI\n[*] Thu Nov 1 11:25:45 2018\n[*]\n[timestart] 0\n[size] 1394 830\n[pos] -"
},
{
"path": "cores/serv/cover.sby",
"chars": 1312,
"preview": "[options]\nmode cover\nappend 0\ntbtop wrapper.uut\ndepth 150\n\n[engines]\nsmtbmc boolector\n\n[script]\nread -sv defines.sv \\\n "
},
{
"path": "cores/serv/cover.sv",
"chars": 309,
"preview": "module testbench (\n\tinput clock,\n\tinput reset,\n\t`RVFI_OUTPUTS\n);\n\trvfi_wrapper wrapper (\n\t\t.clock(clock),\n\t\t.reset(reset"
},
{
"path": "cores/serv/disasm.py",
"chars": 1327,
"preview": "#!/usr/bin/env python3\n\nfrom Verilog_VCD.Verilog_VCD import parse_vcd\nfrom os import system\nfrom sys import argv\n\nrvfi_v"
},
{
"path": "cores/serv/generate.sh",
"chars": 119,
"preview": "#!/bin/bash\nset -ex\nrm -rf serv-src\ngit clone git@github.com:olofk/serv.git serv-src\npython3 ../../checks/genchecks.py\n"
},
{
"path": "cores/serv/sbram.sv",
"chars": 14603,
"preview": "// SiliconBlue RAM Cells\n\nmodule SB_RAM40_4K (\n\toutput [15:0] RDATA,\n\tinput RCLK, RCLKE, RE,\n\tinput [10:0] RADD"
},
{
"path": "cores/serv/wrapper.sv",
"chars": 1549,
"preview": "module rvfi_wrapper (\n\tinput clock,\n\tinput reset,\n\t`RVFI_OUTPUTS\n);\n\t// I-MEM\n\t(* keep *) wire [31:0] ibus_adr;\n\t(*"
},
{
"path": "docs/config.md",
"chars": 8766,
"preview": "\nRISCV-FORMAL Configuration Macros\n=================================\n\nThe riscv-formal insn models and checkers are conf"
},
{
"path": "docs/csrs.md",
"chars": 2515,
"preview": "RISC-V Formal CSR Sematics\n==========================\n\nFor the most part the CSR values output via RVFI match exactly th"
},
{
"path": "docs/examplebugs.md",
"chars": 4025,
"preview": "\nExamples of bugs found by riscv-formal\n======================================\n\nThis page lists a few examples of common"
},
{
"path": "docs/procedure.md",
"chars": 28537,
"preview": "\nriscv-formal Verification Procedure\n===================================\n\nThe following formal test are performed to ver"
},
{
"path": "docs/quickstart.md",
"chars": 4050,
"preview": "\nQuick Start Guide\n=================\n\nSo you want to get your hands dirty with riscv-formal? Install the tools and\npick "
},
{
"path": "docs/references.md",
"chars": 1623,
"preview": "\nReferences and related work\n===========================\n\nARM's [ISA-Formal Framework](https://alastairreid.github.io/pa"
},
{
"path": "docs/rvfi.md",
"chars": 20612,
"preview": "\nRISC-V Formal Interface (RVFI)\n==============================\n\nRVFI Specification\n------------------\n\nIn the following "
},
{
"path": "insns/generate.py",
"chars": 65768,
"preview": "#!/usr/bin/env python3\n#\n# Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.com>\n#\n# Permission to use, copy, modif"
},
{
"path": "insns/insn_add.v",
"chars": 2375,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_add (\n input "
},
{
"path": "insns/insn_addi.v",
"chars": 2314,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_addi (\n input "
},
{
"path": "insns/insn_addiw.v",
"chars": 2349,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_addiw (\n input "
},
{
"path": "insns/insn_addw.v",
"chars": 2410,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_addw (\n input "
},
{
"path": "insns/insn_and.v",
"chars": 2375,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_and (\n input "
},
{
"path": "insns/insn_andi.v",
"chars": 2314,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_andi (\n input "
},
{
"path": "insns/insn_auipc.v",
"chars": 2150,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_auipc (\n input "
},
{
"path": "insns/insn_beq.v",
"chars": 2643,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_beq (\n input "
},
{
"path": "insns/insn_bge.v",
"chars": 2661,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_bge (\n input "
},
{
"path": "insns/insn_bgeu.v",
"chars": 2645,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_bgeu (\n input "
},
{
"path": "insns/insn_blt.v",
"chars": 2660,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_blt (\n input "
},
{
"path": "insns/insn_bltu.v",
"chars": 2644,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_bltu (\n input "
},
{
"path": "insns/insn_bne.v",
"chars": 2643,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_bne (\n input "
},
{
"path": "insns/insn_c_add.v",
"chars": 2261,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_add (\n input "
},
{
"path": "insns/insn_c_addi.v",
"chars": 2282,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_addi (\n input "
},
{
"path": "insns/insn_c_addi16sp.v",
"chars": 2389,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_addi16sp (\n input "
},
{
"path": "insns/insn_c_addi4spn.v",
"chars": 2322,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_addi4spn (\n input "
},
{
"path": "insns/insn_c_addiw.v",
"chars": 2341,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_addiw (\n input "
},
{
"path": "insns/insn_c_addw.v",
"chars": 2383,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_addw (\n input "
},
{
"path": "insns/insn_c_and.v",
"chars": 2348,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_and (\n input "
},
{
"path": "insns/insn_c_andi.v",
"chars": 2376,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_andi (\n input "
},
{
"path": "insns/insn_c_beqz.v",
"chars": 2376,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_beqz (\n input "
},
{
"path": "insns/insn_c_bnez.v",
"chars": 2376,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_bnez (\n input "
},
{
"path": "insns/insn_c_j.v",
"chars": 2316,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_j (\n input "
},
{
"path": "insns/insn_c_jal.v",
"chars": 2340,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_jal (\n input "
},
{
"path": "insns/insn_c_jalr.v",
"chars": 2258,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_jalr (\n input "
},
{
"path": "insns/insn_c_jr.v",
"chars": 2234,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_jr (\n input "
},
{
"path": "insns/insn_c_ld.v",
"chars": 3033,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_ld (\n input "
},
{
"path": "insns/insn_c_ldsp.v",
"chars": 3018,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_ldsp (\n input "
},
{
"path": "insns/insn_c_li.v",
"chars": 2251,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_li (\n input "
},
{
"path": "insns/insn_c_lui.v",
"chars": 2312,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_lui (\n input "
},
{
"path": "insns/insn_c_lw.v",
"chars": 3044,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_lw (\n input "
},
{
"path": "insns/insn_c_lwsp.v",
"chars": 3017,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_lwsp (\n input "
},
{
"path": "insns/insn_c_mv.v",
"chars": 2232,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_mv (\n input "
},
{
"path": "insns/insn_c_or.v",
"chars": 2346,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_or (\n input "
},
{
"path": "insns/insn_c_sd.v",
"chars": 2854,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_sd (\n input "
},
{
"path": "insns/insn_c_sdsp.v",
"chars": 2855,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_sdsp (\n input "
},
{
"path": "insns/insn_c_slli.v",
"chars": 2323,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_slli (\n input "
},
{
"path": "insns/insn_c_srai.v",
"chars": 2410,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_srai (\n input "
},
{
"path": "insns/insn_c_srli.v",
"chars": 2400,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_srli (\n input "
},
{
"path": "insns/insn_c_sub.v",
"chars": 2348,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_sub (\n input "
},
{
"path": "insns/insn_c_subw.v",
"chars": 2383,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_subw (\n input "
},
{
"path": "insns/insn_c_sw.v",
"chars": 2865,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_sw (\n input "
},
{
"path": "insns/insn_c_swsp.v",
"chars": 2853,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_swsp (\n input "
},
{
"path": "insns/insn_c_xor.v",
"chars": 2348,
"preview": "// DO NOT EDIT -- auto-generated from riscv-formal/insns/generate.py\n\nmodule rvfi_insn_c_xor (\n input "
}
]
// ... and 82 more files (download for full content)
About this extraction
This page contains the full source code of the cliffordwolf/riscv-formal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 282 files (3.0 MB), approximately 792.1k tokens, and a symbol index with 115 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.