Пример #1
0
class M5:
    in0 = Input(dim(types.i32, 16))
    in1 = Input(types.i32)
    t_c = dim(types.i32, 16)
    c = Output(t_c)

    @generator
    def build(ports):
        # a 32x32xi1 ndarray.
        # A dtype of i32 is fairly expensive wrt. the size of the output IR, but
        # but allows for assigning indiviudal bits.
        m = NDArray((32, 32), dtype=types.i1, name='m1')

        # Assign individual bits to the first 32 bits.
        for i in range(32):
            m[0, i] = hw.ConstantOp(types.i1, 1)

        # Fill the next 15 values with an i32. The ndarray knows how to convert
        # from i32 to <32xi1> to comply with the ndarray dtype.
        for i in range(1, 16):
            m[i] = ports.in1

        # Fill the upportmost 16 rows with the input array of in0 : 16xi32
        m[16:32] = ports.in0

        # We don't provide a method of reshaping the ndarray wrt. its dtype.
        # that is: 32x32xi1 => 32xi32
        # This has massive overhead in the generated IR, and can be easily
        # achieved by a bitcast.
        ports.c = hw.BitcastOp(M5.t_c, m.to_circt())
Пример #2
0
class Plus:
    a = Input(types.i32)
    b = Input(types.i32)
    y = Output(types.i32)

    def __init__(self, name: str = None) -> None:
        if name is not None:
            self.instance_name = name
Пример #3
0
class Mux:
    clk = Clock()
    data = Input(dim(8, 14))
    sel = Input(types.i4)

    out = Output(types.i8)

    @generator
    def build(ports):
        sel_reg = ports.sel.reg()
        ports.out = ports.data.reg()[sel_reg].reg()
Пример #4
0
class M1:
    in1 = Input(dim(types.i32, 10))
    in2 = Input(dim(types.i32, 10))
    in3 = Input(dim(types.i32, 10))
    out = Output(dim(types.i32, 30))

    @generator
    def build(ports):
        # Explicit ndarray.
        m = NDArray(from_value=ports.in1, name='m1')
        # Here we could do a sequence of transformations on 'm'...
        # Finally, concatenate [in2, m, in3]
        ports.out = ports.in2.concatenate((m, ports.in3))
Пример #5
0
class CompReg:
    clk = Input(types.i1)
    input = Input(types.i8)
    output = Output(types.i8)

    @generator
    def build(ports):
        compreg = seq.CompRegOp(types.i8,
                                clk=ports.clk,
                                input=ports.input,
                                name="reg",
                                sym_name="reg")
        ports.output = compreg
Пример #6
0
class FSM:
    a = Input(types.i1)
    b = Input(types.i1)
    c = Input(types.i1)

    # States
    A = fsm.State(initial=True)
    (B, C) = fsm.States(2)

    # Transitions
    A.set_transitions((B, lambda ports: ports.a))
    B.set_transitions((A, lambda ports: ports.b), (C, ))
    C.set_transitions((B, lambda ports: ports.a))
Пример #7
0
class M2:
    in0 = Input(dim(types.i32, 16))
    in1 = Input(types.i32)
    t_c = dim(types.i32, 8, 4)
    c = Output(t_c)

    @generator
    def build(ports):
        # a 32xi32 ndarray.
        m = NDArray((32, ), dtype=types.i32, name='m2')
        for i in range(16):
            m[i] = ports.in1
        m[16:32] = ports.in0
        m = m.reshape((4, 8))
        ports.c = m.to_circt()
Пример #8
0
class FSMUser:
    a = Input(types.i1)
    b = Input(types.i1)
    c = Input(types.i1)
    clk = Input(types.i1)
    is_a = Output(types.i1)
    is_b = Output(types.i1)
    is_c = Output(types.i1)

    @generator
    def construct(ports):
        fsm = FSM(a=ports.a, b=ports.b, c=ports.c, clk=ports.clk)
        ports.is_a = fsm.is_A
        ports.is_b = fsm.is_B
        ports.is_c = fsm.is_C
Пример #9
0
class Slicing:
  In = Input(dim(8, 4, 5))
  Sel8 = Input(types.i8)
  Sel2 = Input(types.i2)

  OutIntSlice = Output(types.i2)
  OutArrSlice8 = Output(dim(8, 4, 2))
  OutArrSlice2 = Output(dim(8, 4, 2))

  @generator
  def create(ports):
    i = ports.In[0][0]
    ports.OutIntSlice = i.slice(ports.Sel2, 2)
    ports.OutArrSlice2 = ports.In.slice(ports.Sel2, 2)
    ports.OutArrSlice8 = ports.In.slice(ports.Sel8, 2)
