diff --git a/cfgs/qc_iu/arch_overlay/ext/Xqciu.yaml b/cfgs/qc_iu/arch_overlay/ext/Xqciu.yaml new file mode 100644 index 000000000..8d0c44d35 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/ext/Xqciu.yaml @@ -0,0 +1,25 @@ +--- +Xqciu: + long_name: Qualcomm DSP extensions + type: unprivileged + versions: + - version: 0.1 + state: development + ratification_date: null + contributors: + - name: Albert Yosher + company: Qualcomm Technologies, Inc. + email: ayosher@qti.qualcomm.com + - name: Derek Hower + company: Qualcomm Technologies, Inc. + email: dhower@qti.qualcomm.com + description: | + Custom instructions for the Qualcomm RVIU. + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ + company: + name: Qualcomm Technologies, Inc. + url: https://qualcomm.com + + \ No newline at end of file diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addsat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addsat.yaml new file mode 100644 index 000000000..d58b013f3 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addsat.yaml @@ -0,0 +1,43 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.addsat: + long_name: Saturating signed addition + description: | + Add signed values rs1 and rs2, saturate the signed result, and write to rd. + definedBy: Xqciu + encoding: + match: 0001110----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg sum = X[rs1] + X[rs2]; + XReg most_negative_number = 1 << (xlen() - 1); + XReg most_positive_number = (1 << (xlen() - 1)) - 1; + + # overflow occurs if the operands are the same sign and the result is a different sign + if (X[rs1][xlen()-1] == X[rs2][xlen()-1]) { + if (sum[xlen()-1] != X[rs1][xlen()-1]) { + if ($signed(X[rs1]) < 0) { + X[rd] = most_negative_number; + } else { + X[rd] = most_positive_number; + } + } + } + + # otherwise, overflow did not occur + X[rd] = sum; diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addusat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addusat.yaml new file mode 100644 index 000000000..864a5cb18 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.addusat.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.addusat: + long_name: Saturating unsigned addition + description: | + Add unsigned values rs1 and rs2, saturate the unsigned result, and write to rd. + definedBy: Xqciu + encoding: + match: 0001111----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg sum = X[rs1] + X[rs2]; + + # overflow occurs if the msb of at least one operand is 1 and the msb of the sum is not + if ((X[rs1][xlen()-1] == 1) || (X[rs2][xlen()-1] == 1)) { + if (sum[xlen()-1] == 0) { + X[rd] = ~{XLEN{1'b0}}; # return largest number + } + } + + # otherwise, overflow did not occur + X[rd] = sum; diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.beqi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.beqi.yaml new file mode 100644 index 000000000..06c97a2fc --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.beqi.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.beqi: + long_name: Branch on equal (immediate) + description: | + Branches to PC + offset if the value in rs1 is equal to the signed immediate + definedBy: Xqciu + encoding: + match: -----------------000-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if ($signed(X[rs1]) == $signed(imm)) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgei.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgei.yaml new file mode 100644 index 000000000..23fb63f2a --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgei.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.bgei: + long_name: Branch on greater than or equal (immediate) + description: | + Branches to PC + offset if the value in rs1 is greater than or equal to the immediate. + definedBy: Xqciu + encoding: + match: -----------------101-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if ($signed(X[rs1]) >= $signed(imm)) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgeui.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgeui.yaml new file mode 100644 index 000000000..b5b7b49a8 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bgeui.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.bgeui: + long_name: Branch on greater than or equal unsigned (immediate) + description: | + Branches to PC + offset if the unsigned value in rs1 is greater than or equal to the unsigned immediate. + definedBy: Xqciu + encoding: + match: -----------------111-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (X[rs1] >= imm) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.blti.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.blti.yaml new file mode 100644 index 000000000..6d04b0fc7 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.blti.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.blti: + long_name: Branch on less than (immediate) + description: | + Branches to PC + offset if the value in rs1 is less than the immediate. + definedBy: Xqciu + encoding: + match: -----------------100-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if ($signed(X[rs1]) < $signed(imm)) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bltui.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bltui.yaml new file mode 100644 index 000000000..1cdf3d3af --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bltui.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.bltui: + long_name: Branch on less than unsigned (immediate) + description: | + Branches to PC + offset if the unsigned value in rs1 is less than the unsigned immediate. + definedBy: Xqciu + encoding: + match: -----------------110-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (X[rs1] < imm) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bnei.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bnei.yaml new file mode 100644 index 000000000..95a99a06e --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.bnei.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.bnei: + long_name: Branch on not equal (immediate) + description: | + Branches to PC + offset if the value in rs1 is not equal to the signed immediate + definedBy: Xqciu + encoding: + match: -----------------001-----1111011 + variables: + - name: offset + location: 31|7|30-25|11-8 + left_shift: 1 + - name: imm + location: 24-20 + not: 0 + - name: rs1 + location: 19-15 + not: 0 + assembly: xs1, imm, offset + access: + s: always + u: always + vs: always + vu: always + operation(): | + if ($signed(X[rs1]) != $signed(imm)) { + jump(PC + $signed(offset)); + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.brev.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.brev.yaml new file mode 100644 index 000000000..e94e11be2 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.brev.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.brev: + long_name: Reverse bit order + description: | + Reverses the bit order of rs1 and writes the result to rd + definedBy: Xqciu + encoding: + match: 000011000000-----011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg orig_val = X[rs1]; + XReg tmp; + + for (U32 i=0; i pair = {X[rs1 + 1], X[rs1]}; + + X[rd] = sext((pair >> shamt) & ((1 << width) - 1), width-1); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extdu.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extdu.yaml new file mode 100644 index 000000000..9aab18607 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extdu.yaml @@ -0,0 +1,33 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.extdu: + long_name: Extract bits from pair unsigned + description: | + Extract a subset of bits from the register pair [rs, rs+1] into rd. + + The width of the subset is determined by width[4:0], + and the offset (into the pair) of the subset is determined by shamt[4:0]. + definedBy: Xqciu + base: 32 + encoding: + match: 10---------------010-----0001011 + variables: + - name: width + location: 29-25 + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm, shamt, width + access: + s: always + u: always + vs: always + vu: always + operation(): | + Bits<{1'b0, XLEN}*2> pair = {X[rs1 + 1], X[rs1]}; + + X[rd] = (pair >> shamt) & ((1 << width) - 1); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.exts.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.exts.yaml new file mode 100644 index 000000000..4bef698ec --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.exts.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.exts: + long_name: Extract bits signed + description: | + Extract a subset of bits from rs1 into rd, and sign-extend the result. + + The width of the subset is determined by width[4:0], + and the offset of the subset is determined by shamt[4:0]. + definedBy: Xqciu + base: 32 + encoding: + match: 00---------------010-----0001011 + variables: + - name: width + location: 29-25 + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm, shamt, width + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg unsigned_extraction = (X[rs1] >> shamt) & ((1 << width) - 1); + + X[rd] = sext(unsigned_extraction, width - 1); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extu.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extu.yaml new file mode 100644 index 000000000..821153207 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.extu.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.extu: + long_name: Extract bits unsigned + description: | + Extract a subset of bits from rs1 into rd. + + The width of the subset is determined by width[4:0], + and the offset of the subset is determined by shamt[4:0]. + definedBy: Xqciu + base: 32 + encoding: + match: 00---------------010-----0001011 + variables: + - name: width + location: 29-25 + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm, shamt, width + access: + s: always + u: always + vs: always + vu: always + operation(): | + X[rd] = (X[rs1] >> shamt) & ((1 << width) - 1); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insb.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insb.yaml new file mode 100644 index 000000000..0c44cd0b1 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insb.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.insb: + long_name: Insert bits (register) + description: | + Insertion of a subset of bits from rs1 into rd. + + The width of the subset is determined by width[4:0], + and the offset of the subset is determined by shamt[4:0]. + definedBy: Xqciu + base: 32 + encoding: + match: 01---------------001-----0001011 + variables: + - name: width + location: 29-25 + - name: shamt + location: 24-20 + - name: rs1 + location: 19-15 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm, shamt, width + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg mask = ((1 << width) - 1) << shamt; + XReg orig_val = X[rd]; + + X[rd] = (orig_val & ~mask) | ((X[rs1] << shamt) & mask); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insbi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insbi.yaml new file mode 100644 index 000000000..caba04aa5 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.insbi.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.insbi: + long_name: Insert bits (immediate) + description: | + Insertion of a subset of bits of an immediate into rd. + + The width of the subset is determined by width[4:0], + and the offset of the subset is determined by shamt[4:0]. + definedBy: Xqciu + base: 32 + encoding: + match: 00---------------001-----0001011 + variables: + - name: width + location: 29-25 + - name: shamt + location: 24-20 + - name: imm + location: 19-15 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm, shamt, width + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg mask = ((1 << width) - 1) << shamt; + XReg orig_val = X[rd]; + + X[rd] = (orig_val & ~mask) | ((imm << shamt) & mask); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lli.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lli.yaml new file mode 100644 index 000000000..8b53b671a --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lli.yaml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.lli: + long_name: Load immediate large + description: | + Loads the 20-bit immediate into rd. + definedBy: Xqciu + encoding: + match: -------------------------0011011 + variables: + - name: imm + location: 31|15-12|30-16 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm + access: + s: always + u: always + vs: always + vu: always + operation(): | + X[rd] = imm; diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwm.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwm.yaml new file mode 100644 index 000000000..6510333f7 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwm.yaml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.lwm: + long_name: Load word multiple + description: | + Loads multiple words starting from address (rs1 + imm) to registers, starting from rd. + + The number of words is in rs2 + definedBy: + - [Xqciu, ">= 0"] + - [Xqciu, ">= 0"] + encoding: + match: 01---------------111-----0001011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + XReg num_words = X[rs2]; + + raise (ExceptionCode::IllegalInstruction, $encoding) if ((rd + num_words) > 32); + + for (U32 i = 0; i < num_words; i++) { + X[rd + i] = read_memory<32>(vaddr); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwmi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwmi.yaml new file mode 100644 index 000000000..dd5110df9 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.lwmi.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.lwmi: + long_name: Load word multiple (immediate) + description: | + Loads multiple words starting from address (rs1 + imm) to registers, starting from rd. + + The number of words is in the `length` immediate. + definedBy: Xqciu + encoding: + match: 01---------------111-----0001011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: length + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, imm + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + + raise (ExceptionCode::IllegalInstruction, $encoding) if ((rd + length) > 32); + + for (U32 i = 0; i < length; i++) { + X[rd + i] = read_memory<32>(vaddr); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.mpyaddi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.mpyaddi.yaml new file mode 100644 index 000000000..f9722d02a --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.mpyaddi.yaml @@ -0,0 +1,28 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.mpyaddi: + long_name: Multiply and accumulate (immediate) + description: | + Increments rd by the multiplication of rs1 and an unsigned immediate + definedBy: Xqciu + encoding: + match: -----------------110-----0001011 + variables: + - name: imm + location: 31-20 + - name: rs1 + location: 19-15 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, imm + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg orig_val = X[rd]; + + X[rd] = orig_val + (X[rs1] * imm); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwm.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwm.yaml new file mode 100644 index 000000000..8f1357402 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwm.yaml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.setwm: + long_name: Set word multiple (Register) + description: | + Stores the value of rs3 multiple times into the address starting at (rs1 + imm). + + The number of writes is in rs2. + definedBy: Xqciu + encoding: + match: 10---------------111-----0101011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: rs2 + location: 24-20 + not: 0 + - name: rs3 + location: 11-7 + not: 0 + assembly: xs3, imm(xs1), xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + Bits<32> write_value = X[rs3][31:0]; + + XReg num_words = X[rs2]; + + for (U32 i = 0; i < num_words; i++) { + write_memory<32>(vaddr, write_value); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwmi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwmi.yaml new file mode 100644 index 000000000..5a5c4a2cb --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.setwmi.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.setwmi: + long_name: Set word multiple (Immediate) + description: | + Stores the value of rs3 multiple times into the address starting at (rs1 + imm). + + The number of writes is in `length`. + definedBy: Xqciu + encoding: + match: 11---------------111-----0101011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: length + location: 24-20 + not: 0 + - name: rs3 + location: 11-7 + not: 0 + assembly: xs3, imm(xs1), xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + Bits<32> write_value = X[rs3][31:0]; + + for (U32 i = 0; i < length; i++) { + write_memory<32>(vaddr, write_value); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.slasat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.slasat.yaml new file mode 100644 index 000000000..ed7432475 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.slasat.yaml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.slasat: + long_name: Saturating arithmetic left shift + description: | + Left shift rs1 by the value of rs2, and saturate the signed result. + + The number of words is in `length`. + definedBy: Xqciu + encoding: + match: 0001010----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + Bits<{1'b0, XLEN}*2> shifted_value = X[rs1] << X[rs2][4:0]; + XReg most_negative_number = 1 << (xlen() - 1); + XReg most_positive_number = (1 << (xlen() - 1) - 1); + + if ($signed(shifted_value) < $signed(most_negative_number)) { + X[rd] = most_negative_number; + } else if ($signed(shifted_value) > $signed(most_positive_number)) { + X[rd] = most_positive_number; + } else { + X[rd] = shifted_value; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.sllsat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.sllsat.yaml new file mode 100644 index 000000000..48190eeeb --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.sllsat.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.sllsat: + long_name: Saturating logical left shift + description: | + Left shift rs1 by the value of rs2, and saturate the unsigned result. + + The number of words is in `length`. + definedBy: Xqciu + encoding: + match: 0001100----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + Bits<{1'b0, XLEN}*2> sext_double_width_rs1 = {{XLEN{X[rs1][xlen()-1]}}, X[rs1]}; + Bits<{1'b0, XLEN}*2> shifted_value = sext_double_width_rs1 << X[rs2][4:0]; + XReg largest_unsigned_value = {XLEN{1'b1}}; + + if (shifted_value > largest_unsigned_value) { + X[rd] = largest_unsigned_value; + } else { + X[rd] = shifted_value; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subsat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subsat.yaml new file mode 100644 index 000000000..4e3d72c24 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subsat.yaml @@ -0,0 +1,43 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.subsat: + long_name: Saturating signed subtraction + description: | + Subtract signed values rs1 and rs2, saturate the signed result, and write to rd. + definedBy: Xqciu + encoding: + match: 0010000----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg result = X[rs1] - X[rs2]; + XReg most_negative_number = 1 << (xlen() - 1); + XReg most_positive_number = (1 << (xlen() - 1)) - 1; + + # overflow occurs if the operands have different signs and the result is a different sign than the first operand + if (X[rs1][xlen()-1] != X[rs2][xlen()-1]) { + if (result[xlen()-1] != X[rs1][xlen()-1]) { + if ($signed(X[rs1]) < 0) { + X[rd] = most_negative_number; + } else { + X[rd] = most_positive_number; + } + } + } + + # otherwise, overflow did not occur + X[rd] = result; diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subusat.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subusat.yaml new file mode 100644 index 000000000..5d6716b89 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.subusat.yaml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.subusat: + long_name: Saturating unsigned subtraction + description: | + Subtract unsigned values rs1 and rs2, saturate the unsigned result, and write to rd. + definedBy: Xqciu + encoding: + match: 0010001----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + not: 0 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, xs1, xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + X[rd] = (X[rs1] < X[rs2]) ? 0 : X[rs1] - X[rs2]; diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swm.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swm.yaml new file mode 100644 index 000000000..3deecc72c --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swm.yaml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.swm: + long_name: Store word multiple + description: | + Stores multiple words from the registers starting at rs3 to the address starting at (rs1 + imm). + + The number of words is in rs2. + definedBy: Xqciu + encoding: + match: 00---------------111-----0101011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: rs2 + location: 24-20 + not: 0 + - name: rs3 + location: 11-7 + not: 0 + assembly: xs3, imm(xs1), xs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + XReg num_words = X[rs2]; + + raise (ExceptionCode::IllegalInstruction, $encoding) if ((rs3 + num_words) > 32); + + for (U32 i = 0; i < num_words; i++) { + write_memory<32>(vaddr, X[rs3 + i]); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swmi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swmi.yaml new file mode 100644 index 000000000..9dffe96ec --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.swmi.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.swmi: + long_name: Store word multiple (immediate) + description: | + Stores multiple words from the registers starting at rs3 to the address starting at (rs1 + imm). + + The number of words is in `length`. + definedBy: Xqciu + encoding: + match: 00---------------111-----0101011 + variables: + - name: imm + location: 30-25 + left_shift: 2 + - name: rs1 + location: 19-15 + - name: length + location: 24-20 + not: 0 + - name: rs3 + location: 11-7 + not: 0 + assembly: xs3, imm(xs1), \#length + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg vaddr = X[rs1] + imm; + + raise (ExceptionCode::IllegalInstruction, $encoding) if ((rs3 + length) > 32); + + for (U32 i = 0; i < length; i++) { + write_memory<32>(vaddr, X[rs3 + i]); + vaddr = vaddr + 4; + } diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrap.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrap.yaml new file mode 100644 index 000000000..748e0cb3a --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrap.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.wrap: + long_name: Wraparound addition + description: | + Adds an immediate value to rs1. If the result overflows, store the amount of overflow. + + The number of words is in `length`. + definedBy: Xqciu + encoding: + match: 0010010----------011-----0001011 + variables: + - name: rs1 + location: 19-15 + - name: rs2 + location: 24-20 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, rs1, rs2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg rs1_value = X[rs1]; + + X[rd] = ($signed(rs1_value) >= $signed(X[rs2])) + ? rs1_value - X[rs2] + : (($signed(rs1_value) < 0) + ? (rs1_value + X[rs2]) + : rs1_value); diff --git a/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrapi.yaml b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrapi.yaml new file mode 100644 index 000000000..590b2edb1 --- /dev/null +++ b/cfgs/qc_iu/arch_overlay/inst/Xqciu/qc.wrapi.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../../../schemas/inst_schema.json + +qc.wrapi: + long_name: Wraparound addition (Immediate) + description: | + Adds an immediate value to rs1. If the result overflows, store the amount of overflow. + + The number of words is in `length`. + definedBy: Xqciu + encoding: + match: 0----------------000-----0001011 + variables: + - name: imm + location: 30-20 + - name: rs1 + location: 19-15 + not: 0 + - name: rd + location: 11-7 + not: 0 + assembly: xd, rs1, imm + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg rs1_value = X[rs1]; + + X[rd] = ($signed(rs1_value) >= imm) + ? rs1_value - imm + : (($signed(rs1_value) < 0) + ? (rs1_value + imm) + : rs1_value); diff --git a/cfgs/qc_iu/params.yaml b/cfgs/qc_iu/params.yaml new file mode 100644 index 000000000..97707cfad --- /dev/null +++ b/cfgs/qc_iu/params.yaml @@ -0,0 +1,315 @@ +# yaml-language-server: $schema=../../schemas/config_schema.json + +--- +params: + XLEN: 32 + + # name of the configuration + NAME: qc_iu + + # vendor-specific architecture ID in marchid + ARCH_ID: 0x1000000000000000 + + # vendor-specific implementation ID in mimpid + IMP_ID: 0x0 + + # JEDEC Vendor ID bank (Qualcomm = 0) + VENDOR_ID_BANK: 0x0 + + # JEDEC Vendor ID offset (Qualcomm = 0x70) + VENDOR_ID_OFFSET: 0x70 + + # whether or not the implementation supports misaligned loads and stores in main memory (not including atomics) + # must be true when Zicclsm is supported + MISALIGNED_LDST: true + + # whether or not the implementation supports misaligned atomics + MISALIGNED_AMO: false + + # number of implemented programmable hardware performance counters + NUM_HPM_COUNTERS: 8 + + # Indicates which counters can be disabled from mcountinhibit + # + # An unimplemented counter cannot be specified, i.e., if + # NUM_HPM_COUNTERS == 8, it would be illegal to add index + # 11 in COUNTINHIBIT_EN since the highest implemented counter + # would be at bit 10 + COUNTINHIBIT_EN: + - true # CY + - false # empty + - true # IR + - true # HPME3 + - true # HPME4 + - true # HPME5 + - true # HPME6 + - true # HPME7 + - true # HPME8 + - true # HPME9 + - true # HPME10 + - false # HPME11 + - false # HPME12 + - false # HPME13 + - false # HPME14 + - false # HPME15 + - false # HPME16 + - false # HPME17 + - false # HPME18 + - false # HPME19 + - false # HPME20 + - false # HPME21 + - false # HPME22 + - false # HPME23 + - false # HPME24 + - false # HPME25 + - false # HPME26 + - false # HPME27 + - false # HPME28 + - false # HPME29 + - false # HPME30 + - false # HPME31 + + MISALIGNED_SPLIT_STRATEGY: by_byte + + # list of defined HPM events + HPM_EVENTS: + - 0 + - 3 + + # Indicates which counters can delegated via mcounteren + # + # An unimplemented counter cannot be specified, i.e., if + # NUM_HPM_COUNTERS == 8, it would be illegal to add index + # 11 in COUNTEN_EN since the highest implemented counter + # would be at bit 10 + COUNTENABLE_EN: + - true # CY + - false # empty + - true # IR + - true # HPME3 + - true # HPME4 + - true # HPME5 + - true # HPME6 + - true # HPME7 + - true # HPME8 + - true # HPME9 + - true # HPME10 + - false # HPME11 + - false # HPME12 + - false # HPME13 + - false # HPME14 + - false # HPME15 + - false # HPME16 + - false # HPME17 + - false # HPME18 + - false # HPME19 + - false # HPME20 + - false # HPME21 + - false # HPME22 + - false # HPME23 + - false # HPME24 + - false # HPME25 + - false # HPME26 + - false # HPME27 + - false # HPME28 + - false # HPME29 + - false # HPME30 + - false # HPME31 + + # when true, writing an illegal value to a WLRL CSR field raises an Illegal Instruction exception + # when false, writing an illegal value to a WLRL CSR field is ignored + TRAP_ON_ILLEGAL_WLRL: true + + # when true, *tval is written with the virtual PC of the EBREAK instruction (same information as *epc) + # when false, *tval is written with 0 on an EBREAK instruction + # + # regardless, *tval is always written with a virtual PC when an external breakpoint is generated + REPORT_VA_IN_MTVAL_ON_BREAKPOINT: true + + REPORT_VA_IN_MTVAL_ON_LOAD_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: true + REPORT_VA_IN_MTVAL_ON_LOAD_PAGE_FAULT: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_PAGE_FAULT: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT: true + REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: true + REPORT_CAUSE_IN_MTVAL_ON_SOFTWARE_CHECK: true + MTVAL_WIDTH: 64 # must check that this can hold any valid VA if any REPORT_VA* or Sdext, and, if REPORT_ENCODING*, at least [MXLEN, ILEN].min bits + + REPORT_VA_IN_STVAL_ON_BREAKPOINT: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: true + REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: true + REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: true + REPORT_CAUSE_IN_STVAL_ON_SOFTWARE_CHECK: true + STVAL_WIDTH: 64 # must check that this can hold any valid VA, and, if REPORT_ENCODING*, at least [SXLEN, ILEN].min bits + + REPORT_VA_IN_VSTVAL_ON_BREAKPOINT: true + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_MISALIGNED: true + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_MISALIGNED: true + REPORT_VA_IN_VSTVAL_ON_LOAD_ACCESS_FAULT: true + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_ACCESS_FAULT: true + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_ACCESS_FAULT: true + REPORT_VA_IN_VSTVAL_ON_LOAD_PAGE_FAULT: true + REPORT_VA_IN_VSTVAL_ON_STORE_AMO_PAGE_FAULT: true + REPORT_VA_IN_VSTVAL_ON_INSTRUCTION_PAGE_FAULT: true + REPORT_ENCODING_IN_VSTVAL_ON_ILLEGAL_INSTRUCTION: true + REPORT_CAUSE_IN_VSTVAL_ON_SOFTWARE_CHECK: true + # VSTVAL_WIDTH not needed; "vstval is a WARL register that must be able to hold the same set of values that stval can hold" + + # address of the unified discovery configuration data structure + # this address is reported in the mconfigptr CSR + CONFIG_PTR_ADDRESS: 0x1000 + + # number of implemented PMP entries. Can be any value between 0-64, inclusive. + # + # the number of implemented PMP registers must be 0, 16, or 64. + # + # Therefore, whether or not a pmpaddrN or pmpcfgN register exists depends on + # NUM_PMP_ENTRIES as follows: + # |=== + # | NUM_PMP_ENTRIES | pmpaddr<0-15> / pmpcfg<0-3> | pmpaddr<16-63> / pmpcfg<4-15> + # | 0 | N | N + # | 1-16 | Y | N + # | 17-64 | Y | Y + # |=== + # ** pmpcfgN for an odd N never exist when XLEN == 64 + # + # when NUM_PMP_ENTRIES is not exactly 0, 16, or 64, some extant pmp registers, + # and associated pmpNcfg, will be read-only zero (but will not cause an exception). + NUM_PMP_ENTRIES: 14 + + # log2 of the smallest supported PMP region + # generally, for systems with an MMU, should not be smaller than 12, + # as that would preclude caching PMP results in the TLB along with + # virtual memory translations + # + # Note that PMP_GRANULARITY is equal to G+2 (not G) as described in + # the privileged architecture + PMP_GRANULARITY: 12 + + # log2 of the smallest supported PMA region + # generally, for systems with an MMU, should not be smaller than 12, + # as that would preclude caching PMP results in the TLB along with + # virtual memory translations + PMA_GRANULARITY: 12 + + # number of bits in the physical address space + PHYS_ADDR_WIDTH: 34 + + # number of implemented ASID bits + # maximum value is 16 + ASID_WIDTH: 12 + + # when the A extension is supported, indicates whether or not + # the extension can be disabled in the `misa.A` bit. + MUTABLE_MISA_A: false + + # when the B extension is supported, indicates whether or not + # the extension can be disabled in the `misa.B` bit. + MUTABLE_MISA_B: false + + # when the C extension is supported, indicates whether or not + # the extension can be disabled in the `misa.C` bit. + MUTABLE_MISA_C: false + + # size of a cache block, in bytes + CACHE_BLOCK_SIZE: 64 + + # number of supported virtualized guest interrupts + # corresponds to the `GEILEN` parameter in the RVI specs + NUM_EXTERNAL_GUEST_INTERRUPTS: 4 + + # Endianess of data in M-mode. Can be one of: + # + # * 0: M-mode data is always little endian + # * 1: M-mode data is always big endian + # * 2: M-mode data can be either little or big endian, depending on the RW CSR field mstatus.MBE + M_MODE_ENDIANESS: 0 + + # Endianess of data in M-mode. Can be one of: + # + # * 0: S-mode data is always little endian + # * 1: S-mode data is always big endian + # * 2: S-mode data can be either little or big endian, depending on the RW CSR field mstatus.SBE + S_MODE_ENDIANESS: 0 + + # Endianess of data in M-mode. Can be one of: + # + # * 0: U-mode data is always little endian + # * 1: U-mode data is always big endian + # * 2: U-mode data can be either little or big endian, depending on the RW CSR field mstatus.UBE + U_MODE_ENDIANESS: 0 + + # Endianess of data in VU-mode. Can be one of: + # + # * 0: VU-mode data is always little endian + # * 1: VU-mode data is always big endian + # * 2: VU-mode data can be either little or big endian, depending on the RW CSR field vsstatus.UBE + VU_MODE_ENDIANESS: 0 + + # Endianess of data in VS-mode. Can be one of: + # + # * 0: VS-mode data is always little endian + # * 1: VS-mode data is always big endian + # * 2: VS-mode data can be either little or big endian, depending on the RW CSR field hstatus.VSBE + VS_MODE_ENDIANESS: 0 + + # XLENs supported in U-mode. Can be one of: + # + # * 32: SXLEN is always 32 + # * 64: SXLEN is always 64 + # * 3264: SXLEN can be changed (via mstatus.SXL) between 32 and 64 + UXLEN: 32 + + # XLENs supported in VS-mode. Can be one of: + # + # * 32: VSXLEN is always 32 + # * 64: VSXLEN is always 64 + # * 3264: VSXLEN can be changed (via hstatus.VSXL) between 32 and 64 + VSXLEN: 32 + + # XLENs supported in VS-mode. Can be one of: + # + # * 32: VSXLEN is always 32 + # * 64: VSXLEN is always 64 + # * 3264: VSXLEN can be changed (via hstatus.VSXL) between 32 and 64 + VUXLEN: 32 + + # HAS_FENCE_TSO indicates whether or not the implementation supports the fence.tso instruction + # HAS_FENCE_TSO: true + + # PTE_A_D_ACCESS_EXCEPTION indicates support for hardware PTE access/dirty updates + # + # * true: Hardware automatically updates PTEs according to Svadu + # * false: Hardware does not automatically update PTEs; as such, PageFaults may be generated + # PTE_A_D_ACCESS_EXCEPTION: true + + # STVEC_MODE_DIRECT indicates that stvec.MODE can hold 0 (Direct) + # STVEC_MODE_DIRECT: true + +hpm_events: + - 'L1_ICACHE_MISS' + - 'L2_CACHE_MISS' + +extensions: + - [A, 2.1] + - [B, 1.0] + - [D, 2.2] + # - [F, 2.2] + - [I, 2.1] + - [M, 2.0] + - [Zicntr, 2.0] + - [Zicsr, 2.0] + - [Zihpm, 2.0] + - [Zicboz, "1.0.1-b34ea8a"] + - [Zicbom, "1.0.1-b34ea8a"] + - [Xqciu, 0.1]