diff --git a/examples/coreir/counters.py b/examples/coreir/counters.py index 2b3ec81..29b15b4 100644 --- a/examples/coreir/counters.py +++ b/examples/coreir/counters.py @@ -1,14 +1,14 @@ +import mantle.coreir +from mantle import * +from magma import * import os os.environ['MANTLE'] = 'coreir' -from magma import * -from mantle import * -import mantle.coreir def DefineMantleReg(init): class MantleReg(Circuit): name = f"MantleReg{init}" - IO = ["in", In(Bits(16)), "clk", In(Clock), "out", Out(Bits(16)), "clr", In(Bit)] + io = m.IO(in=In(Bits(16)), clk=In(Clock), out=Out(Bits(16)), clr=In(Bit)) @classmethod def definition(io): c0 = bits(0, 16) @@ -25,7 +25,7 @@ def definition(io): class Counter(Circuit): name = "Counter16" - IO = ["clk", In(Clock), "clr", In(Bit), "out", Out(Bits(16))] + io = m.IO(clk=In(Clock), clr=In(Bit), out=Out(Bits(16))) @classmethod def definition(io): @@ -35,13 +35,15 @@ def definition(io): wire(c1, a.in0) wire(r.out, a.in1) wire(r.clk, io.clk) - wire(a.out, getattr(r, "in")) # r.in doesn't work because in is a keyword + # r.in doesn't work because in is a keyword + wire(a.out, getattr(r, "in")) wire(r.out, io.out) wire(io.clr, r.clr) + class Counters(Circuit): name = "Counters" - IO = ["clk", In(Clock)] + io = m.IO(clk=In(Clock)) @classmethod def definition(io): count0 = Counter(16) diff --git a/examples/coreir/counters_wire.py b/examples/coreir/counters_wire.py index c0c6f9b..415a98e 100644 --- a/examples/coreir/counters_wire.py +++ b/examples/coreir/counters_wire.py @@ -1,14 +1,14 @@ +import mantle.coreir +from mantle import * +from magma import * import os os.environ['MANTLE'] = 'coreir' -from magma import * -from mantle import * -import mantle.coreir def DefineMantleReg(init): class MantleReg(Circuit): name = f"MantleReg{init}" - IO = ["in", In(Bits(16)), "clk", In(Clock), "out", Out(Bits(16)), "clr", In(Bit)] + io = m.IO(in=In(Bits(16)), clk=In(Clock), out=Out(Bits(16)), clr=In(Bit)) @classmethod def definition(io): c0 = bits(0, 16) @@ -25,7 +25,7 @@ def definition(io): class Counter(Circuit): name = "Counter16" - IO = ["clk", In(Clock), "clr", In(Bit), "out", Out(Bits(16))] + io = m.IO(clk=In(Clock), clr=In(Bit), out=Out(Bits(16))) @classmethod def definition(io): @@ -35,21 +35,23 @@ def definition(io): wire(c1, a.in0) wire(r.out, a.in1) wire(r.clk, io.clk) - wire(a.out, getattr(r, "in")) # r.in doesn't work because in is a keyword + # r.in doesn't work because in is a keyword + wire(a.out, getattr(r, "in")) wire(r.out, io.out) wire(io.clr, r.clr) + class Counters(Circuit): name = "Counters_wire" - IO = ["clk", In(Clock)] + io = m.IO(clk=In(Clock)) @classmethod def definition(io): count0_out = DefineWire(16)(name="mywire0") count1_out = DefineWire(16)(name="mywire1") count0_clr = count1_out.O[8] count1_clr = count0_out.O[4] - count0 = Counter(16,name="count0") - count1 = Counter(16,name="count1") + count0 = Counter(16, name="count0") + count1 = Counter(16, name="count1") count0( clk=io.clk, out=count0_out.I, diff --git a/examples/fsm/top.py b/examples/fsm/top.py index 5b6a0cf..221d617 100644 --- a/examples/fsm/top.py +++ b/examples/fsm/top.py @@ -28,7 +28,8 @@ def fsm_logic(current_state: m.Bits(2), next_state = State.HBLANK next_pixel_count = m.bits(0, 11) elif current_state == State.HACT: - next_state = State.HBLANK if pixel_count == m.bits(1, 11) else State.HACT + next_state = State.HBLANK if pixel_count == m.bits( + 1, 11) else State.HACT # TODO: Support AugAssign node # next_pixel_count -= 1 next_pixel_count = pixel_count - m.uint(1, 11) @@ -39,11 +40,11 @@ def fsm_logic(current_state: m.Bits(2), class MagmaFSM(m.Circuit): - IO = ["frameValid", m.In(m.Bit), - "clk", m.In(m.Clock), - "rst", m.In(m.AsyncReset), - "real_href", m.In(m.Bit), - "pixel_valid", m.Out(m.Bit)] + io = m.IO(frameValid=m.In(m.Bit), + clk=m.In(m.Clock), + rst=m.In(m.AsyncReset), + real_href=m.In(m.Bit), + pixel_valid=m.Out(m.Bit)) @classmethod def definition(io): diff --git a/mantle/common/RAM.py b/mantle/common/RAM.py index c4e8089..a3545f9 100644 --- a/mantle/common/RAM.py +++ b/mantle/common/RAM.py @@ -6,11 +6,13 @@ __all__ = ["DefineRAM", "DefineDualRAM"] + def REGs(n, width, has_ce): return [Register(width, has_ce=has_ce) for i in range(n)] + def MUXs(n, width): - return [Mux(2,width) for i in range(n)] + return [Mux(2, width) for i in range(n)] def readport(addr_width, width, regs, raddr): @@ -35,7 +37,7 @@ def writeport(addr_width, width, regs, WADDR, I, WE): n = 1 << addr_width decoder = Decoder(addr_width) - enable = And(2,n) + enable = And(2, n) enable(decoder(WADDR), repeat(WE, n)) for i in range(n): @@ -44,49 +46,49 @@ def writeport(addr_width, width, regs, WADDR, I, WE): def DefineRAM(height, width): addr_width = clog2(height) - TADDR = Bits[ addr_width ] - TDATA = Bits[ width ] + TADDR = Bits[addr_width] + TDATA = Bits[width] class _RAM(Circuit): name = f'RAM{height}x{width}' - IO = ['RADDR', In(TADDR), - 'RDATA', Out(TDATA), - 'WADDR', In(TADDR), - 'WDATA', In(TDATA), - 'WE', In(Bit), - 'CLK', In(Clock) - ] + io = m.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(height, width, has_ce=True) writeport(addr_width, width, regs, io.WADDR, io.WDATA, io.WE) - wire( readport(addr_width, width, regs, io.RADDR), io.RDATA ) + wire(readport(addr_width, width, regs, io.RADDR), io.RDATA) return _RAM def DefineDualRAM(height, width): addr_width = clog2(height) - TADDR = Bits[ addr_width ] - TDATA = Bits[ width ] + TADDR = Bits[addr_width] + TDATA = Bits[width] class _DualRAM(Circuit): name = f'DualRAM{height}x{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)] + io = m.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(addr_width, width, regs, io.WADDR, io.WDATA, io.WE) - wire( readport(addr_width, width, regs, io.RADDR0), io.RDATA0 ) - wire( readport(addr_width, width, regs, io.RADDR1), io.RDATA1 ) + wire(readport(addr_width, width, regs, io.RADDR0), io.RDATA0) + wire(readport(addr_width, width, regs, io.RADDR1), io.RDATA1) return _DualRAM diff --git a/mantle/common/ROM.py b/mantle/common/ROM.py index e8c5a67..e0f14f1 100644 --- a/mantle/common/ROM.py +++ b/mantle/common/ROM.py @@ -4,26 +4,31 @@ from mantle import Mux from .RAM import readport -__all__ = ['DefineROM', 'ROM'] +__all__ = ['DefineROM', 'ROM'] + def ROM4(data, i, width): return fork([uncurry(LUT(data[i][w], 4)) for w in range(width)]) + def ROM4s(n, width, data): return [ROM4(data, i, width) for i in range(n//16)] + def MUXs(n, width): - return [Mux(2,width) for i in range(n)] + return [Mux(2, width) for i in range(n)] + def interleave16(data, width): n = len(data) bits = [int2seq(data[i], width) for i in range(n)] #print(n, bits) - data = [ [ [bits[i+j][w] for j in range(16)] for w in range(width)] \ - for i in range(0,n,16) ] + data = [[[bits[i+j][w] for j in range(16)] for w in range(width)] + for i in range(0, n, 16)] #print(len(data), data) return data + def DefineROM(height, width, data): assert height >= 4 n = 1 << height @@ -35,16 +40,16 @@ def DefineROM(height, width, data): class _ROM(Circuit): name = f'ROM{n}x{width}' - IO = ['RADDR', In(TADDR), 'RDATA', Out(TDATA)] + io = m.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 ) + wire(readport(height-4, width, roms, io.RADDR[4:]), io.RDATA) return _ROM + def ROM(height, width, data=None): return DefineROM(height, width, data=data)() - diff --git a/mantle/common/arbiter.py b/mantle/common/arbiter.py index 8e7bf3e..7ae383d 100644 --- a/mantle/common/arbiter.py +++ b/mantle/common/arbiter.py @@ -8,24 +8,30 @@ # an Arbiter returns an array with only a single bit set, # in this case the lowest bit set is retained # + + def DefineArbiter(n): - T = Bits[ n ] + T = Bits[n] + class _Arbiter(Circuit): name = 'Arbiter'+str(n) - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(Arb): ones = n * [1] y = DefineAdd(n)()(Arb.I, array(ones)) # y = x - 1 + def a(y): - return LUT([0, 1, 0, 0]) # A0 & ~A1 + return LUT([0, 1, 0, 0]) # A0 & ~A1 arb = join(col(a, n)) arb(Arb.I, y) wire(arb.O, Arb.O) return _Arbiter + def Arbiter(n, **kwargs): return DefineArbiter(n)(**kwargs) + def arbiter(I, **kwargs): return Arbiter(len(I), **kwargs)(I) diff --git a/mantle/common/barrel.py b/mantle/common/barrel.py index 98fc00a..19d5e51 100644 --- a/mantle/common/barrel.py +++ b/mantle/common/barrel.py @@ -2,8 +2,8 @@ from magma.bitutils import log2 from mantle import Mux2 -__all__ = ['DefineShift', 'Shift'] -__all__ = ['DefineLSL', 'LSL'] +__all__ = ['DefineShift', 'Shift'] +__all__ = ['DefineLSL', 'LSL'] __all__ += ['DefineLSR', 'LSR'] __all__ += ['DefineASR', 'ASR'] @@ -11,52 +11,58 @@ __all__ += ['DefineROL', 'ROL'] __all__ += ['DefineROR', 'ROR'] + def DefineShiftK(n, k, op): assert k < n - T = Bits[ n ] + T = Bits[n] + class _ShiftK(Circuit): name = f'{op.upper()}{n}_{k}' - IO = ['I', In(T), 'S', In(Bit), "O", Out(T)] + io = m.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 == 'lsl': + if op == 'lsl': shifti = i - k I = bits([Is[i], Is[shifti] if shifti >= 0 else 0]) elif op == 'lsr': shifti = i + k - I = bits([Is[i], Is[shifti] if shifti < n else 0]) + I = bits([Is[i], Is[shifti] if shifti < n else 0]) elif op == 'asr': shifti = i + k - I = bits([Is[i], Is[shifti] if shifti < n else Is[n-1]]) + I = bits([Is[i], Is[shifti] if shifti < n else Is[n-1]]) else: assert False - muxes[i]( I, io.S ) + muxes[i](I, io.S) for i in range(n): Is[i] = muxes[i].O wire(bits(Is), io.O) return _ShiftK + def ShiftK(n, k, op): return DefineShiftK(n, k, op)() + def DefineShift(n, op): assert n in [2, 4, 8, 16] logn = log2(n) - T = Bits[ n ] + T = Bits[n] + class _Shift(Circuit): name = f'{op.upper()}{n}' - IO = ['I', In(T), 'S', In(Bits[ logn ]), "O", Out(T)] + io = m.IO(I=In(T), S=In(Bits[logn]), O=Out(T)) @classmethod def definition(io): I = io.I for k in range(logn): - I = ShiftK(n, 1< 0: args += ["I0", cascade.I1] - if k > 1: args += ["I1", cascade.I2] - if k > 2: args += ["I2", cascade.I3] + if k > 0: + args += ["I0", cascade.I1] + if k > 1: + args += ["I1", cascade.I2] + if k > 2: + args += ["I2", cascade.I3] args += ["O", cascade.O] return AnonymousCircuit(*args) + class EQNone(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - EQ1LUT = ((A0&A1)|(~A0&~A1)) - wire( LUT2(EQ1LUT)(io.I0, io.I1), io.O ) + EQ1LUT = ((A0 & A1) | (~A0 & ~A1)) + wire(LUT2(EQ1LUT)(io.I0, io.I1), io.O) + class EQ1(Circuit): - IO = ["I0", In(Bits[ 1 ]), "I1", In(Bits[ 1 ]), "O", Out(Bit)] + io = m.IO(I0=In(Bits[1]), I1=In(Bits[1]), O=Out(Bit)) @classmethod def definition(io): wire(EQNone()(io.I0[0], io.I1[0]), io.O) + class EQ2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - EQ2LUT = ((A0&A1)|(~A0&~A1)) & ((A2&A3)|(~A2&~A3)) - wire( LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + EQ2LUT = ((A0 & A1) | (~A0 & ~A1)) & ((A2 & A3) | (~A2 & ~A3)) + wire(LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineEQ(n): - T = Bits[ n ] + T = Bits[n] + class _EQ(Circuit): name = "EQ{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - eq = _Cascade(n, 2, A0&((A1&A2)|(~A1&~A2)), 1) - wire(eq(io.I0, io.I1), io.O) + eq = _Cascade(n, 2, A0 & ((A1 & A2) | (~A1 & ~A2)), 1) + wire(eq(io.I0, io.I1), io.O) return _EQ + def EQ(n, **kwargs): - if n == None: + if n == None: return EQNone(**kwargs) elif n == 1: return EQ1(**kwargs) @@ -83,33 +94,37 @@ def EQ(n, **kwargs): class NE1(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - NE1LUT = (A0^A1) - wire( LUT2(NE1LUT)(io.I0, io.I1), io.O ) + NE1LUT = (A0 ^ A1) + wire(LUT2(NE1LUT)(io.I0, io.I1), io.O) + class NE2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - NE2LUT = (A0^A1)|(A2^A3) - wire( LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + NE2LUT = (A0 ^ A1) | (A2 ^ A3) + wire(LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineNE(n): - T = Bits[ n ] + T = Bits[n] + class _NE(Circuit): name = "NE{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - ne = _Cascade(n, 2, A0|(A1^A2), 0) - wire(ne(io.I0, io.I1), io.O) + ne = _Cascade(n, 2, A0 | (A1 ^ A2), 0) + wire(ne(io.I0, io.I1), io.O) return _NE + def NE(n, **kwargs): - if n == 1: + if n == 1: return NE1(**kwargs) elif n == 2: return NE2(**kwargs) @@ -120,9 +135,10 @@ def NE(n, **kwargs): def DefineUCMP(opname, reverse, negate, n): T = UInt[n] + class _UCMP(Circuit): name = "{}{}".format(opname, n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): sub = DefineSub(n, False, True)() @@ -136,15 +152,19 @@ def definition(io): wire(Not()(sub.COUT), io.O) return _UCMP + def DefineUGE(n): return DefineUCMP('UGE', False, False, n) + def DefineULE(n): return DefineUCMP('ULE', True, False, n) + def DefineULT(n): return DefineUCMP('ULT', False, True, n) + def DefineUGT(n): return DefineUCMP('UGT', True, True, n) @@ -154,33 +174,39 @@ def DefineUGT(n): def _sge(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & ~c_msb) | (~a_msb & b_msb)) & 1 + def _slt(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & c_msb) | (a_msb & ~b_msb)) & 1 + def DefineSCMP(opname, op, reverse, n): T = SInt[n] + class _SCMP(Circuit): - name = "{}{}".format(opname,n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + name = "{}{}".format(opname, n) + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): sub = DefineSub(n)() cmp = LUT3(op) if not reverse: - wire(cmp( sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1] ), io.O) + wire(cmp(sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1]), io.O) else: - wire(cmp( sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1] ), io.O) + wire(cmp(sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1]), io.O) return _SCMP + def DefineSGE(n): return DefineSCMP('SGE', _sge, False, n) + def DefineSLE(n): return DefineSCMP('SLE', _sge, True, n) + def DefineSLT(n): return DefineSCMP('SLT', _slt, False, n) + def DefineSGT(n): return DefineSCMP('SGT', _slt, True, n) - diff --git a/mantle/lattice/mantle40/fulladder.py b/mantle/lattice/mantle40/fulladder.py index c9fe2ed..7a65217 100644 --- a/mantle/lattice/mantle40/fulladder.py +++ b/mantle/lattice/mantle40/fulladder.py @@ -2,16 +2,18 @@ from ..ice40.PLB import SB_CARRY, A0, A1, A2 from .LUT import LUT3 -__all__ = ["FullAdder", 'fulladder'] +__all__ = ["FullAdder", 'fulladder'] + class FullAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "CIN", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), CIN=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - sum = LUT3(A0^A1^A2) - carry = SB_CARRY() # (A0&A1)|(A1&A2)|(A2&A0) - wire( sum(io.I0,io.I1,io.CIN), io.O ) - wire( carry(io.I0,io.I1,io.CIN), io.COUT ) + sum = LUT3(A0 ^ A1 ^ A2) + carry = SB_CARRY() # (A0&A1)|(A1&A2)|(A2&A0) + wire(sum(io.I0, io.I1, io.CIN), io.O) + wire(carry(io.I0, io.I1, io.CIN), io.COUT) + def fulladder(a, b, c, **kwargs): return FullAdder()(a, b, c, **kwargs) diff --git a/mantle/lattice/mantle40/halfadder.py b/mantle/lattice/mantle40/halfadder.py index ae4e082..9c56240 100644 --- a/mantle/lattice/mantle40/halfadder.py +++ b/mantle/lattice/mantle40/halfadder.py @@ -2,17 +2,18 @@ from ..ice40.PLB import SB_CARRY, A0, A1, A2, A3 from .LUT import LUT2 -__all__ = ["HalfAdder", 'halfadder'] +__all__ = ["HalfAdder", 'halfadder'] + class HalfAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - sum = LUT2(A0^A1) - carry = SB_CARRY() # (A0&A1)|(A1&A2)|(A2&A0) - wire( sum(io.I0,io.I1), io.O ) - wire( carry(io.I0,io.I1,0), io.COUT ) + sum = LUT2(A0 ^ A1) + carry = SB_CARRY() # (A0&A1)|(A1&A2)|(A2&A0) + wire(sum(io.I0, io.I1), io.O) + wire(carry(io.I0, io.I1, 0), io.COUT) + def halfadder(a, b, **kwargs): return HalfAdder()(a, b, **kwargs) - diff --git a/mantle/lattice/mantle40/logic.py b/mantle/lattice/mantle40/logic.py index 082a964..24e76ec 100644 --- a/mantle/lattice/mantle40/logic.py +++ b/mantle/lattice/mantle40/logic.py @@ -1,14 +1,14 @@ from __future__ import division +from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3 +from magma import * +from collections.abc import Sequence import sys if sys.version_info > (3, 0): from functools import reduce from functools import lru_cache -from collections.abc import Sequence -from magma import * -from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3 # unary operators -__all__ = ['DefineReduceAnd', 'ReduceAnd'] +__all__ = ['DefineReduceAnd', 'ReduceAnd'] __all__ += ['DefineReduceNAnd', 'ReduceNAnd'] __all__ += ['DefineReduceOr', 'ReduceOr'] __all__ += ['DefineReduceNOr', 'ReduceNOr'] @@ -27,80 +27,100 @@ __all__ += ['DefineInvert', 'Invert'] __all__ += ['Not'] + def FlatCascade(n, k, expr, cin, **kwargs): - def f(y): - e = expr[y] if isinstance(expr, Sequence) else expr - return LUT( e, n=k+1 ) + def f(y): + e = expr[y] if isinstance(expr, Sequence) else expr + return LUT(e, n=k+1) + + # number of luts + m = (n+k-1) // k + c = braid(col(f, m), foldargs={"I0": "O"}) - # number of luts - m = (n+k-1) // k - c = braid( col(f, m), foldargs={"I0":"O"}) + wire(cin, c.I0) - wire(cin, c.I0) + c = flat(uncurry(c)) - c = flat(uncurry(c)) + for i in range(n, len(c.I)): + wire(cin, c.I[i]) - for i in range(n, len(c.I)): - wire(cin, c.I[i]) + return AnonymousCircuit(['I', c.I[0:n], 'O', c.O]) - return AnonymousCircuit( ['I', c.I[0:n], 'O', c.O] ) def DefineReduceOp(opname, n, luts, cascadeexpr, cin): - T = Bits[ n ] + T = Bits[n] + class _ReduceOp(Circuit): name = '{}{}'.format(opname, n) - IO = ['I', In(T), 'O', Out(Bit)] + io = m.IO(I=In(T), O=Out(Bit)) @classmethod def definition(io): - if n == 1: a = uncurry(LUT1(luts[n - 1])) - elif n == 2: a = uncurry(LUT2(luts[n - 1])) - elif n == 3: a = uncurry(LUT3(luts[n - 1])) - elif n == 4: a = uncurry(LUT4(luts[n - 1])) - else: a = FlatCascade(n, 1, cascadeexpr, cin) + if n == 1: + a = uncurry(LUT1(luts[n - 1])) + elif n == 2: + a = uncurry(LUT2(luts[n - 1])) + elif n == 3: + a = uncurry(LUT3(luts[n - 1])) + elif n == 4: + a = uncurry(LUT4(luts[n - 1])) + else: + a = FlatCascade(n, 1, cascadeexpr, cin) wire(a(io.I), io.O) return _ReduceOp + def DefineReduceAnd(n): - luts = [A0, A0&A1, A0&A1&A2, A0&A1&A2&A3] + luts = [A0, A0 & A1, A0 & A1 & A2, A0 & A1 & A2 & A3] return DefineReduceOp('And', n, luts, A0 & A1, 1) + def ReduceAnd(height=2, **kwargs): return DefineReduceAnd(height)(**kwargs) + def DefineReduceNAnd(n): - luts = [~A0, ~(A0&A1), ~(A0&A1&A2), ~(A0&A1&A2&A3)] + luts = [~A0, ~(A0 & A1), ~(A0 & A1 & A2), ~(A0 & A1 & A2 & A3)] return DefineReduceOp('NAnd', n, luts, A0 & ~A1, 0) + def ReduceNAnd(height=2, **kwargs): return DefineReduceNAnd(height)(**kwargs) + def DefineReduceOr(n): - luts = [A0, A0|A1, A0|A1|A2, A0|A1|A2|A3] + luts = [A0, A0 | A1, A0 | A1 | A2, A0 | A1 | A2 | A3] return DefineReduceOp('Or', n, luts, A0 | A1, 0) + def ReduceOr(height=2, **kwargs): return DefineReduceOr(height)(**kwargs) + def DefineReduceNOr(n): - luts = [~A0, ~(A0|A1), ~(A0|A1|A2), ~(A0|A1|A2|A3)] + luts = [~A0, ~(A0 | A1), ~(A0 | A1 | A2), ~(A0 | A1 | A2 | A3)] return DefineReduceOp('NOr', n, luts, A0 | ~A1, 1) + def ReduceNOr(height=2, **kwargs): return DefineReduceNOr(height)(**kwargs) + def DefineReduceXOr(n): - luts = [A0, A0^A1, A0^A1^A2, A0^A1^A2^A3] + luts = [A0, A0 ^ A1, A0 ^ A1 ^ A2, A0 ^ A1 ^ A2 ^ A3] return DefineReduceOp('XOr', n, luts, A0 ^ A1, 0) + def ReduceXOr(height=2, **kwargs): return DefineReduceXOr(height)(**kwargs) + def DefineReduceNXOr(n): - luts = [~A0, ~(A0^A1), ~(A0^A1^A2), ~(A0^A1^A2^A3)] + luts = [~A0, ~(A0 ^ A1), ~(A0 ^ A1 ^ A2), ~(A0 ^ A1 ^ A2 ^ A3)] return DefineReduceOp('NXOr', n, luts, A0 ^ ~A1, 1) + def ReduceNXOr(height=2, **kwargs): return DefineReduceNXOr(height)(**kwargs) @@ -111,13 +131,13 @@ def DefineOp(opname, op, height=2, width=1): I0 : In(Bits(width)), I1 : In(Bits(width)), O : Out(Bits(width)) """ - T = Bits[ width ] + T = Bits[width] class _Op(Circuit): name = '{}{}x{}'.format(opname, height, width) IO = sum([['I{}'.format(i), In(T)] for i in range(height)], []) - IO += ['O', Out(T)] + IO += ['O', Out(T)] @classmethod def definition(io): @@ -129,49 +149,61 @@ def opm(y): wire(opmxn.O, io.O) return _Op + def DefineAnd(height=2, width=1): return DefineOp('And', ReduceAnd, height, width) + def And(height=2, width=None, **kwargs): if width is None: return curry(ReduceAnd(height, **kwargs)) return DefineAnd(height, width)(**kwargs) + def DefineNAnd(height=2, width=None): return DefineOp('NAnd', ReduceNAnd, height, width) + def NAnd(height=2, width=None, **kwargs): if width is None: return curry(ReduceNAnd(height, **kwargs)) return DefineNAnd(height, width)(**kwargs) + def DefineOr(height=2, width=None): return DefineOp('Or', ReduceOr, height, width) + def Or(height=2, width=None, **kwargs): if width is None: return curry(ReduceOr(height, **kwargs)) return DefineOr(height, width)(**kwargs) + def DefineNOr(height=2, width=None): return DefineOp('NOr', ReduceNOr, height, width) + def NOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNOr(height, **kwargs)) return DefineNOr(height, width)(**kwargs) + def DefineXOr(height=2, width=None): return DefineOp('XOr', ReduceXOr, height, width) + def XOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceXOr(height, **kwargs)) return DefineXOr(height, width)(**kwargs) + def DefineNXOr(height=2, width=None): return DefineOp('NXOr', ReduceNXOr, height, width) + def NXOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNXOr(height, **kwargs)) @@ -185,22 +217,24 @@ def DefineInvert(width): I0 : Bits(width) -> O : Bits(width) """ - T = Bits[ width ] + T = Bits[width] + class _Invert(Circuit): name = 'Invert%d' % width - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(def_): def not_(y): - return Not(loc=(0,y/8, y%8)) + return Not(loc=(0, y/8, y % 8)) invert = join(col(not_, width)) wire(def_.I, invert.I0) wire(invert.O, def_.O) return _Invert + def Invert(n, **kwargs): return DefineInvert(n)(**kwargs) @@ -208,5 +242,3 @@ def Invert(n, **kwargs): def Not(**kwargs): """Not gate - 1-bit input.""" return LUT1(~A0, **kwargs) - - diff --git a/mantle/primitives/arith.py b/mantle/primitives/arith.py index 1af854c..68f5704 100644 --- a/mantle/primitives/arith.py +++ b/mantle/primitives/arith.py @@ -15,6 +15,7 @@ def DeclareAdd(N, cin=False, cout=False): if has_cin: IO_ += ['CIN', In(Bit)] name_ += "_cin" + class Add(Circuit): # Underscores because there's some weird scoping issue here with Python # when trying to capture name and IO @@ -31,7 +32,7 @@ def add(*args, **kwargs): if not all(isinstance(arg, BitsType) for arg in args): # TODO: Something more specific than a ValueError? raise ValueError("Arguments to add should be all Bits" - " {}".format([(arg, type(arg)) for arg in args])) + " {}".format([(arg, type(arg)) for arg in args])) adders = [Add(width, **kwargs) for _ in range(len(args) - 1)] curr = adders[0] wire(args[0], curr.I0) @@ -59,6 +60,7 @@ def DeclareSub(N, cin=False, cout=False, T=m.Bits): if has_cin: IO_ += ['CIN', In(Bit)] name_ += "_cin" + class Sub(Circuit): # Underscores because there's some weird scoping issue here with Python # when trying to capture name and IO @@ -75,7 +77,7 @@ def sub(*args, **kwargs): if not all(isinstance(arg, BitsType) for arg in args): # TODO: Something more specific than a ValueError? raise ValueError("Arguments to sub should be all Bits" - " {}".format([(arg, type(arg)) for arg in args])) + " {}".format([(arg, type(arg)) for arg in args])) subbers = [Sub(width, **kwargs) for _ in range(len(args) - 1)] curr = subbers[0] wire(args[0], curr.I0) @@ -89,17 +91,20 @@ def sub(*args, **kwargs): curr = next_ return curr.O + def DeclareNegate(width): T = Bits[width] + class _Negate(Circuit): name = 'Negate{}'.format(width) - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) return _Negate def DeclareASR(width): T = Bits[width] + class _ASR(Circuit): name = 'ASR{}'.format(width) - IO = ["I0", In(T), "I1", In(T), "O", Out(T)] + io = m.IO(I0=In(T), I1=In(T), O=Out(T)) return _ASR diff --git a/mantle/util/compressor/pop.py b/mantle/util/compressor/pop.py index b7a2c38..df49720 100644 --- a/mantle/util/compressor/pop.py +++ b/mantle/util/compressor/pop.py @@ -4,18 +4,21 @@ __all__ = ['DefinePopCount', 'PopCount', 'popcount'] + def DefinePopCount(n): class _PopCount(Circuit): name = 'PopCount{}'.format(n) - IO = ['I', In(Bits[ n ]), 'O', Out(Bits[ log2(n)+1 ])] + io = m.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 ) + wire(bits(r), io.O) return _PopCount + def PopCount(n, **kwargs): return DefinePopCount(n)(**kwargs) + def popcount(I, **kwargs): return PopCount(len(I), **kwargs)(I) diff --git a/mantle/util/sort/bitonic.py b/mantle/util/sort/bitonic.py index baa34ea..7345e7d 100644 --- a/mantle/util/sort/bitonic.py +++ b/mantle/util/sort/bitonic.py @@ -2,7 +2,7 @@ from .swap import swap from .halfcleaner import HalfCleaner, ReverseHalfCleaner -__all__ = ['DefineBitonicSorter', 'BitonicSorter', 'bitonicsorter'] +__all__ = ['DefineBitonicSorter', 'BitonicSorter', 'bitonicsorter'] __all__ += ['DefineMerger', 'Merger', 'merger'] __all__ += ['DefineSorter', 'Sorter', 'sorter'] @@ -10,12 +10,15 @@ # # HalfCleaner(n) => 2 BitonicSorter(n//2) # + + def DefineBitonicSorter(n): assert n in [2, 4, 8, 16] T = Bits(n) + class _BitonicSorter(Circuit): name = 'BitonicSorter{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): if n == 2: @@ -24,14 +27,16 @@ def definition(io): halfcleaner = HalfCleaner(n) bitonic0 = BitonicSorter(n//2) bitonic1 = BitonicSorter(n//2) - bitonic = flat( join(bitonic0, bitonic1), flatargs=['I','O'] ) - s = compose( bitonic, halfcleaner ) - wire( s(io.I), io.O ) + bitonic = flat(join(bitonic0, bitonic1), flatargs=['I', 'O']) + s = compose(bitonic, halfcleaner) + wire(s(io.I), io.O) return _BitonicSorter + def BitonicSorter(n): return DefineBitonicSorter(n)() + def bitonicsorter(I): return BitonicSorter(len(I))(I) @@ -44,9 +49,10 @@ def bitonicsorter(I): def DefineMerger(n): assert n in [2, 4, 8, 16] T = Bits(n) + class _Merger(Circuit): name = 'Merger{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): if n == 2: @@ -55,43 +61,50 @@ def definition(io): revhalfcleaner = ReverseHalfCleaner(n) bitonic0 = BitonicSorter(n//2) bitonic1 = BitonicSorter(n//2) - bitonic = flat( join(bitonic0, bitonic1), flatargs=['I','O'] ) - s = compose( bitonic, revhalfcleaner ) - wire( s(io.I), io.O ) + bitonic = flat(join(bitonic0, bitonic1), flatargs=['I', 'O']) + s = compose(bitonic, revhalfcleaner) + wire(s(io.I), io.O) return _Merger + def Merger(n): return DefineMerger(n)() + def merger(I): return Merger(len(I))(I) # # Convert an unsorted sequence into a sorted sequence # -# 2 Sorters(n/2) => Merger(n) +# 2 Sorters(n/2) => Merger(n) # + + def DefineSorter(n): assert n in [2, 4, 8, 16] T = Bits(n) + class _Sorter(Circuit): name = 'Sorter{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): - if n == 2: # Sort 2 element sequences + if n == 2: # Sort 2 element sequences wire(swap(io.I), io.O) else: merger = Merger(n) - sorter0 = Sorter(n//2) # bot sorter - sorter1 = Sorter(n//2) # top sorter - sorter = flat( join(sorter0, sorter1), flatargs=['I','O'] ) - s = compose( merger, sorter ) - wire( s(io.I), io.O ) + sorter0 = Sorter(n//2) # bot sorter + sorter1 = Sorter(n//2) # top sorter + sorter = flat(join(sorter0, sorter1), flatargs=['I', 'O']) + s = compose(merger, sorter) + wire(s(io.I), io.O) return _Sorter + def Sorter(n): return DefineSorter(n)() + def sorter(I): return Sorter(len(I))(I) diff --git a/mantle/util/sort/brick.py b/mantle/util/sort/brick.py index 5381262..70d6bfe 100644 --- a/mantle/util/sort/brick.py +++ b/mantle/util/sort/brick.py @@ -3,17 +3,20 @@ from mantle import * from .swap import swaps, evenoddswaps -__all__ = ['DefineBrickSorter', 'BrickSorter', 'bricksorter'] +__all__ = ['DefineBrickSorter', 'BrickSorter', 'bricksorter'] # # Brick Sorter # + + def DefineBrickSorter(n): assert n % 2 == 0 T = Bits(n) + class _BrickSorter(Circuit): name = 'BrickSorter{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): I = io.I @@ -23,8 +26,10 @@ def definition(io): wire(I, io.O) return _BrickSorter + def BrickSorter(n): return DefineBrickSorter(n)() + def bricksorter(I): return BrickSorter(len(I))(I) diff --git a/mantle/util/sort/evenodd.py b/mantle/util/sort/evenodd.py index 0596e7a..142d492 100644 --- a/mantle/util/sort/evenodd.py +++ b/mantle/util/sort/evenodd.py @@ -2,69 +2,78 @@ from .swap import swap, EvenOddSwaps from .permute import Riffle, UnRiffle -__all__ = ['DefineEvenOddMerger', 'EvenOddMerger', 'evenoddmerger'] -__all__ = ['DefineEvenOddSorter', 'EvenOddSorter', 'evenoddsorter'] +__all__ = ['DefineEvenOddMerger', 'EvenOddMerger', 'evenoddmerger'] +__all__ = ['DefineEvenOddSorter', 'EvenOddSorter', 'evenoddsorter'] # # Convert an unsorted sequence into a sorted sequence # -# EvenOdd(n) => 2 EvenOddMerger(n//2) => EvenOddSwaps(n)) +# EvenOdd(n) => 2 EvenOddMerger(n//2) => EvenOddSwaps(n)) # + + def DefineEvenOddMerger(n): assert n in [2, 4, 8, 16] T = Bits(n) + class _EvenOddMerger(Circuit): name = 'EvenOddMerger{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): - if n == 2: # Sort 2 element sequences + if n == 2: # Sort 2 element sequences wire(swap(io.I), io.O) else: unriffle = UnRiffle(n) - merger0 = EvenOddMerger(n//2) # bot merger - merger1 = EvenOddMerger(n//2) # top merger - merger = flat( join(merger0, merger1) ) + merger0 = EvenOddMerger(n//2) # bot merger + merger1 = EvenOddMerger(n//2) # top merger + merger = flat(join(merger0, merger1)) riffle = Riffle(n) - merger = compose( riffle, compose( merger, unriffle ) ) + merger = compose(riffle, compose(merger, unriffle)) evenoddswap = EvenOddSwaps(n) - merger = compose( evenoddswap, merger ) - wire( merger(io.I), io.O ) + merger = compose(evenoddswap, merger) + wire(merger(io.I), io.O) return _EvenOddMerger + def EvenOddMerger(n): return DefineEvenOddMerger(n)() + def evenoddmerger(I): return EvenOddMerger(len(I))(I) # # Convert an unsorted sequence into a sorted sequence # -# 2 EvenOddSorter(n//2) => EvenOddMerger(n)) +# 2 EvenOddSorter(n//2) => EvenOddMerger(n)) # + + def DefineEvenOddSorter(n): assert n in [2, 4, 8, 16] T = Bits(n) + class _EvenOddSorter(Circuit): name = 'EvenOddSorter{}'.format(n) - IO = ['I', In(T), "O", Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): - if n == 2: # Sort 2 element sequences + if n == 2: # Sort 2 element sequences wire(swap(io.I), io.O) else: - sorter0 = EvenOddSorter(n//2) # bot sorter - sorter1 = EvenOddSorter(n//2) # top sorter - sorter = flat( join(sorter0, sorter1) ) + sorter0 = EvenOddSorter(n//2) # bot sorter + sorter1 = EvenOddSorter(n//2) # top sorter + sorter = flat(join(sorter0, sorter1)) merger = EvenOddMerger(n) - sorter = compose( merger, sorter ) - wire( sorter(io.I), io.O ) + sorter = compose(merger, sorter) + wire(sorter(io.I), io.O) return _EvenOddSorter + def EvenOddSorter(n): return DefineEvenOddSorter(n)() + def evenoddsorter(I): return EvenOddSorter(len(I))(I) - diff --git a/mantle/util/sort/permute.py b/mantle/util/sort/permute.py index 860b8a8..cd007a7 100644 --- a/mantle/util/sort/permute.py +++ b/mantle/util/sort/permute.py @@ -1,20 +1,24 @@ from magma import In, Out, Bits, Circuit, wire, cache_definition -__all__ = ['DefinePermute', 'Permute'] +__all__ = ['DefinePermute', 'Permute'] __all__ += ['Reverse'] __all__ += ['Riffle', 'UnRiffle'] __all__ += ['ReverseRiffle', 'UnReverseRiffle'] __all__ += ['EvenOdd'] + def flatten(l): return sum(l, []) + def shuffle(l, r): return flatten([[l[i], r[i]] for i in range(n//2)]) + def concat(l, r): return l+r + def inverse(l): return [l.index(i) for i in range(len(l))] @@ -22,65 +26,82 @@ def inverse(l): def _identity(n): return range(n) + def _reverse(n): return list(reversed(range(n))) + def _even(n): return [2*i for i in range(n//2)] + def _odd(n): return [2*i+1 for i in range(n//2)] + def _bottom(n): return [i for i in range(n//2)] + def _top(n): return [n//2+i for i in range(n//2)] + def _evenodd(n): return _even(n) + _odd(n) + def _riffle(n): return flatten([[i, i+n//2] for i in range(n//2)]) + def _unriffle(n): return inverse(_riffle(n)) + def _reverseriffle(n): return flatten([[i, n-1-i] for i in range(n//2)]) + def _unreverseriffle(n): return inverse(_reverseriffle(n)) -def DefinePermute(na,permutation): + +def DefinePermute(na, permutation): n = len(permutation) + class Permute(Circuit): name = na - IO = ["I", In(Bits(n)), "O", Out(Bits(n))] + io = m.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))] return Permute -def Permute(name,permutation): - return DefinePermute(name,tuple(permutation))() + +def Permute(name, permutation): + return DefinePermute(name, tuple(permutation))() def Reverse(n): - return Permute('Reverse{}'.format(n),_reverse(n)) + return Permute('Reverse{}'.format(n), _reverse(n)) + def Riffle(n): - return Permute('Riffle{}'.format(n),_riffle(n)) + return Permute('Riffle{}'.format(n), _riffle(n)) + def UnRiffle(n): - return Permute('UnRiffle{}'.format(n),_unriffle(n)) + return Permute('UnRiffle{}'.format(n), _unriffle(n)) + def ReverseRiffle(n): - return Permute('ReverseRiffle{}'.format(n),_reverseriffle(n)) + return Permute('ReverseRiffle{}'.format(n), _reverseriffle(n)) + def UnReverseRiffle(n): - return Permute('UnReverseRiffle{}'.format(n),_unreverseriffle(n)) + return Permute('UnReverseRiffle{}'.format(n), _unreverseriffle(n)) -def EvenOdd(n): - return Permute('EvenOdd{}'.format(n),_evenodd(n)) +def EvenOdd(n): + return Permute('EvenOdd{}'.format(n), _evenodd(n)) diff --git a/mantle/util/sort/swap.py b/mantle/util/sort/swap.py index a1597b4..0155ad0 100644 --- a/mantle/util/sort/swap.py +++ b/mantle/util/sort/swap.py @@ -1,20 +1,23 @@ from magma import Circuit, Bits, In, Out, wire, fork, join, flat, uncurry, map_, cache_definition from mantle import And, Or -__all__ = ['Swap', 'swap'] +__all__ = ['Swap', 'swap'] __all__ += ['Swaps', 'swaps'] __all__ += ['DefineEvenOddSwaps', 'EvenOddSwaps', 'evenoddswaps'] # # Binary swap circuit # + + class Swap(Circuit): - IO = ['I', In(Bits(2)), "O", Out(Bits(2))] + io = m.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="I") #swap = uncurry( fork( And(2), Or(2) ) , prefix="in") - wire( swap( io.I ), io.O ) + wire(swap(io.I), io.O) + def swap(I): return Swap()(I) @@ -23,16 +26,18 @@ def swap(I): def DefineSwaps(n): class Swaps(Circuit): name = 'Swap{}'.format(n) - IO = ['I', In(Bits(n)), "O", Out(Bits(n))] + io = m.IO(I=In(Bits(n)), O=Out(Bits(n))) @classmethod def definition(io): - s = flat( join( map_(Swap, n//2) ), flatargs = ['I', 'O'] ) + s = flat(join(map_(Swap, n//2)), flatargs=['I', 'O']) wire(s(io.I), io.O) return Swaps + def Swaps(n): return DefineSwaps(n)() + def swaps(I): return Swaps(len(I))(I) @@ -40,17 +45,19 @@ def swaps(I): def DefineEvenOddSwaps(n): class EvenOddSwaps(Circuit): name = 'EvenOddSwap{}'.format(n) - IO = ['I', In(Bits(n)), "O", Out(Bits(n))] + io = m.IO(I=In(Bits(n)), O=Out(Bits(n))) @classmethod def definition(io): - s = flat( join( map_(Swap, n//2-1) ), flatargs = ['I', 'O'] ) + 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]) return EvenOddSwaps + def EvenOddSwaps(n): return DefineEvenOddSwaps(n)() + def evenoddswaps(I): return EvenOddSwaps(len(I))(I) diff --git a/mantle/xilinx/mantle3/MUX.py b/mantle/xilinx/mantle3/MUX.py index 375d68d..502f717 100644 --- a/mantle/xilinx/mantle3/MUX.py +++ b/mantle/xilinx/mantle3/MUX.py @@ -3,27 +3,31 @@ from magma.bitutils import lutinit from ..spartan3.CLB import * -__all__ = ['Mux2', 'Mux4', 'Mux8', 'Mux16'] +__all__ = ['Mux2', 'Mux4', 'Mux8', 'Mux16'] __all__ += ['DefineMux', 'Mux'] # # C ? B : A # -MUX2DATA = (~A2&A0)|(A2&A1) +MUX2DATA = (~A2 & A0) | (A2 & A1) # """Construct a Mux with 2 1-bit inputs.""" + + class Mux2(Circuit): - IO = ["I", In(Bits[ 2 ]), "S", In(Bit), "O", Out(Bit) ] - + io = m.IO(I=In(Bits[2]), S=In(Bit), O=Out(Bit)) + @classmethod def definition(io): - lut = _LUT3(INIT=lutinit(MUX2DATA,1<<3)) - wire( lut(io.I[0], io.I[1], io.S), io.O) + lut = _LUT3(INIT=lutinit(MUX2DATA, 1 << 3)) + wire(lut(io.I[0], io.I[1], io.S), io.O) # """Construct a Mux with 4 1-bit inputs.""" + + class Mux4(Circuit): - IO = ["I", In(Bits[ 4 ]), "S", In(Bits[ 2 ]), "O", Out(Bit) ] - + io = m.IO(I=In(Bits[4]), S=In(Bits[2]), O=Out(Bit)) + @classmethod def definition(mux4): @@ -31,15 +35,17 @@ def definition(mux4): mux1 = Mux2() mux = MUXF5() - mux0(mux4.I[0:2],mux4.S[0]) - mux1(mux4.I[2:4],mux4.S[0]) - mux( mux0.O, mux1.O, mux4.S[1] ) - wire( mux.O, mux4.O ) + mux0(mux4.I[0:2], mux4.S[0]) + mux1(mux4.I[2:4], mux4.S[0]) + mux(mux0.O, mux1.O, mux4.S[1]) + wire(mux.O, mux4.O) # """Construct a Mux with 8 1-bit inputs.""" + + class Mux8(Circuit): - IO = ["I", In(Bits[ 8 ]), "S", In(Bits[ 3 ]), "O", Out(Bit) ] - + io = m.IO(I=In(Bits[8]), S=In(Bits[3]), O=Out(Bit)) + @classmethod def definition(mux8): @@ -47,15 +53,17 @@ def definition(mux8): mux1 = Mux4() mux = MUXF6() - mux0(mux8.I[0:4], mux8.S[0:2]) + mux0(mux8.I[0:4], mux8.S[0:2]) mux1(mux8.I[4:8], mux8.S[0:2]) - mux( mux0.O, mux1.O, mux8.S[2] ) - wire( mux.O, mux8.O ) + mux(mux0.O, mux1.O, mux8.S[2]) + wire(mux.O, mux8.O) # """Construct a Mux with 16 1-bit inputs.""" + + class Mux16(Circuit): - IO = ["I", In(Bits[ 16 ]), "S", In(Bits[ 4 ]), "O", Out(Bit) ] - + io = m.IO(I=In(Bits[16]), S=In(Bits[4]), O=Out(Bit)) + @classmethod def definition(mux16): @@ -73,20 +81,21 @@ def definition(mux16): def _MuxName(height, width): return f'Mux{height}x{width}' + def _MuxInterface(height, width): - AW = In(Bits[ width ]) - if height == 2: - args = ['I0', AW, + AW = In(Bits[width]) + if height == 2: + args = ['I0', AW, 'I1', AW] args += ['S', In(Bit)] elif height == 4: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW] - args += ['S', In(Bits[ 2 ])] + args += ['S', In(Bits[2])] elif height == 8: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW, @@ -94,9 +103,9 @@ def _MuxInterface(height, width): 'I5', AW, 'I6', AW, 'I7', AW] - args += ['S', In(Bits[ 3 ])] + args += ['S', In(Bits[3])] elif height == 16: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW, @@ -104,7 +113,7 @@ def _MuxInterface(height, width): 'I5', AW, 'I6', AW, 'I7', AW, - 'I8', AW, + 'I8', AW, 'I9', AW, 'I10', AW, 'I11', AW, @@ -112,12 +121,13 @@ def _MuxInterface(height, width): 'I13', AW, 'I14', AW, 'I15', AW] - args += ['S', In(Bits[ 4 ])] + args += ['S', In(Bits[4])] args += ['O', Out(AW)] return args + def MuxN(height, **kwargs): assert height in [2, 4, 8, 16] @@ -130,8 +140,8 @@ def MuxN(height, **kwargs): elif height == 16: return Mux16(**kwargs) -def DefineMux(height=2, width=1, T=None): +def DefineMux(height=2, width=1, T=None): """ Construct a Mux. Height inputs are width bits wide. """ @@ -161,17 +171,21 @@ def amux(y): return curry(MuxN(height), prefix='I') mux = braid(col(amux, width), forkargs=['S']) - if height == 2: mux( Mux.I0, Mux.I1, Mux.S ) - elif height == 4: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, Mux.S ) - elif height == 8: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, - Mux.I4, Mux.I5, Mux.I6, Mux.I7, Mux.S ) - elif height == 16: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, - Mux.I4, Mux.I5, Mux.I6, Mux.I7, - Mux.I8, Mux.I9, Mux.I10, Mux.I11, - Mux.I12, Mux.I13, Mux.I14, Mux.I15, Mux.S ) - wire( mux.O, Mux.O ) + if height == 2: + mux(Mux.I0, Mux.I1, Mux.S) + elif height == 4: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, Mux.S) + elif height == 8: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, + Mux.I4, Mux.I5, Mux.I6, Mux.I7, Mux.S) + elif height == 16: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, + Mux.I4, Mux.I5, Mux.I6, Mux.I7, + Mux.I8, Mux.I9, Mux.I10, Mux.I11, + Mux.I12, Mux.I13, Mux.I14, Mux.I15, Mux.S) + wire(mux.O, Mux.O) return _Mux + def Mux(height=2, width=None, T=None, **kwargs): return DefineMux(height, width, T)(**kwargs) - diff --git a/mantle/xilinx/mantle3/arith.py b/mantle/xilinx/mantle3/arith.py index 09a2aaf..2637e91 100644 --- a/mantle/xilinx/mantle3/arith.py +++ b/mantle/xilinx/mantle3/arith.py @@ -3,10 +3,11 @@ from .logic import Not from .cascade import FullCascade -__all__ = ['DefineAdd'] +__all__ = ['DefineAdd'] __all__ += ['DefineSub'] __all__ += ['DefineNegate'] + def _Name(basename, n, cin, cout): name = basename + str(n) if cin is 0 or cin is 1: @@ -17,6 +18,7 @@ def _Name(basename, n, cin, cout): name += '_cout' return name + def _Args(n, cin, cout): T = Bits[n] @@ -33,20 +35,22 @@ def _Args(n, cin, cout): return args # -# Create an n-bit Add +# Create an n-bit Add # # I0:In(Bits(n)), I1:In(Bits(n)), CIN:In(Bit), O:Out(Bits(n)), COUT:Out(Bit) # # if cin, CIN is added to the circuit # if cout: COUT is added to the circuit # + + def DefineAdd(n, cin=0, cout=False): class _Add(Circuit): name = _Name('Add', n, cin, cout) IO = _Args(n, cin, cout) @classmethod def definition(io): - add = FullCascade(n, 2, A0^A1, A0, cin, cout) + add = FullCascade(n, 2, A0 ^ A1, A0, cin, cout) wire(io.I0, add.I0) wire(io.I1, add.I1) wire(add.O, io.O) @@ -55,7 +59,7 @@ def definition(io): if cout is True: wire(add.COUT, io.COUT) return _Add - + def DefineSub(n, cin=1, cout=False): class _Sub(Circuit): @@ -63,24 +67,25 @@ class _Sub(Circuit): IO = _Args(n, cin, cout) @classmethod def definition(io): - sub = FullCascade(n, 2, A0^~A1, A0, cin, cout) + sub = FullCascade(n, 2, A0 ^ ~A1, A0, cin, cout) wire(io.I0, sub.I0) wire(io.I1, sub.I1) wire(sub.O, io.O) if cin is True: - wire( Not()(io.CIN), sub.CIN ) + wire(Not()(io.CIN), sub.CIN) if cout is True: wire(sub.COUT, io.COUT) return _Sub + def DefineNegate(n): T = Bits[n] + class _Negate(Circuit): name = 'Negate{}'.format(n) - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): - sub = DefineSub(n)() - wire( sub( uint(0,n), io.I ), io.O ) + sub = DefineSub(n)() + wire(sub(uint(0, n), io.I), io.O) return _Negate - diff --git a/mantle/xilinx/mantle3/compare.py b/mantle/xilinx/mantle3/compare.py index afdd7ba..bc6298a 100644 --- a/mantle/xilinx/mantle3/compare.py +++ b/mantle/xilinx/mantle3/compare.py @@ -4,7 +4,7 @@ from .logic import Not from .cascade import HalfCascade -__all__ = ['DefineEQ', 'EQ'] +__all__ = ['DefineEQ', 'EQ'] __all__ += ['DefineNE', 'NE'] __all__ += ['DefineUGE'] __all__ += ['DefineULE'] @@ -15,81 +15,92 @@ __all__ += ['DefineSGT'] __all__ += ['DefineSLT'] -EQ1LUT = ((A0&A1)|(~A0&~A1)) -EQ2LUT = ((A0&A1)|(~A0&~A1)) & ((A2&A3)|(~A2&~A3)) +EQ1LUT = ((A0 & A1) | (~A0 & ~A1)) +EQ2LUT = ((A0 & A1) | (~A0 & ~A1)) & ((A2 & A3) | (~A2 & ~A3)) + class EQ1(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - wire( LUT2(EQ1LUT)(io.I0, io.I1), io.O ) + wire(LUT2(EQ1LUT)(io.I0, io.I1), io.O) + class EQ2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - wire( LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + wire(LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineEQ(n): assert n % 2 == 0 - T = Bits[ n ] + T = Bits[n] + class _EQ(Circuit): name = "EQ{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - eq = HalfCascade(n//2, 4, EQ2LUT, ZERO, 1) - for i in range(n//2): - wire(io.I0[2*i], eq.I0[i]) - wire(io.I1[2*i], eq.I1[i]) - wire(io.I0[2*i+1], eq.I2[i]) - wire(io.I1[2*i+1], eq.I3[i]) - wire(eq.O, io.O) + eq = HalfCascade(n//2, 4, EQ2LUT, ZERO, 1) + for i in range(n//2): + wire(io.I0[2*i], eq.I0[i]) + wire(io.I1[2*i], eq.I1[i]) + wire(io.I0[2*i+1], eq.I2[i]) + wire(io.I1[2*i+1], eq.I3[i]) + wire(eq.O, io.O) return _EQ + def EQ(n, **kwargs): - if n == 1: + if n == 1: return EQ1(**kwargs) elif n == 2: return EQ2(**kwargs) return DefineEQ(n)(**kwargs) -NE1LUT = (A0^A1) -NE2LUT = (A0^A1)|(A2^A3) + +NE1LUT = (A0 ^ A1) +NE2LUT = (A0 ^ A1) | (A2 ^ A3) + class NE1(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - wire( LUT2(NE1LUT)(io.I0, io.I1), io.O ) + wire(LUT2(NE1LUT)(io.I0, io.I1), io.O) + class NE2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - wire( LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + wire(LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineNE(n): assert n % 2 == 0 - T = Bits[ n ] + T = Bits[n] + class _NE(Circuit): name = "NE{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - ne = HalfCascade(n//2, 4, NE2LUT, ZERO, 1) - for i in range(n//2): - wire(io.I0[2*i], ne.I0[i]) - wire(io.I1[2*i], ne.I1[i]) - wire(io.I0[2*i+1], ne.I2[i]) - wire(io.I1[2*i+1], ne.I3[i]) - wire(ne.O, io.O) + ne = HalfCascade(n//2, 4, NE2LUT, ZERO, 1) + for i in range(n//2): + wire(io.I0[2*i], ne.I0[i]) + wire(io.I1[2*i], ne.I1[i]) + wire(io.I0[2*i+1], ne.I2[i]) + wire(io.I1[2*i+1], ne.I3[i]) + wire(ne.O, io.O) return _NE + def NE(n, **kwargs): - if n == 1: + if n == 1: return NE1(**kwargs) elif n == 2: return NE2(**kwargs) @@ -100,12 +111,13 @@ def NE(n, **kwargs): def DefineUCMP(opname, reverse, negate, n): T = UInt[n] + class _UCMP(Circuit): name = "{}{}".format(opname, n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - sub = DefineSub(n,1,True)() + sub = DefineSub(n, 1, True)() if not reverse: sub(io.I0, io.I1) else: @@ -116,15 +128,19 @@ def definition(io): wire(Not()(sub.COUT), io.O) return _UCMP + def DefineUGE(n): return DefineUCMP('UGE', False, False, n) + def DefineULE(n): return DefineUCMP('ULE', True, False, n) + def DefineULT(n): return DefineUCMP('ULT', False, True, n) + def DefineUGT(n): return DefineUCMP('UGT', True, True, n) @@ -134,33 +150,39 @@ def DefineUGT(n): def _sge(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & ~c_msb) | (~a_msb & b_msb)) & 1 + def _slt(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & c_msb) | (a_msb & ~b_msb)) & 1 + def DefineSCMP(opname, op, reverse, n): T = SInt[n] + class _SCMP(Circuit): - name = "{}{}".format(opname,n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + name = "{}{}".format(opname, n) + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): sub = DefineSub(n)() cmp = LUT3(op) if not reverse: - wire(cmp( sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1] ), io.O) + wire(cmp(sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1]), io.O) else: - wire(cmp( sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1] ), io.O) + wire(cmp(sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1]), io.O) return _SCMP + def DefineSGE(n): return DefineSCMP('SGE', _sge, False, n) + def DefineSLE(n): return DefineSCMP('SLE', _sge, True, n) + def DefineSLT(n): return DefineSCMP('SLT', _slt, False, n) + def DefineSGT(n): return DefineSCMP('SGT', _slt, True, n) - diff --git a/mantle/xilinx/mantle3/decode.py b/mantle/xilinx/mantle3/decode.py index 6412198..4af397e 100644 --- a/mantle/xilinx/mantle3/decode.py +++ b/mantle/xilinx/mantle3/decode.py @@ -3,7 +3,8 @@ from .ROM import ROMN from .cascade import FlatHalfCascade -__all__ = ['DefineDecode', 'Decode', 'decode'] +__all__ = ['DefineDecode', 'Decode', 'decode'] + def DefineDecode(i, n, invert=False): """ @@ -14,7 +15,7 @@ def DefineDecode(i, n, invert=False): class _Decode(Circuit): name = 'Decode_{}_{}'.format(i, n) - IO = ['I', In(Bits[n]), 'O', Out(Bit)] + io = m.IO(I=In(Bits[n]), O=Out(Bit)) @classmethod def definition(io): @@ -29,15 +30,17 @@ def definition(io): nluts = (n + 3) // 4 data = nluts * [0] for j in range(nluts): - data[j] = (i >> 4*j) & 0xf # 4-bit pieces + data[j] = (i >> 4*j) & 0xf # 4-bit pieces decode = FlatHalfCascade(n, 4, data, ZERO, 1) wire(io.I, decode.I) wire(decode.O, io.O) return _Decode + def Decode(i, n, invert=False): return DefineDecode(i, n, invert=invert)() + def decode(I, i, invert=False): return Decode(i, len(I), invert=invert)(I) diff --git a/mantle/xilinx/mantle3/fulladder.py b/mantle/xilinx/mantle3/fulladder.py index 671dcd3..277e3be 100644 --- a/mantle/xilinx/mantle3/fulladder.py +++ b/mantle/xilinx/mantle3/fulladder.py @@ -3,15 +3,16 @@ __all__ = ['FullAdder', 'fulladder'] + class FullAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "I2", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), I2=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - s = LUT3(A0^A1^A2) - c = LUT3(A0&A1|A1&A2|A2&A0) - wire( s(io.I0, io.I1, io.I2), io.O ) - wire( c(io.I0, io.I1, io.I2), io.COUT ) + s = LUT3(A0 ^ A1 ^ A2) + c = LUT3(A0 & A1 | A1 & A2 | A2 & A0) + wire(s(io.I0, io.I1, io.I2), io.O) + wire(c(io.I0, io.I1, io.I2), io.COUT) + def fulladder(a, b, c): return FullAdder()(a, b, c) - diff --git a/mantle/xilinx/mantle3/halfadder.py b/mantle/xilinx/mantle3/halfadder.py index a732c54..c20972d 100644 --- a/mantle/xilinx/mantle3/halfadder.py +++ b/mantle/xilinx/mantle3/halfadder.py @@ -1,17 +1,18 @@ from magma import * from .LUT import LUT2, A0, A1 -__all__ = ["HalfAdder", 'halfadder'] +__all__ = ["HalfAdder", 'halfadder'] + class HalfAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - s = LUT2(A0^A1) - c = LUT2(A0&A1) - wire( s(io.I0, io.I1), io.O ) - wire( c(io.I0, io.I1), io.COUT ) - + s = LUT2(A0 ^ A1) + c = LUT2(A0 & A1) + wire(s(io.I0, io.I1), io.O) + wire(c(io.I0, io.I1), io.COUT) + + def halfadder(a, b): return HalfAdder()(a, b) - diff --git a/mantle/xilinx/mantle3/logic.py b/mantle/xilinx/mantle3/logic.py index a5fa04c..a9534fc 100644 --- a/mantle/xilinx/mantle3/logic.py +++ b/mantle/xilinx/mantle3/logic.py @@ -1,17 +1,17 @@ from __future__ import division +from .cascade import FlatHalfCascade +from .ROM import ROMN +from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3, ZERO, ONE +from magma import * +from collections.abc import Sequence import sys if sys.version_info > (3, 0): from functools import reduce from functools import lru_cache -from collections.abc import Sequence -from magma import * -from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3, ZERO, ONE -from .ROM import ROMN -from .cascade import FlatHalfCascade # unary operators -__all__ = ['DefineReduceAnd', 'ReduceAnd'] +__all__ = ['DefineReduceAnd', 'ReduceAnd'] __all__ += ['DefineReduceNAnd', 'ReduceNAnd'] __all__ += ['DefineReduceOr', 'ReduceOr'] __all__ += ['DefineReduceNOr', 'ReduceNOr'] @@ -33,17 +33,20 @@ # # Efficient Reduction using carry chain and FlatHalfCascade # + + def DefineReduceOp(opname, n, lutexprs, andexpr, cin): #assert n % 4 == 0 - T = Bits[ n ] + T = Bits[n] + class _ReduceOp(Circuit): name = '{}{}'.format(opname, n) - IO = ['I', In(T), 'O', Out(Bit)] + io = m.IO(I=In(T), O=Out(Bit)) @classmethod def definition(io): I = io.I - if n <= 4: #8? + if n <= 4: # 8? a = ROMN(lutexprs[n - 1], n) else: nluts = 4 * ((n + 3) // 4) @@ -53,80 +56,100 @@ def definition(io): wire(a(I), io.O) return _ReduceOp + def DefineReduceAnd(n): - luts = [A0, A0&A1, A0&A1&A2, A0&A1&A2&A3] + luts = [A0, A0 & A1, A0 & A1 & A2, A0 & A1 & A2 & A3] return DefineReduceOp('And', n, luts, ZERO, 1) + def ReduceAnd(height=2, **kwargs): return DefineReduceAnd(height)(**kwargs) + def DefineReduceNAnd(n): - luts = [A0, A0&A1, A0&A1&A2, A0&A1&A2&A3] + luts = [A0, A0 & A1, A0 & A1 & A2, A0 & A1 & A2 & A3] return DefineReduceOp('NAnd', n, luts, ONE, 0) + def ReduceNAnd(height=2, **kwargs): return DefineReduceNAnd(height)(**kwargs) + def DefineReduceOr(n): - luts = [~A0, ~(A0|A1), ~(A0|A1|A2), ~(A0|A1|A2|A3)] + luts = [~A0, ~(A0 | A1), ~(A0 | A1 | A2), ~(A0 | A1 | A2 | A3)] return DefineReduceOp('Or', n, luts, ONE, 0) + def ReduceOr(height=2, **kwargs): return DefineReduceOr(height)(**kwargs) + def DefineReduceNOr(n): - luts = [~A0, ~(A0|A1), ~(A0|A1|A2), ~(A0|A1|A2|A3)] + luts = [~A0, ~(A0 | A1), ~(A0 | A1 | A2), ~(A0 | A1 | A2 | A3)] return DefineReduceOp('NOr', n, luts, ZERO, 1) + def ReduceNOr(height=2, **kwargs): return DefineReduceNOr(height)(**kwargs) + def LUTCascade(n, k, expr, cin): - def f(y): - e = expr[y] if isinstance(expr, Sequence) else expr - return LUT( e, n=k+1 ) + def f(y): + e = expr[y] if isinstance(expr, Sequence) else expr + return LUT(e, n=k+1) - # number of luts - m = (n+k-1) // k - c = braid( col(f, m), foldargs={"I0":"O"}) + # number of luts + m = (n+k-1) // k + c = braid(col(f, m), foldargs={"I0": "O"}) - wire(cin, c.I0) + wire(cin, c.I0) - c = flat(uncurry(c)) + c = flat(uncurry(c)) - for i in range(n, len(c.I)): - wire(cin, c.I[i]) + for i in range(n, len(c.I)): + wire(cin, c.I[i]) + + return AnonymousCircuit(['I', c.I[0:n], 'O', c.O]) - return AnonymousCircuit( ['I', c.I[0:n], 'O', c.O] ) def DefineReduceLUT(opname, n, luts, cascadeexpr, cin): - T = Bits[ n ] + T = Bits[n] + class _ReduceLUT(Circuit): name = '{}{}'.format(opname, n) - IO = ['I', In(T), 'O', Out(Bit)] + io = m.IO(I=In(T), O=Out(Bit)) @classmethod def definition(io): - if n == 1: a = uncurry(LUT1(luts[n - 1])) - elif n == 2: a = uncurry(LUT2(luts[n - 1])) - elif n == 3: a = uncurry(LUT3(luts[n - 1])) - elif n == 4: a = uncurry(LUT4(luts[n - 1])) - else: a = LUTCascade(n, 1, cascadeexpr, cin) + if n == 1: + a = uncurry(LUT1(luts[n - 1])) + elif n == 2: + a = uncurry(LUT2(luts[n - 1])) + elif n == 3: + a = uncurry(LUT3(luts[n - 1])) + elif n == 4: + a = uncurry(LUT4(luts[n - 1])) + else: + a = LUTCascade(n, 1, cascadeexpr, cin) wire(a(io.I), io.O) return _ReduceLUT + def DefineReduceXOr(n): - luts = [A0, A0^A1, A0^A1^A2, A0^A1^A2^A3] + luts = [A0, A0 ^ A1, A0 ^ A1 ^ A2, A0 ^ A1 ^ A2 ^ A3] return DefineReduceLUT('XOr', n, luts, A0 ^ A1, 0) + def ReduceXOr(height=2, **kwargs): return DefineReduceXOr(height)(**kwargs) + def DefineReduceNXOr(n): - luts = [~A0, ~(A0^A1), ~(A0^A1^A2), ~(A0^A1^A2^A3)] + luts = [~A0, ~(A0 ^ A1), ~(A0 ^ A1 ^ A2), ~(A0 ^ A1 ^ A2 ^ A3)] return DefineReduceLUT('NXOr', n, luts, A0 ^ ~A1, 1) + def ReduceNXOr(height=2, **kwargs): return DefineReduceNXOr(height)(**kwargs) @@ -137,13 +160,13 @@ def DefineOp(opname, op, height=2, width=1): I0 : In(Bits(width)), I1 : In(Bits(width)), O : Out(Bits(width)) """ - T = Bits[ width ] + T = Bits[width] class _Op(Circuit): name = '{}{}x{}'.format(opname, height, width) IO = sum([['I{}'.format(i), In(T)] for i in range(height)], []) - IO += ['O', Out(T)] + IO += ['O', Out(T)] @classmethod def definition(io): @@ -155,49 +178,61 @@ def opm(y): wire(opmxn.O, io.O) return _Op + def DefineAnd(height=2, width=1): return DefineOp('And', ReduceAnd, height, width) + def And(height=2, width=None, **kwargs): if width is None: return curry(ReduceAnd(height, **kwargs)) return DefineAnd(height, width)(**kwargs) + def DefineNAnd(height=2, width=None): return DefineOp('NAnd', ReduceNAnd, height, width) + def NAnd(height=2, width=None, **kwargs): if width is None: return curry(ReduceNAnd(height, **kwargs)) return DefineNAnd(height, width)(**kwargs) + def DefineOr(height=2, width=None): return DefineOp('Or', ReduceOr, height, width) + def Or(height=2, width=None, **kwargs): if width is None: return curry(ReduceOr(height, **kwargs)) return DefineOr(height, width)(**kwargs) + def DefineNOr(height=2, width=None): return DefineOp('NOr', ReduceNOr, height, width) + def NOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNOr(height, **kwargs)) return DefineNOr(height, width)(**kwargs) + def DefineXOr(height=2, width=None): return DefineOp('XOr', ReduceXOr, height, width) + def XOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceXOr(height, **kwargs)) return DefineXOr(height, width)(**kwargs) + def DefineNXOr(height=2, width=None): return DefineOp('NXOr', ReduceNXOr, height, width) + def NXOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNXOr(height, **kwargs)) @@ -211,10 +246,11 @@ def DefineInvert(width): I0 : Bits(width) -> O : Bits(width) """ - T = Bits[ width ] + T = Bits[width] + class _Invert(Circuit): name = 'Invert%d' % width - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(def_): @@ -226,6 +262,7 @@ def not_(y): return _Invert + def Invert(n, **kwargs): return DefineInvert(n)(**kwargs) @@ -233,4 +270,3 @@ def Invert(n, **kwargs): def Not(**kwargs): """Not gate - 1-bit input.""" return LUT1(~A0, **kwargs) - diff --git a/mantle/xilinx/mantle3/mothball/_halfcascade.py b/mantle/xilinx/mantle3/mothball/_halfcascade.py index fd038a8..6236c03 100644 --- a/mantle/xilinx/mantle3/mothball/_halfcascade.py +++ b/mantle/xilinx/mantle3/mothball/_halfcascade.py @@ -3,27 +3,29 @@ from .LUT import LUTN, LOG_BITS_PER_LUT, A0, A1, A2, A3, ZERO, ONE from .carry import HalfCarry -__all__ = ['DefineFlatHalfCascade', 'FlatCascade'] +__all__ = ['DefineFlatHalfCascade', 'FlatCascade'] #__all__ += ['AndCascade', 'NAndCascade', 'OrCascade', 'NOrCascade'] __all__ += ['DefineHalfCascade', 'HalfCascade'] + def InputArgs(n, k, forkargs): T = Bits(n) I = [] for i in range(k): - name = "I{}".format(i) - I.append(name) - I.append(In(Bit) if name in forkargs else In(T)) + name = "I{}".format(i) + I.append(name) + I.append(In(Bit) if name in forkargs else In(T)) return I + def _CascadeName(name, n, lutexpr, andexpr, cin): if isinstance(lutexpr, Sequence): lutexpr = "_".join(["%04X" % (e & 0xffff) for e in lutexpr]) else: lutexpr = "%04X" % (lutexpr & 0xffff) andexpr = "%04X" % (andexpr & 0xffff) - return '%s%d_%s_%s_%d' % (name ,n, lutexpr, andexpr, cin) + return '%s%d_%s_%s_%d' % (name, n, lutexpr, andexpr, cin) # # Build a column of LUTs feeding into MUXCY. In the Half version @@ -37,16 +39,19 @@ def _CascadeName(name, n, lutexpr, andexpr, cin): # lutexpr is the expression that goes into each LUT # # The output of MUXCY is selected by the output of the LUT -# cin is the value going into the first MUXCY in the column +# cin is the value going into the first MUXCY in the column # + + def DefineFlatHalfCascade(n, k, lutexpr, andexpr, cin, name=None): if name is None: nm = _CascadeName('FlatHalfCascade', n, lutexpr, andexpr, cin) else: nm = name + str(n) + class _FlatHalfCascade(Circuit): name = nm - IO = ["I", In(Bits(n)), "O", Out(Bit)] + io = m.IO(I=In(Bits(n)), O=Out(Bit)) @classmethod def definition(io): def f(y): @@ -56,9 +61,9 @@ def f(y): # calculate number of LUTs nluts = (n+LOG_BITS_PER_LUT-1)//LOG_BITS_PER_LUT - c = braid( col(f, nluts), foldargs={"CIN":"COUT"}) + c = braid(col(f, nluts), foldargs={"CIN": "COUT"}) c = flat(c) - #print(repr(c)) + # print(repr(c)) for i in range(LOG_BITS_PER_LUT*nluts): wire(io.I[i], c.I[i]) @@ -67,19 +72,20 @@ def f(y): return _FlatHalfCascade + def FlatHalfCascade(n, k, lutexpr, andexpr, cin, name=None): return DefineFlatHalfCascade(n, k, lutexpr, andexpr, cin, name=name)() -#def AndCascade( n ): +# def AndCascade( n ): # return FlatHalfCascade(n, 4, A0&A1&A2&A3, ZERO, 1, 'AndCascade') # -#def NAndCascade( n ): +# def NAndCascade( n ): # return FlatHalfCascade(n, 4, A0&A1&A2&A3, ONE, 0) # -#def OrCascade( n ): +# def OrCascade( n ): # return FlatHalfCascade(n, 4, ~(A0|A1|A2|A3), ONE, 0) # -#def NOrCascade( n ): +# def NOrCascade( n ): # return FlatHalfCascade(n, 4, ~(A0|A1|A2|A3), ZERO, 1) @@ -88,6 +94,7 @@ def DefineHalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): nm = _CascadeName('HalfCascade', n, lutexpr, andexpr, cin) else: nm = '{}_{}'.format(name, n) + class _HalfCascade(Circuit): name = nm IO = InputArgs(n, k, forkargs) + ["O", Out(Bit)] @@ -97,23 +104,28 @@ def f(y): e = lutexpr[y] if isinstance(lutexpr, Sequence) else lutexpr return HalfCarry(k, e, andexpr) - c = braid( col(f, n), foldargs={"CIN":"COUT"}, forkargs=forkargs) - #print(repr(c)) - if k >= 1: wire(io.I0, c.I0) - if k >= 2: wire(io.I1, c.I1) - if k >= 3: wire(io.I2, c.I2) - if k >= 4: wire(io.I3, c.I3) + c = braid(col(f, n), foldargs={"CIN": "COUT"}, forkargs=forkargs) + # print(repr(c)) + if k >= 1: + wire(io.I0, c.I0) + if k >= 2: + wire(io.I1, c.I1) + if k >= 3: + wire(io.I2, c.I2) + if k >= 4: + wire(io.I3, c.I3) wire(c.COUT, io.O) wire(cin, c.CIN) return _HalfCascade + def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): return DefineHalfCascade(n, k, lutexpr, andexpr, cin, forkargs, name)() # -#def _Name(n, k, expr1, expr2, cin): +# def _Name(n, k, expr1, expr2, cin): # assert not isinstance(expr1, Sequence) # #if isinstance(expr1, Sequence): # # expr1 = seq2int(expr1) @@ -123,39 +135,39 @@ def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): # return 'Cascade%dx%d_%X_%X_%d' % (n, k, expr1, expr2, cin) # ## -## Create circuit consisting of an LUT feeding into MUXCY. +# Create circuit consisting of an LUT feeding into MUXCY. ## ## -## LUT -## k is the number of input bits -## expr1 is what goes into the LUT +# LUT +# k is the number of input bits +# expr1 is what goes into the LUT ## -## MUXCY -## the output of the LUT selects the output -## expr2 selects what goes into the 0 slot -## A0 -## A1 -## A0&A1 -## ZERO -## ONE -## CIN goes into the 1 slot +# MUXCY +# the output of the LUT selects the output +# expr2 selects what goes into the 0 slot +# A0 +# A1 +# A0&A1 +# ZERO +# ONE +# CIN goes into the 1 slot ## -## The resulting circuit has the following interface +# The resulting circuit has the following interface ## -## ['I0', rom.I0, ..., 'Ik", rom.Ik, "COUT", mux.COUT, "CIN", CIN] +# ['I0', rom.I0, ..., 'Ik", rom.Ik, "COUT", mux.COUT, "CIN", CIN] ## -##def FullCascade(k, expr1, expr2): +# def FullCascade(k, expr1, expr2): ## ## assert k <= 4 ## ## lut = LUTN(expr1, k) ## ## args = [] -## if k >= 1: +# if k >= 1: ## I0 = Bit() ## wire(I0, lut.I0) ## args += ['I0', I0] -## if k >= 2: +# if k >= 2: ## I1 = Bit() ## wire(I1, lut.I1) ## args += ['I1', I1] @@ -163,18 +175,18 @@ def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): ## if k >= 4: args += ['I3', lut.I3] ## ## -## if expr2 == A0&A1: +# if expr2 == A0&A1: ## and1 = ANDCY() ## wire(I0, and1.I0) ## wire(I1, and1.I1) ## DI = and1.LO -## elif expr2 == A0: +# elif expr2 == A0: ## DI = I0 -## elif expr2 == A1: +# elif expr2 == A1: ## DI = I1 -## elif expr2 == ZERO: +# elif expr2 == ZERO: ## DI = 0 -## elif expr2 == ONE: +# elif expr2 == ONE: ## DI = 1 ## ## CIN = Bit() @@ -185,21 +197,21 @@ def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): ## wire(CIN, mux.CI) ## ## args += ["COUT", mux.O, "CIN", CIN] -## return AnonymousCircuit( args ) +# return AnonymousCircuit( args ) # # ## -## k is the number of bits per input -## n is the number of inputs -## expr1 goes into LUT -## expr2 goes into DIN +# k is the number of bits per input +# n is the number of inputs +# expr1 goes into LUT +# expr2 goes into DIN # -## cin is a constant carry in: 0 or 1 +# cin is a constant carry in: 0 or 1 ## -## the inputs are either forked or joined, depending on forkargs -## I0 : Bit/Array(n,Bit), ..., Ik : Bit/Array(n,Bit) -> O : Bit +# the inputs are either forked or joined, depending on forkargs +# I0 : Bit/Array(n,Bit), ..., Ik : Bit/Array(n,Bit) -> O : Bit ## -##def DefineHalfCascade(n, k, expr1, expr2, cin, forkargs={}): +# def DefineHalfCascade(n, k, expr1, expr2, cin, forkargs={}): ## ## T = In(Bits(n)) ## args = [] @@ -209,15 +221,15 @@ def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): ## if k >= 4: args += ["I3", In(Bit) if 'I3' in forkargs else T] ## args += ["O", Out(Bit)] ## -## class _HalfCascade(Circuit): +# class _HalfCascade(Circuit): ## name = _CascadeName('HalfCascade', n, k, expr1, expr2, cin, 0) ## IO = args ## -## @classmethod -## def definition(io): +# @classmethod +# def definition(io): ## -## def f(y): -## return HalfCarry(k, expr1, expr2) +# def f(y): +# return HalfCarry(k, expr1, expr2) ## ## c = braid( col(f, n), foldargs={"CIN":"COUT"}, forkargs=forkargs ) ## @@ -228,7 +240,7 @@ def HalfCascade(n, k, lutexpr, andexpr, cin, forkargs={}, name=None): ## wire(c.COUT, io.O) ## wire(cin, c.CIN) ## -## return _HalfCascade +# return _HalfCascade ## # # diff --git a/mantle/xilinx/mantle6/MUX.py b/mantle/xilinx/mantle6/MUX.py index 3a141b3..fbf4b51 100644 --- a/mantle/xilinx/mantle6/MUX.py +++ b/mantle/xilinx/mantle6/MUX.py @@ -3,33 +3,38 @@ from magma.bitutils import lutinit from ..spartan6.CLB import * -__all__ = ['Mux2', 'Mux4', 'Mux8', 'Mux16'] +__all__ = ['Mux2', 'Mux4', 'Mux8', 'Mux16'] __all__ += ['DefineMux', 'Mux'] # """Construct a Mux with 2 1-bit inputs.""" class Mux2(Circuit): - IO = ["I", In(Bits[ 2 ]), "S", In(Bit), "O", Out(Bit) ] + io = m.IO(I=In(Bits[2]), S=In(Bit), O=Out(Bit)) @classmethod def definition(io): - MUX2DATA = (~A2&A0)|(A2&A1) - lut = _LUT3(INIT=lutinit(MUX2DATA,1<<3)) - wire( lut(io.I[0], io.I[1], io.S), io.O) + MUX2DATA = (~A2 & A0) | (A2 & A1) + lut = _LUT3(INIT=lutinit(MUX2DATA, 1 << 3)) + wire(lut(io.I[0], io.I[1], io.S), io.O) # """Construct a Mux with 4 1-bit inputs.""" + + class Mux4(Circuit): - IO = ["I", In(Bits[ 4 ]), "S", In(Bits[ 2 ]), "O", Out(Bit) ] + io = m.IO(I=In(Bits[4]), S=In(Bits[2]), O=Out(Bit)) @classmethod def definition(io): - MUX4DATA = (~A4&~A5&A0)|(A4&~A5&A1)|(~A4&A5&A2)|(A4&A5&A3) - lut = _LUT6(INIT=lutinit(MUX4DATA,1<<6)) - wire( lut(io.I[0], io.I[1], io.I[2], io.I[3], io.S[0], io.S[1]), io.O) + MUX4DATA = (~A4 & ~A5 & A0) | (A4 & ~A5 & A1) | ( + ~A4 & A5 & A2) | (A4 & A5 & A3) + lut = _LUT6(INIT=lutinit(MUX4DATA, 1 << 6)) + wire(lut(io.I[0], io.I[1], io.I[2], io.I[3], io.S[0], io.S[1]), io.O) # """Construct a Mux with 8 1-bit inputs.""" + + class Mux8(Circuit): - IO = ["I", In(Bits[ 8 ]), "S", In(Bits[ 3 ]), "O", Out(Bit) ] + io = m.IO(I=In(Bits[8]), S=In(Bits[3]), O=Out(Bit)) @classmethod def definition(mux8): @@ -40,12 +45,14 @@ def definition(mux8): mux0(mux8.I[0:4], mux8.S[0:2]) mux1(mux8.I[4:8], mux8.S[0:2]) - mux( mux0.O, mux1.O, mux8.S[2] ) - wire( mux.O, mux8.O ) + mux(mux0.O, mux1.O, mux8.S[2]) + wire(mux.O, mux8.O) # """Construct a Mux with 16 1-bit inputs.""" + + class Mux16(Circuit): - IO = ["I", In(Bits[ 16 ]), "S", In(Bits[ 4 ]), "O", Out(Bit) ] + io = m.IO(I=In(Bits[16]), S=In(Bits[4]), O=Out(Bit)) @classmethod def definition(mux16): @@ -64,20 +71,21 @@ def definition(mux16): def _MuxName(height, width): return f'Mux{height}x{width}' + def _MuxInterface(height, width): - AW = In(Bits[ width ]) - if height == 2: - args = ['I0', AW, + AW = In(Bits[width]) + if height == 2: + args = ['I0', AW, 'I1', AW] args += ['S', In(Bit)] elif height == 4: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW] - args += ['S', In(Bits[ 2 ])] + args += ['S', In(Bits[2])] elif height == 8: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW, @@ -85,9 +93,9 @@ def _MuxInterface(height, width): 'I5', AW, 'I6', AW, 'I7', AW] - args += ['S', In(Bits[ 3 ])] + args += ['S', In(Bits[3])] elif height == 16: - args = ['I0', AW, + args = ['I0', AW, 'I1', AW, 'I2', AW, 'I3', AW, @@ -95,7 +103,7 @@ def _MuxInterface(height, width): 'I5', AW, 'I6', AW, 'I7', AW, - 'I8', AW, + 'I8', AW, 'I9', AW, 'I10', AW, 'I11', AW, @@ -103,12 +111,13 @@ def _MuxInterface(height, width): 'I13', AW, 'I14', AW, 'I15', AW] - args += ['S', In(Bits[ 4 ])] + args += ['S', In(Bits[4])] args += ['O', Out(AW)] return args + def MuxN(height, **kwargs): assert height in [2, 4, 8, 16] @@ -121,8 +130,8 @@ def MuxN(height, **kwargs): elif height == 16: return Mux16(**kwargs) -def DefineMux(height=2, width=1, T=None): +def DefineMux(height=2, width=1, T=None): """ Construct a Mux. Height inputs are width bits wide. """ @@ -152,17 +161,21 @@ def amux(y): return curry(MuxN(height), prefix='I') mux = braid(col(amux, width), forkargs=['S']) - if height == 2: mux( Mux.I0, Mux.I1, Mux.S ) - elif height == 4: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, Mux.S ) - elif height == 8: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, - Mux.I4, Mux.I5, Mux.I6, Mux.I7, Mux.S ) - elif height == 16: mux( Mux.I0, Mux.I1, Mux.I2, Mux.I3, - Mux.I4, Mux.I5, Mux.I6, Mux.I7, - Mux.I8, Mux.I9, Mux.I10, Mux.I11, - Mux.I12, Mux.I13, Mux.I14, Mux.I15, Mux.S ) - wire( mux.O, Mux.O ) + if height == 2: + mux(Mux.I0, Mux.I1, Mux.S) + elif height == 4: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, Mux.S) + elif height == 8: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, + Mux.I4, Mux.I5, Mux.I6, Mux.I7, Mux.S) + elif height == 16: + mux(Mux.I0, Mux.I1, Mux.I2, Mux.I3, + Mux.I4, Mux.I5, Mux.I6, Mux.I7, + Mux.I8, Mux.I9, Mux.I10, Mux.I11, + Mux.I12, Mux.I13, Mux.I14, Mux.I15, Mux.S) + wire(mux.O, Mux.O) return _Mux + def Mux(height=2, width=None, T=None, **kwargs): return DefineMux(height, width, T)(**kwargs) - diff --git a/mantle/xilinx/mantle6/arith.py b/mantle/xilinx/mantle6/arith.py index f0669f1..b29a73c 100644 --- a/mantle/xilinx/mantle6/arith.py +++ b/mantle/xilinx/mantle6/arith.py @@ -3,10 +3,11 @@ from .logic import Not from .cascade import FullCascade -__all__ = ['DefineAdd'] +__all__ = ['DefineAdd'] __all__ += ['DefineSub'] __all__ += ['DefineNegate'] + def _Name(basename, n, cin, cout): name = basename + str(n) if cin is 0 or cin is 1: @@ -17,8 +18,9 @@ def _Name(basename, n, cin, cout): name += '_cout'.format(cout) return name + def _Args(n, cin, cout): - T = Bits[ n ] + T = Bits[n] args = ["I0", In(T), "I1", In(T)] @@ -40,13 +42,15 @@ def _Args(n, cin, cout): # if cin, CIN is added to the circuit # if cout: COUT is added to the circuit # + + def DefineAdd(n, cin=False, cout=False): class _Add(Circuit): name = _Name('Add', n, cin, cout) IO = _Args(n, cin, cout) @classmethod def definition(io): - add = FullCascade(n, 2, A0^A1, A0, cin, cout) + add = FullCascade(n, 2, A0 ^ A1, A0, cin, cout) wire(io.I0, add.I0) wire(io.I1, add.I1) wire(add.O, io.O) @@ -55,7 +59,7 @@ def definition(io): if cout is True: wire(add.COUT, io.COUT) return _Add - + def DefineSub(n, cin=1, cout=False): class _Sub(Circuit): @@ -63,25 +67,25 @@ class _Sub(Circuit): IO = _Args(n, cin, cout) @classmethod def definition(io): - sub = FullCascade(n, 2, A0^~A1, A0, cin, cout) + sub = FullCascade(n, 2, A0 ^ ~A1, A0, cin, cout) wire(io.I0, sub.I0) wire(io.I1, sub.I1) wire(sub.O, io.O) if cin is True: - wire( Not()(io.CIN), sub.CIN ) + wire(Not()(io.CIN), sub.CIN) if cout is True: wire(sub.COUT, io.COUT) return _Sub + def DefineNegate(n): - T = Bits[ n ] + T = Bits[n] + class _Negate(Circuit): name = 'Negate{}'.format(n) - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(io): - sub = DefineSub(n)() - wire( sub( uint(0,n), io.I ), io.O ) + sub = DefineSub(n)() + wire(sub(uint(0, n), io.I), io.O) return _Negate - - diff --git a/mantle/xilinx/mantle6/compare.py b/mantle/xilinx/mantle6/compare.py index 1b05e60..bc6298a 100644 --- a/mantle/xilinx/mantle6/compare.py +++ b/mantle/xilinx/mantle6/compare.py @@ -4,7 +4,7 @@ from .logic import Not from .cascade import HalfCascade -__all__ = ['DefineEQ', 'EQ'] +__all__ = ['DefineEQ', 'EQ'] __all__ += ['DefineNE', 'NE'] __all__ += ['DefineUGE'] __all__ += ['DefineULE'] @@ -15,81 +15,92 @@ __all__ += ['DefineSGT'] __all__ += ['DefineSLT'] -EQ1LUT = ((A0&A1)|(~A0&~A1)) -EQ2LUT = ((A0&A1)|(~A0&~A1)) & ((A2&A3)|(~A2&~A3)) +EQ1LUT = ((A0 & A1) | (~A0 & ~A1)) +EQ2LUT = ((A0 & A1) | (~A0 & ~A1)) & ((A2 & A3) | (~A2 & ~A3)) + class EQ1(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - wire( LUT2(EQ1LUT)(io.I0, io.I1), io.O ) + wire(LUT2(EQ1LUT)(io.I0, io.I1), io.O) + class EQ2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - wire( LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + wire(LUT4(EQ2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineEQ(n): assert n % 2 == 0 - T = Bits[ n ] + T = Bits[n] + class _EQ(Circuit): name = "EQ{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - eq = HalfCascade(n//2, 4, EQ2LUT, ZERO, 1) - for i in range(n//2): - wire(io.I0[2*i], eq.I0[i]) - wire(io.I1[2*i], eq.I1[i]) - wire(io.I0[2*i+1], eq.I2[i]) - wire(io.I1[2*i+1], eq.I3[i]) - wire(eq.O, io.O) + eq = HalfCascade(n//2, 4, EQ2LUT, ZERO, 1) + for i in range(n//2): + wire(io.I0[2*i], eq.I0[i]) + wire(io.I1[2*i], eq.I1[i]) + wire(io.I0[2*i+1], eq.I2[i]) + wire(io.I1[2*i+1], eq.I3[i]) + wire(eq.O, io.O) return _EQ + def EQ(n, **kwargs): - if n == 1: + if n == 1: return EQ1(**kwargs) elif n == 2: return EQ2(**kwargs) return DefineEQ(n)(**kwargs) -NE1LUT = (A0^A1) -NE2LUT = (A0^A1)|(A2^A3) + +NE1LUT = (A0 ^ A1) +NE2LUT = (A0 ^ A1) | (A2 ^ A3) + class NE1(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit)) @classmethod def definition(io): - wire( LUT2(NE1LUT)(io.I0, io.I1), io.O ) + wire(LUT2(NE1LUT)(io.I0, io.I1), io.O) + class NE2(Circuit): - T = Bits[ 2 ] - IO = ["I0", In(T), "I1", In(T), "O", Out(Bit)] + T = Bits[2] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - wire( LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O ) + wire(LUT4(NE2LUT)(io.I0[0], io.I1[0], io.I0[1], io.I1[1]), io.O) + def DefineNE(n): assert n % 2 == 0 - T = Bits[ n ] + T = Bits[n] + class _NE(Circuit): name = "NE{}".format(n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - ne = HalfCascade(n//2, 4, NE2LUT, ZERO, 1) - for i in range(n//2): - wire(io.I0[2*i], ne.I0[i]) - wire(io.I1[2*i], ne.I1[i]) - wire(io.I0[2*i+1], ne.I2[i]) - wire(io.I1[2*i+1], ne.I3[i]) - wire(ne.O, io.O) + ne = HalfCascade(n//2, 4, NE2LUT, ZERO, 1) + for i in range(n//2): + wire(io.I0[2*i], ne.I0[i]) + wire(io.I1[2*i], ne.I1[i]) + wire(io.I0[2*i+1], ne.I2[i]) + wire(io.I1[2*i+1], ne.I3[i]) + wire(ne.O, io.O) return _NE + def NE(n, **kwargs): - if n == 1: + if n == 1: return NE1(**kwargs) elif n == 2: return NE2(**kwargs) @@ -99,13 +110,14 @@ def NE(n, **kwargs): # unsigned comparisons def DefineUCMP(opname, reverse, negate, n): - T = UInt[ n ] + T = UInt[n] + class _UCMP(Circuit): name = "{}{}".format(opname, n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): - sub = DefineSub(n,1,True)() + sub = DefineSub(n, 1, True)() if not reverse: sub(io.I0, io.I1) else: @@ -116,15 +128,19 @@ def definition(io): wire(Not()(sub.COUT), io.O) return _UCMP + def DefineUGE(n): return DefineUCMP('UGE', False, False, n) + def DefineULE(n): return DefineUCMP('ULE', True, False, n) + def DefineULT(n): return DefineUCMP('ULT', False, True, n) + def DefineUGT(n): return DefineUCMP('UGT', True, True, n) @@ -134,33 +150,39 @@ def DefineUGT(n): def _sge(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & ~c_msb) | (~a_msb & b_msb)) & 1 + def _slt(c_msb, a_msb, b_msb): return int((~(a_msb ^ b_msb) & c_msb) | (a_msb & ~b_msb)) & 1 + def DefineSCMP(opname, op, reverse, n): - T = SInt[ n ] + T = SInt[n] + class _SCMP(Circuit): - name = "{}{}".format(opname,n) - IO = ['I0', In(T), 'I1', In(T), "O", Out(Bit)] + name = "{}{}".format(opname, n) + io = m.IO(I0=In(T), I1=In(T), O=Out(Bit)) @classmethod def definition(io): sub = DefineSub(n)() cmp = LUT3(op) if not reverse: - wire(cmp( sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1] ), io.O) + wire(cmp(sub(io.I0, io.I1)[-1], io.I0[-1], io.I1[-1]), io.O) else: - wire(cmp( sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1] ), io.O) + wire(cmp(sub(io.I1, io.I0)[-1], io.I1[-1], io.I0[-1]), io.O) return _SCMP + def DefineSGE(n): return DefineSCMP('SGE', _sge, False, n) + def DefineSLE(n): return DefineSCMP('SLE', _sge, True, n) + def DefineSLT(n): return DefineSCMP('SLT', _slt, False, n) + def DefineSGT(n): return DefineSCMP('SGT', _slt, True, n) - diff --git a/mantle/xilinx/mantle6/decode.py b/mantle/xilinx/mantle6/decode.py index 135fb0f..4af397e 100644 --- a/mantle/xilinx/mantle6/decode.py +++ b/mantle/xilinx/mantle6/decode.py @@ -3,7 +3,8 @@ from .ROM import ROMN from .cascade import FlatHalfCascade -__all__ = ['DefineDecode', 'Decode', 'decode'] +__all__ = ['DefineDecode', 'Decode', 'decode'] + def DefineDecode(i, n, invert=False): """ @@ -14,7 +15,7 @@ def DefineDecode(i, n, invert=False): class _Decode(Circuit): name = 'Decode_{}_{}'.format(i, n) - IO = ['I', In(Bits[ n ]), 'O', Out(Bit)] + io = m.IO(I=In(Bits[n]), O=Out(Bit)) @classmethod def definition(io): @@ -29,15 +30,17 @@ def definition(io): nluts = (n + 3) // 4 data = nluts * [0] for j in range(nluts): - data[j] = (i >> 4*j) & 0xf # 4-bit pieces + data[j] = (i >> 4*j) & 0xf # 4-bit pieces decode = FlatHalfCascade(n, 4, data, ZERO, 1) wire(io.I, decode.I) wire(decode.O, io.O) return _Decode + def Decode(i, n, invert=False): return DefineDecode(i, n, invert=invert)() + def decode(I, i, invert=False): return Decode(i, len(I), invert=invert)(I) diff --git a/mantle/xilinx/mantle6/fulladder.py b/mantle/xilinx/mantle6/fulladder.py index 671dcd3..277e3be 100644 --- a/mantle/xilinx/mantle6/fulladder.py +++ b/mantle/xilinx/mantle6/fulladder.py @@ -3,15 +3,16 @@ __all__ = ['FullAdder', 'fulladder'] + class FullAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "I2", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), I2=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - s = LUT3(A0^A1^A2) - c = LUT3(A0&A1|A1&A2|A2&A0) - wire( s(io.I0, io.I1, io.I2), io.O ) - wire( c(io.I0, io.I1, io.I2), io.COUT ) + s = LUT3(A0 ^ A1 ^ A2) + c = LUT3(A0 & A1 | A1 & A2 | A2 & A0) + wire(s(io.I0, io.I1, io.I2), io.O) + wire(c(io.I0, io.I1, io.I2), io.COUT) + def fulladder(a, b, c): return FullAdder()(a, b, c) - diff --git a/mantle/xilinx/mantle6/halfadder.py b/mantle/xilinx/mantle6/halfadder.py index a732c54..c20972d 100644 --- a/mantle/xilinx/mantle6/halfadder.py +++ b/mantle/xilinx/mantle6/halfadder.py @@ -1,17 +1,18 @@ from magma import * from .LUT import LUT2, A0, A1 -__all__ = ["HalfAdder", 'halfadder'] +__all__ = ["HalfAdder", 'halfadder'] + class HalfAdder(Circuit): - IO = ["I0", In(Bit), "I1", In(Bit), "O", Out(Bit), "COUT", Out(Bit)] + io = m.IO(I0=In(Bit), I1=In(Bit), O=Out(Bit), COUT=Out(Bit)) @classmethod def definition(io): - s = LUT2(A0^A1) - c = LUT2(A0&A1) - wire( s(io.I0, io.I1), io.O ) - wire( c(io.I0, io.I1), io.COUT ) - + s = LUT2(A0 ^ A1) + c = LUT2(A0 & A1) + wire(s(io.I0, io.I1), io.O) + wire(c(io.I0, io.I1), io.COUT) + + def halfadder(a, b): return HalfAdder()(a, b) - diff --git a/mantle/xilinx/mantle6/logic.py b/mantle/xilinx/mantle6/logic.py index 7f4d6fc..4ab34a9 100644 --- a/mantle/xilinx/mantle6/logic.py +++ b/mantle/xilinx/mantle6/logic.py @@ -1,17 +1,17 @@ from __future__ import division +from .cascade import FlatHalfCascade +from .ROM import ROMN +from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3, ZERO, ONE +from magma import * +from collections.abc import Sequence import sys if sys.version_info > (3, 0): from functools import reduce from functools import lru_cache -from collections.abc import Sequence -from magma import * -from .LUT import LUT, LUT1, LUT2, LUT3, LUT4, A0, A1, A2, A3, ZERO, ONE -from .ROM import ROMN -from .cascade import FlatHalfCascade # unary operators -__all__ = ['DefineReduceAnd', 'ReduceAnd'] +__all__ = ['DefineReduceAnd', 'ReduceAnd'] __all__ += ['DefineReduceNAnd', 'ReduceNAnd'] __all__ += ['DefineReduceOr', 'ReduceOr'] __all__ += ['DefineReduceNOr', 'ReduceNOr'] @@ -33,16 +33,19 @@ # # Efficient Reduction using carry chain and FlatHalfCascade # + + def DefineReduceOp(opname, n, lutexprs, andexpr, cin): - T = Bits[ n ] + T = Bits[n] + class _ReduceOp(Circuit): name = f'{opname}{n}' - IO = ['I', In(T), 'O', Out(Bit)] + io = m.IO(I=In(T), O=Out(Bit)) @classmethod def definition(io): I = io.I - if n <= 4: #8? + if n <= 4: # 8? a = ROMN(lutexprs[n - 1], n) else: nluts = 4 * ((n + 3) // 4) @@ -53,80 +56,100 @@ def definition(io): wire(a(I), io.O) return _ReduceOp + def DefineReduceAnd(n): - luts = [A0, A0&A1, A0&A1&A2, A0&A1&A2&A3] + luts = [A0, A0 & A1, A0 & A1 & A2, A0 & A1 & A2 & A3] return DefineReduceOp('And', n, luts, ZERO, 1) + def ReduceAnd(height=2, **kwargs): return DefineReduceAnd(height)(**kwargs) + def DefineReduceNAnd(n): - luts = [A0, A0&A1, A0&A1&A2, A0&A1&A2&A3] + luts = [A0, A0 & A1, A0 & A1 & A2, A0 & A1 & A2 & A3] return DefineReduceOp('NAnd', n, luts, ONE, 0) + def ReduceNAnd(height=2, **kwargs): return DefineReduceNAnd(height)(**kwargs) + def DefineReduceOr(n): - luts = [~A0, ~(A0|A1), ~(A0|A1|A2), ~(A0|A1|A2|A3)] + luts = [~A0, ~(A0 | A1), ~(A0 | A1 | A2), ~(A0 | A1 | A2 | A3)] return DefineReduceOp('Or', n, luts, ONE, 0) + def ReduceOr(height=2, **kwargs): return DefineReduceOr(height)(**kwargs) + def DefineReduceNOr(n): - luts = [~A0, ~(A0|A1), ~(A0|A1|A2), ~(A0|A1|A2|A3)] + luts = [~A0, ~(A0 | A1), ~(A0 | A1 | A2), ~(A0 | A1 | A2 | A3)] return DefineReduceOp('NOr', n, luts, ZERO, 1) + def ReduceNOr(height=2, **kwargs): return DefineReduceNOr(height)(**kwargs) + def LUTCascade(n, k, expr, cin): - def f(y): - e = expr[y] if isinstance(expr, Sequence) else expr - return LUT( e, n=k+1 ) + def f(y): + e = expr[y] if isinstance(expr, Sequence) else expr + return LUT(e, n=k+1) + + # number of luts + m = (n+k-1) // k + c = braid(col(f, m), foldargs={"I0": "O"}) - # number of luts - m = (n+k-1) // k - c = braid( col(f, m), foldargs={"I0":"O"}) + wire(cin, c.I0) - wire(cin, c.I0) + c = flat(uncurry(c)) - c = flat(uncurry(c)) + for i in range(n, len(c.I)): + wire(cin, c.I[i]) - for i in range(n, len(c.I)): - wire(cin, c.I[i]) + return AnonymousCircuit(['I', c.I[0:n], 'O', c.O]) - return AnonymousCircuit( ['I', c.I[0:n], 'O', c.O] ) def DefineReduceLUT(opname, n, luts, cascadeexpr, cin): - T = Bits[ n ] + T = Bits[n] + class _ReduceLUT(Circuit): name = '{}{}'.format(opname, n) - IO = ['I', In(T), 'O', Out(Bit)] + io = m.IO(I=In(T), O=Out(Bit)) @classmethod def definition(io): - if n == 1: a = uncurry(LUT1(luts[n - 1])) - elif n == 2: a = uncurry(LUT2(luts[n - 1])) - elif n == 3: a = uncurry(LUT3(luts[n - 1])) - elif n == 4: a = uncurry(LUT4(luts[n - 1])) - else: a = LUTCascade(n, 1, cascadeexpr, cin) + if n == 1: + a = uncurry(LUT1(luts[n - 1])) + elif n == 2: + a = uncurry(LUT2(luts[n - 1])) + elif n == 3: + a = uncurry(LUT3(luts[n - 1])) + elif n == 4: + a = uncurry(LUT4(luts[n - 1])) + else: + a = LUTCascade(n, 1, cascadeexpr, cin) wire(a(io.I), io.O) return _ReduceLUT + def DefineReduceXOr(n): - luts = [A0, A0^A1, A0^A1^A2, A0^A1^A2^A3] + luts = [A0, A0 ^ A1, A0 ^ A1 ^ A2, A0 ^ A1 ^ A2 ^ A3] return DefineReduceLUT('XOr', n, luts, A0 ^ A1, 0) + def ReduceXOr(height=2, **kwargs): return DefineReduceXOr(height)(**kwargs) + def DefineReduceNXOr(n): - luts = [~A0, ~(A0^A1), ~(A0^A1^A2), ~(A0^A1^A2^A3)] + luts = [~A0, ~(A0 ^ A1), ~(A0 ^ A1 ^ A2), ~(A0 ^ A1 ^ A2 ^ A3)] return DefineReduceLUT('NXOr', n, luts, A0 ^ ~A1, 1) + def ReduceNXOr(height=2, **kwargs): return DefineReduceNXOr(height)(**kwargs) @@ -137,13 +160,13 @@ def DefineOp(opname, op, height=2, width=1): I0 : In(Bits(width)), I1 : In(Bits(width)), O : Out(Bits(width)) """ - T = Bits[ width ] + T = Bits[width] class _Op(Circuit): name = '{}{}x{}'.format(opname, height, width) IO = sum([['I{}'.format(i), In(T)] for i in range(height)], []) - IO += ['O', Out(T)] + IO += ['O', Out(T)] @classmethod def definition(io): @@ -155,49 +178,61 @@ def opm(y): wire(opmxn.O, io.O) return _Op + def DefineAnd(height=2, width=1): return DefineOp('And', ReduceAnd, height, width) + def And(height=2, width=None, **kwargs): if width is None: return curry(ReduceAnd(height, **kwargs)) return DefineAnd(height, width)(**kwargs) + def DefineNAnd(height=2, width=None): return DefineOp('NAnd', ReduceNAnd, height, width) + def NAnd(height=2, width=None, **kwargs): if width is None: return curry(ReduceNAnd(height, **kwargs)) return DefineNAnd(height, width)(**kwargs) + def DefineOr(height=2, width=None): return DefineOp('Or', ReduceOr, height, width) + def Or(height=2, width=None, **kwargs): if width is None: return curry(ReduceOr(height, **kwargs)) return DefineOr(height, width)(**kwargs) + def DefineNOr(height=2, width=None): return DefineOp('NOr', ReduceNOr, height, width) + def NOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNOr(height, **kwargs)) return DefineNOr(height, width)(**kwargs) + def DefineXOr(height=2, width=None): return DefineOp('XOr', ReduceXOr, height, width) + def XOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceXOr(height, **kwargs)) return DefineXOr(height, width)(**kwargs) + def DefineNXOr(height=2, width=None): return DefineOp('NXOr', ReduceNXOr, height, width) + def NXOr(height=2, width=None, **kwargs): if width is None: return curry(ReduceNXOr(height, **kwargs)) @@ -211,10 +246,11 @@ def DefineInvert(width): I0 : Bits(width) -> O : Bits(width) """ - T = Bits[ width ] + T = Bits[width] + class _Invert(Circuit): name = 'Invert%d' % width - IO = ['I', In(T), 'O', Out(T)] + io = m.IO(I=In(T), O=Out(T)) @classmethod def definition(def_): @@ -226,6 +262,7 @@ def not_(y): return _Invert + def Invert(n, **kwargs): return DefineInvert(n)(**kwargs) @@ -233,5 +270,3 @@ def Invert(n, **kwargs): def Not(**kwargs): """Not gate - 1-bit input.""" return LUT1(~A0, **kwargs) - - diff --git a/mantle/xilinx/mantle6/mothball/flatcascade.py b/mantle/xilinx/mantle6/mothball/flatcascade.py index 4a84fd8..32db66c 100644 --- a/mantle/xilinx/mantle6/mothball/flatcascade.py +++ b/mantle/xilinx/mantle6/mothball/flatcascade.py @@ -5,18 +5,21 @@ __all__ = ['FlatCascade', 'DefineFlatCascade'] + def _Name(n, k, expr, input, din, cin): if isinstance(expr, Sequence): - expr = "_".join(["%X" % uint(e, 1< 1 and height <= 4 name = 'And%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def andm(y): - if height == 2: return And2(loc=(0,y/8, y%8)) - if height == 3: return And3(loc=(0,y/8, y%8)) - if height == 4: return And4(loc=(0,y/8, y%8)) - if height == 5: return And5(loc=(0,y/8, y%8)) - if height == 6: return And6(loc=(0,y/8, y%8)) + if height == 2: + return And2(loc=(0, y/8, y % 8)) + if height == 3: + return And3(loc=(0, y/8, y % 8)) + if height == 4: + return And4(loc=(0, y/8, y % 8)) + if height == 5: + return And5(loc=(0, y/8, y % 8)) + if height == 6: + return And6(loc=(0, y/8, y % 8)) andmxn = join(col(andm, width)) wire(def_.I0, andmxn.I0) wire(def_.I1, andmxn.I1) @@ -66,9 +78,11 @@ def andm(y): return _And + def And(height, width=2, **kwargs): return DefineAnd(height, width)(**kwargs) + def AndN(n, **kwargs): """And gate with n-bit input.""" @@ -76,34 +90,38 @@ def AndN(n, **kwargs): if n == 1: return ROM1(~(A0), **kwargs) if n == 2: - return ROM2(~(A0&A1), **kwargs) + return ROM2(~(A0 & A1), **kwargs) if n == 3: - return ROM3(~(A0&A1&A2), **kwargs) + return ROM3(~(A0 & A1 & A2), **kwargs) if n == 4: - return ROM4(~(A0&A1&A2&A3), **kwargs) + return ROM4(~(A0 & A1 & A2 & A3), **kwargs) if n == 5: - return ROM5(A0&A1&A2&A3&A4, **kwargs) + return ROM5(A0 & A1 & A2 & A3 & A4, **kwargs) if n == 6: - return ROM6(A0&A1&A2&A3&A4&A5, **kwargs) + return ROM6(A0 & A1 & A2 & A3 & A4 & A5, **kwargs) else: - return FlatCascade(n, 6, A0&A1&A2&A3&A4&A5, 1, 0, 1, **kwargs) - + return FlatCascade(n, 6, A0 & A1 & A2 & A3 & A4 & A5, 1, 0, 1, **kwargs) def NAnd2(**kwargs): - return LUT2(~(A0&A1), **kwargs ) + return LUT2(~(A0 & A1), **kwargs) + def NAnd3(**kwargs): - return LUT3(~(A0&A1&A2), **kwargs) + return LUT3(~(A0 & A1 & A2), **kwargs) + def NAnd4(**kwargs): - return LUT4(~(A0&A1&A2&A3), **kwargs) + return LUT4(~(A0 & A1 & A2 & A3), **kwargs) + def NAnd5(**kwargs): - return LUT5(~(A0&A1&A2&A3&A4), **kwargs) + return LUT5(~(A0 & A1 & A2 & A3 & A4), **kwargs) + def NAnd6(**kwargs): - return LUT6(~(A0&A1&A2&A3&A4&A5), **kwargs) + return LUT6(~(A0 & A1 & A2 & A3 & A4 & A5), **kwargs) + def DefineNAnd(height, width): """ @@ -113,27 +131,34 @@ def DefineNAnd(height, width): """ T = Array(width, Bit) + class _NAnd(Circuit): assert height > 1 and height <= 4 name = 'NAnd%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def nandm(y): - if height == 2: return NAnd2(loc=(0,y/8, y%8)) - if height == 3: return NAnd3(loc=(0,y/8, y%8)) - if height == 4: return NAnd4(loc=(0,y/8, y%8)) - if height == 5: return NAnd5(loc=(0,y/8, y%8)) - if height == 6: return NAnd6(loc=(0,y/8, y%8)) + if height == 2: + return NAnd2(loc=(0, y/8, y % 8)) + if height == 3: + return NAnd3(loc=(0, y/8, y % 8)) + if height == 4: + return NAnd4(loc=(0, y/8, y % 8)) + if height == 5: + return NAnd5(loc=(0, y/8, y % 8)) + if height == 6: + return NAnd6(loc=(0, y/8, y % 8)) nandmxn = join(col(nandm, width)) wire(def_.I0, nandmxn.I0) wire(def_.I1, nandmxn.I1) @@ -141,9 +166,11 @@ def nandm(y): return _NAnd + def NAnd(height, width=2, **kwargs): return DefineNAnd(height, width)(**kwargs) + def NAndN(n, **kwargs): """NAnd gate with n-bit input.""" @@ -151,33 +178,38 @@ def NAndN(n, **kwargs): if n == 1: return ROM1(~(A0), **kwargs) if n == 2: - return ROM2(~(A0&A1), **kwargs) + return ROM2(~(A0 & A1), **kwargs) if n == 3: - return ROM3(~(A0&A1&A2), **kwargs) + return ROM3(~(A0 & A1 & A2), **kwargs) if n == 4: - return ROM4(~(A0&A1&A2&A3), **kwargs) + return ROM4(~(A0 & A1 & A2 & A3), **kwargs) if n == 5: - return ROM5(~(A0&A1&A2&A3&A4), **kwargs) + return ROM5(~(A0 & A1 & A2 & A3 & A4), **kwargs) if n == 6: - return ROM6(~(A0&A1&A2&A3&A4&A5), **kwargs) + return ROM6(~(A0 & A1 & A2 & A3 & A4 & A5), **kwargs) else: - return FlatCascade(n, 6, A0&A1&A2&A3&A4&A5, 1, 1, 0, **kwargs) + return FlatCascade(n, 6, A0 & A1 & A2 & A3 & A4 & A5, 1, 1, 0, **kwargs) def Or2(**kwargs): - return LUT2(A0|A1, **kwargs) + return LUT2(A0 | A1, **kwargs) + def Or3(**kwargs): - return LUT3(A0|A1|A2, **kwargs) + return LUT3(A0 | A1 | A2, **kwargs) + def Or4(**kwargs): - return LUT4(A0|A1|A2|A3, **kwargs) + return LUT4(A0 | A1 | A2 | A3, **kwargs) + def Or5(**kwargs): - return LUT5(A0|A1|A2|A3|A4, **kwargs) + return LUT5(A0 | A1 | A2 | A3 | A4, **kwargs) + def Or6(**kwargs): - return LUT6(A0|A1|A2|A3|A4|A5, **kwargs) + return LUT6(A0 | A1 | A2 | A3 | A4 | A5, **kwargs) + def DefineOr(height, width): """ @@ -187,27 +219,34 @@ def DefineOr(height, width): """ T = Array(width, Bit) + class _Or(Circuit): assert height > 1 and height <= 4 name = 'Or%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def orm(y): - if height == 2: return Or2(loc=(0,y/8, y%8)) - if height == 3: return Or3(loc=(0,y/8, y%8)) - if height == 4: return Or4(loc=(0,y/8, y%8)) - if height == 5: return Or5(loc=(0,y/8, y%8)) - if height == 6: return Or6(loc=(0,y/8, y%8)) + if height == 2: + return Or2(loc=(0, y/8, y % 8)) + if height == 3: + return Or3(loc=(0, y/8, y % 8)) + if height == 4: + return Or4(loc=(0, y/8, y % 8)) + if height == 5: + return Or5(loc=(0, y/8, y % 8)) + if height == 6: + return Or6(loc=(0, y/8, y % 8)) ormxn = join(col(orm, width)) wire(def_.I0, ormxn.I0) wire(def_.I1, ormxn.I1) @@ -215,9 +254,11 @@ def orm(y): return _Or + def Or(height, width=2, **kwargs): return DefineOr(height, width)(**kwargs) + def OrN(n, **kwargs): """Or gate with n-bit input.""" @@ -225,33 +266,38 @@ def OrN(n, **kwargs): if n == 1: return ROM1(A0, **kwargs) if n == 2: - return ROM2(A0|A1, **kwargs) + return ROM2(A0 | A1, **kwargs) if n == 3: - return ROM3(A0|A1|A2, **kwargs) + return ROM3(A0 | A1 | A2, **kwargs) if n == 4: - return ROM4(A0|A1|A2|A3, **kwargs) + return ROM4(A0 | A1 | A2 | A3, **kwargs) if n == 5: - return ROM5(A0|A1|A2|A3|A4, **kwargs) + return ROM5(A0 | A1 | A2 | A3 | A4, **kwargs) if n == 6: - return ROM6(A0|A1|A2|A3|A4|A5, **kwargs) + return ROM6(A0 | A1 | A2 | A3 | A4 | A5, **kwargs) else: - return FlatCascade(n, 6, ~(A0|A1|A2|A3|A4|A5), 0, 1, 0, **kwargs) + return FlatCascade(n, 6, ~(A0 | A1 | A2 | A3 | A4 | A5), 0, 1, 0, **kwargs) def Nor2(**kwargs): - return LUT2(~(A0|A1), **kwargs) + return LUT2(~(A0 | A1), **kwargs) + def Nor3(**kwargs): - return LUT3(~(A0|A1|A2), **kwargs) + return LUT3(~(A0 | A1 | A2), **kwargs) + def Nor4(**kwargs): - return LUT4(~(A0|A1|A2|A3), **kwargs) + return LUT4(~(A0 | A1 | A2 | A3), **kwargs) + def Nor5(): - return LUT5(~(A0|A1|A2|A3|A4)) + return LUT5(~(A0 | A1 | A2 | A3 | A4)) + def Nor6(): - return LUT6(~(A0|A1|A2|A3|A4|A5)) + return LUT6(~(A0 | A1 | A2 | A3 | A4 | A5)) + def DefineNor(height, width): """ @@ -261,27 +307,34 @@ def DefineNor(height, width): """ T = Array(width, Bit) + class _Nor(Circuit): assert height > 1 and height <= 4 name = 'Nor%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def orm(y): - if height == 2: return Nor2(loc=(0,y/8, y%8)) - if height == 3: return Nor3(loc=(0,y/8, y%8)) - if height == 4: return Nor4(loc=(0,y/8, y%8)) - if height == 5: return Nor5(loc=(0,y/8, y%8)) - if height == 6: return Nor6(loc=(0,y/8, y%8)) + if height == 2: + return Nor2(loc=(0, y/8, y % 8)) + if height == 3: + return Nor3(loc=(0, y/8, y % 8)) + if height == 4: + return Nor4(loc=(0, y/8, y % 8)) + if height == 5: + return Nor5(loc=(0, y/8, y % 8)) + if height == 6: + return Nor6(loc=(0, y/8, y % 8)) normxn = join(col(norm, width)) wire(def_.I0, normxn.I0) wire(def_.I1, normxn.I1) @@ -289,9 +342,11 @@ def orm(y): return _Nor + def Nor(height, width=2, **kwargs): return DefineNor(height, width)(**kwargs) + def NorN(n, **kwargs): """Nor gate with n-bit input.""" @@ -299,33 +354,38 @@ def NorN(n, **kwargs): if n == 1: return ROM1(~(A0), **kwargs) if n == 2: - return ROM2(~(A0|A1), **kwargs) + return ROM2(~(A0 | A1), **kwargs) if n == 3: - return ROM3(~(A0|A1|A2), **kwargs) + return ROM3(~(A0 | A1 | A2), **kwargs) if n == 4: - return ROM4(~(A0|A1|A2|A3), **kwargs) + return ROM4(~(A0 | A1 | A2 | A3), **kwargs) if n == 5: - return ROM5(~(A0|A1|A2|A3|A4), **kwargs) + return ROM5(~(A0 | A1 | A2 | A3 | A4), **kwargs) if n == 6: - return ROM6(~(A0|A1|A2|A3|A4|A5), **kwargs) + return ROM6(~(A0 | A1 | A2 | A3 | A4 | A5), **kwargs) else: - return FlatCascade(n, 6, ~(A0|A1|A2|A3|A4|A5), 0, 0, 1, **kwargs) + return FlatCascade(n, 6, ~(A0 | A1 | A2 | A3 | A4 | A5), 0, 0, 1, **kwargs) def Xor2(**kwargs): - return LUT2(A0^A1, **kwargs) + return LUT2(A0 ^ A1, **kwargs) + def Xor3(**kwargs): - return LUT3(A0^A1^A2, **kwargs) + return LUT3(A0 ^ A1 ^ A2, **kwargs) + def Xor4(**kwargs): - return LUT4(A0^A1^A2^A3, **kwargs) + return LUT4(A0 ^ A1 ^ A2 ^ A3, **kwargs) + def Xor5(): - return LUT5(A0^A1^A2^A3^A4, **kwargs) + return LUT5(A0 ^ A1 ^ A2 ^ A3 ^ A4, **kwargs) + def Xor6(): - return LUT6(A0^A1^A2^A3^A4^A5, **kwargs) + return LUT6(A0 ^ A1 ^ A2 ^ A3 ^ A4 ^ A5, **kwargs) + def DefineXor(height, width): """ @@ -335,27 +395,34 @@ def DefineXor(height, width): """ T = Array(width, Bit) + class _Xor(Circuit): assert height > 1 and height <= 4 name = 'Xor%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def xorm(y): - if height == 2: return Xor2(loc=(0,y/8, y%8)) - if height == 3: return Xor3(loc=(0,y/8, y%8)) - if height == 4: return Xor4(loc=(0,y/8, y%8)) - if height == 5: return Xor5(loc=(0,y/8, y%8)) - if height == 6: return Xor6(loc=(0,y/8, y%8)) + if height == 2: + return Xor2(loc=(0, y/8, y % 8)) + if height == 3: + return Xor3(loc=(0, y/8, y % 8)) + if height == 4: + return Xor4(loc=(0, y/8, y % 8)) + if height == 5: + return Xor5(loc=(0, y/8, y % 8)) + if height == 6: + return Xor6(loc=(0, y/8, y % 8)) xormxn = join(col(xorm, width)) wire(def_.I0, xormxn.I0) wire(def_.I1, xormxn.I1) @@ -363,9 +430,11 @@ def xorm(y): return _Xor + def Xor(height, width=2, **kwargs): return DefineXor(height, width)(**kwargs) + def XorN(n, **kwargs): """XNor gate with n-bit input.""" @@ -373,32 +442,37 @@ def XorN(n, **kwargs): if n == 1: return ROM1(A0, **kwargs) if n == 2: - return ROM2(A0^A1, **kwargs) + return ROM2(A0 ^ A1, **kwargs) if n == 3: - return ROM3(A0^A1^A2, **kwargs) + return ROM3(A0 ^ A1 ^ A2, **kwargs) if n == 4: - return ROM4(A0^A1^A2^A3, **kwargs) + return ROM4(A0 ^ A1 ^ A2 ^ A3, **kwargs) if n == 5: - return ROM5(A0^A1^A2^A3^A4, **kwargs) + return ROM5(A0 ^ A1 ^ A2 ^ A3 ^ A4, **kwargs) if n == 6: - return ROM6(A0^A1^A2^A3^A4^A5, **kwargs) + return ROM6(A0 ^ A1 ^ A2 ^ A3 ^ A4 ^ A5, **kwargs) return None def NXor2(**kwargs): - return LUT2(~(A0^A1), **kwargs) + return LUT2(~(A0 ^ A1), **kwargs) + def NXor3(**kwargs): - return LUT3(~(A0^A1^A2), **kwargs) + return LUT3(~(A0 ^ A1 ^ A2), **kwargs) + def NXor4(**kwargs): - return LUT4(~(A0^A1^A2^A3), **kwargs) + return LUT4(~(A0 ^ A1 ^ A2 ^ A3), **kwargs) + def NXor5(**kwargs): - return LUT5(~(A0^A1^A2^A3^A4), **kwargs) + return LUT5(~(A0 ^ A1 ^ A2 ^ A3 ^ A4), **kwargs) + def NXor6(): - return LUT6(~(A0^A1^A2^A3^A4^A5), **kwargs) + return LUT6(~(A0 ^ A1 ^ A2 ^ A3 ^ A4 ^ A5), **kwargs) + def DefineNXor(height, width): """ @@ -408,27 +482,34 @@ def DefineNXor(height, width): """ T = Array(width, Bit) + class _NXor(Circuit): assert height > 1 and height <= 4 name = 'NXor%dx%d' % (height, width) - if height == 2: - IO = ['input I0', T, 'input I1', T] + if height == 2: + io = m.IO('input I0', T, 'input I1', T) elif height == 3: - IO = ['input I0', T, 'input I1', T, 'input I2', T] + io = m.IO('input I0', T, 'input I1', T, 'input I2', T) elif height == 4: - IO = ['input I0', T, 'input I1', T, 'input I2', T, 'input I3', T] - IO += ['output O', T] + io = m.IO('input I0', T, 'input I1', T, + 'input I2', T, 'input I3', T) + IO += ['output O', T] @classmethod def definition(def_): def nxorm(y): - if height == 2: return NXor2(loc=(0,y/8, y%8)) - if height == 3: return NXor3(loc=(0,y/8, y%8)) - if height == 4: return NXor4(loc=(0,y/8, y%8)) - if height == 5: return NXor5(loc=(0,y/8, y%8)) - if height == 6: return NXor6(loc=(0,y/8, y%8)) + if height == 2: + return NXor2(loc=(0, y/8, y % 8)) + if height == 3: + return NXor3(loc=(0, y/8, y % 8)) + if height == 4: + return NXor4(loc=(0, y/8, y % 8)) + if height == 5: + return NXor5(loc=(0, y/8, y % 8)) + if height == 6: + return NXor6(loc=(0, y/8, y % 8)) nxormxn = join(col(nxorm, width)) wire(def_.I0, nxormxn.I0) wire(def_.I1, nxormxn.I1) @@ -436,9 +517,11 @@ def nxorm(y): return _NXor + def NXor(height, width=2, **kwargs): return DefineNXor(height, width)(**kwargs) + def NXorN(n, **kwargs): """XNor gate with n-bit input.""" @@ -446,15 +529,15 @@ def NXorN(n, **kwargs): if n == 1: return ROM1(~(A0), **kwargs) if n == 2: - return ROM2(~(A0^A1), **kwargs) + return ROM2(~(A0 ^ A1), **kwargs) if n == 3: - return ROM3(~(A0^A1^A2), **kwargs) + return ROM3(~(A0 ^ A1 ^ A2), **kwargs) if n == 4: - return ROM4(~(A0^A1^A2^A3), **kwargs) + return ROM4(~(A0 ^ A1 ^ A2 ^ A3), **kwargs) if n == 5: - return ROM5(~(A0^A1^A2^A3^A4), **kwargs) + return ROM5(~(A0 ^ A1 ^ A2 ^ A3 ^ A4), **kwargs) if n == 6: - return ROM6(~(A0^A1^A2^A3^A4^A5), **kwargs) + return ROM6(~(A0 ^ A1 ^ A2 ^ A3 ^ A4 ^ A5), **kwargs) return None @@ -462,6 +545,7 @@ def Buf(**kwargs): """Buffer - 1-bit input.""" return LUT1(A0, **kwargs) + def DefineBuffer(width): """ Generate Buffer module @@ -472,18 +556,19 @@ def DefineBuffer(width): class _Buffer(Circuit): name = 'Buffer%d' % width - IO = ['input I', T, 'output O', T] + io = m.IO('input I', T, 'output O', T) @classmethod def definition(def_): def buf(y): - return Buf(loc=(0,y/8, y%8)) + return Buf(loc=(0, y/8, y % 8)) buffer = join(col(buf, width)) wire(def_.I, buffer.I0) wire(buffer.O, def_.O) return _Buffer + def Buffer(n, **kwargs): return DefineBuffer(n)(**kwargs) @@ -492,6 +577,7 @@ def Not(**kwargs): """Not gate - 1-bit input.""" return LUT1(~A0, **kwargs) + def DefineInvert(width): """ Generate Invert module @@ -500,21 +586,22 @@ def DefineInvert(width): """ T = Array(width, Bit) + class _Invert(Circuit): name = 'Invert%d' % width - IO = ['input I', T, 'output O', T] + io = m.IO('input I', T, 'output O', T) @classmethod def definition(def_): def not_(y): - return Not(loc=(0,y/8, y%8)) + return Not(loc=(0, y/8, y % 8)) invert = join(col(not_, width)) wire(def_.I, invert.I0) wire(invert.O, def_.O) return _Invert + def Invert(n, **kwargs): return DefineInvert(n)(**kwargs) - diff --git a/tests/test_coreir/test_compare.py b/tests/test_coreir/test_compare.py index 5799e45..268b5fd 100644 --- a/tests/test_coreir/test_compare.py +++ b/tests/test_coreir/test_compare.py @@ -3,13 +3,15 @@ from mantle.coreir.compare import EQ, NE, ULT, ULE, UGT, UGE, SLT, SLE, SGT, \ SGE + def check(circuit_type): circuit_type_name = circuit_type.__name__ print(circuit_type_name) - T = UInt[ 4 ] + T = UInt[4] + class TestCircuit(Circuit): name = "test_{}_two".format(circuit_type_name) - IO = ["a", In(T), "b", In(T), "c", Out(Bit)] + io = m.IO(a=In(T), b=In(T), c=Out(Bit)) @classmethod def definition(circuit): print(repr(circuit)) @@ -20,35 +22,46 @@ def definition(circuit): compile("build/test_{}_two".format(circuit_type_name), TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_{}_two.json".format(circuit_type_name), - "gold/test_{}_two.json".format(circuit_type_name)) + "build/test_{}_two.json".format( + circuit_type_name), + "gold/test_{}_two.json".format(circuit_type_name)) + def test_eq(): check(EQ) + def test_ne(): check(NE) + def test_ult(): check(ULT) + def test_ule(): check(ULE) + def test_ugt(): check(UGT) + def test_uge(): check(UGE) + def test_slt(): check(SLT) + def test_sle(): check(SLE) + def test_sgt(): check(SGT) + def test_sge(): check(SGE) diff --git a/tests/test_coreir/test_conv.py b/tests/test_coreir/test_conv.py index fb0e108..9d3fd4d 100644 --- a/tests/test_coreir/test_conv.py +++ b/tests/test_coreir/test_conv.py @@ -3,122 +3,148 @@ from mantle import * import mantle.coreir + def Define_mantle_reg_U6(init): - class mantle_reg_U6(Circuit): - name = f"mantle_reg_U6_{init}" - IO = ["I", Array[ 4,In(Bit) ], "clk", In(Clock), "O", Array[ 4,Out(Bit) ], "en", In(Bit)] + class mantle_reg_U6(Circuit): + name = f"mantle_reg_U6_{init}" + io = m.IO(I=Array[4, In(Bit)], clk=In(Clock), + O=Array[4, Out(Bit)], en=In(Bit)) + + @classmethod + def definition(io): + enMux = mantle.coreir.DefineCoreirMux(width=4)(name="enMux") + reg0 = mantle.coreir.DefineCoreirReg( + init=init, width=4)(name="reg0") + wire(enMux.I0, reg0.O) + wire(enMux.I1, io.I) + wire(reg0.I, enMux.O) + wire(enMux.S, io.en) + wire(reg0.CLK, io.clk) + wire(io.O, reg0.O) + return mantle_reg_U6 + + +class commonlib_LinebufferMem_U5(Circuit): + name = "commonlib_LinebufferMem_U5" + io = m.IO(clk=In(Clock), rdata=Array[16, Out(Bit)], valid=Out( + Bit), wdata=Array[16, In(Bit)], wen=In(Bit)) + @classmethod def definition(io): - enMux = mantle.coreir.DefineCoreirMux(width=4)(name="enMux") - reg0 = mantle.coreir.DefineCoreirReg(init=init, width=4)(name="reg0") - wire(enMux.I0, reg0.O) - wire(enMux.I1, io.I) - wire(reg0.I, enMux.O) - wire(enMux.S, io.en) - wire(reg0.CLK, io.clk) - wire(io.O, reg0.O) - return mantle_reg_U6 + add_r = mantle.coreir.DefineCoreirAdd(width=4)(name="add_r") + add_w = mantle.coreir.DefineCoreirAdd(width=4)(name="add_w") + c1 = mantle.coreir.DefineCoreirConst(value=1, width=4)(name="c1") + max_const = mantle.coreir.DefineCoreirConst( + value=10, width=4)(name="max_const") + mem = mantle.coreir.DefineCoreirMem(depth=10, width=16)(name="mem") + raddr = Define_mantle_reg_U6(init=0)() + raddr_eq = mantle.coreir.DefineCoreirEq(width=4)(name="raddr_eq") + raddr_mux = mantle.coreir.DefineCoreirMux(width=4)(name="raddr_mux") + veq = mantle.coreir.DefineCoreirNeq(width=4)(name="veq") + waddr = Define_mantle_reg_U6(init=0)() + waddr_eq = mantle.coreir.DefineCoreirEq(width=4)(name="waddr_eq") + waddr_mux = mantle.coreir.DefineCoreirMux(width=4)(name="waddr_mux") + zero_const = mantle.coreir.DefineCoreirConst( + value=0, width=4)(name="zero_const") + wire(add_r.I0, raddr.O) + wire(add_r.I1, c1.O) + wire(raddr_eq.I0, add_r.O) + wire(raddr_mux.I0, add_r.O) + wire(add_w.I0, waddr.O) + wire(add_w.I1, c1.O) + wire(waddr_eq.I0, add_w.O) + wire(waddr_mux.I0, add_w.O) + wire(raddr_eq.I1, max_const.O) + wire(waddr_eq.I1, max_const.O) + wire(mem.clk, io.clk) + wire(mem.raddr, raddr.O) + wire(io.rdata, mem.rdata) + wire(mem.waddr, waddr.O) + wire(mem.wdata, io.wdata) + wire(mem.wen, io.wen) + wire(raddr.clk, io.clk) + wire(raddr.en, io.wen) + wire(raddr.I, raddr_mux.O) + wire(veq.I0, raddr.O) + wire(raddr_mux.S, raddr_eq.O) + wire(raddr_mux.I1, zero_const.O) + wire(waddr.clk, io.clk) + wire(io.valid, veq.O) + wire(waddr.en, io.wen) + wire(veq.I1, waddr.O) + wire(waddr.I, waddr_mux.O) + wire(waddr_mux.S, waddr_eq.O) + wire(waddr_mux.I1, zero_const.O) -class commonlib_LinebufferMem_U5(Circuit): - name = "commonlib_LinebufferMem_U5" - IO = ["clk", In(Clock), "rdata", Array[ 16,Out(Bit) ], "valid", Out(Bit), "wdata", Array[ 16,In(Bit) ], "wen", In(Bit)] - @classmethod - def definition(io): - add_r = mantle.coreir.DefineCoreirAdd(width=4)(name="add_r") - add_w = mantle.coreir.DefineCoreirAdd(width=4)(name="add_w") - c1 = mantle.coreir.DefineCoreirConst(value=1, width=4)(name="c1") - max_const = mantle.coreir.DefineCoreirConst(value=10, width=4)(name="max_const") - mem = mantle.coreir.DefineCoreirMem(depth=10, width=16)(name="mem") - raddr = Define_mantle_reg_U6(init=0)() - raddr_eq = mantle.coreir.DefineCoreirEq(width=4)(name="raddr_eq") - raddr_mux = mantle.coreir.DefineCoreirMux(width=4)(name="raddr_mux") - veq = mantle.coreir.DefineCoreirNeq(width=4)(name="veq") - waddr = Define_mantle_reg_U6(init=0)() - waddr_eq = mantle.coreir.DefineCoreirEq(width=4)(name="waddr_eq") - waddr_mux = mantle.coreir.DefineCoreirMux(width=4)(name="waddr_mux") - zero_const = mantle.coreir.DefineCoreirConst(value=0, width=4)(name="zero_const") - wire(add_r.I0, raddr.O) - wire(add_r.I1, c1.O) - wire(raddr_eq.I0, add_r.O) - wire(raddr_mux.I0, add_r.O) - wire(add_w.I0, waddr.O) - wire(add_w.I1, c1.O) - wire(waddr_eq.I0, add_w.O) - wire(waddr_mux.I0, add_w.O) - wire(raddr_eq.I1, max_const.O) - wire(waddr_eq.I1, max_const.O) - wire(mem.clk, io.clk) - wire(mem.raddr, raddr.O) - wire(io.rdata, mem.rdata) - wire(mem.waddr, waddr.O) - wire(mem.wdata, io.wdata) - wire(mem.wen, io.wen) - wire(raddr.clk, io.clk) - wire(raddr.en, io.wen) - wire(raddr.I, raddr_mux.O) - wire(veq.I0, raddr.O) - wire(raddr_mux.S, raddr_eq.O) - wire(raddr_mux.I1, zero_const.O) - wire(waddr.clk, io.clk) - wire(io.valid, veq.O) - wire(waddr.en, io.wen) - wire(veq.I1, waddr.O) - wire(waddr.I, waddr_mux.O) - wire(waddr_mux.S, waddr_eq.O) - wire(waddr_mux.I1, zero_const.O) class commonlib_Linebuffer_U3(Circuit): - name = "commonlib_Linebuffer_U3" - IO = ["clk", In(Clock), "I", Array[ 16,In(Bit) ], "wen", In(Bit), "O", Array[ 2,Array[ 1,Array[ 16,Out(Bit) ] ] ]] - @classmethod - def definition(io): - mem_1 = commonlib_LinebufferMem_U5() - mem_1_valid_term = mantle.coreir.DefineCorebitTerm()(name="mem_1_valid_term") - wire(io.O[0][0], mem_1.rdata) - wire(mem_1_valid_term.I, mem_1.valid) - wire(mem_1.wdata, io.I) - wire(mem_1.wen, io.wen) - wire(io.O[1][0], io.I) + name = "commonlib_Linebuffer_U3" + io = m.IO(clk=In(Clock), I=Array[16, In(Bit)], wen=In( + Bit), O=Array[2, Array[1, Array[16, Out(Bit)]]]) + + @classmethod + def definition(io): + mem_1 = commonlib_LinebufferMem_U5() + mem_1_valid_term = mantle.coreir.DefineCorebitTerm()(name="mem_1_valid_term") + wire(io.O[0][0], mem_1.rdata) + wire(mem_1_valid_term.I, mem_1.valid) + wire(mem_1.wdata, io.I) + wire(mem_1.wen, io.wen) + wire(io.O[1][0], io.I) + class mantle_wire_U0(Circuit): - name = "mantle_wire_U0" - IO = ["I", Array[ 16,In(Bit) ], "O", Array[ 16,Out(Bit) ]] - @classmethod - def definition(io): - wire(io.O, io.I) + name = "mantle_wire_U0" + io = m.IO(I=Array[16, In(Bit)], O=Array[16, Out(Bit)]) + @classmethod + def definition(io): + wire(io.O, io.I) + class global_DesignTop(Circuit): - name = "global_DesignTop" - IO = ["clk", In(Clock), "I", Array[ 1,Array[ 16,In(Bit) ] ], "O", Array[ 16,Out(Bit) ]] - @classmethod - def definition(io): - _336_pt = mantle_wire_U0() - _341_pt = mantle_wire_U0() - add_335_339_340 = mantle.coreir.DefineCoreirAdd(width=16)(name="add_335_339_340") - add_335_343_344 = mantle.coreir.DefineCoreirAdd(width=16)(name="add_335_343_344") - const0__334 = mantle.coreir.DefineCoreirConst(value=0, width=16)(name="const0__334") - const7__338 = mantle.coreir.DefineCoreirConst(value=7, width=16)(name="const7__338") - const7__338__ds__1 = mantle.coreir.DefineCoreirConst(value=7, width=16)(name="const7__338__ds__1") - lb_p4_clamped_stencil_update_stream = commonlib_Linebuffer_U3() - lb_p4_clamped_stencil_update_stream_wen = mantle.coreir.DefineCorebitConst(value=1)(name="lb_p4_clamped_stencil_update_stream_wen") - mul_337_338_339 = mantle.coreir.DefineCoreirMul(width=16)(name="mul_337_338_339") - mul_342_338_343 = mantle.coreir.DefineCoreirMul(width=16)(name="mul_342_338_343") - wire(_336_pt.I, lb_p4_clamped_stencil_update_stream.O[0][0]) - wire(mul_337_338_339.I0, _336_pt.O) - wire(_341_pt.I, lb_p4_clamped_stencil_update_stream.O[1][0]) - wire(mul_342_338_343.I0, _341_pt.O) - wire(add_335_339_340.I0, const0__334.O) - wire(add_335_339_340.I1, mul_337_338_339.O) - wire(add_335_343_344.I0, add_335_339_340.O) - wire(add_335_343_344.I1, mul_342_338_343.O) - wire(io.O, add_335_343_344.O) - wire(mul_337_338_339.I1, const7__338.O) - wire(mul_342_338_343.I1, const7__338__ds__1.O) - wire(lb_p4_clamped_stencil_update_stream.clk, io.clk) - wire(lb_p4_clamped_stencil_update_stream.I, io.I[0]) - wire(lb_p4_clamped_stencil_update_stream.wen, lb_p4_clamped_stencil_update_stream_wen.O) + name = "global_DesignTop" + io = m.IO(clk=In(Clock), + I=Array[1, Array[16, In(Bit)]], O=Array[16, Out(Bit)]) + + @classmethod + def definition(io): + _336_pt = mantle_wire_U0() + _341_pt = mantle_wire_U0() + add_335_339_340 = mantle.coreir.DefineCoreirAdd( + width=16)(name="add_335_339_340") + add_335_343_344 = mantle.coreir.DefineCoreirAdd( + width=16)(name="add_335_343_344") + const0__334 = mantle.coreir.DefineCoreirConst( + value=0, width=16)(name="const0__334") + const7__338 = mantle.coreir.DefineCoreirConst( + value=7, width=16)(name="const7__338") + const7__338__ds__1 = mantle.coreir.DefineCoreirConst( + value=7, width=16)(name="const7__338__ds__1") + lb_p4_clamped_stencil_update_stream = commonlib_Linebuffer_U3() + lb_p4_clamped_stencil_update_stream_wen = mantle.coreir.DefineCorebitConst( + value=1)(name="lb_p4_clamped_stencil_update_stream_wen") + mul_337_338_339 = mantle.coreir.DefineCoreirMul( + width=16)(name="mul_337_338_339") + mul_342_338_343 = mantle.coreir.DefineCoreirMul( + width=16)(name="mul_342_338_343") + wire(_336_pt.I, lb_p4_clamped_stencil_update_stream.O[0][0]) + wire(mul_337_338_339.I0, _336_pt.O) + wire(_341_pt.I, lb_p4_clamped_stencil_update_stream.O[1][0]) + wire(mul_342_338_343.I0, _341_pt.O) + wire(add_335_339_340.I0, const0__334.O) + wire(add_335_339_340.I1, mul_337_338_339.O) + wire(add_335_343_344.I0, add_335_339_340.O) + wire(add_335_343_344.I1, mul_342_338_343.O) + wire(io.O, add_335_343_344.O) + wire(mul_337_338_339.I1, const7__338.O) + wire(mul_342_338_343.I1, const7__338__ds__1.O) + wire(lb_p4_clamped_stencil_update_stream.clk, io.clk) + wire(lb_p4_clamped_stencil_update_stream.I, io.I[0]) + wire(lb_p4_clamped_stencil_update_stream.wen, + lb_p4_clamped_stencil_update_stream_wen.O) + def test_conv(): compile("build/test_coreir_conv", global_DesignTop, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_conv.json", "gold/test_coreir_conv.json") + "build/test_coreir_conv.json", "gold/test_coreir_conv.json") diff --git a/tests/test_coreir/test_coreir_shift_register.py b/tests/test_coreir/test_coreir_shift_register.py index d37628d..50fd85d 100644 --- a/tests/test_coreir/test_coreir_shift_register.py +++ b/tests/test_coreir/test_coreir_shift_register.py @@ -6,11 +6,11 @@ def test_shift_register(): N = 4 Register4 = DefineRegister(4) - T = m.Bits[ N ] + T = m.Bits[N] class ShiftRegister(m.Circuit): name = "ShiftRegister" - IO = ["I", m.In(T), "O", m.Out(T), "CLK", m.In(m.Clock)] + io = m.IO(I=m.In(T), O=m.Out(T), CLK=m.In(m.Clock)) @classmethod def definition(io): regs = [Register4() for _ in range(N)] diff --git a/tests/test_coreir/test_logic.py b/tests/test_coreir/test_logic.py index baf22a9..b397db2 100644 --- a/tests/test_coreir/test_logic.py +++ b/tests/test_coreir/test_logic.py @@ -1,18 +1,18 @@ +import fault +from mantle import lsl, lsr +from mantle.coreir import static_left_shift, static_right_shift, Wire +from mantle.coreir import NAnd, NOr, NXOr, ReduceNAnd, ReduceNOr, ReduceNXOr +from mantle.coreir import And, Or, XOr, Not, Invert, ReduceAnd, ReduceOr, ReduceXOr +from magma.testing import check_files_equal +from magma import * import pytest coreir = pytest.importorskip("coreir") -from magma import * -from magma.testing import check_files_equal -from mantle.coreir import And, Or, XOr, Not, Invert, ReduceAnd, ReduceOr, ReduceXOr -from mantle.coreir import NAnd, NOr, NXOr, ReduceNAnd, ReduceNOr, ReduceNXOr -from mantle.coreir import static_left_shift, static_right_shift, Wire -from mantle import lsl, lsr -import fault def test_coreir_bit(): class TestCircuit(Circuit): name = "test_coreir_bit" - IO = ["a", In(Bit), "b", In(Bit), "c", In(Bit), "d", Out(Bit)] + io = m.IO(a=In(Bit), b=In(Bit), c=In(Bit), d=Out(Bit)) @classmethod def definition(circuit): d = Or(2)(Not()(And(2)(circuit.a, circuit.b)), @@ -20,74 +20,87 @@ def definition(circuit): wire(d, circuit.d) compile("build/test_coreir_bit", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_bit.json", "gold/test_coreir_bit.json") + "build/test_coreir_bit.json", "gold/test_coreir_bit.json") def test_coreir_bit_2(): class TestCircuit(Circuit): name = "test_coreir_bit_2" - IO = ["a", In(Bit), "b", In(Bit), "c", In(Bit), "d", Out(Bit)] + io = m.IO(a=In(Bit), b=In(Bit), c=In(Bit), d=Out(Bit)) @classmethod def definition(circuit): d = NOr(2)((NAnd(2)(circuit.a, circuit.b)), - NXOr(2)(circuit.b, circuit.c)) + NXOr(2)(circuit.b, circuit.c)) wire(d, circuit.d) compile("build/test_coreir_bit_2", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_bit_2.json", "gold/test_coreir_bit_2.json") + "build/test_coreir_bit_2.json", "gold/test_coreir_bit_2.json") def test_coreir_bits(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_bits" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", In(Bits[ width ]), "d", Out(Bits[ width ])] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), + c=In(Bits[width]), d=Out(Bits[width])) + @classmethod def definition(circuit): d = Or(2, width)(Invert(width)(And(2, width)(circuit.a, circuit.b)), - XOr(2, width)(circuit.b, circuit.c)) + XOr(2, width)(circuit.b, circuit.c)) wire(d, circuit.d) compile("build/test_coreir_bits", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_bits.json", "gold/test_coreir_bits.json") + "build/test_coreir_bits.json", "gold/test_coreir_bits.json") def test_coreir_bits_2(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_bits_2" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", In(Bits[ width ]), "d", Out(Bits[ width ])] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), + c=In(Bits[width]), d=Out(Bits[width])) + @classmethod def definition(circuit): d = NOr(2, width)(NAnd(2, width)(circuit.a, circuit.b), - NXOr(2, width)(circuit.b, circuit.c)) + NXOr(2, width)(circuit.b, circuit.c)) wire(d, circuit.d) compile("build/test_coreir_bits_2", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_bits_2.json", "gold/test_coreir_bits_2.json") + "build/test_coreir_bits_2.json", "gold/test_coreir_bits_2.json") def test_three_args(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_three_args" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", In(Bits[ width ]), "d", Out(Bits[ width ])] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), + c=In(Bits[width]), d=Out(Bits[width])) + @classmethod def definition(circuit): d = Or(3, width)(circuit.a, - Invert(width)(And(3, width)(circuit.a, circuit.b, circuit.c)), + Invert(width)(And(3, width)( + circuit.a, circuit.b, circuit.c)), XOr(3, width)(circuit.b, circuit.c, circuit.a)) wire(d, circuit.d) compile("build/test_coreir_three_args", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_three_args.json", "gold/test_coreir_three_args.json") + "build/test_coreir_three_args.json", "gold/test_coreir_three_args.json") def test_reduce(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_reduce" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", In(Bits[ width ]), "d", Out(Bit)] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), + c=In(Bits[width]), d=Out(Bit)) + @classmethod def definition(circuit): d = Or(3, None)(ReduceAnd(width)(circuit.a), @@ -96,14 +109,17 @@ def definition(circuit): wire(d, circuit.d) compile("build/test_coreir_reduce", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_reduce.json", "gold/test_coreir_reduce.json") + "build/test_coreir_reduce.json", "gold/test_coreir_reduce.json") def test_reduce_2(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_reduce_2" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", In(Bits[ width ]), "d", Out(Bit)] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), + c=In(Bits[width]), d=Out(Bit)) + @classmethod def definition(circuit): d = Or(3, None)(ReduceNAnd(width)(circuit.a), @@ -112,14 +128,15 @@ def definition(circuit): wire(d, circuit.d) compile("build/test_coreir_reduce_2", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_reduce_2.json", "gold/test_coreir_reduce_2.json") + "build/test_coreir_reduce_2.json", "gold/test_coreir_reduce_2.json") def test_static_shift(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_static_shift" - IO = ["a", In(Bits[ width ]), "b", In(Bits[ width ]), "c", Out(Bits[ width ])] + io = m.IO(a=In(Bits[width]), b=In(Bits[width]), c=Out(Bits[width])) @classmethod def definition(circuit): c = Or(2, width)(static_left_shift(circuit.a, 2), @@ -127,14 +144,15 @@ def definition(circuit): wire(c, circuit.c) compile("build/test_coreir_static_shift", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_static_shift.json", "gold/test_coreir_static_shift.json") + "build/test_coreir_static_shift.json", "gold/test_coreir_static_shift.json") def test_ls(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_ls" - IO = ["a", In(Bits[ width ]), "b", In(UInt[ width ]), "c", Out(Bits[ width ])] + io = m.IO(a=In(Bits[width]), b=In(UInt[width]), c=Out(Bits[width])) @classmethod def definition(circuit): c = Or(2, width)(lsl(circuit.a, circuit.b), @@ -142,14 +160,15 @@ def definition(circuit): wire(c, circuit.c) compile("build/test_coreir_ls", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_ls.json", "gold/test_coreir_ls.json") + "build/test_coreir_ls.json", "gold/test_coreir_ls.json") def test_wire(): width = 4 + class TestCircuit(Circuit): name = "test_coreir_wire" - IO = ["a", In(Bits[ width ]), "b", Out(Bits[ width ]), "e", Out(Bit)] + io = m.IO(a=In(Bits[width]), b=Out(Bits[width]), e=Out(Bit)) @classmethod def definition(circuit): c = Wire(width, name="c") @@ -158,7 +177,7 @@ def definition(circuit): wire(d(circuit.a[0]), circuit.e) compile("build/test_coreir_wire", TestCircuit, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_wire.json", "gold/test_coreir_wire.json") + "build/test_coreir_wire.json", "gold/test_coreir_wire.json") tester = fault.Tester(TestCircuit) for i in range(0, 1 << 4): tester.poke(TestCircuit.a, i) diff --git a/tests/test_coreir/test_lut.py b/tests/test_coreir/test_lut.py index 50e4052..7ad72d7 100644 --- a/tests/test_coreir/test_lut.py +++ b/tests/test_coreir/test_lut.py @@ -8,7 +8,7 @@ def test_coreir_lut(): class Test(m.Circuit): name = "test_coreir_lut3" - IO = ["I", m.In(m.Bits(3)), "O", Out(Bit)] + io = m.IO(I=m.In(m.Bits(3)), O=Out(Bit)) @classmethod def definition(cls): lut3 = LUT(0xDE, 3) @@ -18,4 +18,4 @@ def definition(cls): m.compile("build/test_lut3", Test, output="coreir") assert check_files_equal(__file__, - "build/test_lut3.json", "gold/test_lut3.json") + "build/test_lut3.json", "gold/test_lut3.json") diff --git a/tests/test_coreir/test_memory.py b/tests/test_coreir/test_memory.py index ea19e89..18cc1fb 100644 --- a/tests/test_coreir/test_memory.py +++ b/tests/test_coreir/test_memory.py @@ -1,24 +1,27 @@ +import os +from magma.backend.coreir_ import CoreIRBackend +from magma.simulator.coreir_simulator import CoreIRSimulator +from mantle import RAM +from mantle.coreir.memory import DefineCoreirMem, DefineRAM, DefineMemory +from magma.testing import check_files_equal +from magma import * import pytest coreir = pytest.importorskip("coreir") -from magma import * -from magma.testing import check_files_equal -from mantle.coreir.memory import DefineCoreirMem, DefineRAM, DefineMemory -from mantle import RAM -from magma.simulator.coreir_simulator import CoreIRSimulator -from magma.backend.coreir_ import CoreIRBackend -import os + def test_coreir_rom(): addr_width = 2 width = 16 + class Mem(Circuit): name = "test_coreir_mem" - IO = ["raddr", In(Bits[ addr_width ]), - "rdata", Out(Bits[ width ]), - "waddr", In(Bits[ addr_width ]), - "wdata", In(Bits[ width ]), - "clk", In(Clock), - "wen", In(Bit) ] + io = m.IO(raddr=In(Bits[addr_width]), + rdata=Out(Bits[width]), + waddr=In(Bits[addr_width]), + wdata=In(Bits[width]), + clk=In(Clock), + wen=In(Bit)) + @classmethod def definition(io): mem = DefineCoreirMem(4, 16)() @@ -30,7 +33,8 @@ def definition(io): wire(io.wen, mem.wen) compile("build/test_coreir_mem", Mem, output="coreir") assert check_files_equal(__file__, - "build/test_coreir_mem.json", "gold/test_coreir_mem.json") + "build/test_coreir_mem.json", "gold/test_coreir_mem.json") + def test_ram1x8(): c = coreir.Context() @@ -39,10 +43,12 @@ def test_ram1x8(): testcircuit = DefineRAM(1, 8) CoreIRSimulator(testcircuit, testcircuit.CLK, context=cirb.context) + def test_ram_latency1(): - mem = DefineMemory(height=256,width=16,read_latency=1) + mem = DefineMemory(height=256, width=16, read_latency=1) compile("build/test_latency", mem, output='coreir-verilog') - assert check_files_equal(__file__,"build/test_latency.v","gold/test_latency.v") + assert check_files_equal( + __file__, "build/test_latency.v", "gold/test_latency.v") def test_generic_memory_import(): diff --git a/tests/test_coreir/test_mux.py b/tests/test_coreir/test_mux.py index 1b7f03e..467c433 100644 --- a/tests/test_coreir/test_mux.py +++ b/tests/test_coreir/test_mux.py @@ -8,12 +8,12 @@ m.Array[2, m.Tuple[m.Bit, m.Bits[2]]]]) def test_coreir_mux_complex(T): class Main(m.Circuit): - IO = [ - "I0", m.In(T), - "I1", m.In(T), - "S", m.In(m.Bit), - "O", m.Out(T) - ] + io = m.IO( + I0=m.In(T), + I1=m.In(T), + S=m.In(m.Bit), + O=m.Out(T) + ) @classmethod def definition(circuit): MuxT = mantle.DefineMux(2, T=type(circuit.I0)) diff --git a/tests/test_coreir/test_operator.py b/tests/test_coreir/test_operator.py index a0bf8f8..f5c21f0 100644 --- a/tests/test_coreir/test_operator.py +++ b/tests/test_coreir/test_operator.py @@ -6,7 +6,7 @@ def test_dyanmic_mux_getitem(): class TestDynamicMuxGetItem(m.Circuit): - IO = ["I", m.In(m.Bits[ 2 ]), "S", m.In(m.Bit), "O", m.Out(m.Bit)] + io = m.IO(I=m.In(m.Bits[2]), S=m.In(m.Bit), O=m.Out(m.Bit)) @classmethod def definition(io): diff --git a/tests/test_coreir/test_register.py b/tests/test_coreir/test_register.py index 0ead341..1a86b1b 100644 --- a/tests/test_coreir/test_register.py +++ b/tests/test_coreir/test_register.py @@ -6,14 +6,14 @@ @pytest.mark.parametrize("has_ce", [True, False]) @pytest.mark.parametrize("has_async_reset,has_async_resetn", [(True, False), - (False, True), - (False, False)]) + (False, True), + (False, False)]) def test_reg(has_ce, has_async_reset, has_async_resetn): def DefineReg(): class testReg(m.Circuit): name = "test" - IO = ["clk", m.In(m.Clock)] + io = m.IO(clk=m.In(m.Clock)) IO += ["In0", m.In(m.Bits[1])] IO += ["Out0", m.Out(m.Bits[1])] IO += m.ClockInterface(has_ce=has_ce, @@ -31,7 +31,8 @@ def definition(io): return testReg test = DefineReg() - m.compile(f"build/testReg-{has_ce}-{has_async_reset}-{has_async_resetn}", test, output="coreir-verilog") + m.compile( + f"build/testReg-{has_ce}-{has_async_reset}-{has_async_resetn}", test, output="coreir-verilog") assert check_files_equal( __file__, diff --git a/tests/test_coreir/util.py b/tests/test_coreir/util.py index 1cbf201..1edce44 100644 --- a/tests/test_coreir/util.py +++ b/tests/test_coreir/util.py @@ -2,7 +2,7 @@ def wrap(circ): - _IO = [] + _io = m.IO() for key, value in circ.IO.items(): _IO += [key, value] diff --git a/tests/test_mantle/test_operator.py b/tests/test_mantle/test_operator.py index aca89f1..eefcf51 100644 --- a/tests/test_mantle/test_operator.py +++ b/tests/test_mantle/test_operator.py @@ -5,10 +5,11 @@ def test_mux(): class Test(m.Circuit): - IO = ["I0", m.In(m.Bits[10]), - "I1", m.In(m.Bits[10]), - "S", m.In(m.Bit), - "O", m.Out(m.Bits[10])] + io = m.IO(I0=m.In(m.Bits[10]), + I1=m.In(m.Bits[10]), + S=m.In(m.Bit), + O=m.Out(m.Bits[10])) + @classmethod def definition(io): io.O <= mantle.mux([io.I0, io.I1], io.S, name="my_mux")