lots more documentation cleanup

float_support
Anton Lydike 4 years ago
parent fdcb3a71be
commit 0574766a81

@ -17,32 +17,37 @@ class MMU:
The MemoryManagementUnit (handles loading binaries, and reading/writing data)
"""
max_size = 0xFFFFFFFF
"""
The maximum size of the memory in bytes
"""
max_size = 0xFFFFFFFF
sections: List[LoadedMemorySection]
"""
A list of all loaded memory sections
"""
sections: List[LoadedMemorySection]
binaries: List[LoadedExecutable]
"""
A list of all loaded executables
"""
binaries: List[LoadedExecutable]
last_bin: Optional[LoadedExecutable] = None
"""
The last loaded executable (the next executable is inserted directly after this one)
"""
last_bin: Optional[LoadedExecutable] = None
global_symbols: Dict[str, int]
"""
The global symbol table
"""
global_symbols: Dict[str, int]
def __init__(self, conf: RunConfig):
"""
Create a new MMU, respeccting the active RunConfiguration
:param conf: The config to respect
"""
self.sections = list()
self.binaries = list()
self.last_bin = None
@ -52,6 +57,7 @@ class MMU:
def load_bin(self, bin: Executable) -> LoadedExecutable:
"""
Load an executable into memory
:param bin: the executable to load
:return: A LoadedExecutable
:raises OutOfMemoryException: When all memory is used
@ -88,6 +94,7 @@ class MMU:
def get_sec_containing(self, addr: int) -> Optional[LoadedMemorySection]:
"""
Returns the section that contains the address addr
:param addr: the Address to look for
:return: The LoadedMemorySection or None
"""
@ -99,6 +106,7 @@ class MMU:
def read_ins(self, addr: int) -> LoadedInstruction:
"""
Read a single instruction located at addr
:param addr: The location
:return: The Instruction
"""
@ -108,6 +116,7 @@ class MMU:
def read(self, addr: int, size: int) -> bytearray:
"""
Read size bytes of memory at addr
:param addr: The addres at which to start reading
:param size: The number of bytes to read
:return: The bytearray at addr
@ -118,6 +127,7 @@ class MMU:
def write(self, addr: int, size: int, data):
"""
Write bytes into memory
:param addr: The address at which to write
:param size: The number of bytes to write
:param data: The bytearray to write (only first size bytes are written)
@ -138,9 +148,10 @@ class MMU:
return
sec.dump(addr, *args, **kwargs)
def symbol(self, symb:str):
def symbol(self, symb: str):
"""
Look up the symbol symb in all local symbol tables (and the global one)
:param symb: The symbol name to look up
"""
print(FMT_MEM + "[MMU] Lookup for symbol {}:".format(symb) + FMT_NONE)
@ -153,4 +164,4 @@ class MMU:
def __repr__(self):
return "MMU(\n\t{}\n)".format(
"\n\t".join(repr(x) for x in self.sections)
)
)

