Compare commits

...

4 Commits

Author SHA1 Message Date
Anton Lydike 4d19738072 release 2.1.1 1 year ago
Anton Lydike 47fef8c99f update changelog 1 year ago
Anton Lydike d508e01a6b misc: test python 3.8 in CI, add cfg arg to RiscemuRunner 1 year ago
Anton Lydike 47a9b12263 misc: improve typing and structure 1 year ago

@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: ['3.10'] python-version: ['3.8','3.10']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

10
.gitignore vendored

@ -1,6 +1,8 @@
venv
__pycache__ __pycache__
.mypy_cache .mypy_cache
dist/ .pytest_cache
riscemu.egg-info
build/ /venv*
/dist
/riscemu.egg-info
/build

@ -1,14 +1,18 @@
# Changelog # Changelog
## Upcoming 2.0.6 ## 2.1.1
- Bugfix: Allow infinite registers with more than two digits in load/store ins
- Bugfix: Fix how floating point registers are displayed in the debugger
- Bugfix: Various semantic problems in RV32F
## 2.1.0
- Added a very basic libc containing a `crt0.s`, and a few functions - Added a very basic libc containing a `crt0.s`, and a few functions
such as `malloc`, `rand`, and `memcpy`. such as `malloc`, `rand`, and `memcpy`.
- Added a subset of the `mmap2` syscall (code 192) to allocate new memory - Added a subset of the `mmap2` syscall (code 192) to allocate new memory
- Refactored the launching code to improve using riscemu from code - Refactored the launching code to improve using riscemu from code
- Added floating point support (enabled by default). The RV32F extension is now available
**Planned:**
- Add a floating point unit
## 2.0.5 ## 2.0.5

@ -348,7 +348,7 @@ class MMU:
return InstructionContext() return InstructionContext()
def find_entrypoint(self) -> int | None: def find_entrypoint(self) -> Optional[int]:
# try to find the global entrypoint # try to find the global entrypoint
if "_start" in self.global_symbols: if "_start" in self.global_symbols:
return self.global_symbols["_start"] return self.global_symbols["_start"]

@ -34,4 +34,4 @@ from .parser import tokenize, parse_tokens, AssemblyFileLoader
__author__ = "Anton Lydike <Anton@Lydike.com>" __author__ = "Anton Lydike <Anton@Lydike.com>"
__copyright__ = "Copyright 2023 Anton Lydike" __copyright__ = "Copyright 2023 Anton Lydike"
__version__ = "2.0.5" __version__ = "2.1.1"

@ -12,7 +12,7 @@ from riscemu.riscemu_main import RiscemuMain
try: try:
main = RiscemuMain() main = RiscemuMain()
main.run(sys.argv[1:]) main.run_from_cli(sys.argv[1:])
sys.exit(main.cpu.exit_code if not main.cfg.ignore_exit_code else 0) sys.exit(main.cpu.exit_code if not main.cfg.ignore_exit_code else 0)
except RiscemuBaseException as e: except RiscemuBaseException as e:

