Exemplo n.º 1
0
def get_rs1_val(iteration, xlen):
    """
  Calculates and returns the 3 test RS1 values that will be used
  to exercise the CSR.

  Args:
    iteration: Integer between 0 and 2 inclusive, indicates which
               test value to return.
    xlen: The currnet RISC-V ISA bit length.

  Returns:
    A bitarray encoding the value that will be written to the CSR to test it.
    Will be one of 3 values:
      1) 0xa5a5...
      2) 0x5a5a...
      3) A randomly generated number
  """
    if iteration == 0:
        return bitarray(hex=f"0x{'a5'*int(xlen/8)}")
    elif iteration == 1:
        return bitarray(hex=f"0x{'5a'*int(xlen/8)}")
    elif iteration == 2:
        val = bitarray(uint=0, length=xlen)
        # Must randomize all 32 bits, due to randomization library limitations
        for i in range(32):
            bit = random.randint(0, 1)
            val.set(bit, i)
        return val
Exemplo n.º 2
0
def predict_csr_val(csr_op, rs1_val, csr_val, csr_address, csr_write_mask, csr_read_mask):
    """
    Predicts the CSR reference value, based on the current CSR operation.

    Args:
      csr_op: A string of the CSR operation being performed.
      rs1_val: A bitarray containing the value to be written to the CSR.
      csr_val: A bitarray containing the current value of the CSR.
      csr_write_mask: A bitarray containing the CSR's write mask.
      csr_read_mask: A bitarray containing the CSR's read mask

    Returns:
      A hexadecimal string of the predicted CSR value.
    """
    prediction = None
    max_event = bitarray(uint=50, length=32)
    # create a zero bitarray to zero extend immediates
    zero = bitarray(uint=0, length=csr_val.len - 5)
    prediction = csr_read(csr_val, csr_read_mask)
    if csr_op == 'csrrw':
      if (csr_address == 803 or csr_address == 804 or csr_address == 805 or csr_address == 806):
        if(max_event.uint<rs1_val.uint):
          csr_val.overwrite(bitarray(uint=50, length=32), 0) 
        else:
          csr_write(rs1_val, csr_val, csr_write_mask)
      else:
        csr_write(rs1_val, csr_val, csr_write_mask)
    elif csr_op == 'csrrs':
      if (csr_address == 803 or csr_address == 804 or csr_address == 805 or csr_address == 806):
        if((max_event.uint<rs1_val.uint) or (max_event.uint<=csr_val.uint)):
          csr_val.overwrite(bitarray(uint=50, length=32), 0) 
        else:
          csr_write(rs1_val, csr_val, csr_write_mask)
      else:
        csr_write(rs1_val | prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrc':
      """if (csr_address == 803 or csr_address == 804 or csr_address == 805 or csr_address == 806):
        if(max_event.uint<rs1_val.uint):
          csr_val.overwrite(bitarray(uint=0, length=32), 0)
        else:
          csr_write((~rs1_val) & prediction, csr_val, csr_write_mask)
      else:"""
      csr_write((~rs1_val) & prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrwi':
        zero.append(rs1_val[-5:])
        csr_write(zero, csr_val, csr_write_mask)
    elif csr_op == 'csrrsi':
        zero.append(rs1_val[-5:])
        csr_write(zero | prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrci':
        zero.append(rs1_val[-5:])
        csr_write((~zero) & prediction, csr_val, csr_write_mask)
    return "0x{}".format(prediction.hex)
Exemplo n.º 3
0
def get_csr_map(csr_file, xlen):
    """
  Parses the YAML file containing CSR descriptions.

  Args:
    csr_file: The CSR YAML file.
    xlen: The current RISC-V ISA bit length.

  Returns:
    A dictionary contining mappings for each CSR, of the form:
    { csr_name : [csr_address, csr_val_bitarray, csr_write_mask_bitarray, csr_read_mask_bitarray] }
  """
    rv_string = "rv{}".format(str(xlen))
    csrs = {}
    with open(csr_file, "r") as c:
        csr_description = yaml.safe_load(c)
        for csr_dict in csr_description:
            csr_name = csr_dict.get("csr")
            csr_address = csr_dict.get("address")
            assert (
                rv_string
                in csr_dict), "The {} CSR must be configured for rv{}".format(
                    csr_name, str(rv))
            csr_value = bitarray(uintbe=0, length=xlen)
            csr_write_mask = []
            csr_read_mask = bitarray(uintbe=0, length=xlen)
            csr_field_list = csr_dict.get(rv_string)
            for csr_field_detail_dict in csr_field_list:
                field_type = csr_field_detail_dict.get("type")
                field_val = csr_field_detail_dict.get("reset_val")
                field_msb = csr_field_detail_dict.get("msb")
                field_lsb = csr_field_detail_dict.get("lsb")
                field_size = field_msb - field_lsb + 1
                if field_type != "WPRI":
                    val_bitarray = bitarray(uint=field_val, length=field_size)
                    mask_bitarray = bitarray(uint=1, length=1) * field_size
                    start_pos = xlen - 1 - field_msb
                    end_pos = xlen - 1 - field_lsb
                    csr_read_mask.overwrite(mask_bitarray,
                                            xlen - 1 - field_msb)
                    csr_value.overwrite(val_bitarray, xlen - 1 - field_msb)
                    access = True if field_type == "R" else False
                    csr_write_mask.append(
                        [mask_bitarray, (start_pos, end_pos), access])
            csrs.update({
                csr_name:
                [csr_address, csr_value, csr_write_mask, csr_read_mask]
            })
    return csrs
Exemplo n.º 4
0
def predict_csr_val(csr_op, rs1_val, csr_val, csr_write_mask, csr_read_mask):
    """
  Predicts the CSR reference value, based on the current CSR operation.

  Args:
    csr_op: A string of the CSR operation being performed.
    rs1_val: A bitarray containing the value to be written to the CSR.
    csr_val: A bitarray containing the current value of the CSR.
    csr_write_mask: A bitarray containing the CSR's write mask.
    csr_read_mask: A bitarray containing the CSR's read mask

  Returns:
    A hexadecimal string of the predicted CSR value.
  """
    prediction = None
    # create a zero bitarray to zero extend immediates
    zero = bitarray(uint=0, length=csr_val.len - 5)
    prediction = csr_read(csr_val, csr_read_mask)
    if csr_op == 'csrrw':
        csr_write(rs1_val, csr_val, csr_write_mask)
    elif csr_op == 'csrrs':
        csr_write(rs1_val | prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrc':
        csr_write((~rs1_val) & prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrwi':
        zero.append(rs1_val[-5:])
        csr_write(zero, csr_val, csr_write_mask)
    elif csr_op == 'csrrsi':
        zero.append(rs1_val[-5:])
        csr_write(zero | prediction, csr_val, csr_write_mask)
    elif csr_op == 'csrrci':
        zero.append(rs1_val[-5:])
        csr_write((~zero) & prediction, csr_val, csr_write_mask)
    return f"0x{prediction.hex}"
Exemplo n.º 5
0
def gen_csr_instr(csr_map, csr_instructions, xlen, iterations, out):
  """
  Uses the information in the map produced by get_csr_map() to generate
  test CSR instructions operating on the generated random values.

  Args:
    csr_map: The dictionary containing CSR mappings generated by get_csr_map()
    csr_instructions: A list of all supported CSR instructions in string form.
    xlen: The RISC-V ISA bit length.
    iterations: Indicates how many randomized test files will be generated.
    out: A string containing the directory path that the tests will be generated in.

  Returns:
    No explicit return value, but will write the randomized assembly test code
    to the specified number of files.
  """
  for i in range(iterations):
    # pick two GPRs at random to act as source and destination registers
    # for CSR operations
    source_reg, dest_reg = [f"x{i}" for i in random.sample(range(5, 15), 2)]
    csr_list = list(csr_map.keys())
    with open(f"{out}/riscv_csr_test.{i}.S", "w") as csr_test_file:
      csr_test_file.write(f"csr_test:\n")
      for csr in csr_list:
        last_csr = csr
        csr_val, csr_mask = csr_map.get(csr)
        for op in csr_instructions:
          for i in range(3):
            # hex string
            rand_rs1_val = get_rs1_val(i, xlen)
            # I type CSR instruction
            first_li = ""
            if op[-1] == "i":
              imm = rand_rs1_val[-5:]
              csr_inst = f"\t{op} {dest_reg}, {csr}, 0b{imm.bin}\n"
            else:
              first_li = f"\tli {source_reg}, 0x{rand_rs1_val.hex}\n"
              csr_inst = f"\t{op} {dest_reg}, {csr}, {source_reg}\n"
              predict_li = f"\tli {source_reg}, {predict_csr_val(op, rand_rs1_val, csr_val, csr_mask)}\n"
            branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
            csr_test_file.write(first_li)
            csr_test_file.write(csr_inst)
            csr_test_file.write(predict_li)
            csr_test_file.write(branch_check)
            """
            We must hardcode in one final CSR check, as the value that has last
            been written to the CSR has not been tested.
            """
            if csr == csr_list[-1] and op == csr_instructions[-1] and i == 2:
              final_csr_read = f"\tcsrr {dest_reg}, {csr_list[-1]}\n"
              csrrs_read_mask = bitarray(uint=0, length=xlen)
              final_li = f"\tli {source_reg}, {predict_csr_val('csrrs', csrrs_read_mask, csr_val, csr_mask)}\n"
              final_branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
              csr_test_file.write(final_csr_read)
              csr_test_file.write(final_li)
              csr_test_file.write(final_branch_check)
      gen_csr_test_pass(csr_test_file)
      gen_csr_test_fail(csr_test_file)
Exemplo n.º 6
0
def gen_csr_instr(original_csr_map, csr_instructions, xlen, iterations, out,
                  end_signature_addr):
    """
    Uses the information in the map produced by get_csr_map() to generate
    test CSR instructions operating on the generated random values.

    Args:
      original_csr_map: The dictionary containing CSR mappings generated by get_csr_map()
      csr_instructions: A list of all supported CSR instructions in string form.
      xlen: The RISC-V ISA bit length.
      iterations: Indicates how many randomized test files will be generated.
      out: A string containing the directory path that the tests will be generated in.
      end_signature_addr: The address the test should write to upon terminating

    Returns:
      No explicit return value, but will write the randomized assembly test code
      to the specified number of files.
    """
    for i in range(iterations):
        # pick two GPRs at random to act as source and destination registers
        # for CSR operations
        csr_map = copy.deepcopy(original_csr_map)
        source_reg, dest_reg = [
            "x{}".format(i) for i in random.sample(range(1, 16), 2)
        ]
        csr_list = list(csr_map.keys())
        with open("{}/riscv_csr_test_{}.S".format(out, i),
                  "w") as csr_test_file:
            gen_setup(csr_test_file)
            for csr in csr_list:
                csr_address, csr_val, csr_write_mask, csr_read_mask = csr_map.get(
                    csr)
                csr_test_file.write("\t# {}\n".format(csr))
                for op in csr_instructions:
                    for i in range(3):
                        # hex string
                        rand_rs1_val = get_rs1_val(i, xlen)
                        # I type CSR instruction
                        first_li = ""
                        if op[-1] == "i":
                            imm = rand_rs1_val[-5:]
                            csr_inst = "\t{} {}, {}, 0b{}\n".format(
                                op, dest_reg, csr_address, imm.bin)
                            imm_val = bitarray(uint=0, length=xlen - 5)
                            imm_val.append(imm)
                            predict_li = ("\tli {}, "
                                          "{}\n".format(
                                              source_reg,
                                              predict_csr_val(
                                                  op, imm_val, csr_val,
                                                  csr_write_mask,
                                                  csr_read_mask)))
                        else:
                            first_li = "\tli {}, 0x{}\n".format(
                                source_reg, rand_rs1_val.hex)
                            csr_inst = "\t{} {}, {}, {}\n".format(
                                op, dest_reg, csr_address, source_reg)
                            predict_li = ("\tli {}, "
                                          "{}\n".format(
                                              source_reg,
                                              predict_csr_val(
                                                  op, rand_rs1_val, csr_val,
                                                  csr_write_mask,
                                                  csr_read_mask)))
                        branch_check = "\tbne {}, {}, csr_fail\n".format(
                            source_reg, dest_reg)
                        csr_test_file.write(first_li)
                        csr_test_file.write(csr_inst)
                        csr_test_file.write(predict_li)
                        csr_test_file.write(branch_check)
                        """
            We must hardcode in one final CSR check, as the value that has last
            been written to the CSR has not been tested.
            """
                        if csr == csr_list[-1] and op == csr_instructions[
                                -1] and i == 2:
                            final_csr_read = "\tcsrr {}, {}\n".format(
                                dest_reg, csr_address)
                            csrrs_read_mask = bitarray(uint=0, length=xlen)
                            final_li = ("\tli {}, "
                                        "{}\n".format(
                                            source_reg,
                                            predict_csr_val(
                                                'csrrs', csrrs_read_mask,
                                                csr_val, csr_write_mask,
                                                csr_read_mask)))
                            final_branch_check = "\tbne {}, {}, csr_fail\n".format(
                                source_reg, dest_reg)
                            csr_test_file.write(final_csr_read)
                            csr_test_file.write(final_li)
                            csr_test_file.write(final_branch_check)
            gen_csr_test_pass(csr_test_file, end_signature_addr)
            gen_csr_test_fail(csr_test_file, end_signature_addr)