def HdlType_bits(cls, typ: Bits, ctx, declaration=False): isVector = typ.force_vector or typ.bit_length() > 1 nameBuff = [] sigType = ctx.signalType if sigType is SIGNAL_TYPE.PORT: pass elif sigType is SIGNAL_TYPE.REG: nameBuff.append("reg") elif sigType is SIGNAL_TYPE.WIRE: nameBuff.append("wire") else: raise NotImplementedError() if typ.signed: nameBuff.append("signed") w = typ.bit_length() if not isVector: pass elif isinstance(w, int): nameBuff.append("[%d:0]" % (w - 1)) else: nameBuff.append("[%s- 1:0]" % cls.Value(w, ctx)) return " ".join(nameBuff)
def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): isVector = typ.force_vector or typ.bit_length() > 1 sigType = self.signalType if typ == INT: t = HdlValueId("int", obj=int) elif sigType is SIGNAL_TYPE.PORT_WIRE: t = HdlTypeAuto elif sigType is SIGNAL_TYPE.REG or sigType is SIGNAL_TYPE.PORT_REG: t = HdlValueId("reg", obj=LanguageKeyword()) elif sigType is SIGNAL_TYPE.WIRE: t = HdlValueId("wire", obj=LanguageKeyword()) else: raise ValueError(sigType) if typ.signed is None: is_signed = None else: is_signed = self.as_hdl_int(int(typ.signed)) if isVector: w = typ.bit_length() assert isinstance(w, int) or (isinstance(w, RtlSignal) and w._const), w w = hdl_downto(self.as_hdl(w - 1), self.as_hdl_int(0)) else: w = None return HdlOp(HdlOpType.PARAMETRIZATION, [t, w, is_signed])
def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() if typ == BOOL: return self.BOOLEAN if typ == INT: return self.INTEGER bitLength = typ.bit_length() w = typ.bit_length() isVector = typ.force_vector or bitLength > 1 if typ.signed is None: if isVector: name = self.STD_LOGIC_VECTOR else: return self.STD_LOGIC elif typ.signed: name = self.SIGNED else: name = self.UNSIGNED return HdlOp(HdlOpType.CALL, [ name, HdlOp(HdlOpType.DOWNTO, [ self.as_hdl(w - 1), self.as_hdl_int(0) ])])
def makeTestbenchTemplate(unit: Unit, name: str=None): """ :param unit: synthesized unit :return: (entity, arch, context) of testbench """ if name is None: name = unit._name + "_tb" entity = Entity(name) arch = Architecture(entity) arch.components.append(unit._entity) arch.componentInstances.append(unit._entity) nl = RtlNetlist() ctx = {} for p in unit._entity.ports: t = p._dtype if isinstance(t, Bits) and not t == BIT: t = Bits(t.bit_length(), signed=t.signed, forceVector=t.forceVector) s = RtlSignal(nl, p.name, t, t.fromPy(0)) ctx[p._interface] = s p.connectSig(s) arch.variables.extend(ctx.values()) return entity, arch, ctx
def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() if typ == BOOL: return self.BOOL if typ == INT: return self.INT w = typ.bit_length() assert isinstance(w, int), w def add_kw(name, val): kw = hdl_map_asoc(HdlValueId(name), HdlValueInt(val, None, None)) args.append(kw) args = [HdlValueInt(w, None, None)] if typ.signed is not BITS_DEFAUTL_SIGNED: add_kw("signed", typ.signed) if typ.force_vector is not BITS_DEFAUTL_FORCEVECTOR and w <= 1: add_kw("force_vector", typ.force_vector) if typ.negated is not BITS_DEFAUTL_NEGATED: add_kw("negated", typ.negated) return hdl_call(self.BITS, args)
def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): assert not declaration w = typ.bit_length() if isinstance(w, int): pass else: w = int(w) return hdl_call(self.BITS3T, [ HdlValueInt(w, None, None), HdlValueInt(int(bool(typ.signed)), None, None) ])
def HdlType_bits(cls, typ: Bits, ctx, declaration=False): disableRange = False bitLength = typ.bit_length() w = typ.bit_length() isVector = typ.force_vector or bitLength > 1 if typ.signed is None: if isVector: name = 'STD_LOGIC_VECTOR' else: return 'STD_LOGIC' elif typ.signed: name = "SIGNED" else: name = 'UNSIGNED' if disableRange: constr = "" else: constr = "(%d DOWNTO 0)" % (w - 1) return name + constr
def HdlType_bits(cls, typ: Bits, ctx, declaration=False): if declaration: raise NotImplementedError() w = typ.bit_length() assert isinstance(w, int), w iItems = ["%d" % w] if typ.signed is not BITS_DEFAUTL_SIGNED: iItems.append("signed=%r" % typ.signed) if typ.force_vector is not BITS_DEFAUTL_FORCEVECTOR and w <= 1: iItems.append("force_vector=%r" % typ.force_vector) if typ.negated is not BITS_DEFAUTL_NEGATED: iItems.append("negated=%r" % typ.negated) return "Bits(%s)" % (", ".join(iItems))
def as_hdl_HdlType_bits(self, typ: Bits, declaration=False): if declaration: raise NotImplementedError() w = typ.bit_length() if w <= 64: if typ.signed: typeBaseName = self.sc_int else: typeBaseName = self.sc_uint else: if typ.signed: typeBaseName = self.sc_bigint else: typeBaseName = self.sc_biguint t = HdlOp(HdlOpType.PARAMETRIZATION, [typeBaseName, self.as_hdl_int(w)]) if self.signalType == SIGNAL_TYPE.WIRE: t = HdlOp(HdlOpType.PARAMETRIZATION, [self.sc_signal, t]) return t
def _impl(self): S_ADDR_STEP = self.S_ADDR_STEP assert S_ADDR_STEP >= self.S_DATA_WIDTH, \ (S_ADDR_STEP, self.S_DATA_WIDTH) axi = self.m # if 2 * self.S_ADDR_STEP <= self.DATA_WIDTH: # # multiple items can be in a single axi word # # require the transaction alignment # axi_resize = AxiResize(axi.__class__) # axi_resize._updateParamsFrom(axi) # axi_resize.DATA_WIDTH = self.S_ADDR_STEP # axi_resize.OUT_DATA_WIDTH = axi.DATA_WIDTH # axi_resize.OUT_ADDR_WIDTH = axi.ADDR_WIDTH # self.axi_resize = axi_resize # axi(axi_resize.m) # axi = axi_resize.s # add extra register on axi b = AxiBuff(axi.__class__) b._updateParamsFrom(axi) self.axi_buff = b axi(b.m) axi = b.s cntr_t = Bits(log2ceil(self.MAX_TRANS_OVERLAP), signed=False) CNTR_MAX = mask(cntr_t.bit_length()) if self.HAS_R: s_r = self.s_r r_cntr = self._reg("r_cntr", cntr_t, def_val=0) self.connect_r(s_r, axi, r_cntr, CNTR_MAX, self.in_axi_t) if self.HAS_W: s_w = self.s_w w_cntr = self._reg("w_cntr", cntr_t, def_val=0) self.connect_w(s_w, axi, w_cntr, CNTR_MAX, self.in_axi_t) propagateClkRstn(self)
class FifoArray(Unit): """ This component is an array of list nodes, which can be used to emulate multiple FIFOs. The memory is shared and the number of lists stored in this array is limited only by memory. Corresponds to data structure: .. code-block:: cpp // note that in implementation each part of struct item is stored in separate array struct item { value_t value; item * next; bool valid; bool last; }; item items[ITEMS]; :note: The insert_addr is used to pop from specific list. The list can be read only from it's head in FIFO order manner. Item is last if it's next pointer points on this item. :note: DistRAM implementation. :note: The pop address is not checked it is possible to pop from wrong list if address is specified incorrectly .. hwt-autodoc:: """ def _config(self): self.ITEMS = Param(4) self.DATA_WIDTH = Param(8) def _declr(self): assert self.ITEMS > 1, self.ITEMS self.addr_t = Bits(log2ceil(self.ITEMS - 1), signed=False) self.value_t = Bits(self.DATA_WIDTH) addClkRstn(self) self.insert = FifoArrayInsertInterface() self.pop = FifoArrayPopInterface()._m() for i in [self.insert, self.pop]: i.ADDR_WIDTH = self.addr_t.bit_length() i.DATA_WIDTH = self.value_t.bit_length() def _impl(self): addr_t = self.addr_t value_t = self.value_t item_mask_t = Bits(self.ITEMS) # bitmap used to quickly detect position of an empty node item_valid = self._reg("item_valid", item_mask_t, def_val=0) item_last = self._reg("item_last", item_mask_t, def_val=0) # an address on where next item should be inserted insert_addr_next = self._reg("insert_addr_next", addr_t, def_val=0) insert_addr_next( oneHotToBin( self, rename_signal( self, ~item_valid.next, "item_become_invalid"))) # get index of first non valid pop = self.pop insert = self.insert insert.addr_ret(insert_addr_next) insert.rd(item_valid != mask(self.ITEMS)) pop_one_hot = rename_signal(self, binToOneHot(pop.addr, en=pop.vld & pop.rd), "pop_one_hot") insert_one_hot = rename_signal( self, binToOneHot(insert_addr_next, en=insert.vld & insert.rd), "insert_one_hot") insert_parent_one_hot = rename_signal( self, binToOneHot(insert.addr, en=insert.vld & insert.rd & insert.append), "insert_parent_one_hot") item_valid((item_valid & ~pop_one_hot) | insert_one_hot) item_last((item_last & ~insert_parent_one_hot) | insert_one_hot) values = self._sig("values", value_t[self.ITEMS]) next_ptrs = self._sig("next_ptrs", addr_t[self.ITEMS]) If( self.clk._onRisingEdge(), If( insert.vld & insert.rd, next_ptrs[insert.addr] (insert_addr_next), # append behind parent node at insert_ptr values[insert_addr_next](insert.data), )) pop.data(values[pop.addr]) pop.addr_next(next_ptrs[pop.addr]) pop.last(item_last[pop.addr] & item_valid[pop.addr]) pop.vld(item_valid != 0)
def getLen_t(self): len_t = self.driver.req.len._dtype if not self.isAlwaysAligned(): len_t = Bits(len_t.bit_length() + 1, signed=False) return len_t
def _impl(self): DEPTH = self.DEPTH index_t = Bits(log2ceil(DEPTH), signed=False) s = self._sig r = self._reg mem = self.mem = s("memory", Bits(self.DATA_WIDTH)[self.DEPTH + 1]) # write pointer which is seen by reader wr_ptr = r("wr_ptr", index_t, 0) # read pointer which is used by reader and can be potentially # reseted to a rd_ptr value (copy command) or can update rd_ptr (non-copy command) rd_ptr_tmp = r("rd_ptr_tmp", index_t, 0) rd_ptr = r("rd_ptr", index_t, 0) MAX_DEPTH = DEPTH - 1 assert MAX_DEPTH.bit_length() == index_t.bit_length(), (MAX_DEPTH, index_t) dout = self.dataOut din = self.dataIn fifo_write = s("fifo_write") fifo_read = s("fifo_read") frame_copy = self.dataOut_copy_frame # Update Tail pointer as needed If( fifo_read, If( frame_copy.vld & frame_copy.data, If(rd_ptr._eq(MAX_DEPTH), rd_ptr_tmp(0)).Else(rd_ptr_tmp(rd_ptr + 1))).Elif( rd_ptr_tmp._eq(MAX_DEPTH), rd_ptr_tmp(0)).Else(rd_ptr_tmp(rd_ptr_tmp + 1)), ) If( frame_copy.vld & ~frame_copy.data, # jump to next frame rd_ptr(rd_ptr_tmp) # If(rd_ptr_tmp._eq(MAX_DEPTH), # rd_ptr(0) # ).Else( # rd_ptr(rd_ptr_tmp + 1) # ) ) wr_ptr_next = self._sig("wr_ptr_next", index_t) If(wr_ptr._eq(MAX_DEPTH), wr_ptr_next(0)).Else(wr_ptr_next(wr_ptr + 1)) # Increment Head pointer as needed If(fifo_write, wr_ptr(wr_ptr_next)) If( self.clk._onRisingEdge(), If( fifo_write, # Write Data to Memory mem[wr_ptr](din.data))) fifo_read(dout.en & ( (wr_ptr != rd_ptr_tmp) | (frame_copy.vld & frame_copy.data))) read_addr_tmp = rename_signal( self, (frame_copy.vld & frame_copy.data)._ternary(rd_ptr, rd_ptr_tmp), "read_addr_tmp") If( self.clk._onRisingEdge(), If( fifo_read, # Update data output dout.data(mem[read_addr_tmp]))) fifo_write(din.en & (wr_ptr_next != rd_ptr)) # Update Empty and Full flags din.wait(wr_ptr_next._eq(rd_ptr)) If(frame_copy.vld & frame_copy.data, dout.wait(0)).Else(dout.wait((wr_ptr._eq(rd_ptr_tmp))))