Code Monkey home page Code Monkey logo

sail-riscv's Introduction

RISCV Sail Model

This repository contains a formal specification of the RISC-V architecture, written in Sail. It has been adopted by the RISC-V Foundation. As of 2021-08-24, the repo has been moved from https://github.com/rems-project/sail-riscv to https://github.com/riscv/sail-riscv.

The model specifies assembly language formats of the instructions, the corresponding encoders and decoders, and the instruction semantics. The current status of its coverage of the prose RISC-V specification is summarized here. A reading guide to the model is provided in the doc/ subdirectory, along with a guide on how to extend the model.

Latex or AsciiDoc definitions can be generated from the model that are suitable for inclusion in reference documentation. Drafts of the RISC-V unprivileged and privileged specifications that include the Sail formal definitions are available in the sail branch of this risc-v-isa-manual repository. The process to perform this inclusion is explained here. There is also the newer Sail AsciiDoctor documentation support for RISC-V.

This is one of several formal models that were compared within the 2019 RISC-V ISA Formal Spec Public Review.

What is Sail?

Sail is a language for describing the instruction-set architecture (ISA) semantics of processors: the architectural specification of the behaviour of machine instructions. Sail is an engineer-friendly language, much like earlier vendor pseudocode, but more precisely defined and with tooling to support a wide range of use-cases.

Given a Sail specification, the tool can type-check it, generate documentation snippets (in LaTeX or AsciiDoc), generate executable emulators (in C or OCaml), show specification coverage, generate versions of the ISA for relaxed memory model tools, support automated instruction-sequence test generation, generate theorem-prover definitions for interactive proof (in Isabelle, HOL4, and Coq), support proof about binary code (in Islaris), and (in progress) generate a reference ISA model in SystemVerilog that can be used for formal hardware verification.

Sail is being used for multiple ISA descriptions, including essentially complete versions of the sequential behaviour of Arm-A (automatically derived from the authoritative Arm-internal specification, and released under a BSD Clear licence with Arm's permission), RISC-V, CHERI-RISC-V, CHERIoT, MIPS, and CHERI-MIPS; all these are complete enough to boot various operating systems. There are also Sail models for smaller fragments of IBM POWER and x86, including a version of the ACL2 x86 model automatically translated from that.

Example RISC-V instruction specifications

These are verbatim excerpts from the model file containing the base instructions, riscv_insts_base.sail, with a few comments added.

ITYPE (or ADDI)

/* the assembly abstract syntax tree (AST) clause for the ITYPE instructions */

union clause ast = ITYPE : (bits(12), regbits, regbits, iop)

/* the encode/decode mapping between AST elements and 32-bit words */

mapping encdec_iop : iop <-> bits(3) = {
  RISCV_ADDI  <-> 0b000,
  RISCV_SLTI  <-> 0b010,
  RISCV_SLTIU <-> 0b011,
  RISCV_ANDI  <-> 0b111,
  RISCV_ORI   <-> 0b110,
  RISCV_XORI  <-> 0b100
}

mapping clause encdec = ITYPE(imm, rs1, rd, op) <-> imm @ rs1 @ encdec_iop(op) @ rd @ 0b0010011

/* the execution semantics for the ITYPE instructions */

function clause execute (ITYPE (imm, rs1, rd, op)) = {
  let rs1_val = X(rs1);
  let immext : xlenbits = EXTS(imm);
  let result : xlenbits = match op {
    RISCV_ADDI  => rs1_val + immext,
    RISCV_SLTI  => EXTZ(rs1_val <_s immext),
    RISCV_SLTIU => EXTZ(rs1_val <_u immext),
    RISCV_ANDI  => rs1_val & immext,
    RISCV_ORI   => rs1_val | immext,
    RISCV_XORI  => rs1_val ^ immext
  };
  X(rd) = result;
  true
}

/* the assembly/disassembly mapping between AST elements and strings */

mapping itype_mnemonic : iop <-> string = {
  RISCV_ADDI  <-> "addi",
  RISCV_SLTI  <-> "slti",
  RISCV_SLTIU <-> "sltiu",
  RISCV_XORI  <-> "xori",
  RISCV_ORI   <-> "ori",
  RISCV_ANDI  <-> "andi"
}

mapping clause assembly = ITYPE(imm, rs1, rd, op)
                      <-> itype_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)

SRET

union clause ast = SRET : unit

mapping clause encdec = SRET() <-> 0b0001000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011

function clause execute SRET() = {
  match cur_privilege {
    User       => handle_illegal(),
    Supervisor => if   mstatus.TSR() == true
                  then handle_illegal()
                  else nextPC = handle_exception(cur_privilege, CTL_SRET(), PC),
    Machine    => nextPC = handle_exception(cur_privilege, CTL_SRET(), PC)
  };
  false
}

mapping clause assembly = SRET() <-> "sret"

Sequential execution

The model builds OCaml and C emulators that can execute RISC-V ELF files, and both emulators provide platform support sufficient to boot Linux, FreeBSD and seL4. The OCaml emulator can generate its own platform device-tree description, while the C emulator currently requires a consistent description to be manually provided. The C emulator can be linked against the Spike emulator for execution with per-instruction tandem-verification.

The C emulator, for the Linux boot, currently runs at approximately 300 KIPS on an Intel i7-7700 (when detailed per-instruction tracing is disabled), and there are many opportunities for future optimisation (the Sail MIPS model runs at approximately 1 MIPS). This enables one to boot Linux in about 4 minutes, and FreeBSD in about 2 minutes. Memory usage for the C emulator when booting Linux is approximately 140MB.

The files in the OCaml and C emulator directories implement ELF loading and the platform devices, define the physical memory map, and use command-line options to select implementation-specific ISA choices.

Use for specification coverage measurement in testing

The Sail-generated C emulator can measure specification branch coverage of any executed tests, displaying the results as per-file tables and as html-annotated versions of the model source.

Use as test oracle in tandem verification

For tandem verification of random instruction streams, the tools support the protocols used in TestRIG to directly inject instructions into the C emulator and produce trace information in RVFI format. This has been used for cross testing against spike and the RVBS specification written in Bluespec SystemVerilog.

The C emulator can also be directly linked to Spike, which provides tandem-verification on ELF binaries (including OS boots). This is often useful in debugging OS boot issues in the model when the boot is known working on Spike. It is also useful to detect platform-specific implementation choices in Spike that are not mandated by the ISA specification.

Concurrent execution

The ISA model is integrated with the operational model of the RISC-V relaxed memory model, RVWMO (as described in an appendix of the RISC-V user-level specification), which is one of the reference models used in the development of the RISC-V concurrency architecture; this is part of the RMEM tool. It is also integrated with the RISC-V axiomatic concurrency model as part of the isla-axiomatic tool.

Concurrent testing

As part of the University of Cambridge/ INRIA concurrency architecture work, those groups produced and released a library of approximately 7000 litmus tests. The operational and axiomatic RISC-V concurrency models are in sync for these tests, and they moreover agree with the corresponding ARM architected behaviour for the tests in common.

