def createmodel(): m = ila.Abstraction('alu') m.enable_parameterized_synthesis = 1 regs = [m.reg('r%d' % i, 8) for i in xrange(4)] opcode = m.inp('opcode', 7) rs_index = opcode[1:0] rt_index = opcode[3:2] rd_index = opcode[5:4] op = opcode[6:6] def sel(regs, idx): return ila.ite( idx == 0, regs[0], ila.ite(idx == 1, regs[1], ila.ite(idx == 2, regs[2], regs[3]))) rs = sel(regs, rs_index) rt = sel(regs, rt_index) res = ila.choice('op', rs + rt, rs - rt) for i in xrange(4): ri_next = ila.ite(rd_index == i, res, regs[i]) m.set_next('r%d' % i, ri_next) m.fetch_expr = opcode m.decode_exprs = [opcode == i for i in xrange(0, 128)] m.synthesize(alusim) for i, di in enumerate(m.decode_exprs): for reg in xrange(4): exp_i = m.get_next('r%d' % reg, i) si = ila.simplify(di, exp_i) if not m.areEqual(di, exp_i, si): print 'decode:', di print 'exp:', exp_i
def synToFile(m, filePath): if not os.path.exists(filePath): os.makedirs(filePath) sim = lambda s: RSA().simulate(s) for s in all_states: st = time.clock() m.synthesize(s, sim) dt = time.clock() - st print s + ' synthesized: %.2f' % dt fileName = filePath + '/' + s nxt = m.get_next(s) si = ila.simplify(m.bool(True), nxt) m.exportOne(si, fileName)
def get_cfg(uclid5, rom, pc, pc_next, inst_next, init_states, romconst, next_exprs): stack = init_states visited = set() state_map = {} state_edges = {} ret_set = set() state_to_nexts = {} while len(stack): top_pc, call_stack = stack.pop() # keep track of visited states. state = (top_pc, call_stack) if state in visited: continue else: visited.add(state) state_name = state_to_name(top_pc, call_stack) assert state_name not in state_map state_map[state_name] = (top_pc, call_stack) # set the current PC value. uclid5.setVar('PC', top_pc) # get current opcode. thisInst = uclid5.getExprValues(rom[pc]) thisInst1 = uclid5.getExprValues(rom[pc + 1]) thisInst2 = uclid5.getExprValues(rom[pc + 2]) assert len(thisInst) == 1 assert len(thisInst1) == 1 assert len(thisInst2) == 1 opcode = thisInst[0] opcode1, opcode2 = thisInst1[0], thisInst2[0] # if it is a call, we have to add it to the stack. if iscall(opcode): call_stack_new = tuple(list(call_stack) + [nextpc(top_pc, opcode)]) nextPCs = uclid5.getExprValues(pc_next) # if it is a return, don't symbolically execute, instead pop off the stack. elif isret(opcode): call_stack_new_list = list(call_stack) ret_pc = call_stack_new_list.pop() call_stack_new = tuple(call_stack_new_list) nextPCs = [ret_pc] ret_set.add(state_name) # else symbolic execution rules. else: call_stack_new = call_stack nextPCs = uclid5.getExprValues(pc_next) # add new states to be visited to the stack. next_states = [(n, call_stack_new) for n in nextPCs] stack += next_states # add edges to state graph. next_state_names = [ state_to_name(next_pc, call_stack_new) for (next_pc, call_stack_new) in next_states ] assert state_name not in state_edges state_edges[state_name] = next_state_names # now print out where we are. assert len(nextPCs) <= 16 next_string = ' '.join('%04X' % nextPC_i for nextPC_i in nextPCs) call_stack_string = ' '.join('%04X' % pc for pc in call_stack) simp_nexts = {} # TODO: Parallelize this loop, too slow on one core for s in next_exprs.keys(): simp_nexts[s] = ila.simplify( (rom[pc] == opcode) & (rom[pc + 1] == opcode1) & (rom[pc + 2] == opcode2) & (pc == top_pc), next_exprs[s]) state_to_nexts[state_name] = simp_nexts pc_next_simplified = ila.simplify( (rom[pc] == opcode) & (rom[pc + 1] == opcode1) & (rom[pc + 2] == opcode2) & (pc == top_pc), pc_next) print 'PC: %04X [%20s]; OP: %02X -> NEXT: %s; PC_NEXT_EXPR: %s' % ( top_pc, call_stack_string, opcode, next_string, str(pc_next_simplified)) return state_map, state_edges, ret_set, state_to_nexts
def model(num_regs, reg_size, paramsyn): reg_field_width = int(math.log(num_regs, 2)) assert (1 << reg_field_width) == num_regs # create the alu. alu = alu_sim(reg_field_width, reg_size) sys = ila.Abstraction("alu") sys.enable_parameterized_synthesis = paramsyn # state elements. rom = sys.mem('rom', alu.ROM_ADDR_WIDTH, alu.OPCODE_WIDTH) pc = sys.reg('pc', alu.ROM_ADDR_WIDTH) opcode = rom[pc] regs = [sys.reg('r%d' % i, alu.REG_SIZE) for i in xrange(alu.NUM_REGS)] # get the two sources. rs = ila.choice('rs', regs) rt = ila.choice('rt', regs) rs = [rs+rt, rs-rt, rs&rt, rs|rt, ~rs, -rs, ~rt, -rt] # set next. sys.set_next('pc', ila.choice('pc', pc+1, pc+2)) # set rom next. sys.set_next('rom', rom) regs_next = [] for i in xrange(alu.NUM_REGS): ri_next = ila.choice('result%d' % i, rs+[regs[i]]) sys.set_next('r%d' % i, ri_next) # set the fetch expressions. sys.fetch_expr = opcode # now set the decode expressions. sys.decode_exprs = [opcode == i for i in xrange(alu.NUM_OPCODES)] # synthesize pc first. sys.synthesize('pc', lambda s: alu.alusim(s)) pc_next = sys.get_next('pc') assert sys.areEqual(pc_next, pc+1) # now synthesize. st = time.clock() sys.synthesize(lambda s: alu.alusim(s)) et = time.clock() print 'time for synthesis: %.3f' % (et-st) regs_next = aluexpr(rom, pc, regs) for i in xrange(alu.NUM_REGS): rn1 = sys.get_next('r%d' % i) rn2 = regs_next[i] print '(a) r%d: %s' % (i, str(rn1)) print '(b) r%d: %s' % (i, str(rn2)) assert sys.areEqual(rn1, rn2) print '--> PC_NEXT:', sys.get_next('pc') #sys.add_assumption(opcode == 0x80) #print sys.syn_elem("r0", sys.get_next('r0'), alusim) # simplify PC. pc_next_p = ila.simplify(sys.bool(True), sys.get_next('pc')) sys.set_next('pc', pc_next_p) print '--> PC_NEXT:', sys.get_next('pc') expFile = "tmp/alu.txt" sys.exportAll(expFile); verilogFile = "tmp/alu.v" ila.setloglevel(3, "") ila.enablelog("VerilogExport") sys.generateVerilog(verilogFile) # now import into a new abstraction and check. sysp = ila.Abstraction("alu") sysp.importAll(expFile); romp = sysp.getmem('rom') pcp = sysp.getreg('pc') regsp = [sysp.getreg('r%d' % i) for i in xrange(alu.NUM_REGS)] regs_next = aluexpr(romp, pcp, regsp) for i in xrange(alu.NUM_REGS): rn1 = sysp.get_next('r%d' % i) rn2 = regs_next[i] assert sysp.areEqual(rn1, rn2)