예제 #1
0
    def decode_instruction(self, control, op):
        opcode = op[-7:]
        encodings, operands = self.get_encodings(op)
        self.precompute_base(op, operands)

        decoder = RiscDecoder(opcode)
        for code, encode_type, fct in self.get_op_mapping():
            fct(control & decoder.get_control(code), *encodings[encode_type])

        ###  Specific parts ###
        rd = operands[0]

        # Shifts
        (c1, dec1), (c2, dec2) = self.left_shifts
        result = arith.left_shift(self.reg_rs1, mux(c1, dec2, dec1))
        self.write_rd(c1 | c2, result)

        (c1, dec1, lead1), (c2, dec2, lead2) = self.right_shifts
        result = arith.right_shift(self.reg_rs1, mux(c1, dec2, dec1), False,
                                   mux(c1, lead2, lead1))
        self.write_rd(c1 | c2, result)

        ## Write in rd
        control = self.all_rd_writes[0][0]
        val = self.all_rd_writes[0][1]
        for c, v in self.all_rd_writes[1:]:
            control = control | c
            val = mux(c, val, v)
        self.proc.registers.write_reg(control, rd, val)
예제 #2
0
    def do_division(dividend, divisor, step):
        if step >= len(dividend):
            return (bit(size=0), dividend)
        quotient_up, dividend_up = do_division(dividend, divisor << 1,
                                               step + 1)
        # Don't overflow
        dividend = mux(divisor[1], dividend_up, dividend)
        quotient = mux(divisor[1], quotient_up, bit(0, size=len(quotient_up)))

        sub = hdl.simple_adder(dividend, hdl.negative_of_int(divisor))[0]
        return (mux(sub[0], quotient + '1',
                    quotient + '0'), mux(sub[0], sub, dividend))
예제 #3
0
def left_shift(bits, shift, invert=False):
    shift = list(shift)
    k = -1 if invert else 1
    while shift:
        bits = mux(shift.pop(), bits, bits << k)
        k *= 2
    return bits
예제 #4
0
 def comp(self, control, first, second, signed):
     self.signed.set(self.signed.get() | (control & signed))
     if len(second) < self.word_size:
         second = mux(signed, hdl.extend(self.word_size, second),
                      hdl.sign_extend(self.word_size, second))
     self.add(control, first, second, True)
     return self.num_result[0]
예제 #5
0
    def op_load(self, control, rd, width, rs1, offset):
        # Implements LW, LH, LHU, LB, LBU
        addr = self.alu.add(control, self.reg_rs1,
                            hdl.sign_extend(self.word_size, offset))[0]
        result = self.proc.memory.read_at(control, addr)
        # First bit is 1 if unsigned
        r_16bits = mux(addr[-2], result[:16], result[16:])
        r_16bits_ext = hdl.extend(self.word_size, r_16bits,
                                  (~width[0]) & r_16bits[0])

        r_8bits = mux(addr[-1], r_16bits[:8], r_16bits[8:])
        r_8bits_ext = hdl.extend(self.word_size, r_8bits,
                                 (~width[0]) & r_8bits[0])
        result = mux(width[1], mux(width[2], r_8bits_ext, r_16bits_ext),
                     result)  # LW = 010, LH[U] = *01, LB[U] = *00

        self.write_rd(control, result)
예제 #6
0
    def op_branch(self, control, offset1, funct3, rs1_addr, rs2_addr, offset2):
        equality = ~hdl.merge_with_op(hdl.OrOp, self.reg_rs1 ^ self.reg_rs2)
        r1_m_r2 = self.alu.comp(control, self.reg_rs1, self.reg_rs2,
                                ~funct3[1])
        r = mux(funct3[0], equality, r1_m_r2[0])
        r = r ^ funct3[2]  # Invert if funct3[2] == 1

        offset = hdl.sign_extend(self.word_size, offset1 + offset2)
        # Don't use the ALU 2 times
        jump_addr = self.proc.adder(self.proc.reg_pc, offset)[0]
        self.proc.reg_pc.add(control & r, jump_addr)
예제 #7
0
    def write_at(self, control, addr, value):
        # Because it is 32bit-addressed
        value = arith.right_shift(value, addr[-5:])
        addr = addr[:-5][-IO_SIGNIFICANT_BITS:]

        for i_out in range(len(self.outputs)):
            bit_eq = ~(addr ^ self.out_addresses[i_out])
            is_eq = hdl.merge_with_op(hdl.AndOp, bit_eq)
            length = len(self.outputs[i_out])

            self.outputs[i_out] = mux(is_eq & control, self.outputs[i_out],
                                      value[-length:])
예제 #8
0
def right_shift(bits, shift, invert=False, lead_bit=bit('0')):
    if invert:
        return left_shift(bits, shift)

    lead = lead_bit
    shift = list(shift)
    k = 1
    while shift:
        bits = mux(shift.pop(), bits, lead + bits[:-k])
        k *= 2
        lead = lead + lead
    return bits
