# reference: https://github.com/secworks/aes
from pyhgl.logic import *
from pyhgl.tester import *
import pyhgl.logic.utils as utils
import time
# multiplication under Rijndael’s finite field
# --------------------------------------------
def gm2(op): return (op << 1) ^ (op[-1]**8 & '8:h1b')
def gm3(op): return gm2(op) ^ op
def gm4(op): return gm2(gm2(op))
def gm8(op): return gm2(gm4(op))
def gm09(op): return gm8(op) ^ op
def gm11(op): return gm8(op) ^ gm2(op) ^ op
def gm13(op): return gm8(op) ^ gm4(op) ^ op
def gm14(op): return gm8(op) ^ gm4(op) ^ gm2(op)
def mixw(w):
"""
2 3 1 1 a0 b0
1 2 3 1 a1 -> b1
1 1 2 3 * a2 b2
3 1 1 2 a3 b3
input: array of 4 bytes: [a3, a2, a1, a0]
return: array of 4 bytes: [b3, b2, b1, b0]
"""
a3, a2, a1, a0 = w
b0 = gm2(a0) ^ gm3(a1) ^ a2 ^ a3
b1 = a0 ^ gm2(a1) ^ gm3(a2) ^ a3
b2 = a0 ^ a1 ^ gm2(a2) ^ gm3(a3)
b3 = gm3(a0) ^ a1 ^ a2 ^ gm2(a3)
return Array([b3, b2, b1, b0])
def inv_mixw(w):
a3, a2, a1, a0 = w
b0 = gm14(a0) ^ gm11(a1) ^ gm13(a2) ^ gm09(a3)
b1 = gm09(a0) ^ gm14(a1) ^ gm11(a2) ^ gm13(a3)
b2 = gm13(a0) ^ gm09(a1) ^ gm14(a2) ^ gm11(a3)
b3 = gm11(a0) ^ gm13(a1) ^ gm09(a2) ^ gm14(a3)
return Array([b3, b2, b1, b0])
# a: Array of 16 bytes
def mixcolumns(a): return Array(mixw(i) for i in a._reshape(4,4))._flat
def inv_mixcolumns(a): return Array(inv_mixw(i) for i in a._reshape(4,4))._flat
def shiftrows(a):
"""
input:
a00 a01 a02 a03
a10 a11 a12 a13
a20 a21 a22 a23
a30 a31 a32 a33
"""
a = a._reshape(4,4)
return Array([ a[1,0], a[2,1], a[3,2], a[0,3],
a[2,0], a[3,1], a[0,2], a[1,3],
a[3,0], a[0,1], a[1,2], a[2,3],
a[0,0], a[1,1], a[2,2], a[3,3],])
def inv_shiftrows(a):
a = a._reshape(4,4)
return Array([ a[3,0], a[2,1], a[1,2], a[0,3],
a[0,0], a[3,1], a[2,2], a[1,3],
a[1,0], a[0,1], a[3,2], a[2,3],
a[2,0], a[1,1], a[0,2], a[3,3],])
def addroundkey(data, rkey): return data ^ rkey
@module aes_encipher_block:
io = Bundle(
round = UInt('4:b0') @ Output, # nth round
new_block = UInt[8].zeros(16) @ Output,
ready = UInt('0') @ Output,
sboxw = UInt[8].zeros(4) @ Output,
)
sword_ctr_reg = Reg(UInt('2:b0')) # word counter, read sbox 4 cycles
round_ctr_reg = Reg(io.round) # round counter
block_reg = Reg(io.new_block)
ready_reg = Reg(io.ready)
switch update_type:=Enum['NO_UPDATE',...]():
once 'INIT_UPDATE':
block_reg <== addroundkey(conf.p.block, conf.p.round_key)
once 'SBOX_UPDATE':
switch sword_ctr_reg:
once 0: io.sboxw,block_reg[12:16] <== block_reg[12:16],conf.p.sbox.new_sboxw
once 1: io.sboxw,block_reg[8:12] <== block_reg[8:12],conf.p.sbox.new_sboxw
once 2: io.sboxw,block_reg[4:8] <== block_reg[4:8],conf.p.sbox.new_sboxw
once 3: io.sboxw,block_reg[0:4] <== block_reg[0:4],conf.p.sbox.new_sboxw
once 'MAIN_UPDATE':
block_reg <== addroundkey(mixcolumns(shiftrows(block_reg)), conf.p.round_key)
once 'FINAL_UPDATE':
block_reg <== addroundkey(shiftrows(block_reg), conf.p.round_key)
switch state:=Reg(Enum()):
once 'CTRL_IDLE':
when conf.p.next:
round_ctr_reg, ready_reg <== 0
state <== 'CTRL_INIT'
once 'CTRL_INIT':
round_ctr_reg <== round_ctr_reg + 1
sword_ctr_reg <== 0
update_type <== 'INIT_UPDATE'
state <== 'CTRL_SBOX'
once 'CTRL_SBOX':
sword_ctr_reg <== sword_ctr_reg + 1
update_type <== 'SBOX_UPDATE'
when sword_ctr_reg == 3:
state <== 'CTRL_MAIN'
once 'CTRL_MAIN':
sword_ctr_reg <== 0
round_ctr_reg <== round_ctr_reg + 1
when round_ctr_reg < conf.p.num_rounds:
update_type <== 'MAIN_UPDATE'
state <== 'CTRL_SBOX'
otherwise:
update_type <== 'FINAL_UPDATE'
ready_reg <== 1
state <== 'CTRL_IDLE'
@module aes_decipher_block:
io = Bundle(
round = UInt('4:b0') @ Output, # nth round
new_block = UInt[8].zeros(16) @ Output,
ready = UInt('0') @ Output,
)
sword_ctr_reg = Reg(UInt('2:b0')) # word counter, read sbox 4 cycles
round_ctr_reg = Reg(io.round) # round counter, decrease because use later keys
block_reg = Reg(io.new_block)
ready_reg = Reg(io.ready)
inv_sbox = aes_inv_sbox()
switch update_type:=Enum['NO_UPDATE',...]():
once 'INIT_UPDATE':
block_reg <== inv_shiftrows(addroundkey(conf.p.block, conf.p.round_key))
once 'SBOX_UPDATE':
switch sword_ctr_reg:
once 0: inv_sbox.sboxw,block_reg[12:16] <== block_reg[12:16],inv_sbox.new_sboxw
once 1: inv_sbox.sboxw,block_reg[8:12] <== block_reg[8:12],inv_sbox.new_sboxw
once 2: inv_sbox.sboxw,block_reg[4:8] <== block_reg[4:8],inv_sbox.new_sboxw
once 3: inv_sbox.sboxw,block_reg[0:4] <== block_reg[0:4],inv_sbox.new_sboxw
once 'MAIN_UPDATE':
block_reg <== inv_shiftrows(inv_mixcolumns(addroundkey(block_reg, conf.p.round_key)))
once 'FINAL_UPDATE':
block_reg <== addroundkey(block_reg, conf.p.round_key)
switch state:=Reg(Enum()):
once 'CTRL_IDLE':
when conf.p.next:
round_ctr_reg <== conf.p.num_rounds
ready_reg <== 0
state <== 'CTRL_INIT'
once 'CTRL_INIT':
sword_ctr_reg <== 0
update_type <== 'INIT_UPDATE'
state <== 'CTRL_SBOX'
once 'CTRL_SBOX':
sword_ctr_reg <== sword_ctr_reg + 1
update_type <== 'SBOX_UPDATE'
when sword_ctr_reg == 3:
round_ctr_reg <== round_ctr_reg - 1
state <== 'CTRL_MAIN'
once 'CTRL_MAIN':
sword_ctr_reg <== 0
when round_ctr_reg > 0:
update_type <== 'MAIN_UPDATE'
state <== 'CTRL_SBOX'
otherwise:
update_type <== 'FINAL_UPDATE'
ready_reg <== 1
state <== 'CTRL_IDLE'
@module aes_core:
io = Bundle(
encdec = UInt('0') @Input,
init = UInt('0') @Input,
next = UInt('0') @Input,
ready = UInt('0') @Output,
key = UInt('256:b0') @Input,
keylen = UInt('0') @Input,
block = UInt('128:b0') @Input,
result = UInt('128:b0') @Output,
result_valid = UInt('0') @Output,
)
conf.p.init = io.init # pass to aes_key_mem
conf.p.next = io.next # pass to enc/dec block
conf.p.num_rounds = Mux(io.keylen, 14, 10) # pass to enc/dec block
conf.p.keylen = io.keylen # pass to aes_key_mem
conf.p.sbox = aes_sbox() # sbox is accessed by both enc_block and aes_key_mem
conf.p.key = io.key.split(8) # pass to aes_key_mem
result_valid_reg = Reg(io.result_valid)
ready_reg = Reg(io.ready)
keymem = aes_key_mem() # key expension
conf.p.round_key = keymem.io.round_key # pass to enc/dec block
conf.p.block = io.block.split(8) # pass to enc/dec block
enc_block = aes_encipher_block()
dec_block = aes_decipher_block()
init_state = UInt(0)
# sbox_mux
conf.p.sbox.sboxw <== Mux(init_state, keymem.io.sboxw, enc_block.io.sboxw)
# encdex_mux
keymem.io.round <== Mux(io.encdec, enc_block.io.round, dec_block.io.round)
io.result <== Mux(io.encdec, Cat(*enc_block.io.new_block), Cat(*dec_block.io.new_block))
muxed_ready = Mux(io.encdec, enc_block.io.ready, dec_block.io.ready)
switch state:=Reg(Enum()):
once 'CTRL_IDLE':
when io.init:
init_state <== 1
ready_reg,result_valid_reg <== 0
state <== 'CTRL_INIT'
elsewhen io.next:
init_state, ready_reg, result_valid_reg <== 0
state <== 'CTRL_NEXT'
once 'CTRL_INIT':
init_state <== 1
when keymem.io.ready:
ready_reg <== 1
state <== 'CTRL_IDLE'
once 'CTRL_NEXT':
init_state <== 0
when muxed_ready:
ready_reg, result_valid_reg <== 1
state <== 'CTRL_IDLE'
@module aes_key_mem:
io = Bundle(
round = UInt('4:b0') @ Input, # input nth round
round_key = UInt[8].zeros(16) @ Output, # output nth key
ready = UInt('0') @ Output, # init ready
sboxw = UInt[8].zeros(4) @ Output, # result
)
# 16 x Vec[15,8]; 16 columns of bytes
key_mem = Reg( (15*UInt[8])(0) for _ in range(16) )
# output
io.round_key <== (key_mem_column[io.round] for key_mem_column in key_mem)
key_mem_new = WireNext(conf.p.key[16:])
round_ctr_reg = Reg(UInt('4:b0')) # round counter, nth round
rcon_reg = Reg(UInt('8:b0')) # round constant
ready_reg = Reg(io.ready)
round_key_update = UInt(0)
when round_key_update: # store generated keys
for odd_mem, new_mem in zip(key_mem, key_mem_new):
odd_mem[round_ctr_reg] <== new_mem
# update rcon
rcon_next = UInt(0)
when !round_key_update: # init rcon
rcon_reg <== '8:h8d'
when rcon_next: # next rcon
rcon_reg <== gm2(rcon_reg)
k0, k1, k2, k3 = UInt[8].zeros(4,4)
w3, w2, w1, w0 = RegNext(conf.p.key[16:])._reshape(4,4)
w7, w6, w5, w4 = RegNext(conf.p.key[16:])._reshape(4,4)
io.sboxw <== w7
tw = conf.p.sbox.new_sboxw
trw = Array([ tw[3], tw[0], tw[1], tw[2] ^ rcon_reg])
when round_key_update:
rcon_next <== 1
when conf.p.keylen == 0: # AES128
when round_ctr_reg != 0:
k0, k1, k2, k3 <== w4^trw, w5^w4^trw, w6^w5^w4^trw, w7^w6^w5^w4^trw
key_mem_new <== *k3, *k2, *k1, *k0
w7, w6, w5, w4 <== k3, k2, k1, k0
otherwise: # AES256
when round_ctr_reg == 0:
rcon_next <== 0
elsewhen round_ctr_reg == 1:
key_mem_new <== conf.p.key[:16]
w7, w6, w5, w4 <== conf.p.key[:16]._reshape(4,4)
otherwise:
when round_ctr_reg[0] == 0:
k0, k1, k2, k3 <== w0^trw, w1^w0^trw, w2^w1^w0^trw, w3^w2^w1^w0^trw
rcon_next <== 0
otherwise:
k0, k1, k2, k3 <== w0^tw, w1^w0^tw, w2^w1^w0^tw, w3^w2^w1^w0^tw
key_mem_new <== *k3, *k2, *k1, *k0
w7, w6, w5, w4, w3, w2, w1, w0 <== k3, k2, k1, k0, w7, w6, w5, w4
switch state:=Reg(Enum()):
once 'IDLE':
when conf.p.init:
ready_reg <== 0
state <== 'INIT'
once 'INIT':
round_ctr_reg <== 0
state <== 'GENERATE'
once 'GENERATE':
round_ctr_reg <== round_ctr_reg + 1
round_key_update <== 1
when round_ctr_reg == conf.p.num_rounds:
state <== 'DONE'
once 'DONE':
ready_reg <== 1
state <== 'IDLE'
@module aes_sbox:
""" input: 4 bytes
"""
sboxw = UInt(['8:b0'] * 4)
sbox = Vector(256, UInt[8])([
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
])
new_sboxw = Array(sbox[i] for i in sboxw)
@module aes_inv_sbox:
sboxw = UInt(['8:b0'] * 4)
sbox = Vector(256, UInt[8])([
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
])
new_sboxw = Array(sbox[i] for i in sboxw)
@task test_enc_dec(self, dut, mode, key, text, expected):
assert mode in ['128enc','128dec','256enc','256dec']
mode_encode = (mode[-3:] == 'enc')
mode_256 = (mode[:3] == '256')
setv(dut.io.encdec, mode_encode)
setv(dut.io.keylen, mode_256)
setv(dut.io.key, key)
setv(dut.io.block, text)
setv(dut.io.init, 1)
yield self.clock_n(2)
setv(dut.io.init, 0)
yield dut.io.ready
setv(dut.io.next, 1)
yield self.clock_n(2)
setv(dut.io.next, 0)
yield dut.io.ready
result = getv(dut.io.result)
self.AssertEq(result, expected)
print(f"mode:{mode}, key:{hex(key)}, text:{hex(text)}, expected:{hex(expected)}, result:{hex(result.v)}")
@tester test_AES(self):
sess = Session()
sess.enter()
conf.reset = (conf.reset[0], 0)
t = time.time()
dut = aes_core()
print('pyhgl build: ', time.time()-t)
aes128_key1 = 0x2b7e151628aed2a6abf7158809cf4f3c00000000000000000000000000000000
aes128_key2 = 0x000102030405060708090a0b0c0d0e0f00000000000000000000000000000000
aes256_key1 = 0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
aes256_key2 = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
plaintext0 = 0x6bc1bee22e409f96e93d7e117393172a
plaintext1 = 0xae2d8a571e03ac9c9eb76fac45af8e51
plaintext2 = 0x30c81c46a35ce411e5fbc1191a0a52ef
plaintext3 = 0xf69f2445df4f9b17ad2b417be66c3710
plaintext4 = 0x00112233445566778899aabbccddeeff
_128_enc_expected0 = 0x3ad77bb40d7a3660a89ecaf32466ef97
_128_enc_expected1 = 0xf5d3d58503b9699de785895a96fdbaaf
_128_enc_expected2 = 0x43b1cd7f598ece23881b00e3ed030688
_128_enc_expected3 = 0x7b0c785e27e8ad3f8223207104725dd4
_128_enc_expected4 = 0x69c4e0d86a7b0430d8cdb78070b4c55a
_256_enc_expected0 = 0xf3eed1bdb5d2a03c064b5a7e3db181f8
_256_enc_expected1 = 0x591ccb10d410ed26dc5ba74a31362870
_256_enc_expected2 = 0xb6ed21b99ca6f4f9f153e7b1beafed1d
_256_enc_expected3 = 0x23304b7a39f9f3ff067d8d8f9e24ecc7
_256_enc_expected4 = 0x8ea2b7ca516745bfeafc49904b496089
@task aes_tests(self):
yield self.reset()
yield test_enc_dec(dut, '128enc', aes128_key1, plaintext0, _128_enc_expected0)
yield test_enc_dec(dut, '128enc', aes128_key1, plaintext1, _128_enc_expected1)
yield test_enc_dec(dut, '128enc', aes128_key1, plaintext2, _128_enc_expected2)
yield test_enc_dec(dut, '128enc', aes128_key1, plaintext3, _128_enc_expected3)
yield test_enc_dec(dut, '128enc', aes128_key2, plaintext4, _128_enc_expected4)
yield test_enc_dec(dut, '128dec', aes128_key1, _128_enc_expected0, plaintext0)
yield test_enc_dec(dut, '128dec', aes128_key1, _128_enc_expected1, plaintext1)
yield test_enc_dec(dut, '128dec', aes128_key1, _128_enc_expected2, plaintext2)
yield test_enc_dec(dut, '128dec', aes128_key1, _128_enc_expected3, plaintext3)
yield test_enc_dec(dut, '128dec', aes128_key2, _128_enc_expected4, plaintext4)
yield test_enc_dec(dut, '256enc', aes256_key1, plaintext0, _256_enc_expected0)
yield test_enc_dec(dut, '256enc', aes256_key1, plaintext1, _256_enc_expected1)
yield test_enc_dec(dut, '256enc', aes256_key1, plaintext2, _256_enc_expected2)
yield test_enc_dec(dut, '256enc', aes256_key1, plaintext3, _256_enc_expected3)
yield test_enc_dec(dut, '256enc', aes256_key2, plaintext4, _256_enc_expected4)
yield test_enc_dec(dut, '256dec', aes256_key1, _256_enc_expected0, plaintext0)
yield test_enc_dec(dut, '256dec', aes256_key1, _256_enc_expected1, plaintext1)
yield test_enc_dec(dut, '256dec', aes256_key1, _256_enc_expected2, plaintext2)
yield test_enc_dec(dut, '256dec', aes256_key1, _256_enc_expected3, plaintext3)
yield test_enc_dec(dut, '256dec', aes256_key2, _256_enc_expected4, plaintext4)
sess.dumpVerilog('AES.sv', delay=True, top = False)
sess.track(dut, dut.dec_block, dut.keymem, dut.enc_block)
t = time.time()
sess.join(aes_tests())
print('pyhgl sim:', time.time()-t)
print(sess)
sess.dumpVCD('AES.vcd')
sess.dumpGraph('AES.gv')
sess.exit()