Skip to content

Commit

Permalink
Add support for cmo extensions except prefetch.* instructions
Browse files Browse the repository at this point in the history
(They will be overlapped by ORI instruciton).
  • Loading branch information
Weiwei Li committed Jul 20, 2023
1 parent ae905fb commit 2424492
Show file tree
Hide file tree
Showing 25 changed files with 381 additions and 8 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ SAIL_DEFAULT_INST += riscv_insts_zbkx.sail

SAIL_DEFAULT_INST += riscv_insts_zicond.sail

SAIL_DEFAULT_INST += riscv_insts_zicbom.sail
SAIL_DEFAULT_INST += riscv_insts_zicboz.sail

SAIL_SEQ_INST = $(SAIL_DEFAULT_INST) riscv_jalr_seq.sail
SAIL_RMEM_INST = $(SAIL_DEFAULT_INST) riscv_jalr_rmem.sail riscv_insts_rmem.sail

Expand Down
3 changes: 3 additions & 0 deletions c_emulator/riscv_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ mach_bits plat_rom_size(unit u)
return rv_rom_size;
}

mach_bits plat_cache_block_size()
{ return rv_cache_block_size; }

// Provides entropy for the scalar cryptography extension.
mach_bits plat_get_16_random_bits()
{
Expand Down
2 changes: 2 additions & 0 deletions c_emulator/riscv_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ bool within_phys_mem(mach_bits, sail_int);
mach_bits plat_rom_base(unit);
mach_bits plat_rom_size(unit);

mach_bits plat_cache_block_size(unit);

// Provides entropy for the scalar cryptography extension.
mach_bits plat_get_16_random_bits();

Expand Down
2 changes: 2 additions & 0 deletions c_emulator/riscv_platform_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ uint64_t rv_ram_size = UINT64_C(0x4000000);
uint64_t rv_rom_base = UINT64_C(0x1000);
uint64_t rv_rom_size = UINT64_C(0x100);

uint64_t rv_cache_block_size = UINT64_C(0x40);

// Provides entropy for the scalar cryptography extension.
uint64_t rv_16_random_bits(void)
{
Expand Down
2 changes: 2 additions & 0 deletions c_emulator/riscv_platform_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ extern uint64_t rv_ram_size;
extern uint64_t rv_rom_base;
extern uint64_t rv_rom_size;

extern uint64_t rv_cache_block_size;

// Provides entropy for the scalar cryptography extension.
extern uint64_t rv_16_random_bits(void);

Expand Down
13 changes: 13 additions & 0 deletions c_emulator/riscv_sim.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ static struct option options[] = {
#ifdef SAILCOV
{"sailcov-file", required_argument, 0, 'c'},
#endif
{"cache-block-size", required_argument, 0, 'B'},
{0, 0, 0, 0 }
};

Expand Down Expand Up @@ -221,6 +222,7 @@ char *process_args(int argc, char **argv)
{
int c;
uint64_t ram_size = 0;
uint64_t block_size = 0;
while (true) {
c = getopt_long(argc, argv,
"a"
Expand Down Expand Up @@ -249,6 +251,7 @@ char *process_args(int argc, char **argv)
"V::"
"v::"
"l:"
"B:"
"x",
options, NULL);
if (c == -1)
Expand Down Expand Up @@ -352,6 +355,16 @@ char *process_args(int argc, char **argv)
sailcov_file = strdup(optarg);
break;
#endif
case 'B':
block_size = atol(optarg);
if ((block_size & (block_size - 1)) == 0) {
fprintf(stderr, "setting cache-block-size to %" PRIu64 " B\n", block_size);
rv_cache_block_size = block_size;
} else {
fprintf(stderr, "invalid cache-block-size '%s' provided.\n", optarg);
exit(1);
}
break;
case '?':
print_usage(argv[0], 1);
break;
Expand Down
4 changes: 4 additions & 0 deletions handwritten_support/0.11/riscv_extras.lem
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ val plat_rom_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_rom_size () = wordFromInteger 0
declare ocaml target_rep function plat_rom_size = `Platform.rom_size`

val plat_cache_block_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_cache_block_size () = wordFromInteger 0
declare ocaml target_rep function plat_cache_block_size = `Platform.cache_block_size`

val plat_clint_base : forall 'a. Size 'a => unit -> bitvector 'a
let plat_clint_base () = wordFromInteger 0
declare ocaml target_rep function plat_clint_base = `Platform.clint_base`
Expand Down
4 changes: 4 additions & 0 deletions handwritten_support/0.11/riscv_extras_sequential.lem
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ val plat_rom_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_rom_size () = wordFromInteger 0
declare ocaml target_rep function plat_rom_size = `Platform.rom_size`

val plat_cache_block_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_cache_block_size () = wordFromInteger 0
declare ocaml target_rep function plat_cache_block_size = `Platform.cache_block_size`

val plat_clint_base : forall 'a. Size 'a => unit -> bitvector 'a
let plat_clint_base () = wordFromInteger 0
declare ocaml target_rep function plat_clint_base = `Platform.clint_base`
Expand Down
4 changes: 4 additions & 0 deletions handwritten_support/riscv_extras.lem
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ val plat_rom_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_rom_size () = wordFromInteger 0
declare ocaml target_rep function plat_rom_size = `Platform.rom_size`

val plat_cache_block_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_cache_block_size () = wordFromInteger 0
declare ocaml target_rep function plat_cache_block_size = `Platform.cache_block_size`

val plat_clint_base : forall 'a. Size 'a => unit -> bitvector 'a
let plat_clint_base () = wordFromInteger 0
declare ocaml target_rep function plat_clint_base = `Platform.clint_base`
Expand Down
4 changes: 4 additions & 0 deletions handwritten_support/riscv_extras_sequential.lem
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ val plat_rom_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_rom_size () = wordFromInteger 0
declare ocaml target_rep function plat_rom_size = `Platform.rom_size`

val plat_cache_block_size : forall 'a. Size 'a => unit -> bitvector 'a
let plat_cache_block_size () = wordFromInteger 0
declare ocaml target_rep function plat_cache_block_size = `Platform.cache_block_size`

val plat_clint_base : forall 'a. Size 'a => unit -> bitvector 'a
let plat_clint_base () = wordFromInteger 0
declare ocaml target_rep function plat_clint_base = `Platform.clint_base`
Expand Down
2 changes: 1 addition & 1 deletion model/riscv_addr_checks.sail
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ type ext_data_addr_error = unit

/* Default data addr is just base register + immediate offset (may be zero).
Extensions might override and add additional checks. */
function ext_data_get_addr(base : regidx, offset : xlenbits, acc : AccessType(ext_access_type), width : word_width)
function ext_data_get_addr(base : regidx, offset : xlenbits, acc : AccessType(ext_access_type), width : xlenbits)
-> Ext_DataAddr_Check(ext_data_addr_error) =
let addr = X(base) + offset in
Ext_DataAddr_OK(addr)
Expand Down
4 changes: 4 additions & 0 deletions model/riscv_csr_map.sail
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ mapping clause csr_name_map = 0x143 <-> "stval"
mapping clause csr_name_map = 0x144 <-> "sip"
/* supervisor protection and translation */
mapping clause csr_name_map = 0x180 <-> "satp"
/* supervisor envcfg */
mapping clause csr_name_map = 0x10A <-> "senvcfg"
/* machine information registers */
mapping clause csr_name_map = 0xF11 <-> "mvendorid"
mapping clause csr_name_map = 0xF12 <-> "marchid"
Expand Down Expand Up @@ -159,6 +161,8 @@ mapping clause csr_name_map = 0xB00 <-> "mcycle"
mapping clause csr_name_map = 0xB02 <-> "minstret"
mapping clause csr_name_map = 0xB80 <-> "mcycleh"
mapping clause csr_name_map = 0xB82 <-> "minstreth"
/* machine envcfg */
mapping clause csr_name_map = 0x30A <-> "menvcfg"
/* TODO: other hpm counters and events */
/* trigger/debug */
mapping clause csr_name_map = 0x7a0 <-> "tselect"
Expand Down
6 changes: 3 additions & 3 deletions model/riscv_insts_aext.sail
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function clause execute(LOADRES(aq, rl, rs1, width, rd)) = {
/* Get the address, X(rs1) (no offset).
* Extensions might perform additional checks on address validity.
*/
match ext_data_get_addr(rs1, zeros(), Read(Data), width) {
match ext_data_get_addr(rs1, zeros(), Read(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) => {
let aligned : bool =
Expand Down Expand Up @@ -188,7 +188,7 @@ function clause execute (STORECON(aq, rl, rs2, rs1, width, rd)) = {
/* Get the address, X(rs1) (no offset).
* Extensions might perform additional checks on address validity.
*/
match ext_data_get_addr(rs1, zeros(), Write(Data), width) {
match ext_data_get_addr(rs1, zeros(), Write(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) => {
let aligned : bool =
Expand Down Expand Up @@ -278,7 +278,7 @@ function clause execute (AMO(op, aq, rl, rs2, rs1, width, rd)) = {
/* Get the address, X(rs1) (no offset).
* Some extensions perform additional checks on address validity.
*/
match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) {
match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) => {
match translateAddr(vaddr, ReadWrite(Data, Data)) {
Expand Down
4 changes: 2 additions & 2 deletions model/riscv_insts_base.sail
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ function clause execute(LOAD(imm, rs1, rd, is_unsigned, width, aq, rl)) = {
let offset : xlenbits = EXTS(imm);
/* Get the address, X(rs1) + offset.
Some extensions perform additional checks on address validity. */
match ext_data_get_addr(rs1, offset, Read(Data), width) {
match ext_data_get_addr(rs1, offset, Read(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) =>
if check_misaligned(vaddr, width)
Expand Down Expand Up @@ -444,7 +444,7 @@ function clause execute (STORE(imm, rs2, rs1, width, aq, rl)) = {
let offset : xlenbits = EXTS(imm);
/* Get the address, X(rs1) + offset.
Some extensions perform additional checks on address validity. */
match ext_data_get_addr(rs1, offset, Write(Data), width) {
match ext_data_get_addr(rs1, offset, Write(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) =>
if check_misaligned(vaddr, width)
Expand Down
4 changes: 2 additions & 2 deletions model/riscv_insts_fext.sail
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ function clause execute(LOAD_FP(imm, rs1, rd, width)) = {
let offset : xlenbits = EXTS(imm);
/* Get the address, X(rs1) + offset.
Some extensions perform additional checks on address validity. */
match ext_data_get_addr(rs1, offset, Read(Data), width) {
match ext_data_get_addr(rs1, offset, Read(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) =>
if check_misaligned(vaddr, width)
Expand Down Expand Up @@ -443,7 +443,7 @@ function clause execute (STORE_FP(imm, rs2, rs1, width)) = {
let (aq, rl, con) = (false, false, false);
/* Get the address, X(rs1) + offset.
Some extensions perform additional checks on address validity. */
match ext_data_get_addr(rs1, offset, Write(Data), width) {
match ext_data_get_addr(rs1, offset, Write(Data), EXTZ(size_bits(width))) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) =>
if check_misaligned(vaddr, width)
Expand Down
150 changes: 150 additions & 0 deletions model/riscv_insts_zicbom.sail
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*=======================================================================================*/
/* RISCV Sail Model */
/* */
/* This Sail RISC-V architecture model, comprising all files and */
/* directories except for the snapshots of the Lem and Sail libraries */
/* in the prover_snapshots directory (which include copies of their */
/* licences), is subject to the BSD two-clause licence below. */
/* */
/* Copyright (c) 2017-2023 */
/* Prashanth Mundkur */
/* Rishiyur S. Nikhil and Bluespec, Inc. */
/* Jon French */
/* Brian Campbell */
/* Robert Norton-Wright */
/* Alasdair Armstrong */
/* Thomas Bauereiss */
/* Shaked Flur */
/* Christopher Pulte */
/* Peter Sewell */
/* Alexander Richardson */
/* Hesham Almatary */
/* Jessica Clarke */
/* Microsoft, for contributions by Robert Norton-Wright and Nathaniel Wesley Filardo */
/* Peter Rugg */
/* Aril Computer Corp., for contributions by Scott Johnson */
/* Philipp Tomsich */
/* VRULL GmbH, for contributions by its employees */
/* PLCT, for contributions by its employees */
/* */
/* All rights reserved. */
/* */
/* 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). */
/* */
/* */
/* Redistribution and use in source and binary forms, with or without */
/* modification, are permitted provided that the following conditions */
/* are met: */
/* 1. Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* 2. Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in */
/* the documentation and/or other materials provided with the */
/* distribution. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' */
/* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */
/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */
/* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR */
/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF */
/* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND */
/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
/* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */
/* SUCH DAMAGE. */
/*=======================================================================================*/

/* ****************************************************************** */
union clause ast = RISCV_ZICBOM : (cbop_zicbom, regidx)

mapping encdec_cbop : cbop_zicbom <-> bits(12) = {
CBO_CLEAN <-> 0b000000000001,
CBO_FLUSH <-> 0b000000000010,
CBO_INVAL <-> 0b000000000000
}

mapping clause encdec = RISCV_ZICBOM(cbop, rs1) if haveZicbom()
<-> encdec_cbop(cbop) @ rs1 @ 0b010 @ 0b00000 @ 0b0001111 if haveZicbom()

mapping cbop_mnemonic : cbop_zicbom <-> string = {
CBO_CLEAN <-> "cbo.clean",
CBO_FLUSH <-> "cbo.flush",
CBO_INVAL <-> "cbo.inval"
}

mapping clause assembly = RISCV_ZICBOM(cbop, rs1)
<-> cbop_mnemonic(cbop) ^ spc() ^ "(" ^ reg_name(rs1) ^ ")"

val process_clean_inval : (regidx, cbop_zicbom) -> Retired effect {escape, rmem, rmemt, rreg, wmv, wmvt, wreg}
function process_clean_inval(rs1, cbop) = {
let rs1_val = X(rs1);
let cache_block_size = plat_cache_block_size();
let begin_addr = rs1_val & ~(cache_block_size - EXTZ(0b1));
let offset = begin_addr - rs1_val;
match ext_data_get_addr(rs1, offset, Read(Data), cache_block_size) {
Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
Ext_DataAddr_OK(vaddr) => {
let res: option(ExceptionType) = match translateAddr(vaddr, Read(Data)) {
TR_Address(paddr, _) => {
match mem_read(Read(Data), paddr, 1, false, false, false) {
MemValue(_) => None(),
MemException(e) => Some(e)
}
},
TR_Failure(e, _) => Some(e)
};
match res {
None() => RETIRE_SUCCESS, // do nothing for cbop currently
Some(e) => {
match (e) {
E_Load_Access_Fault() => { handle_mem_exception(vaddr, E_SAMO_Access_Fault()); RETIRE_FAIL },
E_Load_Page_Fault() => { handle_mem_exception(vaddr, E_SAMO_Page_Fault()); RETIRE_FAIL }
}
}
}
}
}
}

function cbo_clean_flush_enable(p : Privilege) -> bool =
~((p != Machine & menvcfg.CBCFE() == 0b0) | (p == User & senvcfg.CBCFE() == 0b0))

function cbop_for_cbo_inval(p : Privilege) -> option(cbop_zicbom) = {
let illegal = ((p != Machine) & (menvcfg.CBIE() == 0b00)) |
((p == User) & (senvcfg.CBIE() == 0b00));
let flush = ((p != Machine) & (menvcfg.CBIE() == 0b01)) |
((p == User) & (senvcfg.CBIE() == 0b01));
if illegal then None()
else if flush then Some(CBO_FLUSH)
else Some(CBO_INVAL)
}

function clause execute(RISCV_ZICBOM(cbop, rs1)) = {
let cbcfe = cbo_clean_flush_enable(cur_privilege);
let final_op : option(cbop_zicbom) = match (cbop, cbcfe) {
(CBO_CLEAN, true) => Some(CBO_CLEAN),
(CBO_CLEAN, false) => None(),
(CBO_FLUSH, true) => Some(CBO_FLUSH),
(CBO_FLUSH, false) => None(),
(CBO_INVAL, _) => cbop_for_cbo_inval(cur_privilege)
};
match final_op {
None() => { handle_illegal(); RETIRE_FAIL },
Some(cbop) => process_clean_inval(rs1, cbop)
}
}
Loading

0 comments on commit 2424492

Please sign in to comment.