From 653c27135d0d5437c663f35c4dd57635564e24dd Mon Sep 17 00:00:00 2001 From: Metehan Dundar Date: Tue, 11 Mar 2025 05:10:03 +0100 Subject: [PATCH] Add initial support for RISC-V architecture and update relevant files --- osaca/data/isa/riscv.yml | 688 ++++++++++++++++++++++++++++++ osaca/data/rv64.yml | 1 + osaca/db_interface.py | 48 ++- osaca/osaca.py | 9 +- osaca/semantics/arch_semantics.py | 22 + osaca/semantics/hw_model.py | 1 + osaca/semantics/isa_semantics.py | 37 +- osaca/semantics/marker_utils.py | 1 + tests/test_files/kernel_riscv.s | 324 ++++++++------ tests/test_parser_RISCV.py | 6 +- 10 files changed, 1009 insertions(+), 128 deletions(-) create mode 100644 osaca/data/isa/riscv.yml create mode 100644 osaca/data/rv64.yml diff --git a/osaca/data/isa/riscv.yml b/osaca/data/isa/riscv.yml new file mode 100644 index 0000000..db26210 --- /dev/null +++ b/osaca/data/isa/riscv.yml @@ -0,0 +1,688 @@ +--- +osaca_version: 0.6.1 +isa: riscv +# Contains all operand-irregular instruction forms OSACA supports for RISC-V. +# Operand-regular for a RISC-V instruction form with N operands in the shape of +# mnemonic op1 ... opN +# means that op1 is the only destination operand and op2 to op(N) are source operands. +# For vector instructions with suffixes (.v, .vv, .vf), the operand behavior follows +# the base instruction pattern. +instruction_forms: + - name: addi + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: immediate + imd: 'int' + source: true + destination: false + - name: add + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: sub + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: mul + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: div + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: and + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: or + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: xor + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: sll + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: srl + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: sra + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - name: lw + operands: + - class: register + prefix: x + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: sw + operands: + - class: register + prefix: x + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: false + destination: true + - name: lb + operands: + - class: register + prefix: x + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: sb + operands: + - class: register + prefix: x + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: false + destination: true + - name: lh + operands: + - class: register + prefix: x + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: sh + operands: + - class: register + prefix: x + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: false + destination: true + - name: beq + operands: + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - class: identifier + source: true + destination: false + - name: bne + operands: + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - class: identifier + source: true + destination: false + - name: blt + operands: + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - class: identifier + source: true + destination: false + - name: bge + operands: + - class: register + prefix: x + source: true + destination: false + - class: register + prefix: x + source: true + destination: false + - class: identifier + source: true + destination: false + - name: jal + operands: + - class: register + prefix: x + source: false + destination: true + - class: identifier + source: true + destination: false + - name: jalr + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: immediate + imd: 'int' + source: true + destination: false + - name: lui + operands: + - class: register + prefix: x + source: false + destination: true + - class: immediate + imd: 'int' + source: true + destination: false + - name: auipc + operands: + - class: register + prefix: x + source: false + destination: true + - class: immediate + imd: 'int' + source: true + destination: false + - name: li + operands: + - class: register + prefix: x + source: false + destination: true + - class: immediate + imd: 'int' + source: true + destination: false + - name: mv + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - name: ret + operands: [] + - name: j + operands: + - class: identifier + source: true + destination: false + - name: jr + operands: + - class: register + prefix: x + source: true + destination: false + # Floating-point instructions + - name: flw + operands: + - class: register + prefix: f + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: fsw + operands: + - class: register + prefix: f + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: false + destination: true + - name: fadd + operands: + - class: register + prefix: f + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - class: register + prefix: f + source: true + destination: false + - name: fsub + operands: + - class: register + prefix: f + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - class: register + prefix: f + source: true + destination: false + - name: fmul + operands: + - class: register + prefix: f + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - class: register + prefix: f + source: true + destination: false + - name: fdiv + operands: + - class: register + prefix: f + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - class: register + prefix: f + source: true + destination: false + - name: fmv.x.w + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - name: fmv.w.x + operands: + - class: register + prefix: f + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + # Vector instructions + - name: vsetvli + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - name: vsetivli + operands: + - class: register + prefix: x + source: false + destination: true + - class: immediate + imd: 'int' + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - class: identifier + source: true + destination: false + - name: vle32.v + operands: + - class: register + prefix: v + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: vse32.v + operands: + - class: register + prefix: v + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: false + destination: true + - name: vadd.vv + operands: + - class: register + prefix: v + source: false + destination: true + - class: register + prefix: v + source: true + destination: false + - class: register + prefix: v + source: true + destination: false + - name: vfmv.v.f + operands: + - class: register + prefix: v + source: false + destination: true + - class: register + prefix: f + source: true + destination: false + - name: vfmadd.vv + operands: + - class: register + prefix: v + source: false + destination: true + - class: register + prefix: v + source: true + destination: false + - class: register + prefix: v + source: true + destination: false + - name: vfmacc.vf + operands: + - class: register + prefix: v + source: true + destination: true + - class: register + prefix: f + source: true + destination: false + - class: register + prefix: v + source: true + destination: false + # CSR instructions + - name: csrr + operands: + - class: register + prefix: x + source: false + destination: true + - class: identifier + source: true + destination: false + - name: csrw + operands: + - class: identifier + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - name: csrs + operands: + - class: identifier + source: true + destination: true + - class: register + prefix: x + source: true + destination: false + - name: csrc + operands: + - class: identifier + source: true + destination: true + - class: register + prefix: x + source: true + destination: false + # Atomic instructions + - name: lr.w + operands: + - class: register + prefix: x + source: false + destination: true + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: false + - name: sc.w + operands: + - class: register + prefix: x + source: false + destination: true + - class: register + prefix: x + source: true + destination: false + - class: memory + base: "*" + offset: "*" + index: "*" + scale: "*" + pre_indexed: "*" + post_indexed: "*" + source: true + destination: true \ No newline at end of file diff --git a/osaca/data/rv64.yml b/osaca/data/rv64.yml new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/osaca/data/rv64.yml @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/osaca/db_interface.py b/osaca/db_interface.py index 4107670..b9b4a6c 100644 --- a/osaca/db_interface.py +++ b/osaca/db_interface.py @@ -234,7 +234,11 @@ def _create_db_operand(operand, isa): return _create_db_operand_aarch64(operand) elif isa == "x86": return _create_db_operand_x86(operand) - + elif isa == "riscv": + return _create_db_operand_riscv(operand) + else: + raise ValueError(f"Unsupported ISA: {isa}") + def _create_db_operand_aarch64(operand): """Get DB operand for AArch64 by operand string.""" @@ -282,6 +286,30 @@ def _create_db_operand_x86(operand): raise ValueError("Parameter {} is not a valid operand code".format(operand)) +def _create_db_operand_riscv(operand): + """Get DB operand for RISC-V by operand string.""" + if operand == "i": + return {"class": "immediate", "imd": "int"} + elif operand == "x": + return {"class": "register", "prefix": "x"} # Integer register + elif operand == "f": + return {"class": "register", "prefix": "f"} # Floating point register + elif operand == "v": + return {"class": "register", "prefix": "v"} # Vector register + elif operand.startswith("m"): + return { + "class": "memory", + "base": "x" if "b" in operand else None, + "offset": "int" if "o" in operand else None, + "index": None, # RISC-V doesn't use index registers in memory addressing + "scale": 1, + "pre_indexed": False, # RISC-V doesn't have pre/post indexing like AArch64 + "post_indexed": False, + } + else: + raise ValueError(f"Parameter {operand} is not a valid operand code for RISC-V") + + ######################## # HELPERS SANITY CHECK # ######################## @@ -383,11 +411,29 @@ def _check_sanity_arch_db(arch_mm, isa_mm, internet_check=True): # prefixes of instruction forms which we assume to have non-default operands suspicious_prefixes_x86 = ["vfm", "fm"] suspicious_prefixes_arm = ["fml", "ldp", "stp", "str"] + suspicious_prefixes_riscv = [ + "vfm", # Vector floating-point multiply + "vle", # Vector load + "vse", # Vector store + "vset", # Vector configuration + "vfmacc", # Vector FMA + "vsetvl", # Vector length setting + "vfmv", # Vector floating-point move + "vadd", # Vector add + "vsub", # Vector subtract + "vmul", # Vector multiply + ] + + # Default to empty list if ISA not recognized + suspicious_prefixes = [] + # already known to be default-operand instruction forms with 2 operands if arch_mm.get_ISA().lower() == "aarch64": suspicious_prefixes = suspicious_prefixes_arm if arch_mm.get_ISA().lower() == "x86": suspicious_prefixes = suspicious_prefixes_x86 + if arch_mm.get_ISA().lower() == "riscv": + suspicious_prefixes = suspicious_prefixes_riscv # returned lists missing_throughput = [] diff --git a/osaca/osaca.py b/osaca/osaca.py index d0fb49d..353a3b9 100644 --- a/osaca/osaca.py +++ b/osaca/osaca.py @@ -11,7 +11,7 @@ from ruamel.yaml import YAML from osaca.db_interface import import_benchmark_output, sanity_check from osaca.frontend import Frontend -from osaca.parser import BaseParser, ParserAArch64, ParserX86ATT +from osaca.parser import BaseParser, ParserAArch64, ParserX86ATT, ParserRISCV from osaca.semantics import ( INSTR_FLAGS, ArchSemantics, @@ -42,10 +42,12 @@ SUPPORTED_ARCHS = [ "A72", "M1", "V2", + "RV64", ] DEFAULT_ARCHS = { "aarch64": "V2", "x86": "SPR", + "riscv": "RV64", } @@ -430,7 +432,10 @@ def get_asm_parser(arch) -> BaseParser: return ParserX86ATT() elif isa == "aarch64": return ParserAArch64() - + elif isa == "riscv": + return ParserRISCV() + else: + raise ValueError("Unknown ISA: {}".format(isa)) def get_unmatched_instruction_ratio(kernel): """Return ratio of unmatched from total instructions in kernel.""" diff --git a/osaca/semantics/arch_semantics.py b/osaca/semantics/arch_semantics.py index e87e5e7..01b3930 100644 --- a/osaca/semantics/arch_semantics.py +++ b/osaca/semantics/arch_semantics.py @@ -208,6 +208,16 @@ class ArchSemantics(ISASemantics): instruction_data = self._machine_model.get_instruction( instruction_form.mnemonic[:suffix_start], instruction_form.operands ) + if ( + instruction_data is None + and self._isa == "riscv" + and "." in instruction_form.mnemonic + ): + # Check for instruction without shape suffix (e.g., fadd.s -> fadd) + suffix_start = instruction_form.mnemonic.index(".") + instruction_data = self._machine_model.get_instruction( + instruction_form.mnemonic[:suffix_start], instruction_form.operands + ) if instruction_data: # instruction form in DB ( @@ -251,6 +261,16 @@ class ArchSemantics(ISASemantics): instruction_data_reg = self._machine_model.get_instruction( instruction_form.mnemonic[:suffix_start], operands ) + if ( + instruction_data_reg is None + and self._isa == "riscv" + and "." in instruction_form.mnemonic + ): + # Check for instruction without vector suffix (.v, .vv, .vf, etc.) + suffix_start = instruction_form.mnemonic.index(".") + instruction_data_reg = self._machine_model.get_instruction( + instruction_form.mnemonic[:suffix_start], operands + ) if instruction_data_reg: assign_unknown = False reg_type = self._parser.get_reg_type( @@ -448,6 +468,8 @@ class ArchSemantics(ISASemantics): register = RegisterOperand(name=reg_type + regtype) elif self._isa == "aarch64": register = RegisterOperand(name=regtype, prefix=reg_type) + elif self._isa == "riscv": + register = RegisterOperand(name=regtype, prefix=reg_type) return register def _nullify_data_ports(self, port_pressure): diff --git a/osaca/semantics/hw_model.py b/osaca/semantics/hw_model.py index 45f9f2b..cd9d3c5 100644 --- a/osaca/semantics/hw_model.py +++ b/osaca/semantics/hw_model.py @@ -1,3 +1,4 @@ +# TODO #!/usr/bin/env python3 import hashlib diff --git a/osaca/semantics/isa_semantics.py b/osaca/semantics/isa_semantics.py index a84602d..e2457e5 100644 --- a/osaca/semantics/isa_semantics.py +++ b/osaca/semantics/isa_semantics.py @@ -2,7 +2,7 @@ from itertools import chain from osaca import utils -from osaca.parser import ParserAArch64, ParserX86ATT +from osaca.parser import ParserAArch64, ParserX86ATT, ParserRISCV from osaca.parser.memory import MemoryOperand from osaca.parser.operand import Operand from osaca.parser.register import RegisterOperand @@ -36,7 +36,11 @@ class ISASemantics(object): self._parser = ParserX86ATT() elif self._isa == "aarch64": self._parser = ParserAArch64() - + elif self._isa == "riscv": + self._parser = ParserRISCV() + else: + raise ValueError("Unknown ISA {!r}.".format(isa)) + def process(self, instruction_forms): """Process a list of instruction forms.""" for i in instruction_forms: @@ -72,6 +76,12 @@ class ISASemantics(object): isa_data = self._isa_model.get_instruction( instruction_form.mnemonic[:suffix_start], instruction_form.operands ) + if isa_data is None and self._isa == "riscv" and "." in instruction_form.mnemonic: + # Check for instruction without vector/FP suffix (.v, .vv, .vf, .s, .d etc.) + suffix_start = instruction_form.mnemonic.index(".") + isa_data = self._isa_model.get_instruction( + instruction_form.mnemonic[:suffix_start], instruction_form.operands + ) operands = instruction_form.operands op_dict = {} @@ -107,6 +117,16 @@ class ISASemantics(object): isa_data_reg = self._isa_model.get_instruction( instruction_form.mnemonic[:suffix_start], operands_reg ) + if ( + isa_data_reg is None + and self._isa == "riscv" + and "." in instruction_form.mnemonic + ): + # Check for instruction without vector/FP suffix (.v, .vv, .vf, .s, .d etc.) + suffix_start = instruction_form.mnemonic.index(".") + isa_data_reg = self._isa_model.get_instruction( + instruction_form.mnemonic[:suffix_start], operands_reg + ) if isa_data_reg: assign_default = False op_dict = self._apply_found_ISA_data(isa_data_reg, operands) @@ -189,6 +209,12 @@ class ISASemantics(object): isa_data = self._isa_model.get_instruction( instruction_form.mnemonic[:suffix_start], instruction_form.operands ) + if isa_data is None and self._isa == "riscv" and "." in instruction_form.mnemonic: + # Check for instruction without vector/FP suffix (.v, .vv, .vf, .s, .d etc.) + suffix_start = instruction_form.mnemonic.index(".") + isa_data = self._isa_model.get_instruction( + instruction_form.mnemonic[:suffix_start], instruction_form.operands + ) if only_postindexed: for o in instruction_form.operands: @@ -329,6 +355,10 @@ class ISASemantics(object): return [op for op in instruction_form.operands[0:-1]] elif self._isa == "aarch64": return [op for op in instruction_form.operands[1:]] + elif self._isa == "riscv": + # For RISC-V, the first operand is typically the destination, + # and the rest are sources + return [op for op in instruction_form.operands[1:]] else: raise ValueError("Unsupported ISA {}.".format(self._isa)) @@ -343,6 +373,9 @@ class ISASemantics(object): if self._isa == "aarch64": # return first operand return instruction_form.operands[:1] + elif self._isa == "riscv": + # For RISC-V, the first operand is typically the destination + return instruction_form.operands[:1] else: raise ValueError("Unsupported ISA {}.".format(self._isa)) diff --git a/osaca/semantics/marker_utils.py b/osaca/semantics/marker_utils.py index 5f2eb4a..dc7c784 100644 --- a/osaca/semantics/marker_utils.py +++ b/osaca/semantics/marker_utils.py @@ -1,3 +1,4 @@ +# TODO #!/usr/bin/env python3 from collections import OrderedDict diff --git a/tests/test_files/kernel_riscv.s b/tests/test_files/kernel_riscv.s index cb6845e..308705a 100644 --- a/tests/test_files/kernel_riscv.s +++ b/tests/test_files/kernel_riscv.s @@ -1,120 +1,204 @@ -# Basic RISC-V test kernel with various instructions - -.text -.globl vector_add -.align 2 - -# Example of a basic function -vector_add: - # Prologue - addi sp, sp, -16 - sw ra, 12(sp) - sw s0, 8(sp) - addi s0, sp, 16 - - # Setup - mv a3, a0 - lw a0, 0(a0) # Load first element - lw a4, 0(a1) # Load second element - add a0, a0, a4 # Add elements - sw a0, 0(a2) # Store to result array - - # Integer operations - addi t0, zero, 10 - addi t1, zero, 5 - add t2, t0, t1 - sub t3, t0, t1 - and t4, t0, t1 - or t5, t0, t1 - xor t6, t0, t1 - sll a0, t0, t1 - srl a1, t0, t1 - sra a2, t0, t1 - - # Memory operations - lw a0, 8(sp) - sw a1, 4(sp) - lbu a2, 1(sp) - sb a3, 0(sp) - lh a4, 2(sp) - sh a5, 2(sp) - - # Branch and jump instructions - beq t0, t1, skip - bne t0, t1, continue - jal ra, function - jalr t0, 0(ra) - -.L1: # Loop Header - beq t0, t1, .L2 - addi t0, t0, 1 - j .L1 - -.L2: - # Floating point operations - flw fa0, 0(a0) - flw fa1, 4(a0) - fadd.s fa2, fa0, fa1 - fsub.s fa3, fa0, fa1 - fmv.x.w a0, fa0 - fmv.w.x fa4, a0 - - # CSR operations - csrr t0, mstatus - csrw mtvec, t0 - csrs mie, t0 - csrc mip, t0 - - # Vector instructions (RVV) - vsetvli t0, a0, e32, m4, ta, ma - vle32.v v0, (a0) - vle32.v v4, (a1) - vadd.vv v8, v0, v4 - vse32.v v8, (a2) - - # Atomic operations - lr.w t0, (a0) - sc.w t1, t2, (a0) - amoswap.w t3, t4, (a0) - amoadd.w t5, t6, (a0) - - # Multiply/divide instructions - mul t0, t1, t2 - mulh t3, t4, t5 - div t0, t1, t2 - rem t3, t4, t5 - - # Pseudo-instructions - li t0, 1234 - la t1, data - li a0, %hi(data) - addi a1, a0, %lo(data) - -skip: - # Skip destination - addi t2, zero, 20 - -continue: - # Continue destination - addi t3, zero, 30 - -function: - # Function destination - addi a0, zero, 0 - ret - - # Epilogue - lw ra, 12(sp) - lw s0, 8(sp) - addi sp, sp, 16 - ret - -.data -.align 4 -data: - .word 0x12345678 - .byte 0x01, 0x02, 0x03, 0x04 - .half 0xABCD, 0xEF01 - .float 3.14159 - .space 16 - .ascii "RISC-V Test String" \ No newline at end of file +saxpy_golden: + beq a0,zero,.L12 + addi a5,a1,4 + csrr a4,vlenb + sub a5,a2,a5 + addi a4,a4,-8 + bleu a5,a4,.L3 + vsetvli a5,zero,e32,m1,ta,ma + vfmv.v.f v3,fa0 + mv a4,a2 +.L4: + vsetvli a5,a0,e32,m1,ta,ma + vle32.v v1,0(a1) + vle32.v v2,0(a2) + slli a3,a5,2 + sub a0,a0,a5 + add a1,a1,a3 + add a2,a2,a3 + vfmadd.vv v1,v3,v2 + vse32.v v1,0(a4) + add a4,a4,a3 + bne a0,zero,.L4 + ret +.L3: + slli a0,a0,2 + add a0,a2,a0 +.L6: + flw fa5,0(a1) + flw fa4,0(a2) + addi a2,a2,4 + addi a1,a1,4 + fmadd.s fa5,fa0,fa5,fa4 + fsw fa5,-4(a2) + bne a2,a0,.L6 +.L12: + ret +saxpy_vec: + beq a0,zero,.L25 +.L18: + vsetvli a5,a0,e32,m8,ta,ma + vle32.v v16,0(a1) + vle32.v v8,0(a2) + slli a4,a5,2 + sub a0,a0,a5 + add a1,a1,a4 + vfmacc.vf v8,fa0,v16 + vse32.v v8,0(a2) + add a2,a2,a4 + bne a0,zero,.L18 +.L25: + ret +fp_eq: + fabs.s fa4,fa0 + fsub.s fa1,fa1,fa0 + fmv.s fa5,fa2 + fgt.s a5,fa4,fa2 + fabs.s fa1,fa1 + beq a5,zero,.L28 + fmv.s fa5,fa4 +.L28: + fmul.s fa5,fa5,fa2 + flt.s a0,fa1,fa5 + ret +.LC2: + .string "fail, %f=!%f\n" +.LC3: + .string "pass" +main: + addi sp,sp,-64 + sd s1,40(sp) + lui a5,%hi(.LC0) + lui s1,%hi(.LANCHOR0) + flw fa5,%lo(.LC0)(a5) + addi a5,s1,%lo(.LANCHOR0) + vsetivli zero,4,e32,m1,ta,ma + addi a4,a5,144 + sd s0,48(sp) + vle32.v v7,0(a4) + addi a3,a5,336 + addi a4,a5,352 + addi s0,a5,256 + addi a7,a5,272 + addi a6,a5,288 + addi a0,a5,304 + addi a1,a5,320 + addi a2,a5,128 + addi t6,a5,160 + addi t5,a5,176 + addi t4,a5,192 + addi t3,a5,208 + addi t1,a5,224 + vle32.v v10,0(a3) + vle32.v v9,0(a4) + vle32.v v15,0(s0) + vle32.v v14,0(a7) + vle32.v v13,0(a6) + vle32.v v12,0(a0) + vle32.v v11,0(a1) + vle32.v v8,0(a2) + vle32.v v6,0(t6) + vle32.v v5,0(t5) + vle32.v v4,0(t4) + vle32.v v3,0(t3) + vle32.v v2,0(t1) + vfmv.v.f v1,fa5 + sd s2,32(sp) + sd ra,56(sp) + vfmadd.vv v8,v1,v15 + vfmadd.vv v3,v1,v10 + vfmadd.vv v2,v1,v9 + vfmadd.vv v7,v1,v14 + vfmadd.vv v6,v1,v13 + vfmadd.vv v5,v1,v12 + vfmadd.vv v4,v1,v11 + sd s3,24(sp) + sd s4,16(sp) + fsd fs0,8(sp) + vse32.v v3,0(a3) + vse32.v v2,0(a4) + vse32.v v8,0(s0) + vse32.v v7,0(a7) + vse32.v v6,0(a6) + vse32.v v5,0(a0) + vse32.v v4,0(a1) + addi a4,a5,240 + vsetivli zero,3,e32,m1,ta,ma + addi a5,a5,368 + vfmv.v.f v3,fa5 + addi s2,s1,%lo(.LANCHOR0) + vle32.v v1,0(a4) + vle32.v v2,0(a5) + addi a4,s1,%lo(.LANCHOR0) + li a3,31 + vfmadd.vv v1,v3,v2 + vse32.v v1,0(a5) +.L31: + vsetvli a5,a3,e32,m8,ta,ma + vle32.v v16,0(a2) + vle32.v v8,0(a4) + slli a1,a5,2 + sub a3,a3,a5 + add a2,a2,a1 + vfmacc.vf v8,fa5,v16 + vse32.v v8,0(a4) + add a4,a4,a1 + bne a3,zero,.L31 + lui a5,%hi(.LC1) + flw fs0,%lo(.LC1)(a5) + addi s1,s1,%lo(.LANCHOR0) + addi s2,s2,380 + li s3,1 + lui s4,%hi(.LC2) + j .L35 +.L32: + addi s0,s0,4 + addi s1,s1,4 + beq s2,s0,.L48 +.L35: + flw fa3,0(s0) + flw fa1,0(s1) + fmv.s fa5,fs0 + fabs.s fa2,fa3 + fsub.s fa4,fa1,fa3 + fgt.s a5,fa2,fs0 + fabs.s fa4,fa4 + beq a5,zero,.L34 + fmv.s fa5,fa2 +.L34: + fmul.s fa5,fa5,fs0 + fgt.s a5,fa5,fa4 + bne a5,zero,.L32 + fcvt.d.s fa5,fa1 + addi a0,s4,%lo(.LC2) + addi s0,s0,4 + fmv.x.d a2,fa5 + fcvt.d.s fa5,fa3 + li s3,0 + addi s1,s1,4 + fmv.x.d a1,fa5 + call printf + bne s2,s0,.L35 +.L48: + bne s3,zero,.L49 +.L43: + ld ra,56(sp) + ld s0,48(sp) + ld s1,40(sp) + ld s2,32(sp) + ld s4,16(sp) + fld fs0,8(sp) + xori a0,s3,1 + ld s3,24(sp) + addi sp,sp,64 + jr ra +.L49: + lui a0,%hi(.LC3) + addi a0,a0,%lo(.LC3) + call puts + j .L43 +.LC0: + .word 1113498583 +.LC1: + .word 897988541 + .set .LANCHOR0,. + 0 \ No newline at end of file diff --git a/tests/test_parser_RISCV.py b/tests/test_parser_RISCV.py index e5a696c..32d0ed4 100644 --- a/tests/test_parser_RISCV.py +++ b/tests/test_parser_RISCV.py @@ -196,9 +196,9 @@ class TestParserRISCV(unittest.TestCase): self.assertGreater(len(parsed), 80) # More than 80 lines should be parsed # Test parsing specific parts of the file - # Find vector_add label - vector_add_idx = next((i for i, instr in enumerate(parsed) if instr.label == "vector_add"), None) - self.assertIsNotNone(vector_add_idx) + # Find saxpy_vec label (which is the vector routine in the updated file) + vector_idx = next((i for i, instr in enumerate(parsed) if instr.label == "saxpy_vec"), None) + self.assertIsNotNone(vector_idx) # Find floating-point instructions flw_idx = next((i for i, instr in enumerate(parsed) if instr.mnemonic == "flw"), None)