Ejemplo n.º 1
0
    def __init__(self, data_width, data_depth):
        super().__init__()

        self.data_width = data_width
        self.data_depth = data_depth
        TData = magma.Bits(self.data_width)
        TBit = magma.Bits(1)

        self.add_ports(data_in=magma.In(TData),
                       addr_in=magma.In(TData),
                       data_out=magma.Out(TData),
                       clk=magma.In(magma.Clock),
                       config=magma.In(ConfigurationType(8, 32)),
                       read_config_data=magma.Out(magma.Bits(32)),
                       reset=magma.In(magma.AsyncReset),
                       flush=magma.In(TBit),
                       wen_in=magma.In(TBit),
                       ren_in=magma.In(TBit),
                       stall=magma.In(magma.Bits(4)))

        wrapper = memory_core_genesis2.memory_core_wrapper
        param_mapping = memory_core_genesis2.param_mapping
        generator = wrapper.generator(param_mapping, mode="declare")
        circ = generator(data_width=self.data_width,
                         data_depth=self.data_depth)
        self.underlying = FromMagma(circ)

        self.wire(self.ports.data_in, self.underlying.ports.data_in)
        self.wire(self.ports.addr_in, self.underlying.ports.addr_in)
        self.wire(self.ports.data_out, self.underlying.ports.data_out)
        self.wire(self.ports.config.config_addr,
                  self.underlying.ports.config_addr[24:32])
        self.wire(self.ports.config.config_data,
                  self.underlying.ports.config_data)
        self.wire(self.ports.config.write[0], self.underlying.ports.config_en)
        self.wire(self.underlying.ports.read_data, self.ports.read_config_data)
        self.wire(self.ports.reset, self.underlying.ports.reset)
        self.wire(self.ports.flush[0], self.underlying.ports.flush)
        self.wire(self.ports.wen_in[0], self.underlying.ports.wen_in)
        self.wire(self.ports.ren_in[0], self.underlying.ports.ren_in)

        # PE core uses clk_en (essentially active low stall)
        self.stallInverter = FromMagma(mantle.DefineInvert(1))
        self.wire(self.stallInverter.ports.I, self.ports.stall[0:1])
        self.wire(self.stallInverter.ports.O[0], self.underlying.ports.clk_en)

        # TODO(rsetaluri): Actually wire these inputs.
        signals = (
            ("config_en_sram", 4),
            ("config_en_linebuf", 1),
            ("chain_wen_in", 1),
            ("config_read", 1),
            ("config_write", 1),
            ("chain_in", self.data_width),
        )
        for name, width in signals:
            val = magma.bits(0, width) if width > 1 else magma.bit(0)
            self.wire(Const(val), self.underlying.ports[name])
        self.wire(Const(magma.bits(0, 24)),
                  self.underlying.ports.config_addr[0:24])
Ejemplo n.º 2
0
    def __init__(self, num_inputs, width, sel_bits, default):
        super().__init__()

        self.num_inputs = num_inputs
        self.width = width
        self.sel_bits = sel_bits
        self.default = default

        if 2**self.sel_bits <= self.num_inputs:
            raise ValueError(f"(2 ^ sel_bits) must be > num_inputs "
                             f"(sel_bits={self.sel_bits}, "
                             f"num_inputs={self.num_inputs})")

        self.data_mux = MuxWrapper(self.num_inputs, self.width)
        self.default_mux = MuxWrapper(2, self.width)
        lt = mantle.DefineULT(self.sel_bits)
        and_gate = mantle.DefineAnd(2)
        self.lt = FromMagma(lt)
        self.and_gate = FromMagma(and_gate)

        T = magma.Bits(self.width)
        self.add_ports(
            I=magma.In(magma.Array(self.num_inputs, T)),
            S=magma.In(magma.Bits(self.sel_bits)),
            EN=magma.In(magma.Bits(1)),
            O=magma.Out(T),
        )

        # Wire data inputs to data mux.
        for i in range(self.num_inputs):
            self.wire(self.ports.I[i], self.data_mux.ports.I[i])

        # Wire select input to select input of data_mux. Note that we only wire
        # the first clog2(num_inputs) bits of the select input.
        self.wire(self.ports.S[:self.data_mux.sel_bits], self.data_mux.ports.S)

        # Wire default value to first input of default mux, and output of
        # data_mux to second input of default mux.
        default_mux_inputs = [
            Const(magma.bits(self.default, self.width)),
            self.data_mux.ports.O,
        ]
        for i, mux_in in enumerate(default_mux_inputs):
            self.wire(mux_in, self.default_mux.ports.I[i])

        # Generate select logic for default mux:
        #   sel = (S < num_inputs) & EN
        self.wire(self.ports.S, self.lt.ports.I0)
        self.wire(Const(magma.bits(self.num_inputs, self.sel_bits)),
                  self.lt.ports.I1)
        self.wire(self.lt.ports.O, self.and_gate.ports.I0)
        self.wire(self.ports.EN[0], self.and_gate.ports.I1)
        self.wire(self.and_gate.ports.O, self.default_mux.ports.S[0])
        self.wire(self.default_mux.ports.O, self.ports.O)
