Skip to content

Commit abe8d69

Browse files
author
Peter Birch
committed
Adding support for RV32A atomic operations (AMO*, LR, and SC)
1 parent 3d49550 commit abe8d69

3 files changed

Lines changed: 166 additions & 1 deletion

File tree

riscvmodel/insn.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,91 @@ def expand(self):
481481

482482
def execute(self, model: Model):
483483
model.state.intreg[self.rd] = model.state.intreg[self.rs]
484+
485+
486+
@isa("lr", RV32A, opcode=0b0101111, funct7=0b0001011, funct3=0b010)
487+
class InstructionLR(InstructionRType):
488+
""" Load reserved """
489+
def execute(self, model: Model):
490+
# TODO: implement
491+
pass
492+
493+
494+
@isa("sc", RV32A, opcode=0b0101111, funct7=0b0001111, funct3=0b010)
495+
class InstructionSC(InstructionRType):
496+
""" Store conditional """
497+
def execute(self, model: Model):
498+
# TODO: implement
499+
pass
500+
501+
502+
@isa("amoadd", RV32A, opcode=0b0101111, funct5=0b00000, funct3=0b010)
503+
class InstructionAMOADD(InstructionAMOType):
504+
""" Atomic swap operation """
505+
def execute(self, model: Model):
506+
# TODO: implement
507+
pass
508+
509+
510+
@isa("amoxor", RV32A, opcode=0b0101111, funct5=0b00100, funct3=0b010)
511+
class InstructionAMOXOR(InstructionAMOType):
512+
""" Atomic swap operation """
513+
def execute(self, model: Model):
514+
# TODO: implement
515+
pass
516+
517+
518+
@isa("amoor", RV32A, opcode=0b0101111, funct5=0b01000, funct3=0b010)
519+
class InstructionAMOOR(InstructionAMOType):
520+
""" Atomic swap operation """
521+
def execute(self, model: Model):
522+
# TODO: implement
523+
pass
524+
525+
526+
@isa("amoand", RV32A, opcode=0b0101111, funct5=0b01100, funct3=0b010)
527+
class InstructionAMOAND(InstructionAMOType):
528+
""" Atomic swap operation """
529+
def execute(self, model: Model):
530+
# TODO: implement
531+
pass
532+
533+
534+
@isa("amomin", RV32A, opcode=0b0101111, funct5=0b10000, funct3=0b010)
535+
class InstructionAMOMIN(InstructionAMOType):
536+
""" Atomic swap operation """
537+
def execute(self, model: Model):
538+
# TODO: implement
539+
pass
540+
541+
542+
@isa("amomax", RV32A, opcode=0b0101111, funct5=0b10100, funct3=0b010)
543+
class InstructionAMOMAX(InstructionAMOType):
544+
""" Atomic swap operation """
545+
def execute(self, model: Model):
546+
# TODO: implement
547+
pass
548+
549+
550+
@isa("amominu", RV32A, opcode=0b0101111, funct5=0b11000, funct3=0b010)
551+
class InstructionAMOMINU(InstructionAMOType):
552+
""" Atomic swap operation """
553+
def execute(self, model: Model):
554+
# TODO: implement
555+
pass
556+
557+
558+
@isa("amomaxu", RV32A, opcode=0b0101111, funct5=0b11100, funct3=0b010)
559+
class InstructionAMOMAXU(InstructionAMOType):
560+
""" Atomic swap operation """
561+
def execute(self, model: Model):
562+
# TODO: implement
563+
pass
564+
565+
566+
@isa("amoswap", RV32A, opcode=0b0101111, funct5=0b00001, funct3=0b010)
567+
class InstructionAMOSWAP(InstructionAMOType):
568+
""" Atomic swap operation """
569+
def execute(self, model: Model):
570+
# TODO: implement
571+
pass

riscvmodel/isa.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ def __eq__(self, other):
212212
class InstructionFunct3Type(Instruction, metaclass=ABCMeta):
213213
field_funct3 = Field(name="funct3", base=12, size=3, description="", static=True)
214214

215+
class InstructionFunct5Type(Instruction, metaclass=ABCMeta):
216+
field_funct5 = Field(name="funct5", base=27, size=5, description="", static=True)
217+
215218
class InstructionFunct7Type(Instruction, metaclass=ABCMeta):
216219
field_funct7 = Field(name="funct7", base=25, size=7, description="", static=True)
217220

