diff --git a/scripts/dbgbmap.py b/scripts/dbgbmap.py index b5b968b3..9eba7864 100755 --- a/scripts/dbgbmap.py +++ b/scripts/dbgbmap.py @@ -2733,7 +2733,6 @@ class Gstate: locals()[g.__name__.lower()] = ft.cached_property(_parser(g)) -# TODO sync # high-level littlefs representation class Lfs: def __init__(self, bd, mtree, config=None, gstate=None, cksum=None, *, diff --git a/scripts/dbgbmapd3.py b/scripts/dbgbmapd3.py index b5d031e4..0460a969 100755 --- a/scripts/dbgbmapd3.py +++ b/scripts/dbgbmapd3.py @@ -3851,8 +3851,6 @@ def punescape(s, attrs=None): return re.sub(pattern, unescape, s) -# TODO sync these - # naive space filling curve (the default) def naive_curve(width, height): for y in range(height): @@ -4065,580 +4063,6 @@ class BmapBlock: } -# a mergable range set type -class RangeSet: - def __init__(self, ranges=None): - self._ranges = [] - - if ranges is not None: - # using add here makes sure all ranges are merged/sorted - # correctly - for r in ranges: - self.add(r) - - def __repr__(self): - return 'RangeSet(%r)' % self._ranges - - def __contains__(self, k): - i = bisect.bisect(self._ranges, k, - key=lambda r: r.start) - 1 - if i > -1: - return k in self._ranges[i] - else: - return False - - def __bool__(self): - return bool(self._ranges) - - def ranges(self): - yield from self._ranges - - def __iter__(self): - for r in self._ranges: - yield from r - - def add(self, r): - assert isinstance(r, range) - # trivial range? - if not r: - return - - # find earliest possible merge point - ranges = self._ranges - i = bisect.bisect_left(ranges, r.start, - key=lambda r: r.stop) - - # copy ranges < merge - merged = ranges[:i] - - # merge ranges and append - while i < len(ranges) and ranges[i].start <= r.stop: - r = range( - min(ranges[i].start, r.start), - max(ranges[i].stop, r.stop)) - i += 1 - merged.append(r) - - # copy ranges > merge - merged.extend(ranges[i:]) - - self._ranges = merged - - def remove(self, r): - assert isinstance(r, range) - # trivial range? - if not r: - return - - # find earliest possible carve point - ranges = self._ranges - i = bisect.bisect_left(ranges, r.start, - key=lambda r: r.stop) - - # copy ranges < carve - carved = ranges[:i] - - # carve overlapping ranges, note this can split ranges - while i < len(ranges) and ranges[i].start <= r.stop: - if ranges[i].start < r.start: - carved.append(range(ranges[i].start, r.start)) - if ranges[i].stop > r.stop: - carved.append(range(r.stop, ranges[i].stop)) - i += 1 - - # copy ranges > carve - carved.extend(ranges[i:]) - - self._ranges = carved - - @property - def start(self): - if not self._ranges: - return 0 - else: - return self._ranges[0].start - - @property - def stop(self): - if not self._ranges: - return 0 - else: - return self._ranges[-1].stop - - def __len__(self): - return self.stop - - def copy(self): - # create a shallow copy - ranges = RangeSet() - ranges._ranges = self._ranges.copy() - return ranges - - def __getitem__(self, slice_): - assert isinstance(slice_, slice) - - # create a copy - ranges = self.copy() - - # just use remove to do the carving, it's good enough probably - if slice_.stop is not None: - ranges.remove(range(slice_.stop, len(self))) - if slice_.start is not None: - ranges.remove(range(0, slice_.start)) - ranges._ranges = [range( - r.start - slice_.start, - r.stop - slice_.start) - for r in ranges._ranges] - - return ranges - - def __ior__(self, other): - for r in other.ranges(): - self.add(r) - return self - - def __or__(self, other): - ranges = self.copy() - ranges |= other - return ranges - -# a mergable range dict type -class RangeDict: - def __init__(self, ranges=None): - self._ranges = [] - - if ranges is not None: - # using __setitem__ here makes sure all ranges are - # merged/sorted correctly - for r, v in ranges: - self[r] = v - - def __repr__(self): - return 'RangeDict(%r)' % self._ranges - - def _get(self, k): - i = bisect.bisect(self._ranges, k, - key=lambda rv: rv[0].start) - 1 - if i > -1: - return self._ranges[i][1] - else: - raise KeyError(k) - - def get(self, k, d=None): - try: - return self._get(k) - except KeyError: - return d - - def __getitem__(self, k): - # special case for slicing - if isinstance(k, slice): - return self._slice(k) - else: - return self._get(k) - - def __contains__(self, k): - try: - self._get(k) - return True - except KeyError: - return False - - def __bool__(self): - return bool(self._ranges) - - def ranges(self): - yield from self._ranges - - def __iter__(self): - for r, v in self._ranges: - for k in r: - yield k, v - - # apply a function to a range - def map(self, r, f): - assert isinstance(r, range) - # trivial range? - if not r: - return - - # find earliest possible merge point - ranges = self._ranges - i = bisect.bisect_left(ranges, r.start, - key=lambda rv: rv[0].stop) - - # copy ranges < merge - merged = ranges[:i] - - # map, merge/carve ranges - while i < len(ranges) and ranges[i][0].start <= r.stop: - # carve prefix - if ranges[i][0].start < r.start: - merged.append(( - range(ranges[i][0].start, r.start), - ranges[i][1])) - - # need fill? - if ranges[i][0].start > r.start: - v = f(None) - # merge? - if (merged - and merged[-1][0].stop >= r.start - and merged[-1][1] == v): - merged[-1] = ( - range( - merged[-1][0].start, - ranges[i][0].start), - merged[-1][1]) - else: - merged.append(( - range(r.start, ranges[i][0].start), - f(None))) - - # apply f - v = f(ranges[i][1]) - - # merge? - if (merged - and merged[-1][0].stop >= r.start - and merged[-1][1] == v): - merged[-1] = ( - range( - merged[-1][0].start, - min(ranges[i][0].stop, r.stop)), - merged[-1][1]) - else: - merged.append(( - range( - r.start, - min(ranges[i][0].stop, r.stop)), - v)) - r = range( - min(ranges[i][0].stop, r.stop), - r.stop) - - # carve suffix - if ranges[i][0].stop > r.stop: - # merge? - if ranges[i][1] == v: - merged[-1] = ( - range( - merged[-1][0].start, - ranges[i][0].stop), - merged[-1][1]) - else: - merged.append(( - range(r.stop, ranges[i][0].stop), - ranges[i][1])) - - i += 1 - - # need fill? - if not merged or merged[-1][0].stop < r.stop: - v = f(None) - # merge? - if (merged - and merged[-1][0].stop >= r.start - and merged[-1][1] == v): - merged[-1] = ( - range(merged[-1][0].start, r.stop), - merged[-1][1]) - else: - merged.append((r, v)) - - # copy ranges > merge - merged.extend(ranges[i:]) - - self._ranges = merged - - def __setitem__(self, r, v): - # we can define __setitem__ using map - assert isinstance(r, range) - self.map(r, lambda _: v) - - def __delitem__(self, r): - # __delitem__ is a bit more complicated - assert isinstance(r, range) - # trivial range? - if not r: - return - - # find earliest possible carve point - ranges = self._ranges - i = bisect.bisect_left(ranges, r.start, - key=lambda rv: rv[0].stop) - - # copy ranges < carve - carved = ranges[:i] - - # carve overlapping ranges, note this can split ranges - while i < len(ranges) and ranges[i][0].start <= r.stop: - if ranges[i][0].start < r.start: - carved.append(( - range(ranges[i][0].start, r.start), - ranges[i][1])) - if ranges[i][0].stop > r.stop: - carved.append(( - range(r.stop, ranges[i][0].stop), - ranges[i][1])) - i += 1 - - # copy ranges > carve - carved.extend(ranges[i:]) - - self._ranges = carved - - @property - def start(self): - if not self._ranges: - return 0 - else: - return self._ranges[0][0].start - - @property - def stop(self): - if not self._ranges: - return 0 - else: - return self._ranges[-1][0].stop - - def __len__(self): - return self.stop - - def copy(self): - # create a shallow copy - ranges = RangeDict() - ranges._ranges = self._ranges.copy() - return ranges - - def _slice(self, slice_): - assert isinstance(slice_, slice) - - # create a copy - ranges = RangeDict() - ranges._ranges = self._ranges - - # just use __delitem__ to do the carving, it's good enough probably - if slice_.stop is not None: - del ranges[range(slice_.stop, len(self))] - if slice_.start is not None: - del ranges[range(0, slice_.start)] - ranges._ranges = [( - range( - r.start - slice_.start, - r.stop - slice_.start), - v) - for r, v in ranges._ranges] - - return ranges - - def __ior__(self, other): - for r, v in other.ranges(): - self[r] = v - return self - - def __or__(self, other): - ranges = self.copy() - ranges |= other - return ranges - - -## a representation of a range of blocks/offs to show -#class BmapSlice: -# def __init__(self, blocks=None, off=None, size=None): -# self.orig_blocks = blocks -# self.orig_off = off -# self.orig_size = size -# -# # flatten blocks, default to all blocks -# blocks = ([blocks] if isinstance(blocks, slice) -# else list(it.chain.from_iterable( -# [blocks_] if isinstance(blocks_, slice) else blocks_ -# for blocks_ in blocks)) -# if blocks is not None -# else [slice(None)]) -# -# # blocks may also encode offsets -# blocks, offs, size = ( -# [block[0] if isinstance(block, tuple) -# else block -# for block in blocks], -# [off.start if isinstance(off, slice) -# else off if off is not None -# else size.start if isinstance(size, slice) -# else block[1] if isinstance(block, tuple) -# else None -# for block in blocks], -# (size.stop - (size.start or 0) -# if size.stop is not None -# else None) if isinstance(size, slice) -# else size if size is not None -# else ((off.stop - (off.start or 0)) -# if off.stop is not None -# else None) if isinstance(off, slice) -# else None) -# -# self.blocks = blocks -# self.offs = offs -# self.size = size -# -# @property -# def off(self): -# if not self.offs: -# return None -# else: -# return self.offs[-1] -# -# def __repr__(self): -# return 'BmapSlice(%r, %r, %r)' % ( -# self.orig_blocks, -# self.orig_off, -# self.orig_size) -# -# def slices(self, block_size, block_count): -# for block, off in zip(self.blocks, self.offs): -# # figure out off range, bound to block_size -# off = off if off is not None else 0 -# size = self.size if self.size is not None else block_size - off -# if off >= block_size: -# continue -# size = min(off + size, block_size) - off -# -# # flatten/filter blocks -# if isinstance(block, slice): -# start = block.start if block.start is not None else 0 -# stop = block.stop if block.stop is not None else block_count -# for block_ in range(start, min(stop, block_count)): -# yield block_, off, size -# else: -# block = block if block is not None else 0 -# if block < block_count: -# yield block, off, size -# -# def blocks(self, block_count): -# for block in self.blocks: -# # flatten/filter blocks -# if isinstance(block, slice): -# start = block.start if block.start is not None else 0 -# stop = block.stop if block.stop is not None else block_count -# for block_ in range(start, min(stop, block_count)): -# yield block_ -# else: -# block = block if block is not None else 0 -# if block < block_count: -# yield block -# -# def sorted_slices(self, block_size, block_count): -# # merge block ranges -# blocks = RangeDict() -# for block in self.blocks: -# # figure out off range, bound to block_size -# off = off if off is not None else 0 -# size = self.size if self.size is not None else block_size - off -# if off >= block_size: -# continue -# size = min(off + size, block_size) - off -# -# # flatten/filter blocks -# if isinstance(block, slice): -# start = block.start if block.start is not None else 0 -# stop = block.stop if block.stop is not None else block_count -# blocks.map(range(start, min(stop, block_count)), -# lambda r: (r if r is not None else RangeSet()) -# | RangeSet([range(off, off+size)])) -# else: -# block = block if block is not None else 0 -# if block < block_count: -# blocks.map(range(block, block+1), -# lambda r: (r if r is not None else RangeSet()) -# | RangeSet([range(off, off+size)])) -# -# for block, r in blocks: -# for off, stop in r: -# yield off, stop-off -# -# def sorted_blocks(self, block_count): -# # merge block ranges -# blocks = RangeSet() -# for block in self.blocks: -# # flatten/filter blocks -# if isinstance(block, slice): -# start = block.start if block.start is not None else 0 -# stop = block.stop if block.stop is not None else block_count -# blocks.add(range(start, min(stop, block_count))) -# else: -# block = block if block is not None else 0 -# if block < block_count: -# blocks.add(range(block, block+1)) -# -# yield from blocks -# -# -# -## # merge block ranges -## merged = [] -## for blocks, offs in zip(self.blocks, self.offs): -## # simplify blocks first -## if not isinstance(blocks, slice): -## blocks = slice(blocks, blocks+1) -## blocks = slice( -## blocks.start if blocks.start is not None else 0, -## blocks.start if blocks.start is not None else block_count) -## -## # copy ranges before merge -## i = 0 -## merged_ = [] -## blocks_ = blocks -## while i < len(merged) and merged[i].stop < blocks_.start: -## merged_.append(merged[i]) -## -## # merge ranges and append -## while i < len(merged) and merged[i].start <= blocks_.stop: -## blocks_ = slice( -## min(merged[i].start, blocks_.start), -## max(merged[i].stop, blocks_.stop)) -## merged_.append(blocks_) -## -## # and copy the rest -## merged_.extend(merged[i:]) -## -## -## -## -## -## for blocks_ in merged: -## # merge ranges? -## if blocks_ -## else -# -# -# def __contains__(self, block): -# if isinstance(block, tuple): -# block, off = block -# else: -# block, off = block, None -# -# for block_, off_ in zip(self.blocks, self.offs): -# # in off range? -# if off is not None: -# off_ = off_ if off_ is not None else 0 -# size_ = self.size -# if not (off >= off_ -# and (size_ is None or off < off_ + size_)): -# continue -# -# # in block range? -# if isinstance(block_, slice): -# if ((block_.start is None or block >= block_.start) -# and (block_.stop is None or block < block_.stop)): -# return True -# else: -# if block_ is None or block == block_: -# return True -# -# return False - - def main(disk, output, mroots=None, *, trunk=None, @@ -5799,47 +5223,6 @@ if __name__ == "__main__": '--block-count', type=lambda x: int(x, 0), help="Block count in blocks.") - -# # subparser for block arguments -# blocks_parser = argparse.ArgumentParser( -# prog="%s -@/--blocks" % parser.prog, -# allow_abbrev=False) -# blocks_parser.add_argument( -# 'blocks', -# nargs='*', -# type=lambda x: ( -# slice(*(int(x, 0) if x.strip() else None -# for x in x.split(',', 1))) -# if ',' in x and '{' not in x -# else rbydaddr(x)), -# help="Block addresses, may be a range.") -# blocks_parser.add_argument( -# '--off', -# type=lambda x: ( -# slice(*(int(x, 0) if x.strip() else None -# for x in x.split(',', 1))) -# if ',' in x -# else int(x, 0)), -# help="Show a specific offset, may be a range.") -# blocks_parser.add_argument( -# '-n', '--size', -# type=lambda x: ( -# slice(*(int(x, 0) if x.strip() else None -# for x in x.split(',', 1))) -# if ',' in x -# else int(x, 0)), -# help="Show this many bytes, may be a range.") -# -# parser.add_argument( -# '-@', '--blocks', -# type=lambda blocks: BmapSlice(**{k: v -# for k, v in vars(blocks_parser.parse_intermixed_args( -# shlex.split(blocks))).items() -# if v is not None}), -# help="Optional blocks to show, may be a range. Can also include " -# "--off and -n/--size flags to indicate a range inside the " -# "block, both which may also be ranges.") - parser.add_argument( '-@', '--blocks', type=lambda x: ( diff --git a/scripts/tracebd.py b/scripts/tracebd.py index b13ec4fc..879ce20e 100755 --- a/scripts/tracebd.py +++ b/scripts/tracebd.py @@ -53,13 +53,6 @@ WEAR_COLORS = ['1;30', '1;30', '1;30', '', '', '', '', '31', '31', '1;31'] # erases, so progs are more interesting Z_ORDER = ['prog', 'erase', 'read', 'wear', 'noop'] -# TODO rm -#CHARS = 'rpe-' -#COLORS = ['32', '35', '34', '90'] -# -#WEAR_CHARS = '-123456789' -#WEAR_COLORS = ['90', '', '', '', '', '', '', '35', '35', '1;31'] - CHARS_DOTS = " .':" CHARS_BRAILLE = ( '⠀⢀⡀⣀⠠⢠⡠⣠⠄⢄⡄⣄⠤⢤⡤⣤' '⠐⢐⡐⣐⠰⢰⡰⣰⠔⢔⡔⣔⠴⢴⡴⣴' @@ -917,473 +910,6 @@ class TraceBlock: - - - - -## space filling Hilbert-curve -## -## note we memoize the last curve since this is a bit expensive -## -#@ft.lru_cache(1) -#def hilbert_curve(width, height): -# # based on generalized Hilbert curves: -# # https://github.com/jakubcerveny/gilbert -# # -# def hilbert_(x, y, a_x, a_y, b_x, b_y): -# w = abs(a_x+a_y) -# h = abs(b_x+b_y) -# a_dx = -1 if a_x < 0 else +1 if a_x > 0 else 0 -# a_dy = -1 if a_y < 0 else +1 if a_y > 0 else 0 -# b_dx = -1 if b_x < 0 else +1 if b_x > 0 else 0 -# b_dy = -1 if b_y < 0 else +1 if b_y > 0 else 0 -# -# # trivial row -# if h == 1: -# for _ in range(w): -# yield (x,y) -# x, y = x+a_dx, y+a_dy -# return -# -# # trivial column -# if w == 1: -# for _ in range(h): -# yield (x,y) -# x, y = x+b_dx, y+b_dy -# return -# -# a_x_, a_y_ = a_x//2, a_y//2 -# b_x_, b_y_ = b_x//2, b_y//2 -# w_ = abs(a_x_+a_y_) -# h_ = abs(b_x_+b_y_) -# -# if 2*w > 3*h: -# # prefer even steps -# if w_ % 2 != 0 and w > 2: -# a_x_, a_y_ = a_x_+a_dx, a_y_+a_dy -# -# # split in two -# yield from hilbert_(x, y, a_x_, a_y_, b_x, b_y) -# yield from hilbert_(x+a_x_, y+a_y_, a_x-a_x_, a_y-a_y_, b_x, b_y) -# else: -# # prefer even steps -# if h_ % 2 != 0 and h > 2: -# b_x_, b_y_ = b_x_+b_dx, b_y_+b_dy -# -# # split in three -# yield from hilbert_(x, y, b_x_, b_y_, a_x_, a_y_) -# yield from hilbert_(x+b_x_, y+b_y_, a_x, a_y, b_x-b_x_, b_y-b_y_) -# yield from hilbert_( -# x+(a_x-a_dx)+(b_x_-b_dx), y+(a_y-a_dy)+(b_y_-b_dy), -# -b_x_, -b_y_, -(a_x-a_x_), -(a_y-a_y_)) -# -# if width >= height: -# curve = hilbert_(0, 0, +width, 0, 0, +height) -# else: -# curve = hilbert_(0, 0, 0, +height, +width, 0) -# -# return list(curve) -# -## space filling Z-curve/Lebesgue-curve -## -## note we memoize the last curve since this is a bit expensive -## -#@ft.lru_cache(1) -#def lebesgue_curve(width, height): -# # we create a truncated Z-curve by simply filtering out the points -# # that are outside our region -# curve = [] -# for i in range(2**(2*mt.ceil(mt.log2(max(width, height))))): -# # we just operate on binary strings here because it's easier -# b = '{:0{}b}'.format(i, 2*mt.ceil(mt.log2(i+1)/2)) -# x = int(b[1::2], 2) if b[1::2] else 0 -# y = int(b[0::2], 2) if b[0::2] else 0 -# if x < width and y < height: -# curve.append((x, y)) -# -# return curve -# -# -#class Pixel(int): -# __slots__ = () -# def __new__(cls, state=0, *, -# wear=0, -# readed=False, -# proged=False, -# erased=False): -# return super().__new__(cls, -# state -# | (wear << 3) -# | (1 if readed else 0) -# | (2 if proged else 0) -# | (4 if erased else 0)) -# -# @property -# def wear(self): -# return self >> 3 -# -# @property -# def readed(self): -# return (self & 1) != 0 -# -# @property -# def proged(self): -# return (self & 2) != 0 -# -# @property -# def erased(self): -# return (self & 4) != 0 -# -# def read(self): -# return Pixel(int(self) | 1) -# -# def prog(self): -# return Pixel(int(self) | 2) -# -# def erase(self): -# return Pixel((int(self) | 4) + 8) -# -# def clear(self): -# return Pixel(int(self) & ~7) -# -# def __or__(self, other): -# return Pixel( -# (int(self) | int(other)) & 7, -# wear=max(self.wear, other.wear)) -# -# def worn(self, max_wear, *, -# block_cycles=None, -# wear_chars=None, -# **_): -# if wear_chars is None: -# wear_chars = WEAR_CHARS -# -# if block_cycles: -# return self.wear / block_cycles -# else: -# return self.wear / max(max_wear, len(wear_chars)) -# -# def draw(self, max_wear, char=None, *, -# reads=True, -# progs=True, -# erases=True, -# wear=False, -# block_cycles=None, -# color=True, -# dots=False, -# braille=False, -# chars=None, -# wear_chars=None, -# colors=None, -# wear_colors=None, -# **_): -# # fallback to default chars/colors -# if chars is None: -# chars = CHARS -# if len(chars) < len(CHARS): -# chars = chars + CHARS[len(chars):] -# -# if colors is None: -# colors = COLORS -# if len(colors) < len(COLORS): -# colors = colors + COLORS[len(colors):] -# -# if wear_chars is None: -# wear_chars = WEAR_CHARS -# -# if wear_colors is None: -# wear_colors = WEAR_COLORS -# -# # compute char/color -# c = chars[3] -# f = [colors[3]] -# -# if wear: -# w = min(self.worn( -# max_wear, -# block_cycles=block_cycles, -# wear_chars=wear_chars), -# 1) -# -# c = wear_chars[int(w * (len(wear_chars)-1))] -# f.append(wear_colors[int(w * (len(wear_colors)-1))]) -# -# if progs and self.proged: -# c = chars[1] -# f.append(colors[1]) -# elif erases and self.erased: -# c = chars[2] -# f.append(colors[2]) -# elif reads and self.readed: -# c = chars[0] -# f.append(colors[0]) -# -# # override char? -# if char: -# c = char -# -# # apply colors -# if f and color: -# c = '%s%s\x1b[m' % ( -# ''.join('\x1b[%sm' % f_ for f_ in f), -# c) -# -# return c -# -# -#class Bmap: -# def __init__(self, *, -# block_size=1, -# block_count=1, -# block_window=None, -# off_window=None, -# width=1, -# height=1, -# pixels=None): -# # default width to block_window or block_size -# if width is None: -# if block_window is not None: -# width = len(block_window) -# else: -# width = block_count -# -# # allocate pixels if not provided -# if pixels is None: -# pixels = [Pixel() for _ in range(width*height)] -# -# self.pixels = pixels -# self.block_size = block_size -# self.block_count = block_count -# self.block_window = block_window -# self.off_window = off_window -# self.width = width -# self.height = height -# -# @property -# def _block_window(self): -# if self.block_window is None: -# return range(0, self.block_count) -# else: -# return self.block_window -# -# @property -# def _off_window(self): -# if self.off_window is None: -# return range(0, self.block_size) -# else: -# return self.off_window -# -# @property -# def _window(self): -# return len(self._off_window)*len(self._block_window) -# -# def _op(self, f, block=None, off=None, size=None): -# if block is None: -# range_ = range(len(self.pixels)) -# else: -# if off is None: -# off, size = 0, self.block_size -# elif size is None: -# off, size = 0, off -# -# # map into our window -# if block not in self._block_window: -# return -# block -= self._block_window.start -# -# size = (max(self._off_window.start, -# min(self._off_window.stop, off+size)) -# - max(self._off_window.start, -# min(self._off_window.stop, off))) -# off = (max(self._off_window.start, -# min(self._off_window.stop, off)) -# - self._off_window.start) -# if size == 0: -# return -# -# # map to our block space -# range_ = range( -# block*len(self._off_window) + off, -# block*len(self._off_window) + off+size) -# range_ = range( -# (range_.start*len(self.pixels)) // self._window, -# (range_.stop*len(self.pixels)) // self._window) -# range_ = range( -# range_.start, -# max(range_.stop, range_.start+1)) -# -# # apply the op -# for i in range_: -# self.pixels[i] = f(self.pixels[i]) -# -# def read(self, block=None, off=None, size=None): -# self._op(Pixel.read, block, off, size) -# -# def prog(self, block=None, off=None, size=None): -# self._op(Pixel.prog, block, off, size) -# -# def erase(self, block=None, off=None, size=None): -# self._op(Pixel.erase, block, off, size) -# -# def clear(self, block=None, off=None, size=None): -# self._op(Pixel.clear, block, off, size) -# -# def resize(self, *, -# block_size=None, -# block_count=None, -# width=None, -# height=None): -# block_size = (block_size if block_size is not None -# else self.block_size) -# block_count = (block_count if block_count is not None -# else self.block_count) -# width = width if width is not None else self.width -# height = height if height is not None else self.height -# -# if (block_size == self.block_size -# and block_count == self.block_count -# and width == self.width -# and height == self.height): -# return -# -# # transform our pixels -# self.block_size = block_size -# self.block_count = block_count -# -# pixels = [] -# for x in range(width*height): -# # map into our old bd space -# range_ = range( -# (x*self._window) // (width*height), -# ((x+1)*self._window) // (width*height)) -# range_ = range( -# range_.start, -# max(range_.stop, range_.start+1)) -# -# # aggregate state -# pixels.append(ft.reduce( -# Pixel.__or__, -# self.pixels[range_.start:range_.stop], -# Pixel())) -# -# self.width = width -# self.height = height -# self.pixels = pixels -# -# def draw(self, row, *, -# reads=False, -# progs=False, -# erases=False, -# wear=False, -# hilbert=False, -# lebesgue=False, -# dots=False, -# braille=False, -# **args): -# # find max wear? -# max_wear = None -# if wear: -# max_wear = max(p.wear for p in self.pixels) -# -# # fold via a curve? -# if hilbert: -# grid = [None]*(self.width*self.height) -# for (x,y), p in zip( -# hilbert_curve(self.width, self.height), -# self.pixels): -# grid[x + y*self.width] = p -# elif lebesgue: -# grid = [None]*(self.width*self.height) -# for (x,y), p in zip( -# lebesgue_curve(self.width, self.height), -# self.pixels): -# grid[x + y*self.width] = p -# else: -# grid = self.pixels -# -# # need to wait for more trace output before rendering -# # -# # this is sort of a hack that knows the output is going to a terminal -# if (braille and self.height < 4) or (dots and self.height < 2): -# needed_height = 4 if braille else 2 -# -# self.history = getattr(self, 'history', []) -# self.history.append(grid.copy()) -# -# if len(self.history)*self.height < needed_height: -# # skip for now -# return None -# -# grid = list(it.chain.from_iterable( -# # did we resize? -# it.islice(it.chain(h, it.repeat(Pixel())), -# self.width*self.height) -# for h in self.history)) -# self.history = [] -# -# line = [] -# if braille: -# # encode into a byte -# for x in range(0, self.width, 2): -# byte_p = 0 -# best_p = Pixel() -# for i in range(2*4): -# p = grid[x+(2-1-(i%2)) + ((row*4)+(4-1-(i//2)))*self.width] -# best_p |= p -# if ((reads and p.readed) -# or (progs and p.proged) -# or (erases and p.erased) -# or (not reads and not progs and not erases -# and wear and p.worn(max_wear, **args) >= 0.7)): -# byte_p |= 1 << i -# -# line.append(best_p.draw( -# max_wear, -# CHARS_BRAILLE[byte_p], -# braille=True, -# reads=reads, -# progs=progs, -# erases=erases, -# wear=wear, -# **args)) -# elif dots: -# # encode into a byte -# for x in range(self.width): -# byte_p = 0 -# best_p = Pixel() -# for i in range(2): -# p = grid[x + ((row*2)+(2-1-i))*self.width] -# best_p |= p -# if ((reads and p.readed) -# or (progs and p.proged) -# or (erases and p.erased) -# or (not reads and not progs and not erases -# and wear and p.worn(max_wear, **args) >= 0.7)): -# byte_p |= 1 << i -# -# line.append(best_p.draw( -# max_wear, -# CHARS_DOTS[byte_p], -# dots=True, -# reads=reads, -# progs=progs, -# erases=erases, -# wear=wear, -# **args)) -# else: -# for x in range(self.width): -# line.append(grid[x + row*self.width].draw( -# max_wear, -# reads=reads, -# progs=progs, -# erases=erases, -# wear=wear, -# **args)) -# -# return ''.join(line) - - - def main(path='-', *, block_size=None, block_count=None, @@ -1542,36 +1068,6 @@ def main(path='-', *, ## trace parser # precompute trace regexes - - # TODO rm me -# trace_pattern = re.compile( -# '^(?P[^:]*):(?P[0-9]+):trace:.*?bd_(?:' -# '(?Pcreate\w*)\(' -# '(?:' -# 'block_size=(?P\w+)' -# '|' 'block_count=(?P\w+)' -# '|' '.*?' ')*' -# '\)' -# '|' '(?Pread)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*\)' -# '|' '(?Pprog)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*\)' -# '|' '(?Perase)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' -# '\s*\(\s*(?P\w+)\s*\)' '\s*\)' -# '|' '(?Psync)\(' -# '\s*(?P\w+)' '\s*\)' -# ')\s*$') - init_pattern = re.compile( '^(?P[^ :]*):(?P[0-9]+):trace:' '.*?bd_createcfg\(' @@ -1879,8 +1375,6 @@ def main(path='-', *, b.width = max(b.width, 1) b.height = max(b.height, 1) - # TODO chars should probably take priority over braille/dots - # TODO limit these based on requested ops? # assign chars based on op + block for b in bmap.values(): b.chars = {} @@ -1936,8 +1430,6 @@ def main(path='-', *, # render to canvas in a specific z-order that prioritizes # interesting ops for op in reversed(Z_ORDER): - # TODO if we're rendering noops as dashes here, should we render - # unused as dashes even in usage mode in dbgbmap.py? # don't render noops in braille/dots mode if (braille or dots) and op == 'noop': continue @@ -2047,414 +1539,6 @@ def main(path='-', *, b.clear() - -# TODO rm me -# -# -# -# -# -# -# -# -# -# # exclusive wear or reads/progs/erases by default -# if not reads and not progs and not erases and not wear: -# reads = True -# progs = True -# erases = True -# -# # assume a reasonable lines/height if not specified -# # -# # note that we let height = None if neither hilbert or lebesgue -# # are specified, this is a bit special as the default may be less -# # than one character in height. -# if height is None and (hilbert or lebesgue): -# if lines is not None: -# height = lines -# else: -# height = 5 -# -# if lines is None: -# if height is not None: -# lines = height -# else: -# lines = 5 -# -# # is bd geometry specified? -# if isinstance(block_size, tuple): -# block_size, block_count_ = block_size -# if block_count is None: -# block_count = block_count_ -# -# # try to simplify the block/off/size arguments a bit -# if not isinstance(block, dict): -# block = {'block': block} -# block, off, size = ( -# block.get('block'), -# block.get('off'), -# block.get('size')) -# -# if not isinstance(block, tuple): -# block = block, -# if isinstance(off, tuple) and len(off) == 1: -# off, = off -# if isinstance(size, tuple) and len(size) == 1: -# if off is None: -# off, = size -# size = None -# -# if any(isinstance(b, tuple) and len(b) > 1 for b in block): -# print("error: more than one block address?", -# file=sys.stderr) -# sys.exit(-1) -# if isinstance(block[0], tuple): -# block = (block[0][0], *block[1:]) -# if len(block) > 1 and isinstance(block[1], tuple): -# block = (block[0], block[1][0]) -# if isinstance(block[0], tuple): -# block, off_ = (block[0][0], *block[1:]), block[0][1] -# if off is None: -# off = off_ -# if len(block) > 1 and isinstance(block[1], tuple): -# block = (block[0], block[1][0]) -# if len(block) == 1: -# block, = block -# -# if isinstance(off, tuple): -# off, size_ = off[0], off[1] - off[0] -# if size is None: -# size = size_ -# if isinstance(size, tuple): -# off_, size = off[0], off[1] - off[0] -# if off is None: -# off = off_ -# -# # is a block window specified? -# block_window = None -# if block is not None: -# if isinstance(block, tuple): -# block_window = range(*block) -# else: -# block_window = range(block, block+1) -# -# off_window = None -# if off is not None or size is not None: -# off_ = off if off is not None else 0 -# size_ = size if size is not None else 1 -# off_window = range(off_, off_+size_) -# -# # create our block device representation -# bmap = Bmap( -# block_size=block_size if block_size is not None else 1, -# block_count=block_count if block_count is not None else 1, -# block_window=block_window, -# off_window=off_window) -# -# def resize(): -# nonlocal bmap -# -# # figure out best width/height -# if width is None: -# width_ = min(80, shutil.get_terminal_size((80, 5))[0]) -# elif width: -# width_ = width -# else: -# width_ = shutil.get_terminal_size((80, 5))[0] -# -# if height is None: -# height_ = 0 -# elif height: -# height_ = height -# else: -# height_ = shutil.get_terminal_size((80, 5))[1] -# -# # terminal size changed? -# if width_ != bmap.width or height_ != bmap.height: -# bmap.resize( -# # scale if we're printing with dots or braille -# width=2*width_ if braille else width_, -# height=max( -# 1, -# 4*height_ if braille -# else 2*height_ if dots -# else height_)) -# resize() -# -# # keep track of some extra info -# readed = 0 -# proged = 0 -# erased = 0 -# -# # parse a line of trace output -# pattern = re.compile( -# '^(?P[^:]*):(?P[0-9]+):trace:.*?bd_(?:' -# '(?Pcreate\w*)\(' -# '(?:' -# 'block_size=(?P\w+)' -# '|' 'block_count=(?P\w+)' -# '|' '.*?' ')*' -# '\)' -# '|' '(?Pread)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*\)' -# '|' '(?Pprog)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' '\s*\)' -# '|' '(?Perase)\(' -# '\s*(?P\w+)' '\s*,' -# '\s*(?P\w+)' -# '\s*\(\s*(?P\w+)\s*\)' '\s*\)' -# '|' '(?Psync)\(' -# '\s*(?P\w+)' '\s*\)' -# ')\s*$') -# def parse(line): -# nonlocal bmap -# nonlocal readed -# nonlocal proged -# nonlocal erased -# -# # string searching is much faster than the regex here, and this -# # actually has a big impact given the sheer quantity of how much -# # trace output we have to deal with -# if 'trace' not in line or 'bd' not in line: -# return False -# m = pattern.match(line) -# if not m: -# return False -# -# if m.group('create'): -# # update our block size/count -# block_size_ = int(m.group('block_size'), 0) -# block_count_ = int(m.group('block_count'), 0) -# -# if reset: -# bmap = Bmap( -# block_size=block_size_, -# block_count=block_count_, -# block_window=bmap.block_window, -# off_window=bmap.off_window, -# width=bmap.width, -# height=bmap.height) -# elif ((block_size is None -# and block_size_ != bmap.block_size) -# or (block_count is None -# and block_count_ != bmap.block_count)): -# bmap.resize( -# block_size=block_size if block_size is not None -# else block_size_, -# block_count=block_count if block_count is not None -# else block_count_) -# return True -# -# elif m.group('read') and reads: -# block = int(m.group('read_block'), 0) -# off = int(m.group('read_off'), 0) -# size = int(m.group('read_size'), 0) -# -# if ((block_size is None and off+size > bmap.block_size) -# or (block_count is None and block >= bmap.block_count)): -# bmap.resize( -# block_size=block_size if block_size is not None -# else max(off+size, bmap.block_size), -# block_count=block_count if block_count is not None -# else max(block+1, bmap.block_count)) -# -# bmap.read(block, off, size) -# readed += size -# return True -# -# elif m.group('prog') and progs: -# block = int(m.group('prog_block'), 0) -# off = int(m.group('prog_off'), 0) -# size = int(m.group('prog_size'), 0) -# -# if ((block_size is None and off+size > bmap.block_size) -# or (block_count is None and block >= bmap.block_count)): -# bmap.resize( -# block_size=block_size if block_size is not None -# else max(off+size, bmap.block_size), -# block_count=block_count if block_count is not None -# else max(block+1, bmap.block_count)) -# -# bmap.prog(block, off, size) -# proged += size -# return True -# -# elif m.group('erase') and (erases or wear): -# block = int(m.group('erase_block'), 0) -# size = int(m.group('erase_size'), 0) -# -# if ((block_size is None and size > bmap.block_size) -# or (block_count is None and block >= bmap.block_count)): -# bmap.resize( -# block_size=block_size if block_size is not None -# else max(size, bmap.block_size), -# block_count=block_count if block_count is not None -# else max(block+1, bmap.block_count)) -# -# bmap.erase(block, size) -# erased += size -# return True -# -# else: -# return False -# -# # print trace output -# def draw(f): -# nonlocal readed -# nonlocal proged -# nonlocal erased -# -# def writeln(s=''): -# f.write(s) -# f.write('\n') -# f.writeln = writeln -# -# # don't forget we've scaled this for braille/dots! -# for row in range( -# mt.ceil(bmap.height/4) if braille -# else mt.ceil(bmap.height/2) if dots -# else bmap.height): -# line = bmap.draw(row, -# reads=reads, -# progs=progs, -# erases=erases, -# wear=wear, -# block_cycles=block_cycles, -# color=color, -# dots=dots, -# braille=braille, -# hilbert=hilbert, -# lebesgue=lebesgue, -# **args) -# if line: -# f.writeln(line) -# -# # print some information about reads/progs/erases -# # -# # cat implies no-header, because a header wouldn't really make sense -# if not no_header and not cat: -# # compute total ops -# total = readed+proged+erased -# -# # compute stddev of wear using our bmap, this is a bit different -# # from reads/progs/erases which ignores any bmap window, but it's -# # what we have -# if wear: -# mean = (sum(p.wear for p in bmap.pixels) -# / max(len(bmap.pixels), 1)) -# stddev = mt.sqrt(sum((p.wear - mean)**2 for p in bmap.pixels) -# / max(len(bmap.pixels), 1)) -# worst = max((p.wear for p in bmap.pixels), default=0) -# -# # a bit of a hack here, but this forces our header to always be -# # at row zero -# if len(f.lines) == 0: -# f.lines.append('') -# f.lines[0] = 'bd %dx%d%s%s%s%s' % ( -# bmap.block_size, bmap.block_count, -# ', %6s read' % ('%.1f%%' % (100*readed / max(total, 1))) -# if reads else '', -# ', %6s prog' % ('%.1f%%' % (100*proged / max(total, 1))) -# if progs else '', -# ', %6s erase' % ('%.1f%%' % (100*erased / max(total, 1))) -# if erases else '', -# ', %13s wear' % ('%.1fσ (%.1f%%)' % ( -# worst / max(stddev, 1), -# 100*stddev / max(worst, 1))) -# if wear else '') -# -# bmap.clear() -# readed = 0 -# proged = 0 -# erased = 0 -# resize() -# -# -# # read/parse/coalesce operations -# if cat: -# ring = sys.stdout -# else: -# ring = RingIO(lines + (1 if not no_header else 0), head) -# -# # if sleep print in background thread to avoid getting stuck in a read call -# event = th.Event() -# lock = th.Lock() -# if sleep: -# done = False -# def background(): -# while not done: -# event.wait() -# event.clear() -# with lock: -# draw(ring) -# if not cat: -# ring.draw() -# # sleep a minimum amount of time to avoid flickering -# time.sleep(sleep or 0.01) -# th.Thread(target=background, daemon=True).start() -# -# try: -# while True: -# with openio(path) as f: -# changed = 0 -# for line in f: -# with lock: -# changed += parse(line) -# -# # need to redraw? -# if changed and (not coalesce or changed >= coalesce): -# if sleep: -# event.set() -# else: -# draw(ring) -# if not cat: -# ring.draw() -# changed = 0 -# -# if not keep_open: -# break -# # don't just flood open calls -# time.sleep(sleep or 2) -# except FileNotFoundError as e: -# print("error: file not found %r" % path, -# file=sys.stderr) -# sys.exit(-1) -# except KeyboardInterrupt: -# pass -# -# if sleep: -# done = True -# lock.acquire() # avoids https://bugs.python.org/issue42717 -# if not cat: -# sys.stdout.write('\n') -# -# -# -# -# -# -# -# def trace_(line): -# # TODO -# -# # TODO adopt f -> ring name in all scripts? -# def draw_(ring, *, -# width=None, -# height=None): -# # TODO - - - - - ## main loop lock = th.Lock() event = th.Event() @@ -2489,15 +1573,12 @@ def main(path='-', *, # keep track of history if lines specified if lines is not None: ring = RingIO(lines+1 - # TODO expose no_header in other scripts for consistency if not no_header and lines > 0 else lines) def draw_(): # cat? write directly to stdout if cat: draw__(sys.stdout, - # TODO copy this pattern (width+height) for - # other scripts? width=width, # make space for shell prompt height=-1 if height is ... else height) @@ -2545,25 +1626,6 @@ def main(path='-', *, sys.stdout.write('\n') - - - - -# # TODO WIP -# -# # cat? let main_ write directly to stdout -# else: -# main_(sys.stdout) -# -# # not cat? write to a bounded ring -# if not cat: -# ring = RingIO(lines, head=head) -# main_(ring) -# sys.stdout.write('\n') - - - - if __name__ == "__main__": import sys import argparse @@ -2759,7 +1821,6 @@ if __name__ == "__main__": '--padding', type=float, help="Padding to add to each block. Defaults to 0.") - # TODO lines in dbgbmap.py? parser.add_argument( '-n', '--lines', nargs='?',