def f(n): if n.nodetype == ast.Node.BITVECVAR and n.name in port_names: assert n.width == 8 n_p = ast.BitVecVar(n.name + 'INREG', n.width) return n_p else: return n
def f(n): if n.nodetype == ast.Node.READMEM: if not n.mem.isMemVar(): err_msg = 'Reading from modified memories not supported yet.' raise NotImplementedError, err_msg s = subs.getSub(param, n.mem, n.addr) if not s: name = 'RD_%s_%d' % (n.mem.name, subs.count(param, n.mem)) s = ast.BitVecVar(name, n.mem.dwidth) subs.addSub(param, n.mem, n.addr, s) return s else: return n
def rewriteAST(name, n): if 'width' in n.__dict__: inp = ast.BitVecVar(name, n.width) if inp == n: return n else: S = z3.Solver() y = z3.Bool('y') S.add(y == z3.Distinct(inp.toZ3(), n.toZ3())) if S.check(y) == z3.unsat: inp.clearCache() return inp else: n.clearCache() return n else: return n
def f(n): if n.nodetype == ast.Node.APPLY: width = n.width nchunks = width // 64 chunksizes = [64] * nchunks assert sum(chunksizes) <= width if (nchunks * 64) < width: chunksizes.append(width % 64) assert sum(chunksizes) == width assert 0 not in chunksizes these_inputs = [] for cs in chunksizes: name = 'input_%s_%d' % (n.fun.name, len(inputs)) var = ast.BitVecVar(name, cs) inp = (var, name, (cs - 1, 0)) inputs.append(inp) these_inputs.append(var) return ast.Concat(*these_inputs) else: return n
def getExpr(self, cnst, mem, sub, this_opcode=None, vctx=None): exprs = [] all_same = False for p, m, a, s in self.subs: if mem == m and sub == s: exprs.append((p, a)) if p == -1: all_same = True assert len(exprs) >= 1 if all_same: assert len(exprs) == 1 if this_opcode and not all_same: assert vctx != None abstr_addr_name = sub.name + '_ABSTR_ADDR' vctx.cinputs.append((abstr_addr_name, (mem.awidth - 1, 0))) abstr_addr = ast.BitVecVar(abstr_addr_name, mem.awidth) vctx.objects[abstr_addr] = abstr_addr_name addr = None for p, a in exprs: if p == this_opcode: addr = a break if addr: return ast.If(ast.Equal(cnst, ast.BitVecVal(p, cnst.width)), addr, abstr_addr) else: return abstr_addr def createIf(i): [p, a] = exprs[i] if i == len(exprs) - 1: return a else: return ast.If(ast.Equal(cnst, ast.BitVecVal(p, mem.awidth)), a, createIf(i + 1)) return createIf(0)
def createInputs(syn): xram = syn.addInput(ast.MemVar('xram', 16, 8)) op = syn.addInput(ast.BitVecVar('op', 4)) addrin = syn.addInput(ast.BitVecVar('addrin', 16)) datain = syn.addInput(ast.BitVecVar('datain', 8)) aes_state = syn.addInput(ast.BitVecVar('aes_state', 8)) aes_addr = syn.addInput(ast.BitVecVar('aes_addr', 16)) aes_len = syn.addInput(ast.BitVecVar('aes_len', 16)) aes_ctr = syn.addInput(ast.BitVecVar('aes_ctr', 128)) aes_key0 = syn.addInput(ast.BitVecVar('aes_key0', 128)) aes_key1 = syn.addInput(ast.BitVecVar('aes_key1', 128)) aes_bytes_processed = syn.addInput(ast.BitVecVar('aes_bytes_processed', 16)) aes_read_data = syn.addInput(ast.BitVecVar('aes_read_data', 128)) aes_enc_data = syn.addInput(ast.BitVecVar('aes_enc_data', 128)) # There is a minor bug here - the aes_func should be from bv384 -> bv128 # I forgot to include the key in the input. But it doesn't matter that much # right now because we don't verify the AES output. aes_func = syn.addInput(ast.FuncVar('aes_func', 256, 128)) sha_state = syn.addInput(ast.BitVecVar('sha_state', 8)) sha_rdaddr = syn.addInput(ast.BitVecVar('sha_rdaddr', 16)) sha_wraddr = syn.addInput(ast.BitVecVar('sha_wraddr', 16)) sha_len = syn.addInput(ast.BitVecVar('sha_len', 16)) sha_bytes_processed = syn.addInput(ast.BitVecVar('sha_bytes_processed', 16)) sha_read_data = syn.addInput(ast.BitVecVar('sha_read_data', 512)) sha_digest = syn.addInput(ast.BitVecVar('sha_digest', 160)) sha_func = syn.addInput(ast.FuncVar('sha_func', 512 + 160, 160)) return XmemContext(xram=xram, op=op, addrin=addrin, datain=datain, aes_state=aes_state, aes_addr=aes_addr, aes_len=aes_len, aes_ctr=aes_ctr, aes_key0=aes_key0, aes_key1=aes_key1, aes_bytes_processed=aes_bytes_processed, aes_read_data=aes_read_data, aes_enc_data=aes_enc_data, aes_func=aes_func, sha_state=sha_state, sha_rdaddr=sha_rdaddr, sha_wraddr=sha_wraddr, sha_len=sha_len, sha_bytes_processed=sha_bytes_processed, sha_read_data=sha_read_data, sha_digest=sha_digest, sha_func=sha_func)
def main(argv): if len(argv) != 3: print 'Syntax error.' print 'Usage: %s <ast-dir> <output.v>' return 1 asts = readAllASTs(argv[1]) assert len(asts) == 0x10 vctx = VerilogContext() cnst = ast.Concat(ast.Extract(1, 0, ast.BitVecVar('sha_state', 8)), ast.Extract(1, 0, ast.BitVecVar('aes_state', 8))) vctx.setCnst(cnst) vctx.cinputs.append(('op', (3, 0))) vctx.cinputs.append(('addrin', (15, 0))) vctx.cinputs.append(('datain', (7, 0))) vctx.objects[ast.BitVecVar('op', 4)] = 'op' vctx.objects[ast.BitVecVar('addrin', 16)] = 'addrin' vctx.objects[ast.BitVecVar('datain', 8)] = 'datain' vctx.addInput(ast.BoolVar('WR_XRAM_EN'), None) vctx.addInput(ast.BitVecVar('WR_XRAM_ADDR', 16), (15, 0)) subs = ast2verilog.AddrSubs() asts_p = [] nondet_inputs = [] for opcode, astdict in enumerate(asts): astdict_p = [] acc_v = None for st, v in astdict.iteritems(): v_p1 = ast2verilog.stripMacros(v) v_p2 = rewriteComplexMemReads(v_p1) v_p3 = ast2verilog.replaceFunctions(v_p2, nondet_inputs) v_p4 = ast2verilog.rewriteMemReads(opcode, v_p3, subs) astdict_p.append((st, v_p4)) asts_p.append(astdict_p) for var, name, width in nondet_inputs: vctx.cinputs.append((name, width)) vctx.objects[var] = name ports = subs.getReadPorts() for m, s in ports: vctx.addComment("port: " + m.name + "->" + str(s)) vctx.createWire(s) vctx.cinputs.append((s, vctx.getWidth(s))) vctx.objects[s] = s.name for m, s in ports: addr_expr = subs.getExpr(cnst, m, s) addr_name = s.name + "_ADDR" vctx.addComment(addr_name + "=" + str(addr_expr)) vctx.addAssignment(addr_expr, vctx.getExpr(addr_expr), addr_name) vctx.outputs.append((addr_name, vctx.getWidth(addr_expr))) max_writes = 120 choice_vars = [] for i in xrange(120): name = 'nondet_memwrite_choice_%d' % i var = ast.BoolVar(name) vctx.cinputs.append((name, None)) vctx.objects[var] = name choice_vars.append(var) for opcode, astdict in enumerate(asts_p): assert len(astdict) == 18 memwrites = [] for st, v in astdict: # ignore the case where nothing changes. if v.isVar() and v.name == st: continue # some comments to show what is going on. vctx.addComment('') vctx.addComment('%s_%02x' % (st, opcode)) vctx.addComment('') if not v.isMem(): name = '%s_%02x' % (st, opcode) vctx.addAssignment(v, vctx.getExpr(v), name) vctx.addStateChange(st, opcode, name) else: vctx.getMemWriteAddrs(ast.BoolVal(1), st, v, memwrites) # mw = vctx.getMemWrite(st, v) # if mw != None: vctx.addMemWrite(st, opcode, mw) cond, addr = nondetChooseMemWrite(choice_vars, memwrites) vctx.addAssignment(cond, vctx.getExpr(cond), 'WR_XRAM_EN_%02x' % opcode) vctx.addStateChange('WR_XRAM_EN', opcode, 'WR_XRAM_EN_%02x' % opcode) vctx.addAssignment(addr, vctx.getExpr(addr), 'WR_XRAM_ADDR_%02x' % opcode) vctx.addStateChange('WR_XRAM_ADDR', opcode, 'WR_XRAM_ADDR_%02x' % opcode) vctx.inputs.append(('dataout', (7, 0))) vctx.addOutputs() # vctx.addMems() with open(argv[2], 'wt') as f: vctx.dump(f, 'xm8051_golden_model')
def forceRegsToZero(st, v): if st in zero_regs: return ast.BitVecVar(st, 8) return v
def gen_gm(astdir, cnstfile, opcode, outputfile): asts = readAllASTs(astdir) assert len(asts) == 0x100 vctx = VerilogContext() cnst = readCnst(cnstfile) subs = ast2verilog.AddrSubs() cnst_p = ast2verilog.rewriteMemReads(-1, cnst, subs) vctx.setCnst(cnst_p) this_opcode = opcode vctx.cinputs.append(('XRAM_DATA_IN', (7, 0))) vctx.objects[ast.BitVecVar('XRAM_DATA_IN', 8)] = 'XRAM_DATA_IN' vctx.addInput(ast.BitVecVar('XRAM_ADDR', 16), (15,0)) vctx.addInput(ast.BitVecVar('XRAM_DATA_OUT', 8), (7,0)) for i in xrange(4): pi = 'P%dIN' % i pireg = 'P%dINREG' % i vctx.cinputs.append((pi, (7,0))) vctx.always_stmts.append('%s <= %s;' % (pireg, pi)) asts_p = [] for opcode, astdict in enumerate(asts): astdict_p = [] acc_v = None for st, v in astdict.iteritems(): v_p1 = ast2verilog.stripMacros(v) v_p2 = ast2verilog.rewriteMemReads(opcode, v_p1, subs) v_p3 = forceRegsToZero(st, v_p2) v_p = rewritePortsAsInputs(opcode, st, v_p3) astdict_p.append((st, v_p)) if st == 'ACC': acc_v = v_p assert acc_v != None acc_p = ast.BVXor(ast.Extract(7, 7, acc_v), ast.BVXor(ast.Extract(6, 6, acc_v), ast.BVXor(ast.Extract(5, 5, acc_v), ast.BVXor(ast.Extract(4, 4, acc_v), ast.BVXor(ast.Extract(3, 3, acc_v), ast.BVXor(ast.Extract(2, 2, acc_v), ast.BVXor(ast.Extract(1, 1, acc_v), ast.Extract(0, 0, acc_v)))))))) for i in xrange(len(astdict_p)): st = astdict_p[i][0] v = astdict_p[i][1] if st == 'PSW': v_p = ast.Concat(ast.Extract(7, 1, v), acc_p) astdict_p[i] = (st, v_p) asts_p.append(astdict_p) ports = subs.getReadPorts() for m, s in ports: vctx.addComment("port: " + m.name + "->" + str(s)) vctx.createWire(s) if m.name == 'ROM': vctx.cinputs.append((s, vctx.getWidth(s))) vctx.objects[s] = s.name; for m, s in ports: addr_expr = subs.getExpr(cnst_p, m, s, this_opcode, vctx) addr_name = s.name + "_ADDR" vctx.addComment(addr_name + "=" + str(addr_expr)) vctx.addAssignment(addr_expr, vctx.getExpr(addr_expr), addr_name) if(m.name != 'ROM'): rd_expr = ast2verilog.resizeMem(ast.ReadMem(m, addr_expr), 'IRAM', 4) vctx.addAssignment(rd_expr, vctx.getExpr(rd_expr), s.name) else: vctx.outputs.append((addr_name, vctx.getWidth(addr_expr))) for opcode, astdict in enumerate(asts_p): assert len(astdict) == 25 for st, v in astdict: # ignore the case where nothing changes. if v.isVar() and v.name == st and v.isMem(): continue if st in zero_regs: continue # some comments to show what is going on. vctx.addComment('') vctx.addComment('%s_%02x' % (st, opcode)) vctx.addComment('') if v.isMem(): mw = vctx.getMemWrite(st, ast2verilog.resizeMem(v, 'IRAM', 4)) if mw != None: vctx.addMemWrite(st, opcode, mw) else: if opcode != this_opcode: continue name = '%s_%02x' % (st, opcode) vctx.addAssignment(v, vctx.getExpr(v), name) vctx.addStateChange(st, opcode, name) vctx.addOutputsSingleOp(this_opcode) vctx.addMems(this_opcode) vctx.outputs.append(('IRAM_full', (127,0))) vctx.statements.append('assign IRAM_full = {IRAM[15], IRAM[14], IRAM[13], IRAM[12], IRAM[11], IRAM[10], IRAM[9], IRAM[8], IRAM[7], IRAM[6], IRAM[5], IRAM[4], IRAM[3], IRAM[2], IRAM[1], IRAM[0]} ;') vctx.setRst('P0', 'ff') vctx.setRst('P1', 'ff') vctx.setRst('P2', 'ff') vctx.setRst('P3', 'ff') vctx.setRst('TCON', '0') vctx.setRst('SP', '7') addZeroRegs(vctx) addMissingInputs(vctx) vctx.init_mem_guard = 'OC8051_SIMULATION' with open(outputfile, 'wt') as f: vctx.dump(f, 'oc8051_golden_model')
def writeMem(self, mem, writes, this_opcode): wrports = WritePorts() if this_opcode: maxports = 0 for opcode, stmts in writes.iteritems(): if maxports < len(stmts): maxports = len(stmts) a_conds, a_addrs, a_datas = [], [], [] for i in xrange(maxports): ca_i = 'WR_COND_ABSTR_%s_%d' % (mem.name, i) aa_i = 'WR_ADDR_ABSTR_%s_%d' % (mem.name, i) da_i = 'WR_DATA_ABSTR_%s_%d' % (mem.name, i) cond_i = '(%s && !(%s))' % ( ca_i, self.getExpr( ast.Equal(self.cnst, ast.BitVecVal(this_opcode, self.cnst.width)))) a_conds.append(cond_i) a_addrs.append(aa_i) a_datas.append(da_i) self.cinputs.append((ca_i, None)) self.cinputs.append((aa_i, (mem.awidth - 1, 0))) self.cinputs.append((da_i, (mem.dwidth - 1, 0))) for opcode, stmts in writes.iteritems(): if this_opcode: for i, [c, m, a, d] in enumerate(stmts): assert m == mem if opcode == this_opcode: wrports.addWrite(i, c, a, d) else: for i, [c, m, a, d] in enumerate(stmts): assert m == mem wrports.addWrite(i, c, a, d) if this_opcode: for i in xrange(maxports): wrports.addWrite(i, a_conds[i], a_addrs[i], a_datas[i]) # print mem.name, 'num ports:', wrports.numPorts for i in xrange(wrports.numPorts): addrport = 'WR_ADDR_%d_%s' % (i, mem.name) dataport = 'WR_DATA_%d_%s' % (i, mem.name) condport = 'WR_COND_%d_%s' % (i, mem.name) addr = ast.BitVecVar(addrport, mem.awidth) self.createWire(addr) data = ast.BitVecVar(dataport, mem.dwidth) self.createWire(data) cond = ast.BoolVar(condport) self.createWire(cond) self.addAssignment(addr, wrports.addrExpr(i), addr.name) self.addAssignment(data, wrports.dataExpr(i), data.name) self.addAssignment(cond, wrports.condExpr(i), cond.name) self.always_stmts.append('if (%s) %s[%s] <= %s;' % (condport, mem.name, addrport, dataport))
def eval(op, inputs, outputs): a = inputs['a'] b = inputs['b'] c = inputs['c'] if op == 0: outputs['r'] = ((a + b) & 0xFF) if c == 227 else 0 else: outputs['r'] = (a + op) & 0xFF syn = Synthesizer() a = syn.addInput(ast.BitVecVar('a', 8)) b = syn.addInput(ast.BitVecVar('b', 8)) c = syn.addInput(ast.BitVecVar('c', 8)) r_add = ast.If( ast.Equal(c, ast.BVInRange('c', ast.BitVecVal(220, 8), ast.BitVecVal(230, 8))), ast.Add(a, b), ast.BitVecVal(0, 8)) r_inc = ast.Add( a, ast.BVInRange('inc', ast.BitVecVal(1, 8), ast.BitVecVal(11, 8))) r = ast.Choice('r', None, [r_add, r_inc]) syn.addOutput('r', r, Synthesizer.BITVEC) syn.VERBOSITY = 2