@@ -647,6 +650,79 @@ def randomize(self, variant: Variant):
647650
self.imm.randomize()
648651

649652

653+
class InstructionAMOType(InstructionFunct3Type, InstructionFunct5Type, metaclass=ABCMeta):
654+
"""
655+
AMO-type instructions used a modified version of the R-type instruction.
656+
These are also 3-register instructions (use 2 source, write 1 output) but
657+
have additional flags for controlling acquisition (aq) and release (rl) of
658+
locks on target addresses.
659+
660+
:param rd: Destination register
661+
:type rd: int
662+
:param rs1: Source register 1
663+
:type rs1: int
664+
:param rs2: Source register 2
665+
:type rs2: int
666+
:param rl: Lock release flag
667+
:type rl: int
668+
:param aq: Lock acquisition flag
669+
:type aq: int
670+
"""
671+
672+
isa_format_id = "R"
673+
asm_arg_signature = "<rd>, <rs1>, <rs2>, <rl>, <aq>"
674+
675+
field_rd = Field(name="rd", base=7, size=5, description="")
676+
field_rs1 = Field(name="rs1", base=15, size=5, description="")
677+
field_rs2 = Field(name="rs2", base=20, size=5, description="")
678+
field_rl = Field(name="rl", base=25, size=1, description="Lock release")
679+
field_aq = Field(name="aq", base=26, size=1, description="Lock acquire")
680+
681+
def __init__(
682+
self,
683+
rd: int = None,
684+
rs1: int = None,
685+
rs2: int = None,
686+
rl: int = None,
687+
aq: int = None,
688+
):
689+
super(InstructionAMOType, self).__init__()
690+
self.rd = rd
691+
self.rs1 = rs1
692+
self.rs2 = rs2
693+
self.rl = rl
694+
self.aq = aq
695+
696+
def ops_from_list(self, ops):
697+
(self.rd, self.rs1, self.rs2, self.rl, self.aq) = [int(op[1:]) for ops in ops]
698+
699+
def randomize(self, variant: Variant):
700+
self.rd = randrange(0, variant.xlen)
701+
self.rs1 = randrange(0, variant.xlen)
702+
self.rs2 = randrange(0, variant.xlen)
703+
self.rl = randrange(0, variant.xlen)
704+
self.aq = randrange(0, variant.xlen)
705+
706+
def inopstr(self, model):
707+
opstr = "{:>3}={}, ".format(
708+
"x{}".format(self.rs1), model.state.intreg[self.rs1]
709+
)
710+
opstr += "{:>3}={} ".format(
711+
"x{}".format(self.rs2), model.state.intreg[self.rs2]
712+
)
713+
return opstr
714+
715+
def outopstr(self, model):
716+
return "{:>3}={} ".format(
717+
"x{}".format(self.rd), model.state.intreg[self.rd]
718+
)
719+
720+
def __str__(self):
721+
return "{} x{}, x{}, x{}, {}, {}".format(
722+
self.mnemonic, self.rd, self.rs1, self.rs2, self.rl, self.aq
723+
)
724+
725+
650726
def isa(mnemonic: str,
651727
variant: Variant,
652728
*,

riscvmodel/variant.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Variant:
2828
"Zifencei": Extension("Zifencei", "Instruction-Fetch Fence", [])
2929
}
3030
regex = re.compile(
31-
r"^RV(32|64|128)(I|E|G)({})*((?:(?:Z|X).+)(?:_(?:(?:Z|X).*))*)?$".
31+
r"^RV(32|64|128)(A|I|E|G)({})*((?:(?:Z|X).+)(?:_(?:(?:Z|X).*))*)?$".
3232
format("|".join(list(stdext.keys()) + ["G"])))
3333
G_expand = ["I", "M", "A", "F", "D", "Zicsr", "Zifencei"]
3434

@@ -133,6 +133,7 @@ def __add__(self, other):
133133
RV64G = Variant("RV64G")
134134
RV64GC = Variant("RV64GC")
135135
RV128I = Variant("RV128I")
136+
RV32A = Variant("RV32A")
136137

137138

138139
def describe_argparser():

0 commit comments

Comments
 (0)