Those tests have also been run on RISC-V hardware, on a SiFive RISC-V FU540 multicore proto board (Freedom Unleashed), kindly on loan from Imperas. To date, only sequentially consistent behaviour was observed there.

Use in test generation

The Sail OCaml backend can produce QuickCheck-style random generators for types in Sail specifications, which have been used to produce random instructions sequences for testing. The generation of individual types can be overridden by the developer to, for example, remove implementation-specific instructions or introduce register biasing.

Generating theorem-prover definitions

Sail aims to support the generation of idiomatic theorem prover definitions across multiple tools. At present it supports Isabelle, HOL4 and Coq, and the prover_snapshots directory provides snapshots of the generated theorem prover definitions.

These theorem-prover translations can target multiple monads for different purposes. The first is a state monad with nondeterminism and exceptions, suitable for reasoning in a sequential setting, assuming that effectful expressions are executed without interruptions and with exclusive access to the state.

For reasoning about concurrency, where instructions execute out-of-order, speculatively, and non-atomically, there is a free monad over an effect datatype of memory actions. This monad is also used as part of the aforementioned concurrency support via the RMEM tool.

The files under handwritten_support provide library definitions for Coq, Isabelle and HOL4.

Directory Structure

sail-riscv
- model                   // Sail specification modules
- generated_definitions   // files generated by Sail, in RV32 and RV64 subdirectories
  -  c
  -  ocaml
  -  lem
  -  isabelle
  -  coq
  -  hol4
  -  latex
- prover_snapshots        // snapshots of generated theorem prover definitions
- handwritten_support     // prover support files
- c_emulator              // supporting platform files for C emulator
- ocaml_emulator          // supporting platform files for OCaml emulator
- doc                     // documentation, including a reading guide
- test                    // test files
  - riscv-tests           // snapshot of tests from the riscv/riscv-tests github repo
- os-boot                 // information and sample files for booting OS images

Getting started

Building the model

Install Sail using opam then:

$ make

will build the 64-bit OCaml simulator in ocaml_emulator/riscv_ocaml_sim_RV64 and the C simulator in c_emulator/riscv_sim_RV64.

One can build either the RV32 or the RV64 model by specifying ARCH=RV32 or ARCH=RV64 on the make line, and using the matching target suffix. RV64 is built by default, but the RV32 model can be built using:

$ ARCH=RV32 make

which creates the 32-bit OCaml simulator in ocaml_emulator/riscv_ocaml_sim_RV32 and the C simulator in c_emulator/riscv_sim_RV32.

The Makefile targets riscv_isa_build, riscv_coq_build, and riscv_hol_build invoke the respective prover to process the definitions and produce the Isabelle model in generated_definitions/isabelle/RV64/Riscv.thy, the Coq model in generated_definitions/coq/RV64/riscv.v, or the HOL4 model in generated_definitions/hol4/RV64/riscvScript.sml respectively. We have tested Isabelle 2018, Coq 8.8.1, and HOL4 Kananaskis-12. When building these targets, please make sure the corresponding prover libraries in the Sail directory ($SAIL_DIR/lib/$prover) are up-to-date and built, e.g. by running make in those directories.

Executing test binaries

The C and OCaml simulators can be used to execute small test binaries. The OCaml simulator depends on the Device Tree Compiler package, which can be installed in Ubuntu with:

$ sudo apt-get install device-tree-compiler

Then, you can run test binaries:

$ ./ocaml_emulator/riscv_ocaml_sim_<arch>  <elf-file>
$ ./c_emulator/riscv_sim_<arch> <elf-file>

A suite of RV32 and RV64 test programs derived from the riscv-tests test-suite is included under test/riscv-tests/. The test-suite can be run using test/run_tests.sh.

Configuring platform options

Some information on additional configuration options for each simulator is available from ./ocaml_emulator/riscv_ocaml_sim_<arch> -h and ./c_emulator/riscv_sim_<arch> -h.

Some useful options are: configuring whether misaligned accesses trap (--enable-misaligned for C and -enable-misaligned for OCaml), and whether page-table walks update PTE bits (--enable-dirty-update for C and -enable-dirty-update for OCaml).

Experimental integration with riscv-config

There is also (as yet unmerged) support for integration with riscv-config to allow configuring the compiled model according to a riscv-config yaml specification.

Booting OS images

For booting operating system images, see the information under the os-boot/ subdirectory.

Using development versions of Sail

Rarely, the version of Sail packaged in opam may not meet your needs. This could happen if you need a bug fix or new feature not yet in the released Sail version, or you are actively working on Sail. In this case you can tell the sail-riscv Makefile to use a local copy of Sail by setting SAIL_DIR to the root of a checkout of the Sail repo when you invoke make. Alternatively, you can use opam pin to install Sail from a local checkout of the Sail repo as described in the Sail installation instructions.

Licence

The model is made available under the BSD two-clause licence in LICENCE.

Authors

Prashanth Mundkur, SRI International; Rishiyur S. Nikhil (Bluespec Inc.); Jon French, University of Cambridge; Brian Campbell, University of Edinburgh; Robert Norton-Wright, University of Cambridge and Microsoft; Alasdair Armstrong, University of Cambridge; Thomas Bauereiss, University of Cambridge; Shaked Flur, University of Cambridge; Christopher Pulte, University of Cambridge; Peter Sewell, University of Cambridge; Alexander Richardson, University of Cambridge; Hesham Almatary, University of Cambridge; Jessica Clarke, University of Cambridge; Nathaniel Wesley Filardo, Microsoft; Peter Rugg, University of Cambridge; Scott Johnson, Aril Computer Corp.

Funding

This software was developed by the above within the Rigorous Engineering of Mainstream Systems (REMS) project, partly funded by EPSRC grant EP/K008528/1, at the Universities of Cambridge and Edinburgh.

This software was developed by SRI International and the University of Cambridge Computer Laboratory (Department of Computer Science and Technology) under DARPA/AFRL contract FA8650-18-C-7809 ("CIFV"), and under DARPA contract HR0011-18-C-0016 ("ECATS") as part of the DARPA SSITH research programme.

This project has received funding from the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement 789108, ELVER).

sail-riscv's People

Contributors

alasdair avatar arichardson avatar bacam avatar bauereiss avatar ben-marshall avatar bilalsakhawat avatar billmcspadden-riscv avatar cp526 avatar fshaked avatar heshamelmatary avatar janweinstock avatar jordancarlin avatar jrtc27 avatar kotorinminami avatar martinberger avatar nwf avatar nwf-msr avatar ojno avatar peterrugg avatar petersewell avatar pmundkur avatar ptomsich avatar rmn30 avatar ronorton avatar rsnikhil avatar scottj97 avatar thinkopenly avatar timmmm avatar ved-rivos avatar xinlaiwan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sail-riscv's Issues

Random test generation

