Skip to content

Commit e75e84f

Browse files
committed
Further fixes to instruction coding
1 parent 5ee305f commit e75e84f

File tree

3 files changed

+38
-31
lines changed

3 files changed

+38
-31
lines changed

riscvmodel/code.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,27 @@
66
from . import __version__
77

88
class MachineDecodeError(Exception):
9-
pass
9+
def __init__(self, word):
10+
self.word = word
11+
def __str__(self):
12+
return "Invalid instruction word: {:08x}".format(self.word)
1013

11-
def decode(machinecode: int):
12-
if machinecode & 0x3 != 3:
14+
def decode(word: int):
15+
if word & 0x3 != 3:
1316
# compact
1417
for icls in get_insns(cls=InstructionCType):
15-
if icls._match(machinecode):
18+
if icls._match(word):
1619
i = icls()
17-
i.decode(machinecode)
20+
i.decode(word)
1821
return i
19-
raise MachineDecodeError("Cannot decode {:04x}".format(machinecode))
20-
opcode = machinecode & 0x7F
22+
raise MachineDecodeError(word)
23+
opcode = word & 0x7F
2124
for icls in get_insns():
22-
if icls._opcode == opcode and icls._match(machinecode):
25+
if icls.field_opcode.value == opcode and icls.match(word):
2326
i = icls()
24-
i.decode(machinecode)
27+
i.decode(word)
2528
return i
26-
raise MachineDecodeError()
29+
raise MachineDecodeError(word)
2730

2831

2932
def read_from_binary(fname: str, *, stoponerror: bool = False):

riscvmodel/isa.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,19 @@ def asm_signature(cls):
4747
return signature
4848

4949
@classmethod
50-
def extract_field(cls, field, machinecode):
50+
def extract_field(cls, field, word):
5151
fname = "field_{}".format(field)
5252
base = getattr(cls, fname).base
5353
size = getattr(cls, fname).size
54-
return (machinecode >> base) & (2**size - 1)
54+
if not isinstance(base, list):
55+
base = [base]
56+
size = [size]
57+
off = 0
58+
value = 0
59+
for part in range(len(base)):
60+
value |= ((word >> base[part]) & (2**size[part] - 1)) << off
61+
off += size[part]
62+
return value << getattr(cls, fname).offset
5563

5664
@classmethod
5765
def set_field(cls, field, word, value):
@@ -61,7 +69,7 @@ def set_field(cls, field, word, value):
6169
if not isinstance(base, list):
6270
base = [base]
6371
size = [size]
64-
off = 0
72+
off = getattr(cls, fname).offset
6573
for part in range(len(base)):
6674
word |= (((value >> off) & (2**size[part] - 1)) << base[part])
6775
off += size[part]
@@ -82,6 +90,14 @@ def get_isa_format(cls, *, asdict: bool=False):
8290
fields = [field._asdict() for field in fields]
8391
return {"id": cls.isa_format_id, "fields": fields}
8492

93+
@classmethod
94+
def match(cls, word: int):
95+
"""Try to match a machine code to this instruction"""
96+
for field in cls.get_static_fields():
97+
if cls.extract_field(field.name, word) != field.value:
98+
return False
99+
return True
100+
85101
def ops_from_string(self, ops: str):
86102
"""
87103
Extract operands from string
@@ -126,11 +142,13 @@ def decode(self, word: int):
126142
assert self.extract_field(field.name, word) == field.value
127143
else:
128144
attr = getattr(self, field.name)
145+
value = self.extract_field(field.name, word)
129146
if isinstance(attr, Register):
130-
attr.set(self.extract_field(field.name, word))
147+
attr.set(value)
148+
elif isinstance(attr, Immediate):
149+
attr.set_from_bits(value)
131150
else:
132-
assert isinstance(attr, Immediate)
133-
attr.set_from_bits(self.extract_field(field.name, word))
151+
setattr(self, field.name, value)
134152

135153
def encode(self) -> int:
136154
"""
@@ -661,18 +679,6 @@ class WrappedClass(wrapped): # pylint: disable=too-few-public-methods
661679
assert fid in dir(wrapped), "Invalid field {} for {}".format(fid, wrapped.__name__)
662680
setattr(wrapped, fid, getattr(wrapped, fid)._replace(value=kwargs[field]))
663681

664-
@classmethod
665-
def match(cls, word: int):
666-
"""Try to match a machine code to this instruction"""
667-
if not cls.field_opcode:
668-
return False
669-
670-
for field in cls.get_static_fields():
671-
if cls.extract_field(field.name, word) != field.value:
672-
return False
673-
674-
return True
675-
676682
WrappedClass.__name__ = wrapped.__name__
677683
WrappedClass.__module__ = wrapped.__module__
678684
WrappedClass.__qualname__ = wrapped.__qualname__
@@ -701,8 +707,6 @@ def wrapper(wrapped):
701707
class WrappedClass(wrapped): # pylint: disable=too-few-public-methods
702708
"""Generic wrapper class"""
703709

704-
#TODO
705-
706710
WrappedClass.__name__ = wrapped.__name__
707711
WrappedClass.__module__ = wrapped.__module__
708712
WrappedClass.__qualname__ = wrapped.__qualname__

riscvmodel/sim.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def run(self, *, pc=0):
2626
except TerminateException as exc:
2727
assert exc.returncode == 0
2828
return cnt
29-
except IndexError:
29+
except IndexError as exc:
3030
return cnt
3131
return cnt
3232

0 commit comments

Comments
 (0)