diff options
Diffstat (limited to 'model/riscv_insts_vext_vset.sail')
-rw-r--r-- | model/riscv_insts_vext_vset.sail | 178 |
1 files changed, 98 insertions, 80 deletions
diff --git a/model/riscv_insts_vext_vset.sail b/model/riscv_insts_vext_vset.sail index abd5587..000b2f3 100644 --- a/model/riscv_insts_vext_vset.sail +++ b/model/riscv_insts_vext_vset.sail @@ -41,60 +41,54 @@ mapping maybe_ma_flag : string <-> bits(1) = { sep() ^ "mu" <-> 0b0 } -/* ****************************** vsetvli & vsetvl ******************************* */ -union clause ast = VSET_TYPE : (vsetop, bits(1), bits(1), bits(3), bits(3), regidx, regidx) +val handle_illegal_vtype : unit -> unit effect {rreg} +function handle_illegal_vtype() = { + /* Note: Implementations can set vill or trap if the vtype setting is not supported. + * TODO: configuration support for both solutions + */ + vtype.bits = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ + vl = zeros(); + print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); + print_reg("CSR vl <- " ^ BitStr(vl)) +} -mapping encdec_vsetop : vsetop <-> bits(4) ={ - VSETVLI <-> 0b0000, - VSETVL <-> 0b1000 +val calculate_new_vl : (int, int) -> xlenbits +function calculate_new_vl(AVL, VLMAX) = { + /* Note: ceil(AVL / 2) ≤ vl ≤ VLMAX when VLMAX < AVL < (2 * VLMAX) + * TODO: configuration support for either using ceil(AVL / 2) or VLMAX + */ + if AVL <= VLMAX then to_bits(sizeof(xlen), AVL) + else if AVL < 2 * VLMAX then to_bits(sizeof(xlen), (AVL + 1) / 2) + else to_bits(sizeof(xlen), VLMAX) } -mapping clause encdec = VSET_TYPE(op, ma, ta, sew, lmul, rs1, rd) if haveVExt() - <-> encdec_vsetop(op) @ ma @ ta @ sew @ lmul @ rs1 @ 0b111 @ rd @ 0b1010111 if haveVExt() +/* *********************************** vsetvli *********************************** */ +union clause ast = VSETVLI : (bits(1), bits(1), bits(3), bits(3), regidx, regidx) -function clause execute VSET_TYPE(op, ma, ta, sew, lmul, rs1, rd) = { - let VLEN_pow = get_vlen_pow(); - let ELEN_pow = get_elen_pow(); +mapping clause encdec = VSETVLI(ma, ta, sew, lmul, rs1, rd) if haveVExt() + <-> 0b0000 @ ma @ ta @ sew @ lmul @ rs1 @ 0b111 @ rd @ 0b1010111 if haveVExt() + +function clause execute VSETVLI(ma, ta, sew, lmul, rs1, rd) = { let LMUL_pow_ori = get_lmul_pow(); let SEW_pow_ori = get_sew_pow(); let ratio_pow_ori = SEW_pow_ori - LMUL_pow_ori; /* set vtype */ - match op { - VSETVLI => { - vtype.bits = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul - }, - VSETVL => { - let rs2 : regidx = sew[1 .. 0] @ lmul; - vtype.bits = X(rs2) - } - }; + vtype.bits = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul; - /* check legal SEW and LMUL and calculate VLMAX */ + /* check new SEW and LMUL are legal and calculate VLMAX */ + let VLEN_pow = get_vlen_pow(); + let ELEN_pow = get_elen_pow(); let LMUL_pow_new = get_lmul_pow(); let SEW_pow_new = get_sew_pow(); - if SEW_pow_new > LMUL_pow_new + ELEN_pow then { - /* Note: Implementations can set vill or trap if the vtype setting is not supported. - * TODO: configuration support for both solutions - */ - vtype.bits = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ - vl = zeros(); - print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); - print_reg("CSR vl <- " ^ BitStr(vl)); - return RETIRE_SUCCESS - }; + if SEW_pow_new > (LMUL_pow_new + ELEN_pow) then { handle_illegal_vtype(); return RETIRE_SUCCESS }; let VLMAX = int_power(2, VLEN_pow + LMUL_pow_new - SEW_pow_new); /* set vl according to VLMAX and AVL */ if (rs1 != 0b00000) then { /* normal stripmining */ let rs1_val = X(rs1); let AVL = unsigned(rs1_val); - vl = if AVL <= VLMAX then to_bits(sizeof(xlen), AVL) - else if AVL < 2 * VLMAX then to_bits(sizeof(xlen), (AVL + 1) / 2) - else to_bits(sizeof(xlen), VLMAX); - /* Note: ceil(AVL / 2) ≤ vl ≤ VLMAX when VLMAX < AVL < (2 * VLMAX) - * TODO: configuration support for either using ceil(AVL / 2) or VLMAX - */ + vl = calculate_new_vl(AVL, VLMAX); X(rd) = vl; } else if (rd != 0b00000) then { /* set vl to VLMAX */ let AVL = unsigned(ones(sizeof(xlen))); @@ -103,81 +97,105 @@ function clause execute VSET_TYPE(op, ma, ta, sew, lmul, rs1, rd) = { } else { /* keep existing vl */ let AVL = unsigned(vl); let ratio_pow_new = SEW_pow_new - LMUL_pow_new; - if (ratio_pow_new != ratio_pow_ori) then { - /* Note: Implementations can set vill or trap if the vtype setting is not supported. - * TODO: configuration support for both solutions - */ - vtype.bits = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ - vl = zeros(); - } + if (ratio_pow_new != ratio_pow_ori) then { handle_illegal_vtype(); return RETIRE_SUCCESS } }; - print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); - print_reg("CSR vl <- " ^ BitStr(vl)); /* reset vstart to 0 */ vstart = zeros(); + + print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); + print_reg("CSR vl <- " ^ BitStr(vl)); print_reg("CSR vstart <- " ^ BitStr(vstart)); RETIRE_SUCCESS } -mapping vsettype_mnemonic : vsetop <-> string ={ - VSETVLI <-> "vsetvli", - VSETVL <-> "vsetvli" -} +mapping clause assembly = VSETVLI(ma, ta, sew, lmul, rs1, rd) + <-> "vsetvli" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ sew_flag(sew) ^ maybe_lmul_flag(lmul) ^ maybe_ta_flag(ta) ^ maybe_ma_flag(ma) -mapping clause assembly = VSET_TYPE(op, ma, ta, sew, lmul, rs1, rd) - <-> vsettype_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ sew_flag(sew) ^ maybe_lmul_flag(lmul) ^ maybe_ta_flag(ta) ^ maybe_ma_flag(ma) +/* *********************************** vsetvl ************************************ */ +union clause ast = VSETVL : (regidx, regidx, regidx) -/* ********************************* vsetivli ************************************ */ -union clause ast = VSETI_TYPE : ( bits(1), bits(1), bits(3), bits(3), regidx, regidx) +mapping clause encdec = VSETVL(rs2, rs1, rd) if haveVExt() + <-> 0b1000000 @ rs2 @ rs1 @ 0b111 @ rd @ 0b1010111 if haveVExt() -mapping clause encdec = VSETI_TYPE(ma, ta, sew, lmul, uimm, rd) if haveVExt() - <-> 0b1100 @ ma @ ta @ sew @ lmul @ uimm @ 0b111 @ rd @ 0b1010111 if haveVExt() - -function clause execute VSETI_TYPE(ma, ta, sew, lmul, uimm, rd) = { - let VLEN_pow = get_vlen_pow(); - let ELEN_pow = get_elen_pow(); +function clause execute VSETVL(rs2, rs1, rd) = { let LMUL_pow_ori = get_lmul_pow(); let SEW_pow_ori = get_sew_pow(); let ratio_pow_ori = SEW_pow_ori - LMUL_pow_ori; /* set vtype */ - vtype.bits = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul; + vtype.bits = X(rs2); - /* check legal SEW and LMUL and calculate VLMAX */ + /* check new SEW and LMUL are legal and calculate VLMAX */ + let VLEN_pow = get_vlen_pow(); + let ELEN_pow = get_elen_pow(); let LMUL_pow_new = get_lmul_pow(); let SEW_pow_new = get_sew_pow(); - if SEW_pow_new > LMUL_pow_new + ELEN_pow then { - /* Note: Implementations can set vill or trap if the vtype setting is not supported. - * TODO: configuration support for both solutions - */ - vtype.bits = 0b1 @ zeros(sizeof(xlen) - 1); /* set vtype.vill */ - vl = zeros(); - print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); - print_reg("CSR vl <- " ^ BitStr(vl)); - return RETIRE_SUCCESS - }; + if SEW_pow_new > (LMUL_pow_new + ELEN_pow) then { handle_illegal_vtype(); return RETIRE_SUCCESS }; let VLMAX = int_power(2, VLEN_pow + LMUL_pow_new - SEW_pow_new); - let AVL = unsigned(uimm); /* AVL is encoded as 5-bit zero-extended imm in the rs1 field */ /* set vl according to VLMAX and AVL */ - vl = if AVL <= VLMAX then to_bits(sizeof(xlen), AVL) - else if AVL < 2 * VLMAX then to_bits(sizeof(xlen), (AVL + 1) / 2) - else to_bits(sizeof(xlen), VLMAX); - /* Note: ceil(AVL / 2) ≤ vl ≤ VLMAX when VLMAX < AVL < (2 * VLMAX) - * TODO: configuration support for either using ceil(AVL / 2) or VLMAX - */ - X(rd) = vl; + if (rs1 != 0b00000) then { /* normal stripmining */ + let rs1_val = X(rs1); + let AVL = unsigned(rs1_val); + vl = calculate_new_vl(AVL, VLMAX); + X(rd) = vl; + } else if (rd != 0b00000) then { /* set vl to VLMAX */ + let AVL = unsigned(ones(sizeof(xlen))); + vl = to_bits(sizeof(xlen), VLMAX); + X(rd) = vl; + } else { /* keep existing vl */ + let AVL = unsigned(vl); + let ratio_pow_new = SEW_pow_new - LMUL_pow_new; + if (ratio_pow_new != ratio_pow_ori) then { handle_illegal_vtype(); return RETIRE_SUCCESS } + }; + + /* reset vstart to 0 */ + vstart = zeros(); + print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); print_reg("CSR vl <- " ^ BitStr(vl)); + print_reg("CSR vstart <- " ^ BitStr(vstart)); + + RETIRE_SUCCESS +} + +mapping clause assembly = VSETVL(rs2, rs1, rd) + <-> "vsetvl" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2) + +/* ********************************** vsetivli *********************************** */ +union clause ast = VSETIVLI : ( bits(1), bits(1), bits(3), bits(3), regidx, regidx) + +mapping clause encdec = VSETIVLI(ma, ta, sew, lmul, uimm, rd) if haveVExt() + <-> 0b1100 @ ma @ ta @ sew @ lmul @ uimm @ 0b111 @ rd @ 0b1010111 if haveVExt() + +function clause execute VSETIVLI(ma, ta, sew, lmul, uimm, rd) = { + /* set vtype */ + vtype.bits = 0b0 @ zeros(sizeof(xlen) - 9) @ ma @ ta @ sew @ lmul; + + /* check new SEW and LMUL are legal and calculate VLMAX */ + let VLEN_pow = get_vlen_pow(); + let ELEN_pow = get_elen_pow(); + let LMUL_pow_new = get_lmul_pow(); + let SEW_pow_new = get_sew_pow(); + if SEW_pow_new > (LMUL_pow_new + ELEN_pow) then { handle_illegal_vtype(); return RETIRE_SUCCESS }; + let VLMAX = int_power(2, VLEN_pow + LMUL_pow_new - SEW_pow_new); + + /* set vl according to VLMAX and AVL */ + let AVL = unsigned(uimm); /* AVL is encoded as 5-bit zero-extended imm in the rs1 field */ + vl = calculate_new_vl(AVL, VLMAX); + X(rd) = vl; /* reset vstart to 0 */ vstart = zeros(); + + print_reg("CSR vtype <- " ^ BitStr(vtype.bits)); + print_reg("CSR vl <- " ^ BitStr(vl)); print_reg("CSR vstart <- " ^ BitStr(vstart)); RETIRE_SUCCESS } -mapping clause assembly = VSETI_TYPE(ma, ta, sew, lmul, uimm, rd) +mapping clause assembly = VSETIVLI(ma, ta, sew, lmul, uimm, rd) <-> "vsetivli" ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_5(uimm) ^ sep() ^ sew_flag(sew) ^ maybe_lmul_flag(lmul) ^ maybe_ta_flag(ta) ^ maybe_ma_flag(ma) |