Skip to content

Commit 5ee305f

Browse files
committed
Fixes to support encoding/decoding
1 parent 6f866e8 commit 5ee305f

File tree

2 files changed

+62
-66
lines changed

2 files changed

+62
-66
lines changed

riscvmodel/insn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def execute(self, model: Model):
290290
pass
291291

292292

293-
@isa("ecall", RV32I, opcode=0b1110011, funct3=0b000, imm=0b000000000000)
293+
@isa("ecall", RV32I, opcode=0b1110011, funct3=0b000, imm=0b000000000000, rd=0b00000, rs1=0b00000)
294294
class InstructionECALL(InstructionIType):
295295
def execute(self, model: Model):
296296
model.environment.call(model.state)

riscvmodel/isa.py

Lines changed: 61 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
from .types import Immediate, Register
1616
from .variant import RV32I
1717

18-
Field = namedtuple("Field", ["name", "base", "size", "description", "static", "value"])
19-
Field.__new__.__defaults__ = (None, None, None, None, False, None)
18+
Field = namedtuple("Field", ["name", "base", "size", "offset", "description", "static", "value"])
19+
Field.__new__.__defaults__ = (None, None, None, 0, None, False, None)
2020

2121
class Instruction(metaclass=ABCMeta):
2222
"""
@@ -58,7 +58,14 @@ def set_field(cls, field, word, value):
5858
fname = "field_{}".format(field)
5959
base = getattr(cls, fname).base
6060
size = getattr(cls, fname).size
61-
return word | ((value & (2**size - 1)) << base)
61+
if not isinstance(base, list):
62+
base = [base]
63+
size = [size]
64+
off = 0
65+
for part in range(len(base)):
66+
word |= (((value >> off) & (2**size[part] - 1)) << base[part])
67+
off += size[part]
68+
return word
6269

6370
@classmethod
6471
def get_fields(cls):
@@ -131,7 +138,7 @@ def encode(self) -> int:
131138
"""
132139
word = 0
133140
for field in self.get_fields():
134-
if field.static:
141+
if field.value is not None:
135142
word = self.set_field(field.name, word, field.value)
136143
else:
137144
value = getattr(self, field.name)
@@ -207,8 +214,8 @@ class InstructionRType(InstructionFunct3Type, InstructionFunct7Type, metaclass=A
207214
asm_arg_signature = "<rd>, <rs1>, <rs2>"
208215

209216
field_rd = Field(name="rd", base=7, size=5, description="")
210-
field_rs1 = Field(name="rd", base=15, size=5, description="")
211-
field_rs2 = Field(name="rd", base=20, size=5, description="")
217+
field_rs1 = Field(name="rs1", base=15, size=5, description="")
218+
field_rs2 = Field(name="rs2", base=20, size=5, description="")
212219

213220
def __init__(self, rd: int = None, rs1: int = None, rs2: int = None):
214221
super(InstructionRType, self).__init__()
@@ -217,8 +224,8 @@ def __init__(self, rd: int = None, rs1: int = None, rs2: int = None):
217224
self.rs1 = rs1
218225
self.rs2 = rs2
219226

220-
def ops_from_string(self, ops):
221-
(self.rd, self.rs1, self.rs2) = [int(op[1:]) for op in ops.split(",")]
227+
def ops_from_list(self, ops):
228+
(self.rd, self.rs1, self.rs2) = [int(op[1:]) for op in ops]
222229

223230
def randomize(self, variant: Variant):
224231
self.rd = randrange(0, variant.xlen)
@@ -268,7 +275,7 @@ class InstructionIType(InstructionFunct3Type, metaclass=ABCMeta):
268275

269276
field_rd = Field(name="rd", base=7, size=5, description="")
270277
field_rs1 = Field(name="rs1", base=15, size=5, description="")
271-
field_imm = Field(name="imm", base=20, size=5, description="")
278+
field_imm = Field(name="imm", base=20, size=12, description="")
272279

273280
def __init__(self, rd: int = None, rs1: int = None, imm: int = None):
274281
super(InstructionIType, self).__init__()
@@ -279,9 +286,15 @@ def __init__(self, rd: int = None, rs1: int = None, imm: int = None):
279286
self.imm.set(imm)
280287

281288
def ops_from_list(self, ops):
289+
if len(ops) == 0: # ecall
290+
return
282291
self.rd = int(ops[0][1:])
283-
self.rs1 = int(ops[1][1:])
284-
self.imm.set(int(ops[2]))
292+
if ops[1][0] == "x":
293+
self.rs1 = int(ops[1][1:])
294+
self.imm.set(int(ops[2], 0))
295+
else: # Load
296+
self.rs1 = int(ops[2][1:])
297+
self.imm.set(int(ops[1], 0))
285298

286299
def randomize(self, variant: Variant):
287300
self.rd = randrange(0, variant.xlen)
@@ -300,12 +313,6 @@ def __str__(self) -> str:
300313
return "{} x{}, x{}, {}".format(self.mnemonic, self.rd, self.rs1,
301314
self.imm)
302315

303-
def __eq__(self, other) -> bool:
304-
if not super().__eq__(other):
305-
return False
306-
return self.rd == other.rd and self.rs1 == other.rs1 and self.imm == other.imm
307-
308-
309316
class InstructionILType(InstructionIType, metaclass=ABCMeta):
310317
"""
311318
I-type instruction specialization for stores. The produce a different
@@ -335,21 +342,24 @@ class InstructionISType(InstructionFunct3Type,InstructionFunct7Type, metaclass=A
335342
:type imm: int
336343
"""
337344

345+
isa_format_id = "IS"
346+
338347
field_rd = Field(name="rd", base=7, size=5, description="")
339348
field_rs1 = Field(name="rs1", base=15, size=5, description="")
340349
field_shamt = Field(name="shamt", base=20, size=5, description="")
341350

351+
asm_arg_signature = "<rd>, <rs1>, <shamt>"
352+
342353
def __init__(self, rd: int = None, rs1: int = None, shamt: int = None):
343354
super(InstructionISType, self).__init__()
344355
self.rd = rd
345356
self.rs1 = rs1
346357
self.shamt = Immediate(bits=5, init=shamt)
347358

348-
def ops_from_string(self, ops):
349-
ops = ops.split(",")
359+
def ops_from_list(self, ops):
350360
self.rd = int(ops[0][1:])
351361
self.rs1 = int(ops[1][1:])
352-
self.shamt.set(int(ops[2]))
362+
self.shamt.set(int(ops[2], 0))
353363

354364
def randomize(self, variant: Variant):
355365
self.rd = randrange(0, variant.xlen)
@@ -383,17 +393,25 @@ class InstructionSType(InstructionFunct3Type, metaclass=ABCMeta):
383393
:param imm: Offset of store, for calculation of address relative to rs1
384394
:type imm: int
385395
"""
396+
397+
isa_format_id = "S"
398+
399+
field_rs1 = Field(name="rs1", base=15, size=5, description="")
400+
field_rs2 = Field(name="rs2", base=20, size=5, description="")
401+
field_imm = Field(name="imm", base=[7, 25], size=[5, 7], description="")
402+
403+
asm_arg_signature = "<rs2>, <imm>(<rs1>)"
404+
386405
def __init__(self, rs1: int = None, rs2: int = None, imm: int = None):
387406
super(InstructionSType, self).__init__()
388407
self.rs1 = rs1
389408
self.rs2 = rs2
390409
self.imm = Immediate(bits=12, signed=True, init=imm)
391410

392-
def ops_from_string(self, ops):
393-
ops = ops.split(",")
394-
self.rs1 = int(ops[0][1:])
395-
self.rs2 = int(ops[1][ops[1].find("(") + 2:-1])
396-
self.imm.set(int(ops[1][0:ops[1].find("(")]))
411+
def ops_from_list(self, ops):
412+
self.rs1 = int(ops[2][1:])
413+
self.rs2 = int(ops[0][1:])
414+
self.imm.set(int(ops[1], 0))
397415

398416
def randomize(self, variant: Variant):
399417
self.rs1 = randrange(0, variant.xlen)
@@ -411,12 +429,6 @@ def __str__(self):
411429
return "{} x{}, {}(x{})".format(self.mnemonic, self.rs2, self.imm,
412430
self.rs1)
413431

414-
def __eq__(self, other):
415-
if not super().__eq__(other):
416-
return False
417-
return self.rs1 == other.rs1 and self.rs2 == other.rs2 and self.imm == other.imm
418-
419-
420432
class InstructionBType(InstructionFunct3Type, metaclass=ABCMeta):
421433
"""
422434
B-type instructions encode branches. Branches have two source registers that
@@ -430,35 +442,31 @@ class InstructionBType(InstructionFunct3Type, metaclass=ABCMeta):
430442
16-bit aligned)
431443
:type imm: int
432444
"""
445+
446+
isa_format_id = "B"
447+
448+
field_rs1 = Field(name="rs1", base=15, size=5, description="")
449+
field_rs2 = Field(name="rs2", base=20, size=5, description="")
450+
field_imm = Field(name="imm", base=[7, 25], size=[5, 7], offset=1, description="")
451+
452+
asm_arg_signature = "<rs1>, <rs2>, <imm>"
453+
433454
def __init__(self, rs1: int = None, rs2: int = None, imm: int = None):
434455
super(InstructionBType, self).__init__()
435456
self.rs1 = rs1
436457
self.rs2 = rs2
437-
self.imm = Immediate(bits=13, signed=True, lsb0=True)
438-
if imm is not None:
439-
self.imm.set(imm)
458+
self.imm = Immediate(bits=13, signed=True, lsb0=True, init=imm)
440459

441-
def ops_from_string(self, ops):
442-
ops = ops.split(",")
460+
def ops_from_list(self, ops):
443461
self.rs1 = int(ops[0][1:])
444462
self.rs2 = int(ops[1][1:])
445-
self.imm.set(int(ops[2]))
463+
self.imm.set(int(ops[2], 0))
446464

447465
def randomize(self, variant: Variant):
448466
self.rs1 = randrange(0, variant.xlen)
449467
self.rs2 = randrange(0, variant.xlen)
450468
self.imm.randomize()
451469

452-
def decode(self, machinecode: int):
453-
self.rs1 = (machinecode >> 15) & 0x1F
454-
self.rs2 = (machinecode >> 20) & 0x1F
455-
imm11 = (machinecode >> 7) & 0x1
456-
imm1to4 = (machinecode >> 8) & 0xF
457-
imm5to10 = (machinecode >> 25) & 0x3F
458-
imm12 = (machinecode >> 31) & 0x1
459-
self.imm.set_from_bits((imm12 << 12) | (imm11 << 11) | (imm5to10 << 5)
460-
| (imm1to4 << 1))
461-
462470
def inopstr(self, model):
463471
opstr = "{:>3}={}, ".format("x{}".format(self.rs1),
464472
model.state.intreg[self.rs1])
@@ -470,12 +478,6 @@ def __str__(self):
470478
return "{} x{}, x{}, .{:+}".format(self.mnemonic, self.rs1, self.rs2,
471479
self.imm)
472480

473-
def __eq__(self, other):
474-
if not super().__eq__(other):
475-
return False
476-
return self.rs1 == other.rs1 and self.rs2 == other.rs2 and self.imm == other.imm
477-
478-
479481
class InstructionUType(Instruction, metaclass=ABCMeta):
480482
"""
481483
U-type instructions are used for constant formation and set the upper bits of a register.
@@ -485,15 +487,18 @@ class InstructionUType(Instruction, metaclass=ABCMeta):
485487
:param imm: Immediate (20-bit, unsigned)
486488
:type imm: int
487489
"""
490+
491+
field_rd = Field(name="rd", base=7, size=5, description="")
492+
field_imm = Field(name="imm", base=12, size=20, description="")
493+
488494
def __init__(self, rd: int = None, imm: int = None):
489495
super(InstructionUType, self).__init__()
490496
self.rd = rd # pylint: disable=invalid-name
491497
self.imm = Immediate(bits=20, init=imm)
492498

493-
def ops_from_string(self, ops):
494-
ops = ops.split(",")
499+
def ops_from_list(self, ops):
495500
self.rd = int(ops[0][1:])
496-
self.imm.set(int(ops[1]))
501+
self.imm.set(int(ops[1], 0))
497502

498503
def randomize(self, variant: Variant):
499504
self.rd = randrange(0, variant.xlen)
@@ -506,11 +511,6 @@ def outopstr(self, model):
506511
def __str__(self):
507512
return "{} x{}, {}".format(self.mnemonic, self.rd, self.imm)
508513

509-
def __eq__(self, other):
510-
if not super().__eq__(other):
511-
return False
512-
return self.rd == other.rd and self.imm == other.imm
513-
514514

515515
class InstructionJType(Instruction, metaclass=ABCMeta):
516516
"""
@@ -539,10 +539,6 @@ def outopstr(self, model):
539539
def __str__(self):
540540
return "{} x{}, .{:+}".format(self.mnemonic, self.rd, self.imm)
541541

542-
def __eq__(self, other):
543-
if not super().__eq__(other):
544-
return False
545-
return self.rd == other.rd and self.imm == other.imm
546542

547543
class InstructionCType(Instruction, metaclass=ABCMeta):
548544
"""

0 commit comments

Comments
 (0)