Hello all,
According to the Readme, Sail can be used for random test generation. But I cannot find how to do so.

state monad in sail-riscv coq definition

Hi
This is a great job for ISA semantics!
I successfully compiled the coq model with the prompt_monad, which can be used for concurrent semantics.

  1. I want to ask that has the state monad mentioned in your POPL 2019 paper been tested in risc-v model yet?

  2. Another question is that how to define the effect of instructions of monad, like defining the effect of "Read_reg", "Write_reg", etc. Although it has a register accessor defined in riscv-type.v, it has been used yet.

Get error messages from c_emulator?

I'm running test cases randomly generated by Google's riscv-dv on the sail-riscv c_emulator model.

It runs a few thousand instructions and then dies:

[2399] [M]: 0x00000000800016BC (0x1D73222F) sc.w.aq tp, t1, s7
Sail exception!Exiting due to uncaught exception

How can I tell what this "uncaught exception" is referring to? I can't find anything in the c_emulator/* that would tell me anything more than have_exception.

When I run the same code on the ocaml emulator, I see:

[2399] [M]: 0x00000000800016BC (0x1D73222F) sc.w.aq tp, t1, s7
reservation: 0x000000008001E000, key=0x000000008001E000

Error: Not implemented: sc.aq

Which is a nice clear error message.

How can I find that same message when running the C model?

I see this struct zexception in the generated C code, but I'm not sure how I can access that struct from within riscv_sim.c. That struct is not defined in any header file, and since riscv_sim.c is compiled separately, it can't see it.

CSRW to FCSR should set mstatus.FS=Dirty

The mstatus.FS field should be set to Dirty whenever floating-point state is written.

I've observed that csrwi fscr,0 does not update mstatus.FS, leaving it set to Initial, the value it previously contained. Spike sets FS=Dirty as expected on this operation.

I haven't tried any other floating point operations yet, and I can't find where in the model code it ever updates FS to Dirty, so perhaps they are all missing this functionality?

cc @rsnikhil

Build fails on all Archs

I am getting the following error on the current sail-riscv version
(I added SAIL_FLAGS += -dsmt_verbose to the Makefile):

$ make
mkdir -p generated_definitions/ocaml/RV64
sail -dno_cast -dsmt_verbose -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV64 -o riscv model/prelude.sail model/prelude_mapping.sail model/riscv_xlen64.sail model/riscv_flen_D.sail model/prelude_mem_metadata.sail model/prelude_mem.sail model/riscv_types_common.sail model/riscv_types_ext.sail model/riscv_types.sail model/riscv_vmem_types.sail model/riscv_reg_type.sail model/riscv_freg_type.sail model/riscv_regs.sail model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_pmp_regs.sail model/riscv_pmp_control.sail model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_misa_ext.sail model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail model/riscv_next_control.sail model/riscv_fdext_regs.sail model/riscv_fdext_control.sail model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_pte.sail model/riscv_ptw.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv39.sail model/riscv_vmem_sv48.sail model/riscv_vmem_rv64.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail model/riscv_insts_next.sail model/riscv_softfloat_interface.sail model/riscv_insts_fext.sail model/riscv_insts_dext.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail model/riscv_step.sail model/riscv_analysis.sail
Prove (type_check.ml/2207) |- ((not(not('n == 'm)) | 'n != 'm) & (not('n != 'm) | not('n == 'm)))
SMTLIB2 constraints are:
(push)
(declare-const v0 Int)
(declare-const v1 Int)
(define-fun constraint () Bool (not (and (or (not (not (= v1 v0))) (not (= v1 v0))) (or (not (not (= v1 v0))) (not (= v1 v0))))))
(assert constraint)
(check-sat)
(pop)

Error:
Error when calling smt: Reporting.Fatal_error(_)
make: *** [generated_definitions/ocaml/RV64/riscv.ml] Error 1

==================
I have seen a reference to such an eror before but it seems that this is a source problem which has not been resolved. This happens on RV32 and RV64 on both emulators. It happens on WSL (Ubuntu 18.04) and on RH6.

Illegal Instruction Fault on executing D extension instructions on a rv32 machine.

On executing an instruction from the D extension in the rv32 model an illegal instruction fault is raised. The misa reset value for a rv32 machine is 0x40141105. This indicates that the D extension is disabled whereas the reset value should be 0x4014110D. The model encounters an illegal instruction fault even after setting the misa to the correct value.

compressed hints treated as illegal ops instead of nops

According to the isa manual the operation: c.add zero, ra is a hint operation and effectively should be treated as nop. However, SAIL seems to interpret this as an illegal instruction.

Following is the log using the C emulator:

mem[X,0x800001EC] -> 0x9006                                                                                
[168] [M]: 0x800001EC (0x9006) c.illegal 36870                                                             
trapping from M to M to handle illegal-instruction                                                         
handling exc#0x02 at priv M with tval 0x00000000                                                           
CSR mstatus <- 0x00001800  

Other hints like c.nop 0 also are interpreted as illegal instructions.

CSRs that "should not exist" not handled well

The written spec states for example "In systems with only M-mode, or with both M-mode and U-mode but without U-mode trap support, the medeleg and mideleg registers should not exist." which does not seem to be reflected in Sail. Same for sedeleg/sideleg without N extension. And similarly, a clause has been recently added that mcounteren should not exist in M mode only systems.
Finally, is_CSR_defined for the user mode counters seems to be off - it require p==User where I would expect haveUsrMode() as M or S mode can access the user mode counters (if user mode exists).

Feature wishlist

This issue stores ideas for new features for the RISCV model that have been discussed, deemed desirable, but nobody has yet volunteered to supply them. If you have a new idea, suggest it in a separate issue / PR first.

  1. More could be done to improve use of Docker e.g.:

    • Document use of the Dockerfile to build the model. It is partially documented in the above commit message but needs a proper README
    • Add a Dockerfile that builds the model too
    • Integrate with github actions / CI
    • Push built images to Dockerhub

    This would benefit from somebody with a lot of experience in Docker. See

AMOMAX[U].W/AMOMIN[U].W on RV64 differ from Spike

The 32-bit AMOMAX.W, AMOMAXU.W, AMOMIN.W, and AMOMINU.W instructions load 32 bits from memory, do a comparison of the loaded value against a register value, then write the max or min value back to memory.

It seems that the Sail model is comparing the 64-bit sign-extended loaded value against the 64-bit register, whereas Spike is comparing only against the low 32 bits of the register.

The result is a mismatch when the 64-bit source register is e.g. 0x00000000_80000000. Spike is interpreting this as a negative 32-bit number, but Sail sees it as a positive value.

One specific case for signed mismatch:
loaded memory value is 0x00000000
rs2_val is 0x00000000_80031CF8
AMOMIN.W executes:
Sail writes to memory 0x00000000
Spike writes to memory 0x80031CF8