예제 #9
0
    def op_m_ext(self, control, rd, funct3, rs1, rs2):
        if self.proc.MUL_ENABLED:
            # '000' -> mul
            # '011' -> mulhu
            # '001' -> mulh
            # '010' -> mulhsu
            mul_control = (~funct3[0]) & control
            hight_control = funct3[1] | funct3[2]

            sign1 = self.reg_rs1[0] & (funct3[1] ^ funct3[2])
            sign2 = self.reg_rs2[0] & (~funct3[1])

            num1 = hdl.extend(64, self.reg_rs1, sign1)
            num2 = hdl.extend(64, self.reg_rs2, sign2)
            m_ext_mul = hdl.simple_product(num1, num2)

            self.write_rd(mul_control & hight_control, m_ext_mul[:32])
            self.write_rd(mul_control & (~hight_control), m_ext_mul[-32:])

        if self.proc.DIV_ENABLED:
            # 100 -> div
            # 110 -> rem
            # 101 -> divu
            # 111 -> remu
            div_control = funct3[0] & control
            rem_control = funct3[1]
            is_signed = ~funct3[2]

            sign1 = is_signed & self.reg_rs1[0]
            sign2 = is_signed & self.reg_rs2[0]
            num1 = mux(sign1, self.reg_rs1, hdl.negative_of_int(self.reg_rs1))
            num2 = mux(sign2, self.reg_rs2, hdl.negative_of_int(self.reg_rs2))

            quotient, remainder = arith.simple_divide(num1, num2)
            quotient = mux(sign1 ^ sign2, quotient,
                           hdl.negative_of_int(quotient))
            remainder = mux(sign1, remainder, hdl.negative_of_int(remainder))

            self.write_rd(div_control & rem_control, remainder)
            self.write_rd(div_control & (~rem_control), quotient)
예제 #10
0
    def read_at(self, control: 'bit', addr: 32, memory_only=False):
        dest, addr = addr[:3], addr[3:][:-2] + bit('00000')
        self.used = self.used | (control &
                                 (~(dest[0] | dest[1])))  # RAM and ROM -> 00x
        output = bit(0, size=32)

        for dest_id, dest_obj, is_memory in self.sources:
            if not memory_only or is_memory:
                isdest = ~(bit(dest) ^ dest_id)
                isdest = isdest[0] & isdest[1] & isdest[2]
                dest_out = dest_obj.read_at(control & isdest, addr)
                if dest_out is not None:
                    output = mux(isdest, output, dest_out)
        return output
예제 #11
0
    def __init__(self, size, adder_function):
        self.input1 = MultiControl()
        self.input2 = MultiControl()
        self.inv = virtual(1, bit(0))
        self.signed = virtual(1, bit(0))
        self.word_size = size

        operand1 = virtual(size, self.input1)
        operand1 = mux(
            self.signed,
            hdl.extend(size + 1, operand1),
            hdl.sign_extend(size + 1, operand1),
        )

        operand2 = virtual(size, self.input2)
        operand2 = mux(
            self.signed,
            hdl.extend(size + 1, operand2),
            hdl.sign_extend(size + 1, operand2),
        )
        operand2 = mux(self.inv, operand2, hdl.negative_of_int(operand2))
        self.num_result, self.carry = adder_function(operand1, operand2)
        self.result = self.num_result[1:], self.num_result[0]
예제 #12
0
def simple_divide(dividend: 'l', divisor: 'l') -> (Bit, Bit):
    """ Returns (quotient, remainder) """
    sign = dividend[0] ^ divisor[0]
    dividend = '0' + mux(dividend[0], dividend, hdl.negative_of_int(dividend))
    divisor = '0' + mux(divisor[0], divisor, hdl.negative_of_int(divisor))

    def do_division(dividend, divisor, step):
        if step >= len(dividend):
            return (bit(size=0), dividend)
        quotient_up, dividend_up = do_division(dividend, divisor << 1,
                                               step + 1)
        # Don't overflow
        dividend = mux(divisor[1], dividend_up, dividend)
        quotient = mux(divisor[1], quotient_up, bit(0, size=len(quotient_up)))

        sub = hdl.simple_adder(dividend, hdl.negative_of_int(divisor))[0]
        return (mux(sub[0], quotient + '1',
                    quotient + '0'), mux(sub[0], sub, dividend))

    quotient, remain = do_division(dividend, divisor, 0)
    remain = remain[1:]
    remain = mux(sign, remain, hdl.negative_of_int(remain))
    return quotient[1:], remain
예제 #13
0
    def write_reg(self, control: 'bit', addr: 'bus', val: 'bus'):
        if len(addr) != self.reg_addr_size:
            raise hdl.BuildError(
                f"The size of the register address must be {self.reg_addr_size}, not {len(addr)}"
            )
        if len(val) != self.word_size:
            raise hdl.BuildError(
                f"The size of the register value must be {self.word_size}, not {len(val)}"
            )

        reg_controls = SimpleDecoder(addr)

        for i_reg, register in enumerate(self.registers):
            if i_reg:
                register.source(
                    mux(control & reg_controls.get_control(i_reg), register,
                        val))
예제 #14
0
    def op_store(self, control, offset1, width, rs1_dest, rs2_src, offset2):
        # Implements SW, SH, SB
        addr = self.alu.add(control, self.reg_rs1,
                            hdl.sign_extend(self.word_size,
                                            offset1 + offset2))[0]
        data_32 = self.reg_rs2  # SW : 010

        # Do not overwrite previous data
        prev = self.proc.memory.read_at(control & (~width[1]), addr)

        p1 = mux((~addr[-1]) & (~addr[-2]), prev[0:8], data_32[24:])
        p2 = mux(addr[-1] & (~addr[-2]), prev[8:16], data_32[24:])
        p3 = mux((~addr[-1]) & addr[-2], prev[16:24], data_32[24:])
        p4 = mux(addr[-1] & addr[-2], prev[24:], data_32[24:])

        # SH : 001
        # SB : 000
        data_16 = mux(addr[-2], data_32[16:] + prev[16:],
                      prev[0:16] + data_32[16:])
        data_8 = p1 + p2 + p3 + p4

        data = mux(width[1], mux(width[2], data_8, data_16), data_32)

        self.proc.memory.write_at(control, addr, data)