Ejemplo n.º 3
0
    def __init__(self):
        super().__init__()

        # TODO(rsetaluri): Currently we assume the default parameters into the
        # wrapper. Ideally we should take some arguments into this generator
        # and pass them to the genesis wrapper.
        wrapper = pe_core_genesis2.pe_core_wrapper
        generator = wrapper.generator(mode="declare")
        circ = generator()
        self.underlying = FromMagma(circ)

        TData = magma.Bits(16)
        TBit = magma.Bits(1)
        TFlag = magma.Bits(4)

        self.add_ports(
            data0=magma.In(TData),
            data1=magma.In(TData),
            bit0=magma.In(TBit),
            bit1=magma.In(TBit),
            bit2=magma.In(TBit),
            res=magma.Out(TData),
            res_p=magma.Out(TFlag),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            config=magma.In(ConfigurationType(8, 32)),
            read_config_data=magma.Out(magma.Bits(32)),
            # TODO: Make number of stall domains paramaterizable
            stall=magma.In(magma.Bits(4))
        )

        self.wire(self.ports.data0, self.underlying.ports.data0)
        self.wire(self.ports.data1, self.underlying.ports.data1)
        self.wire(self.ports.bit0[0], self.underlying.ports.bit0)
        self.wire(self.ports.bit1[0], self.underlying.ports.bit1)
        self.wire(self.ports.bit2[0], self.underlying.ports.bit2)
        self.wire(self.ports.res, self.underlying.ports.res)
        self.wire(self.ports.res_p, self.underlying.ports.res_p)
        self.wire(self.ports.config.config_addr, self.underlying.ports.cfg_a)
        self.wire(self.ports.config.config_data,
                  self.underlying.ports.cfg_d)
        self.wire(self.ports.config.write[0], self.underlying.ports.cfg_en)
        self.wire(self.underlying.ports.read_data, self.ports.read_config_data)

        # TODO: Make PE core use active high reset
        self.wire(self.ports.reset, self.underlying.ports.rst_n)

        # PE core uses clk_en (essentially active low stall)
        self.stallInverter = FromMagma(mantle.DefineInvert(1))
        self.wire(self.stallInverter.ports.I, self.ports.stall[0:1])
        self.wire(self.stallInverter.ports.O[0], self.underlying.ports.clk_en)
Ejemplo n.º 4
0
    def __init__(self, height, width):
        super().__init__()

        self.height = height
        self.width = width

        T = magma.Bits(self.width)

        # In the case that @height <= 1, we make this circuit a simple
        # pass-through circuit.
        if self.height <= 1:
            self.add_ports(
                I=magma.In(magma.Array(1, T)),
                O=magma.Out(T),
            )
            self.wire(self.ports.I[0], self.ports.O)
            self.sel_bits = 0
            return

        MuxCls = mantle.DefineMux(self.height, self.width)
        self.mux = FromMagma(MuxCls)

        self.sel_bits = magma.bitutils.clog2(self.height)

        self.add_ports(
            I=magma.In(magma.Array(self.height, T)),
            S=magma.In(magma.Bits(self.sel_bits)),
            O=magma.Out(T),
        )

        for i in range(self.height):
            self.wire(self.ports.I[i], self.mux.ports[f"I{i}"])
        mux_in = self.ports.S if self.sel_bits > 1 else self.ports.S[0]
        self.wire(mux_in, self.mux.ports.S)
        self.wire(self.mux.ports.O, self.ports.O)
Ejemplo n.º 5
0
    def __make_register_buffer(self, unbuffered_mux):
        signal_in = unbuffered_mux.ports.O
        width = get_width(signal_in.type())

        # register = Register(width)
        RegisterCls = DefineRegister(width)
        register = FromMagma(RegisterCls)

        mux = MuxWrapper(2, width)
        self.wire(signal_in, mux.ports.I[0])
        self.wire(signal_in, register.ports.I)
        self.wire(register.ports.O, mux.ports.I[1])
        return mux
