Ejemplo n.º 1
0
    def COMPARE(self, arg1: intbv, arg2: intbv, rd, cond="e", signed=True):
        """
        Comapre arg1 and arg2.
        Args:
            arg1: first argument
            arg2: second argument
            cond: comparison condition. e for equal, l for less, and g for greater, le for <=, ge for >=.
            signed: Boolean flag for sign. By default is True. Set to False in case inputs are unsigned
        """
        if signed:  # Check the sign
            arg1 = arg1.signed()
            arg2 = arg2.signed()

        if cond == "e":  # Check the conditions
            self.regs[rd] = intbv(arg1 == arg2)[32:]
            return arg1 == arg2
        elif cond == "l":
            self.regs[rd] = intbv(arg1 < arg2)[32:]
            return arg1 < arg2
        elif cond == "g":
            self.regs[rd] = intbv(arg1 > arg2)[32:]
            return arg1 > arg2
        elif cond == "le":
            self.regs[rd] = intbv(arg1 <= arg2)[32:]
        elif cond == "ge":
            self.regs[rd] = intbv(arg1 >= arg2)[32:]
Ejemplo n.º 2
0
    def BRANCH(self, rs1, rs2, imm: intbv, cond='e', signed=True):
        """
        Execute branching instructions based on comparison conditions of two values
        Args:
            rs1: register source 1
            rs2: register source 2
            imm: immediate value
            cond: e for rs1==rs2, ne for !=, lt for <, ge for >=
            signed: boolean flag. True by default. Set to false to enable unsigned branch
        """
        val1 = intbv(self.regs[rs1])[32:0]
        val2 = intbv(self.regs[rs2])[32:0]
        res = False
        if signed:
            val1 = val1.signed()
            val2 = val2.signed()
        if cond == 'e':
            res = val1 == val2
        elif cond == 'ne':
            res = not (val1 == val2)
        elif cond == 'lt':
            res = val1 < val2
        elif cond == 'ge':
            res = val1 >= val2
        else:
            print("Error: Please enter valid comparison condition")

        if res:
            self.jump_flag = True
            self.pc = self.pc + int(imm.signed())
Ejemplo n.º 3
0
 def LOAD(self, rd, rs1, imm: intbv, width=1, signed=True):
     """
     Executes load instructions.
     Load the value of memory address [ register rs1+imm value(offset) ] into register rd
     Args:
         rd: destination register
         rs1: source register
         imm: immediate value, represents offset
         width: number of bytes. can be 1, 2, or 4 for byte, half word, or word
         signed: boolean flag. Set to True by default. Set to False to enable unsigned immediate
     """
     # These instructions take the form lb rd, imm(rs1)
     if signed:
         imm = imm.signed()
     src = intbv(self.regs[rs1])[32:0]
     target_address = src + imm
     loaded_bytes = None
     if width == 1:
         loaded_bytes = self.ram.read(target_address)
     elif width == 2:
         loaded_bytes = self.ram.readHalfWord(target_address)
     elif width == 4:
         loaded_bytes = self.ram.readWord(target_address)
     else:
         print("Error: please enter valid load width")
         exit(0)
     # Store the loaded byte as an integer in the destination reg
     self.regs[rd] = intbv(int.from_bytes(loaded_bytes, 'little'))[32:]
Ejemplo n.º 4
0
 def JALR(self, rd, rs1, imm: intbv):
     """
     Jump to address stored in rs1 + imm (immediate serves as offset, usually 0)
     Args:
         rd: saves return address
         rs1: contains the address to jump to
         imm: immediate value, serves as offset. Usually 0
     """
     self.regs[rd] = intbv(self.pc + 4)[32:0]
     self.jump_flag = True
     self.pc = self.regs[rs1] + imm.signed()  # immediate is signed
Ejemplo n.º 5
0
 def MUL(self, arg1: intbv, arg2: intbv, rd, sign='S'):
     # I considered the notation (s)(u) to mean arg1 is signed, arg2 not signed
     if sign.capitalize() == 'SU':
         self.regs[rd] = intbv(arg1.signed() * arg2.unsigned())[32:]
         return arg1.signed() * arg2.unsigned()
     elif sign.capitalize() == 'U':
         self.regs[rd] = intbv(arg1 * arg2)[32:]
         return arg1 * arg2
     elif sign.capitalize() == 'S':
         self.regs[rd] = intbv(arg1.signed() * arg2.signed())[32:]
         return arg1.signed() * arg2.signed()
     else:
         print("Error: condition " + sign +
               " is not defined for MUL function")
Ejemplo n.º 6
0
    def JAL(self, rd, imm: intbv):
        """
        Jump by increasing pc by amount of imm. Save return address in rd
        Args:
            rd: saves return address
            imm: immediate value. The pc will be incremented by this amount * 2
        Returns:
        """
        # make immediate a signed number
        imm = imm.signed()

        self.regs[rd] = intbv(self.pc + 4)[32:0]  # Save return address in rd
        self.jump_flag = True  # update jump flag
        self.pc = self.pc + imm  # jump
Ejemplo n.º 7
0
 def SHIFT(self,
           arg1: intbv,
           arg2: intbv,
           rd,
           dir='r',
           signed=False):  # needs testing
     """
     Shifts arg1 by amount of arg2
     Args:
         arg1: Number to be shifted
         arg2: Shift amount
         dir: direction of shift. By default is r. Set to l for shift left
         signed: Boolean flag for sign. By default is False. Set to True to enable sign extension
     """
     if dir == "r":
         if signed:
             self.regs[rd] = intbv(arg1.signed() >> arg2)[32:]
         else:
             self.regs[rd] = intbv(arg1 >> arg2)[32:]
     elif dir == "l":
         self.regs[rd] = intbv(arg1 << arg2)[32:]
Ejemplo n.º 8
0
 def REM(self, arg1: intbv, arg2: intbv, rd, signed=True):
     if signed:
         self.regs[rd] = intbv(arg1.signed() % arg2.signed())[32:]
         return arg1.signed() % arg2.signed()
     self.regs[rd] = intbv(arg1 % arg2)[32:]
     return arg1 % arg2
Ejemplo n.º 9
0
 def DIV(self, arg1: intbv, arg2: intbv, rd, signed=True):
     if signed:
         self.regs[rd] = intbv(arg1.signed() // arg2.signed())[32:]
         return arg1.signed() // arg2.signed()
     self.regs[rd] = intbv(arg1 // arg2)[32:]
     return arg1 // arg2
Ejemplo n.º 10
0
 def SUB(self, arg1: intbv, arg2: intbv, rd: intbv):
     self.regs[rd] = intbv(arg1.signed() - arg2)[32:]
Ejemplo n.º 11
0
 def ADD(self, arg1: intbv, arg2: intbv, rd: intbv):
     self.regs[rd] = intbv(arg1.signed() + arg2.signed())[32:]