@ -2,7 +2,7 @@ import argparse
import glob import glob
import os import os
import sys import sys
from typing import List, Type from typing import Type, Dict, List, Optional
from riscemu import AssemblyFileLoader, __version__, __copyright__ from riscemu import AssemblyFileLoader, __version__, __copyright__
from riscemu.types import CPU, ProgramLoader, Program from riscemu.types import CPU, ProgramLoader, Program
@ -17,21 +17,21 @@ class RiscemuMain:
interoperability. interoperability.
""" """
available_ins_sets: dict[str, type[InstructionSet]] available_ins_sets: Dict[str, Type[InstructionSet]]
available_file_loaders: list[type[ProgramLoader]] available_file_loaders: List[Type[ProgramLoader]]
cfg: RunConfig | None cfg: Optional[RunConfig]
cpu: CPU | None cpu: Optional[CPU]
input_files: list[str] input_files: List[str]
selected_ins_sets: list[Type[InstructionSet]] selected_ins_sets: List[Type[InstructionSet]]
def __init__(self): def __init__(self, cfg: Optional[RunConfig] = None):
self.available_ins_sets = dict() self.available_ins_sets = dict()
self.selected_ins_sets = [] self.selected_ins_sets = []
self.available_file_loaders = [] self.available_file_loaders = []
self.cfg: RunConfig | None = None self.cfg: Optional[RunConfig] = cfg
self.cpu: CPU | None = None self.cpu: Optional[CPU] = None
self.input_files = [] self.input_files = []
self.selected_ins_sets = [] self.selected_ins_sets = []
@ -129,7 +129,7 @@ class RiscemuMain:
def register_all_program_loaders(self): def register_all_program_loaders(self):
self.available_file_loaders.append(AssemblyFileLoader) self.available_file_loaders.append(AssemblyFileLoader)
def parse_argv(self, argv: list[str]): def parse_argv(self, argv: List[str]):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="RISC-V Userspace emulator", description="RISC-V Userspace emulator",
prog="riscemu", prog="riscemu",
@ -153,7 +153,7 @@ class RiscemuMain:
setattr(args, "ins", {k: True for k in self.available_ins_sets}) setattr(args, "ins", {k: True for k in self.available_ins_sets})
# create RunConfig # create RunConfig
self.cfg = self.config_from_parsed_args(args) self.cfg = self.create_config(args)
# set input files # set input files
self.input_files = args.files self.input_files = args.files
@ -167,6 +167,12 @@ class RiscemuMain:
# if use_libc is given, attach libc to path # if use_libc is given, attach libc to path
if self.cfg.use_libc: if self.cfg.use_libc:
self.add_libc_to_input_files()
def add_libc_to_input_files(self):
"""
This adds the provided riscemu libc to the programs runtime.
"""
libc_path = os.path.join( libc_path = os.path.join(
os.path.dirname(__file__), os.path.dirname(__file__),
"..", "..",
@ -174,9 +180,10 @@ class RiscemuMain:
"*.s", "*.s",
) )
for path in glob.iglob(libc_path): for path in glob.iglob(libc_path):
if path not in self.input_files:
self.input_files.append(path) self.input_files.append(path)
def config_from_parsed_args(self, args: argparse.Namespace) -> RunConfig: def create_config(self, args: argparse.Namespace) -> RunConfig:
# create a RunConfig from the cli args # create a RunConfig from the cli args
cfg_dict = dict( cfg_dict = dict(
stack_size=args.stack_size, stack_size=args.stack_size,
@ -208,7 +215,7 @@ class RiscemuMain:
for p in programs: for p in programs:
self.cpu.mmu.load_program(p) self.cpu.mmu.load_program(p)
def run(self, argv: list[str]): def run_from_cli(self, argv: List[str]):
# register everything # register everything
self.register_all_isas() self.register_all_isas()
self.register_all_program_loaders() self.register_all_program_loaders()
@ -221,6 +228,29 @@ class RiscemuMain:
# run the program # run the program
self.cpu.launch(self.cfg.verbosity > 1) self.cpu.launch(self.cfg.verbosity > 1)
def run(self):
"""
This assumes that these values were set externally:
- available_file_loaders: A list of available file loaders.
Can be set using .register_all_program_loaders()
- cfg: The RunConfig object. Can be directly assigned to the attribute
- input_files: A list of assembly files to load.
- selected_ins_sets: A list of instruction sets the CPU should support.
"""
assert self.cfg is not None, "self.cfg must be set before calling run()"
assert self.selected_ins_sets, "self.selected_ins_sets cannot be empty"
assert self.input_files, "self.input_files cannot be empty"
if self.cfg.use_libc:
self.add_libc_to_input_files()
self.instantiate_cpu()
self.load_programs()
# run the program
self.cpu.launch(self.cfg.verbosity > 1)
class OptionStringAction(argparse.Action): class OptionStringAction(argparse.Action):
def __init__(self, option_strings, dest, keys=None, omit_empty=False, **kwargs): def __init__(self, option_strings, dest, keys=None, omit_empty=False, **kwargs):

@ -7,7 +7,7 @@ SPDX-License-Identifier: MIT
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from math import log2, ceil from math import log2, ceil
from typing import Dict, IO from typing import Dict, IO, Union
from .types import BinaryDataMemorySection, MemoryFlags from .types import BinaryDataMemorySection, MemoryFlags
from .colors import FMT_SYSCALL, FMT_NONE from .colors import FMT_SYSCALL, FMT_NONE
@ -70,7 +70,7 @@ class Syscall:
def __repr__(self): def __repr__(self):
return "Syscall(id={}, name={})".format(self.id, self.name) return "Syscall(id={}, name={})".format(self.id, self.name)
def ret(self, code: int | Int32): def ret(self, code: Union[int, Int32]):
self.cpu.regs.set("a0", Int32(code)) self.cpu.regs.set("a0", Int32(code))

Loading…
Cancel
Save