Skip to content

Add Zilsd/Zclsd Support #765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Supported RISC-V ISA features
- Svinval extension for fine-grained address-translation cache invalidation, v1.0
- Sv32, Sv39, Sv48 and Sv57 page-based virtual-memory systems
- Physical Memory Protection (PMP)
- Zilsd and Zclsd extensions for RV32 Load/Store pair instructions, v1.0

**For a list of unsupported extensions and features, see the [Extension Roadmap](https://github.com/riscv/sail-riscv/wiki/Extension-Roadmap).**

Expand Down
6 changes: 6 additions & 0 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@
"Zicboz" : {
"enabled" : false
},
"Zilsd": {
"enabled": true
},
"Zclsd": {
"enabled": true
},
"Zvkb" : {
"enabled" : false
},
Expand Down
2 changes: 2 additions & 0 deletions model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ foreach (xlen IN ITEMS 32 64)
${vext_srcs}
"riscv_insts_zicbom.sail"
"riscv_insts_zicboz.sail"
"riscv_insts_zilsd.sail"
"riscv_insts_zclsd.sail"
"riscv_insts_zvbb.sail"
"riscv_insts_zvbc.sail"
# Zimop and Zcmop should be at the end so they can be overridden by earlier extensions
Expand Down
4 changes: 4 additions & 0 deletions model/riscv_extensions.sail
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ enum clause extension = Ext_Zcb
enum clause extension = Ext_Zcd
// Code Size Reduction: compressed single precision floating point loads and stores
enum clause extension = Ext_Zcf
// Load/Store Pair for RV32
enum clause extension = Ext_Zilsd
// Compressed Load/Store pair instructions
enum clause extension = Ext_Zclsd
// Compressed May-Be-Operations
enum clause extension = Ext_Zcmop

Expand Down
2 changes: 1 addition & 1 deletion model/riscv_insts_zcf.sail
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

/* ****************************************************************** */

function clause extensionEnabled(Ext_Zcf) = extensionEnabled(Ext_Zca) & extensionEnabled(Ext_F) & xlen == 32
function clause extensionEnabled(Ext_Zcf) = extensionEnabled(Ext_Zca) & extensionEnabled(Ext_F) & not(sys_enable_zclsd()) & (xlen == 32)

union clause ast = C_FLWSP : (bits(6), fregidx)

Expand Down
73 changes: 73 additions & 0 deletions model/riscv_insts_zclsd.sail
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*=======================================================================================*/
/* This Sail RISC-V architecture model, comprising all files and */
/* directories except where otherwise noted is subject the BSD */
/* two-clause license in the LICENSE file. */
/* */
/* SPDX-License-Identifier: BSD-2-Clause */
/*=======================================================================================*/

function clause extensionEnabled(Ext_Zclsd) = true & sys_enable_zilsd() & extensionEnabled(Ext_Zca) & not(extensionEnabled(Ext_Zcf)) & xlen == 32

/* ****************************************************************** */
union clause ast = ZCLSD_C_LDSP : (bits(9), regidx)

mapping clause encdec_compressed = ZCLSD_C_LDSP(ui86 @ ui5 @ ui43 @ 0b000, rd)
<-> 0b011 @ ui5 : bits(1) @ encdec_reg(rd) @ ui43 : bits(2) @ ui86 : bits(3) @ 0b10
when extensionEnabled(Ext_Zclsd)

function clause execute (ZCLSD_C_LDSP(imm, rd)) = {
execute(ZILSD_LD(zero_extend(imm), sp, rd))
}

mapping clause assembly = ZCLSD_C_LDSP(uimm, rd)
<-> "c.ldsp" ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_9(uimm)
when xlen == 32

/* ****************************************************************** */
union clause ast = ZCLSD_C_SDSP : (bits(9), regidx)

mapping clause encdec_compressed = ZCLSD_C_SDSP(ui86 @ ui53 @ 0b000, rs2)
<-> 0b111 @ ui53 : bits(3) @ ui86 : bits(3) @ encdec_reg(rs2) @ 0b10
when extensionEnabled(Ext_Zclsd)

function clause execute (ZCLSD_C_SDSP(uimm, rs2)) = {
execute(ZILSD_SD(zero_extend(uimm), rs2, sp))
}

mapping clause assembly = ZCLSD_C_SDSP(uimm, rs2)
<-> "c.sdsp" ^ spc() ^ reg_name(rs2) ^ sep() ^ hex_bits_9(uimm)
when xlen == 32

/* ****************************************************************** */
union clause ast = ZCLSD_C_LD : (bits(8), cregidx, cregidx)

mapping clause encdec_compressed = ZCLSD_C_LD(ui76 @ ui53 @ 0b000, rs1, rd)
<-> 0b011 @ ui53 : bits(3) @ encdec_creg(rs1) @ ui76 : bits(2) @ encdec_creg(rd) @ 0b00
when extensionEnabled(Ext_Zclsd)

function clause execute (ZCLSD_C_LD(uimm, rsc, rdc)) = {
let rd = creg2reg_idx(rdc);
let rs = creg2reg_idx(rsc);
execute(ZILSD_LD(zero_extend(uimm), rs, rd))
}

mapping clause assembly = ZCLSD_C_LD(uimm, rsc, rdc)
<-> "c.ld" ^ spc() ^ creg_name(rdc) ^ sep() ^ creg_name(rsc) ^ sep() ^ hex_bits_8(uimm)
when xlen == 32

/* ****************************************************************** */
union clause ast = ZCLSD_C_SD : (bits(8), cregidx, cregidx)

mapping clause encdec_compressed = ZCLSD_C_SD(ui76 @ ui53 @ 0b000, rs1, rs2)
<-> 0b111 @ ui53 : bits(3) @ encdec_creg(rs1) @ ui76 : bits(2) @ encdec_creg(rs2) @ 0b00
when extensionEnabled(Ext_Zclsd)

function clause execute (ZCLSD_C_SD(uimm, rsc1, rsc2)) = {
let rs1 = creg2reg_idx(rsc1);
let rs2 = creg2reg_idx(rsc2);
execute(ZILSD_SD(zero_extend(uimm), rs2, rs1))
}

mapping clause assembly = ZCLSD_C_SD(uimm, rsc1, rsc2)
<-> "c.sd" ^ spc() ^ creg_name(rsc1) ^ sep() ^ creg_name(rsc2) ^ sep() ^ hex_bits_8(uimm)
when xlen == 32
89 changes: 89 additions & 0 deletions model/riscv_insts_zilsd.sail
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*=======================================================================================*/
/* This Sail RISC-V architecture model, comprising all files and */
/* directories except where otherwise noted is subject the BSD */
/* two-clause license in the LICENSE file. */
/* */
/* SPDX-License-Identifier: BSD-2-Clause */
/*=======================================================================================*/

function clause extensionEnabled(Ext_Zilsd) = sys_enable_zilsd() & xlen == 32

/* ****************************************************************** */
union clause ast = ZILSD_LD : (bits(12), regidx, regidx)

mapping clause encdec = ZILSD_LD(imm, rs1, rd)
<-> imm @ encdec_reg(rs1) @ 0b011 @ encdec_reg(rd) @ 0b0000011
when extensionEnabled(Ext_Zilsd) & not(bit_to_bool(encdec_reg(rd)[0]))

function load_imm(imm : bits(12), base_val : xlenbits, rd : regidx, width : word_width) -> Retired = {
let offset : xlenbits = sign_extend(imm);
let width_bytes = size_bytes(width);
assert(width_bytes <= xlen_bytes);

let vaddr = Virtaddr(base_val + offset);
if check_misaligned(vaddr, width)
then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL }
else match translateAddr(vaddr, Read(Data)) {
TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
TR_Address(paddr, _) => {
match mem_read(Read(Data), paddr, width_bytes, false, false, false) {
Ok(result) => { X(rd) = extend_value(false, result); RETIRE_SUCCESS },
Err(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
}
},
}
}

function clause execute ZILSD_LD(imm, rs1, rd) = {
if rd != zreg then {
let base_val = X(rs1);
let _ = load_imm(imm, base_val, rd, WORD);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this cause issues if the first load fails? I think you need to check what it returns so that we get the RETIRE_FAIL if the first load fails.

Right now if the first load fails but the second one succeeds (like if it is right on some memory region boundary) this instruction will act like it succeeded.

load_imm(imm+4, base_val, rd+1, WORD)
} else {
RETIRE_SUCCESS
}
}
mapping clause assembly = ZILSD_LD(imm, rs1, rd) <-> "ld" ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_signed_12(imm) ^ "(" ^ reg_name(rs1) ^ ")"


/* ****************************************************************** */
union clause ast = ZILSD_SD : (bits(12), regidx, regidx)

mapping clause encdec = ZILSD_SD(imm7 @ imm5, rs2, rs1)
<-> imm7 : bits(7) @ encdec_reg(rs2) @ encdec_reg(rs1) @ 0b011 @ imm5 : bits(5) @ 0b0100011
when extensionEnabled(Ext_Zilsd) & not(bit_to_bool(encdec_reg(rs2)[0]))

function store_imm(imm : bits(12), rs2_val : xlenbits, base_val : xlenbits, width : word_width) -> Retired = {
let offset : xlenbits = sign_extend(imm);
let width_bytes = size_bytes(width);
assert(width_bytes <= xlen_bytes);

let vaddr = Virtaddr(base_val + offset);
if check_misaligned(vaddr, width)
then { handle_mem_exception(vaddr, E_SAMO_Addr_Align()); RETIRE_FAIL }
else match translateAddr(vaddr, Write(Data)) {
TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
TR_Address(paddr, _) => {
match mem_write_ea(paddr, width_bytes, false, false, false) {
Err(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
Ok(_) => {
match mem_write_value(paddr, width_bytes, rs2_val[width_bytes * 8 - 1 .. 0], false, false, false) {
Ok(true) => RETIRE_SUCCESS,
Ok(false) => internal_error(__FILE__, __LINE__, "store got false from mem_write_value"),
Err(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }
}
}
}
}
}
}

function clause execute ZILSD_SD(imm, rs2, rs1) = {
let base_val = X(rs1);
let rs2_val = X(rs2);
let rs2_pair_val = if rs2 != zreg then X(rs2+1) else rs2_val;
let _ = store_imm(imm, rs2_val, base_val, WORD);
store_imm(imm+4, rs2_pair_val, base_val, WORD)
}

mapping clause assembly = ZILSD_SD(offset, rs2, rs1) <-> "sd" ^ spc() ^ reg_name(rs2) ^ sep() ^ hex_bits_signed_12(offset) ^ "(" ^ reg_name(rs1) ^ ")"
4 changes: 4 additions & 0 deletions model/riscv_sys_regs.sail
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ function sys_enable_bext() -> bool = config extensions.B.enabled
function sys_enable_zicbom() -> bool = config extensions.Zicbom.enabled
function sys_enable_zicboz() -> bool = config extensions.Zicboz.enabled

// "Zilsd", "Zclsd" Extensions for Load/Store pair for RV32
function sys_enable_zilsd() -> bool = config extensions.Zilsd.enabled
function sys_enable_zclsd() -> bool = config extensions.Zclsd.enabled

// Is the Zvkb extension supported.
function sys_enable_zvkb() -> bool = config extensions.Zvkb.enabled

Expand Down
3 changes: 3 additions & 0 deletions model/riscv_types.sail
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ newtype regidx = Regidx : bits(5) /* uncompressed register identifiers */
newtype cregidx = Cregidx : bits(3) /* identifiers in RVC instructions */
type csreg = bits(12) /* CSR addressing */

function add_regidx_int(Regidx(reg) : regidx, offset : int) -> regidx = Regidx(reg + offset)
overload operator + = { add_regidx_int }

function regidx_offset(Regidx(r) : regidx, o : bits(5)) -> regidx = Regidx(r + o)
function regidx_bits (Regidx(b) : regidx) -> bits(5) = b

Expand Down
Loading