From c99ebf0bbfa351a65f7fff98245180701012f45f Mon Sep 17 00:00:00 2001 From: Edwin Lu Date: Fri, 1 Nov 2024 10:14:51 -0700 Subject: [PATCH] RISC-V: Add banana pi target Add support targeting the RISC-V Banana Pi 3 board. Assembly generated by this target will automatically be compilable without additional modifications Signed-off-by: Edwin Lu --- targets/generic/tools/mp_seq.py | 8 ++ targets/riscv/env/riscv_bp3.py | 108 +++++++++++++++++++++++++ targets/riscv/policies/seq.py | 1 + targets/riscv/wrappers/riscv-bp3.py | 121 ++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 targets/riscv/env/riscv_bp3.py create mode 100644 targets/riscv/wrappers/riscv-bp3.py diff --git a/targets/generic/tools/mp_seq.py b/targets/generic/tools/mp_seq.py index 05416302..2a7ff4b2 100755 --- a/targets/generic/tools/mp_seq.py +++ b/targets/generic/tools/mp_seq.py @@ -114,6 +114,14 @@ def _generic_policy_wrapper(all_arguments: Tuple[List[InstructionType], str, wrapper = wrapper_class(endless=kwargs['endless'], reset=kwargs['reset']) + elif target.name.endswith("riscv64_bp3"): + + wrapper_name = "RiscvBP3" + extension = "S" + wrapper_class = _get_wrapper(wrapper_name) + wrapper = wrapper_class(endless=kwargs['endless'], + reset=kwargs['reset']) + elif target.environment.default_wrapper: wrapper_name = target.environment.default_wrapper diff --git a/targets/riscv/env/riscv_bp3.py b/targets/riscv/env/riscv_bp3.py new file mode 100644 index 00000000..8cb37634 --- /dev/null +++ b/targets/riscv/env/riscv_bp3.py @@ -0,0 +1,108 @@ +# Copyright 2011-2021 IBM Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Docstring +""" + +# Futures +from __future__ import absolute_import + +# Own modules +from microprobe.code.address import InstructionAddress +from microprobe.target.env import GenericEnvironment + +# Constants + +# Functions + + +# Classes +class riscv64_bp3(GenericEnvironment): + + _elf_code = ""\ + ""\ + "" + + def __init__(self, isa): + super( + riscv64_bp3, + self).__init__( + "riscv64_bp3", + "RISC-V architecture (64bit addressing mode), " + "Assembly using RISC-V Banana Pi 3", + isa, + little_endian=True + ) + + self._default_wrapper = "RiscvBP3" + + @property + def stack_pointer(self): + """ """ + return self.isa.registers["X2"] + + @property + def stack_direction(self): + """ """ + return "increase" + + def elf_abi(self, stack_size, start_symbol, **kwargs): + + return super(riscv64_bp3, self).elf_abi(stack_size, + start_symbol, + stack_alignment=16, + **kwargs) + + def function_call(self, target, + return_address_reg=None, + long_jump=False): + + if return_address_reg is None: + return_address_reg = self.target.isa.registers["X1"] + + if isinstance(target, str): + target = InstructionAddress(base_address=target) + + jal_ins = self.target.new_instruction("JAL_V0") + jal_ins.set_operands([target, return_address_reg]) + + return [jal_ins] + + def function_return(self, + return_address_reg=None): + + if return_address_reg is None: + return_address_reg = self.target.isa.registers["X1"] + + ret_ins = self.target.new_instruction("JALR_V0") + ret_ins.set_operands([0, + return_address_reg, + self.target.isa.registers["X0"]]) + return [ret_ins] + + @property + def volatile_registers(self): + + rlist = [] + for idx in [ + 1, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, + 28, 29, 30, 31]: + rlist += [self.target.registers['X%d' % idx]] + + for idx in [ + 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, + 28, 29, 30, 31]: + rlist += [self.target.registers['F%d' % idx]] + + return rlist diff --git a/targets/riscv/policies/seq.py b/targets/riscv/policies/seq.py index 3eb5307b..02503972 100644 --- a/targets/riscv/policies/seq.py +++ b/targets/riscv/policies/seq.py @@ -47,6 +47,7 @@ SUPPORTED_TARGETS = [ "riscv_v22-riscv_generic-riscv64_linux_gcc", "riscv_v22-riscv_generic-riscv64_test_p", + "riscv_v22-riscv_generic-riscv64_bp3", ] diff --git a/targets/riscv/wrappers/riscv-bp3.py b/targets/riscv/wrappers/riscv-bp3.py new file mode 100644 index 00000000..38eb494d --- /dev/null +++ b/targets/riscv/wrappers/riscv-bp3.py @@ -0,0 +1,121 @@ +# Copyright 2011-2021 IBM Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Futures +from __future__ import absolute_import + + +# Own modules +from microprobe.code import get_wrapper +from microprobe.utils.logger import get_logger + + +# Constants +LOG = get_logger(__name__) +__all__ = ["RiscvBP3"] + +# Functions + + +# Classes +class RiscvBP3(get_wrapper("Assembly")): + + def __init__(self, endless=False, reset=False): + self._endless = endless + self._reset = reset + super(RiscvBP3, self).__init__() + +# def headers(self): +# return """\ +# +# /* Headers */ +# #include "riscv_test.h" +# #include "riscv-tests/isa/macros/scalar/test_macros.h" +# +# """ + + def start_main(self): + return """\ +.global main + +/* Start Main */ +.section .text +main: +""" + + def outputname(self, name): + """ + + :param name: + + """ + if not name.endswith(".S"): + return "%s.S" % name + return name + + def post_var(self): + return "".join("reset:") + + def start_loop(self, instr, instr_reset, dummy_aligned=True): + """ + + :param instr: + :param instr_reset: + :param dummy_aligned: (Default value = True) + + """ + + start_loop = ["/* Building block start */\n"] + if not self._endless: + return "\n".join(start_loop) + + if self._reset: + instr_reset.add_comment("Loop start reseting") + if not instr_reset.label: + instr_reset.set_label("reset") + self._loop_label = "reset" + else: + self._loop_label = instr_reset.label + + else: + instr.add_comment("Loop start") + if not instr.label: + instr.set_label("infloop") + self._loop_label = "infloop" + else: + self._loop_label = instr.label + + return "\n".join(start_loop) + + def end_loop(self, dummy_instr): + """ + """ + if not self._endless: + return "/* Loop End */" + + loop = ["/* Loop End */"] + loop.append(self.wrap_ins("j %s" % self._loop_label)) + return "\n".join(loop) + + def end_main(self): + return """\ + +/* End Main */ + +""" + + def declare_global_var(self, var): + if var.align: + return ".comm %s, %d, %d\n" % (var.name, var.size, var.align) + else: + return ".comm %s, %d\n" % (var.name, var.size)