@ -8,18 +8,15 @@ from dataclasses import dataclass
from typing import Dict, IO
import sys
from .Registers import Registers
from .Exceptions import InvalidSyscallException
from .helpers import *
import riscemu
import typing
if typing.TYPE_CHECKING:
from . import CPU
"""
All available syscalls (mapped id->name)
"""
SYSCALLS = {
63: 'read',
64: 'write',
@ -27,10 +24,8 @@ SYSCALLS = {
1024: 'open',
1025: 'close',
}
"""All available syscalls (mapped id->name)"""
"""
All available file open modes
"""
OPEN_MODES = {
0: 'rb',
1: 'wb',
@ -38,7 +33,7 @@ OPEN_MODES = {
3: 'x',
4: 'ab',
}
"""All available file open modes"""
@dataclass(frozen=True)
class Syscall:
@ -46,8 +41,9 @@ class Syscall:
Represents a syscall
"""
id: int
registers: Registers
cpu: 'CPU'
"""The syscall number (e.g. 64 - write)"""
cpu: 'riscemu.CPU'
"""The CPU object that created the syscall"""
@property
def name(self):
@ -59,13 +55,14 @@ class Syscall:
)
def ret(self, code):
self.registers.set('a0', code)
self.cpu.regs.set('a0', code)
def get_syscall_symbols():
"""
Retuns a dictionary of all syscall symbols (SCALL_<name> -> id)
:return:
Generate global syscall symbols (such as SCALL_READ, SCALL_EXIT etc)
:return: dictionary of all syscall symbols (SCALL_<name> -> id)
"""
return {
('SCALL_' + name.upper()): num for num, name in SYSCALLS.items()
@ -97,11 +94,11 @@ class SyscallInterface:
read syscall (63): read from file no a0, into addr a1, at most a2 bytes
on return a0 will be the number of read bytes or -1 if an error occured
"""
fileno = scall.registers.get('a0')
addr = scall.registers.get('a1')
size = scall.registers.get('a2')
fileno = scall.cpu.regs.get('a0')
addr = scall.cpu.regs.get('a1')
size = scall.cpu.regs.get('a2')
if fileno not in self.open_files:
scall.registers.set('a0', -1)
scall.cpu.regs.set('a0', -1)
return
chars = self.open_files[fileno].readline(size)
@ -119,9 +116,9 @@ class SyscallInterface:
write syscall (64): write a2 bytes from addr a1 into fileno a0
on return a0 will hold the number of bytes written or -1 if an error occured
"""
fileno = scall.registers.get('a0')
addr = scall.registers.get('a1')
size = scall.registers.get('a2')
fileno = scall.cpu.regs.get('a0')
addr = scall.cpu.regs.get('a1')
size = scall.cpu.regs.get('a2')
if fileno not in self.open_files:
return scall.ret(-1)
@ -152,9 +149,9 @@ class SyscallInterface:
print(FMT_SYSCALL + '[Syscall] open: opening files not supported without scall-fs flag!' + FMT_NONE)
return scall.ret(-1)
mode = scall.registers.get('a0')
addr = scall.registers.get('a1')
size = scall.registers.get('a2')
mode = scall.cpu.regs.get('a0')
addr = scall.cpu.regs.get('a1')
size = scall.cpu.regs.get('a2')
mode_st = OPEN_MODES.get(mode, )
if mode_st == -1:
@ -181,7 +178,7 @@ class SyscallInterface:
return -1 if an error was encountered, otherwise returns 0
"""
fileno = scall.registers.get('a0')
fileno = scall.cpu.regs.get('a0')
if fileno not in self.open_files:
print(FMT_SYSCALL + '[Syscall] close: unknown fileno {}!'.format(fileno) + FMT_NONE)
return scall.ret(-1)
@ -196,7 +193,7 @@ class SyscallInterface:
Exit syscall. Exits the system with status code a0
"""
scall.cpu.exit = True
scall.cpu.exit_code = scall.registers.get('a0')
scall.cpu.exit_code = scall.cpu.regs.get('a0')
def __repr__(self):
return "{}(\n\tfiles={}\n)".format(

@ -25,3 +25,6 @@ from .Syscall import SyscallInterface, Syscall
from .CPU import CPU
from .Config import RunConfig
__author__ = "Anton Lydike <Anton@Lydike.com"
__copyright__ = "Copyright 2021 Anton Lydike"

@ -8,14 +8,14 @@ from math import log10, ceil
from .Exceptions import *
def align_addr(addr: int, to_bytes: int = 8):
def align_addr(addr: int, to_bytes: int = 8) -> int:
"""
align an address to `to_bytes` (meaning addr & to_bytes = 0)
"""
return addr + (-addr % to_bytes)
def parse_numeric_argument(arg: str):
def parse_numeric_argument(arg: str) -> int:
"""
parse hex or int strings
"""
@ -27,7 +27,7 @@ def parse_numeric_argument(arg: str):
raise ParseException('Invalid immediate argument \"{}\", maybe missing symbol?'.format(arg), (arg, ex))
def int_to_bytes(val, bytes=4, unsigned=False):
def int_to_bytes(val, bytes=4, unsigned=False) -> bytearray:
"""
int -> byte (two's complement)
"""
@ -38,7 +38,7 @@ def int_to_bytes(val, bytes=4, unsigned=False):
])
def int_from_bytes(bytes, unsigned=False):
def int_from_bytes(bytes, unsigned=False) -> int:
"""
byte -> int (two's complement)
"""
@ -53,19 +53,20 @@ def int_from_bytes(bytes, unsigned=False):
return to_signed(num)
def to_unsigned(num: int, bytes=4):
def to_unsigned(num: int, bytes=4) -> int:
if num < 0:
return 2 ** (bytes * 8) + num
return num
def to_signed(num: int, bytes=4):
def to_signed(num: int, bytes=4) -> int:
if num >> (bytes * 8 - 1):
return num - 2 ** (8 * bytes)
return num
def create_chunks(my_list, chunk_size):
"""Split a list like [a,b,c,d,e,f,g,h,i,j,k,l,m] into e.g. [[a,b,c,d],[e,f,g,h],[i,j,k,l],[m]]"""
return [my_list[i:i + chunk_size] for i in range(0, len(my_list), chunk_size)]
@ -83,6 +84,7 @@ def highlight_in_list(items, hi_ind):
def format_bytes(byte_arr: bytearray, fmt: str, group: int = 1, highlight: int = -1):
"""Format byte array as per fmt. Group into groups of size `group`, and highlight index `highlight`."""
chunks = create_chunks(byte_arr, group)
if fmt == 'hex':
return highlight_in_list(['0x{}'.format(ch.hex()) for ch in chunks], highlight)

@ -24,6 +24,9 @@ class InstructionSet(ABC):
"""
def __init__(self, cpu: 'CPU'):
"""Create a new instance of the Instruction set. This requires access to a CPU, and grabs vertain things
from it such as access to the MMU and registers.
"""
self.name = self.__class__.__name__
self.cpu = cpu
self.mmu = cpu.mmu

@ -293,7 +293,7 @@ class RV32I(InstructionSet):
def instruction_scall(self, ins: 'LoadedInstruction'):
ASSERT_LEN(ins.args, 0)
syscall = Syscall(self.regs.get('a7'), self.regs, self.cpu)
syscall = Syscall(self.regs.get('a7'), self.cpu)
self.cpu.syscall_int.handle_syscall(syscall)
def instruction_sbreak(self, ins: 'LoadedInstruction'):

Loading…
Cancel
Save