def gen_amo_instr(self): allowed_lr_instr = [] allowed_sc_instr = [] if riscv_instr_group_t.RV32A in rcs.supported_isa: allowed_lr_instr.append(riscv_instr_name_t.LR_W) allowed_sc_instr.append(riscv_instr_name_t.SC_W) if riscv_instr_group_t.RV64A in rcs.supported_isa: allowed_lr_instr.append(riscv_instr_name_t.LR_D) allowed_sc_instr.append(riscv_instr_name_t.SC_D) self.lr_instr = riscv_instr.get_rand_instr( include_instr=allowed_lr_instr) self.sc_instr = riscv_instr.get_rand_instr( include_instr=allowed_sc_instr) with self.lr_instr.randomize_with(): # self.lr_instr.rs1 == self.rs1_reg[0] # TODO Getting error with vsc.if_then(self.reserved_rd.size > 0): self.lr_instr.rd.not_inside(vsc.rangelist(self.reserved_rd)) with vsc.if_then(cfg.reserved_regs.size > 0): self.lr_instr.rd.not_inside(vsc.rangelist(cfg.reserved_regs)) # self.lr_instr.rd != self.rs1_reg[0] # TODO with self.sc_instr.randomize_with(): # self.sc_instr.rs1 == self.rs1_reg[0] # TODO with vsc.if_then(self.reserved_rd.size > 0): self.sc_instr.rd.not_inside(vsc.rangelist(self.reserved_rd)) with vsc.if_then(cfg.reserved_regs.size > 0): self.sc_instr.rd.not_inside(vsc.rangelist(cfg.reserved_regs)) # self.sc_instr.rd != self.rs1_reg[0] # TODO self.instr_list.extend((self.lr_instr, self.sc_instr))
def ab_c(self): with vsc.if_then(self.a == 1): with vsc.if_then(self.b == 2): self.c == 2 with vsc.foreach(self.arr, idx=True) as i: with vsc.if_then(self.a == 1): self.arr[i] == 1
def legal_rv32_c_slli(self): with vsc.if_then((self.c_msb == 0) and (self.c_op == 2) and (self.xlen == 32)): with vsc.if_then(self.exception == illegal_instr_type_e.kReservedCompressedInstr): self.instr_bin[12] == 1 with vsc.else_then(): self.instr_bin[12] == 0
def illegal_func7_c(self): with vsc.if_then(self.compressed == 0): with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalFunc7): self.func7.not_inside(vsc.rangelist(0, 32, 1)) with vsc.if_then(self.opcode == 9): # SLLI, SRLI, SRAI self.func7[6:1].not_inside(vsc.rangelist(0, 16)) with vsc.else_then(): self.func7.inside(vsc.rangelist(0, 32, 1))
def mstatus_c(self): with vsc.if_then(self.set_mstatus_mprv == 1): self.mstatus_mprv == 1 with vsc.else_then(): self.mstatus_mprv == 0 with vsc.if_then(self.SATP_MODE == satp_mode_t.BARE): self.mstatus_mxr == 0 self.mstatus_sum == 0 self.mstatus_tvm == 0
def illegal_compressed_op_c(self): with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalCompressedOpcode): self.c_op != 1 with vsc.if_then(self.legal_c00_opcode.size == 8): self.c_op != 0 with vsc.else_then(): self.c_msb.not_inside(vsc.rangelist(self.legal_c00_opcode)) with vsc.if_then(self.legal_c10_opcode.size == 8): self.c_op != 2 with vsc.else_then(): self.c_msb.not_inside(vsc.rangelist(self.legal_c10_opcode))
def gen_amo_instr(self): for i in range(self.num_amo): self.amo_instr.append(riscv_instr.get_rand_instr( include_category=[riscv_instr_category_t.AMO])) with self.amo_instr[i].randomize_with(): with vsc.if_then(self.reserved_rd.size > 0): self.amo_instr[i].rd.not_inside(vsc.rangelist(self.reserved_rd)) with vsc.if_then(cfg.reserved_regs.size > 0): self.amo_instr[i].rd.not_inside(vsc.rangelist(cfg.reserved_regs)) self.amo_instr[i].rs1.inside(vsc.rangelist(self.rs1_reg)) self.amo_instr[i].rd.inside(vsc.rangelist(self.rs1_reg)) self.instr_list.insert(0, self.amo_instr[i])
def test_2(self): @vsc.randobj class my_sub_s(object): def __init__(self): self.has_rs1 = vsc.uint8_t(1) self.has_rs2 = vsc.uint8_t(1) self.has_rd = vsc.uint8_t(1) self.avail_regs = vsc.rand_list_t(vsc.uint8_t(0), 10) self.reserved_rd = vsc.rand_list_t(vsc.uint8_t(0), 10) self.reserved_regs = vsc.rand_list_t(vsc.uint8_t(0), 10) self.rd = vsc.rand_uint8_t(0) self.rs1 = vsc.rand_uint8_t(0) self.rs2 = vsc.rand_uint8_t(0) self.format = vsc.uint8_t(2) obj = my_sub_s() with obj.randomize_with() as it: with vsc.if_then(obj.avail_regs.size > 0): with vsc.if_then(obj.has_rs1): obj.rs1.inside(vsc.rangelist(obj.avail_regs)) with vsc.if_then(obj.has_rs2): obj.rs2.inside(vsc.rangelist(obj.avail_regs)) with vsc.if_then(obj.has_rd): obj.rd.inside(vsc.rangelist(obj.avail_regs)) with vsc.foreach(obj.reserved_rd, idx=True) as i: with vsc.if_then(obj.has_rd): obj.rd != obj.reserved_rd[i] with vsc.if_then(obj.format == 2): obj.rs1 != obj.reserved_rd[i] with vsc.foreach(obj.reserved_regs, idx=True) as i: with vsc.if_then(obj.has_rd): obj.rd != obj.reserved_regs[i] with vsc.if_then(obj.format == 2): obj.rs1 != obj.reserved_regs[i]
def system_instr_c(self): with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalSystemInstr): self.opcode == 115 # ECALL/EBREAK/xRET/WFI with vsc.if_then(self.func3 == 0): # Constrain RS1 and RD to be non-zero self.instr_bin[19:15] != 0 self.instr_bin[11:7] != 0 # Valid SYSTEM instructions considered by this # Constrain the upper 12 bits to be invalid self.instr_bin[31:20].not_inside(vsc.rangelist(0, 1, 2, 258, 770, 1970, 261)) with vsc.else_then(): # Invalid CSR instructions self.instr_bin[31:20].not_inside(vsc.rangelist(self.csrs))
def exception_type_c(self): with vsc.if_then(self.compressed == 1): self.exception.inside(vsc.rangelist(illegal_instr_type_e.kReservedCompressedInstr, illegal_instr_type_e.kIllegalCompressedOpcode, illegal_instr_type_e.kHintInstr)) with vsc.else_then(): self.exception.inside(vsc.rangelist(illegal_instr_type_e.kIllegalOpcode, illegal_instr_type_e.kIllegalFunc3, illegal_instr_type_e.kIllegalFunc7, illegal_instr_type_e.kIllegalSystemInstr)) with vsc.if_then(self.has_func7 == 0): self.exception != illegal_instr_type_e.kIllegalFunc7 with vsc.if_then(self.has_func3 == 0): self.exception != illegal_instr_type_e.kIllegalFunc3
def instr_bit_assignment_c(self): vsc.solve_order(self.opcode, self.instr_bin) vsc.solve_order(self.func3, self.instr_bin) vsc.solve_order(self.func7, self.instr_bin) vsc.solve_order(self.c_msb, self.instr_bin) # vsc.solve_order(self.c_op, self.instr_bin) with vsc.if_then(self.compressed == 1): self.instr_bin[1:0] == self.c_op self.instr_bin[15:13] == self.c_msb with vsc.else_then(): self.instr_bin[6:0] == self.opcode with vsc.if_then(self.has_func7 == 1): self.instr_bin[31:25] == self.func7 with vsc.if_then(self.has_func3 == 1): self.instr_bin[14:12] == self.func3
def imm_val_c(self): with vsc.if_then( self.imm_type.inside(vsc.rangelist(imm_t.NZIMM, imm_t.NZUIMM))): self.imm[5:0] != 0 with vsc.if_then(self.instr_name == riscv_instr_name_t.C_LUI): self.imm[31:5] == 0 with vsc.if_then( self.instr_name.inside( vsc.rangelist(riscv_instr_name_t.C_SRAI, riscv_instr_name_t.C_SRLI, riscv_instr_name_t.C_SLLI))): self.imm[31:5] == 0 with vsc.if_then(self.instr_name == riscv_instr_name_t.C_ADDI4SPN): self.imm[1:0] == 0
def has_func7_c(self): vsc.solve_order(self.opcode, self.func7) with vsc.if_then((self.opcode == 19) and (self.func3 == 1 or self.func3 == 5) or (self.opcode == 51 or self.opcode == 59)): self.has_func7 == 1 with vsc.else_then(): self.has_func7 == 0
def illegal_opcode_c(self): vsc.solve_order(self.opcode, self.instr_bin) with vsc.if_then(self.exception == illegal_instr_type_e.kIllegalOpcode): self.opcode.not_inside(vsc.rangelist(self.legal_opcode)) self.opcode[1:0] == 3 with vsc.else_then(): self.opcode.inside(vsc.rangelist(self.legal_opcode))
def has_func3_c(self): vsc.solve_order(self.opcode, self.func7) with vsc.if_then(self.opcode == 55 or self.opcode == 111 or self.opcode == 23): self.has_func3 == 0 with vsc.else_then(): self.has_func3 == 1
def mtvec_c(self): self.mtvec_mode.inside( vsc.rangelist(mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED)) with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT): vsc.soft(self.tvec_alignment == 2) with vsc.else_then(): vsc.soft(self.tvec_alignment == (rcs.XLEN * 4) // 8)
def imm_c(self): with vsc.if_then( self.instr_name.inside( vsc.rangelist(riscv_instr_name_t.SLLIW, riscv_instr_name_t.SRLIW, riscv_instr_name_t.SRAIW))): self.imm[11:5] == 0 with vsc.if_then( self.instr_name.inside( vsc.rangelist(riscv_instr_name_t.SLLI, riscv_instr_name_t.SRLI, riscv_instr_name_t.SRAI))): with vsc.if_then(self.XLEN == 32): self.imm[11:5] == 0 with vsc.if_then(self.XLEN != 32): self.imm[11:6] == 0
def aligned_amo_c(self): with vsc.foreach(self.offset, idx = True) as i: with vsc.if_then(self.XLEN == 32): self.offset[i] % 4 == 0 with vsc.else_then(): self.offset[i] % 8 == 0
def ab_c(self): vsc.solve_order(self.a, self.b) with vsc.if_then(self.a == 0): self.b == 4 with vsc.else_then: self.b != 4
def addr_translation_c(self): with vsc.if_then( (self.init_privil_mode != privileged_mode_t.MACHINE_MODE) & (self.SATP_MODE != satp_mode_t.BARE)): self.virtual_addr_translation_on == 1 with vsc.else_then(): self.virtual_addr_translation_on == 0
def b_extension_c(self): if riscv_instr_group_t.RV32B in rcs.supported_isa: with vsc.if_then(self.exception in [ illegal_instr_type_e.kIllegalFunc3, illegal_instr_type_e.kIllegalFunc7 ]): self.opcode.inside(vsc.rangelist([51, 19, 59]))
def mtvec_c(self): self.mtvec_mode.inside(vsc.rangelist(self.supported_interrupt_mode)) with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT): vsc.soft(self.tvec_alignment == 2) with vsc.else_then(): # Setting MODE = Vectored may impose an additional alignmentconstraint on BASE, # requiring up to 4×XLEN-byte alignment vsc.soft(self.tvec_alignment == self.tvec_ceil)
def ab_c(self): self.a == 1 with vsc.if_then(self.a == 1): self.b == 1 with vsc.else_then(): self.b == 2
def sp_tp_c(self): with vsc.if_then(self.fix_sp == 1): self.sp == riscv_reg_t.SP self.sp != self.tp self.sp.not_inside( vsc.rangelist(riscv_reg_t.GP, riscv_reg_t.RA, riscv_reg_t.ZERO)) self.tp.not_inside( vsc.rangelist(riscv_reg_t.GP, riscv_reg_t.RA, riscv_reg_t.ZERO))
def addr_c(self): vsc.solve_order(self.data_page_id, self.max_load_store_offset) vsc.solve_order(self.max_load_store_offset, self.base) self.data_page_id < self.max_data_page_id with vsc.foreach(self.data_page, idx = True) as i: with vsc.if_then(i == self.data_page_id): self.max_load_store_offset == self.data_page[i].size_in_bytes self.base in vsc.rangelist(vsc.rng(0, self.max_load_store_offset - 1))
def ab_c(self): vsc.solve_order(self.b, self.c) vsc.solve_order(self.a, self.b) self.b < 30 self.a < 20 with vsc.if_then(self.a == 0): self.b < 10
def enum_inter_class(self): # Does not work self.c1[0].a[0].enum_test == level_e.level_2 with vsc.if_then(self.c1[0].a[0].enum_test == level_e.level_0): self.c2[0].x[0].value == 1 with vsc.else_if(self.c1[0].a[0].enum_test == level_e.level_1): self.c2[0].x[0].value == 2 with vsc.else_then: self.c2[0].x[0].value == 3
def post_randomize(self): last_level = 0 last_level = self.stack_level[self.program_cnt - 1] for i in range(len(self.program_h)): self.program_h[i].program_id = i self.program_h[i].call_stack_level = self.stack_level[i] # Top-down generate the entire call stack. # A program can only call the programs in the next level. for i in range(last_level): program_list = [] next_program_list = [] sub_program_id_pool = vsc.randlist_t() sub_program_cnt = [] idx = 0 for j in range(self.program_cnt): if self.stack_level[j] == i: program_list.append(j) if self.stack_level[j] == i + 1: next_program_list.append(j) # Randmly duplicate some sub programs in the pool to create a case that # one sub program is called by multiple caller. Also it's possible to call # the same sub program in one program multiple times. total_sub_program_cnt = random.randrange( len(next_program_list), len(next_program_list) + 1) sub_program_id_pool = [0] * total_sub_program_cnt for i in range(len(sub_program_id_pool)): with sub_program_id_pool[i].randomize_with(): with vsc.if_then(sub_program_id_pool[i]): sub_program_id_pool[i] == next_program_list[i] with vsc.else_then(): sub_program_id_pool[i].inside( vsc.rangelist(next_program_list)) random.shuffle(sub_program_id_pool) sub_program_cnt = [0] * len(program_list) logging.info( "{} programs @Lv{}-> {} programs at next level".format( len(program_list), i, len(sub_program_id_pool))) # Distribute the programs of the next level among the programs of current level # Make sure all program has a caller so that no program is obsolete. for j in range(len(sub_program_id_pool)): caller_id = random.randrange(0, len(sub_program_cnt) - 1) sub_program_cnt[caller_id] += 1 for j in range(len(program_list)): id = program_list[j] self.program_h[id].sub_program_id = [0] * sub_program_cnt[j] logging.info( "{} sub programs are assigned to program[{}]".format( sub_program_cnt[j], id)) for k in range(len(self.program_h[id].sub_program_id)): self.program_h[id].sub_program_id[k] = sub_program_id_pool[ idx] idx += 1
def no_hint_illegal_instr_c(self): with vsc.if_then( self.instr_name.inside( vsc.rangelist( riscv_instr_name_t.C_ADDI, riscv_instr_name_t.C_ADDIW, riscv_instr_name_t.C_LI, riscv_instr_name_t.C_LUI, riscv_instr_name_t.C_SLLI, riscv_instr_name_t.C_SLLI64, riscv_instr_name_t.C_LQSP, riscv_instr_name_t.C_LDSP, riscv_instr_name_t.C_MV, riscv_instr_name_t.C_ADD, riscv_instr_name_t.C_LWSP))): self.rd != riscv_reg_t.ZERO with vsc.if_then(self.instr_name == riscv_instr_name_t.C_JR): self.rs1 != riscv_reg_t.ZERO with vsc.if_then( self.instr_name.inside( vsc.rangelist(riscv_instr_name_t.C_ADD, riscv_instr_name_t.C_MV))): self.rs2 != riscv_reg_t.ZERO with vsc.if_then(self.instr_name == riscv_instr_name_t.C_LUI): self.rd != riscv_reg_t.SP
def program_stack_level_c(self): # The stack level is assigned in ascending order to avoid call loop self.stack_level.size == self.program_cnt self.stack_level[0] == 0 with vsc.foreach(self.stack_level, idx=True) as i: with vsc.if_then(i > 0): self.stack_level[i] in vsc.rangelist( vsc.rng(1, self.program_cnt - 1)) self.stack_level[i] >= self.stack_level[i - 1] self.stack_level[i] <= self.stack_level[i - 1] + 1 self.stack_level[i] <= self.max_stack_level