def int2vec(num, length=None): """Convert a signed integer to a BitVector.""" if num < 0: req_length = clog2(abs(num)) + 1 bv = uint2vec(2 ** req_length + num) else: req_length = clog2(num + 1) + 1 bv = uint2vec(num, req_length) if length: if length < req_length: fstr = "overflow: num = {} requires length >= {}, got length = {}" raise ValueError(fstr.format(num, req_length, length)) else: bv.sext(length - req_length) return bv
def _int2farray(ftype, num, length=None): """Convert a signed integer to an farray.""" if num < 0: req_length = clog2(abs(num)) + 1 objs = _uint2objs(ftype, 2**req_length + num) else: req_length = clog2(num + 1) + 1 objs = _uint2objs(ftype, num, req_length) if length: if length < req_length: fstr = "overflow: num = {} requires length >= {}, got length = {}" raise ValueError(fstr.format(num, req_length, length)) else: sign = objs[-1] objs += [sign] * (length - req_length) return farray(objs)
def Mux(fs, sel, simplify=True): """ Return an expression that multiplexes a sequence of input functions over a sequence of select functions. """ # convert Mux([a, b], x) to Mux([a, b], [x]) if isinstance(sel, Expression): sel = [sel] if len(sel) < clog2(len(fs)): fstr = "expected at least {} select bits, got {}" raise ValueError(fstr.format(clog2(len(fs)), len(sel))) it = boolfunc.iter_terms(sel) y = exprnode.or_(*[exprnode.and_(f.node, *[lit.node for lit in next(it)]) for f in fs]) if simplify: y = y.simplify() return _expr(y)
def Mux(fs, sel, simplify=True): """ Return an expression that multiplexes a sequence of input functions over a sequence of select functions. """ # convert Mux([a, b], x) to Mux([a, b], [x]) if isinstance(sel, Expression): sel = [sel] if len(sel) < clog2(len(fs)): fstr = "expected at least {} select bits, got {}" raise ValueError(fstr.format(clog2(len(fs)), len(sel))) it = boolfunc.iter_terms(sel) y = exprnode.or_( *[exprnode.and_(f.node, *[lit.node for lit in next(it)]) for f in fs]) if simplify: y = y.simplify() return _expr(y)
def _filtdim(items, shape, dim, nsl): """Return items, shape filtered by a dimension slice.""" normshape = tuple(stop - start for start, stop in shape) nsl_type = type(nsl) newitems = list() # Number of groups num = reduce(operator.mul, normshape[:dim + 1]) # Size of each group size = len(items) // num # Size of the dimension n = normshape[dim] if nsl_type is int: for i in range(num): if i % n == nsl: newitems += items[size * i:size * (i + 1)] # Collapse dimension newshape = shape[:dim] + shape[dim + 1:] elif nsl_type is slice: for i in range(num): if nsl.start <= (i % n) < nsl.stop: newitems += items[size * i:size * (i + 1)] # Reshape dimension offset = shape[dim][0] redim = (offset + nsl.start, offset + nsl.stop) newshape = shape[:dim] + (redim, ) + shape[dim + 1:] # farray else: if nsl.size < clog2(n): fstr = "expected dim {} select to have >= {} bits, got {}" raise ValueError(fstr.format(dim, clog2(n), nsl.size)) groups = [list() for _ in range(n)] for i in range(num): groups[i % n] += items[size * i:size * (i + 1)] for muxins in zip(*groups): it = boolfunc.iter_terms(nsl._items) xs = [ reduce(operator.and_, (muxin, ) + next(it)) for muxin in muxins ] newitems.append(reduce(operator.or_, xs)) # Collapse dimension newshape = shape[:dim] + shape[dim + 1:] return newitems, newshape
def _filtdim(items, shape, dim, nsl): """Return items, shape filtered by a dimension slice.""" normshape = tuple(stop - start for start, stop in shape) nsl_type = type(nsl) newitems = list() # Number of groups num = reduce(operator.mul, normshape[:dim+1]) # Size of each group size = len(items) // num # Size of the dimension N = normshape[dim] if nsl_type is int: for i in range(num): if i % N == nsl: newitems += items[size*i:size*(i+1)] # Collapse dimension newshape = shape[:dim] + shape[dim+1:] elif nsl_type is slice: for i in range(num): if nsl.start <= (i % N) < nsl.stop: newitems += items[size*i:size*(i+1)] # Reshape dimension offset = shape[dim][0] redim = (offset + nsl.start, offset + nsl.stop) newshape = shape[:dim] + (redim, ) + shape[dim+1:] # farray else: if nsl.size < clog2(N): fstr = "expected dim {} select to have >= {} bits, got {}" raise ValueError(fstr.format(dim, clog2(N), nsl.size)) groups = [list() for _ in range(N)] for i in range(num): groups[i % N] += items[size*i:size*(i+1)] for muxins in zip(*groups): it = boolfunc.iter_terms(nsl.items) args = [reduce(operator.and_, (muxin, ) + next(it)) for muxin in muxins] newitems.append(reduce(operator.or_, args)) # Collapse dimension newshape = shape[:dim] + shape[dim+1:] return newitems, newshape
def kogge_stone_add(A, B, cin=0): """Return symbolic logic for an N-bit Kogge-Stone adder.""" if len(A) != len(B): raise ValueError("expected A and B to be equal length") N = len(A) # generate/propagate logic g = [A[i] * B[i] for i in range(N)] p = [Xor(A[i], B[i]) for i in range(N)] for i in range(clog2(N)): start = 1 << i for j in range(start, N): g[j] = g[j] + p[j] * g[j-start] p[j] = p[j] * p[j-start] # sum logic s = [Xor(A[i], B[i], (cin if i == 0 else g[i-1])) for i in range(N)] return BitVector(s), BitVector(g)
def kogge_stone_add(A, B, cin=0): """Return symbolic logic for an N-bit Kogge-Stone adder.""" if len(A) != len(B): raise ValueError("expected A and B to be equal length") N = len(A) # generate/propagate logic gs = [A[i] & B[i] for i in range(N)] ps = [A[i] ^ B[i] for i in range(N)] for i in range(clog2(N)): start = 1 << i for j in range(start, N): gs[j] = gs[j] | ps[j] & gs[j-start] ps[j] = ps[j] & ps[j-start] # sum logic ss = [A[0] ^ B[0] ^ cin] ss += [A[i] ^ B[i] ^ gs[i-1] for i in range(1, N)] return farray(ss), farray(gs)
def kogge_stone_add(A, B, cin=0): """Return symbolic logic for an N-bit Kogge-Stone adder.""" if len(A) != len(B): raise ValueError("expected A and B to be equal length") N = len(A) # generate/propagate logic gs = [A[i] & B[i] for i in range(N)] ps = [A[i] ^ B[i] for i in range(N)] for i in range(clog2(N)): start = 1 << i for j in range(start, N): gs[j] = gs[j] | ps[j] & gs[j - start] ps[j] = ps[j] & ps[j - start] # sum logic ss = [A[0] ^ B[0] ^ cin] ss += [A[i] ^ B[i] ^ gs[i - 1] for i in range(1, N)] return farray(ss), farray(gs)
def create_and_render_memory_template(template_path, output_path, program_elements, data_start, mem_size, trap_address=None): if (max([int(x[0] + len(x[1]) - data_start // 4) for x in program_elements] + [1]) * 4) > mem_size: raise Exception("Memory Size Exceeded") num_words = 2 ** clog2( max([int(x[0] + len(x[1]) - data_start // 4) for x in program_elements] + [1]) * 4 ) array_offset = data_start // 4 with open(template_path, 'r') as template_fp: template = Template(template_fp.read(), lstrip_blocks=True, trim_blocks=True) with open(str(output_path), "w") as output_file: output_file.write(template.render( program_elements=program_elements, num_words=num_words, array_offset=array_offset )) if trap_address: return output_path, num_words, trap_address else: return output_path, num_words