Пример #10
0
class M1:
    in1 = Input(dim(types.i32, 4, 8))
    out = Output(dim(types.i32, 2, 16))

    @generator
    def build(ports):
        ports.out = ports.in1.transpose((1, 0)).reshape((16, 2))
Пример #11
0
class M1:
    in1 = Input(dim(types.i32, 4, 8))
    out = Output(dim(types.i32, 8, 4))

    @generator
    def build(ports):
        ports.out = ports.in1.transpose((1, 0))
Пример #12
0
class ClkError:
    a = Input(types.i32)

    @generator
    def build(ports):
        # CHECK: ValueError: If 'clk' not specified, must be in clock block
        ports.a.reg()
Пример #13
0
class Test:
    clk = Clock()
    x = Input(types.i32)

    @generator
    def build(ports):
        ports.x.reg(appid=AppID("reg", 5))
Пример #14
0
class Top:
  clk = Input(types.i1)

  @generator
  def construct(ports):
    p = Producer(clk=ports.clk)
    Consumer(clk=ports.clk, int_in=p.const_out)
Пример #15
0
class M1:
    in1 = Input(dim(types.i32, 10))
    out = Output(dim(types.i32, 10))

    @generator
    def build(ports):
        ports.out = ports.in1.roll(3)
Пример #16
0
class Consumer:
  clk = Input(types.i1)
  int_in = InputChannel(types.i32)

  @generator
  def construct(ports):
    data, valid = ports.int_in.unwrap(ready=1)
Пример #17
0
class M1:
    in1 = Input(dim(types.i32, 10))

    @generator
    def build(ports):
        # CHECK: ValueError: Must specify either shape and dtype, or initialize from a value, but not both.
        NDArray((10, 32), from_value=ports.in1, dtype=types.i1, name='m1')
Пример #18
0
class M1:
    in1 = Input(dim(types.i32, 10))
    out = Output(dim(types.i32, 10))

    @generator
    def build(ports):
        m = NDArray(from_value=ports.in1, name='m1')
        ports.out = m.to_circt(create_wire=False)
Пример #19
0
class Producer:
  clk = Input(types.i1)
  const_out = OutputChannel(types.i32)

  @generator
  def construct(ports):
    chan, ready = types.channel(types.i32).wrap(42, valid=1)
    ports.const_out = chan
Пример #20
0
def fsm_wrapper_class(fsm_mod, fsm_name, clock, reset=None):
    """
  Generate a wrapper class for the FSM class which contains the clock and reset
  signals, as well as a `fsm.hw_instance` instaitiation of the FSM.
  """
    class fsm_hw_mod:
        @generator
        def construct(ports):
            in_ports = {
                port_name: getattr(ports, port_name)
                for (port_name, _) in fsm_mod._pycde_mod.input_ports
            }
            fsm_instance = fsm_mod(**in_ports)
            # Attach clock and optional reset on the backedges created during
            # the MachineOp:instatiate call.
            clock_be = getattr(fsm_instance._instantiation, '_clock_backedge')
            connect(clock_be, getattr(ports, clock))
            if hasattr(fsm_instance._instantiation, '_reset_backedge'):
                reset_be = getattr(fsm_instance._instantiation,
                                   '_reset_backedge')
                connect(reset_be, getattr(ports, reset))

            # Connect outputs
            for (port_name, _) in fsm_mod._pycde_mod.output_ports:
                setattr(ports, port_name, getattr(fsm_instance, port_name))

    # Inherit in and output ports. We do this outside of the wrapped class
    # since we cannot do setattr inside the class scope (def-use).
    for (name, type) in fsm_mod._pycde_mod.input_ports:
        setattr(fsm_hw_mod, name, Input(type))
    for (name, type) in fsm_mod._pycde_mod.output_ports:
        setattr(fsm_hw_mod, name, Output(type))

    # Add clock and additional reset port.
    setattr(fsm_hw_mod, clock, Input(types.i1))

    if reset is not None:
        setattr(fsm_hw_mod, reset, Input(types.i1))

    # The wrapper class now overloads the name of the user-defined FSM.
    # From this point on, instantiating the user FSM class will actually
    # instantiate the wrapper HW module class.
    fsm_hw_mod.__qualname__ = fsm_name
    fsm_hw_mod.__name__ = fsm_name
    fsm_hw_mod.__module__ = fsm_name
    return fsm_hw_mod
