Line 16... |
Line 16... |
enum, always_seq, always_comb, concat, ConcatSignal, modbv
|
enum, always_seq, always_comb, concat, ConcatSignal, modbv
|
|
|
IDLE, RESET, WRITE, READ, STARTC, STARTD = range(6)
|
IDLE, RESET, WRITE, READ, STARTC, STARTD = range(6)
|
|
|
COMPRESS = True
|
COMPRESS = True
|
|
DECOMPRESS = False
|
|
DECOMPRESS = True
|
|
|
|
DYNAMIC = False
|
|
DYNAMIC = True
|
|
|
MATCH10 = False
|
MATCH10 = False
|
MATCH10 = True
|
MATCH10 = True
|
|
|
FAST = False
|
FAST = False
|
FAST = True
|
FAST = True
|
|
|
CWINDOW = 32 # Search window for compression
|
CWINDOW = 32 # Search window for compression
|
|
|
OBSIZE = 8192 # Size of output buffer (BRAM)
|
OBSIZE = 8192 # Size of output buffer (BRAM)
|
IBSIZE = 4 * CWINDOW # 2048 # Size of input buffer (LUT-RAM)
|
OBSIZE = 32768 # Size of output buffer for ANY input (BRAM)
|
|
|
|
# Size of input buffer (LUT-RAM)
|
|
IBSIZE = 16 * CWINDOW # This size gives method 2 (dynamic tree) for testbench
|
|
IBSIZE = 2 * CWINDOW # Minimal window
|
|
|
|
LMAX = 24 # Size of progress and I/O counters
|
|
|
|
|
if OBSIZE > IBSIZE:
|
if OBSIZE > IBSIZE:
|
LBSIZE = int(log2(OBSIZE))
|
LBSIZE = int(log2(OBSIZE))
|
else:
|
else:
|
LBSIZE = int(log2(IBSIZE))
|
LBSIZE = int(log2(IBSIZE))
|
|
|
LIBSIZE = int(log2(IBSIZE))
|
LIBSIZE = int(log2(IBSIZE))
|
|
LOBSIZE = int(log2(OBSIZE))
|
|
|
IBS = (1 << LIBSIZE) - 1
|
IBS = (1 << LIBSIZE) - 1
|
|
OBS = (1 << LOBSIZE) - 1
|
|
|
d_state = enum('IDLE', 'HEADER', 'BL', 'READBL', 'REPEAT', 'DISTTREE', 'INIT3',
|
d_state = enum('IDLE', 'HEADER', 'BL', 'READBL', 'REPEAT', 'DISTTREE', 'INIT3',
|
'HF1', 'HF1INIT', 'HF2', 'HF3', 'HF4', 'HF4_2', 'HF4_3',
|
'HF1', 'HF1INIT', 'HF2', 'HF3', 'HF4', 'HF4_2', 'HF4_3',
|
'STATIC', 'D_NEXT', 'D_NEXT_2',
|
'STATIC', 'D_NEXT', 'D_NEXT_2',
|
'D_INFLATE', 'SPREAD', 'NEXT', 'INFLATE', 'COPY', 'CSTATIC',
|
'D_INFLATE', 'SPREAD', 'NEXT', 'INFLATE', 'COPY', 'CSTATIC',
|
'SEARCH', 'DISTANCE', 'CHECKSUM') # , encoding='one_hot')
|
'SEARCH', 'SEARCHF', 'DISTANCE', 'CHECKSUM') # , encoding='one_hot')
|
|
|
CodeLengthOrder = (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14,
|
CodeLengthOrder = (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14,
|
1, 15)
|
1, 15)
|
|
|
CopyLength = (3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35,
|
CopyLength = (3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35,
|
Line 56... |
Line 72... |
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193,
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193,
|
12289, 16385, 24577)
|
12289, 16385, 24577)
|
|
|
ExtraDistanceBits = (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
|
ExtraDistanceBits = (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
|
|
|
|
out_codes = (
|
|
0x00c, 0x08c, 0x04c, 0x0cc, 0x02c, 0x0ac, 0x06c, 0x0ec,
|
|
0x01c, 0x09c, 0x05c, 0x0dc, 0x03c, 0x0bc, 0x07c, 0x0fc,
|
|
0x002, 0x082, 0x042, 0x0c2, 0x022, 0x0a2, 0x062, 0x0e2,
|
|
0x012, 0x092, 0x052, 0x0d2, 0x032, 0x0b2, 0x072, 0x0f2,
|
|
0x00a, 0x08a, 0x04a, 0x0ca, 0x02a, 0x0aa, 0x06a, 0x0ea,
|
|
0x01a, 0x09a, 0x05a, 0x0da, 0x03a, 0x0ba, 0x07a, 0x0fa,
|
|
0x006, 0x086, 0x046, 0x0c6, 0x026, 0x0a6, 0x066, 0x0e6,
|
|
0x016, 0x096, 0x056, 0x0d6, 0x036, 0x0b6, 0x076, 0x0f6,
|
|
0x00e, 0x08e, 0x04e, 0x0ce, 0x02e, 0x0ae, 0x06e, 0x0ee,
|
|
0x01e, 0x09e, 0x05e, 0x0de, 0x03e, 0x0be, 0x07e, 0x0fe,
|
|
0x001, 0x081, 0x041, 0x0c1, 0x021, 0x0a1, 0x061, 0x0e1,
|
|
0x011, 0x091, 0x051, 0x0d1, 0x031, 0x0b1, 0x071, 0x0f1,
|
|
0x009, 0x089, 0x049, 0x0c9, 0x029, 0x0a9, 0x069, 0x0e9,
|
|
0x019, 0x099, 0x059, 0x0d9, 0x039, 0x0b9, 0x079, 0x0f9,
|
|
0x005, 0x085, 0x045, 0x0c5, 0x025, 0x0a5, 0x065, 0x0e5,
|
|
0x015, 0x095, 0x055, 0x0d5, 0x035, 0x0b5, 0x075, 0x0f5,
|
|
0x00d, 0x08d, 0x04d, 0x0cd, 0x02d, 0x0ad, 0x06d, 0x0ed,
|
|
0x01d, 0x09d, 0x05d, 0x0dd, 0x03d, 0x0bd, 0x07d, 0x0fd,
|
|
0x013, 0x113, 0x093, 0x193, 0x053, 0x153, 0x0d3, 0x1d3,
|
|
0x033, 0x133, 0x0b3, 0x1b3, 0x073, 0x173, 0x0f3, 0x1f3,
|
|
0x00b, 0x10b, 0x08b, 0x18b, 0x04b, 0x14b, 0x0cb, 0x1cb,
|
|
0x02b, 0x12b, 0x0ab, 0x1ab, 0x06b, 0x16b, 0x0eb, 0x1eb,
|
|
0x01b, 0x11b, 0x09b, 0x19b, 0x05b, 0x15b, 0x0db, 0x1db,
|
|
0x03b, 0x13b, 0x0bb, 0x1bb, 0x07b, 0x17b, 0x0fb, 0x1fb,
|
|
0x007, 0x107, 0x087, 0x187, 0x047, 0x147, 0x0c7, 0x1c7,
|
|
0x027, 0x127, 0x0a7, 0x1a7, 0x067, 0x167, 0x0e7, 0x1e7,
|
|
0x017, 0x117, 0x097, 0x197, 0x057, 0x157, 0x0d7, 0x1d7,
|
|
0x037, 0x137, 0x0b7, 0x1b7, 0x077, 0x177, 0x0f7, 0x1f7,
|
|
0x00f, 0x10f, 0x08f, 0x18f, 0x04f, 0x14f, 0x0cf, 0x1cf,
|
|
0x02f, 0x12f, 0x0af, 0x1af, 0x06f, 0x16f, 0x0ef, 0x1ef,
|
|
0x01f, 0x11f, 0x09f, 0x19f, 0x05f, 0x15f, 0x0df, 0x1df,
|
|
0x03f, 0x13f, 0x0bf, 0x1bf, 0x07f, 0x17f, 0x0ff, 0x1ff,
|
|
0x000, 0x040, 0x020, 0x060, 0x010, 0x050, 0x030, 0x070,
|
|
0x008, 0x048, 0x028, 0x068, 0x018, 0x058, 0x038, 0x078,
|
|
0x004, 0x044, 0x024, 0x064, 0x014, 0x054, 0x034, 0x074,
|
|
0x003, 0x083, 0x043, 0x0c3, 0x023, 0x0a3, 0x063, 0x0e3
|
|
)
|
|
|
|
|
@block
|
@block
|
def deflate(i_mode, o_done, i_data, o_iprogress, o_oprogress, o_byte, i_addr,
|
def deflate(i_mode, o_done, i_data, o_iprogress, o_oprogress, o_byte,
|
clk, reset):
|
i_waddr, i_raddr, clk, reset):
|
|
|
""" Deflate (de)compress
|
""" Deflate (de)compress
|
|
|
Ports:
|
Ports:
|
|
|
"""
|
"""
|
|
|
iram = [Signal(intbv()[8:]) for _ in range(IBSIZE)]
|
iram = [Signal(intbv()[8:]) for _ in range(IBSIZE)]
|
oram = [Signal(intbv()[8:]) for _ in range(OBSIZE)]
|
oram = [Signal(intbv()[8:]) for _ in range(OBSIZE)]
|
|
|
oaddr = Signal(intbv()[LBSIZE:])
|
oaddr = Signal(modbv()[LOBSIZE:])
|
oraddr = Signal(intbv()[LBSIZE:])
|
oraddr = Signal(modbv()[LOBSIZE:])
|
obyte = Signal(intbv()[8:])
|
obyte = Signal(intbv()[8:])
|
orbyte = Signal(intbv()[8:])
|
orbyte = Signal(intbv()[8:])
|
|
|
iraddr = Signal(intbv()[LIBSIZE:])
|
# iraddr = Signal(modbv()[LIBSIZE:])
|
|
|
isize = Signal(intbv()[LBSIZE:])
|
isize = Signal(intbv()[LMAX:])
|
state = Signal(d_state.IDLE)
|
state = Signal(d_state.IDLE)
|
method = Signal(intbv()[3:])
|
method = Signal(intbv()[3:])
|
final = Signal(bool())
|
final = Signal(bool())
|
|
wtick = Signal(bool())
|
do_compress = Signal(bool())
|
do_compress = Signal(bool())
|
|
|
numLiterals = Signal(intbv()[9:])
|
numLiterals = Signal(intbv()[9:])
|
numDistance = Signal(intbv()[6:])
|
numDistance = Signal(intbv()[6:])
|
numCodeLength = Signal(intbv()[9:])
|
numCodeLength = Signal(intbv()[9:])
|
Line 96... |
Line 152... |
EndOfBlock = 256
|
EndOfBlock = 256
|
MaxBitLength = 288
|
MaxBitLength = 288
|
# MaxToken = 285
|
# MaxToken = 285
|
InvalidToken = 300
|
InvalidToken = 300
|
|
|
CODEBITS = 10 # MaxCodeLength
|
CODEBITS = MaxCodeLength
|
BITBITS = 9
|
BITBITS = 4
|
|
|
codeLength = [Signal(intbv()[4:]) for _ in range(MaxBitLength+2)]
|
codeLength = [Signal(intbv()[4:]) for _ in range(MaxBitLength+32)]
|
bits = Signal(intbv()[4:])
|
bits = Signal(intbv()[4:])
|
bitLengthCount = [Signal(intbv()[9:]) for _ in range(MaxCodeLength+1)]
|
bitLengthCount = [Signal(intbv()[9:]) for _ in range(MaxCodeLength+1)]
|
nextCode = [Signal(intbv()[CODEBITS:]) for _ in range(MaxCodeLength)]
|
nextCode = [Signal(intbv()[CODEBITS+1:]) for _ in range(MaxCodeLength+1)]
|
reverse = Signal(intbv()[CODEBITS:])
|
reverse = Signal(modbv()[CODEBITS:])
|
code_bits = [Signal(intbv()[9:]) for _ in range(MaxBitLength)]
|
# code_bits = [Signal(intbv()[MaxCodeLength:]) for _ in range(MaxBitLength)]
|
distanceLength = [Signal(intbv()[4:]) for _ in range(32)]
|
distanceLength = [Signal(intbv()[4:]) for _ in range(32)]
|
|
|
|
if DECOMPRESS:
|
|
if DYNAMIC:
|
|
leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(16384)]
|
|
d_leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(4096)]
|
|
else:
|
leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(512)]
|
leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(512)]
|
lwaddr = Signal(intbv()[9:])
|
d_leaves = [Signal(bool())]
|
# lraddr = Signal(intbv()[9:])
|
# leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(32768)]
|
d_leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(128)]
|
# d_leaves = [Signal(intbv()[CODEBITS + BITBITS:]) for _ in range(32768)]
|
# rleaf = Signal(intbv()[CODEBITS + BITBITS:])
|
else:
|
|
leaves = [Signal(bool())]
|
|
d_leaves = [Signal(bool())]
|
|
lwaddr = Signal(intbv()[MaxCodeLength:])
|
|
lraddr = Signal(intbv()[MaxCodeLength:])
|
|
rleaf = Signal(intbv()[CODEBITS + BITBITS:])
|
wleaf = Signal(intbv()[CODEBITS + BITBITS:])
|
wleaf = Signal(intbv()[CODEBITS + BITBITS:])
|
leaf = Signal(intbv()[CODEBITS + BITBITS:])
|
leaf = Signal(intbv()[CODEBITS + BITBITS:])
|
|
|
minBits = Signal(intbv()[5:])
|
minBits = Signal(intbv()[5:])
|
maxBits = Signal(intbv()[5:])
|
maxBits = Signal(intbv()[5:])
|
d_maxBits = Signal(intbv()[5:])
|
d_maxBits = Signal(intbv()[5:])
|
instantMaxBit = Signal(intbv()[InstantMaxBit:])
|
instantMaxBit = Signal(intbv()[InstantMaxBit:])
|
d_instantMaxBit = Signal(intbv()[InstantMaxBit:])
|
d_instantMaxBit = Signal(intbv()[InstantMaxBit:])
|
instantMask = Signal(intbv()[MaxCodeLength:])
|
instantMask = Signal(intbv()[MaxCodeLength:])
|
d_instantMask = Signal(intbv()[MaxCodeLength:])
|
d_instantMask = Signal(intbv()[MaxCodeLength:])
|
spread = Signal(intbv()[10:])
|
spread = Signal(intbv()[InstantMaxBit:])
|
step = Signal(intbv()[10:])
|
step = Signal(intbv()[InstantMaxBit:])
|
|
|
static = Signal(bool())
|
static = Signal(bool())
|
|
|
code = Signal(intbv()[15:])
|
code = Signal(intbv()[15:])
|
lastToken = Signal(intbv()[15:])
|
lastToken = Signal(intbv()[15:])
|
howOften = Signal(intbv()[9:])
|
howOften = Signal(intbv()[9:])
|
|
|
cur_i = Signal(intbv()[LBSIZE:])
|
cur_i = Signal(intbv()[LMAX:])
|
spread_i = Signal(intbv()[9:])
|
spread_i = Signal(intbv()[9:])
|
cur_HF1 = Signal(intbv()[10:])
|
cur_HF1 = Signal(intbv()[MaxCodeLength+1:])
|
cur_static = Signal(intbv()[9:])
|
cur_static = Signal(intbv()[9:])
|
cur_cstatic = Signal(intbv()[LBSIZE:])
|
cur_cstatic = Signal(intbv()[LMAX:])
|
cur_search = Signal(intbv(min=-CWINDOW,max=IBSIZE))
|
# cur_search = Signal(intbv(min=-CWINDOW,max=IBSIZE))
|
|
cur_search = Signal(intbv(min=-1,max=1<<LMAX))
|
cur_dist = Signal(intbv(min=-CWINDOW,max=IBSIZE))
|
cur_dist = Signal(intbv(min=-CWINDOW,max=IBSIZE))
|
# cur_next = Signal(intbv()[5:])
|
cur_next = Signal(intbv()[4:])
|
cur_next = Signal(bool())
|
# cur_next = Signal(bool())
|
|
|
length = Signal(intbv()[LBSIZE:])
|
length = Signal(modbv()[LOBSIZE:])
|
offset = Signal(intbv()[LBSIZE:])
|
offset = Signal(intbv()[LOBSIZE:])
|
|
|
di = Signal(intbv()[LBSIZE:])
|
di = Signal(modbv()[LMAX:])
|
old_di = Signal(intbv()[LBSIZE:])
|
old_di = Signal(intbv()[LMAX:])
|
dio = Signal(intbv()[3:])
|
dio = Signal(intbv()[3:])
|
do = Signal(intbv()[LBSIZE:])
|
do = Signal(intbv()[LMAX:])
|
doo = Signal(intbv()[3:])
|
doo = Signal(intbv()[3:])
|
|
|
b1 = Signal(intbv()[8:])
|
b1 = Signal(intbv()[8:])
|
b2 = Signal(intbv()[8:])
|
b2 = Signal(intbv()[8:])
|
b3 = Signal(intbv()[8:])
|
b3 = Signal(intbv()[8:])
|
Line 161... |
Line 228... |
b41 = ConcatSignal(b4, b3, b2, b1)
|
b41 = ConcatSignal(b4, b3, b2, b1)
|
b41._markUsed()
|
b41._markUsed()
|
|
|
b14 = ConcatSignal(b1, b2, b3, b4)
|
b14 = ConcatSignal(b1, b2, b3, b4)
|
b14._markUsed()
|
b14._markUsed()
|
|
b15 = ConcatSignal(b1, b2, b3, b4, b5)
|
|
|
if MATCH10:
|
if MATCH10:
|
b6 = Signal(intbv()[8:])
|
b6 = Signal(intbv()[8:])
|
b7 = Signal(intbv()[8:])
|
b7 = Signal(intbv()[8:])
|
b8 = Signal(intbv()[8:])
|
b8 = Signal(intbv()[8:])
|
Line 200... |
Line 268... |
leaves[lwaddr].next = wleaf
|
leaves[lwaddr].next = wleaf
|
|
|
@always(clk.posedge)
|
@always(clk.posedge)
|
def oramread():
|
def oramread():
|
orbyte.next = oram[oraddr]
|
orbyte.next = oram[oraddr]
|
# rleaf.next = leaves[lraddr]
|
rleaf.next = leaves[lraddr]
|
|
|
@block
|
@block
|
def matcher3(o_m, mi):
|
def matcher3(o_m, mi):
|
@always_comb
|
@always_comb
|
def logic():
|
def logic():
|
Line 229... |
Line 297... |
b3.next = 0
|
b3.next = 0
|
b4.next = 0
|
b4.next = 0
|
old_di.next = 0
|
old_di.next = 0
|
else:
|
else:
|
if isize < 4:
|
if isize < 4:
|
pass
|
nb.next = 0
|
|
old_di.next = 0
|
elif i_mode == STARTC or i_mode == STARTD:
|
elif i_mode == STARTC or i_mode == STARTD:
|
nb.next = 0
|
nb.next = 0
|
old_di.next = 0
|
old_di.next = 0
|
else:
|
else:
|
"""
|
"""
|
if do_compress:
|
if do_compress:
|
print("FILL", di, old_di, nb, b1, b2, b3, b4)
|
print("FILL", di, old_di, nb, b1, b2, b3, b4)
|
"""
|
"""
|
if FAST: # and nb == 4:
|
if FAST: # and do_compress:
|
shift = (di - old_di) * 8
|
shift = (di - old_di) * 8
|
"""
|
"""
|
if shift != 0:
|
if shift != 0:
|
print("shift", shift, cwindow, b1, b2, b3, b4)
|
print("shift", shift, cwindow, b1, b2, b3, b4)
|
"""
|
"""
|
if shift <= 32:
|
if MATCH10:
|
cwindow.next = (cwindow << shift) | (b14 >> (32 - shift))
|
|
elif shift == 40:
|
|
cwindow.next = (cwindow << shift) | (b14 << 8) | b5
|
|
elif MATCH10:
|
|
cwindow.next = (cwindow << shift) | (b110 >> (80 - shift))
|
cwindow.next = (cwindow << shift) | (b110 >> (80 - shift))
|
|
else:
|
|
cwindow.next = (cwindow << shift) | (b15 >> (40 - shift))
|
|
|
if old_di == di:
|
if old_di == di:
|
nb.next = 4
|
nb.next = 4
|
# wtick.next = True
|
|
old_di.next = di
|
old_di.next = di
|
|
|
# iraddr.next = di
|
# print("B1", iram[di & IBS])
|
b1.next = iram[di & IBS]
|
b1.next = iram[di & IBS]
|
b2.next = iram[di+1 & IBS]
|
b2.next = iram[di+1 & IBS]
|
b3.next = iram[di+2 & IBS]
|
b3.next = iram[di+2 & IBS]
|
b4.next = iram[di+3 & IBS]
|
b4.next = iram[di+3 & IBS]
|
b5.next = iram[di+4 & IBS]
|
b5.next = iram[di+4 & IBS]
|
Line 268... |
Line 335... |
b6.next = iram[di+5 & IBS]
|
b6.next = iram[di+5 & IBS]
|
b7.next = iram[di+6 & IBS]
|
b7.next = iram[di+6 & IBS]
|
b8.next = iram[di+7 & IBS]
|
b8.next = iram[di+7 & IBS]
|
b9.next = iram[di+8 & IBS]
|
b9.next = iram[di+8 & IBS]
|
b10.next = iram[di+9 & IBS]
|
b10.next = iram[di+9 & IBS]
|
"""
|
|
@always(clk.posedge)
|
|
def fill_buf():
|
|
if not reset:
|
|
print("FILL RESET")
|
|
nb.next = 0
|
|
old_di.next = 0
|
|
b1.next = 0
|
|
b2.next = 0
|
|
b3.next = 0
|
|
b4.next = 0
|
|
else:
|
|
if isize < 4:
|
|
pass
|
|
elif i_mode == STARTC or i_mode == STARTD:
|
|
nb.next = 0
|
|
elif not filled and nb == 4 and di - old_di <= 4:
|
|
delta = di - old_di
|
|
if delta == 1:
|
|
# print("delta == 1")
|
|
if FAST:
|
|
cwindow.next = (cwindow << 8) | b1
|
|
b1.next = b2
|
|
b2.next = b3
|
|
b3.next = b4
|
|
b4.next = iram[di+3 & IBS]
|
|
# nb.next = 4
|
|
elif delta == 2:
|
|
print("delta == 2")
|
|
if FAST:
|
|
cwindow.next = (cwindow << 16) | (b14 >> 16)
|
|
b1.next = b3
|
|
b2.next = b4
|
|
b3.next = iram[di+2 & IBS]
|
|
nb.next = 3
|
|
elif delta == 3:
|
|
print("delta == 3")
|
|
if FAST:
|
|
cwindow.next = (cwindow << 24) | (b14 >> 8)
|
|
b1.next = b4
|
|
b2.next = iram[di+1 & IBS]
|
|
nb.next = 2
|
|
elif delta == 4:
|
|
print("delta == 4")
|
|
if FAST:
|
|
cwindow.next = (cwindow << 32) | (b14)
|
|
b1.next = iram[di & IBS]
|
|
nb.next = 1
|
|
else:
|
|
pass
|
|
elif not filled or nb == 0:
|
|
print("nb = 0")
|
|
b1.next = iram[di & IBS]
|
|
nb.next = 1
|
|
elif not filled or nb == 1:
|
|
print("nb = 1")
|
|
b2.next = iram[di+1 & IBS]
|
|
nb.next = 2
|
|
elif not filled or nb == 2:
|
|
print("nb = 2")
|
|
# raise Error("nb == 2")
|
|
b3.next = iram[di+2 & IBS]
|
|
nb.next = 3
|
|
elif not filled or nb == 3:
|
|
print("nb = 3")
|
|
b4.next = iram[di+3 & IBS]
|
|
nb.next = 4
|
|
else:
|
|
pass
|
|
old_di.next = di
|
|
"""
|
|
|
|
def get4(boffset, width):
|
def get4(boffset, width):
|
if nb != 4:
|
if nb != 4:
|
print("----NB----")
|
print("----NB----")
|
raise Error("NB")
|
raise Error("NB")
|
Line 401... |
Line 397... |
|
|
def rev_bits(b, nb):
|
def rev_bits(b, nb):
|
if b >= 1 << nb:
|
if b >= 1 << nb:
|
raise Error("too few bits")
|
raise Error("too few bits")
|
print("too few bits")
|
print("too few bits")
|
|
if nb > 15:
|
|
raise Error("nb too large")
|
r = (((b >> 14) & 0x1) << 0) | (((b >> 13) & 0x1) << 1) | \
|
r = (((b >> 14) & 0x1) << 0) | (((b >> 13) & 0x1) << 1) | \
|
(((b >> 12) & 0x1) << 2) | (((b >> 11) & 0x1) << 3) | \
|
(((b >> 12) & 0x1) << 2) | (((b >> 11) & 0x1) << 3) | \
|
(((b >> 10) & 0x1) << 4) | (((b >> 9) & 0x1) << 5) | \
|
(((b >> 10) & 0x1) << 4) | (((b >> 9) & 0x1) << 5) | \
|
(((b >> 8) & 0x1) << 6) | (((b >> 7) & 0x1) << 7) | \
|
(((b >> 8) & 0x1) << 6) | (((b >> 7) & 0x1) << 7) | \
|
(((b >> 6) & 0x1) << 8) | (((b >> 5) & 0x1) << 9) | \
|
(((b >> 6) & 0x1) << 8) | (((b >> 5) & 0x1) << 9) | \
|
Line 427... |
Line 425... |
def get_code(aleaf):
|
def get_code(aleaf):
|
return (aleaf >> BITBITS) # & ((1 << CODEBITS) - 1)
|
return (aleaf >> BITBITS) # & ((1 << CODEBITS) - 1)
|
|
|
@always(clk.posedge)
|
@always(clk.posedge)
|
def io_logic():
|
def io_logic():
|
|
o_byte.next = oram[i_raddr & OBS]
|
if i_mode == WRITE:
|
if i_mode == WRITE:
|
|
|
# print("WRITE:", i_addr, i_data)
|
# print("WRITE:", i_addr, i_data)
|
iram[i_addr & IBS].next = i_data
|
iram[i_waddr & IBS].next = i_data
|
isize.next = i_addr
|
isize.next = i_waddr
|
|
|
elif i_mode == READ:
|
|
|
|
# o_data.next = oram[i_addr]
|
|
# oraddr.next = i_addr
|
|
o_byte.next = oram[i_addr]
|
|
|
|
else:
|
|
pass
|
|
|
|
@always(clk.posedge)
|
@always(clk.posedge)
|
def logic():
|
def logic():
|
if not reset:
|
if not reset:
|
print("DEFLATE RESET")
|
print("DEFLATE RESET")
|
Line 470... |
Line 459... |
doo.next = 0
|
doo.next = 0
|
filled.next = True
|
filled.next = True
|
cur_static.next = 0
|
cur_static.next = 0
|
state.next = d_state.STATIC
|
state.next = d_state.STATIC
|
|
|
elif i_mode == STARTD:
|
elif DECOMPRESS and i_mode == STARTD:
|
|
|
do_compress.next = False
|
do_compress.next = False
|
o_done.next = False
|
o_done.next = False
|
o_iprogress.next = 0
|
o_iprogress.next = 0
|
o_oprogress.next = 0
|
o_oprogress.next = 0
|
Line 489... |
Line 478... |
else:
|
else:
|
pass
|
pass
|
|
|
elif state == d_state.HEADER:
|
elif state == d_state.HEADER:
|
|
|
if not filled:
|
if not DECOMPRESS:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
# Read block header
|
# Read block header
|
elif di == 0:
|
elif di == 0:
|
Line 514... |
Line 505... |
hm = get4(1, 2)
|
hm = get4(1, 2)
|
method.next = hm
|
method.next = hm
|
print("method", hm)
|
print("method", hm)
|
# print(di, dio, nb, b1, b2, b3, b4, hm, isize)
|
# print(di, dio, nb, b1, b2, b3, b4, hm, isize)
|
if hm == 2:
|
if hm == 2:
|
|
if not DYNAMIC:
|
|
print("dynamic tree mode disabled")
|
|
raise Error("dynamic tree mode disabled")
|
state.next = d_state.BL
|
state.next = d_state.BL
|
numCodeLength.next = 0
|
numCodeLength.next = 0
|
numLiterals.next = 0
|
numLiterals.next = 0
|
static.next = False
|
static.next = False
|
adv(3)
|
adv(3)
|
Line 568... |
Line 562... |
elif cur_cstatic == 2:
|
elif cur_cstatic == 2:
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = put(0x3, 3)
|
obyte.next = put(0x3, 3)
|
put_adv(0x3, 3)
|
put_adv(0x3, 3)
|
elif flush:
|
elif flush:
|
print("flush", do, ob1)
|
# print("flush", do, ob1)
|
no_adv = 1
|
no_adv = 1
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = ob1
|
obyte.next = ob1
|
do_flush()
|
do_flush()
|
|
elif cur_cstatic >= isize - 10 and i_mode != IDLE:
|
|
print("P", cur_cstatic, isize)
|
|
no_adv = 1
|
elif cur_cstatic - 3 > isize:
|
elif cur_cstatic - 3 > isize:
|
if cur_cstatic - 3 == isize + 1:
|
if cur_cstatic - 3 == isize + 1:
|
print("Put EOF", do)
|
print("Put EOF", do)
|
cs_i = EndOfBlock
|
cs_i = EndOfBlock
|
outlen = codeLength[cs_i]
|
outlen = codeLength[cs_i]
|
outbits = code_bits[cs_i]
|
outbits = out_codes[cs_i] # code_bits[cs_i]
|
print("EOF BITS:", cs_i, outlen, outbits)
|
print("EOF BITS:", cs_i, outlen, outbits)
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = put(outbits, outlen)
|
obyte.next = put(outbits, outlen)
|
put_adv(outbits, outlen)
|
put_adv(outbits, outlen)
|
elif cur_cstatic - 3 == isize + 2:
|
elif cur_cstatic - 3 == isize + 2:
|
Line 595... |
Line 592... |
elif cur_cstatic - 3 == isize + 3:
|
elif cur_cstatic - 3 == isize + 3:
|
print("c1")
|
print("c1")
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = adler2 >> 8
|
obyte.next = adler2 >> 8
|
do.next = do + 1
|
do.next = do + 1
|
|
o_oprogress.next = do + 1
|
elif cur_cstatic - 3 == isize + 4:
|
elif cur_cstatic - 3 == isize + 4:
|
print("c2")
|
print("c2")
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = adler2 & 0xFF
|
obyte.next = adler2 & 0xFF
|
do.next = do + 1
|
do.next = do + 1
|
|
o_oprogress.next = do + 1
|
elif cur_cstatic - 3 == isize + 5:
|
elif cur_cstatic - 3 == isize + 5:
|
print("c3")
|
print("c3")
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = adler1 >> 8
|
obyte.next = adler1 >> 8
|
do.next = do + 1
|
do.next = do + 1
|
|
o_oprogress.next = do + 1
|
elif cur_cstatic - 3 == isize + 6:
|
elif cur_cstatic - 3 == isize + 6:
|
print("c4")
|
print("c4")
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = adler1 & 0xFF
|
obyte.next = adler1 & 0xFF
|
|
o_oprogress.next = do + 1
|
elif cur_cstatic - 3 == isize + 7:
|
elif cur_cstatic - 3 == isize + 7:
|
print("EOF finish", do)
|
print("EOF finish", do)
|
o_done.next = True
|
o_done.next = True
|
o_oprogress.next = do + 1
|
|
state.next = d_state.IDLE
|
state.next = d_state.IDLE
|
else:
|
else:
|
print(cur_cstatic, isize)
|
print(cur_cstatic, isize)
|
raise Error("???")
|
raise Error("???")
|
else:
|
else:
|
bdata = iram[di]
|
bdata = iram[di & IBS]
|
# Fix this when > 1 byte output:
|
o_iprogress.next = di # & IBS
|
# print("cs1", bdata)
|
|
adler1_next = (adler1 + bdata) % 65521
|
adler1_next = (adler1 + bdata) % 65521
|
adler1.next = adler1_next
|
adler1.next = adler1_next
|
adler2.next = (adler2 + ladler1) % 65521
|
adler2.next = (adler2 + ladler1) % 65521
|
ladler1.next = adler1_next
|
ladler1.next = adler1_next
|
# print("in: ", bdata, di, isize)
|
# print("in: ", bdata, di, isize)
|
state.next = d_state.SEARCH
|
state.next = d_state.SEARCH
|
cur_search.next = di - 1
|
cur_search.next = di - 1 # & IBS
|
|
|
if not no_adv:
|
if not no_adv:
|
cur_cstatic.next = cur_cstatic + 1
|
cur_cstatic.next = cur_cstatic + 1
|
|
|
elif state == d_state.DISTANCE:
|
elif state == d_state.DISTANCE:
|
|
|
if not COMPRESS:
|
if not COMPRESS:
|
pass
|
pass
|
elif flush:
|
elif flush:
|
do_flush()
|
do_flush()
|
|
elif cur_i == 1024:
|
|
lencode = length + 254
|
|
# print("fast:", distance, di, isize, match)
|
|
outlen = codeLength[lencode]
|
|
outbits = out_codes[lencode] # code_bits[lencode]
|
|
# print("BITS:", outlen, outbits)
|
|
oaddr.next = do
|
|
obyte.next = put(outbits, outlen)
|
|
put_adv(outbits, outlen)
|
|
cur_i.next = 0
|
else:
|
else:
|
# print("DISTANCE", di, do, cur_i, cur_dist)
|
# print("DISTANCE", di, do, cur_i, cur_dist)
|
nextdist = CopyDistance[cur_i+1]
|
nextdist = CopyDistance[cur_i+1]
|
if nextdist > cur_dist:
|
if nextdist > cur_dist:
|
copydist = CopyDistance[cur_i]
|
copydist = CopyDistance[cur_i]
|
Line 677... |
Line 686... |
ladler1.next = adler1_next
|
ladler1.next = adler1_next
|
cur_i.next = cur_i.next + 1
|
cur_i.next = cur_i.next + 1
|
else:
|
else:
|
state.next = d_state.CSTATIC
|
state.next = d_state.CSTATIC
|
|
|
elif state == d_state.SEARCH:
|
elif state == d_state.SEARCHF:
|
|
|
if not COMPRESS:
|
if FAST and COMPRESS:
|
pass
|
lfmatch = length
|
elif not filled:
|
distance = lfmatch + 1
|
filled.next = True
|
|
elif nb < 4:
|
|
pass
|
|
else:
|
|
if cur_search >= 0 \
|
|
and cur_search >= di - CWINDOW \
|
|
and di < isize - 3:
|
|
|
|
if FAST:
|
|
found = 0
|
|
fmatch = 0
|
|
for si in range(CWINDOW):
|
|
# print("test", di, si, di - si - 1)
|
|
if smatch[si]:
|
|
print("fmatch", si)
|
|
fmatch = si
|
|
found = 1
|
|
break
|
|
if not found or di - fmatch - 1 < 0:
|
|
cur_search.next = -1
|
|
# print("NO FSEARCH")
|
|
else:
|
|
distance = fmatch + 1
|
|
# print("FSEARCH", distance)
|
# print("FSEARCH", distance)
|
fmatch = di - fmatch + 2
|
fmatch2 = di - lfmatch + 2
|
# Length is 3 code
|
# Length is 3 code
|
lencode = 257
|
lencode = 257
|
match = 3
|
match = 3
|
|
|
if di < isize - 4 and \
|
if di < isize - 4 and \
|
iram[fmatch & IBS] == b4:
|
iram[fmatch2 & IBS] == b4:
|
lencode = 258
|
lencode = 258
|
match = 4
|
match = 4
|
if di < isize - 5 and \
|
if di < isize - 5 and \
|
iram[fmatch+1 & IBS] == b5:
|
iram[fmatch2+1 & IBS] == b5:
|
lencode = 259
|
lencode = 259
|
match = 5
|
match = 5
|
if MATCH10 and di < isize - 6 and \
|
if MATCH10 and di < isize - 6 and \
|
iram[fmatch+2 & IBS] == b6:
|
iram[fmatch2+2 & IBS] == b6:
|
lencode = 260
|
lencode = 260
|
match = 6
|
match = 6
|
if di < isize - 7 and \
|
if di < isize - 7 and \
|
iram[fmatch+3 & IBS] == b7:
|
iram[fmatch2+3 & IBS] == b7:
|
lencode = 261
|
lencode = 261
|
match = 7
|
match = 7
|
if di < isize - 8 and \
|
if di < isize - 8 and \
|
iram[fmatch+4 & IBS] == b8:
|
iram[fmatch2+4 & IBS] == b8:
|
lencode = 262
|
lencode = 262
|
match = 8
|
match = 8
|
if di < isize - 9 and \
|
if di < isize - 9 and \
|
iram[fmatch+5 & IBS] == b9:
|
iram[fmatch2+5 & IBS] == b9:
|
lencode = 263
|
lencode = 263
|
match = 9
|
match = 9
|
if di < isize - 10 and \
|
if di < isize - 10 and \
|
iram[fmatch+6 & IBS] == b10:
|
iram[fmatch2+6 & IBS] == b10:
|
lencode = 264
|
lencode = 264
|
match = 10
|
match = 10
|
|
|
print("fast:", distance, di, isize, match)
|
|
outlen = codeLength[lencode]
|
|
outbits = code_bits[lencode]
|
|
# print("BITS:", outlen, outbits)
|
|
oaddr.next = do
|
|
obyte.next = put(outbits, outlen)
|
|
put_adv(outbits, outlen)
|
|
|
|
# distance = di - cur_search
|
# distance = di - cur_search
|
# print("distance", distance)
|
# print("d/l", di, distance, match)
|
cur_dist.next = distance
|
cur_dist.next = distance
|
cur_i.next = 0
|
cur_i.next = 1024
|
# adv(match * 8)
|
# adv(match * 8)
|
di.next = di + match
|
di.next = di + match
|
cur_cstatic.next = cur_cstatic + match - 1
|
cur_cstatic.next = cur_cstatic + match - 1
|
length.next = match
|
length.next = match
|
state.next = d_state.DISTANCE
|
state.next = d_state.DISTANCE
|
|
|
elif iram[cur_search & IBS] == b1 and \
|
elif state == d_state.SEARCH:
|
|
|
|
if not COMPRESS:
|
|
pass
|
|
elif not filled:
|
|
filled.next = True
|
|
elif nb < 4:
|
|
pass
|
|
else:
|
|
# print("cs", cur_search, di, di - CWINDOW)
|
|
if cur_search >= 0 \
|
|
and cur_search >= di - CWINDOW \
|
|
and di < isize - 3:
|
|
|
|
if FAST:
|
|
found = 0
|
|
fmatch = 0
|
|
for si in range(CWINDOW):
|
|
# print("test", di, si, di - si - 1)
|
|
if smatch[si]:
|
|
# print("fmatch", si)
|
|
fmatch = si
|
|
found = 1
|
|
break
|
|
if not found or di - fmatch - 1 < 0:
|
|
cur_search.next = -1
|
|
# print("NO FSEARCH")
|
|
else:
|
|
length.next = fmatch
|
|
state.next = d_state.SEARCHF
|
|
|
|
elif not FAST and iram[cur_search & IBS] == b1 and \
|
iram[cur_search+1 & IBS] == b2 and \
|
iram[cur_search+1 & IBS] == b2 and \
|
iram[cur_search+2 & IBS] == b3:
|
iram[cur_search+2 & IBS] == b3:
|
# Length is 3 code
|
# Length is 3 code
|
lencode = 257
|
lencode = 257
|
match = 3
|
match = 3
|
Line 770... |
Line 779... |
if di < isize - 4 and \
|
if di < isize - 4 and \
|
iram[cur_search+3 & IBS] == b4: # iram[di + 3 & IBS]:
|
iram[cur_search+3 & IBS] == b4: # iram[di + 3 & IBS]:
|
lencode = 258
|
lencode = 258
|
match = 4
|
match = 4
|
if di < isize - 5 and \
|
if di < isize - 5 and \
|
iram[cur_search+4 & IBS] == iram[di + 4 & IBS]:
|
iram[cur_search+4 & IBS] == b5:
|
lencode = 259
|
lencode = 259
|
match = 5
|
match = 5
|
if MATCH10 and di < isize - 6 and \
|
if MATCH10 and di < isize - 6 and \
|
iram[cur_search+5 & IBS] == iram[di + 5 & IBS]:
|
iram[cur_search+5 & IBS] == b6:
|
lencode = 260
|
lencode = 260
|
match = 6
|
match = 6
|
if di < isize - 7 and \
|
if di < isize - 7 and \
|
iram[cur_search+6 & IBS] == iram[di + 6 & IBS]:
|
iram[cur_search+6 & IBS] == b7:
|
lencode = 261
|
lencode = 261
|
match = 7
|
match = 7
|
if di < isize - 8 and \
|
if di < isize - 8 and \
|
iram[cur_search+7 & IBS] == iram[di + 7 & IBS]:
|
iram[cur_search+7 & IBS] == b8:
|
lencode = 262
|
lencode = 262
|
match = 8
|
match = 8
|
if di < isize - 9 and \
|
if di < isize - 9 and \
|
iram[cur_search+8 & IBS] == iram[di + 8 & IBS]:
|
iram[cur_search+8 & IBS] == b9:
|
lencode = 263
|
lencode = 263
|
match = 9
|
match = 9
|
if di < isize - 10 and \
|
if di < isize - 10 and \
|
iram[cur_search+9 & IBS] == iram[di + 9 & IBS]:
|
iram[cur_search+9 & IBS] == b10:
|
lencode = 264
|
lencode = 264
|
match = 10
|
match = 10
|
|
|
print("found:", cur_search, di, isize, match)
|
|
outlen = codeLength[lencode]
|
|
outbits = code_bits[lencode]
|
|
# print("BITS:", outlen, outbits)
|
|
oaddr.next = do
|
|
obyte.next = put(outbits, outlen)
|
|
put_adv(outbits, outlen)
|
|
|
|
distance = di - cur_search
|
distance = di - cur_search
|
# print("distance", distance)
|
# print("distance", distance)
|
cur_dist.next = distance
|
cur_dist.next = distance
|
cur_i.next = 0
|
cur_i.next = 1024 # 0
|
# adv(match * 8)
|
# adv(match * 8)
|
di.next = di + match
|
di.next = di + match
|
cur_cstatic.next = cur_cstatic + match - 1
|
cur_cstatic.next = cur_cstatic + match - 1
|
length.next = match
|
length.next = match
|
state.next = d_state.DISTANCE
|
state.next = d_state.DISTANCE
|
else:
|
else:
|
cur_search.next = cur_search - 1
|
cur_search.next = cur_search - 1
|
else:
|
else:
|
# print("NO MATCH")
|
# print("NO MATCH")
|
bdata = iram[di]
|
bdata = b1 # iram[di]
|
# adv(8)
|
# adv(8)
|
di.next = di + 1
|
di.next = di + 1
|
outlen = codeLength[bdata]
|
outlen = codeLength[bdata]
|
outbits = code_bits[bdata]
|
outbits = out_codes[bdata] # code_bits[bdata]
|
# print("CBITS:", bdata, outlen, outbits)
|
# print("CBITS:", bdata, outlen, outbits)
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = put(outbits, outlen)
|
obyte.next = put(outbits, outlen)
|
put_adv(outbits, outlen)
|
put_adv(outbits, outlen)
|
state.next = d_state.CSTATIC
|
state.next = d_state.CSTATIC
|
Line 837... |
Line 838... |
for stat_i in range(256, 280):
|
for stat_i in range(256, 280):
|
codeLength[stat_i].next = 7
|
codeLength[stat_i].next = 7
|
for stat_i in range(280, 288):
|
for stat_i in range(280, 288):
|
codeLength[stat_i].next = 8
|
codeLength[stat_i].next = 8
|
numCodeLength.next = 288
|
numCodeLength.next = 288
|
|
if do_compress:
|
|
state.next = d_state.CSTATIC
|
|
else:
|
cur_HF1.next = 0
|
cur_HF1.next = 0
|
state.next = d_state.HF1
|
state.next = d_state.HF1
|
"""
|
|
if cur_static < 288:
|
|
if cur_static < 144:
|
|
codeLength[cur_static].next = 8
|
|
elif cur_static < 256:
|
|
codeLength[cur_static].next = 9
|
|
elif cur_static < 280:
|
|
codeLength[cur_static].next = 7
|
|
else:
|
|
codeLength[cur_static].next = 8
|
|
cur_static.next = cur_static + 1
|
|
else:
|
|
numCodeLength.next = 288
|
|
cur_HF1.next = 0
|
|
state.next = d_state.HF1
|
|
"""
|
|
|
|
elif state == d_state.BL:
|
elif state == d_state.BL:
|
|
|
if not filled:
|
if not DECOMPRESS or not DYNAMIC:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
elif numLiterals == 0:
|
elif numLiterals == 0:
|
|
print(di, isize)
|
numLiterals.next = 257 + get4(0, 5)
|
numLiterals.next = 257 + get4(0, 5)
|
print("NL:", 257 + get4(0, 5))
|
print("NL:", 257 + get4(0, 5))
|
numDistance.next = 1 + get4(5, 5)
|
numDistance.next = 1 + get4(5, 5)
|
print("ND:", 1 + get4(5, 5))
|
print("ND:", 1 + get4(5, 5))
|
b_numCodeLength.next = 4 + get4(10, 4)
|
b_numCodeLength.next = 4 + get4(10, 4)
|
Line 889... |
Line 880... |
cur_HF1.next = 0
|
cur_HF1.next = 0
|
state.next = d_state.HF1
|
state.next = d_state.HF1
|
|
|
elif state == d_state.READBL:
|
elif state == d_state.READBL:
|
|
|
if not filled:
|
if not DECOMPRESS or not DYNAMIC:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
elif numCodeLength < numLiterals + numDistance:
|
elif numCodeLength < numLiterals + numDistance:
|
# print(numLiterals + numDistance, numCodeLength)
|
# print(numLiterals + numDistance, numCodeLength)
|
Line 935... |
Line 928... |
cur_i.next = numLiterals
|
cur_i.next = numLiterals
|
state.next = d_state.INIT3
|
state.next = d_state.INIT3
|
|
|
elif state == d_state.INIT3:
|
elif state == d_state.INIT3:
|
|
|
if cur_i < MaxBitLength:
|
if not DECOMPRESS:
|
|
pass
|
|
elif cur_i < len(codeLength): # MaxBitLength:
|
codeLength[cur_i].next = 0
|
codeLength[cur_i].next = 0
|
cur_i.next = cur_i + 1
|
cur_i.next = cur_i + 1
|
else:
|
else:
|
numCodeLength.next = MaxBitLength
|
# numCodeLength.next = MaxBitLength
|
method.next = 3 # Start building bit tree
|
method.next = 3 # Start building bit tree
|
cur_HF1.next = 0
|
cur_HF1.next = 0
|
state.next = d_state.HF1
|
state.next = d_state.HF1
|
|
|
elif state == d_state.DISTTREE:
|
elif state == d_state.DISTTREE:
|
|
|
|
if DECOMPRESS and DYNAMIC:
|
print("DISTTREE")
|
print("DISTTREE")
|
for dist_i in range(32):
|
for dist_i in range(32):
|
codeLength[dist_i].next = distanceLength[dist_i]
|
codeLength[dist_i].next = distanceLength[dist_i]
|
# print(dist_i, distanceLength[dist_i])
|
# print(dist_i, distanceLength[dist_i])
|
numCodeLength.next = 32
|
numCodeLength.next = 32
|
method.next = 4 # Start building dist tree
|
method.next = 4 # Start building dist tree
|
# cur_i.next = 0
|
|
cur_HF1.next = 0
|
cur_HF1.next = 0
|
state.next = d_state.HF1
|
state.next = d_state.HF1
|
|
|
elif state == d_state.REPEAT:
|
elif state == d_state.REPEAT:
|
|
|
# print("HOWOFTEN: ", numCodeLength, howOften)
|
if not DECOMPRESS:
|
if howOften != 0:
|
pass
|
|
elif howOften != 0:
|
codeLength[numCodeLength].next = lastToken
|
codeLength[numCodeLength].next = lastToken
|
howOften.next = howOften - 1
|
howOften.next = howOften - 1
|
numCodeLength.next = numCodeLength + 1
|
numCodeLength.next = numCodeLength + 1
|
elif numCodeLength < numLiterals + numDistance:
|
elif numCodeLength < numLiterals + numDistance:
|
cur_next.next = 0
|
cur_next.next = 0
|
Line 971... |
Line 967... |
else:
|
else:
|
state.next = d_state.READBL
|
state.next = d_state.READBL
|
|
|
elif state == d_state.HF1:
|
elif state == d_state.HF1:
|
|
|
|
if DECOMPRESS:
|
if cur_HF1 < len(bitLengthCount):
|
if cur_HF1 < len(bitLengthCount):
|
bitLengthCount[cur_HF1].next = 0
|
bitLengthCount[cur_HF1].next = 0
|
if cur_HF1 < len(d_leaves):
|
if cur_HF1 < len(d_leaves) and DYNAMIC:
|
d_leaves[cur_HF1].next = 0
|
d_leaves[cur_HF1].next = 0
|
if method != 4 and cur_HF1 < len(leaves):
|
if method != 4 and cur_HF1 < len(leaves):
|
lwaddr.next = cur_HF1
|
lwaddr.next = cur_HF1
|
wleaf.next = 0
|
wleaf.next = 0
|
# leaves[cur_HF1].next = 0
|
# leaves[cur_HF1].next = 0
|
limit = len(leaves)
|
limit = len(leaves)
|
if method == 4:
|
if method == 4 and DYNAMIC:
|
limit = len(d_leaves)
|
limit = len(d_leaves)
|
if cur_HF1 < limit:
|
if cur_HF1 < limit:
|
cur_HF1.next = cur_HF1 + 1
|
cur_HF1.next = cur_HF1 + 1
|
else:
|
else:
|
print("DID HF1 INIT")
|
print("DID HF1 INIT")
|
Line 993... |
Line 990... |
|
|
elif state == d_state.HF1INIT:
|
elif state == d_state.HF1INIT:
|
# get frequencies of each bit length and ignore 0's
|
# get frequencies of each bit length and ignore 0's
|
|
|
# print("HF1")
|
# print("HF1")
|
if cur_i < numCodeLength:
|
if not DECOMPRESS:
|
|
pass
|
|
elif cur_i < numCodeLength:
|
j = codeLength[cur_i]
|
j = codeLength[cur_i]
|
bitLengthCount[j].next = bitLengthCount[j] + 1
|
bitLengthCount[j].next = bitLengthCount[j] + 1
|
# print(cur_i, j, bitLengthCount[j] + 1)
|
# print(cur_i, j, bitLengthCount[j] + 1)
|
cur_i.next = cur_i + 1
|
cur_i.next = cur_i + 1
|
else:
|
else:
|
Line 1012... |
Line 1011... |
|
|
elif state == d_state.HF2:
|
elif state == d_state.HF2:
|
# shortest and longest codes
|
# shortest and longest codes
|
|
|
# print("HF2")
|
# print("HF2")
|
if cur_i <= MaxCodeLength:
|
if not DECOMPRESS:
|
|
pass
|
|
elif cur_i <= MaxCodeLength:
|
if bitLengthCount[cur_i] != 0:
|
if bitLengthCount[cur_i] != 0:
|
if cur_i < minBits:
|
if cur_i < minBits:
|
minBits.next = cur_i
|
minBits.next = cur_i
|
if method == 4:
|
if method == 4:
|
if cur_i > d_maxBits:
|
if cur_i > d_maxBits:
|
Line 1026... |
Line 1027... |
maxBits.next = cur_i
|
maxBits.next = cur_i
|
cur_i.next = cur_i + 1
|
cur_i.next = cur_i + 1
|
else:
|
else:
|
print(minBits, maxBits)
|
print(minBits, maxBits)
|
t = InstantMaxBit
|
t = InstantMaxBit
|
if method == 4:
|
if method == 4 and DYNAMIC:
|
if t > int(d_maxBits):
|
if t > int(d_maxBits):
|
t = int(d_maxBits)
|
t = int(d_maxBits)
|
d_instantMaxBit.next = t
|
d_instantMaxBit.next = t
|
d_instantMask.next = (1 << t) - 1
|
d_instantMask.next = (1 << t) - 1
|
else:
|
else:
|
Line 1048... |
Line 1049... |
|
|
elif state == d_state.HF3:
|
elif state == d_state.HF3:
|
# find bit code for first element of each bitLength group
|
# find bit code for first element of each bitLength group
|
|
|
# print("HF3")
|
# print("HF3")
|
|
if DECOMPRESS:
|
amb = maxBits
|
amb = maxBits
|
if method == 4:
|
if method == 4 and DYNAMIC:
|
amb = d_maxBits
|
amb = d_maxBits
|
if cur_i <= amb:
|
if cur_i <= amb:
|
ncode = ((code + bitLengthCount[cur_i - 1]) << 1)
|
ncode = ((code + bitLengthCount[cur_i - 1]) << 1)
|
code.next = ncode
|
code.next = ncode
|
nextCode[cur_i].next = ncode
|
nextCode[cur_i].next = ncode
|
Line 1065... |
Line 1067... |
spread_i.next = 0
|
spread_i.next = 0
|
print("to HF4")
|
print("to HF4")
|
|
|
elif state == d_state.HF4_2:
|
elif state == d_state.HF4_2:
|
|
|
|
if DECOMPRESS:
|
canonical = nextCode[bits]
|
canonical = nextCode[bits]
|
nextCode[bits].next = nextCode[bits] + 1
|
nextCode[bits].next = nextCode[bits] + 1
|
if bits > MaxCodeLength:
|
if bits > MaxCodeLength:
|
raise Error("too many bits: %d" % bits)
|
raise Error("too many bits: %d" % bits)
|
# print(canonical, bits)
|
# print(canonical, bits)
|
Line 1077... |
Line 1080... |
leaf.next = makeLeaf(spread_i, bits)
|
leaf.next = makeLeaf(spread_i, bits)
|
state.next = d_state.HF4_3
|
state.next = d_state.HF4_3
|
|
|
elif state == d_state.HF4_3:
|
elif state == d_state.HF4_3:
|
|
|
if method == 4:
|
if not DECOMPRESS:
|
|
pass
|
|
elif method == 4 and DYNAMIC:
|
d_leaves[reverse].next = leaf # makeLeaf(spread_i, bits)
|
d_leaves[reverse].next = leaf # makeLeaf(spread_i, bits)
|
if bits <= d_instantMaxBit:
|
if bits <= d_instantMaxBit:
|
if reverse + (1 << bits) <= d_instantMask:
|
if reverse + (1 << bits) <= d_instantMask:
|
step.next = 1 << bits
|
step.next = 1 << bits
|
spread.next = reverse + (1 << bits)
|
spread.next = reverse + (1 << bits)
|
Line 1094... |
Line 1099... |
spread_i.next = spread_i + 1
|
spread_i.next = spread_i + 1
|
else:
|
else:
|
wleaf.next = leaf
|
wleaf.next = leaf
|
lwaddr.next = reverse
|
lwaddr.next = reverse
|
# leaves[reverse].next = leaf # makeLeaf(spread_i, bits)
|
# leaves[reverse].next = leaf # makeLeaf(spread_i, bits)
|
code_bits[spread_i].next = reverse
|
# code_bits[spread_i].next = reverse
|
if bits <= instantMaxBit:
|
if bits <= instantMaxBit:
|
if reverse + (1 << bits) <= instantMask:
|
if reverse + (1 << bits) <= instantMask:
|
step.next = 1 << bits
|
step.next = 1 << bits
|
spread.next = reverse + (1 << bits)
|
spread.next = reverse + (1 << bits)
|
state.next = d_state.SPREAD
|
state.next = d_state.SPREAD
|
Line 1110... |
Line 1115... |
state.next = d_state.HF4
|
state.next = d_state.HF4
|
|
|
elif state == d_state.HF4:
|
elif state == d_state.HF4:
|
# create binary codes for each literal
|
# create binary codes for each literal
|
|
|
if spread_i < numCodeLength:
|
if not DECOMPRESS:
|
|
pass
|
|
elif spread_i < numCodeLength:
|
bits_next = codeLength[spread_i]
|
bits_next = codeLength[spread_i]
|
if bits_next != 0:
|
if bits_next != 0:
|
bits.next = bits_next
|
bits.next = bits_next
|
state.next = d_state.HF4_2
|
state.next = d_state.HF4_2
|
else:
|
else:
|
|
# print("SKIP UNUSED")
|
spread_i.next = spread_i + 1
|
spread_i.next = spread_i + 1
|
else:
|
else:
|
if do_compress:
|
if do_compress:
|
state.next = d_state.CSTATIC
|
state.next = d_state.CSTATIC
|
cur_cstatic.next = 0
|
cur_cstatic.next = 0
|
elif method == 3:
|
elif method == 3 and DYNAMIC:
|
state.next = d_state.DISTTREE
|
state.next = d_state.DISTTREE
|
elif method == 4:
|
elif method == 4 and DYNAMIC:
|
print("DEFLATE m2!")
|
print("DEFLATE m2!")
|
state.next = d_state.NEXT
|
state.next = d_state.NEXT
|
elif method == 2:
|
elif method == 2 and DYNAMIC:
|
numCodeLength.next = 0
|
numCodeLength.next = 0
|
state.next = d_state.NEXT
|
state.next = d_state.NEXT
|
else:
|
else:
|
state.next = d_state.NEXT
|
state.next = d_state.NEXT
|
cur_next.next = 0
|
cur_next.next = 0
|
cur_i.next = 0
|
cur_i.next = 0
|
|
|
elif state == d_state.SPREAD:
|
elif state == d_state.SPREAD:
|
|
|
if method == 4:
|
if DECOMPRESS:
|
|
if method == 4 and DYNAMIC:
|
# print(spread, spread_i)
|
# print(spread, spread_i)
|
d_leaves[spread].next = makeLeaf(
|
d_leaves[spread].next = makeLeaf(
|
spread_i, codeLength[spread_i])
|
spread_i, codeLength[spread_i])
|
else:
|
else:
|
lwaddr.next = spread
|
lwaddr.next = spread
|
wleaf.next = makeLeaf(spread_i, codeLength[spread_i])
|
wleaf.next = makeLeaf(spread_i, codeLength[spread_i])
|
# leaves[spread].next = makeLeaf(spread_i, codeLength[spread_i])
|
# leaves[spread].next = makeLeaf(spread_i, codeLength[spread_i])
|
# print("SPREAD:", spread, step, instantMask)
|
# print("SPREAD:", spread, step, instantMask)
|
aim = instantMask
|
aim = instantMask
|
if method == 4:
|
if method == 4 and DYNAMIC:
|
aim = d_instantMask
|
aim = d_instantMask
|
if spread > aim - step:
|
if spread > aim - step:
|
spread_i.next = spread_i + 1
|
spread_i.next = spread_i + 1
|
state.next = d_state.HF4
|
state.next = d_state.HF4
|
else:
|
else:
|
spread.next = spread + step
|
spread.next = spread + step
|
|
|
elif state == d_state.NEXT:
|
elif state == d_state.NEXT:
|
|
|
if not filled:
|
if not DECOMPRESS:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
elif cur_next == 0:
|
elif cur_next == 0:
|
# print("INIT:", di, dio, instantMaxBit, maxBits)
|
# print("INIT:", di, dio, instantMaxBit, maxBits)
|
cto = get4(0, maxBits)
|
cto = get4(0, maxBits)
|
cur_next.next = 1 # instantMaxBit
|
|
mask = (1 << instantMaxBit) - 1
|
mask = (1 << instantMaxBit) - 1
|
# lraddr.next = (cto & mask)
|
lraddr.next = (cto & mask)
|
leaf.next = leaves[cto & mask]
|
# leaf.next = leaves[cto & mask]
|
|
filled.next = False
|
|
cur_next.next = instantMaxBit + 1
|
# print(cur_next, mask, leaf, maxBits)
|
# print(cur_next, mask, leaf, maxBits)
|
|
# elif get_bits(leaf) >= cur_next:
|
|
elif get_bits(rleaf) >= cur_next:
|
|
print("CACHE MISS", cur_next)
|
|
cto = get4(0, maxBits)
|
|
mask = (1 << cur_next) - 1
|
|
lraddr.next = (cto & mask)
|
|
# leaf.next = leaves[cto & mask]
|
|
filled.next = False
|
|
cur_next.next = cur_next + 1
|
else:
|
else:
|
if get_bits(leaf) < 1:
|
# if get_bits(leaf) < 1:
|
|
if get_bits(rleaf) < 1:
|
print("< 1 bits: ")
|
print("< 1 bits: ")
|
raise Error("< 1 bits: ")
|
raise Error("< 1 bits: ")
|
adv(get_bits(leaf))
|
#adv(get_bits(leaf))
|
if get_code(leaf) == 0:
|
adv(get_bits(rleaf))
|
print("leaf 0")
|
"""
|
code.next = get_code(leaf)
|
if get_code(leaf) == 0:
|
|
print("leaf 0", di, isize)
|
|
"""
|
|
#code.next = get_code(leaf)
|
|
code.next = get_code(rleaf)
|
# print("ADV:", di, get_bits(leaf), get_code(leaf))
|
# print("ADV:", di, get_bits(leaf), get_code(leaf))
|
if method == 2:
|
if method == 2 and DYNAMIC:
|
state.next = d_state.READBL
|
state.next = d_state.READBL
|
else:
|
else:
|
state.next = d_state.INFLATE
|
state.next = d_state.INFLATE
|
|
|
elif state == d_state.D_NEXT:
|
elif state == d_state.D_NEXT:
|
|
|
if not filled:
|
if not DECOMPRESS or not DYNAMIC:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
else:
|
elif cur_next == 0:
|
# print("D_INIT:", di, dio, d_instantMaxBit, d_maxBits)
|
# print("D_INIT:", di, dio, d_instantMaxBit, d_maxBits)
|
|
if d_instantMaxBit > InstantMaxBit:
|
|
raise Error("???")
|
token = code - 257
|
token = code - 257
|
# print("token: ", token)
|
# print("token: ", token)
|
extraLength = ExtraLengthBits[token]
|
extraLength = ExtraLengthBits[token]
|
# print("extra length bits:", extraLength)
|
# print("extra length bits:", extraLength)
|
|
# print("d_maxBits", d_maxBits, d_instantMaxBit)
|
cto = get4(extraLength, d_maxBits)
|
cto = get4(extraLength, d_maxBits)
|
mask = (1 << d_instantMaxBit) - 1
|
mask = (1 << d_instantMaxBit) - 1
|
leaf.next = d_leaves[cto & mask]
|
leaf.next = d_leaves[cto & mask]
|
|
# state.next = d_state.D_NEXT_2
|
|
cur_next.next = instantMaxBit + 1
|
|
elif get_bits(leaf) >= cur_next:
|
|
print("DCACHE MISS", cur_next)
|
|
token = code - 257
|
|
# print("token: ", token)
|
|
extraLength = ExtraLengthBits[token]
|
|
cto = get4(extraLength, d_maxBits)
|
|
mask = (1 << cur_next) - 1
|
|
leaf.next = d_leaves[cto & mask]
|
|
cur_next.next = cur_next + 1
|
|
else:
|
state.next = d_state.D_NEXT_2
|
state.next = d_state.D_NEXT_2
|
|
|
elif state == d_state.D_NEXT_2:
|
elif state == d_state.D_NEXT_2:
|
|
|
|
if DECOMPRESS and DYNAMIC:
|
if get_bits(leaf) == 0:
|
if get_bits(leaf) == 0:
|
raise Error("0 bits")
|
raise Error("0 bits")
|
token = code - 257
|
token = code - 257
|
# print("E2:", token, leaf)
|
# print("E2:", token, leaf)
|
tlength = CopyLength[token]
|
tlength = CopyLength[token]
|
Line 1221... |
Line 1265... |
# print("more bits:", moreBits)
|
# print("more bits:", moreBits)
|
# print("bits:", get_bits(leaf))
|
# print("bits:", get_bits(leaf))
|
mored = get4(extraLength + get_bits(leaf), moreBits)
|
mored = get4(extraLength + get_bits(leaf), moreBits)
|
# print("mored:", mored)
|
# print("mored:", mored)
|
distance += mored
|
distance += mored
|
# print("distance more:", distance)
|
# print("distance more:", distance, do, di, isize)
|
|
if distance > do:
|
|
print(distance, do)
|
|
raise Error("distance too big")
|
adv(moreBits + extraLength + get_bits(leaf))
|
adv(moreBits + extraLength + get_bits(leaf))
|
# print("offset:", do - distance)
|
# print("offset:", do - distance)
|
# print("FAIL?: ", di, dio, do, b1, b2, b3, b4)
|
# print("FAIL?: ", di, dio, do, b1, b2, b3, b4)
|
offset.next = do - distance
|
offset.next = (do - distance) & OBS
|
length.next = tlength
|
length.next = tlength
|
# cur_next.next = 0
|
# cur_next.next = 0
|
cur_i.next = 0
|
cur_i.next = 0
|
oraddr.next = do - distance
|
oraddr.next = do - distance
|
state.next = d_state.COPY
|
state.next = d_state.COPY
|
|
|
elif state == d_state.INFLATE:
|
elif state == d_state.INFLATE:
|
|
|
if not filled:
|
if not DECOMPRESS:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4: # nb <= 2 or (nb == 3 and dio > 1):
|
elif nb < 4: # nb <= 2 or (nb == 3 and dio > 1):
|
# print("EXTRA FETCH", nb, dio)
|
# print("EXTRA FETCH", nb, dio)
|
pass # fetch more bytes
|
pass # fetch more bytes
|
elif di > isize: # - 3: # checksum is 4 bytes
|
elif di >= isize - 4 and not i_mode == IDLE:
|
|
pass # fetch more bytes
|
|
elif do >= i_raddr + OBSIZE: # - 10:
|
|
# print("HOLDB")
|
|
# filled.next = False
|
|
pass
|
|
elif di > isize - 3: # checksum is 4 bytes
|
state.next = d_state.IDLE
|
state.next = d_state.IDLE
|
o_done.next = True
|
o_done.next = True
|
print("NO EOF ", di)
|
print("NO EOF ", di)
|
raise Error("NO EOF!")
|
raise Error("NO EOF!")
|
elif code == EndOfBlock:
|
elif code == EndOfBlock:
|
print("EOF:", di, do)
|
print("EOF:", di, do)
|
if not final:
|
if not final:
|
state.next = d_state.HEADER
|
state.next = d_state.HEADER
|
|
filled.next = False
|
|
print("New Block!")
|
else:
|
else:
|
o_done.next = True
|
o_done.next = True
|
o_oprogress.next = do
|
|
state.next = d_state.IDLE
|
state.next = d_state.IDLE
|
else:
|
else:
|
if code < EndOfBlock:
|
if code < EndOfBlock:
|
# print("B:", code, di, do)
|
# print("B:", code, di, do)
|
oaddr.next = do
|
oaddr.next = do
|
Line 1291... |
Line 1347... |
length.next = tlength
|
length.next = tlength
|
cur_i.next = 0
|
cur_i.next = 0
|
oraddr.next = do - distance
|
oraddr.next = do - distance
|
state.next = d_state.COPY
|
state.next = d_state.COPY
|
else:
|
else:
|
# raise Error("TO DO")
|
if not DYNAMIC:
|
|
print("DYNAMIC mode disabled")
|
|
raise Error("DYNAMIC mode disabled")
|
state.next = d_state.D_NEXT
|
state.next = d_state.D_NEXT
|
cur_next.next = 0
|
cur_next.next = 0
|
|
|
elif state == d_state.COPY:
|
elif state == d_state.COPY:
|
|
|
if not filled:
|
if not DECOMPRESS:
|
|
pass
|
|
elif not filled:
|
filled.next = True
|
filled.next = True
|
elif nb < 4:
|
elif nb < 4:
|
pass
|
pass
|
|
elif cur_i == 0 and do + length >= i_raddr + OBSIZE: # - 10:
|
|
# print("HOLDW", length, offset, cur_i, do, i_raddr)
|
|
pass
|
|
elif di >= isize - 2:
|
|
# print("HOLD2")
|
|
pass
|
elif method == 0:
|
elif method == 0:
|
if cur_i < length:
|
if cur_i < length:
|
oaddr.next = do
|
oaddr.next = do
|
obyte.next = b3
|
obyte.next = b3
|
adv(8)
|
adv(8)
|
cur_i.next = cur_i + 1
|
cur_i.next = cur_i + 1
|
do.next = do + 1
|
do.next = do + 1
|
o_oprogress.next = do + 1
|
o_oprogress.next = do + 1
|
elif not final:
|
elif not final:
|
|
adv(16)
|
state.next = d_state.HEADER
|
state.next = d_state.HEADER
|
|
filled.next = False
|
|
print("new block")
|
else:
|
else:
|
o_oprogress.next = do # + 1
|
|
o_done.next = True
|
o_done.next = True
|
state.next = d_state.IDLE
|
state.next = d_state.IDLE
|
elif cur_i < length + 2:
|
elif cur_i < length + 2:
|
|
# print("L/O", length, offset)
|
oraddr.next = offset + cur_i
|
oraddr.next = offset + cur_i
|
if cur_i == 1:
|
if cur_i == 1:
|
copy1.next = orbyte
|
copy1.next = orbyte
|
# print("c1", cur_i, length, offset, do, orbyte)
|
# print("c1", cur_i, length, offset, do, orbyte)
|
if cur_i == 3:
|
if cur_i == 3:
|
copy2.next = orbyte
|
copy2.next = orbyte
|
if cur_i > 1:
|
if cur_i > 1:
|
# Special 1 byte offset handling:
|
# Special 1 byte offset handling:
|
if offset + cur_i == do + 1:
|
if (offset + cur_i) & OBS == (do + 1) & OBS:
|
obyte.next = copy1
|
obyte.next = copy1
|
elif cur_i == 3 or offset + cur_i != do:
|
elif cur_i == 3 or (offset + cur_i) & OBS != do & OBS:
|
obyte.next = orbyte
|
obyte.next = orbyte
|
# Special 2 byte offset handling:
|
# Special 2 byte offset handling:
|
elif cur_i > 2:
|
elif cur_i > 2:
|
if cur_i & 1:
|
if cur_i & 1:
|
obyte.next = copy2
|
obyte.next = copy2
|
Line 1357... |
Line 1426... |
return io_logic, logic, fill_buf, oramwrite, oramread
|
return io_logic, logic, fill_buf, oramwrite, oramread
|
|
|
|
|
if __name__ == "__main__":
|
if __name__ == "__main__":
|
d = deflate(Signal(intbv()[3:]), Signal(bool(0)),
|
d = deflate(Signal(intbv()[3:]), Signal(bool(0)),
|
Signal(intbv()[8:]), Signal(intbv()[LBSIZE:]),
|
Signal(intbv()[8:]), Signal(intbv()[LMAX:]),
|
Signal(intbv()[LBSIZE:]),
|
Signal(intbv()[LMAX:]),
|
Signal(intbv()[8:]), Signal(intbv()[LBSIZE:]),
|
Signal(intbv()[8:]),
|
|
Signal(modbv()[LIBSIZE:]), Signal(modbv()[LBSIZE:]),
|
Signal(bool(0)), ResetSignal(1, 0, True))
|
Signal(bool(0)), ResetSignal(1, 0, True))
|
d.convert()
|
d.convert()
|
|
|
No newline at end of file
|
No newline at end of file
|