def _mkFieldInterface(self, structIntf, field): t = field.dtype if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): if self.shouldEnterFn(field): if isinstance(t.elmType, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.elmType.bit_length() else: p = HObjList([ StructIntf(t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size)) ]) return p else: p = BramPort_withoutClk() dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(int(t.size) - 1)) else: raise NotImplementedError(t) p.DATA_WIDTH.set(dw) return p
def _impl(self): propagateClkRstn(self) addr_crossbar = self.addr_crossbar data_crossbar = self.data_crossbar master_addr_channels = HObjList([m.ar for m in self.s]) slave_addr_channels = HObjList([s.ar for s in self.m]) addr_crossbar.s(master_addr_channels) slave_addr_channels(addr_crossbar.m) master_r_channels = HObjList([m.r for m in self.s]) master_r_channels(data_crossbar.dataOut) slave_r_channels = HObjList([s.r for s in self.m]) data_crossbar.dataIn(slave_r_channels) for m_i, f in enumerate(self.order_s_index_for_m_data): if f is None: continue f.dataIn(addr_crossbar.order_s_index_for_m_data_out[m_i]) data_crossbar.order_din_index_for_dout_in[m_i](f.dataOut) for s_i, f in enumerate(self.order_m_index_for_s_data): if f is None: continue f.dataIn(addr_crossbar.order_m_index_for_s_data_out[s_i]) data_crossbar.order_dout_index_for_din_in[s_i](f.dataOut)
def _mkFieldInterface(self, structIntf: HStruct, field: HStructField): t = field.dtype if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): field_path = structIntf._field_path / field.name if self.shouldEnterFn(field_path)[0]: if isinstance(t.element_t, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.element_t.bit_length() else: p = HObjList([StructIntf( t.element_t, field_path, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size))]) return p else: p = BramPort_withoutClk() dw = t.element_t.bit_length() p.ADDR_WIDTH = log2ceil(int(t.size) - 1) else: raise NotImplementedError(t) p.DATA_WIDTH = dw return p
def _declr(self): HandshakeSync._declr(self) args = HObjList() for a in self._exception.hw_args: _a = monitor_of(a) args.append(_a) self.args = args
def _declr(self): w = self.DATA_WIDTH sig = bool(self.SIGNED) self.inputs = HObjList( VectSignal(w, sig) for _ in range(int(self.ITEMS))) self.outputs = HObjList( VectSignal(w, sig)._m() for _ in range(int(self.ITEMS)))
def _declr(self): addClkRstn(self) self.a = HObjList( StructIntf(struct0, instantiateFieldFn=self._mkFieldInterface) for _ in range(3)) self.b = HObjList( StructIntf(struct0, instantiateFieldFn=self._mkFieldInterface) for _ in range(3))._m()
def _declr(self): addClkRstn(self) LEN = 2 with self._paramsShared(): self.a = HObjList(AxiStream() for _ in range(LEN)) self.b = HObjList(AxiStream() for _ in range(LEN))._m() self.u0 = SimpleSubunit() self.u1 = SimpleSubunit()
def _registerArray(self, name, items: HObjList): """ Register array of items on interface level object """ items._parent = self items._name = name items._on_append = self._registerArray_append for i, item in enumerate(items): self._registerArray_append(items, item, i)
def _declr(self): LEN = 2 addClkRstn(self) with self._paramsShared(): self.a = HObjList(VldSynced() for _ in range(LEN)) self.b = HObjList(VldSynced() for _ in range(LEN))._m() self.u0 = SimpleSubunit() self.u1 = SimpleSubunit()
def _mkFieldInterface(self, structIntf, field): """ Instantiate field interface for fields in structure template of this endpoint :return: interface for specified field """ t = field.dtype DW = int(self.DATA_WIDTH) shouldEnter, shouldUse = self.shouldEnterFn(field) if shouldUse: if isinstance(t, Bits): p = RegCntrl() dw = t.bit_length() elif isinstance(t, HArray): p = BramPort_withoutClk() assert isinstance(t.elmType, Bits), t.elmType dw = t.elmType.bit_length() p.ADDR_WIDTH.set(log2ceil(t.size - 1)) else: raise NotImplementedError(t) elif shouldEnter: if isinstance(t, HArray): if isinstance(t.elmType, Bits): p = HObjList(RegCntrl() for _ in range(int(t.size))) dw = t.elmType.bit_length() else: return HObjList( StructIntf(t.elmType, instantiateFieldFn=self._mkFieldInterface) for _ in range(int(t.size))) elif isinstance(t, HStruct): return StructIntf(t, instantiateFieldFn=self._mkFieldInterface) else: raise TypeError(t) if isinstance(p, HObjList): _p = p else: _p = [p] if dw == DW: # use param instead of value to improve readability DW = self.DATA_WIDTH if isinstance(DW, Param): for i in _p: i._replaceParam(i.DATA_WIDTH, DW) else: for i in _p: i.DATA_WIDTH.set(dw) return p
def _declr(self) -> None: self._normalize_config() addClkRstn(self) slavePorts = HObjList() for _ in self.MASTERS: s = Mi32() s._updateParamsFrom(self) slavePorts.append(s) self.s = slavePorts masterPorts = HObjList() for _, size in self.SLAVES: m = Mi32()._m() m.ADDR_WIDTH = log2ceil(size - 1) m.DATA_WIDTH = self.DATA_WIDTH masterPorts.append(m) self.m = masterPorts # fifo which keeps index of slave for master read transaction # so the interconnect can delivery the read data to master # which asked for it f = self.r_data_order = HandshakedFifo(Handshaked) f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.SLAVES))
def _mkFieldInterface(self, structIntf: StructIntf, field: HStructField): """ Instantiate field interface for fields in structure template of this endpoint :return: interface for specified field """ t = field.dtype path = structIntf._field_path / field.name shouldEnter, shouldUse = self.shouldEnterFn(self.STRUCT_TEMPLATE, path) if shouldUse: if isinstance(t, Bits): p = BusEndpoint.intf_for_Bits(t) elif isinstance(t, HArray): p = BramPort_withoutClk() assert isinstance(t.element_t, Bits), t.element_t p.DATA_WIDTH = t.element_t.bit_length() p.ADDR_WIDTH = log2ceil(t.size - 1) else: raise NotImplementedError(t) elif shouldEnter: if isinstance(t, HArray): e_t = t.element_t if isinstance(e_t, Bits): p = HObjList() for i_i in range(int(t.size)): i = BusEndpoint.intf_for_Bits(e_t) structIntf._fieldsToInterfaces[path / i_i] = i p.append(i) elif isinstance(e_t, HStruct): p = HObjList( StructIntf(t.element_t, path / i, instantiateFieldFn=self._mkFieldInterface) for i in range(int(t.size))) for i in p: i._fieldsToInterfaces = structIntf._fieldsToInterfaces else: raise NotImplementedError() elif isinstance(t, HStruct): p = StructIntf(t, path, instantiateFieldFn=self._mkFieldInterface) p._fieldsToInterfaces = structIntf._fieldsToInterfaces else: raise TypeError(t) return p
def _declr_match_io(self): if self.MATCH_PORT_CNT is None: # single port version Cam._declr_match_io(self) else: # muliport version self.match = HObjList( [Handshaked() for _ in range(self.MATCH_PORT_CNT)]) for m in self.match: m.DATA_WIDTH = self.KEY_WIDTH self.out = HObjList( [Handshaked()._m() for _ in range(self.MATCH_PORT_CNT)]) for o in self.out: o.DATA_WIDTH = self.ITEMS
def _declr(self, has_r=True, has_w=True): addClkRstn(self) AXI = self.intfCls with self._paramsShared(): self.s = HObjList([AXI() for _ in self.MASTERS]) with self._paramsShared(exclude=({}, {"ADDR_WIDTH"})): self.m = HObjList([AXI()._m() for _ in self.SLAVES]) for i in chain(self.m, self.s): i.HAS_W = has_w i.HAS_R = has_r for s, (_, size) in zip(self.m, self.SLAVES): s.ADDR_WIDTH = log2ceil(size - 1)
def _declr(self): assert self.USE_KEEP addClkRstn(self) with self._paramsShared(): self.dataIn = AxiStream() self.regs = HObjList(UnalignedJoinRegIntf()._m() for _ in range(self.REG_CNT)) self.keep_masks = HObjList( VectSignal(self.DATA_WIDTH // 8) for _ in range(self.REG_CNT)) # used to shift whole register pipeline using input keep_mask self.ready = Signal() if self.ID_WIDTH or self.USER_WIDTH or self.DEST_WIDTH: raise NotImplementedError("It is not clear how id/user/dest" " should be managed between the frames")
def _declr_children(self): # for the case where this memory will be relized using multiple memory blocks children = HObjList() MAX_DW = self.MAX_BLOCK_DATA_WIDTH if MAX_DW is not None and MAX_DW < self.DATA_WIDTH: DW = self.DATA_WIDTH while DW > 0: c = self.__class__() c._updateParamsFrom(self, exclude=({"DATA_WIDTH"}, {})) c.DATA_WIDTH = min(DW, MAX_DW) if self.INIT_DATA is not None: raise NotImplementedError() children.append(c) DW -= MAX_DW self.children = children
def _declr(self): self._compute_constants() addClkRstn(self) # used to initialize the LRU data (in the case of cache reset) # while set port is active all other ports are blocked s = self.set = AddrDataHs() s.ADDR_WIDTH = self.INDEX_W s.DATA_WIDTH = self.LRU_WIDTH # used to increment the LRU data in the case of hit self.incr = HObjList(IndexWayHs() for _ in range(self.INCR_PORT_CNT)) for i in self.incr: i.INDEX_WIDTH = self.INDEX_W i.WAY_CNT = self.WAY_CNT # get a victim for a selected cacheline index # The cacheline returned as a victim is also marked as used just now vr = self.victim_req = AddrHs() vr.ADDR_WIDTH = self.INDEX_W vr.ID_WIDTH = 0 vd = self.victim_data = Handshaked()._m() vd.DATA_WIDTH = log2ceil(self.WAY_CNT - 1) m = self.lru_mem = RamXorSingleClock() m.ADDR_WIDTH = self.INDEX_W m.DATA_WIDTH = self.LRU_WIDTH m.PORT_CNT = ( # victim_req preload, victim_req write back or set, READ, WRITE, # incr preload, incr write back... *flatten((READ, WRITE) for _ in range(self.INCR_PORT_CNT)) )
def _declr(self): addClkRstn(self) with self._paramsShared(): self.a = HObjList(VldSynced() for _ in range(self.LEN)) self.b0 = VldSynced()._m() self.b1 = VldSynced()._m() self.b2 = VldSynced()._m()
def _declr(self): addClkRstn(self) with self._paramsShared(): self.a0 = VldSynced() self.a1 = VldSynced() self.a2 = VldSynced() self.b = HObjList(VldSynced() for _ in range(int(self.LEN)))._m()
def _declr(self): addClkRstn(self) self.input = VectSignal(self.DATAIN_WIDTH, signed=True) self.output = VectSignal(self.DATAIN_WIDTH, signed=True)._m() self.target = VectSignal(self.DATAIN_WIDTH, signed=True) self.coefs = HObjList( VectSignal(self.COEF_WIDTH, signed=True) for _ in range(4))
def _declr(self): self.clk = Signal() self.rst = Signal() self.en_mult = Signal() self.en_sum = Signal() self.input = VectSignal(self.width * self.size) self.output = VectSignal(self.width, signed=True)._m() for i in range(self.size): setattr(self, f"kernel_{i}", VectSignal(self.width)) self.multiplier = HObjList( FixedPointMultiplier( width=self.width, layer_id=self.layer_id, unit_id=self.unit_id, channel_id=self.channel_id, process_id=self.process_id, pixel_id=i, log_level=self.log_level + 1, ) for i in range(self.size)) name = f"ConvUnitL{self.layer_id}" self._name = name self._hdl_module_name = name
def _impl(self) -> None: regs = self.regs = HObjList( HandshakedReg(HandshakeSync) for _ in range(2)) regs[0].dataIn(self.dataIn) regs[1].dataIn(regs[0].dataOut) self.dataOut(regs[1].dataOut) propagateClkRstn(self)
def _declr(self): self.ci = Signal() self.a = VectSignal(self.p_wordlength) self.b = VectSignal(self.p_wordlength) self.s = VectSignal(self.p_wordlength)._m() self.co = Signal()._m() self.fa = HObjList([FullAdder() for _ in range(self.p_wordlength)])
def _declr(self): addClkRstn(self) with self._paramsShared(): self.s = self._bus_cls() # declare an interface with same signals but all inputs for each # monitored interface self.monitor = HObjList( [monitor_of(intf) for (intf, _, _, _, _) in self.monitored_data]) self.io_instantiated = True
def parseTemplate(self): t = self._structT try: t.bit_length() is_const_size_frame = True except TypeError: is_const_size_frame = False if is_const_size_frame: self.sub_t = [] self.children = [] super(AxiS_frameParser, self).parseTemplate() else: if self._tmpl or self._frames: raise NotImplementedError() children = HObjList() self.sub_t = sub_t = [] is_const_sized = self.sub_t_is_const_sized = [] is_padding = self.sub_t_is_padding = [] separated = list(HdlType_separate(t, is_non_const_stream)) if len(separated) > 1 or separated[0][0]: # it may be required to delegate this on children first = True for is_non_const_sized, s_t in separated: _is_padding = is_only_padding(s_t) if is_non_const_sized or (not first and _is_padding): c = None else: c = self.__class__(s_t) sub_t.append(s_t) children.append(c) first = False is_padding.append(_is_padding) is_const_sized.append(not is_non_const_sized) if len(is_const_sized) >= 2 and \ is_const_sized[0] and\ not is_const_sized[1]: # we will parse const-size prefix and # then there will be a variable size suffix children[0].OVERFLOW_SUPPORT = True with self._paramsShared(exclude=({"OVERFLOW_SUPPORT", "T"}, {})): self.children = children
def _declr(self): BusInterconnect._normalize_config(self) self.connection_groups_r = BusInterconnectUtils._extract_separable_groups( self.MASTERS, self.SLAVES, READ) self.connection_groups_w = BusInterconnectUtils._extract_separable_groups( self.MASTERS, self.SLAVES, WRITE) super(AxiInterconnectMatrix, self)._declr() # instantiate sub interconnects for each independent master-slave connection # subgraph (r, w separately) self.sub_interconnect_connections = [] r_interconnects = HObjList() masters_with_read_ch = set() slaves_with_read_ch = set() for r_group in self.connection_groups_r: master_indexes, slave_indexes = r_group masters_with_read_ch.update(master_indexes) slaves_with_read_ch.update(slave_indexes) inter = AxiInterconnectMatrixR(self.intfCls) con = self.configure_sub_interconnect(master_indexes, slave_indexes, inter) r_interconnects.append(inter) self.sub_interconnect_connections.extend(con) masters_with_write_ch = set() slaves_with_write_ch = set() w_interconnects = HObjList() for w_group in self.connection_groups_w: master_indexes, slave_indexes = w_group masters_with_write_ch.update(master_indexes) slaves_with_write_ch.update(slave_indexes) inter = AxiInterconnectMatrixW(self.intfCls) con = self.configure_sub_interconnect(master_indexes, slave_indexes, inter) w_interconnects.append(inter) self.sub_interconnect_connections.extend(con) with self._paramsShared(exclude=({"SLAVES", "MASTERS"}, set())): self.r_interconnects = r_interconnects self.w_interconnects = w_interconnects # dissable read/write unused channels on master/slave interfaces for m_i, m in enumerate(self.s): m.HAS_R = m_i in masters_with_read_ch m.HAS_W = m_i in masters_with_write_ch assert m.HAS_R or m.HAS_W, m_i for s_i, s in enumerate(self.m): s.HAS_R = s_i in slaves_with_read_ch s.HAS_W = s_i in slaves_with_write_ch assert s.HAS_R or s.HAS_W, s_i
def _declr(self): addClkRstn(self) with self._paramsShared(): self.dp = Axi_wDatapump(axiAddrCls=Axi3_addr) self.ic = WStrictOrderInterconnect() self.aw = Axi3_addr()._m() self.w = Axi4_w()._m() self.b = Axi4_b() self.drivers = HObjList(AxiWDatapumpIntf() for _ in range(int(self.DRIVER_CNT)))
def _declr(self): Axi_id._declr(self) self.found = Signal() self.addr = VectSignal(self.ADDR_WIDTH) if self.WAY_CNT > 1: self.way = VectSignal(log2ceil(self.WAY_CNT - 1)) if self.TAG_T is not None: self.tags = HObjList(HdlType_to_Interface().apply(self.TAG_T) for _ in range(self.WAY_CNT)) HandshakeSync._declr(self)
def create_data_reg(self, name_prefix, clk=None, rst=None): """ Create a registers for data signals with default values from :class:`hwt.synthesizer.unit.Unit` parameters and with specified clk/rst """ regs = HObjList() def_vals = self.DATA_RESET_VAL d_sigs = self.get_data(self.dataIn) if def_vals is None or isinstance(def_vals, (int)): def_vals = [def_vals for _ in d_sigs] for d, def_val in zip(d_sigs, def_vals): r = self._reg(name_prefix + d._name, d._dtype, def_val=def_val, clk=clk, rst=rst) regs.append(r) return regs
def _declr(self): addClkRst(self) self.en_mult = Signal() self.en_sum = Signal() self.en_channel = Signal() self.en_batch = Signal() self.en_act = Signal() self.input = VectSignal(self.size * self.channels * self.INPUT_WIDTH) self.output = VectSignal(self.filters * self.OUTPUT_WIDTH)._m() if self.top_entity: output_width = int( self.filters / self.parallelism) * self.OUTPUT_WIDTH # instantiate empty ConvLayerPart self.conv_layer_part = HObjList( ConvLayerPart( input_width=self.size * self.channels * self.INPUT_WIDTH, output_width=output_width, layer_id=self.layer_id, process_id=i, log_level=0, ) for i in range(self.parallelism)) name = f"ConvLayerL{self.layer_id}" else: # instantiate dynamically multichannel units self.conv_layer_part = HObjList( MultiChannelConvUnit( layer_id=self.layer_id, unit_id=i, width=self.width, channels=self.channels, binary=self.binary, size=self.size, bin_input=self.bin_input, bin_output=self.bin_output, process_id=self.process_id, log_level=self.log_level + 1, ) for i in range(self.filters)) name = f"ConvLayerL{self.layer_id}P{self.process_id}" self._hdl_module_name = name self._name = name
def _declr(self) -> None: addClkRstn(self) slavePorts = HObjList() for _, features in self._masters: if features is not ACCESS_RW: raise NotImplementedError(features) m = Ipif() m._updateParamsFrom(self) slavePorts.append(m) self.s = slavePorts masterPorts = HObjList() for _, size, features in self._slaves: if features is not ACCESS_RW: raise NotImplementedError(features) s = Ipif()._m() s.ADDR_WIDTH.set(log2ceil(size - 1)) s._replaceParam(s.DATA_WIDTH, self.DATA_WIDTH) masterPorts.append(s) self.m = masterPorts