def f(n): if n.nodetype == ast.Node.MEMVAR and n.name == name: return ast.MemVar(n.name, sz, n.dwidth) elif n.nodetype == ast.Node.READMEM and n.mem.name == name: return ast.ReadMem(n.mem, ast.Extract(sz - 1, 0, n.addr)) elif n.nodetype == ast.Node.WRITEMEM and n.mem.name == name: return ast.WriteMem(n.mem, ast.Extract(sz - 1, 0, n.addr), n.data) else: return n
def synthesize(output_state, fsm_state, log, output, verbosity, unsat_core): syn = Synthesizer() xmem = createInputs(syn) # common signals. mem_op_bits = ast.Extract(3, 2, xmem.op) rd_en = ast.Equal(mem_op_bits, ast.BitVecVal(1, 2)) wr_en = ast.Equal(mem_op_bits, ast.BitVecVal(2, 2)) # aes. in_aes_range, aes_dataout = modelAES(syn, rd_en, wr_en, xmem) # sha. in_sha_range, sha_dataout = modelSHA(syn, rd_en, wr_en, xmem) # model for the xram. xram_dataout = ast.If(rd_en, ast.ReadMem(xmem.xram, xmem.addrin), ast.BitVecVal(0, 8)) xram = ast.If(ast.And(wr_en, ast.Not(in_aes_range), ast.Not(in_sha_range)), ast.WriteMem(xmem.xram, xmem.addrin, xmem.datain), xmem.xram) # combine everything. xmem.dataout = ast.If(in_aes_range, aes_dataout, ast.If(in_sha_range, sha_dataout, xram_dataout)) xmem.xram = xram syn.addOutput('dataout', xmem.dataout, Synthesizer.BITVEC) syn.addOutput('xram', xmem.xram, Synthesizer.MEM) syn.addOutput('aes_state', xmem.aes_state_next, Synthesizer.BITVEC) syn.addOutput('aes_addr', xmem.aes_addr_next, Synthesizer.BITVEC) syn.addOutput('aes_len', xmem.aes_len_next, Synthesizer.BITVEC) syn.addOutput('aes_ctr', xmem.aes_ctr_next, Synthesizer.BITVEC) syn.addOutput('aes_key0', xmem.aes_key0_next, Synthesizer.BITVEC) syn.addOutput('aes_key1', xmem.aes_key1_next, Synthesizer.BITVEC) syn.addOutput('aes_bytes_processed', xmem.aes_bytes_processed_next, Synthesizer.BITVEC) syn.addOutput('aes_read_data', xmem.aes_read_data_next, Synthesizer.BITVEC) syn.addOutput('aes_enc_data', xmem.aes_enc_data_next, Synthesizer.BITVEC) syn.addOutput('sha_state', xmem.sha_state_next, Synthesizer.BITVEC) syn.addOutput('sha_rdaddr', xmem.sha_rdaddr_next, Synthesizer.BITVEC) syn.addOutput('sha_wraddr', xmem.sha_wraddr_next, Synthesizer.BITVEC) syn.addOutput('sha_len', xmem.sha_len_next, Synthesizer.BITVEC) syn.addOutput('sha_bytes_processed', xmem.sha_bytes_processed_next, Synthesizer.BITVEC) syn.addOutput('sha_read_data', xmem.sha_read_data_next, Synthesizer.BITVEC) syn.addOutput('sha_digest', xmem.sha_digest_next, Synthesizer.BITVEC) if log == 'STDOUT': syn.logfile = sys.stdout elif log: syn.logfile = open(log, 'wt') syn.VERBOSITY = verbosity syn.unsat_core = unsat_core # syn.unsat_core = True aes_state = fsm_state & 0x3 sha_state = (fsm_state & 0xc) >> 2 param = ast.And(ast.Equal(xmem.aes_state, ast.BitVecVal(aes_state, 8)), ast.Equal(xmem.sha_state, ast.BitVecVal(sha_state, 8))) [a] = syn.synthesize([output_state], [param], evalxmm) if output: with open(output, 'wb') as f: pk = Pickler(f, -1) pk.dump(fsm_state) pk.dump(output_state) pk.dump(a) else: print '%s' % output_state print str(a) + '\n'
def modelSHA(syn, rd_en, wr_en, xmem): # addresses for the regs. sha_start_addr = ast.BVInRange('sha_start_addr', ast.BitVecVal(0xfe00, 16), ast.BitVecVal(0xfe0f, 16)) sha_state_addr = ast.BVInRange('sha_state_addr', ast.BitVecVal(0xfe00, 16), ast.BitVecVal(0xfe0f, 16)) sha_rdaddr_addr = ast.BVInRange('sha_rdaddr_addr', ast.BitVecVal(0xfe00, 16), ast.BitVecVal(0xfe0f, 16)) sha_wraddr_addr = ast.BVInRange('sha_wraddr_addr', ast.BitVecVal(0xfe00, 16), ast.BitVecVal(0xfe0f, 16)) sha_len_addr = ast.BVInRange('sha_len_addr', ast.BitVecVal(0xfe00, 16), ast.BitVecVal(0xfe0f, 16)) in_sha_range = ast.And(ast.ULE(ast.BitVecVal(0xfe00, 16), xmem.addrin), ast.ULT(xmem.addrin, ast.BitVecVal(0xfe10, 16))) syn.addConstraint( ast.Equal(ast.Extract(7, 2, xmem.sha_state), ast.BitVecVal(0, 6))) # state values. SHA_IDLE = ast.BitVecVal(0, 8) SHA_READ = ast.BitVecVal(1, 8) SHA_OP = ast.BitVecVal(2, 8) SHA_WRITE = ast.BitVecVal(3, 8) # are we idle sha_state_idle = ast.Equal(xmem.sha_state, SHA_IDLE) sha_state_read = ast.Equal(xmem.sha_state, SHA_READ) sha_state_op = ast.Equal(xmem.sha_state, SHA_OP) sha_state_write = ast.Equal(xmem.sha_state, SHA_WRITE) # should we take a step this cycle? sha_step = ast.Equal(ast.Extract(1, 1, xmem.op), ast.BitVecVal(1, 1)) # write enable sha_wr_en = ast.And(wr_en, sha_state_idle) # reg selects sha_start_sel = ast.Equal(sha_start_addr, xmem.addrin) sha_state_sel = ast.Equal(sha_state_addr, xmem.addrin) sha_rdaddr_sel = ast.Equal(sha_rdaddr_addr, lsb0(xmem.addrin)) sha_wraddr_sel = ast.Equal(sha_wraddr_addr, lsb0(xmem.addrin)) sha_len_sel = ast.Equal(sha_len_addr, lsb0(xmem.addrin)) # read enables sha_state_sel_rd = ast.And(sha_state_sel, rd_en) sha_rdaddr_sel_rd = ast.And(sha_rdaddr_sel, rd_en) sha_wraddr_sel_rd = ast.And(sha_wraddr_sel, rd_en) sha_len_sel_rd = ast.And(sha_len_sel, rd_en) # write enables sha_rdaddr_sel_wr = ast.And(sha_rdaddr_sel, wr_en) sha_wraddr_sel_wr = ast.And(sha_wraddr_sel, wr_en) sha_len_sel_wr = ast.And(sha_len_sel, wr_en) # output for read sha_state_out = xmem.sha_state sha_rdaddr_out = rd2byte(xmem.addrin, xmem.sha_rdaddr) sha_wraddr_out = rd2byte(xmem.addrin, xmem.sha_wraddr) sha_len_out = rd2byte(xmem.addrin, xmem.sha_len) sha_dataout = ast.If( sha_state_sel_rd, sha_state_out, ast.If( sha_rdaddr_sel_rd, sha_rdaddr_out, ast.If(sha_wraddr_sel_rd, sha_wraddr_out, ast.If(sha_len_sel_rd, sha_len_out, ast.BitVecVal(0, 8))))) # write ops xmem.sha_rdaddr_next = ast.Choice('sha_next', xmem.sha_state, [ ast.If(sha_rdaddr_sel_wr, wr2byte(xmem.addrin, xmem.sha_rdaddr, xmem.datain), xmem.sha_rdaddr), xmem.sha_rdaddr ]) xmem.sha_wraddr_next = ast.Choice('sha_next', xmem.sha_state, [ ast.If(sha_wraddr_sel_wr, wr2byte(xmem.addrin, xmem.sha_wraddr, xmem.datain), xmem.sha_wraddr), xmem.sha_wraddr ]) xmem.sha_len_next = ast.Choice('sha_next', xmem.sha_state, [ ast.If(sha_len_sel_wr, wr2byte(xmem.addrin, xmem.sha_len, xmem.datain), xmem.sha_len), xmem.sha_len ]) sha_start_next = ast.And( ast.Equal(ast.Extract(0, 0, xmem.datain), ast.BitVecVal(1, 1)), sha_wr_en, sha_start_sel) # bytes processed sha_bytes_processed_next_1 = ast.If(sha_start_next, ast.BitVecVal(0, 16), xmem.sha_bytes_processed) sha_bytes_processed_next_2 = ast.If( sha_step, ast.Add(xmem.sha_bytes_processed, ast.BitVecVal(64, 16)), xmem.sha_bytes_processed) xmem.sha_bytes_processed_next = ast.Choice( 'sha_bytes_processed_next', xmem.sha_state, [ sha_bytes_processed_next_1, sha_bytes_processed_next_2, xmem.sha_bytes_processed ]) # data read. sha_read_array = [] for i in xrange(64): sha_read_array.append( ast.ReadMem( xmem.xram, ast.Add( xmem.sha_rdaddr, ast.Add(xmem.sha_bytes_processed, ast.BitVecVal(i, 16))))) sha_read_array = sha_read_array[::-1] sha_read_data_next_1 = ast.If(sha_step, ast.Concat(*sha_read_array), xmem.sha_read_data) xmem.sha_read_data_next = ast.Choice( 'sha_read_data_next', xmem.sha_state, [sha_read_data_next_1, xmem.sha_read_data]) # hash data. sha_func_inp = ast.Concat(xmem.sha_read_data, xmem.sha_digest) sha_func_out = ast.Apply(xmem.sha_func, sha_func_inp) sha_digest_1 = ast.If(sha_start_next, ast.BitVecVal(0, 160), xmem.sha_digest) sha_digest_2 = ast.If(sha_step, sha_func_out, xmem.sha_digest) xmem.sha_digest_next = ast.If( sha_state_read, sha_digest_1, ast.If(sha_state_op, sha_digest_2, xmem.sha_digest)) # write data sha_write_xram = xmem.xram for i in xrange(20): sha_write_xram = ast.WriteMem( sha_write_xram, ast.Add(xmem.sha_wraddr, ast.Add(xmem.sha_bytes_processed, ast.BitVecVal(i, 16))), ast.Extract(i * 8 + 7, i * 8, xmem.sha_digest)) xram_next = ast.If(sha_step, sha_write_xram, xmem.xram) xmem.xram = ast.Choice('xram_next', xmem.sha_state, [xram_next, xmem.xram]) sha_state_next_1 = ast.If(sha_start_next, SHA_READ, SHA_IDLE) sha_state_next_2 = ast.If(sha_step, SHA_OP, SHA_READ) sha_state_next_3 = ast.If( sha_step, ast.If(ast.ULT(xmem.sha_bytes_processed_next, xmem.sha_len), SHA_READ, SHA_WRITE), SHA_OP) sha_state_next_4 = ast.If(sha_step, SHA_IDLE, SHA_WRITE) xmem.sha_state_next = ast.Choice('sha_state_next', xmem.sha_state, [ sha_state_next_1, sha_state_next_2, sha_state_next_3, sha_state_next_4 ]) return in_sha_range, sha_dataout
def modelAES(syn, rd_en, wr_en, xmem): # addresses for the regs aes_start_addr = ast.BVInRange('aes_start_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_state_addr = ast.BVInRange('aes_state_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_opaddr_addr = ast.BVInRange('aes_opaddr_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_len_addr = ast.BVInRange('aes_len_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_ctr_addr = ast.BVInRange('aes_ctr_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_key0_addr = ast.BVInRange('aes_key0_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) aes_key1_addr = ast.BVInRange('aes_key1_addr', ast.BitVecVal(0xff00, 16), ast.BitVecVal(0xff39, 16)) in_aes_range = ast.And(ast.ULE(ast.BitVecVal(0xff00, 16), xmem.addrin), ast.ULT(xmem.addrin, ast.BitVecVal(0xff40, 16))) # since we're using uninterpreted functions; the synthesis needs help in distinguishing # between the key and counter registers. syn.addConstraint(ast.ULT(aes_ctr_addr, aes_key0_addr)) syn.addConstraint(ast.ULT(aes_key0_addr, aes_key1_addr)) syn.addConstraint( ast.Equal(ast.Extract(7, 2, xmem.aes_state), ast.BitVecVal(0, 6))) AES_IDLE = ast.BitVecVal(0, 8) AES_READ = ast.BitVecVal(1, 8) AES_OP = ast.BitVecVal(2, 8) AES_WRITE = ast.BitVecVal(3, 8) aes_state_idle = ast.Equal(xmem.aes_state, AES_IDLE) # should we take a step this cycle? aes_step = ast.Equal(ast.Extract(0, 0, xmem.op), ast.BitVecVal(1, 1)) # should we write to a register or just ignore the write? aes_wr_en = ast.And(wr_en, aes_state_idle) # what register is selected for reading/writing? aes_start_sel = ast.Equal(aes_start_addr, xmem.addrin) aes_state_sel = ast.Equal(aes_state_addr, xmem.addrin) aes_opaddr_sel = ast.Equal(aes_opaddr_addr, lsb0(xmem.addrin)) aes_len_sel = ast.Equal(aes_len_addr, lsb0(xmem.addrin)) aes_ctr_sel = ast.Equal(aes_ctr_addr, lsn0(xmem.addrin)) aes_key0_sel = ast.Equal(aes_key0_addr, lsn0(xmem.addrin)) aes_key1_sel = ast.Equal(aes_key1_addr, lsn0(xmem.addrin)) # what register is being read? aes_state_sel_rd = ast.And(aes_state_sel, rd_en) aes_opaddr_sel_rd = ast.And(aes_opaddr_sel, rd_en) aes_len_sel_rd = ast.And(aes_len_sel, rd_en) aes_ctr_sel_rd = ast.And(aes_ctr_sel, rd_en) aes_key0_sel_rd = ast.And(aes_key0_sel, rd_en) aes_key1_sel_rd = ast.And(aes_key1_sel, rd_en) # what register is beig written? aes_state_sel_wr = ast.And(aes_state_sel, aes_wr_en) aes_opaddr_sel_wr = ast.And(aes_opaddr_sel, aes_wr_en) aes_len_sel_wr = ast.And(aes_len_sel, aes_wr_en) aes_ctr_sel_wr = ast.And(aes_ctr_sel, aes_wr_en) aes_key0_sel_wr = ast.And(aes_key0_sel, aes_wr_en) aes_key1_sel_wr = ast.And(aes_key1_sel, aes_wr_en) # output data for a read. aes_state_out = xmem.aes_state aes_opaddr_out = rd2byte(xmem.addrin, xmem.aes_addr) aes_len_out = rd2byte(xmem.addrin, xmem.aes_len) aes_ctr_out = rd16byte(xmem.addrin, xmem.aes_ctr) aes_key0_out = rd16byte(xmem.addrin, xmem.aes_key0) aes_key1_out = rd16byte(xmem.addrin, xmem.aes_key1) aes_dataout = ast.If( aes_state_sel_rd, aes_state_out, ast.If( aes_opaddr_sel_rd, aes_opaddr_out, ast.If( aes_len_sel_rd, aes_len_out, ast.If( aes_ctr_sel_rd, aes_ctr_out, ast.If( aes_key0_sel_rd, aes_key0_out, ast.If(aes_key1_sel_rd, aes_key1_out, ast.BitVecVal(0, 8))))))) # register update for a write xmem.aes_addr_next = ast.Choice('aes_next', xmem.aes_state, [ ast.If(aes_opaddr_sel_wr, wr2byte(xmem.addrin, xmem.aes_addr, xmem.datain), xmem.aes_addr), xmem.aes_addr ]) xmem.aes_len_next = ast.Choice('aes_next', xmem.aes_state, [ ast.If(aes_len_sel_wr, wr2byte(xmem.addrin, xmem.aes_len, xmem.datain), xmem.aes_len), xmem.aes_len ]) xmem.aes_ctr_next = ast.Choice('aes_next', xmem.aes_state, [ ast.If(aes_ctr_sel_wr, wr16byte(xmem.addrin, xmem.aes_ctr, xmem.datain), xmem.aes_ctr), xmem.aes_ctr ]) xmem.aes_key0_next = ast.Choice('aes_next', xmem.aes_state, [ ast.If(aes_key0_sel_wr, wr16byte(xmem.addrin, xmem.aes_key0, xmem.datain), xmem.aes_key0), xmem.aes_key0 ]) xmem.aes_key1_next = ast.Choice('aes_next', xmem.aes_state, [ ast.If(aes_key1_sel_wr, wr16byte(xmem.addrin, xmem.aes_key1, xmem.datain), xmem.aes_key1), xmem.aes_key1 ]) # are we going to start the operation in the next cycle? aes_start_next = ast.And( ast.Equal(ast.Extract(0, 0, xmem.datain), ast.BitVecVal(1, 1)), aes_wr_en, aes_start_sel) # how many bytes have we eaten? aes_bytes_processed_next_1 = ast.If(aes_start_next, ast.BitVecVal(0, 16), xmem.aes_bytes_processed) aes_bytes_processed_next_2 = ast.If( aes_step, ast.Add(xmem.aes_bytes_processed, ast.BitVecVal(16, 16)), xmem.aes_bytes_processed) xmem.aes_bytes_processed_next = ast.Choice( 'aes_bytes_processed_next', xmem.aes_state, [ aes_bytes_processed_next_1, aes_bytes_processed_next_2, xmem.aes_bytes_processed ]) # read data to be processed. aes_read_data_array = [] for i in xrange(16): aes_read_data_array.append( ast.ReadMem( xmem.xram, ast.Add( xmem.aes_addr, ast.Add(xmem.aes_bytes_processed, ast.BitVecVal(i, 16))))) # reverse the damn thing because we want MSB first. aes_read_data_array = aes_read_data_array[::-1] aes_read_data_next_1 = ast.If(aes_step, ast.Concat(*aes_read_data_array), xmem.aes_read_data) xmem.aes_read_data_next = ast.Choice( 'aes_read_data_next', xmem.aes_state, [aes_read_data_next_1, xmem.aes_read_data]) # encrypt data. aes_func_inp = ast.Concat(xmem.aes_ctr, xmem.aes_read_data) aes_func_out = ast.Apply(xmem.aes_func, aes_func_inp) aes_enc_data_next_1 = ast.If(aes_step, aes_func_out, xmem.aes_enc_data) xmem.aes_enc_data_next = ast.Choice( 'aes_enc_data_next', xmem.aes_state, [aes_enc_data_next_1, xmem.aes_enc_data]) # write data aes_write_xram = xmem.xram for i in xrange(16): aes_write_xram = ast.WriteMem( aes_write_xram, ast.Add(xmem.aes_addr, ast.Add(xmem.aes_bytes_processed, ast.BitVecVal(i, 16))), ast.Extract(i * 8 + 7, i * 8, xmem.aes_enc_data)) xram_next = ast.If(aes_step, aes_write_xram, xmem.xram) xmem.xram = ast.Choice('xram_next', xmem.aes_state, [xram_next, xmem.xram]) # next state computation. aes_state_idle_next = ast.If(aes_start_next, AES_READ, AES_IDLE) aes_state_read_next = ast.If(aes_step, AES_OP, AES_READ) aes_state_op_next = ast.If(aes_step, AES_WRITE, AES_OP) aes_state_write_next = ast.If( aes_step, ast.If(ast.ULT(xmem.aes_bytes_processed_next, xmem.aes_len), AES_READ, AES_IDLE), AES_WRITE) xmem.aes_state_next = ast.Choice('aes_state_next', xmem.aes_state, [ aes_state_idle_next, aes_state_read_next, aes_state_op_next, aes_state_write_next ]) return in_aes_range, aes_dataout
def wr16byte(addr, reg, val): addr_ = ast.Extract(3, 0, addr) return ast.If( ast.Equal(addr_, ast.BitVecVal(0, 4)), ast.Concat(ast.Extract(127, 8, reg), val), ast.If( ast.Equal(addr_, ast.BitVecVal(1, 4)), ast.Concat(ast.Extract(127, 16, reg), val, ast.Extract(7, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(2, 4)), ast.Concat(ast.Extract(127, 24, reg), val, ast.Extract(15, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(3, 4)), ast.Concat(ast.Extract(127, 32, reg), val, ast.Extract(23, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(4, 4)), ast.Concat(ast.Extract(127, 40, reg), val, ast.Extract(31, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(5, 4)), ast.Concat(ast.Extract(127, 48, reg), val, ast.Extract(39, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(6, 4)), ast.Concat(ast.Extract(127, 56, reg), val, ast.Extract(47, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(7, 4)), ast.Concat(ast.Extract(127, 64, reg), val, ast.Extract(55, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(8, 4)), ast.Concat(ast.Extract(127, 72, reg), val, ast.Extract(63, 0, reg)), ast.If( ast.Equal(addr_, ast.BitVecVal(9, 4)), ast.Concat( ast.Extract(127, 80, reg), val, ast.Extract(71, 0, reg)), ast.If( ast.Equal( addr_, ast.BitVecVal(10, 4)), ast.Concat( ast.Extract(127, 88, reg), val, ast.Extract(79, 0, reg)), ast.If( ast.Equal( addr_, ast.BitVecVal(11, 4)), ast.Concat( ast.Extract( 127, 96, reg), val, ast.Extract( 87, 0, reg)), ast.If( ast.Equal( addr_, ast.BitVecVal( 12, 4)), ast.Concat( ast.Extract( 127, 104, reg), val, ast.Extract( 95, 0, reg)), ast.If( ast.Equal( addr_, ast.BitVecVal( 13, 4)), ast.Concat( ast.Extract( 127, 112, reg), val, ast.Extract( 103, 0, reg)), ast.If( ast.Equal( addr_, ast. BitVecVal( 14, 4)), ast.Concat( ast. Extract( 127, 120, reg), val, ast. Extract( 111, 0, reg)), ast.Concat( val, ast. Extract( 119, 0, reg)))) )))))))))))))
def rd16byte(addr, reg): addr_ = ast.Extract(3, 0, addr) return ast.If( ast.Equal(addr_, ast.BitVecVal(0, 4)), ast.Extract(7, 0, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(1, 4)), ast.Extract(15, 8, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(2, 4)), ast.Extract(23, 16, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(3, 4)), ast.Extract(31, 24, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(4, 4)), ast.Extract(39, 32, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(5, 4)), ast.Extract(47, 40, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(6, 4)), ast.Extract(55, 48, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(7, 4)), ast.Extract(63, 56, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(8, 4)), ast.Extract(71, 64, reg), ast.If( ast.Equal(addr_, ast.BitVecVal(9, 4)), ast.Extract(79, 72, reg), ast.If( ast.Equal( addr_, ast.BitVecVal(10, 4)), ast.Extract(87, 80, reg), ast.If( ast.Equal( addr_, ast.BitVecVal(11, 4)), ast.Extract(95, 88, reg), ast.If( ast.Equal( addr_, ast.BitVecVal( 12, 4)), ast.Extract( 103, 96, reg), ast.If( ast.Equal( addr_, ast.BitVecVal( 13, 4)), ast.Extract( 111, 104, reg), ast.If( ast.Equal( addr_, ast. BitVecVal( 14, 4)), ast.Extract( 119, 112, reg), ast.Extract( 127, 120, reg)))))))) ))))))))
def wr2byte(addr, reg, val): return ast.If(ast.Equal(ast.Extract(0, 0, addr), ast.BitVecVal(0, 1)), ast.Concat(ast.Extract(15, 8, reg), val), ast.Concat(val, ast.Extract(7, 0, reg)))
def rd2byte(addr, reg): return ast.If(ast.Equal(ast.Extract(0, 0, addr), ast.BitVecVal(0, 1)), ast.Extract(7, 0, reg), ast.Extract(15, 8, reg))
def lsn0(x): return ast.Concat(ast.Extract(15, 4, x), ast.BitVecVal(0, 4))
def lsb0(x): return ast.Concat(ast.Extract(15, 1, x), ast.BitVecVal(0, 1))
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 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')