def top_to_tile(top, tile, tile_idx): tile.add_ports(tile_id=magma.In(magma.Bits(16))) top.wire(Const(magma.bits(tile_idx, 16)), tile.tile_id) tile_eq = FromMagma(mantle.DefineEQ(16)) tile.wire(tile.tile_id, tile_eq.I0) tile.wire(tile.config.config_addr[0:16], tile_eq.I1) return tile_eq
def tile_to_feature(tile, tile_eq, feature, feature_idx): feature.add_ports(config_en=magma.In(magma.Bit)) feature_eq = FromMagma(mantle.DefineEQ(8)) tile.wire(tile.config.config_addr[16:24], feature_eq.I0) tile.wire(Const(magma.bits(feature_idx, 8)), feature_eq.I1) feature_en = FromMagma(mantle.DefineAnd()) tile.wire(feature_eq.O, feature_en.I0) tile.wire(tile_eq.O, feature_en.I1) tile.wire(feature_en.O, feature.config_en)
def tile_to_feature(tile, tile_eq, feature, feature_idx): feature.add_ports( config=magma.In(ConfigurationType(8, 32)), config_en=magma.In(magma.Bit), ) tile.wire(tile.config.config_addr[24:], feature.config.config_addr) tile.wire(tile.config.config_data, feature.config.config_data) feature_eq = FromMagma(mantle.DefineEQ(8)) tile.wire(tile.config.config_addr[16:24], feature_eq.I0) tile.wire(Const(magma.bits(feature_idx, 8)), feature_eq.I1) feature_en = FromMagma(mantle.DefineAnd()) tile.wire(feature_eq.O, feature_en.I0) tile.wire(tile_eq.O, feature_en.I1) tile.wire(feature_en.O, feature.config_en)
def __wire_config_ce(self): if len(self.regs) == 0: return # fanout the stall signals to registers # invert the stall signal to clk_en invert = FromMagma(mantle.DefineInvert(1)) # FIXME: use the low bits of stall signal to stall self.wire(invert.ports.I[0], self.ports.stall[0]) for (reg_node, reg) in self.regs.values(): rmux: RegisterMuxNode = list(reg_node)[0] # get rmux address config_name = get_mux_sel_name(rmux) config_reg = self.registers[config_name] index_val = rmux.get_conn_in().index(reg_node) eq_gate = FromMagma(mantle.DefineEQ(config_reg.width)) self.wire(eq_gate.ports.I0, Const(index_val)) self.wire(eq_gate.ports.I1, config_reg.ports.O) and_gate = FromMagma(mantle.DefineAnd(2, 1)) self.wire(and_gate.ports.I0[0], eq_gate.ports.O) self.wire(and_gate.ports.I1, invert.ports.O) self.wire(reg.ports.CE, self.convert(and_gate.ports.O[0], magma.enable))
def finalize(self): if self.finalized: raise Exception("Circuit already finalized") self.finalized = True # add stall and reset signal self.__add_stall() self.__add_reset() # see if we really need to add config or not if not self.__should_add_config(): return self.add_ports(config=magma.In( ConfigurationType(self.full_config_addr_width, self.config_data_width)), clk=magma.In(magma.Clock), read_config_data=magma.Out( magma.Bits[self.config_data_width])) # double buffer ports if self.double_buffer: self.add_ports(config_db=magma.In(magma.Bit), use_db=magma.In(magma.Bit)) features = self.features() num_features = len(features) self.read_data_mux = MuxWithDefaultWrapper(num_features, self.config_data_width, self.config_addr_width, 0) self.read_data_mux.instance_name = "read_data_mux" # most of the logic copied from tile_magma.py # remove all hardcoded values for feature in self.features(): if "config" not in feature.ports: continue 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) if self.double_buffer and "config_db" in feature.ports: self.wire(self.ports.config_db, feature.ports.config_db) self.wire(self.ports.use_db, feature.ports.use_db) # 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 read_and_tile = FromMagma(mantle.DefineAnd(2)) eq_tile = FromMagma(mantle.DefineEQ(self.tile_id_width)) # config_addr.tile_id == self.tile_id? self.wire(self.ports.tile_id, eq_tile.ports.I0) self.wire(self.ports.config.config_addr[self.tile_id_slice], eq_tile.ports.I1) # (config_addr.tile_id == self.tile_id) & READ self.wire(read_and_tile.ports.I0, eq_tile.ports.O) self.wire(read_and_tile.ports.I1, self.ports.config.read[0]) # read_data_mux.EN = (config_addr.tile_id == self.tile_id) & READ self.wire(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) write_and_tile = FromMagma(mantle.DefineAnd(2)) self.wire(write_and_tile.ports.I0, eq_tile.ports.O) self.wire(write_and_tile.ports.I1, self.ports.config.write[0]) decode_feat = [] feat_and_config_en_tile = [] for i, feat in enumerate(self.features()): # wire each feature's read_data output to # read_data_mux inputs if "read_config_data" in feat.ports: self.wire(feat.ports.read_config_data, self.read_data_mux.ports.I[i]) else: # wire constant self.wire(Const(0), self.read_data_mux.ports.I[i]) # for each feature, # config_en = (config_addr.feature == feature_num) & config_en_tile decode_feat.append( FromMagma(mantle.DefineDecode(i, self.config_addr_width))) decode_feat[-1].instance_name = f"DECODE_FEATURE_{i}" feat_and_config_en_tile.append(FromMagma(mantle.DefineAnd(2))) feat_and_config_en_tile[-1].instance_name = f"FEATURE_AND_{i}" self.wire(decode_feat[i].ports.I, self.ports.config.config_addr[self.feature_addr_slice]) self.wire(decode_feat[i].ports.O, feat_and_config_en_tile[i].ports.I0) self.wire(write_and_tile.ports.O, feat_and_config_en_tile[i].ports.I1) if "config" in feat.ports: self.wire(feat_and_config_en_tile[i].ports.O, feat.ports.config.write[0]) if "config_en" in feat.ports: self.wire(decode_feat[i].ports.O, feat.ports["config_en"])
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, 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])