Compare commits

...

3 Commits

Author SHA1 Message Date
Anton Lydike 51d23a1630 updated .idea files 2 years ago
Anton Lydike 636e06f243 add an unlimited register mode 2 years ago
Anton Lydike 86063d64d7 version update: 2.0.4 2 years ago

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (riscemu)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (riscemu)" project-jdk-type="Python SDK" />
</project>

@ -2,6 +2,7 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/riscemu" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/venv" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
@ -9,7 +10,7 @@
<excludeFolder url="file://$MODULE_DIR$/riscemu.egg-info" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Python 3.10 (riscemu)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -45,7 +45,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.7"
"version": "3.10.8"
}
},
"nbformat": 4,

@ -25,4 +25,4 @@ from .parser import tokenize, parse_tokens, AssemblyFileLoader
__author__ = "Anton Lydike <Anton@Lydike.com>"
__copyright__ = "Copyright 2022 Anton Lydike"
__version__ = '2.0.3'
__version__ = '2.0.4'

@ -57,12 +57,19 @@ if __name__ == '__main__':
setattr(namespace, self.dest, d)
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu')
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu',
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('files', metavar='file.asm', type=str, nargs='+',
help='The assembly files to load, the last one will be run')
parser.add_argument('--options', '-o', action=OptionStringAction,
keys=('disable_debug', 'no_syscall_symbols', 'fail_on_ex', 'add_accept_imm'))
keys=('disable_debug', 'no_syscall_symbols', 'fail_on_ex', 'add_accept_imm', 'unlimited_regs'),
help="""Toggle options. Available options are:
disable_debug: Disable ebreak instructions
no_syscall_symbols: Don't add symbols for SCALL_EXIT and others
fail_on_ex: If set, exceptions won't trigger the debugger
add_accept_imm: Accept "add rd, rs, imm" instruction (instead of addi)
unlimited_regs: Allow an unlimited number of registers""")
parser.add_argument('--syscall-opts', '-so', action=OptionStringAction,
keys=('fs_access', 'disable_input'))
@ -88,6 +95,7 @@ if __name__ == '__main__':
include_scall_symbols=not args.options['no_syscall_symbols'],
debug_on_exception=not args.options['fail_on_ex'],
add_accept_imm=args.options['add_accept_imm'],
unlimited_registers=args.options['unlimited_regs'],
scall_fs=args.syscall_opts['fs_access'],
scall_input=not args.syscall_opts['disable_input'],
verbosity=args.verbose

@ -20,6 +20,7 @@ class RunConfig:
scall_fs: bool = False
verbosity: int = 0
slowdown: float = 1
unlimited_registers: bool = False
CONFIG = RunConfig()

@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
This package holds all instruction sets, available to the processor
"""
from .instruction_set import InstructionSet
from .instruction_set import InstructionSet, Instruction
from .RV32M import RV32M
from .RV32I import RV32I
from .RV32A import RV32A

@ -110,6 +110,9 @@ class AssemblyFileLoader(ProgramLoader):
with open(self.source_path, 'r') as f:
return parse_tokens(self.filename, tokenize(f))
def parse_io(self, io):
return parse_tokens(self.filename, tokenize(io))
@classmethod
def can_parse(cls, source_path: str) -> float:
"""

@ -17,11 +17,22 @@ class Registers:
Represents a bunch of registers
"""
def __init__(self):
valid_regs = {
'zero', 'ra', 'sp', 'gp', 'tp', 's0', 'fp',
't0', 't1', 't2', 't3', 't4', 't5', 't6',
's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11',
'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7',
'ft0', 'ft1', 'ft2', 'ft3', 'ft4', 'ft5', 'ft6', 'ft7',
'fs0', 'fs1', 'fs2', 'fs3', 'fs4', 'fs5', 'fs6', 'fs7', 'fs8', 'fs9', 'fs10', 'fs11',
'fa0', 'fa1', 'fa2', 'fa3', 'fa4', 'fa5', 'fa6', 'fa7'
}
def __init__(self, infinite_regs: bool = False):
from .types import Int32
self.vals = defaultdict(lambda: Int32(0))
self.last_set = None
self.last_read = None
self.infinite_regs = infinite_regs
def dump(self, full=False):
"""
@ -108,7 +119,10 @@ class Registers:
reg = 's1'
if mark_set:
self.last_set = reg
# check 32 bit signed bounds
if not self.infinite_regs and reg not in self.valid_regs:
raise RuntimeError("Invalid register: {}".format(reg))
self.vals[reg] = val.unsigned()
return True
@ -123,6 +137,10 @@ class Registers:
# raise InvalidRegisterException(reg)
if reg == 'fp':
reg = 's0'
if not self.infinite_regs and reg not in self.valid_regs:
raise RuntimeError("Invalid register: {}".format(reg))
if mark_read:
self.last_read = reg
return self.vals[reg]

@ -31,7 +31,7 @@ class CPU(ABC):
def __init__(self, mmu: 'MMU', instruction_sets: List[Type['InstructionSet']], conf: RunConfig):
self.mmu = mmu
self.regs = Registers()
self.regs = Registers(conf.unlimited_registers)
self.conf = conf
self.instruction_sets = set()

Loading…
Cancel
Save