A specific case for unsigned mismatch:
loaded memory value is 0x00001000
rs2_val is 0x00001000_00000000
AMOMINU.W executes:
Sail writes to memory 0x00001000
Spike writes to memory 0x00000000

From my reading of the RISC-V spec (Unprivileged ISA version 20190608-Base-Ratified), the expected behavior is not clear. I think a reasonable argument can be made for either interpretation.

FMAX writes incorrect value when rs1=QNaN rs2=SNaN

The spec for FMAX says "If both inputs are NaNs, the result is the canonical NaN."

The source code has:

  let rd_val_D  = if      (f_is_SNaN_D(rs1_val_D) & f_is_SNaN_D(rs2_val_D))         then canonical_NaN_D()
                  else if f_is_SNaN_D(rs1_val_D)                                    then rs2_val_D
                  else if f_is_SNaN_D(rs2_val_D)                                    then rs1_val_D
                  else if (f_is_QNaN_D(rs1_val_D) & f_is_QNaN_D(rs2_val_D))         then canonical_NaN_D()
                  else if f_is_QNaN_D(rs1_val_D)                                    then rs2_val_D
                  else if f_is_QNaN_D(rs2_val_D)                                    then rs1_val_D
                  else if (f_is_neg_zero_D(rs1_val_D) & f_is_pos_zero_D(rs2_val_D)) then rs2_val_D
                  else if (f_is_neg_zero_D(rs2_val_D) & f_is_pos_zero_D(rs1_val_D)) then rs1_val_D
                  else if rs2_lt_rs1                                                then rs1_val_D
                  else /* (not rs2_lt_rs1) */                                            rs2_val_D;

In the case where one operand is SNaN and the other is QNaN, line 2 or 3 will match, returning rs1 or rs2 when it should return canonical NaN.

The same issue appears four times in the source code:

Build error

After installing sail, I ran make from top-level sail-riscv directory. It failed fairly quickly with an SMT-related error:

mkdir -p generated_definitions/ocaml/RV64
sail  -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV64 -o riscv model/prelude.sail model/prelude_mapping.sail model/riscv_xlen64.sail model/prelude_mem_metadata.sail model/prelude_mem.sail model/riscv_types.sail model/riscv_reg_type.sail model/riscv_regs.sail model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail model/riscv_next_control.sail model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv39.sail model/riscv_vmem_sv48.sail model/riscv_vmem_rv64.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail model/riscv_insts_next.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail model/riscv_step.sail model/riscv_analysis.sail
Error:
Error when calling smt: Reporting.Fatal_error(_)
Makefile:147: recipe for target 'generated_definitions/ocaml/RV64/riscv.ml' failed
make: *** [generated_definitions/ocaml/RV64/riscv.ml] Error 1

The error above is with ocaml 4.06.1. I also tried 4.07.1, and got this similar but slightly different error:

mkdir -p generated_definitions/ocaml/RV64
sail  -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV64 -o riscv model/prelude.sail model/prelude_mapping.sail model/riscv_xlen64.sail model/prelude_mem_metadata.sail model/prelude_mem.sail model/riscv_types.sail model/riscv_reg_type.sail model/riscv_regs.sail model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail model/riscv_next_control.sail model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv39.sail model/riscv_vmem_sv48.sail model/riscv_vmem_rv64.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail model/riscv_insts_next.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail model/riscv_step.sail model/riscv_analysis.sail
Error:
SMT solver returned unexpected status 110
Makefile:147: recipe for target 'generated_definitions/ocaml/RV64/riscv.ml' failed
make: *** [generated_definitions/ocaml/RV64/riscv.ml] Error 1

Googling the error didn't turn up anything - any help would be appreciated. I'm building on Ubuntu 18.04 under WSL.

trace shows incorrect value for frm/fflags

When I do a CSRW instruction to frm or fflags, which are sub-fields of the fcsr register, the trace shows the new fcsr value but reports it as the new value of frm or fflags.

For example if fflags is 2 and I do a CSRW to frm to write a value of 4, the new fcsr value is 0x82, but the trace reports that frm is now 0x82.

The patch pasted below will fix this, but I wonder if this is the best way.

Since these two subsets of fcsr can be accessed separately, would it be better to model them as two separate registers, instead of as bitfields within fcsr?

I think that would simplify many things in the code, and I also prefer that the same bits always show up in the trace under the same name. I find it confusing that sometimes fcsr is updated, and other times fflags is updated, when they refer to the same bits.

Though splitting it into two would have the complication that a single CSRW to fcsr would write two different registers and require two calls to print_reg(), which doesn't fit nicely in function writeCSR today.

If you think this patch is the best way I will submit it as a PR.

diff --git a/model/riscv_fdext_control.sail b/model/riscv_fdext_control.sail
index 7155699..ac3169f 100644
--- a/model/riscv_fdext_control.sail
+++ b/model/riscv_fdext_control.sail
@@ -17,8 +17,8 @@ function clause ext_read_CSR (0x001) = Some (EXTZ (fcsr.FFLAGS()))
 function clause ext_read_CSR (0x002) = Some (EXTZ (fcsr.FRM()))
 function clause ext_read_CSR (0x003) = Some (EXTZ (fcsr.bits()))
 
-function clause ext_write_CSR (0x001, value) = write_fcsr (fcsr.FRM(), value [4..0])
-function clause ext_write_CSR (0x002, value) = write_fcsr (value [2..0], fcsr.FFLAGS())
-function clause ext_write_CSR (0x003, value) = write_fcsr (value [7..5], value [4..0])
+function clause ext_write_CSR (0x001, value) = { write_fcsr (fcsr.FRM(), value [4..0]); Some(EXTZ(fcsr.FFLAGS())) }
+function clause ext_write_CSR (0x002, value) = { write_fcsr (value [2..0], fcsr.FFLAGS()); Some(EXTZ(fcsr.FRM())) }
+function clause ext_write_CSR (0x003, value) = { write_fcsr (value [7..5], value [4..0]); Some(EXTZ(fcsr.bits())) }
 
 /* **************************************************************** */
