def createIla(): m = ila.Abstraction ('sha') m.enable_parameterized_synthesis = 0 # input ports cmd = m.inp ('cmd', 2) cmdaddr = m.inp ('cmdaddr', 16) cmddata = m.inp ('cmddata', 8) # arch states state = m.reg ('sha_state', 3) rd_addr = m.reg ('sha_rdaddr', 16) wr_addr = m.reg ('sha_wraddr', 16) oplen = m.reg ('sha_len', 16) rd_data = m.reg ('sha_rd_data', 512) hs_data = m.reg ('sha_hs_data', 160) xram = m.mem ('XRAM', 16, 8) sha = m.fun ('sha', 160, [512]) # fetch is just looking at the input command. m.fetch_expr = ila.concat ([state, cmd, cmdaddr, cmddata]) m.fetch_valid = (cmd == 1) | (cmd == 2) # write commands. def mb_reg_wr (name, reg): # multibyte reg write. reg_wr = ila.writechunk ('wr_' + name, reg, cmddata) reg_nxt = ila.choice ('nxt_' + name, [reg_wr, reg]) m.set_next (name, reg_nxt) mb_reg_wr ('sha_rdaddr', rd_addr) mb_reg_wr ('sha_wraddr', wr_addr) mb_reg_wr ('sha_len', oplen) # state (atomic) state_nxt = ila.choice ('state_nxt', [ m.const (0, 3), m.const (1, 3), m.const (2, 3), m.const (3, 3), m.const (4, 3), state]) m.set_next ('sha_state', state_nxt) # xram xram_w_sha_little = ila.storeblk (xram, wr_addr, hs_data) xram_w_sha_big = ila.storeblk_big (xram, wr_addr, hs_data) xram_cho = ila.choice ('xram_nxt', xram, xram_w_sha_little, xram_w_sha_big) xram_nxt = ila.ite ((state == 0) & (cmddata == 1), xram_cho, xram) m.set_next ('XRAM', xram_nxt) return m
def createAESILA(enable_ps): m = ila.Abstraction("aes") m.enable_parameterized_synthesis = enable_ps # I/O interface: this is where the commands come from. cmd = m.inp('cmd', 2) cmdaddr = m.inp('cmdaddr', 16) cmddata = m.inp('cmddata', 8) # internal arch state. state = m.reg('aes_state', 2) opaddr = m.reg('aes_addr', 16) oplen = m.reg('aes_len', 16) ctr = m.reg('aes_ctr', 128) key0 = m.reg('aes_key0', 128) # for the uinst. xram = m.mem('XRAM', 16, 8) aes = m.fun('aes', 128, [128, 128, 128]) # fetch is just looking at the input command. m.fetch_expr = ila.concat([cmd, cmdaddr, cmddata ]) # actually, the equivelant instruction m.fetch_valid = (cmd == 2) # when write to some addresses # decode wrcmds = [(cmd == 2) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40)] m.decode_exprs = wrcmds m.add_assumption((state == 0) | (oplen > 1)) um = m.add_microabstraction('aes_compute', (state != 0)) # write commands. def mb_reg_wr(name, reg): # multibyte register write. reg_wr = ila.writechunk('wr_' + name, reg, cmddata) reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) mb_reg_wr('aes_addr', opaddr) mb_reg_wr('aes_len', oplen) mb_reg_wr('aes_ctr', ctr) mb_reg_wr('aes_key0', key0) # state state_next = ila.choice( 'state_next', [state, m.const(0, 2), ila.ite((cmddata == 1), m.const(1, 2), state)]) m.set_next('aes_state', state_next) # xram m.set_next('XRAM', xram) ################################ # Micro-ILA ################################ # read data rd_data = um.reg('rd_data', 128) enc_data = um.reg('enc_data', 128) blk_cnt = um.reg('blk_cnt', 16) uaes_ctr = um.reg('uaes_ctr', 128) um.set_init('blk_cnt', um.const(0, 16)) um.set_init('uaes_ctr', um.getreg('aes_ctr')) uxram = m.getmem('XRAM') um.fetch_expr = state um.decode_exprs = [(state == i) for i in [1, 2, 3]] # READ/OPERATE/WRITE # blk_cnt blk_cnt_inc = blk_cnt + ila.inrange('blkcntrange', um.const(1, 16), um.const(32, 16)) more_blocks = ila.choice('cond1', (blk_cnt_inc != oplen), (oplen >= blk_cnt_inc), (oplen > blk_cnt_inc)) blk_cnt_nxt = ila.choice('blk_cnt_nxt', [ m.const(0, 16), blk_cnt, blk_cnt_inc, ila.ite(more_blocks, blk_cnt_inc, blk_cnt) ]) um.set_next('blk_cnt', blk_cnt_nxt) # ustate ustate = um.getreg('aes_state') ustate_nxt = ila.choice('ustate_next', [ m.const(0, 2), m.const(1, 2), m.const(2, 2), m.const(3, 2), ustate, ila.ite(more_blocks, m.const(1, 2), m.const(0, 2)) ]) # change 4 um.set_next('aes_state', ustate_nxt) # rd_data rdblock = ila.loadblk(uxram, opaddr + blk_cnt, 16) rd_data_nxt = ila.choice('rd_data_nxt', rdblock, rd_data) um.set_next('rd_data', rd_data_nxt) # enc_data aes_key = key0 aes_enc_data = ila.appfun(aes, [uaes_ctr, aes_key, rd_data]) enc_data_nxt = ila.ite(state == 2, aes_enc_data, enc_data) um.set_next('enc_data', enc_data_nxt) #print um.get_next('enc_data') uaes_ctr_nxt = ila.choice( 'uaes_ctr_nxt', uaes_ctr, uaes_ctr + ila.inrange('uaes_ctr_nxt_range', m.const(1, 128), m.const(128, 128))) um.set_next('uaes_ctr', uaes_ctr_nxt) # xram write xram_w_addr = opaddr + blk_cnt xram_w_aes = ila.storeblk(uxram, xram_w_addr, enc_data) xram_nxt = ila.choice('xram_nxt', uxram, xram_w_aes) um.set_next('XRAM', xram_nxt) return m, um
def createSHAILA(synstates, enable_ps): m = ila.Abstraction("sha") m.enable_parameterized_synthesis = enable_ps # I/O interface: this is where commands come from. cmd = m.inp('cmd', 2) cmdaddr = m.inp('cmdaddr', 16) cmddata = m.inp('cmddata', 8) # response. dataout = m.reg('dataout', 8) # internal arch state. state = m.reg('sha_state', 3) rdaddr = m.reg('sha_rdaddr', 16) wraddr = m.reg('sha_wraddr', 16) oplen = m.reg('sha_len', 16) # for the uinst. bytes_read = m.reg('sha_bytes_read', 16) rd_data = m.reg('sha_rd_data', 512) hs_data = m.reg('sha_hs_data', 160) xram = m.mem('XRAM', 16, 8) sha = m.fun('sha', 160, [512]) # fetch is just looking at the input command. m.fetch_expr = ila.concat([state, cmd, cmdaddr, cmddata]) m.fetch_valid = (cmd == 1) | (cmd == 2) # decode rdcmds = [(state == i) & (cmd == 1) & (cmdaddr == addr) for addr in xrange(0xfe00, 0xfe10) for i in [0, 1, 2, 3, 4]] wrcmds = [(state == 0) & (cmd == 2) & (cmdaddr == addr) for addr in xrange(0xfe00, 0xfe10)] nopcmds = [(state == i) & (cmd != 1) & (cmdaddr == addr) for addr in xrange(0xfe00, 0xfe10) for i in [1, 2, 3, 4]] m.decode_exprs = rdcmds + wrcmds + nopcmds # read commands. statebyte = ila.zero_extend(state, 8) rdaddrbyte = ila.readchunk('rd_addr', rdaddr, 8) wraddrbyte = ila.readchunk('wr_addr', wraddr, 8) oplenbyte = ila.readchunk('op_len', oplen, 8) dataoutnext = ila.choice( 'dataout', [statebyte, rdaddrbyte, wraddrbyte, oplenbyte, m.const(0, 8)]) m.set_next('dataout', dataoutnext) # write commands. def mb_reg_wr(name, reg): # multibyte register write. reg_wr = ila.writechunk('wr_' + name, reg, cmddata) reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) mb_reg_wr('sha_rdaddr', rdaddr) mb_reg_wr('sha_wraddr', wraddr) mb_reg_wr('sha_len', oplen) # state state_next = ila.choice('state_next', [ m.const(0, 3), m.const(1, 3), m.const(2, 3), m.const(3, 3), m.const(4, 3), ila.ite(cmddata == 1, m.const(1, 3), state), ila.ite(bytes_read < oplen, m.const(1, 3), m.const(4, 3)) ]) m.set_next('sha_state', state_next) # these are for the uinst # bytes_read #bytes_read_inc = ila.ite(bytes_read+64 <= oplen, bytes_read+64, oplen) bytes_read_inc = bytes_read + 64 bytes_read_rst = ila.ite(cmddata == 1, m.const(0, 16), bytes_read) bytes_read_nxt = ila.choice( 'bytes_read_nxt', [m.const(0, 16), bytes_read_inc, bytes_read_rst, bytes_read]) m.set_next('sha_bytes_read', bytes_read_nxt) # rd_data rdblock_little = ila.loadblk(xram, rdaddr + bytes_read, 64) rdblock_big = ila.loadblk_big(xram, rdaddr + bytes_read, 64) rd_data_nxt = ila.choice('rd_data_nxt', rdblock_big, rdblock_little, rd_data) m.set_next('sha_rd_data', rd_data_nxt) # hs_data sha_hs_data = ila.appfun(sha, [rd_data]) hs_data_nxt = ila.choice('hs_data_nxt', sha_hs_data, hs_data) m.set_next('sha_hs_data', hs_data_nxt) # xram write xram_w_sha_little = ila.storeblk(xram, wraddr, hs_data) xram_w_sha_big = ila.storeblk_big(xram, wraddr, hs_data) xram_nxt = ila.choice('xram_nxt', xram, xram_w_sha_little, xram_w_sha_big) m.set_next('XRAM', xram_nxt) suffix = 'en' if enable_ps else 'dis' timefile = open('sha-times-%s.txt' % suffix, 'wt') t_elapsed = 0 # synthesis. sim = lambda s: SHA().simulate(s) for s in synstates: st = time.clock() m.synthesize(s, sim) dt = time.clock() - st print >> timefile, '%s %.2f' % (s, dt) t_elapsed += dt ast = m.get_next(s) m.exportOne(ast, 'asts/%s_%s' % (s, suffix)) print 'time: %.2f' % t_elapsed #m.generateSim('tmp/shasim.hpp') m.generateSimToDir('sim')
def createAESILA(synstates, enable_ps): m = ila.Abstraction("aes") m.enable_parameterized_synthesis = enable_ps # I/O interface: this is where the commands come from. cmd = m.inp('cmd', 2) cmdaddr = m.inp('cmdaddr', 16) cmddata = m.inp('cmddata', 8) # response. dataout = m.reg('dataout', 8) # internal arch state. state = m.reg('aes_state', 2) opaddr = m.reg('aes_addr', 16) oplen = m.reg('aes_len', 16) keysel = m.reg('aes_keysel', 1) ctr = m.reg('aes_ctr', 128) key0 = m.reg('aes_key0', 128) key1 = m.reg('aes_key1', 128) # for the uinst. byte_cnt = m.reg('byte_cnt', 16) rd_data = m.reg('rd_data', 128) enc_data = m.reg('enc_data', 128) xram = m.mem('XRAM', 16, 8) aes = m.fun('aes', 128, [128, 128, 128]) # fetch is just looking at the input command. m.fetch_expr = ila.concat([state, cmd, cmdaddr, cmddata]) m.fetch_valid = (cmd == 1) | (cmd == 2) # decode rdcmds = [(state == i) & (cmd == 1) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40) for i in [0, 1, 2, 3]] wrcmds = [(state == 0) & (cmd == 2) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40)] nopcmds = [(state == i) & (cmd != 1) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40) for i in [1, 2, 3]] m.decode_exprs = rdcmds + wrcmds + nopcmds # read commands statebyte = ila.zero_extend(state, 8) opaddrbyte = ila.readchunk('rd_addr', opaddr, 8) oplenbyte = ila.readchunk('rd_len', oplen, 8) keyselbyte = ila.zero_extend(keysel, 8) ctrbyte = ila.readchunk('rd_ctr', ctr, 8) key0byte = ila.readchunk('rd_key0', key0, 8) key1byte = ila.readchunk('rd_key1', key1, 8) dataoutnext = ila.choice('dataout', [ statebyte, opaddrbyte, oplenbyte, keyselbyte, ctrbyte, key0byte, key1byte, m.const(0, 8) ]) m.set_next('dataout', dataoutnext) # write commands. def mb_reg_wr(name, reg): # multibyte register write. reg_wr = ila.writechunk('wr_' + name, reg, cmddata) reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) mb_reg_wr('aes_addr', opaddr) mb_reg_wr('aes_len', oplen) mb_reg_wr('aes_ctr', ctr) mb_reg_wr('aes_key0', key0) mb_reg_wr('aes_key1', key1) # bit-level registers def bit_reg_wr(name, reg, sz): # bitwise register write assert reg.type.bitwidth == sz reg_wr = cmddata[sz - 1:0] reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) bit_reg_wr('aes_keysel', keysel, 1) # state state_next = ila.choice('state_next', [ m.const(0, 2), m.const(1, 2), m.const(2, 2), m.const(3, 2), ila.ite(cmddata == 1, m.const(1, 2), state), ila.ite(byte_cnt + 16 < oplen, m.const(1, 2), m.const(0, 2)) ]) m.set_next('aes_state', state_next) # these are for the uinst # byte_cnt byte_cnt_inc = byte_cnt + 16 byte_cnt_rst = ila.ite(cmddata == 1, m.const(0, 16), byte_cnt) byte_cnt_nxt = ila.choice( 'byte_cnt_nxt', [m.const(0, 16), byte_cnt_inc, byte_cnt_rst, byte_cnt]) m.set_next('byte_cnt', byte_cnt_nxt) # rd_data rdblock = ila.loadblk(xram, opaddr + byte_cnt, 16) rd_data_nxt = ila.choice('rd_data_nxt', rdblock, rd_data) m.set_next('rd_data', rd_data_nxt) # enc_data aes_key = ila.ite(keysel == 0, key0, key1) aes_enc_data = ila.appfun(aes, [ctr, aes_key, rd_data]) enc_data_nxt = ila.ite(state == 2, aes_enc_data, enc_data) m.set_next('enc_data', enc_data_nxt) # xram write xram_w_aes = ila.storeblk(xram, opaddr + byte_cnt, enc_data) xram_nxt = ila.choice('xram_nxt', xram, xram_w_aes) m.set_next('XRAM', xram_nxt) # synthesize. timefile = open('aes-times-%s.txt' % ('en' if enable_ps else 'dis'), 'wt') sim = lambda s: AES().simulate(s) for s in synstates: st = time.clock() m.synthesize(s, sim) t_elapsed = time.clock() - st print >> timefile, s print >> timefile, '%.2f' % (t_elapsed) ast = m.get_next(s) m.exportOne(ast, 'asts/%s_%s' % (s, 'en' if enable_ps else 'dis')) m.generateSimToDir('sim')
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] assert sys.areEqual(rn1, rn2) # addr 16 bit, data 8 bit xram = sys.mem('xram', 8, 8) wrrd = sys.reg('wrrd', 8) data = sys.const(0xfe, 8) addr = sys.const(0x04, 8) xram = ila.store(xram, addr, data) wrrd_next = xram[addr] sys.set_next('wrrd', wrrd_next) wrrdblx = sys.reg('wrrdblx', 24) datablx = sys.const(0x0f00fe, 24) xram = ila.storeblk(xram, addr, datablx) wrrdblx_next = ila.loadblk(xram, addr, 3) sys.set_next('wrrdblx', wrrdblx_next) #sys.add_assumption(opcode == 0x80) #print sys.syn_elem("r0", sys.get_next('r0'), alusim) expFile = "tmp/test_ila_export.txt" sys.exportAll(expFile) # 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) #os.unlink(expFile) #simFile = "tmp/test_ila_sim.hpp" #sys.generateSim(simFile) path = 'tmp/dir' if not os.path.exists(path): os.makedirs(path) sys.generateSimToDir(path)
def createShaIla(): m = ila.Abstraction("sha") m.enable_parameterized_synthesis = 0 # I/O interface cmd = m.inp('cmd', 2) cmdaddr = m.inp('cmdaddr', 16) cmddata = m.inp('cmddata', 8) # response dataout = m.reg('dataout', 8) # arch states state = m.reg('sha_state', 3) rdaddr = m.reg('sha_rdaddr', 16) wraddr = m.reg('sha_wraddr', 16) oplen = m.reg('sha_len', 16) xram = m.mem('XRAM', 16, 8) # child-ILA states bytes_read = m.reg('sha_bytes_read', 16) rd_data = m.reg('sha_rd_data', 512) hs_data = m.reg('sha_hs_data', 160) sha = m.fun('sha', 160, [512]) # fetch m.fetch_expr = ila.concat([state, cmd, cmdaddr, cmddata]) m.fetch_valid = (cmd == 1) | (cmd == 2) # read commands. statebyte = ila.zero_extend(state, 8) rdaddrbyte = ila.readchunk('rd_addr', rdaddr, 8) wraddrbyte = ila.readchunk('wr_addr', wraddr, 8) oplenbyte = ila.readchunk('op_len', oplen, 8) dataoutnext = ila.choice( 'dataout', [statebyte, rdaddrbyte, wraddrbyte, oplenbyte, m.const(0, 8)]) m.set_next('dataout', dataoutnext) # write commands. def mb_reg_wr(name, reg): reg_wr = ila.writechunk('wr_' + name, reg, cmddata) reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) mb_reg_wr('sha_rdaddr', rdaddr) mb_reg_wr('sha_wraddr', wraddr) mb_reg_wr('sha_len', oplen) # state state_choice = ila.choice('state_choice', [ m.const(0, 3), m.const(1, 3), m.const(2, 3), m.const(3, 3), m.const(4, 3) ]) rd_nxt = ila.ite(bytes_read < oplen, m.const(1, 3), m.const(4, 3)) state_nxt = ila.choice('state_nxt', [ rd_nxt, state_choice, ila.ite(cmddata == 1, m.const(1, 3), state), state ]) m.set_next('sha_state', state_nxt) # bytes_read bytes_read_inc = bytes_read + 64 bytes_read_rst = ila.ite(cmddata == 1, m.const(0, 16), bytes_read) bytes_read_nxt = ila.choice( 'bytes_read_nxt', [m.const(0, 16), bytes_read_inc, bytes_read_rst, bytes_read]) m.set_next('sha_bytes_read', bytes_read_nxt) # rd_data rdblock_little = ila.loadblk(xram, rdaddr + bytes_read, 64) rdblock_big = ila.loadblk_big(xram, rdaddr + bytes_read, 64) rd_data_nxt = ila.choice('rd_data_nxt', [rdblock_big, rdblock_little, rd_data]) m.set_next('sha_rd_data', rd_data_nxt) # hs_data sha_hs_data = ila.appfun(sha, [rd_data]) hs_data_nxt = ila.choice('sh_data_nxt', sha_hs_data, hs_data) m.set_next('sha_hs_data', hs_data_nxt) # xram xram_w_sha_little = ila.storeblk(xram, wraddr, hs_data) xram_w_sha_big = ila.storeblk_big(xram, wraddr, hs_data) xram_nxt = ila.choice('xram_nxt', [xram_w_sha_little, xram_w_sha_big, xram]) m.set_next('XRAM', xram_nxt) return m
def main(): sys = ila.Abstraction("test") iram = sys.mem('iram', 8, 8) addr = sys.reg('addr', 8) print iram, iram.type data = iram[addr] addrp = sys.reg('addrp', 8) datap = iram[addrp] t = sys.bool(True) f = sys.bool(False) assert sys.areEqual((addr != addrp) | (data == datap), t) print data, data.type datap = data+1 print datap, datap.type iramp = ila.store(iram, addr, data+1) print iramp, iramp.type assert sys.areEqual(iramp[addr], data+1) assert not sys.areEqual(data, data+1) m = ila.MemValues(8, 8, 0xff) print m for i in xrange(0x80, 0x90): m[i] = i-0x80 print m for i in xrange(0x0, 0x100): if i >= 0x80 and i < 0x90: assert m[i] == i-0x80 else: assert m[i] == 0xff print m m1 = sys.const(m) assert m.default == 0xff m.default = 0x0 print m assert m[0] == 0 print m.values m2 = sys.const(m) # assert not sys.areEqual(m1[addr], m2[addr]) ante = ((addr >= 0x80) & (addr < 0x90)) conseq = (m1[addr] == m2[addr]) assert sys.areEqual(ila.implies(ante, conseq), t) assert not sys.areEqual(conseq, t) r1 = iram[addr]+1 r2 = iram[addr]+iram[addr+1] r = ila.choice('r', r1, r2) print sys.syn_elem("foo", r, foo) def bar(d): print d ram = d['iram'] ram_ = ila.MemValues(8, 8, ram.default) print ram print ram_ for (ad, da) in ram.values: ram_[ad] = da addr = d['addr'] print ram_, addr, ram[addr] if addr != 0: ram_[addr] = ram_[addr]+1 print ram_ return { "bar": ram_ } r1 = ila.store(iram, addr, iram[addr]+1) r2 = ila.store(iram, addr, iram[addr]+2) r3 = ila.ite(addr != 0, r1, iram) rp = ila.choice('rp', r1, r2, r3) expr = sys.syn_elem("bar", rp, bar) assert sys.areEqual(expr, r3) ila.setloglevel(3, "") data = sys.const(0xdeadbeef, 32) print data iramp = ila.storeblk(iram, addrp, data) d0 = iramp[addrp] d1 = iramp[addrp+1] d2 = iramp[addrp+2] d3 = iramp[addrp+3] datablk = ila.loadblk(iramp, addrp, 4) assert sys.areEqual(datablk, data) assert sys.areEqual(datablk, ila.concat([d3, d2, d1, d0])) assert sys.areEqual(ila.concat(d0, d1), sys.const(0xefbe, 16)) assert sys.areEqual(ila.concat(d2, d3), sys.const(0xadde, 16))
def createAESILA(enable_ps): m = ila.Abstraction("aes") m.enable_parameterized_synthesis = enable_ps # I/O interface: this is where the commands come from. cmd = m.inp('cmd', 2) cmdaddr = m.inp('cmdaddr', 16) cmddata = m.inp('cmddata', 8) # response. dataout = m.reg('dataout', 8) # internal arch state. state = m.reg('aes_state', 2) opaddr = m.reg('aes_addr', 16) oplen = m.reg('aes_len', 16) keysel = m.reg('aes_keysel', 1) ctr = m.reg('aes_ctr', 128) key0 = m.reg('aes_key0', 128) key1 = m.reg('aes_key1', 128) # for the uinst. xram = m.mem('XRAM', 16, 8) aes = m.fun('aes', 128, [128, 128, 128]) # fetch is just looking at the input command. m.fetch_expr = ila.concat([state, cmd, cmdaddr, cmddata]) m.fetch_valid = (cmd == 1) | (cmd == 2) # decode rdcmds = [(state == i) & (cmd == 1) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40) for i in [0, 1, 2, 3]] wrcmds = [(state == 0) & (cmd == 2) & (cmdaddr == addr) for addr in xrange(0xff00, 0xff40)] nopcmds = [ ((state != 0) & (cmd != 1)) | ((state == 0) & (cmd != 1) & (cmd != 2)) ] m.decode_exprs = rdcmds + wrcmds + nopcmds # read commands statebyte = ila.zero_extend(state, 8) opaddrbyte = ila.readchunk('rd_addr', opaddr, 8) oplenbyte = ila.readchunk('rd_len', oplen, 8) keyselbyte = ila.zero_extend(keysel, 8) ctrbyte = ila.readchunk('rd_ctr', ctr, 8) key0byte = ila.readchunk('rd_key0', key0, 8) key1byte = ila.readchunk('rd_key1', key1, 8) dataoutnext = ila.choice('dataout', [ statebyte, opaddrbyte, oplenbyte, keyselbyte, ctrbyte, key0byte, key1byte, m.const(0, 8) ]) m.set_next('dataout', dataoutnext) # write commands. def mb_reg_wr(name, reg): # multibyte register write. reg_wr = ila.writechunk('wr_' + name, reg, cmddata) reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) mb_reg_wr('aes_addr', opaddr) mb_reg_wr('aes_len', oplen) mb_reg_wr('aes_ctr', ctr) mb_reg_wr('aes_key0', key0) mb_reg_wr('aes_key1', key1) # bit-level registers def bit_reg_wr(name, reg, sz): # bitwise register write assert reg.type.bitwidth == sz reg_wr = cmddata[sz - 1:0] reg_nxt = ila.choice('nxt_' + name, [reg_wr, reg]) m.set_next(name, reg_nxt) bit_reg_wr('aes_keysel', keysel, 1) # these are for the uinst um = m.add_microabstraction('aes_compute', state != 0) um.fetch_expr = state um.decode_exprs = [state == i for i in [1, 2, 3]] # read data rd_data = um.reg('rd_data', 128) enc_data = um.reg('enc_data', 128) byte_cnt = um.reg('byte_cnt', 16) um.set_init('byte_cnt', um.const(0, 16)) uxram = m.getmem('XRAM') usim = lambda s: AES().simMicro(s) # ustate ustate = um.getreg('aes_state') ustate_nxt = ila.choice('ustate_next', [ m.const(0, 2), m.const(1, 2), m.const(2, 2), m.const(3, 2), ila.ite(byte_cnt + 16 < oplen, m.const(1, 2), m.const(0, 2)) ]) um.set_next('aes_state', ustate_nxt) # byte_cnt byte_cnt_inc = ila.ite(byte_cnt + 16 < oplen, byte_cnt + 16, byte_cnt) byte_cnt_nxt = ila.choice('byte_cnt_nxt', [byte_cnt_inc, byte_cnt]) um.set_next('byte_cnt', byte_cnt_nxt) # rd_data rdblock = ila.loadblk(uxram, opaddr + byte_cnt, 16) rd_data_nxt = ila.choice('rd_data_nxt', rdblock, rd_data) um.set_next('rd_data', rd_data_nxt) # enc_data aes_key = ila.ite(keysel == 0, key0, key1) aes_enc_data = ila.appfun(aes, [ctr, aes_key, rd_data]) enc_data_nxt = ila.ite(state == 2, aes_enc_data, enc_data) um.set_next('enc_data', enc_data_nxt) print um.get_next('enc_data') # xram write xram_w_aes = ila.storeblk(uxram, opaddr + byte_cnt, enc_data) xram_nxt = ila.choice('xram_nxt', uxram, xram_w_aes) um.set_next('XRAM', xram_nxt) suffix = ('en' if enable_ps else 'dis') timefile = open('aes-times-uinst-%s.txt' % suffix, 'wt') # micro-synthesis t_elapsed = 0 for s in ['aes_state', 'byte_cnt', 'rd_data', 'XRAM']: st = time.clock() um.synthesize(s, usim) dt = time.clock() - st t_elapsed += dt ast = um.get_next(s) print '%s: %s' % (s, str(ast)) m.exportOne(ast, 'uasts/u%s_%s' % (s, suffix)) print >> timefile, 'u_%s' % s print >> timefile, '%.2f' % dt sim = lambda s: AES().simMacro(s) # state state_next = ila.choice( 'state_next', [state, ila.ite(cmddata == 1, m.const(1, 2), state)]) m.set_next('aes_state', state_next) # xram m.set_next('XRAM', xram) # synthesize. for s in [ 'aes_state', 'aes_addr', 'aes_len', 'aes_keysel', 'aes_ctr', 'aes_key0', 'aes_key1', 'dataout' ]: st = time.clock() m.synthesize(s, sim) dt = time.clock() - st t_elapsed += dt ast = m.get_next(s) print '%s: %s' % (s, str(ast)) m.exportOne(ast, 'uasts/%s_%s' % (s, suffix)) print >> timefile, '%s' % s print >> timefile, '%.2f' % dt # connect to the uinst m.connect_microabstraction('aes_state', um) m.connect_microabstraction('XRAM', um) print 'aes_state: %s' % str(m.get_next('aes_state')) print 'XRAM: %s' % str(m.get_next('XRAM')) print 'time: %.2f' % (t_elapsed) m.generateSimToDir('sim_aes_u')