def disassemble_field_j_imm(bits): imm = Bits(21, 0) imm[1:11] = bits[tinyrv2_field_slice_j_imm0] imm[11:12] = bits[tinyrv2_field_slice_j_imm1] imm[12:20] = bits[tinyrv2_field_slice_j_imm2] imm[20:21] = bits[tinyrv2_field_slice_j_imm3] return "0x{:0>6x}".format(imm.uint())
def gen_random_test(): # Generate some random data data = [] for i in xrange(128): data.append( random.randint(0,0xffffffff) ) # Generate random accesses to this data asm_code = [] for i in xrange(100): a = random.randint(0,127) b = random.randint(0,127) base = Bits( 32, 0x2000 + (4*b) ) offset = Bits( 16, (4*(a - b)) ) result = data[a] asm_code.append( gen_st_value_test( "sw", result, offset.int(), base.uint(), result ) ) # Generate some random data to initialize memory initial_data = [] for i in xrange(128): initial_data.append( random.randint(0,0xffffffff) ) # Add the data to the end of the assembly code asm_code.append( gen_word_data( initial_data ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(25): src = Bits(32, random.randint(0, 0xffffffff)) taken = (src.int() >= 0) asm_code.append(gen_br1_value_test("bgez", src.uint(), taken)) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(25): src = Bits( 32, random.randint(0,0xffffffff) ) taken = ( src.int() > 0 ) asm_code.append( gen_br1_value_test( "bgtz", src.uint(), taken ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): imm = Bits( 16, random.randint(0,0xffff) ) dest = zext(imm,32) << 16 asm_code.append( gen_imm_value_test( "lui", imm.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): # Generate some random data data = [] for i in xrange(128): data.append(random.randint(0, 0xFFFF)) # Generate random accesses to this data asm_code = [] for i in xrange(100): a = random.randint(0, 127) b = random.randint(0, 127) base = Bits(32, 0x2000 + (2 * b)) offset = Bits(16, (2 * (a - b))) result = sext(Bits(16, data[a]), 32) asm_code.append(gen_ld_value_test("lh", offset.int(), base.uint(), result.uint())) # Add the data to the end of the assembly code asm_code.append(gen_hword_data(data)) return asm_code
def gen_random_test(): # Generate some random data data = [] for i in xrange(128): data.append( random.randint(0,0xff) ) # Generate random accesses to this data asm_code = [] for i in xrange(100): a = random.randint(0,127) b = random.randint(0,127) base = Bits( 32, 0x2000 + b ) offset = Bits( 16, a - b ) result = data[a] asm_code.append( gen_ld_value_test( "lbu", offset.int(), base.uint(), result ) ) # Add the data to the end of the assembly code asm_code.append( gen_byte_data( data ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): imm = Bits(16, random.randint(0, 0xffff)) dest = zext(imm, 32) << 16 asm_code.append(gen_imm_value_test("lui", imm.uint(), dest.uint())) return asm_code
def load(self, mem_image): # Iterate over the sections sections = mem_image.get_sections() for section in sections: # For .mngr2proc sections, copy section into mngr2proc queue if section.name == ".mngr2proc": for i in xrange(0, len(section.data), 4): bits = struct.unpack_from("<I", buffer(section.data, i, 4))[0] self.mngr2proc_queue.append(Bits(32, bits)) # For .proc2mngr sections, copy section into proc2mngr_ref queue elif section.name == ".proc2mngr": for i in xrange(0, len(section.data), 4): bits = struct.unpack_from("<I", buffer(section.data, i, 4))[0] self.proc2mngr_ref_queue.append(Bits(32, bits)) # For all other sections, simply copy them into the memory else: start_addr = section.addr stop_addr = section.addr + len(section.data) self.mem[start_addr:stop_addr] = section.data
def gen_random_test(): asm_code = [] for i in xrange(100): src = Bits( 32, random.randint(0,0xffffffff) ) imm = Bits( 16, random.randint(0,0xffff) ) dest = src ^ zext(imm,32) asm_code.append( gen_rimm_value_test( "xori", src.uint(), imm.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(25): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 32, random.randint(0,0xffffffff) ) taken = ( src0 != src1 ) asm_code.append( gen_br2_value_test( "bne", src0.uint(), src1.uint(), taken ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 32, random.randint(0,0xffffffff) ) dest = src0 - src1 asm_code.append( gen_rr_value_test( "subu", src0.uint(), src1.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src = Bits( 32, random.randint(0,0xffffffff) ) imm = Bits( 16, random.randint(0,0xffff) ) dest = Bits( 32, src.int() < sext(imm,32).int() ) asm_code.append( gen_rimm_value_test( "slti", src.uint(), imm.uint(), dest.uint() ) ) return asm_code
def disassemble_field_b_imm(bits): imm = Bits(13, 0) imm[1:5] = bits[tinyrv2_field_slice_b_imm0] imm[5:11] = bits[tinyrv2_field_slice_b_imm1] imm[11:12] = bits[tinyrv2_field_slice_b_imm2] imm[12:13] = bits[tinyrv2_field_slice_b_imm3] return "0x{:0>4x}".format(imm.uint())
def gen_random_test(): # Generate some random data data = [] for i in xrange(128): data.append( random.randint(0,0xffff) ) # Generate random accesses to this data asm_code = [] for i in xrange(100): a = random.randint(0,127) b = random.randint(0,127) base = Bits( 32, 0x2000 + (2*b) ) offset = Bits( 16, (2*(a - b)) ) result = Bits( 32, data[a] ) asm_code.append( gen_st_random_test( "sh", "lhu", result.uint(), offset.int(), base.uint() ) ) # Generate some random data to initialize memory initial_data = [] for i in xrange(128): initial_data.append( random.randint(0,0xffff) ) # Add the data to the end of the assembly code asm_code.append( gen_hword_data( initial_data ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 32, random.randint(0,0xffffffff) ) dest = Bits( 32, src0 / src1 ) asm_code.append( gen_rr_value_test( "divu", src0.uint(), src1.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 32, random.randint(0,0xffffffff) ) # Python rounds to negative infinity even for negative values, so we # need to do something a little more complicated. This was inspired # from this post: # # http://stackoverflow.com/questions/19919387 # a = src0.int() b = src1.int() A = -a if (a < 0) else a B = -b if (b < 0) else b c = -(A // B) if (a < 0) ^ (b < 0) else (A // B) dest = Bits( 32, c ) asm_code.append( gen_rr_value_test( "div", src0.uint(), src1.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 5, random.randint(0,31) ) dest = Bits( 32, src0.int() >> src1.uint() ) asm_code.append( gen_rr_value_test( "srav", src0.uint(), src1.uint(), dest.uint() ) ) return asm_code
def j_imm(self): imm = Bits(21, 0) imm[1:11] = self.bits[tinyrv2_field_slice_j_imm0] imm[11:12] = self.bits[tinyrv2_field_slice_j_imm1] imm[12:20] = self.bits[tinyrv2_field_slice_j_imm2] imm[20:21] = self.bits[tinyrv2_field_slice_j_imm3] return imm
def b_imm(self): imm = Bits(13, 0) imm[1:5] = self.bits[tinyrv2_field_slice_b_imm0] imm[5:11] = self.bits[tinyrv2_field_slice_b_imm1] imm[11:12] = self.bits[tinyrv2_field_slice_b_imm2] imm[12:13] = self.bits[tinyrv2_field_slice_b_imm3] return imm
def assemble_inst(self, sym, pc, inst_str): # Extract instruction name from asm string (inst_name, sep, inst_str) = inst_str.partition(' ') # Use the instruction name to get the opcode match which we can # the use to initialize the instruction bits inst_bits = Bits(self.nbits, self.opcode_match_dict[inst_name]) # Split the remainder of the asm string into field strings. First # we translate non-whitespace deliminters into whitespace so that # we can use split. translation_table = maketrans(",()", " ") asm_field_strs = translate(inst_str, translation_table).split() # Retrieve the list of asm field functions for this instruction asm_field_funcs = self.asm_field_funcs_dict[inst_name] # Apply these asm field functions to the asm field strings for asm_field_str, asm_field_func in zip(asm_field_strs, asm_field_funcs): asm_field_func(inst_bits, sym, pc, asm_field_str) # Return the assembled instruction return inst_bits
def __setitem__(s, idx, value): if idx >= s.size: raise StopIteration addr = s.base_addr + 4 * idx s.mem[addr:addr + 4] = Bits(32, value)
def __init__(self, memory, mngr2proc_queue, proc2mngr_queue): self.PC = Bits(XLEN) self.R = RegisterFile() self.CSR = CsrRegisterFile(mngr2proc_queue, proc2mngr_queue) self.M = memory self.isa = rv64g.isa
def reset(self): self.isa.PC = Bits(32, 0x0000400) self.isa.status = 0 self.status = 0 self.num_total_inst = 0 self.num_inst = 0
def __getitem__( self, key ): if isinstance( key, slice ): start_addr = int(key.start) num_bytes = int(key.stop) - int(key.start) bits = Bits( 8*num_bytes ) for i in range(num_bytes): bits[i*8:i*8+8] = \ struct.unpack_from("<B",buffer(self.mem,start_addr+i,1))[0] return bits else: idx = int(key) return Bits( 8, struct.unpack_from("<B",buffer(self.mem,idx,1))[0] )
def gen_random_test(): # Generate some random data data = [] for i in xrange(128): data.append(random.randint(0, 0xffff)) # Generate random accesses to this data asm_code = [] for i in xrange(100): a = random.randint(0, 127) b = random.randint(0, 127) base = Bits(32, 0x2000 + (2 * b)) offset = Bits(16, (2 * (a - b))) result = sext(Bits(16, data[a]), 32) asm_code.append( gen_ld_value_test("lh", offset.int(), base.uint(), result.uint())) # Add the data to the end of the assembly code asm_code.append(gen_hword_data(data)) return asm_code
def __init__(self): self.regs = [Bits(32, 0) for i in xrange(32)] self.trace_str = "" self.trace_regs = False self.src0 = "" self.src1 = "" self.dest = ""
def __setitem__(self, idx, value): trunc_value = Bits(32, value, trunc=True) if self.trace_regs: self.dest = "X[{:2d}]={:0>8}".format(int(idx), trunc_value) if idx != 0: self.regs[idx] = trunc_value
def assemble_inst(self, sym, pc, inst_str): name, args = split_instr(inst_str) arg_list = simplify_args(args) result = Bits(self.ilen, self.encoding[name].opcode) for asm_field_str, field_name in zip(arg_list, self.encoding[name].simple_args): self.fields[field_name].translate(result, sym, pc, asm_field_str) return result
def disassemble(self, source): """ Computes the value by extracting and concatenating the individual parts from the source Returns: a Bits object of size width with the extracted value """ result = Bits(self.width, 0) for target_slice, field_slice in self.parts: if isinstance(target_slice, slice): result[field_slice] = source[target_slice] else: result[field_slice] = target_slice return result
def test_writing_bits(): mem = Bytes(8) # Write first four bytes mem[0:4] = Bits(32, 0x04030201) assert mem.mem == bytearray("\x01\x02\x03\x04\x00\x00\x00\x00") # Write second four bytes mem[4:8] = Bits(32, 0x04030201) assert mem.mem == bytearray("\x01\x02\x03\x04\x01\x02\x03\x04") # Write middle four bytes mem[2:6] = Bits(32, 0xefbeadde) assert mem.mem == bytearray("\x01\x02\xde\xad\xbe\xef\x03\x04") # Write two bytes mem[2:4] = Bits(16, 0xcdab) assert mem.mem == bytearray("\x01\x02\xab\xcd\xbe\xef\x03\x04") # Write one byte mem[3] = Bits(8, 0x69) assert mem.mem == bytearray("\x01\x02\xab\x69\xbe\xef\x03\x04") # Write entire memory mem[0:8] = Bits(64, 0xfecafecaefbeadde) assert mem.mem == bytearray("\xde\xad\xbe\xef\xca\xfe\xca\xfe")
def assemble(self, target, value): """ Effect: copies the value into the appropriate positions in the target """ value = Bits(self.width, value) for target_slice, field_slice in self.parts: if isinstance(target_slice, slice): target[target_slice] = value[field_slice] elif value[field_slice] != target_slice: raise ValueError( "Incorrect value in slice {} of field {}: found: {} expected: {}" .format(field_slice, value, value[field_slice], target_slice))
def gen_random_test(): asm_code = [] for i in xrange(100): src = Bits( 32, random.randint(0,0xffffffff) ) imm = Bits( 5, random.randint(0,31) ) dest = src >> imm asm_code.append( gen_rimm_value_test( "srl", src.uint(), imm.uint(), dest.uint() ) ) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits(32, random.randint(0, 0xFFFFFFFF)) src1 = Bits(32, random.randint(0, 0xFFFFFFFF)) dest = Bits(32, src0 * src1, trunc=True) asm_code.append(gen_rr_value_test("mul", src0.uint(), src1.uint(), dest.uint())) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits(32, random.randint(0, 0xffffffff)) src1 = Bits(5, random.randint(0, 31)) dest = src0 >> src1 asm_code.append( gen_rr_value_test("srlv", src0.uint(), src1.uint(), dest.uint())) return asm_code
def gen_random_test(): asm_code = [] for i in xrange(25): src0 = Bits(32, random.randint(0, 0xffffffff)) src1 = Bits(32, random.randint(0, 0xffffffff)) taken = (src0 != src1) asm_code.append( gen_br2_value_test("bne", src0.uint(), src1.uint(), taken)) return asm_code
def assemble_field_j_imm(bits, sym, pc, field_str): if sym.has_key(field_str): # notice that we encode the branch target address (a lable) relative # to current PC jtarg_byte_addr = sym[field_str] - pc else: jtarg_byte_addr = int(field_str, 0) imm = Bits(21, jtarg_byte_addr) bits[tinyrv2_field_slice_j_imm0] = imm[1:11] bits[tinyrv2_field_slice_j_imm1] = imm[11:12] bits[tinyrv2_field_slice_j_imm2] = imm[12:20] bits[tinyrv2_field_slice_j_imm3] = imm[20:21]
def test_basic(): data = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ] mem = Bytes(18*4) for i in range(18): mem[i*4:i*4+1] = Bits( 32, data[i] ) src0 = ListBytesProxy( mem, 0*4, 4 ) src1 = ListBytesProxy( mem, 4*4, 4 ) dest = ListBytesProxy( mem, 8*4, 4 ) vvadd( dest, src0, src1 ) data_ref = [ 0, 1, 2, 3, 4, 5, 6, 7, 4, 6, 8, 10, 12, 13, 14, 15, 16, 17 ] data_ref_bytes = Bytes(18*4) for i in range(18): data_ref_bytes[i*4:i*4+1] = Bits( 32, data_ref[i] ) assert mem == data_ref_bytes
def assemble_field_u_imm(bits, sym, pc, field_str): # Check to see if the immediate field derives from a label if field_str[0] == "%": label_addr = Bits(32, sym[field_str[4:-1]]) if field_str.startswith("%hi["): imm = label_addr[12:32] elif field_str.startswith("%lo["): imm = label_addr[0:12] else: assert False else: imm = int(field_str, 0) assert imm < (1 << 20) bits[tinyrv2_field_slice_u_imm] = imm
def gen_random_test(): asm_code = [] for i in xrange(100): src0 = Bits( 32, random.randint(0,0xffffffff) ) src1 = Bits( 32, random.randint(0,0xffffffff) ) a = src0.int() b = src1.int() A = -a if (a < 0) else a B = -b if (b < 0) else b c = -(A % B) if (a < 0) else (A % B) dest = Bits( 32, c ) asm_code.append( gen_rr_value_test( "rem", src0.uint(), src1.uint(), dest.uint() ) ) return asm_code
def __init__(self, memory, mngr2proc_queue, proc2mngr_queue, xcel_mvmult=None): self.M = memory self.mngr2proc_queue = mngr2proc_queue self.proc2mngr_queue = proc2mngr_queue self.R = PisaSemantics.RegisterFile() # Accelerator registers self.xregs = [Bits(32, 0) for i in xrange(32)] self.reset()
def handle_exception(s, instr, packet): s.CSR[CsrRegisters.mtval] = instr s.CSR[CsrRegisters.mcause] = packet.mcause s.CSR[CsrRegisters.mepc] = s.PC mtvec = s.CSR[CsrRegisters.mtvec] mode = mtvec[0:2] base = concat(mtvec[2:XLEN], Bits(2, 0)) if mode == MtvecMode.direct: target = base elif mode == MtvecMode.vectored: target = base + (packet.mcause << 2) else: # this is a bad state. mtvec is curcial to handling # exceptions, and there is no way to handle and exception # related to mtvec. # In a real processor, this would probably just halt or reset # the entire processor assert False s.PC = target
def assemble(asm_code): # If asm_code is a single string, then put it in a list to simplify the # rest of the logic. asm_code_list = asm_code if isinstance(asm_code, str): asm_code_list = [asm_code] # Create a single list of lines asm_list = [] for asm_seq in asm_code_list: asm_list.extend(asm_seq.splitlines()) # First pass to create symbol table. This is obviously very simplistic. # We can maybe make it more robust in the future. addr = 0x00000400 sym = {} for line in asm_list: line = line.partition("#")[0] line = line.strip() if line == "": continue if line.startswith(".offset"): (cmd, sep, addr_str) = line.partition(" ") addr = int(addr_str, 0) elif line.startswith(".data"): pass else: (label, sep, rest) = line.partition(":") if sep != "": sym[label.strip()] = addr else: addr += 4 # Second pass to assemble text section asm_list_idx = 0 addr = 0x00000400 text_bytes = bytearray() mngr2proc_bytes = bytearray() proc2mngr_bytes = bytearray() for line in asm_list: asm_list_idx += 1 line = line.partition("#")[0] line = line.strip() if line == "": continue if line.startswith(".offset"): (cmd, sep, addr_str) = line.partition(" ") addr = int(addr_str, 0) elif line.startswith(".data"): break else: if ":" not in line: inst_str = line # First see if we have either a < or a > if "<" in line: (temp, sep, value) = line.partition("<") bits = Bits(32, int(value, 0)) mngr2proc_bytes.extend(struct.pack("<I", bits)) inst_str = temp elif ">" in line: (temp, sep, value) = line.partition(">") bits = Bits(32, int(value, 0)) proc2mngr_bytes.extend(struct.pack("<I", bits)) inst_str = temp bits = assemble_inst(sym, addr, inst_str) text_bytes.extend(struct.pack("<I", bits.uint())) addr += 4 # Assemble data section data_bytes = bytearray() for line in asm_list[asm_list_idx:]: line = line.partition("#")[0] line = line.strip() if line == "": continue if line.startswith(".offset"): (cmd, sep, addr_str) = line.partition(" ") addr = int(addr_str, 0) elif line.startswith(".word"): (cmd, sep, value) = line.partition(" ") data_bytes.extend(struct.pack("<I", int(value, 0))) addr += 4 elif line.startswith(".hword"): (cmd, sep, value) = line.partition(" ") data_bytes.extend(struct.pack("<H", int(value, 0))) addr += 2 elif line.startswith(".byte"): (cmd, sep, value) = line.partition(" ") data_bytes.extend(struct.pack("<B", int(value, 0))) addr += 1 # Construct the corresponding section objects text_section = SparseMemoryImage.Section(".text", 0x0400, text_bytes) data_section = SparseMemoryImage.Section(".data", 0x2000, data_bytes) mngr2proc_section = SparseMemoryImage.Section(".mngr2proc", 0x3000, mngr2proc_bytes) proc2mngr_section = SparseMemoryImage.Section(".proc2mngr", 0x4000, proc2mngr_bytes) # Build a sparse memory image mem_image = SparseMemoryImage() mem_image.add_section(text_section) if len(data_section.data) > 0: mem_image.add_section(data_section) if len(mngr2proc_section.data) > 0: mem_image.add_section(mngr2proc_section) if len(proc2mngr_section.data) > 0: mem_image.add_section(proc2mngr_section) return mem_image