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])
def __init__(self, node: PortNode, config_addr_width: int, config_data_width: int): if not isinstance(node, PortNode): raise ValueError(node, PortNode.__name__) super().__init__(config_addr_width, config_data_width) self.node: PortNode = node self.mux = create_mux(self.node) # lift the port to the top level self.add_ports(I=self.mux.ports.I.base_type(), O=self.mux.ports.O.base_type()) self.wire(self.ports.I, self.mux.ports.I) self.wire(self.ports.O, self.mux.ports.O) if self.mux.height > 1: self.add_ports( config=magma.In( ConfigurationType(config_addr_width, config_data_width)), read_config_data=magma.Out(magma.Bits(config_data_width)), ) config_name = get_mux_sel_name(self.node) self.add_config(config_name, self.mux.sel_bits) self.wire(self.registers[config_name].ports.O, self.mux.ports.S) self._setup_config()
def __fan_out_config(self): self.add_ports(config=magma.In( ConfigurationType(self.data_width, self.data_width)), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset)) # fan out wires for _, tile_circuit in self.tile_circuits.items(): self.wire(self.ports.config, tile_circuit.ports.config) self.wire(self.ports.reset, tile_circuit.ports.reset)
def __init__(self, num_tracks, width): super().__init__() if num_tracks <= 1: raise ValueError("num_tracks must be > 1") self.num_tracks = num_tracks self.width = width sel_bits = magma.bitutils.clog2(self.num_tracks) self.mux = MuxWrapper(self.num_tracks, self.width) T = magma.Bits(self.width) self.add_ports( I=magma.In(magma.Array(self.num_tracks, T)), O=magma.Out(T), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), config=magma.In(ConfigurationType(8, 32)), read_config_data=magma.Out(magma.Bits(32)), ) self.add_configs(S=sel_bits) # read_config_data output num_config_reg = len(self.registers) if (num_config_reg > 1): self.read_config_data_mux = MuxWrapper(num_config_reg, 32) self.wire(self.ports.config.config_addr, self.read_config_data_mux.ports.S) self.wire(self.read_config_data_mux.ports.O, self.ports.read_config_data) for idx, reg in enumerate(self.registers.values()): self.wire(reg.ports.O, self.read_config_data_mux.ports.I[idx]) # Wire up config register resets self.wire(reg.ports.reset, self.ports.reset) # If we only have 1 config register, we don't need a mux # Wire sole config register directly to read_config_data_output else: reg = list(self.registers.values())[0] zext = ZextWrapper(reg.width, 32) self.wire(reg.ports.O, zext.ports.I) zext_out = zext.ports.O self.wire(zext_out, self.ports.read_config_data) self.wire(self.ports.I, self.mux.ports.I) self.wire(self.registers.S.ports.O, self.mux.ports.S) self.wire(self.mux.ports.O, self.ports.O) for idx, reg in enumerate(self.registers.values()): reg.set_addr(idx) reg.set_addr_width(8) reg.set_data_width(32) self.wire(self.ports.config.config_addr, reg.ports.config_addr) self.wire(self.ports.config.config_data, reg.ports.config_data) # Connect config_en for each config reg self.wire(reg.ports.config_en, self.ports.config.write[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)
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)
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)
def __init__(self, switchbox: SwitchBox, config_addr_width: int, config_data_width: int): super().__init__(config_addr_width, config_data_width) self.switchbox = switchbox # lift the ports up sbs = self.switchbox.get_all_sbs() self.sb_muxs: Dict[str, Tuple[SwitchBoxNode, MuxWrapper]] = {} # first pass to create the mux circuit for sb in sbs: sb_name = str(sb) self.sb_muxs[sb_name] = (sb, create_mux(sb)) # second pass to lift the ports and wire them for sb_name, (sb, mux) in self.sb_muxs.items(): # only lift them if the ports are connect to the outside world port_name = create_name(sb_name) if sb.io == SwitchBoxIO.SB_IN: self.add_port(port_name, magma.In(mux.ports.I.base_type())) self.wire(self.ports[port_name], mux.ports.I) else: self.add_port(port_name, magma.Out(mux.ports.O.base_type())) self.wire(self.ports[port_name], mux.ports.O) # connect internal sbs self.__connect_sbs() # set up the configuration registers self.add_ports( config=magma.In( ConfigurationType(config_addr_width, config_data_width)), read_config_data=magma.Out(magma.Bits(config_data_width)), ) for _, (sb, mux) in self.sb_muxs.items(): config_name = get_mux_sel_name(sb) if mux.height > 1: assert mux.sel_bits > 0 self.add_config(config_name, mux.sel_bits) self.wire(self.registers[config_name].ports.O, mux.ports.S) self._setup_config()
def __init__(self, tiles): super().__init__() self.tiles = tiles self.height = len(tiles) self.add_ports( north=SideType(5, (1, 16)), south=SideType(5, (1, 16)), west=magma.Array(self.height, SideType(5, (1, 16))), east=magma.Array(self.height, SideType(5, (1, 16))), config=magma.In(ConfigurationType(32, 32)), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), read_config_data=magma.Out(magma.Bits(32)), column_num=magma.In(magma.Bits(8)), # TODO (alexcarsello): make number of stall domains a param stall=magma.In(magma.Bits(4))) self.wire(self.ports.north, self.tiles[0].ports.north) self.wire(self.ports.south, self.tiles[-1].ports.south) for i, tile in enumerate(self.tiles): self.wire(self.ports.west[i], tile.ports.west) self.wire(self.ports.east[i], tile.ports.east) # Wire upper 8 bits of tile ID to row number self.wire(tile.ports.tile_id[8:16], Const(magma.bits(i, 8))) # Wire lower 8 bits of tile ID to col number self.wire(tile.ports.tile_id[0:8], self.ports.column_num) for i in range(1, self.height): t0 = self.tiles[i - 1] t1 = self.tiles[i] self.wire(t1.ports.north.O, t0.ports.south.I) self.wire(t0.ports.south.O, t1.ports.north.I) # Call abstract functions # distribute global inputs to all tiles in column self.wire_global_signals() # OR-combine each tile's read_data to form column read_data self.combine_read_data_outputs()
def __init__(self): super().__init__() self.add_ports(data_in_16b=magma.In(magma.Bits(16)), data_out_16b=magma.Out(magma.Bits(16)), data_in_1b=magma.In(magma.Bits(1)), data_out_1b=magma.Out(magma.Bits(1)), clk=magma.In(magma.Clock), reset=magma.In(magma.AsyncReset), config=magma.In(ConfigurationType(8, 32)), read_config_data=magma.Out(magma.Bits(32))) # Dummy core just passes inputs through to outputs self.wire(self.ports.data_in_16b, self.ports.data_out_16b) self.wire(self.ports.data_in_1b, self.ports.data_out_1b) # Add some config registers self.add_configs(dummy_1=32, dummy_2=32) # Create mux allow for reading of config regs num_mux_inputs = len(self.registers.values()) self.read_data_mux = MuxWithDefaultWrapper(num_mux_inputs, 32, 8, 0) # Connect config_addr to mux select self.wire(self.read_data_mux.ports.S, self.ports.config.config_addr) # Connect config_read to mux enable self.wire(self.read_data_mux.ports.EN[0], self.ports.config.read[0]) self.wire(self.read_data_mux.ports.O, self.ports.read_config_data) for i, reg in enumerate(self.registers.values()): reg.set_addr(i) reg.set_addr_width(8) reg.set_data_width(32) # wire output to read_data_mux inputs self.wire(reg.ports.O, self.read_data_mux.ports.I[i]) # Wire config addr and data to each register self.wire(self.ports.config.config_addr, reg.ports.config_addr) self.wire(self.ports.config.config_data, reg.ports.config_data) # Wire config write to each reg's write port self.wire(self.ports.config.write[0], reg.ports.config_en) self.wire(self.ports.reset, reg.ports.reset)
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])
def __init__(self, inputs): super().__init__() self.all_inputs = inputs self.inputs = self.__organize_inputs(inputs) self.add_ports( north=SideType(5, (1, 16)), west=SideType(5, (1, 16)), south=SideType(5, (1, 16)), east=SideType(5, (1, 16)), 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(rsetaluri): Clean up this logic. for i, input_ in enumerate(self.all_inputs): assert input_.type().isoutput() port_name = f"{input_._name}" self.add_port(port_name, magma.In(input_.type())) sides = (self.ports.north, self.ports.west, self.ports.south, self.ports.east) self.muxs = self.__make_muxs(sides) for (side, layer, track), mux in self.muxs.items(): idx = 0 for side_in in sides: if side_in == side: continue mux_in = getattr(side_in.I, f"layer{layer}")[track] self.wire(mux_in, mux.ports.I[idx]) idx += 1 for input_ in self.inputs[layer]: port_name = input_._name self.wire(self.ports[port_name], mux.ports.I[idx]) idx += 1 buffered_mux = self.__make_register_buffer(mux) mux_out = getattr(side.O, f"layer{layer}")[track] self.wire(buffered_mux.ports.O, mux_out) # Add corresponding config register. config_name = f"mux_{side._name}_{layer}_{track}" config_name_mux = config_name + '_sel' config_name_buffer = config_name + '_buffer_sel' self.add_config(config_name_mux, mux.sel_bits) self.wire(self.registers[config_name_mux].ports.O, mux.ports.S) self.add_config(config_name_buffer, buffered_mux.sel_bits) self.wire(self.registers[config_name_buffer].ports.O, buffered_mux.ports.S) # NOTE(rsetaluri): We set the config register addresses explicitly and # in a well-defined order. This ordering can be considered a part of # the functional spec of this module. idx = 0 for side in sides: for layer in (1, 16): for track in range(5): reg_name = f"mux_{side._name}_{layer}_{track}" reg_name_mux = reg_name + '_sel' reg_name_buffer = reg_name + '_buffer_sel' self.registers[reg_name_mux].set_addr(idx) idx += 1 self.registers[reg_name_buffer].set_addr(idx) idx += 1 for idx, reg in enumerate(self.registers.values()): reg.set_addr_width(8) reg.set_data_width(32) self.wire(self.ports.config.config_addr, reg.ports.config_addr) self.wire(self.ports.config.config_data, reg.ports.config_data) self.wire(self.ports.config.write[0], reg.ports.config_en) self.wire(self.ports.reset, reg.ports.reset) # read_config_data output num_config_reg = len(self.registers) if(num_config_reg > 1): self.read_config_data_mux = MuxWrapper(num_config_reg, 32) sel_bits = self.read_config_data_mux.sel_bits # Wire up config_addr to select input of read_data MUX # TODO(rsetaluri): Make this a mux with default. self.wire(self.ports.config.config_addr[:sel_bits], self.read_config_data_mux.ports.S) self.wire(self.read_config_data_mux.ports.O, self.ports.read_config_data) for idx, reg in enumerate(self.registers.values()): zext = ZextWrapper(reg.width, 32) self.wire(reg.ports.O, zext.ports.I) zext_out = zext.ports.O self.wire(zext_out, self.read_config_data_mux.ports.I[idx]) # If we only have 1 config register, we don't need a mux # Wire sole config register directly to read_config_data_output else: self.wire(self.registers[0].ports.O, self.ports.read_config_data)
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])