Ejemplo n.º 6
0
 def read_data_reduction(self):
     pass_through = self.ports.read_config_data
     input_name = pass_through.qualified_name() + "_in"
     # Create input port for pass through read_data reduction
     self.add_port(input_name, magma.In(pass_through.base_type()))
     # Remove the current connection to the read_data output
     self.remove_wire(self.read_data_mux.ports.O, pass_through)
     self.read_data_reduce_or = FromMagma(mantle.DefineOr(2, 32))
     # OR previous read_data output with read_data input to create NEW
     # read_data output
     self.wire(self.read_data_mux.ports.O,
               self.read_data_reduce_or.ports.I0)
     self.wire(self.ports[input_name], self.read_data_reduce_or.ports.I1)
     self.wire(self.read_data_reduce_or.ports.O, pass_through)
Ejemplo n.º 7
0
    def __init__(self, columns):
        super().__init__()

        assert all([c.height == columns[0].height for c in columns])
        self.width = len(columns)
        self.height = columns[0].height
        self.columns = columns
        self.side_type = SideType(5, (1, 16))

        self.add_ports(
            north=magma.Array(self.width, self.side_type),
            south=magma.Array(self.width, self.side_type),
            west=magma.Array(self.height, self.side_type),
            east=magma.Array(self.height, self.side_type),
            config=magma.In(ConfigurationType(32, 32)),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            read_config_data=magma.Out(magma.Bits(32)),
            # TODO: make number of stall domains a param
            stall=magma.In(magma.Bits(4)))

        for column in self.columns:
            self.wire(self.ports.config, column.ports.config)
            self.wire(self.ports.reset, column.ports.reset)
            self.wire(self.ports.stall, column.ports.stall)
        self.wire(self.ports.west, self.columns[0].ports.west)
        self.wire(self.ports.east, self.columns[-1].ports.east)
        for i, column in enumerate(self.columns):
            self.wire(self.ports.north[i], column.ports.north)
            self.wire(self.ports.south[i], column.ports.south)
        for i in range(1, self.width):
            c0 = self.columns[i - 1]
            c1 = self.columns[i]
            for j in range(self.height):
                self.wire(c1.ports.west[j].O, c0.ports.east[j].I)
                self.wire(c0.ports.east[j].O, c1.ports.west[j].I)

        # OR together read_data outputs from each column
        # number of inputs = number of columns
        self.read_data_OR = FromMagma(mantle.DefineOr(len(self.columns), 32))
        for i, col in enumerate(columns):
            self.wire(self.read_data_OR.ports[f"I{i}"],
                      col.ports.read_config_data)
            # wire up column number input
            self.wire(col.ports.column_num, Const(magma.bits(i, 8)))
        self.wire(self.read_data_OR.ports.O, self.ports.read_config_data)
Ejemplo n.º 8
0
    def __init__(self, addr_width, data_width):
        super().__init__()
        super().__init__()

        self.addr_width = addr_width
        self.data_width = data_width
        self.config_type = ConfigurationType(self.addr_width, self.data_width)

        self.add_ports(
            jtag=JTAGType,
            config=magma.Out(self.config_type),
            read_data_in=magma.In(magma.Bits(self.data_width)),
            clk_in=magma.In(magma.Clock),
            reset_in=magma.In(magma.AsyncReset),
            clk_out=magma.Out(magma.Clock),
            reset_out=magma.Out(magma.AsyncReset),
            # TODO: make number of stall domains a param
            stall=magma.Out(magma.Bits(4))
        )

        wrapper = global_controller_genesis2.gc_wrapper
        generator = wrapper.generator(mode="declare")
        self.underlying = FromMagma(generator())

        self.wire(self.ports.jtag.tdi, self.underlying.ports.tdi)
        self.wire(self.ports.jtag.tdo, self.underlying.ports.tdo)
        self.wire(self.ports.jtag.tms, self.underlying.ports.tms)
        self.wire(self.ports.jtag.tck, self.underlying.ports.tck)
        self.wire(self.ports.jtag.trst_n, self.underlying.ports.trst_n)
        self.wire(self.ports.clk_in, self.underlying.ports.clk_in)
        self.wire(self.ports.reset_in, self.underlying.ports.reset_in)

        self.wire(self.underlying.ports.config_addr_out,
                  self.ports.config.config_addr)
        self.wire(self.underlying.ports.config_data_out,
                  self.ports.config.config_data)
        self.wire(self.underlying.ports.read, self.ports.config.read[0])
        self.wire(self.underlying.ports.write, self.ports.config.write[0])
        self.wire(self.underlying.ports.clk_out, self.ports.clk_out)
        self.wire(self.underlying.ports.reset_out, self.ports.reset_out)
        self.wire(self.underlying.ports.cgra_stalled, self.ports.stall)

        self.wire(self.ports.read_data_in, self.underlying.ports.config_data_in)