Пример #21
0
class WireNames:
    clk = Input(types.i1)
    sel = Input(types.i2)
    data_in = Input(dim(32, 3))

    a = Output(types.i32)
    b = Output(types.i32)

    @generator
    def build(ports):
        foo = ports.data_in[0]
        foo.name = "foo"
        arr_data = dim(32, 4)([1, 2, 3, 4], "arr_data")
        ports.set_all_ports({
            'a': foo.reg(ports.clk).reg(ports.clk),
            'b': arr_data[ports.sel],
        })
Пример #22
0
class M1:
    in1 = Input(types.i31)

    @generator
    def build(ports):
        m = NDArray((32, 32), dtype=types.i1, name='m1')
        # CHECK: ValueError: Width mismatch between provided BitVectorValue (i31) and target shape ([32]i1).
        m[0] = ports.in1
Пример #23
0
class TopLevel:
    x = Input(types.i32)
    y = Output(types.i32)

    @generator
    def construct(mod):
        TopLevel.part1 = DesignPartition("part1")
        Plus("Plus1", a=mod.x, b=mod.x, partition=TopLevel.part1)
        mod.y = PlusPipeline(a=mod.x).y
Пример #24
0
class ComplexPorts:
    clk = Input(types.i1)
    sel = Input(types.i2)
    data_in = Input(dim(32, 3))
    struct_data_in = Input(types.struct({"foo": types.i36}))

    a = Output(types.i32)
    b = Output(types.i32)
    c = Output(types.i32)

    @generator
    def build(ports):
        assert len(ports.data_in) == 3
        ports.set_all_ports({
            'a': ports.data_in[0].reg(ports.clk).reg(ports.clk),
            'b': ports.data_in[ports.sel],
            'c': ports.struct_data_in.foo[:-4]
        })
Пример #25
0
class PlusPipeline:
    a = Input(types.i32)
    y = Output(types.i32)

    @generator
    def construct(mod):
        p1 = Plus(a=mod.a, b=mod.a)
        p2 = Plus(a=p1.y, b=mod.a, partition=TopLevel.part1)
        p3 = Plus(a=p2.y, b=mod.a)
        mod.y = p3.y
Пример #26
0
class CompReg:
    clk = Clock()
    input = Input(types.i8)
    output = Output(types.i8)

    @generator
    def build(ports):
        with ports.clk:
            compreg = ports.input.reg(name="reg", sv_attributes=["dont_merge"])
            compreg.appid = AppID("reg", 0)
            ports.output = compreg
Пример #27
0
class ComplexMux:

  Clk = Input(dim(1))
  In = Input(dim(3, 4, 5))
  Sel = Input(dim(1))
  Out = Output(dim(3, 4))
  OutArr = Output(dim(3, 4, 2))
  OutSlice = Output(dim(3, 4, 3))
  OutInt = Output(types.i1)

  @generator
  def create(ports):
    clk = ports.Clk
    select_from = Value([ports.In[3].reg(clk).reg(clk, cycles=2), ports.In[1]])
    ports.Out = select_from[ports.Sel]

    ports.OutArr = array_from_tuple(ports.In[0], ports.In[1])
    ports.OutSlice = ports.In[0:3]

    ports.OutInt = ports.In[0][0][ports.Sel]
Пример #28
0
class MyMod:
    in_port = Input(dim(8))
    out0 = Output(dim(5))
    out1 = Output(dim(5))

    @generator
    def construct(mod):
        # Partial lower slice
        mod.out0 = mod.in_port[3:]
        # partial upper slice
        mod.out1 = mod.in_port[:5]
Пример #29
0
class M1:
    in1 = Input(types.i32)

    @generator
    def build(ports):
        m = NDArray((10), dtype=types.i32, name='m1')
        for i in range(9):
            m[i] = ports.in1
        # CHECK: ValueError: Unassigned sub-matrices:
        # CHECK: {{[[]}}{{[[]}}9{{[]]}}{{[]]}}
        m.to_circt()
Пример #30
0
class F0:
    a = Input(types.i1)
    b = Input(types.i1)
    c = Input(types.i1)

    def maj3(ports):
        def nand(*args):
            return comb.XorOp(comb.AndOp(*args), types.i1(1))

        c1 = nand(ports.a, ports.b)
        c2 = nand(ports.b, ports.c)
        c3 = nand(ports.a, ports.c)
        return nand(c1, c2, c3)

    idle = fsm.State(initial=True)
    (A, B, C) = fsm.States(3)

    idle.set_transitions((A, ))
    A.set_transitions((B, lambda ports: ports.a))
    B.set_transitions((C, maj3))
    C.set_transitions((idle, lambda ports: ports.c),
                      (A, lambda ports: comb.XorOp(ports.b, types.i1(1))))