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 _declr(self): AxiInterconnectCommon._declr(self, has_r=False, has_w=True) masters_for_slave = AxiInterconnectMatrixCrossbar._masters_for_slave( self.MASTERS, len(self.SLAVES)) # fifo for master index for each slave so slave knows # which master did read and where is should send it order_m_index_for_s_data = HObjList() order_m_index_for_s_b = HObjList() for connected_masters in masters_for_slave: if len(connected_masters) > 1: f_w = HandshakedFifo(Handshaked) f_b = HandshakedFifo(Handshaked) for _f in [f_w, f_b]: _f.DEPTH = self.MAX_TRANS_OVERLAP _f.DATA_WIDTH = log2ceil(len(self.MASTERS)) else: f_w, f_b = None, None order_m_index_for_s_data.append(f_w) order_m_index_for_s_b.append(f_b) self.order_m_index_for_s_data = order_m_index_for_s_data self.order_m_index_for_s_b = order_m_index_for_s_b # fifo for slave index for each master # so master knows where it should expect the data order_s_index_for_m_data = HObjList() order_s_index_for_m_b = HObjList() for connected_slaves in self.MASTERS: if len(connected_slaves) > 1: f_w = HandshakedFifo(Handshaked) f_b = HandshakedFifo(Handshaked) for f in [f_w, f_b]: f.DEPTH = self.MAX_TRANS_OVERLAP f.DATA_WIDTH = log2ceil(len(self.SLAVES)) else: f_w, f_b = None, None order_s_index_for_m_data.append(f_w) order_s_index_for_m_b.append(f_b) self.order_s_index_for_m_data = order_s_index_for_m_data self.order_s_index_for_m_b = order_s_index_for_m_b AXI = self.intfCls with self._paramsShared(): self.addr_crossbar = AxiInterconnectMatrixAddrCrossbar(AXI.AW_CLS) with self._paramsShared(): c = self.data_crossbar = AxiInterconnectMatrixCrossbar(AXI.W_CLS) c.INPUT_CNT = len(self.MASTERS) W_OUTPUTS = [set() for _ in self.SLAVES] for m_i, accessible_slaves in enumerate(self.MASTERS): for s_i in accessible_slaves: W_OUTPUTS[s_i].add(m_i) c.OUTPUTS = W_OUTPUTS with self._paramsShared(): c = self.b_crossbar = AxiInterconnectMatrixCrossbarB(AXI.B_CLS) c.INPUT_CNT = len(self.SLAVES) c.OUTPUTS = self.MASTERS
def _impl(self): propagateClkRstn(self) dIn = AxiSBuilder(self, self.dataIn).buff().end sb = self.sizesBuff db = self.dataBuff wordCntr = self._reg("wordCntr", Bits(log2ceil(self.MAX_LEN) + 1), def_val=0) overflow = wordCntr._eq(self.MAX_LEN) last = dIn.last | overflow If( StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn]).ack(), If(last, wordCntr(0)).Else(wordCntr(wordCntr + 1))) length = self._sig("length", wordCntr._dtype) BYTE_CNT = dIn.data._dtype.bit_length() // 8 if dIn.USE_STRB: # compress strb mask as binary number rem = self._sig("rem", Bits(log2ceil(BYTE_CNT))) SwitchLogic(cases=[(dIn.strb[i], rem(0 if i == BYTE_CNT - 1 else i + 1)) for i in reversed(range(BYTE_CNT))], default=[ rem(0), ]) if self.EXPORT_ALIGNMENT_ERROR: errorAlignment = self._reg("errorAlignment_reg", def_val=0) self.errorAlignment(errorAlignment) If(dIn.valid & (dIn.strb != mask(BYTE_CNT)) & ~dIn.last, errorAlignment(1)) If(last & (dIn.strb != mask(BYTE_CNT)), length(wordCntr)).Else(length(wordCntr + 1)) else: length(wordCntr + 1) rem = Bits(log2ceil(BYTE_CNT)).from_py(0) sb.dataIn.data(Concat(length, rem)) db.dataIn(dIn, exclude=[dIn.valid, dIn.ready, dIn.last]) db.dataIn.last(last) StreamNode(masters=[dIn], slaves=[sb.dataIn, db.dataIn], extraConds={ sb.dataIn: last }).sync() self.sizes(sb.dataOut) self.dataOut(db.dataOut)
def _declr(self): if self.ID_WIDTH: self.id = VectSignal(self.ID_WIDTH) # rem is number of bits in last word which is valid - 1, # if rem == 0 it means all bytes are valid self.rem = VectSignal(log2ceil(self.DATA_WIDTH // 8)) if self.SHIFT_OPTIONS != (0, ): self.shift = VectSignal(log2ceil(len(self.SHIFT_OPTIONS))) if self.HAS_PROPAGATE_LAST: self.propagateLast = Signal() HandshakeSync._declr(self)
def _declr(self): if self.ID_WIDTH: self.id = VectSignal(self.ID_WIDTH) self.addr = VectSignal(self.ADDR_WIDTH) assert self.MAX_LEN >= 0, self.MAX_LEN if self.MAX_LEN > 0: self.len = VectSignal(log2ceil(self.MAX_LEN + 1)) # rem is number of bytes in last word which are valid - 1 self.rem = VectSignal(log2ceil(self.DATA_WIDTH // 8)) HandshakeSync._declr(self)
def __init__(self, src_addr_step: int = 8, dst_addr_step: int = 8): self.src_addr_step = src_addr_step self.dst_addr_step = dst_addr_step assert isPow2(src_addr_step), src_addr_step assert isPow2(dst_addr_step), dst_addr_step if src_addr_step == dst_addr_step: align_bits = 0 elif src_addr_step < dst_addr_step: align_bits = log2ceil((dst_addr_step // src_addr_step) - 1) else: align_bits = log2ceil((src_addr_step // dst_addr_step) - 1) self.align_bits = align_bits
def get_lru(self): """ To find LRU, we can perform a depth-first-search starting from root, and traverse nodes in lower levels. If the node is 0, then we traverse the left sub-tree; otherwise, we traverse the right sub-tree. In the diagram above, the LRU is set 3. """ # node_index: bits rlu register node_paths = {} self._build_node_paths(node_paths, 0, tuple()) # also number of levels of rlu tree bin_index_w = log2ceil( self.lru_reg_items(self.lru_regs._dtype.bit_length())) lru_index_bin = [] # msb first in lru binary index for output_bit_i in range(bin_index_w): items_on_current_level = int(2**output_bit_i) current_level_offset = 2**output_bit_i - 1 possible_paths = [] for node_i in range(current_level_offset, current_level_offset + items_on_current_level): p = node_paths[node_i] possible_paths.append(And(*p)) lru_index_bin.append(Or(*possible_paths)) # MSB was first so the result is in little endian MSB..LSB return Concat(*lru_index_bin)
def _declr(self): addClkRstn(self) with self._paramsShared(): # read interface for datapump # interface which sending requests to download addr of next block self.rDatapump = AxiRDatapumpIntf()._m() # because we are downloading only addres of next block self.rDatapump.MAX_LEN = 1 # write interface for datapump self.wDatapump = AxiWDatapumpIntf()._m() self.wDatapump.MAX_LEN = self.BUFFER_CAPACITY // 2 assert self.BUFFER_CAPACITY <= self.ITEMS_IN_BLOCK # interface for items which should be written into list self.dataIn = Handshaked() # interface to control internal register a = self.baseAddr = RegCntrl() a.DATA_WIDTH = self.ADDR_WIDTH self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr.DATA_WIDTH = self.PTR_WIDTH f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE = True f.DATA_WIDTH = self.DATA_WIDTH f.DEPTH = self.BUFFER_CAPACITY self.ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8)
def timeoutHandler(self, rst, incr): timeoutCntr = self._reg("timeoutCntr", Bits(log2ceil(self.TIMEOUT) + 1, signed=False), def_val=self.TIMEOUT) If(rst, timeoutCntr(self.TIMEOUT)).Elif((timeoutCntr != 0) & incr, timeoutCntr(timeoutCntr - 1)) return timeoutCntr._eq(0)
def _declr(self): assert int( self.DEPTH ) > 0, "FifoAsync is disabled in this case, do not use it entirely" assert isPow2( self.DEPTH), f"DEPTH has to be power of 2, is {self.DEPTH:d}" # pow 2 because of gray conter counters if self.EXPORT_SIZE or self.EXPORT_SPACE: raise NotImplementedError() self.dataIn_clk = Clk() self.dataIn_clk.FREQ = self.IN_FREQ self.dataOut_clk = Clk() self.dataOut_clk.FREQ = self.OUT_FREQ with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn_rst_n = Rst_n() with self._associated(rst=self.dataIn_rst_n): self.dataIn = FifoWriter() with self._associated(clk=self.dataOut_clk): self.dataOut_rst_n = Rst_n() with self._associated(rst=self.dataOut_rst_n): self.dataOut = FifoReader()._m() self.AW = log2ceil(self.DEPTH)
def _instantiateTimer(parentUnit, timer, enableSig=None, rstSig=None): """ :param enableSig: enable signal for all counters :param rstSig: reset signal for all counters """ if timer.parent is None: maxVal = timer.maxVal - 1 # use original to propagate parameter origMaxVal = timer.maxValOriginal - 1 assert maxVal >= 0 if maxVal == 0: if enableSig is None: tick = 1 else: tick = enableSig else: timer.cntrRegister = parentUnit._reg( f"{timer.name:s}timerCntr{timer.maxVal:d}", Bits(log2ceil(maxVal + 1)), maxVal) tick = TimerInfo._instantiateTimerTickLogic( parentUnit, timer, origMaxVal, enableSig, rstSig) timer.tick = parentUnit._sig( f"{timer.name:s}timerTick{timer.maxVal:d}", ) timer.tick(tick) else: TimerInfo._instantiateTimerWithParent(parentUnit, timer, timer.parent, enableSig, rstSig)
def _downscale(self, factor): inputRegs_cntr = self._reg("inputRegs_cntr", Bits(log2ceil(factor + 1), False), def_val=0) # instantiate HandshakedReg, handshaked builder is not used to avoid dependencies inReg = HandshakedReg(self.intfCls) inReg._updateParamsFrom(self.dataIn) self.inReg = inReg inReg.clk(self.clk) inReg.rst_n(self.rst_n) inReg.dataIn(self.dataIn) dataIn = inReg.dataOut dataOut = self.dataOut # create output mux for din, dout in zip(self.get_data(dataIn), self.get_data(dataOut)): widthOfPart = din._dtype.bit_length() // factor inParts = iterBits(din, bitsInOne=widthOfPart) Switch(inputRegs_cntr).add_cases( [(i, dout(inPart)) for i, inPart in enumerate(inParts)] ) vld = self.get_valid_signal rd = self.get_ready_signal vld(dataOut)(vld(dataIn)) self.get_ready_signal(dataIn)(inputRegs_cntr._eq(factor - 1) & rd(dataOut)) If(vld(dataIn) & rd(dataOut), If(inputRegs_cntr._eq(factor - 1), inputRegs_cntr(0) ).Else( inputRegs_cntr(inputRegs_cntr + 1) ) )
def _declr(self): assert isPow2(self.DEPTH - 1), ( "DEPTH has to be 2**n + 1" " because fifo has have DEPTH 2**n" " and 1 item is stored on output reg", self.DEPTH) self.dataIn_clk = Clk() self.dataOut_clk = Clk() with self._paramsShared(): with self._associated(clk=self.dataIn_clk): self.dataIn_rst_n = Rst_n() with self._associated(rst=self.dataIn_rst_n): self.dataIn = self.intfCls() with self._associated(clk=self.dataOut_clk): self.dataOut_rst_n = Rst_n() with self._associated(rst=self.dataOut_rst_n): self.dataOut = self.intfCls()._m() f = self.fifo = FifoAsync() f.IN_FREQ = self.IN_FREQ f.OUT_FREQ = self.OUT_FREQ DW = self.dataIn._bit_length() - 2 # 2 for control (valid, ready) f.DATA_WIDTH = DW # because the output register is used as another item storage f.DEPTH = self.DEPTH - 1 f.EXPORT_SIZE = self.EXPORT_SIZE f.EXPORT_SPACE = self.EXPORT_SPACE SIZE_W = log2ceil(self.DEPTH + 1 + 1) if self.EXPORT_SIZE: self.size = VectSignal(SIZE_W, signed=False) if self.EXPORT_SPACE: self.space = VectSignal(SIZE_W, signed=False)
def _impl(self) -> None: if len(self.MASTERS) > 1: raise NotImplementedError() m = self.s[0] wrack = rdack = err = BIT.from_py(0) AW = int(self.ADDR_WIDTH) rdata = [] for i, (s, (s_offset, s_size)) in\ enumerate(zip(self.m, self.SLAVES)): s.bus2ip_addr(m.bus2ip_addr, fit=True) s.bus2ip_be(m.bus2ip_be) s.bus2ip_rnw(m.bus2ip_rnw) s.bus2ip_data(m.bus2ip_data) bitsOfSubAddr = log2ceil(s_size - 1) prefix = get_bit_range(s_offset, bitsOfSubAddr, AW - bitsOfSubAddr) cs = self._sig(f"m_cs_{i:d}") cs(m.bus2ip_addr[AW:bitsOfSubAddr]._eq(prefix)) s.bus2ip_cs(m.bus2ip_cs & cs) err = err | (cs & s.ip2bus_error) rdack = rdack | (cs & s.ip2bus_rdack) wrack = wrack | (cs & s.ip2bus_wrack) rdata.append((cs, s.ip2bus_data)) m.ip2bus_error(err) m.ip2bus_rdack(rdack) m.ip2bus_wrack(wrack) SwitchLogic([(sel, m.ip2bus_data(data)) for sel, data in rdata], default=m.ip2bus_data(None))
def _declr(self): if self.ID_WIDTH: self.id = VectSignal(self.ID_WIDTH) self.index = VectSignal(self.INDEX_WIDTH) if self.WAY_CNT > 1: self.way = VectSignal(log2ceil(self.WAY_CNT - 1)) HandshakeSync._declr(self)
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): assert self.CACHE_LINE_CNT > 0, self.CACHE_LINE_CNT assert self.WAY_CNT > 0, self.WAY_CNT assert self.CACHE_LINE_CNT % self.WAY_CNT == 0, (self.CACHE_LINE_CNT, self.WAY_CNT) self._compupte_tag_index_offset_widths() addClkRstn(self) with self._paramsShared(): self.s = Axi4() self.m = Axi4()._m() rc = self.read_cancel = AddrHs()._m() rc.ID_WIDTH = 0 self.tag_array = AxiCacheTagArray() self.lru_array = AxiCacheLruArray() for a in [self.tag_array, self.lru_array]: a.PORT_CNT = 2 # r+w # self.flush = HandshakeSync() # self.init = HandshakeSync() data_array = self.data_array = RamSingleClock() data_array.MAX_BLOCK_DATA_WIDTH = self.MAX_BLOCK_DATA_WIDTH data_array.DATA_WIDTH = self.DATA_WIDTH data_array.ADDR_WIDTH = log2ceil( self.CACHE_LINE_CNT * ceil(self.CACHE_LINE_SIZE * 8 / self.DATA_WIDTH)) data_array.PORT_CNT = (READ, WRITE) data_array.HAS_BE = True
def _declr(self): addClkRstn(self) self.ALIGN_BITS_IN = log2ceil((self.DATA_WIDTH // 8) - 1) self.ALIGN_BITS_OUT = log2ceil((self.OUT_DATA_WIDTH // 8) - 1) assert self.ALIGN_BITS_IN <= self.ADDR_WIDTH, (self.ALIGN_BITS_IN, self.ADDR_WIDTH) assert self.ALIGN_BITS_OUT <= self.OUT_ADDR_WIDTH, ( self.ALIGN_BITS_OUT, self.OUT_ADDR_WIDTH) with self._paramsShared(): self.s = self.intfCls() with self._paramsShared(): self.m = self.intfCls()._m() self.m.ADDR_WIDTH = self.OUT_ADDR_WIDTH self.m.DATA_WIDTH = self.OUT_DATA_WIDTH
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 _impl(self): st_t = HEnum("state_t", ["IDLE", "LOAD_SR", "CONVERTING", "DONE"]) st = self._reg("st", st_t, def_val=st_t.IDLE) sr_shift = st.next._eq(st_t.CONVERTING) bcd = self.din bin_ = self.dout bcd_sr = self._reg("bcd_sr", bcd.data._dtype, def_val=0) binary_sr = self._reg("binary_sr", bin_.data._dtype, def_val=0) next_bcd = rename_signal(self, bcd_sr >> 1, "next_bcd") MAX_COUNT = binary_sr._dtype.bit_length() bit_count = self._reg("bit_count", Bits(log2ceil(MAX_COUNT), signed=False), def_val=MAX_COUNT) If(sr_shift, bit_count(bit_count - 1), ).Else( bit_count(MAX_COUNT), ) # dabble the digits digits = [] for i in range(self.BCD_DIGITS): d = next_bcd[(i + 1) * 4:i * 4]._unsigned() d_sig = (d < 7)._ternary(d, d - 3) digits.append(d_sig) If(st.next._eq(st_t.LOAD_SR), bcd_sr(bcd.data), binary_sr(0), ).Elif(sr_shift, # shift right binary_sr(Concat(bcd_sr[0], binary_sr[:1])), bcd_sr(Concat(*reversed(digits))), ) bin_.data(binary_sr) Switch(st)\ .Case(st_t.IDLE, If(bcd.vld, st(st_t.LOAD_SR), # load the shift registers ))\ .Case(st_t.LOAD_SR, # shift right each cycle st(st_t.CONVERTING), )\ .Case(st_t.CONVERTING, If(bit_count._eq(0), # indicate completion st(st_t.DONE), ) )\ .Case(st_t.DONE, If(bcd.vld & bin_.rd, st(st_t.LOAD_SR), ).Elif(bin_.rd, st(st_t.IDLE), ) ) bcd.rd(st._eq(st_t.IDLE) | (st._eq(st_t.DONE) & bin_.rd)) bin_.vld(st._eq(st_t.DONE))
def _declr(self): addClkRstn(self) BCD_DIGITS = self.BCD_DIGITS bcd = self.din = Handshaked() # BCD data to convert bcd.DATA_WIDTH = 4 * BCD_DIGITS bin_ = self.dout = Handshaked()._m() bin_.DATA_WIDTH = log2ceil(10 ** BCD_DIGITS - 1) # Converted output. Retained until next conversion
def _declr(self): addClkRstn(self) with self._paramsShared(): # interface which sending requests to download data # and interface which is collecting all data and only data with specified id are processed self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_BYTES = self.BUFFER_CAPACITY // 2 * self.DATA_WIDTH // 8 self.dataOut = Handshaked()._m() # (how much of items remains in block) self.inBlockRemain = VectSignal(log2ceil(self.ITEMS_IN_BLOCK + 1))._m() # interface to control internal register a = self.baseAddr = RegCntrl() a.DATA_WIDTH = self.ADDR_WIDTH self.rdPtr = RegCntrl() self.wrPtr = RegCntrl() for ptr in [self.rdPtr, self.wrPtr]: ptr.DATA_WIDTH = self.PTR_WIDTH f = self.dataFifo = HandshakedFifo(Handshaked) f.EXPORT_SIZE = True f.DATA_WIDTH = self.DATA_WIDTH f.DEPTH = self.BUFFER_CAPACITY
def fifo_pointers(self, DEPTH: int, write_en_wait: Tuple[RtlSignal, RtlSignal], read_en_wait_list: List[Tuple[RtlSignal, RtlSignal]])\ -> List[Tuple[RtlSignal, RtlSignal]]: """ Create fifo writer and reader pointers and enable/wait logic This functions supports multiple reader pointers :attention: writer pointer next logic check only last reader pointer :return: list, tule(en, ptr) for writer and each reader """ index_t = Bits(log2ceil(DEPTH), signed=False) # assert isPow2(DEPTH), DEPTH MAX_DEPTH = DEPTH - 1 s = self._sig r = self._reg fifo_write = s("fifo_write") write_ptr = _write_ptr = r("write_ptr", index_t, 0) ack_ptr_list = [ (fifo_write, write_ptr), ] # update writer (head) pointer as needed If( fifo_write, If(write_ptr._eq(MAX_DEPTH), write_ptr(0)).Else(write_ptr(write_ptr + 1))) write_en, _ = write_en_wait # instantiate all read pointers for i, (read_en, read_wait) in enumerate(read_en_wait_list): read_ptr = r(f"read_ptr{i:d}", index_t, 0) fifo_read = s(f"fifo_read{i:d}") ack_ptr_list.append((fifo_read, read_ptr)) # update reader (tail) pointer as needed If( fifo_read, If(read_ptr._eq(MAX_DEPTH), read_ptr(0)).Else(read_ptr(read_ptr + 1))) looped = r(f"looped{i:d}", def_val=False) # looped logic If(write_en & write_ptr._eq(MAX_DEPTH), looped(True)).Elif(read_en & read_ptr._eq(MAX_DEPTH), looped(False)) # Update Empty and Full flags read_wait(write_ptr._eq(read_ptr) & ~looped) fifo_read(read_en & (looped | (write_ptr != read_ptr))) # previous reader is next port writer (producer) as it next reader can continue only if previous reader did consume the item write_en, _ = read_en, read_wait write_ptr = read_ptr write_en, write_wait = write_en_wait write_ptr = _write_ptr # Update Empty and Full flags write_wait(write_ptr._eq(read_ptr) & looped) fifo_write(write_en & (~looped | (write_ptr != read_ptr))) return ack_ptr_list
def _impl(self) -> None: start = self._sig("start") part_res_t = Bits(self.DATA_WIDTH) # High-order n bits of product a = self._reg("a", part_res_t) # multiplicand m = self._reg("m", part_res_t) # Initially holds multiplier, ultimately holds low-order n bits of product q = self._reg("q", part_res_t) # previous bit 0 of q q_1 = self._reg("q_1") din = self.dataIn dout = self.dataOut counter = self._reg( "counter", Bits(log2ceil(self.DATA_WIDTH + 1), signed=False), def_val=0) done = counter._eq(0) waitinOnConsumer = self._reg("waitinOnConsumer", def_val=0) add = rename_signal(self, (a + m)._signed(), "add") sub = rename_signal(self, (a - m)._signed(), "sub") If(start, a(0), m(din.a), q(din.b), q_1(0), counter(self.DATA_WIDTH), ).Elif(~done, Switch(Concat(q[0], q_1)) .Case(0b01, # add multiplicand to left half of product a(add >> 1), q(Concat(add[0], q[:1])), ).Case(0b10, # substract multiplicand from left half of product a(sub >> 1), q(Concat(sub[0], q[:1])), ).Default( a(a._signed() >> 1), q(Concat(a[0], q[:1])), ), q_1(q[0]), counter(counter - 1) ) If(start, waitinOnConsumer(1) ).Elif(done & dout.rd, waitinOnConsumer(0), ) dout.data(Concat(a, q)._vec()) dout.vld(done & waitinOnConsumer) start(din.vld & done & ~waitinOnConsumer) din.rd(done & ~waitinOnConsumer)
def setUpClass(cls): cls.u = u = AxiInterconnectMatrixR(Axi4) u.MASTERS = ({0},) u.SLAVES = ( (0x0000, 0x1000), ) u.ADDR_WIDTH = log2ceil(0x1000 - 1) cls.compileSim(u)
def _declr(self) -> None: addClkRstn(self) with self._paramsShared(): self.s = Axi4() self.ram = RamSingleClock() self.ram.ADDR_WIDTH = self.ADDR_WIDTH - log2ceil(self.DATA_WIDTH // 8 - 1)
def _declr(self): self.data = VectSignal(self.DATA_WIDTH) self.rem = VectSignal(log2ceil(self.DATA_WIDTH // 8)) self.src_rdy_n = Signal() self.dst_rdy_n = Signal(masterDir=DIRECTION.IN) self.sof_n = Signal() self.eof_n = Signal() self.eop_n = Signal() self.sop_n = Signal()
def setUpClass(cls): cls.u = u = AxiInterconnectMatrixAddrCrossbar(Axi4.AR_CLS) u.MASTERS = ({0}, {0}, {1}, {1}, {0, 1}) u.SLAVES = ( (0x0000, 0x1000), (0x1000, 0x1000), ) u.ADDR_WIDTH = log2ceil(0x2000 - 1) cls.compileSim(u)
def _declr(self): addClkRstn(self) self.cntrl = HandshakeSync() self.COUNTER_WIDTH = log2ceil(self.ITERATIONS) self.index = VectSignal(self.COUNTER_WIDTH)._m() self.body = HandshakeSync()._m() self.bodyBreak = Signal()
def _declr(self): self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE) self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil(self.LVL1_PAGE_TABLE_ITEMS) self.LVL2_PAGE_TABLE_INDX_WIDTH = self.ADDR_WIDTH - self.LVL1_PAGE_TABLE_INDX_WIDTH - self.PAGE_OFFSET_WIDTH self.LVL2_PAGE_TABLE_ITEMS = 2 ** int(self.LVL2_PAGE_TABLE_INDX_WIDTH) assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS # public interfaces addClkRstn(self) with self._paramsShared(): self.rDatapump = AxiRDatapumpIntf()._m() self.rDatapump.MAX_BYTES = self.DATA_WIDTH // 8 i = self.virtIn = Handshaked() i.DATA_WIDTH = self.VIRT_ADDR_WIDTH i = self.physOut = Handshaked()._m() i.DATA_WIDTH = self.ADDR_WIDTH self.segfault = Signal()._m() self.lvl1Table = BramPort_withoutClk() # internal components self.lvl1Storage = RamSingleClock() self.lvl1Storage.PORT_CNT = 1 self.lvl1Converter = RamAsHs() for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]: u.DATA_WIDTH = self.ADDR_WIDTH u.ADDR_WIDTH = self.LVL1_PAGE_TABLE_INDX_WIDTH with self._paramsShared(): self.lvl2get = ArrayItemGetter() self.lvl2get.ITEM_WIDTH = self.ADDR_WIDTH self.lvl2get.ITEMS = self.LVL2_PAGE_TABLE_ITEMS self.lvl2indxFifo = HandshakedFifo(Handshaked) self.lvl2indxFifo.DEPTH = self.MAX_OVERLAP // 2 self.lvl2indxFifo.DATA_WIDTH = self.LVL2_PAGE_TABLE_INDX_WIDTH self.pageOffsetFifo = HandshakedFifo(Handshaked) self.pageOffsetFifo.DEPTH = self.MAX_OVERLAP self.pageOffsetFifo.DATA_WIDTH = self.PAGE_OFFSET_WIDTH