Ejemplo n.º 9
0
    def __add_config(self):
        self.add_ports(config=magma.In(
            ConfigurationType(self.config_data_width, self.config_data_width)),
                       tile_id=magma.In(magma.Bits(self.tile_id_width)),
                       clk=magma.In(magma.Clock),
                       reset=magma.In(magma.AsyncReset),
                       read_config_data=magma.Out(
                           magma.Bits(self.config_data_width)))

        features = self.features()
        num_features = len(features)
        self.read_data_mux = MuxWithDefaultWrapper(num_features,
                                                   self.config_data_width,
                                                   self.config_addr_width, 0)
        # most of the logic copied from tile_magma.py
        # remove all hardcoded values
        for feature in self.features():
            self.wire(self.ports.config.config_addr[self.feature_config_slice],
                      feature.ports.config.config_addr)
            self.wire(self.ports.config.config_data,
                      feature.ports.config.config_data)
            self.wire(self.ports.config.read, feature.ports.config.read)

        # Connect S input to config_addr.feature.
        self.wire(self.ports.config.config_addr[self.feature_addr_slice],
                  self.read_data_mux.ports.S)
        self.wire(self.read_data_mux.ports.O, self.ports.read_config_data)

        # Logic to generate EN input for read_data_mux
        self.read_and_tile = FromMagma(mantle.DefineAnd(2))
        self.eq_tile = FromMagma(mantle.DefineEQ(self.tile_id_width))
        # config_addr.tile_id == self.tile_id?
        self.wire(self.ports.tile_id, self.eq_tile.ports.I0)
        self.wire(self.ports.config.config_addr[self.tile_id_slice],
                  self.eq_tile.ports.I1)
        # (config_addr.tile_id == self.tile_id) & READ
        self.wire(self.read_and_tile.ports.I0, self.eq_tile.ports.O)
        self.wire(self.read_and_tile.ports.I1, self.ports.config.read[0])
        # read_data_mux.EN = (config_addr.tile_id == self.tile_id) & READ
        self.wire(self.read_and_tile.ports.O, self.read_data_mux.ports.EN[0])

        # Logic for writing to config registers
        # Config_en_tile = (config_addr.tile_id == self.tile_id & WRITE)
        self.write_and_tile = FromMagma(mantle.DefineAnd(2))
        self.wire(self.write_and_tile.ports.I0, self.eq_tile.ports.O)
        self.wire(self.write_and_tile.ports.I1, self.ports.config.write[0])
        self.decode_feat = []
        self.feat_and_config_en_tile = []
        for i, feat in enumerate(self.features()):
            # wire each feature's read_data output to
            # read_data_mux inputs
            self.wire(feat.ports.read_config_data,
                      self.read_data_mux.ports.I[i])
            # for each feature,
            # config_en = (config_addr.feature == feature_num) & config_en_tile
            self.decode_feat.append(
                FromMagma(mantle.DefineDecode(i, self.config_addr_width)))
            self.feat_and_config_en_tile.append(FromMagma(mantle.DefineAnd(2)))
            self.wire(self.decode_feat[i].ports.I,
                      self.ports.config.config_addr[self.feature_addr_slice])
            self.wire(self.decode_feat[i].ports.O,
                      self.feat_and_config_en_tile[i].ports.I0)
            self.wire(self.write_and_tile.ports.O,
                      self.feat_and_config_en_tile[i].ports.I1)
            self.wire(self.feat_and_config_en_tile[i].ports.O,
                      feat.ports.config.write[0])
Ejemplo n.º 10
0
 def combine_read_data_outputs(self):
     self.read_data_OR = FromMagma(mantle.DefineOr(self.height, 32))
     self.wire(self.read_data_OR.ports.O, self.ports.read_config_data)
     for i, tile in enumerate(self.tiles):
         self.wire(tile.ports.read_config_data,
                   self.read_data_OR.ports[f"I{i}"])
