class Permute(Circuit): name = na IO = ["I", In(Bits(n)), "O", Out(Bits(n))] @classmethod def definition(io): [wire(io.I[permutation[i]], io.O[i]) for i in range(len(io.I))]
def DefineDualRAM(height, width): n = 1 << height TADDR = Bits(height) TDATA = Bits(width) class _DualRAM(Circuit): name = 'DualRAM{}x{}'.format(n, width) IO = [ 'RADDR0', In(TADDR), 'RDATA0', Out(TDATA), 'RADDR1', In(TADDR), 'RDATA1', Out(TDATA), 'WADDR', In(TADDR), 'WDATA', In(TDATA), 'WE', In(Bit), 'CLK', In(Clock) ] @classmethod def definition(io): regs = REGs(n, width, has_ce=True) writeport(height, width, regs, io.WADDR, io.WDATA, io.WE) wire(readport(height, width, regs, io.RADDR0), io.RDATA0) wire(readport(height, width, regs, io.RADDR1), io.RDATA1) return _DualRAM
class Swap(Circuit): IO = ['I', In(Bits(2)), "O", Out(Bits(2))] @classmethod def definition(io): swap = uncurry(fork(And(2), Or(2)), prefix="I") #swap = uncurry( fork( And(2), Or(2) ) , prefix="in") wire(swap(io.I), io.O)
class Swaps(Circuit): name = 'Swap{}'.format(n) IO = ['I', In(Bits(n)), "O", Out(Bits(n))] @classmethod def definition(io): s = flat(join(map_(Swap, n // 2)), flatargs=['I', 'O']) wire(s(io.I), io.O)
class _PopCount(Circuit): name = 'PopCount{}'.format(n) IO = ['I', In(Bits(n)), 'O', Out(Bits(log2(n) + 1))] @classmethod def definition(io): r = compressor([io.I.as_list()]) wire(bits(r), io.O)
class EvenOddSwaps(Circuit): name = 'EvenOddSwap{}'.format(n) IO = ['I', In(Bits(n)), "O", Out(Bits(n))] @classmethod def definition(io): s = flat(join(map_(Swap, n // 2 - 1)), flatargs=['I', 'O']) wire(io.I[0], io.O[0]) wire(s(io.I[1:-1]), io.O[1:-1]) wire(io.I[-1], io.O[-1])
def DefineRotateK(n, k, op): assert k < n T = Bits(n) class _RotateK(Circuit): name = f'Rotate{n}_{k}' IO = ['I', In(T), 'S', In(Bit), "O", Out(T)] @classmethod def definition(io): Is = [io.I[i] for i in range(n)] muxes = map_(Mux2, n) for i in range(n): if op == 'rol': shifti = (i - k + n) % n I = bits([Is[i], Is[shifti]]) elif op == 'ror': shifti = (i + k) % n I = bits([Is[i], Is[shifti]]) else: assert False muxes[i](I, io.S) for i in range(n): Is[i] = muxes[i].O wire(bits(Is), io.O) return _RotateK
def DefineShiftK(n, k, op): assert k < n T = Bits(n) class _ShiftK(Circuit): name = f'Shift{n}_{k}' IO = ['I', In(T), 'S', In(Bit), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): Is = [io.I[i] for i in range(n)] muxes = map_(Mux2, n) for i in range(n): if op == 'lsl': shifti = i - k I = bits([Is[i], Is[shifti] if shifti >= 0 else io.SI]) elif op == 'lsr' or op == 'asr': shifti = i + k I = bits([Is[i], Is[shifti] if shifti < n else io.SI]) else: assert False muxes[i](I, io.S) for i in range(n): Is[i] = muxes[i].O wire(bits(Is), io.O) return _ShiftK
def DefineSequencer(n): T = Bits(n) class _Sequencer(Circuit): name = 'Sequencer{}'.format(n) IO = [ "addr", In(T), "jump", In(Bit), "we", In(Bit), "O", Out(T), "CLK", In(Clock) ] @classmethod def definition(io): pc = Register(n, has_ce=True) add = Add(n) mux = Mux(2, n) add(pc, bits(1, n=n)) pc(mux) wire(add.O, mux.I0) wire(io.addr, mux.I1) wire(io.jump, mux.S) wire(io.CLK, pc.CLK) wire(io.we, pc.CE) wire(pc.O, io.O) return _Sequencer
class CoreirConst(Circuit): name = f"coreir_const{width}{value}" IO = ["out", Out(Bits(width))] @classmethod def definition(io): wire(io.out, bits(value, width))
def DefineCoreirConst(width, value): def simulate_coreir_const(self, value_store, state_store): value_store.set_value(self.O, value) return DeclareCoreirCircuit(f"coreir_const{width}{value}", "O", Out(Bits(width)), coreir_name="const", coreir_lib="coreir", coreir_genargs={"width": width}, coreir_configargs={"value": BitVector(value, width)}, simulate=simulate_coreir_const)
class _Barrel(Circuit): name = 'Barrel{}'.format(n) IO = ['I', In(T), 'S', In(Bits(logn)), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = BarrelShift(n, 1<<k)(I, io.S[k], io.SI) wire(I, io.O)
class _Shift(Circuit): name = f'Shift{n}' IO = ['I', In(T), 'S', In(Bits(logn)), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = ShiftK(n, 1 << k, op)(I, io.S[k], io.SI) wire(I, io.O)
class _Rotate(Circuit): name = f'Rotate{n}' IO = ['I', In(T), 'S', In(Bits(logn)), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = RotateK(n, 1 << k, op)(I, io.S[k]) wire(I, io.O)
def DefineROM(height, width, data): assert height >= 4 n = 1 << height data = interleave16(data, width) TADDR = Bits(height) TDATA = Bits(width) class _ROM(Circuit): name = f'ROM{n}x{width}' IO = ['RADDR', In(TADDR), 'RDATA', Out(TDATA)] @classmethod def definition(io): roms = ROM4s(n, width, data) [roms[i](io.RADDR[0:4]) for i in range(n // 16)] wire(readport(height - 4, width, roms, io.RADDR[4:]), io.RDATA) return _ROM
def DefineBarrel(n): assert n in [2, 4, 8, 16] logn = log2(n) T = Bits(n) class _Barrel(Circuit): name = 'Barrel{}'.format(n) IO = ['I', In(T), 'S', In(Bits(logn)), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = BarrelShift(n, 1<<k)(I, io.S[k], io.SI) wire(I, io.O) return _Barrel
def DefineMain(self): arrays = {} # form arrays for p in self.pins: if p.used: # find names of the form %s[%d] # these are considered arrays match = re.findall('(.*)\[(\d+)\]', p.name) if match: name, i = match[0] i = int(i) # keep track of the indices if name in arrays: arrays[name].append(i) else: arrays[name] = [i] # collect top level module arguments args = [] for p in self.pins: if p.used: match = re.findall('(.*)\[(\d+)\]', p.name) if match: name, i = match[0] assert name in arrays if len(arrays[name]) == 1: p.rename(name) args.append(name) args.append(In(Bit) if p.direction == INPUT else Out(Bit)) else: i = int(i) if i == max(arrays[name]): args.append(name) T = Bits(i+1) args.append(In(T) if p.direction == INPUT else Out(T)) else: args.append(p.name) if p.name == 'CLKIN': assert p.direction == INPUT args.append(In(Clock)) else: args.append(In(Bit) if p.direction == INPUT else Out(Bit)) D = DefineCircuit('main',*args) D.fpga = self for p in self.peripherals: if p.used: #print(p) p.setup(D) return D
def DefineRAM(height, width): n = 1 << height TADDR = Bits(height) TDATA = Bits(width) class _RAM(Circuit): name = f'RAM{n}x{width}' IO = [ 'RADDR', In(TADDR), 'RDATA', Out(TDATA), 'WADDR', In(TADDR), 'WDATA', In(TDATA), 'WE', In(Bit), 'CLK', In(Clock) ] @classmethod def definition(io): regs = REGs(n, width, has_ce=True) writeport(height, width, regs, io.WADDR, io.WDATA, io.WE) wire(readport(height, width, regs, io.RADDR), io.RDATA) return _RAM
class _Switches(Part): name = 'switch' + str(n) IO = ["O", Out(Bits(n))] def __init__(self): super(_Switches, self).__init__(name, board) self.n = n def on(self, n): assert n <= self.n for i in range(n): gpio = self.O[i].getgpio() gpio.input().on() Part.on(self) return self
def DefineShift(n, op): assert n in [2, 4, 8, 16] logn = log2(n) T = Bits(n) class _Shift(Circuit): name = f'Shift{n}' IO = ['I', In(T), 'S', In(Bits(logn)), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = ShiftK(n, 1 << k, op)(I, io.S[k], io.SI) wire(I, io.O) return _Shift
def DefineRotate(n, op): assert n in [2, 4, 8, 16] logn = log2(n) T = Bits(n) class _Rotate(Circuit): name = f'Rotate{n}' IO = ['I', In(T), 'S', In(Bits(logn)), "O", Out(T)] @classmethod def definition(io): I = io.I for k in range(logn): I = RotateK(n, 1 << k, op)(I, io.S[k]) wire(I, io.O) return _Rotate
def DefineBarrelShift(n, k): assert k < n T = Bits(n) class _BarrelShift(Circuit): name = 'BarrelShift{}_{}'.format(n, k) IO = ['I', In(T), 'S', In(Bit), 'SI', In(Bit), "O", Out(T)] @classmethod def definition(io): Is = [io.I[i] for i in range(n)] muxes = map_(Mux(2), n) for i in range(n): shifti = i - k I = bits([Is[i], Is[shifti] if shifti >= 0 else io.SI]) muxes[i]( I, io.S ) for i in range(n): Is[i] = muxes[i].O wire(bits(Is), io.O) return _BarrelShift
def DefineBuf(width=1): """ Generate Buf module I : In(Bits(width)), O : Out(Bits(width)) """ T = Bits(width) class BufN(Circuit): name = 'Buf{}'.format(width) IO = ['I', In(T), 'O', Out(T)] @classmethod def definition(def_): def buf(y): return Buf(loc=(0,y//8, y%8)) buffer = join(col(buf, width)) wire(def_.I, buffer.I0) wire(buffer.O, def_.O) return BufN
def Decode(i, n, invert=False, **kwargs): """ Decode the n-bit number i. @return: 1 if the n-bit input equals i """ assert n <= 8 if os.environ["MANTLE"] == "coreir": from mantle import eq from magma import Bits, In, Bit, DefineCircuit, EndDefine, wire, bits, Out circ = DefineCircuit(f"Decode{i}{n}", "I", In(Bits(n)), "O", Out(Bit)) wire(circ.O, eq(circ.I, bits(i, n))) EndDefine() return circ() i = 1 << i if invert: m = 1 << n mask = (1 << m) - 1 i = mask & (~i) return uncurry(LUT(i, n, **kwargs))