diff --git a/model/riscv_fdext_regs.sail b/model/riscv_fdext_regs.sail
index 59efd22..b746803 100644
--- a/model/riscv_fdext_regs.sail
+++ b/model/riscv_fdext_regs.sail
@@ -273,12 +273,11 @@ bitfield Fcsr : bits(32) = {
 
 register fcsr : Fcsr
 
-val write_fcsr : (bits(3), bits(5)) -> option(xlenbits) effect {rreg, wreg}
+val write_fcsr : (bits(3), bits(5)) -> unit effect {rreg, wreg}
 function write_fcsr (frm, fflags) = {
   fcsr->FRM()    = frm;      /* Note: frm can be an illegal value, 101, 110, 111 */
   fcsr->FFLAGS() = fflags;
   dirty_fd_context();
-  Some (EXTZ (fcsr.bits()))
 }
 
 val write_fflags : (bits(5)) -> unit effect {rreg, wreg}

Improved docker support requested

More could be done to improve use of Docker e.g.:

  • Document use of the Dockerfile to build the model. It is partially documented in the above commit message but needs a proper README
  • Add a Dockerfile that builds the model too
  • Integrate with github actions / CI
  • Push built images to Dockerhub

This would benefit from somebody with a lot of experience in Docker. See

Page table extension state not updated during walk?

The ext_ptw tokens that get passed around the PTW machinery appear not to be updated as the walk functions do their thing.

Specifically, the initial ext_ptw state is constructed at
https://github.com/rems-project/sail-riscv/blob/38f52c99289e31aef72a4272e1a46b7a3398e076/model/riscv_vmem_rv64.sail#L47 (or at https://github.com/rems-project/sail-riscv/blob/38f52c99289e31aef72a4272e1a46b7a3398e076/model/riscv_vmem_rv32.sail#L40) and is passed down to translateNN a few lines later.

Focusing on Sv39 by way of example, we see that translate39 either takes this initial value and allows checkPTEPermission to filter it in the case of a TLB hit ...
https://github.com/rems-project/sail-riscv/blob/392dba44738d9c4702ef822a44772b73099b0d92/model/riscv_vmem_sv39.sail#L120-L122
... or passes it to walk39 for filtering in the case of a TLB miss ...
https://github.com/rems-project/sail-riscv/blob/392dba44738d9c4702ef822a44772b73099b0d92/model/riscv_vmem_sv39.sail#L149-L151

So far so good. However, internally, walk39 simply punts its given ext_ptw token downwards. At the time of its recursive call ...
https://github.com/rems-project/sail-riscv/blob/392dba44738d9c4702ef822a44772b73099b0d92/model/riscv_vmem_sv39.sail#L36
... ext_ptw is simply that of its argument. Therefore, when walk39 reaches its leaf call to checkPTEPermissions ...
https://github.com/rems-project/sail-riscv/blob/392dba44738d9c4702ef822a44772b73099b0d92/model/riscv_vmem_sv39.sail#L43
... ext_ptw is simply the initial state.

I think the thing to do is to make isPTEPtr have type (pteAttribs, extPte, ext_ptw) -> option(ext_ptw), so that it can mutate the state at internal nodes of the tree. Does that seem right?

Cannot build sail-riscv

Hi All,
I am trying to run the riscv sail model against the riscv-compliance suite, but cannot build the simulator - I am on Ubuntu
I have installed ocaml
ocaml -version
The OCaml toplevel, version 4.06.1

I have sail - doesn't seem to take a version flag, but I get the following
sail -version
sail: unknown option '-version'.
Sail 0.10 (sail2 @ opam)
usage: sail <file1.sail> ... <fileN.sail>

I have cloned the master branch - is there a release branch that should be used ?
git clone https://github.com/rems-project/sail-riscv.git

when I attempt to run make as per the instructions I get the following

ARCH=RV32 make
mkdir -p generated_definitions/ocaml/RV32
/home/moore/.opam/4.06.1/bin/sail -dno_cast -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV32 -o riscv model/prelude.sail model/prelude_mapping.sail model/riscv_xlen32.sail model/riscv_flen_F.sail model/prelude_mem_metadata.sail model/prelude_mem.sail model/riscv_types_common.sail model/riscv_types_ext.sail model/riscv_types.sail model/riscv_vmem_types.sail model/riscv_reg_type.sail model/riscv_freg_type.sail model/riscv_regs.sail model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_pmp_regs.sail model/riscv_pmp_control.sail model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_misa_ext.sail model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail model/riscv_next_control.sail model/riscv_softfloat_interface.sail model/riscv_fdext_regs.sail model/riscv_fdext_control.sail model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_pte.sail model/riscv_ptw.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv32.sail model/riscv_vmem_rv32.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail model/riscv_insts_next.sail model/riscv_insts_fext.sail model/riscv_insts_cfext.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail model/riscv_step.sail
Syntax error:
[model/riscv_insts_begin.sail]:15:30-30
15 |val encdec : ast <-> bits(32) effect {rreg}
| ^
| current token: effect
make: *** [Makefile:189: generated_definitions/ocaml/RV32/riscv.ml] Error 1

hmm, where did I do wrong ?

Thx
Lee

C.ADDI disassembly inaccurate when immediate value is negative

The opcode 0x1541 should decode into c.addi x10, -16 (according to Spike). Sail is reporting it as c.addi x10, 48.

It seems to execute correctly; if x10 is 0, it gets written with 0xffffffff_fffffff0. It's only the immediate value shown in the disassembly that looks incorrect.

RVFI-supporting emulator no longer works with ELF test files

Hello,

I was working with the C emulator that supports the RVFI-DII format (as generated for TestRIG in its Makefile), and I noticed that it no longer works the same way with the provided ELF test files in test/riscv-tests.

For example, if I pass rv32ui-p-add.elf to the standard C emulator (just produced by running ARCH=32 make), the test passes. However, if I pass this same test file to the emulator extended with support for RVFI instruction streams, I get infinite faults of the form:

...

[7907] [M]: 0x00000000 (0x0000) c.illegal 0
trapping from M to M to handle illegal-instruction
handling exc#0x02 at priv M with tval 0x00000000
CSR mstatus <- 0x00001800


[7908] [M]: 0x00000000 (0x0000) c.illegal 0
trapping from M to M to handle illegal-instruction
handling exc#0x02 at priv M with tval 0x00000000
CSR mstatus <- 0x00001800

...

I was wondering whether the 'extended' emulator is only designed to deal with RVFI streams, or whether it is supposed to be able to deal with ELF files as well, just like the standard one.

FENCE instructions should ignore rs1/rd and address fm=2..15 to same as fm=0

The sail-riscv model seems like it expects the rs1/rd fields to be zeros and only defines instruction variants for the FENCE instruction with fm = 0 and fm = 1 (TSO).

From the ISA manual volume I, section 2.7 on Memory Ordering Instructions states:

"The unused fields in the FENCE instructions—rs1 and rd—are reserved for finer-grain fences in future extensions. For forward compatibility, base implementations shall ignore these fields, and standard software shall zero these fields. Likewise, many fm and predecessor/successor set settings
in Table 2.2 are also reserved for future use. Base implementations shall treat all such reserved configurations as normal fences with fm=0000, and standard software shall use only non-reserved
configurations"

These sound more like software restrictions on how the reserved field should be used but the sail model should ignore rs1/rd fields. Likewise fm=2..15 should be the same as fm=0

Instruction fetch erroneously affected by mstatus.MPRV

The mstatus.MPRV bit affects the effective privilege level of loads and stores. According to priv spec section 3.1.6.3 "Memory Privilege in mstatus Register":

The MPRV (Modify PRiVilege) bit modi es the privilege level at which loads and stores execute in all privilege modes. When MPRV=0, loads and stores behave as normal, using the translation and protection mechanisms of the current privilege mode. When MPRV=1, load and store memory addresses are translated and protected as though the current privilege mode were set to MPP. Instruction address-translation and protection are unaffected by the setting of MPRV.

But the Sail model seems to apply the modified privilege even to instruction fetch.

I believe the problem is in pmp_mem_read, where the pmpCheck() privilege level is specified. It should consider fetches differently than loads. Something like this already exists in riscv_vmem_rv32.sail:

  let effPriv : Privilege = match ac {
    Execute() => cur_privilege,
    _         => effectivePrivilege(mstatus, cur_privilege)
  };

Overflow when comparing addresses in riscv_platform.sail

(As discussed with @rmn30, found using TestRIG)

Some of the within... functions, e.g. within_phys_mem, have an overflow issue when accessing addresses very near the top of the address space.

Here is a check inside within_phys_mem:
if ( ram_base <=_u ext_addr & (ext_addr + sizeof('n)) <=_u (ram_base + ram_size))

Here, if ext_addr is 0xffff_ffff (assuming 32 bit memory addresses), and sizeof ('n) is (e.g.) 1, this access will show as being within physical memory regardless of the values of ram_base and ram_size, since in all cases ram_base <=_u 0xffff_ffff, and 0xffff_ffff + 1 = 0 <=_u ram_base + ram_size due to overflow.

Fix should be straightforward (e.g. also check if ext_addr + sizeof('n) >= ext_addr), but I'm not sure in how many places this is an issue. It seems to also be a problem in within_clint.

Cannot build sail-riscv

Hello all,
It seems that I cannot build Sail-RISCV.

make: /home/oyounis/.opam/default/lib/sail/sail: Command not found
make: *** [Makefile:191: generated_definitions/ocaml/RV32/riscv.ml] Error 127

I guess the problem is that I cannot set the SAIL_DIR variable to the right directory:

export SAIL_DIR=/home/oyounis/.opam/default/lib/sail
ARCH=RV32 make

AMO disassembly differs from Spike

The way Sail displays the operands in an AMO is inconsistent with Spike's disassembler. Here's one from Sail:

[882] [M]: 0x0000000080000620 (0xA514252F) amomax.w.aq a0, fp, a7

The same opcode from Spike displays as:

amomax.w a0, a7, (fp)

The 2nd and 3rd operands are reversed. It's especially confusing because the operand referring to the memory address is not shown in parentheses as other instructions do.

Bad disassembly for RVC HINTs

RVC HINTs are disassembled with names like c.nop.hint.<imm> rather than the mnemonics used by actual (dis)assemblers (which are generally just whatever the non-HINT version would be in the case of using a zero register, but some exceptions for things like c.nop, which ends up taking an additional immediate argument when non-zero, and c.s{ll,rl,ra}i with a zero immediate, which end up being the strange c.s{ll,rl,ra}i64 with no immediate).

See discussion in #31.

PMP locking must forbid pmpaddr writes when next entry is TOR

The privileged spec (version 20190608-Priv-MSU-Ratified) section 3.6.1 ("Physical Memory Protection CSRs") under "Locking and Privilege Mode" says:

If PMP entry i is locked, writes to pmpicfg and pmpaddri are ignored. Additionally, if pmpicfg.A is set to TOR, writes to pmpaddri-1 are ignored.

In riscv_pmp_regs.sail I see the pmpaddr locking implemented like so:

function pmpWriteAddr(cfg: Pmpcfg_ent, reg: xlenbits, v: xlenbits) -> xlenbits =
  if   sizeof(xlen) == 32
  then { if cfg.L() == 0b1 then reg else v }
  else { if cfg.L() == 0b1 then reg else EXTZ(v[53..0]) }

This does not seem to consider the second statement I quoted above. It seems that two pmpicfg values are necessary to decide if a given pmpaddr register should be locked.

sstatus/sie/sip don't really exist

Problem

There is a difference between Sail and Spike w.r.t. the CSRs sstatus, sie, and sip.

Currently the RISC-V Sail model reports registers sstatus, sie, and sip as CSRs when they get written by a CSRW (et al) instruction, but these registers are actually implemented using the mstatus, mie, and mip registers.

Spike reports the actual underlying registers that are updated: mstatus, mie, and mip.

Explanation

The privileged ISA section 4.1.1 (sstatus) has commentary about this: "The sstatus register is a subset of the mstatus register. In a straightforward implementation, reading or writing any field in sstatus is equivalent to reading or writing the homonymous field in mstatus."

Current solution

The trace compare program has special-case code to deal with these registers, since Spike handles them differently.

Proposed solution

I think it makes more sense for the Sail model to report the actual register that was updated: mstatus, mie, or mip, instead of the supervisor-level shadow registers. This way, the comparison will not have to be special-cased.

To achieve this I added the following code right above the print_reg in riscv_insts_zicsr.sail:

      /* These three supervisor CSRs are implemented as a subset of the machine CSRs,
         so when they are printed I want to see the machine CSR names. */
      let printcsr : csreg =
      match csr {
        0x100 => 0x300,  /* sstatus -> mstatus */
        0x104 => 0x304,  /* sie     -> mie     */
        0x144 => 0x344,  /* sip     -> mip     */
        _     => csr
      };

Questions

Is this a worthwhile goal?

Is this the best way to achieve it?

N-extension CSRs active despite MISA

When misa[13]==0 (Sail's default) the N-extension (user interrupts) is not present.

I observe that some of the N-extension behavior is properly dependent on misa (via haveNExt()) but not all.

Expected behavior

Access to the N-extension CSRs (e.g. ustatus) should cause an illegal instruction exception.

Bits mstatus[4] (aka UPIE) and mstatus[0] (aka UIE) should be hardwired to 0.

Actual behavior

No illegal instruction exception occurs.

UIE and UPIE are writable and retain the value last written.

TOR pmp matching with same hi and lo pmpaddr

In the case the ranges for a PMP check in TOR mode are the same (ie lo == hi), I am not sure the Sail specification/model will do the right thing.
I believe the correct behaviour here will always be to not match the entry, however the Sail specification would give a partial match.
The effects of this are subtle, because a no match will then go on to check the next entry, wheras a part match will cause the whole check to fail.

Take the following example :
if pmpaddr[0] == pmpaddr[1] == 0x...10000
the address to check is 0x....FFFF for a 2 byte access
This means the two bytes to check are 0x....FFFF and 0x...10000 neither of these should match according to The privileged architecture (section 3.7.1, 20210921-draft), so the result should be "no match" for that entry

here lo == hi == 0x...10000, addr = 0x....FFFF, addr + width = 0x...10001
In the sail spec this will result in a partial match because the first check of the range values is for > not >=, then the second if condition, (addr + width <=_u lo) | (hi <=_u addr), will not be so it falls into the second condition, (lo <=_u addr) & (addr + width <=_u hi), which is also not met so results in a partial match.

Should the initial misconfiguration check, hi <_u lo, be checking for hi <=_u lo?

Risc-V Sail code has no version string

We would like to implement a versioning string so that we can easily tell if a version with some non-backwards compatible change is being used by checking the version. I don't think it matters what the format of the version is - it just need to be monotonically increasing, and not a random hash value. The riscof team has implemented this as a simple CI script, I believe, and you might be able to follow their recipe.

misaligned load/store on page crossing doesn't tablewalk for second page

An 8-byte store to address 0xffc, for example, should store 4 bytes to one page and 4 to the next page. When paging is enabled, two separate translations are required.

The Sail model is only translating the first page, then storing 8 bytes to contiguous physical addresses.

  • No tablewalk occurs for the second page
  • No exceptions are taken if the second page has unacceptable permissions
  • The physical address for the second half of the store is incorrect

I created a repo with a test to recreate the issue. Instruction 128 shows the problem. There is one tablewalk, then 8 bytes loaded from 0x80003FFC.

This should take an exception (with mtval 0x0000003a177df000) because the second page's access bit is 0. The handler will repair the access bit, then re-execute the instruction. The second attempt should succeed, loading the second half of the access from a different physical page.

(Fetches across pages seem to work correctly.)

Lem and adding the plat_get_16_random_bits entropy source function

Hi there

I'm investigating why my PR (#99 ) is failing and this is the error message I get locally:

work@ben-TF:~/riscv/riscv-crypto/extern/sail-riscv$ make ARCH=RV64
mkdir -p ocaml_emulator/_sbuild
cp ocaml_emulator/_tags ocaml_emulator/platform.ml ocaml_emulator/platform_impl.ml ocaml_emulator/softfloat.ml ocaml_emulator/riscv_ocaml_sim.ml generated_definitions/ocaml/RV64/*.ml ocaml_emulator/_sbuild
cd ocaml_emulator/_sbuild && ocamlbuild -use-ocamlfind riscv_ocaml_sim.native
Finished, 25 targets (25 cached) in 00:00:00.
lem -isa -outdir generated_definitions/isabelle/RV64 -lib Sail=/home/work/.opam/ocaml-base-compiler.4.06.1/share/sail/src/lem_interp -lib Sail=/home/work/.opam/ocaml-base-compiler.4.06.1/share/sail/src/gen_lib \
	handwritten_support/0.11/riscv_extras.lem handwritten_support/0.11/mem_metadata.lem handwritten_support/0.11/riscv_extras_fdext.lem \
	generated_definitions/lem/RV64/riscv_types.lem \
	generated_definitions/lem/RV64/riscv.lem
File "generated_definitions/lem/RV64/riscv.lem", line 14941, character 24 to line 14941, character 46
  Type error: unbound variable: plat_get_16_random_bits
make: *** [Makefile:318: generated_definitions/isabelle/RV64/Riscv.thy] Error 1

I am responsible for adding the plat_get_16_random_bits function. This was recommended to me by the Sail authors, since the entropy source model "calls out" to the execution platform to get entropy. However, I have no idea what the "lem" tool is, or why it should complain about my function.

I can build the rv32/64 c and ocaml models fine with

make ARCH=RV32 csim osim
make ARCH=RV64 csim osim

But running make all for either architecture causes this problem.

So, I know I've broken something, but I'm not enough of a Sail expert to know exactly what.

Thanks,
Ben

sail-riscv build fails

Hi,
I am trying to install sail-riscv. I installed sail using opam, but i get the following error when i run make inside sail-riscv folder.

[user@machine sail-riscv]$ make all                                                                                          mkdir -p generated_definitions/ocaml/RV64
sail -dno_cast -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV64 -o riscv model/prelude.sail
model/prelude_mapping.sail model/riscv_xlen64.sail model/riscv_flen_D.sail model/prelude_mem_metadata.sail
model/prelude_mem.sail model/riscv_types_common.sail model/riscv_types_ext.sail model/riscv_types.sail
model/riscv_vmem_types.sail model/riscv_reg_type.sail model/riscv_freg_type.sail model/riscv_regs.sail
model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_pmp_regs.sail model/riscv_pmp_control.sail
model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_misa_ext.sail
model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail
model/riscv_next_control.sail model/riscv_softfloat_interface.sail model/riscv_fdext_regs.sail model/riscv_fdext_control.sail
model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_pte.sail
model/riscv_ptw.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv39.sail
model/riscv_vmem_sv48.sail model/riscv_vmem_rv64.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail
model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail
model/riscv_insts_next.sail model/riscv_insts_hints.sail model/riscv_insts_fext.sail model/riscv_insts_cfext.sail
model/riscv_insts_dext.sail model/riscv_insts_cdext.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail
model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail
model/riscv_step.sail model/riscv_analysis.sail
Error:
Error when calling smt: Reporting.Fatal_error(_)
make: *** [generated_definitions/ocaml/RV64/riscv.ml] Error 1

The version of sail and opam i use is

[user@machine sail-riscv]$ opam --version
2.0.8
[user@machine sail-riscv]$ sail -v
Sail 0.14 (sail2 @ opam)

i have 'home_dir/.opam/ocaml-base-compiler.4.06.1/bin' in my PATH and OPAM_SWITCH_PREFIX, CAML_LD_LIBRARY_PATH, OCAML_TOPLEVEL_PATH, PKG_CONFIG_PATH, MANPATH related to opam are configured.

[user@machine sail-riscv]$ cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"

It would be great if you can help me here 😃

PTW_Ext_Error is not as useful as might be desired?

The translation machinery in riscv_vmem_sv39.sail, for example, maps all checkPTEPermissions failures to PTE_No_Permission...
https://github.com/rems-project/sail-riscv/blob/fa707da94d0329e7d1b7520d876ad85953f2fdd5/model/riscv_vmem_sv39.sail#L43-L46
https://github.com/rems-project/sail-riscv/blob/fa707da94d0329e7d1b7520d876ad85953f2fdd5/model/riscv_vmem_sv39.sail#L120-L121
... which seems somewhat suspect. Perhaps the correct thing to do would be to change
https://github.com/rems-project/sail-riscv/blob/f9f066e89a5c20f2769fbfb2b6a585af9b3f0561/model/riscv_pte.sail#L31-L34
to

union PTE_Check = {
  PTE_Check_Success : ext_ptw,
  PTE_Check_Failure : PTW_Error
}

This probably also obviates the ext_ptw field within the TR_Failure constructor?

Use libfdt in the C emulator

Currently, the FDTs for OS boots with the C emulator need to be manually checked for consistency against the constants defined in the C platform. It would be better for these values to be derived directly from the FDT, using libfdt from the device-tree-compiler package. This would add a dependency to the C emulator, but libfdt is a simple dependency to satisfy on Linux systems.

Compressed floating point instructions missing

The C extension, when combined with F or D extensions, adds floating point load/store opcodes. These seem to be missing from the Sail RISC-V model:

  • c.flw
  • c.fld
  • c.flwsp
  • c.fldsp
  • c.fsw
  • c.fsd
  • c.fswsp
  • c.fsdsp

All of these take an illegal instruction exception.

cc @rsnikhil

Tests elf files

Hi,

I wonder if it still make sense to keep tests elf files precompiled in test/riscv-tests ? I think it make more sense to add riscv-arch-test repo as a git submodule of this repository.

Also maybe we should add a new task to CI to compile and run these tests and make sure they all pass on each PR ?

Kind regards,
Ibrahim.

Sv39 virtual address msb check missing?

The priv spec (section 4.4.1 on "Addressing and Memory Protection") says:

Instruction fetch addresses and load and store effective addresses, which are 64 bits, must have bits 63-39 all equal to bit 38, or else a page-fault exception will occur.

But I am seeing a case where the Sail model successfully performs a load, translating using bits [38:0] of the vaddr, and ignoring the upper bits. Spike (as expected) takes a load page fault.

Configurable word size for test signature file output

Would like to have an option to dump the signature file used by the riscv-arch-test (riscof) in either 32 bit values or 64 bit values.

This is so the barrier of entry for using the riscv-arch-test suite is easier. Currently if you are on a RV64 dut, then the signature is dumped out as 64 bit values (writememh()) and the resulting signature needs to be post processed into 32 bit values to match what sail is generating.

htif_store on RV32 and terminal output not working.

Hi there

I'm trying to run a "Hello World" program on the RV32 SAIL model, and can't get the terminal output to work properly.

I'm re-using the "HTIF" interface built into the riscv_platform.sail file, and can't understand how the htif_store function works on RV32.

https://github.com/rems-project/sail-riscv/blob/7dedd27a2f6fb48ad002eb21daa4ce0c54dc562c/model/riscv_platform.sail#L303

For RV64, it's easy, I store a single double-word to the tohost symbol/address and get working UART output when setting "device" to 0x1 and "cmd" to "0x1".

For RV32, I don't see how the htif_store function can work. It seems like the function processes the command immediately, every time 32-bits are written. This leads to duplicated output on the terminal (every char printed twice) and eventually a spurious command and a failure.

There's even a comment:

https://github.com/rems-project/sail-riscv/blob/7dedd27a2f6fb48ad002eb21daa4ce0c54dc562c/model/riscv_platform.sail#L315

suggesting this is necessary behaviour, but I can't understand why?

So, what is the recommended store/instruction sequence to get correct simulated terminal output when building the RV32 C-simulator?

Many thanks,
Ben

Support for when Xlen != Flen

Hello, I am reviewing the model before implementing parts of the proposed ZFinX extension, and I am wondering if there is any plan to support cases when Xlen != Flen ? (e.g RV32D)

Also I am wondering if there are any guidelines one should follow when planning to contribute to the model repo ?

Thank you very much !

ebreak should set mtval to 0

Today, ebreak sets mtval to the PC of the faulting instruction, but that is not what the spec says to do.

See Spike bug:

Quote Andrew Waterman:

the spec says that mtval should be written with 0 in this case, since a software ebreak is not one of the conditions in the following passage:
"When a hardware breakpoint is triggered, or an address-misaligned, access-fault, or page fault exception occurs on an instruction fetch, load, or store, mtval is written with the faulting virtual address. On an illegal instruction trap, [...]. For other traps, mtval is set to zero, but a future standard may redefine mtval's setting for other traps."

Cannot Build

I have installed sail (succesfully I think)
when trying to run 'make' for sail-riscv I getthe following errors
any help appreciated

$ ARCH=RV32 make
mkdir -p generated_definitions/ocaml/RV32
sail -ocaml -ocaml-nobuild -ocaml_build_dir generated_definitions/ocaml/RV32 -o riscv model/prelude.sail model/prelude_mapping.sail model/riscv_xlen32.sail model/prelude_mem_metadata.sail model/prelude_mem.sail model/riscv_types.sail model/riscv_reg_type.sail model/riscv_regs.sail model/riscv_pc_access.sail model/riscv_sys_regs.sail model/riscv_pmp_regs.sail model/riscv_pmp_control.sail model/riscv_ext_regs.sail model/riscv_addr_checks_common.sail model/riscv_addr_checks.sail model/riscv_csr_map.sail model/riscv_next_regs.sail model/riscv_sys_exceptions.sail model/riscv_sync_exception.sail model/riscv_next_control.sail model/riscv_csr_ext.sail model/riscv_sys_control.sail model/riscv_platform.sail model/riscv_mem.sail model/riscv_vmem_common.sail model/riscv_vmem_tlb.sail model/riscv_vmem_sv32.sail model/riscv_vmem_rv32.sail model/riscv_insts_begin.sail model/riscv_insts_base.sail model/riscv_insts_aext.sail model/riscv_insts_cext.sail model/riscv_insts_mext.sail model/riscv_insts_zicsr.sail model/riscv_insts_next.sail model/riscv_jalr_seq.sail model/riscv_insts_end.sail model/riscv_step_common.sail model/riscv_step_ext.sail model/riscv_decode_ext.sail model/riscv_fetch.sail model/riscv_step.sail
Warning: Possible incomplete pattern match at [model/riscv_pmp_regs.sail]:76:7-12
76 | then match n {
| ^---^
|
Most general matched pattern is 0

Warning: Possible incomplete pattern match at [model/riscv_pmp_regs.sail]:82:7-12
82 | else match n { // sizeof(xlen) == 64
| ^---^
|
Most general matched pattern is 0

Warning: Possible incomplete pattern match at [model/riscv_pmp_regs.sail]:95:7-12
95 | then match n {
| ^---^
|
Most general matched pattern is 0

Warning: Possible incomplete pattern match at [model/riscv_pmp_regs.sail]:118:7-12
118 | then match n {
| ^---^
|
Most general matched pattern is 0

cp: cannot stat '/home/moore/.opam/4.06.1/share/sail/src/value.ml': No such file or directory
cp: cannot stat '/home/moore/.opam/4.06.1/share/sail/src/toFromInterp_lib.ml': No such file or directory
mkdir -p ocaml_emulator/_sbuild
cp ocaml_emulator/_tags ocaml_emulator/platform.ml ocaml_emulator/platform_impl.ml ocaml_emulator/riscv_ocaml_sim.ml generated_definitions/ocaml/RV32/*.ml ocaml_emulator/_sbuild
cd ocaml_emulator/_sbuild && ocamlbuild -use-ocamlfind riscv_ocaml_sim.native

  • ocamlfind ocamldep -package lem -package linksem -package zarith -modules riscv_ocaml_sim.ml > riscv_ocaml_sim.ml.depends
    ocamlfind: Package `lem' not found
    Command exited with code 2.
    Compilation unsuccessful after building 1 target (0 cached) in 00:00:00.
    Makefile:162: recipe for target 'ocaml_emulator/_sbuild/riscv_ocaml_sim.native' failed
    make: *** [ocaml_emulator/_sbuild/riscv_ocaml_sim.native] Error 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.