Ejemplo n.º 11
0
    def __init__(self, core):
        super().__init__()

        self.core = core
        self.sb = SB(self.core.outputs())
        widths = [get_width(i.type()) for i in self.core.inputs()]
        self.cbs = [CB(10, w) for w in widths]

        self.add_ports(
            north=SideType(5, (1, 16)),
            west=SideType(5, (1, 16)),
            south=SideType(5, (1, 16)),
            east=SideType(5, (1, 16)),
            config=magma.In(ConfigurationType(32, 32)),
            tile_id=magma.In(magma.Bits(16)),
            clk=magma.In(magma.Clock),
            reset=magma.In(magma.AsyncReset),
            read_config_data=magma.Out(magma.Bits(32)),
            stall=magma.In(magma.Bits(4))
        )

        self.wire(self.ports.north, self.sb.ports.north)
        self.wire(self.ports.west, self.sb.ports.west)
        self.wire(self.ports.south, self.sb.ports.south)
        self.wire(self.ports.east, self.sb.ports.east)

        # this is hacky, but connect stall if the core has a stall input
        if "stall" in self.core.ports:
            self.wire(self.ports.stall, core.ports.stall)

        sides = (self.ports.north, self.ports.west)
        for i, cb in enumerate(self.cbs):
            side = sides[i % len(sides)]
            self.__wire_cb(side, cb)

        for i, input_ in enumerate(self.core.inputs()):
            self.wire(self.cbs[i].ports.O, input_)

        for i, out in enumerate(self.core.outputs()):
            self.wire(out, self.sb.ports[out._name])

        for feature in self.features():
            self.wire(self.ports.config.config_addr[24:32],
                      feature.ports.config.config_addr)
            self.wire(self.ports.config.config_data,
                      feature.ports.config.config_data)
            self.wire(self.ports.config.read, feature.ports.config.read)

        # read_data mux
        num_mux_inputs = len(self.features())
        self.read_data_mux = MuxWithDefaultWrapper(num_mux_inputs, 32, 8, 0)

        # Connect S input to config_addr.feature.
        self.wire(self.ports.config.config_addr[16:24],
                  self.read_data_mux.ports.S)
        self.wire(self.read_data_mux.ports.O, self.ports.read_config_data)

        # Logic to generate EN input for read_data_mux
        self.read_and_tile = FromMagma(mantle.DefineAnd(2))
        self.eq_tile = FromMagma(mantle.DefineEQ(16))
        # config_addr.tile_id == self.tile_id?
        self.wire(self.ports.tile_id, self.eq_tile.ports.I0)
        self.wire(self.ports.config.config_addr[0:16], self.eq_tile.ports.I1)
        # (config_addr.tile_id == self.tile_id) & READ
        self.wire(self.read_and_tile.ports.I0, self.eq_tile.ports.O)
        self.wire(self.read_and_tile.ports.I1, self.ports.config.read[0])
        # read_data_mux.EN = (config_addr.tile_id == self.tile_id) & READ
        self.wire(self.read_and_tile.ports.O, self.read_data_mux.ports.EN[0])

        # Logic for writing to config registers
        # Config_en_tile = (config_addr.tile_id == self.tile_id & WRITE)
        self.write_and_tile = FromMagma(mantle.DefineAnd(2))
        self.wire(self.write_and_tile.ports.I0, self.eq_tile.ports.O)
        self.wire(self.write_and_tile.ports.I1, self.ports.config.write[0])
        self.decode_feat = []
        self.feat_and_config_en_tile = []
        for i, feat in enumerate(self.features()):
            # wire each feature's read_data output to
            # read_data_mux inputs
            self.wire(feat.ports.read_config_data,
                      self.read_data_mux.ports.I[i])
            # for each feature,
            # config_en = (config_addr.feature == feature_num) & config_en_tile
            self.decode_feat.append(FromMagma(mantle.DefineDecode(i, 8)))
            self.feat_and_config_en_tile.append(FromMagma(mantle.DefineAnd(2)))
            self.wire(self.decode_feat[i].ports.I,
                      self.ports.config.config_addr[16:24])
            self.wire(self.decode_feat[i].ports.O,
                      self.feat_and_config_en_tile[i].ports.I0)
            self.wire(self.write_and_tile.ports.O,
                      self.feat_and_config_en_tile[i].ports.I1)
            self.wire(self.feat_and_config_en_tile[i].ports.O,
                      feat.ports.config.write[0])