def DCR_check_logic_modes(): # -- LOGIC MODES DRC return If( In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux), self.deassign_xyz_mux() ).Elif( In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1), deassign_xyz_mux_if_PREG_eq_1(), ).Else( # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000) )
def main_op(self, dst_stage: OOOOpPipelineStage, src_stage: OOOOpPipelineStage): """ A main opration of counter incrementation :note: This function is called for write back state and its predecessor. However because of write bypass this function is called multiple times for each bypass as well. """ dst = dst_stage.data src = src_stage.data prev_st = self.pipeline[dst_stage.index - 1] OP = self.OPERATION prev_st_op = prev_st.transaction_state.operation return If( prev_st.valid & prev_st.transaction_state.key_match & In(prev_st_op, [OP.LOOKUP, OP.LOOKUP_OR_SWAP]), # lookup or lookup_or_swap with found dst.item_valid(src.item_valid), dst.key(src.key), self.main_op_on_lookup_match_update(dst_stage, src_stage), ).Elif( prev_st.valid & prev_st_op._eq(OP.SWAP), # swap or lookup_or_swap with not found dst(prev_st.data), ).Elif( prev_st.valid & ~prev_st.transaction_state.key_match, # not match not swap, keep as it is dst(src), )
def _impl(self): cmd = self.cntrl.cmd cmd_ack = self.cntrl.rd stT = HEnum("stT", [ "idle", "start_0", "start_1", "start_2", "start_3", "start_4", "stop_0", "stop_1", "stop_2", "stop_3", "rd_0", "rd_1", "rd_2", "rd_3", "wr_0", "wr_1", "wr_2", "wr_3" ]) fsm = FsmBuilder(self, stT) st = fsm.stateReg # check SDA status (multi-master arbitration) sda_chk = self._reg("sda_chk", def_val=0) scl_t = self._reg("scl_t", def_val=0) sda_t = self._reg("sda_t", def_val=0) scl = self.filter("scl", self.i2c.scl.i) sda = self.filter("sda", self.i2c.sda.i) _, stopCond, scl_sync = self.detectStartAndStop(scl, sda, scl_t) stateClkEn = self.stateClkGen(scl_sync, scl_t, scl) al = self.arbitrationLostDriver(st, sda, sda_chk, sda_t, stopCond, stateClkEn) def stateSequence(sequneceName, stateCnt): for i in range(stateCnt): stateFrom = getattr(stT, f"{sequneceName}_{i:d}") if i == stateCnt - 1: stateTo = stT.idle else: _i = i + 1 stateTo = getattr(stT, f"{sequneceName}_{_i:d}") fsm.Trans(stateFrom, (al, stT.idle), stateTo) fsm.Trans( stT.idle, (al, stT.idle), (cmd._eq(NOP), stT.idle), (cmd._eq(START), stT.start_0), (cmd._eq(STOP), stT.stop_0), (cmd._eq(WRITE), stT.wr_0), (cmd._eq(READ), stT.rd_0), ) stateSequence("start", 5) stateSequence("stop", 4) stateSequence("rd", 4) stateSequence("wr", 4) If( al, cmd_ack(0), sda_t(0), scl_t(0), sda_chk(0), ).Else( If( In(st, [ stT.start_1, stT.start_2, stT.start_3, stT.stop_1, stT.stop_2, stT.stop_3, stT.rd_1, stT.rd_2, stT.wr_1, stT.wr_2 ]), scl_t(0)).Elif( In(st, [ stT.start_4, stT.stop_0, stT.rd_0, stT.rd_3, stT.wr_0, stT.wr_3 ]), scl_t(1)), If( In(st, [ stT.start_0, stT.start_1, stT.stop_3, stT.rd_0, stT.rd_1, stT.rd_2, stT.rd_3 ]), sda_t(0)).Elif( In(st, [ stT.start_2, stT.start_3, stT.start_4, stT.stop_0, stT.stop_1, stT.stop_2 ]), sda_t(1)).Elif( In(st, [stT.wr_0, stT.wr_1, stT.wr_2, stT.wr_3]), sda_t(~self.cntrl.din)), # cmd ack at the end of state sequence cmd_ack(In(st, [stT.start_4, stT.stop_3, stT.rd_3, stT.wr_3]))) self.i2c.scl.o(0) self.i2c.sda.o(0) self.i2c.scl.t(scl_t) self.i2c.sda.t(sda_t)
def _impl(self): # timers and other registers CLK_HALF_PERIOD_DIV = ceil(self.clk.FREQ / (self.MDIO_FREQ * 2)) mdio_clk = self._reg("mdio_clk", def_val=0) r_data_vld = self._reg("r_data_vld", def_val=0) req = self.req clk_half_period_en = ClkBuilder(self, self.clk).timer( ("clk_half_period_en", CLK_HALF_PERIOD_DIV)) If( clk_half_period_en, mdio_clk(~mdio_clk), ) mdio_clk_rising = clk_half_period_en & ~mdio_clk mdio_clk_falling = clk_half_period_en & mdio_clk idle = self._sig("idle") preamble_last, addr_block_last, turnarround_last_en, data_last =\ self._packet_sequence_timer( mdio_clk_rising, mdio_clk_falling, ~idle) is_rx = self._reg("is_rx", def_val=0) # protocol FSM st_t = HEnum("st_t", ["idle", "pre", "addr_block", "ta", "data"]) st = FsmBuilder(self, st_t)\ .Trans(st_t.idle, (req.vld & ~r_data_vld, st_t.pre))\ .Trans(st_t.pre, (preamble_last, st_t.addr_block))\ .Trans(st_t.addr_block, (addr_block_last, st_t.ta))\ .Trans(st_t.ta, (turnarround_last_en & ( (is_rx & mdio_clk_falling) | (~is_rx & mdio_clk_rising)), st_t.data))\ .Trans(st_t.data, (data_last, st_t.idle)).stateReg idle(st._eq(st_t.idle)) req.rd(idle & ~r_data_vld) If(idle, is_rx(req.opcode._eq(Mdio.OP.READ))) # TX logic md = self.md TX_W = md.ST_W + md.OP_W + md.PA_W + md.RA_W + md.TA_W + md.D_W tx_reg = self._reg("tx_reg", Bits(TX_W)) If( idle & req.vld, tx_reg( Concat( Mdio.ST, req.opcode, req.addr.phy, req.addr.reg, Mdio.TA, req.wdata))).Elif( mdio_clk_falling & In(st, [st_t.addr_block, st_t.data, st_t.ta, st_t.data]), tx_reg(tx_reg << 1)) md.c(mdio_clk) # because MDIO uses open-drain, this means that if t=0 the value of the signal is 1 md.io.o(0) tx_bit = tx_reg[tx_reg._dtype.bit_length() - 1] md.io.t(~idle & ~tx_bit & (st._eq(st_t.addr_block) | (In(st, [st_t.data, st_t.ta]) & ~is_rx))) # RX logic rx_reg = self._reg("rx_reg", Bits(md.D_W)) If( st._eq(st_t.data) & is_rx & mdio_clk_rising, shift_in_msb_first(rx_reg, self.md.io.i)) If(idle & self.rdata.rd, r_data_vld(0)).Elif(addr_block_last, r_data_vld(is_rx)) self.rdata.vld(idle & r_data_vld) self.rdata.data(rx_reg)
def flush_or_read_node( self, d_arr_r: RamHsR, d_arr_w: AddrDataHs, st2_out: HsStructIntf, data_arr_read: Axi4_r, tag_update: AxiCacheTagArrayUpdateIntf, # out ): ########################## st1 - post (victim flushing, read forwarding) ###################### in_w = AxiSBuilder(self, self.s.w)\ .buff(self.tag_array.LOOKUP_LATENCY + 4)\ .end st2 = st2_out.data d_arr_w.addr( self.addr_in_data_array(st2.victim_way, self.parse_addr(st2.replacement_addr)[1])) data_arr_read_data = d_arr_r.data # HsBuilder(self, d_arr_r.data).buff(1, latency=(1, 2)).end d_arr_w.data(in_w.data) d_arr_w.mask(in_w.strb) self.s.b.id(st2.write_id) self.s.b.resp(RESP_OKAY) data_arr_read.id(st2.read_id) data_arr_read.data(data_arr_read_data.data) data_arr_read.resp(RESP_OKAY) data_arr_read.last(1) m = self.m m.aw.addr(st2.victim_addr) m.aw.id(st2.write_id) m.aw.len(0) self.axiAddrDefaults(m.aw) m.w.data(data_arr_read_data.data) m.w.strb(mask(m.w.data._dtype.bit_length() // 8)) m.w.last(1) # flushing needs to have higher priority then read in order # to prevent deadlock # write replacement after victim load with higher priority # else if found just write the data to data array is_flush = st2.data_array_op._eq(data_trans_t.write_and_flush) contains_write = rename_signal( self, In(st2.data_array_op, [ data_trans_t.write, data_trans_t.write_and_flush, data_trans_t.read_and_write ]), "contains_write") contains_read = rename_signal( self, In(st2.data_array_op, [ data_trans_t.read, data_trans_t.write_and_flush, data_trans_t.read_and_write ]), "contains_read") contains_read_data = rename_signal( self, In(st2.data_array_op, [data_trans_t.read, data_trans_t.read_and_write]), "contains_read_data") flush_or_read_node = StreamNode( [st2_out, data_arr_read_data, in_w ], # collect read data from data array, collect write data [data_arr_read, m.aw, m.w, d_arr_w, self.s.b ], # to read block or to slave connected on "m" interface # write data to data array and send write acknowledge extraConds={ data_arr_read_data: contains_read, in_w: contains_write, data_arr_read: contains_read_data, m.aw: is_flush, m.w: is_flush, d_arr_w: contains_write, self.s.b: contains_write, }, skipWhen={ data_arr_read_data: ~contains_read, in_w: ~contains_write, data_arr_read: ~contains_read_data, m.aw: ~is_flush, m.w: ~is_flush, d_arr_w: ~contains_write, self.s.b: ~contains_write, }) flush_or_read_node.sync() m.b.ready(1) tag_update.vld(st2_out.vld & contains_write) tag_update.delete(0) tag_update.way_en(binToOneHot(st2.victim_way)) tag_update.addr(st2.replacement_addr) # [TODO] initial clean lru_array_set = self.lru_array.set lru_array_set.addr(None) lru_array_set.data(None) lru_array_set.vld(0)
def _impl(self): # internal signals ACASCREG, ADREG, ALUMODEREG, AREG, AUTORESET_PATDET, A_INPUT, BCASCREG, BREG, B_INPUT, CARRYINREG, CARRYINSELREG, \ CREG, DREG, INMODEREG, IS_ALUMODE_INVERTED, IS_CARRYIN_INVERTED, IS_CLK_INVERTED, IS_INMODE_INVERTED, IS_OPMODE_INVERTED, MASK, MREG, \ OPMODEREG, PATTERN, PREG, SEL_MASK, SEL_PATTERN, USE_DPORT, USE_MULT, USE_PATTERN_DETECT, USE_SIMD, ACOUT, \ BCOUT, CARRYCASCOUT, CARRYOUT, MULTSIGNOUT, OVERFLOW, P, PATTERNBDETECT, PATTERNDETECT, PCOUT, UNDERFLOW, \ A, ACIN, ALUMODE, B, BCIN, C, CARRYCASCIN, CARRYIN, CARRYINSEL, CEA1, \ CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL, CED, CEINMODE, \ CEM, CEP, CLK, D, INMODE, MULTSIGNIN, OPMODE, PCIN, RSTA, RSTALLCARRYIN, \ RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP = \ self.ACASCREG, self.ADREG, self.ALUMODEREG, self.AREG, self.AUTORESET_PATDET, self.A_INPUT, self.BCASCREG, self.BREG, self.B_INPUT, self.CARRYINREG, self.CARRYINSELREG, \ self.CREG, self.DREG, self.INMODEREG, self.IS_ALUMODE_INVERTED, self.IS_CARRYIN_INVERTED, self.IS_CLK_INVERTED, self.IS_INMODE_INVERTED, self.IS_OPMODE_INVERTED, self.MASK, self.MREG, \ self.OPMODEREG, self.PATTERN, self.PREG, self.SEL_MASK, self.SEL_PATTERN, self.USE_DPORT, self.USE_MULT, self.USE_PATTERN_DETECT, self.USE_SIMD, self.ACOUT, \ self.BCOUT, self.CARRYCASCOUT, self.CARRYOUT, self.MULTSIGNOUT, self.OVERFLOW, self.P, self.PATTERNBDETECT, self.PATTERNDETECT, self.PCOUT, self.UNDERFLOW, \ self.A, self.ACIN, self.ALUMODE, self.B, self.BCIN, self.C, self.CARRYCASCIN, self.CARRYIN, self.CARRYINSEL, self.CEA1, \ self.CEA2, self.CEAD, self.CEALUMODE, self.CEB1, self.CEB2, self.CEC, self.CECARRYIN, self.CECTRL, self.CED, self.CEINMODE, \ self.CEM, self.CEP, self.CLK, self.D, self.INMODE, self.MULTSIGNIN, self.OPMODE, self.PCIN, self.RSTA, self.RSTALLCARRYIN, \ self.RSTALUMODE, self.RSTB, self.RSTC, self.RSTCTRL, self.RSTD, self.RSTINMODE, self.RSTM, self.RSTP #------------------- constants ------------------------- CARRYOUT_W = 4 A_W = 30 ALUMODE_W = 4 A_MULT_W = 25 B_W = 18 B_MULT_W = 18 D_W = 25 INMODE_W = 5 OPMODE_W = 7 ALU_FULL_W = 48 IS_ALUMODE_INVERTED_BIN = self._sig("IS_ALUMODE_INVERTED_BIN", Bits(4), def_val=IS_ALUMODE_INVERTED) IS_CARRYIN_INVERTED_BIN = self._sig("IS_CARRYIN_INVERTED_BIN", def_val=IS_CARRYIN_INVERTED) IS_CLK_INVERTED_BIN = self._sig("IS_CLK_INVERTED_BIN", def_val=IS_CLK_INVERTED) IS_INMODE_INVERTED_BIN = self._sig("IS_INMODE_INVERTED_BIN", Bits(5), def_val=IS_INMODE_INVERTED) IS_OPMODE_INVERTED_BIN = self._sig("IS_OPMODE_INVERTED_BIN", Bits(7), def_val=IS_OPMODE_INVERTED) a_o_mux = self._sig("a_o_mux", Bits(30)) qa_o_mux = self._sig("qa_o_mux", Bits(30)) qa_o_reg1 = self._sig("qa_o_reg1", Bits(30)) qa_o_reg2 = self._sig("qa_o_reg2", Bits(30)) qacout_o_mux = self._sig("qacout_o_mux", Bits(30)) # new qinmode_o_mux = self._sig("qinmode_o_mux", Bits(5)) qinmode_o_reg = self._sig("qinmode_o_reg", Bits(5)) # new a_preaddsub = self._sig("a_preaddsub", Bits(25)) b_o_mux = self._sig("b_o_mux", Bits(18)) qb_o_mux = self._sig("qb_o_mux", Bits(18)) qb_o_reg1 = self._sig("qb_o_reg1", Bits(18)) qb_o_reg2 = self._sig("qb_o_reg2", Bits(18)) qbcout_o_mux = self._sig("qbcout_o_mux", Bits(18)) qcarryinsel_o_mux = self._sig("qcarryinsel_o_mux", Bits(3)) qcarryinsel_o_reg1 = self._sig("qcarryinsel_o_reg1", Bits(3)) # new #d_o_mux = self._sig("d_o_mux", Bits(D_W)) qd_o_mux = self._sig("qd_o_mux", Bits(D_W)) qd_o_reg1 = self._sig("qd_o_reg1", Bits(D_W)) qmult_o_mux = self._sig("qmult_o_mux", Bits(A_MULT_W + B_MULT_W)) qmult_o_reg = self._sig("qmult_o_reg", Bits(A_MULT_W + B_MULT_W)) # 42:0 qc_o_mux = self._sig("qc_o_mux", Bits(48)) qc_o_reg1 = self._sig("qc_o_reg1", Bits(48)) qp_o_mux = self._sig("qp_o_mux", Bits(48)) qp_o_reg1 = self._sig("qp_o_reg1", Bits(48)) qx_o_mux = self._sig("qx_o_mux", Bits(48)) qy_o_mux = self._sig("qy_o_mux", Bits(48)) qz_o_mux = self._sig("qz_o_mux", Bits(48)) qopmode_o_mux = self._sig("qopmode_o_mux", Bits(7)) qopmode_o_reg1 = self._sig("qopmode_o_reg1", Bits(7)) qcarryin_o_mux0 = self._sig("qcarryin_o_mux0") qcarryin_o_reg0 = self._sig("qcarryin_o_reg0") qcarryin_o_mux7 = self._sig("qcarryin_o_mux7") qcarryin_o_reg7 = self._sig("qcarryin_o_reg7") qcarryin_o_mux = self._sig("qcarryin_o_mux") qalumode_o_mux = self._sig("qalumode_o_mux", Bits(4)) qalumode_o_reg1 = self._sig("qalumode_o_reg1", Bits(4)) self.invalid_opmode = self._sig("invalid_opmode", def_val=1) self.opmode_valid_flag = opmode_valid_flag = self._sig( "opmode_valid_flag", def_val=1) # reg [47:0] alu_o; alu_o = self._sig("alu_o", Bits(48)) qmultsignout_o_reg = self._sig("qmultsignout_o_reg") multsignout_o_mux = self._sig("multsignout_o_mux") multsignout_o_opmode = self._sig("multsignout_o_opmode") pdet_o_mux = self._sig("pdet_o_mux") pdetb_o_mux = self._sig("pdetb_o_mux") the_pattern = self._sig("the_pattern", Bits(48)) the_mask = self._sig("the_mask", Bits(48), def_val=0) carrycascout_o = self._sig("carrycascout_o") the_auto_reset_patdet = self._sig("the_auto_reset_patdet") carrycascout_o_reg = self._sig("carrycascout_o_reg", def_val=0) carrycascout_o_mux = self._sig("carrycascout_o_mux", def_val=0) # CR 588861 carryout_o_reg = self._sig("carryout_o_reg", Bits(4), def_val=0) carryout_o_mux = self._sig("carryout_o_mux", Bits(4)) carryout_x_o = self._sig("carryout_x_o", Bits(4)) pdet_o = self._sig("pdet_o") pdetb_o = self._sig("pdetb_o") pdet_o_reg1 = self._sig("pdet_o_reg1") pdet_o_reg2 = self._sig("pdet_o_reg2") pdetb_o_reg1 = self._sig("pdetb_o_reg1") pdetb_o_reg2 = self._sig("pdetb_o_reg2") overflow_o = self._sig("overflow_o") underflow_o = self._sig("underflow_o") mult_o = self._sig("mult_o", Bits(A_MULT_W + B_MULT_W)) # reg [(MSB_A_MULT+MSB_B_MULT+1):0] mult_o; // 42:0 # new ad_addsub = self._sig("ad_addsub", Bits(A_MULT_W)) ad_mult = self._sig("ad_mult", Bits(A_MULT_W)) qad_o_reg1 = self._sig("qad_o_reg1", Bits(A_MULT_W)) qad_o_mux = self._sig("qad_o_mux", Bits(A_MULT_W)) b_mult = self._sig("b_mult", Bits(B_MULT_W)) # cci_drc_msg = self._sig("cci_drc_msg", def_val=0b0) # cis_drc_msg = self._sig("cis_drc_msg", def_val=0b0) opmode_in = self._sig("opmode_in", Bits(OPMODE_W)) alumode_in = self._sig("alumode_in", Bits(ALUMODE_W)) carryin_in = self._sig("carryin_in") clk_in = self._sig("clk_in") inmode_in = self._sig("inmode_in", Bits(INMODE_W)) #*** Y mux # 08-06-08 # IR 478378 y_mac_cascd = rename_signal( self, qopmode_o_mux[7:4]._eq(0b100)._ternary(replicate(48, MULTSIGNIN), Bits(48).from_py(mask(48))), "y_mac_cascd") #--#################################################################### #--##### ALU ##### #--#################################################################### co = self._sig("co", Bits(ALU_FULL_W)) s = self._sig("s", Bits(ALU_FULL_W)) comux = self._sig("comux", Bits(ALU_FULL_W)) smux = self._sig("smux", Bits(ALU_FULL_W)) carryout_o = self._sig("carryout_o", Bits(CARRYOUT_W)) # FINAL ADDER s0 = rename_signal( self, Concat(BIT.from_py(0), comux[11:0], qcarryin_o_mux) + Concat(BIT.from_py(0), smux[12:0]), "s0") cout0 = rename_signal(self, comux[11] + s0[12], "cout0") C1 = rename_signal( self, BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s0[12], "C1") co11_lsb = rename_signal( self, BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[11], "co11_lsb") s1 = rename_signal( self, Concat(BIT.from_py(0), comux[23:12], co11_lsb) + Concat(BIT.from_py(0), smux[24:12]) + Concat(Bits(12).from_py(0), C1), "s1") cout1 = rename_signal(self, comux[23] + s1[12], "cout1") C2 = rename_signal( self, BIT.from_py(0b0) if (USE_SIMD in ["TWO24", "FOUR12"]) else s1[12], "C2") co23_lsb = rename_signal( self, BIT.from_py(0b0) if (USE_SIMD in ["TWO24", "FOUR12"]) else comux[23], "co23_lsb") s2 = rename_signal( self, Concat(BIT.from_py(0), comux[35:24], co23_lsb) + Concat(BIT.from_py(0), smux[36:24]) + Concat(Bits(12).from_py(0), C2), "s2") cout2 = rename_signal(self, comux[35] + s2[12], "cout2") C3 = rename_signal( self, BIT.from_py(0b0) if USE_SIMD == "FOUR12" else s2[12], "C3") co35_lsb = rename_signal( self, BIT.from_py(0b0) if USE_SIMD == "FOUR12" else comux[35], "co35_lsb") s3 = rename_signal( self, Concat(BIT.from_py(0), comux[48:36], co35_lsb) + Concat(Bits(2).from_py(0), smux[48:36]) + Concat(Bits(13).from_py(0), C3), "s3") cout3 = rename_signal(self, s3[12], "cout3") #cout4 = rename_signal(self, s3[13], "cout4") qcarryin_o_mux_tmp = self._sig("qcarryin_o_mux_tmp") ACOUT(qacout_o_mux) BCOUT(qbcout_o_mux) CARRYCASCOUT(carrycascout_o_mux) CARRYOUT(carryout_x_o) MULTSIGNOUT(multsignout_o_mux) OVERFLOW(overflow_o) P(qp_o_mux) PCOUT(qp_o_mux) PATTERNDETECT(pdet_o_mux) PATTERNBDETECT(pdetb_o_mux) UNDERFLOW(underflow_o) alumode_in(ALUMODE ^ IS_ALUMODE_INVERTED_BIN) carryin_in(CARRYIN ^ IS_CARRYIN_INVERTED_BIN) clk_in(CLK ^ IS_CLK_INVERTED_BIN) inmode_in(INMODE ^ IS_INMODE_INVERTED_BIN) opmode_in(OPMODE ^ IS_OPMODE_INVERTED_BIN) #********************************************************* #********** INMODE signal registering ************ #********************************************************* If( clk_in._onRisingEdge(), If(RSTINMODE, qinmode_o_reg(0b0)).Elif(CEINMODE, qinmode_o_reg(inmode_in))) if INMODEREG == 0: qinmode_o_mux(inmode_in) elif INMODEREG == 1: qinmode_o_mux(qinmode_o_reg) else: raise AssertionError() if A_INPUT == "DIRECT": a_o_mux(A) elif A_INPUT == "CASCADE": a_o_mux(ACIN) else: raise AssertionError() if AREG in (1, 2): If( clk_in._onRisingEdge(), If(RSTA, qa_o_reg1(0b0), qa_o_reg2(0b0)).Else( If(CEA1, qa_o_reg1(a_o_mux)), If( CEA2, qa_o_reg2(a_o_mux if AREG == 1 else qa_o_reg1 if AREG == 2 else None)))) else: qa_o_reg1(None) if AREG == 0: qa_o_mux(a_o_mux) elif AREG == 1: qa_o_mux(qa_o_reg2) elif AREG == 2: qa_o_mux(qa_o_reg2) else: raise AssertionError() if ACASCREG == 1: qacout_o_mux(qa_o_reg1 if AREG == 2 else qa_o_mux) elif ACASCREG == 0: qacout_o_mux(qa_o_mux) elif ACASCREG == 2: qacout_o_mux(qa_o_mux) else: raise AssertionError() If(qinmode_o_mux[1], a_preaddsub(0b0)).Elif( qinmode_o_mux[0], a_preaddsub(qa_o_reg1[25:0]), ).Else(a_preaddsub(qa_o_mux[25:0]), ) if B_INPUT == "DIRECT": b_o_mux(B) elif B_INPUT == "CASCADE": b_o_mux(BCIN) else: raise AssertionError() if BREG in (1, 2): If( clk_in._onRisingEdge(), If(RSTB, qb_o_reg1(0b0), qb_o_reg2(0b0)).Else( If(CEB1, qb_o_reg1(b_o_mux)), If( CEB2, qb_o_reg2(b_o_mux if BREG == 1 else qb_o_reg1 if BREG == 1 else None)))) else: qb_o_reg1(None) if BREG == 0: qb_o_mux(b_o_mux) elif BREG == 1: qb_o_mux(qb_o_reg2) elif BREG == 2: qb_o_mux(qb_o_reg2) else: raise AssertionError() if BCASCREG == 1: qbcout_o_mux(qb_o_reg1 if BREG == 2 else qb_o_mux) elif BCASCREG == 0: qbcout_o_mux(qb_o_mux) elif BCASCREG == 2: qbcout_o_mux(qb_o_mux) else: raise AssertionError() b_mult(qinmode_o_mux[4]._ternary(qb_o_reg1, qb_o_mux)) #********************************************************* #*** Input register C with 1 level deep of register #********************************************************* If(clk_in._onRisingEdge(), If(RSTC, qc_o_reg1(0b0)).Elif(CEC, qc_o_reg1(C))) if CREG == 0: qc_o_mux(C) elif CREG == 1: qc_o_mux(qc_o_reg1) else: raise AssertionError() #********************************************************* #*** Input register D with 1 level deep of register #********************************************************* If(clk_in._onRisingEdge(), If(RSTD, qd_o_reg1(0b0)).Elif(CED, qd_o_reg1(D))) if DREG == 0: qd_o_mux(D) elif DREG == 1: qd_o_mux(qd_o_reg1) else: raise AssertionError() ad_addsub(qinmode_o_mux[3]._ternary( -a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0), a_preaddsub + qinmode_o_mux[2]._ternary(qd_o_mux, 0b0))) If(clk_in._onRisingEdge(), If(RSTD, qad_o_reg1(0b0)).Elif(CEAD, qad_o_reg1(ad_addsub))) if ADREG == 0: qad_o_mux(ad_addsub) elif ADREG == 1: qad_o_mux(qad_o_reg1) else: raise AssertionError() ad_mult(qad_o_mux if USE_DPORT == "TRUE" else a_preaddsub) #********************************************************* #********************************************************* #*************** 25x18 Multiplier *************** #********************************************************* # 05/26/05 -- FP -- Added warning for invalid mult when USE_MULT=NONE # SIMD=FOUR12 and SIMD=TWO24 # Made mult_o to be "X" if USE_MULT == "NONE" or USE_SIMD != "ONE48": mult_o(0b0) else: If(CARRYINSEL._eq(0b010), mult_o(None)).Else( mult_o( replicate(18, ad_mult[24])._concat(ad_mult[25:0]) * replicate(25, b_mult[17])._concat(b_mult))) If(clk_in._onRisingEdge(), If(RSTM, qmult_o_reg(0b0)).Elif(CEM, qmult_o_reg(mult_o))) If(qcarryinsel_o_mux._eq(0b010), qmult_o_mux(None)).Else( qmult_o_mux(qmult_o_reg if MREG == 1 else mult_o)) #*** X mux # ask jmt # add post 2014.4 # else Switch(qopmode_o_mux[2:0])\ .Case(0b00, # X_SEL.ZERO qx_o_mux(0b0))\ .Case(0b01, # X_SEL.M qx_o_mux(replicate(5, qmult_o_mux[A_MULT_W + B_MULT_W - 1])._concat(qmult_o_mux)))\ .Case(0b10, # X_SEL.P qx_o_mux(qp_o_mux if PREG == 1 else None))\ .Case(0b11, # X_SEL.A_B qx_o_mux(None) if USE_MULT == "MULTIPLY" and ( (AREG == 0 and BREG == 0 and MREG == 0) or (AREG == 0 and BREG == 0 and PREG == 0) or (MREG == 0 and PREG == 0)) # print("OPMODE Input Warning : The OPMODE[1:0] %b to DSP48E1 instance %m is invalid when using attributes USE_MULT = MULTIPLY at %.3f ns. Please set USE_MULT to either NONE or DYNAMIC.", qopmode_o_mux[slice(2, 0)], sim.now // 1000.000000) else qx_o_mux(qa_o_mux[A_W:0]._concat(qb_o_mux[B_W:0])) ) # add post 2014.4 Switch(qopmode_o_mux[4:2])\ .Case(0b00, qy_o_mux(0b0))\ .Case(0b01, qy_o_mux(0b0))\ .Case(0b10, qy_o_mux(y_mac_cascd))\ .Case(0b11, qy_o_mux(qc_o_mux)) #*** Z mux # ask jmt # add post 2014.4 Switch(qopmode_o_mux[7:4])\ .Case(0b000, qz_o_mux(0b0))\ .Case(0b001, qz_o_mux(PCIN))\ .Case(0b010, qz_o_mux(qp_o_mux))\ .Case(0b011, qz_o_mux(qc_o_mux))\ .Case(0b100, qz_o_mux(qp_o_mux))\ .Case(0b101, qz_o_mux(replicate(17, PCIN[47])._concat(PCIN[48:17])))\ .Case(0b110, qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17])))\ .Case(0b111, qz_o_mux(replicate(17, qp_o_mux[47])._concat(qp_o_mux[48:17]))) #*** CarryInSel and OpMode with 1 level of register If( clk_in._onRisingEdge(), If(RSTCTRL, qcarryinsel_o_reg1(0b0), qopmode_o_reg1(0b0)).Elif(CECTRL, qcarryinsel_o_reg1(CARRYINSEL), qopmode_o_reg1(opmode_in))) if CARRYINSELREG == 0: qcarryinsel_o_mux(CARRYINSEL) elif CARRYINSELREG == 1: qcarryinsel_o_mux(qcarryinsel_o_reg1) else: raise AssertionError() # CR 219047 (3) # If(qcarryinsel_o_mux._eq(0b010), # If(~((cci_drc_msg._eq(0b1) | qopmode_o_mux._eq(0b1001000)) | (MULTSIGNIN._eq(0b0) & CARRYCASCIN._eq(0b0))), # #print("DRC warning : CARRYCASCIN can only be used in the current DSP48E1 instance %m if the previous DSP48E1 is performing a two input ADD or SUBTRACT operation, or the current DSP48E1 is configured in the MAC extend opmode 7'b1001000 at %.3f ns.", sim.now // 1000.000000), # cci_drc_msg(0b1) # ), # If(~((qopmode_o_mux[4:0] != 0b0101)._isOn())._isOn(), # #print("DRC warning : CARRYINSEL is set to 010 with OPMODE set to multiplication (xxx0101). This is an illegal mode and may show deviation between simulation results and hardware behavior. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000) # ), # If(~cis_drc_msg._eq(0b1), # #print("DRC warning : CARRYINSEL is set to 010 with OPMODEREG set to 0. This causes unknown values after reset occurs. It is suggested to use OPMODEREG = 1 when cascading large adders. DSP48E1 instance %m at %.3f ns.", sim.now // 1000.000000), # cis_drc_msg(0b1) # ) if OPMODEREG == 0b1 else [] # ) if OPMODEREG == 0: qopmode_o_mux(opmode_in) elif OPMODEREG == 1: qopmode_o_mux(qopmode_o_reg1) else: raise AssertionError() #*** ALUMODE with 1 level of register If( clk_in._onRisingEdge(), If(RSTALUMODE, qalumode_o_reg1(0b0)).Elif(CEALUMODE, qalumode_o_reg1(alumode_in))) if ALUMODEREG == 0: qalumode_o_mux(alumode_in) elif ALUMODEREG == 1: qalumode_o_mux(qalumode_o_reg1) else: raise AssertionError() def deassign_xyz_mux_if_PREG_eq_1(): if PREG != 1: return self.display_invalid_opmode() else: return self.deassign_xyz_mux() def DCR_check_logic_modes(): # -- LOGIC MODES DRC return If( In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux), self.deassign_xyz_mux() ).Elif( In(qopmode_o_mux, LOGIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1), deassign_xyz_mux_if_PREG_eq_1(), ).Else( # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000) ) # display_invalid_opmode arith_mode_tmp = qopmode_o_mux._concat(qcarryinsel_o_mux) # no check at first 100ns Switch(qalumode_o_mux[4:2])\ .Case(0b00, # -- ARITHMETIC MODES DRC If(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux), self.deassign_xyz_mux() ).Elif(In(arith_mode_tmp, ARITHMETIC_MODES_DRC_deassign_xyz_mux_if_PREG_eq_1), deassign_xyz_mux_if_PREG_eq_1() ).Else( # CR 444150 # If(qopmode_o_mux._concat(qcarryinsel_o_mux)._eq(0b0000000010)._isOn() & (OPMODEREG._eq(1)._isOn() & CARRYINSELREG._eq(0)._isOn())._isOn(), # print("DRC warning : CARRYINSELREG is set to %d. It is required to have CARRYINSELREG be set to 1 to match OPMODEREG, in order to ensure that the simulation model will match the hardware behavior in all use cases.", CARRYINSELREG) # ), # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is either invalid or the CARRYINSEL %b for that specific OPMODE is invalid at %.3f ns. This warning may be due to a mismatch in the OPMODEREG and CARRYINSELREG attribute settings. It is recommended that OPMODEREG and CARRYINSELREG always be set to the same value. ", qopmode_o_mux, qcarryinsel_o_mux, sim.now // 1000.000000) ) )\ .Case(0b01, DCR_check_logic_modes() )\ .Case(0b11, DCR_check_logic_modes() )\ .Default( # print("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, sim.now // 1000.000000) ) If( qalumode_o_mux[0], co(qx_o_mux & qy_o_mux | ~qz_o_mux & qy_o_mux | qx_o_mux & ~qz_o_mux), s(~qz_o_mux ^ qx_o_mux ^ qy_o_mux)).Else( co(qx_o_mux & qy_o_mux | qz_o_mux & qy_o_mux | qx_o_mux & qz_o_mux), s(qz_o_mux ^ qx_o_mux ^ qy_o_mux)) If( qalumode_o_mux[2], comux(0), ).Else(comux(co), ) smux(qalumode_o_mux[3]._ternary(co, s)) carryout_o_hw = self._sig("carryout_o_hw", Bits(CARRYOUT_W)) carryout_o_hw[0]( (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout0, cout0)) carryout_o_hw[1]( (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout1, cout1)) carryout_o_hw[2]( (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout2, cout2)) carryout_o_hw[3]( (qalumode_o_mux[0] & qalumode_o_mux[1])._ternary(~cout3, cout3)) alu_o(qalumode_o_mux[1]._ternary( ~Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0]), Concat(s3[12:0], s2[12:0], s1[12:0], s0[12:0]))) carrycascout_o(cout3) multsignout_o_opmode( (qopmode_o_mux[7:4]._eq(0b100))._ternary(MULTSIGNIN, qmult_o_mux[42])) If( (qopmode_o_mux[4:0]._eq(0b0101) | (qalumode_o_mux[4:2] != 0b00)), carryout_o[3](None), carryout_o[2](None), carryout_o[1](None), carryout_o[0](None), ).Else( carryout_o[3](carryout_o_hw[3]), carryout_o[2](carryout_o_hw[2] if USE_SIMD == "FOUR12" else None), carryout_o[1](carryout_o_hw[1] if USE_SIMD in ["TWO24", "FOUR12"] else None), carryout_o[0](carryout_o_hw[0] if USE_SIMD == "FOUR12" else None), ) #--########################### END ALU ################################ #*** CarryIn Mux and Register #------- input 0 If( clk_in._onRisingEdge(), If(RSTALLCARRYIN, qcarryin_o_reg0(0b0)).Elif(CECARRYIN, qcarryin_o_reg0(carryin_in))) if CARRYINREG == 0: qcarryin_o_mux0(carryin_in) elif CARRYINREG == 1: qcarryin_o_mux0(qcarryin_o_reg0) else: raise AssertionError() #------- input 7 If( clk_in._onRisingEdge(), If(RSTALLCARRYIN, qcarryin_o_reg7(0b0)).Elif( CEM, qcarryin_o_reg7(ad_mult[24]._eq(b_mult[17])))) if MREG == 0: qcarryin_o_mux7(ad_mult[24]._eq(b_mult[17])) elif MREG == 1: qcarryin_o_mux7(qcarryin_o_reg7) else: raise ValueError( "MREG is set to %d. Legal values for this attribute are 0 or 1.", MREG) Switch(qcarryinsel_o_mux)\ .Case(CARRYIN_SEL.CARRYIN.value, qcarryin_o_mux_tmp(qcarryin_o_mux0))\ .Case(CARRYIN_SEL.PCIN_47_n.value, qcarryin_o_mux_tmp(~PCIN[47]))\ .Case(CARRYIN_SEL.CARRYCASCIN.value, qcarryin_o_mux_tmp(CARRYCASCIN))\ .Case(CARRYIN_SEL.PCIN_47.value, qcarryin_o_mux_tmp(PCIN[47]))\ .Case(CARRYIN_SEL.CARRYCASCOUT.value, qcarryin_o_mux_tmp(carrycascout_o_mux))\ .Case(CARRYIN_SEL.P_47_n.value, qcarryin_o_mux_tmp(~qp_o_mux[47]))\ .Case(CARRYIN_SEL.A_27_eq_B_17.value, qcarryin_o_mux_tmp(qcarryin_o_mux7))\ .Case(CARRYIN_SEL.P_47.value, qcarryin_o_mux_tmp(qp_o_mux[47])) # disable carryin when performing logic operation If(qalumode_o_mux[3] | qalumode_o_mux[2], qcarryin_o_mux(0b0)).Else(qcarryin_o_mux(qcarryin_o_mux_tmp)) if AUTORESET_PATDET == "RESET_MATCH": the_auto_reset_patdet(pdet_o_reg1) elif AUTORESET_PATDET == "RESET_NOT_MATCH": the_auto_reset_patdet(pdet_o_reg2 & ~pdet_o_reg1) else: the_auto_reset_patdet(0) #--#################################################################### #--##### CARRYOUT, CARRYCASCOUT. MULTSIGNOUT and PCOUT ###### #--#################################################################### #*** register with 1 level of register If( clk_in._onRisingEdge(), If(RSTP._isOn() | the_auto_reset_patdet._isOn(), carryout_o_reg(0b0), carrycascout_o_reg(0b0), qmultsignout_o_reg(0b0), qp_o_reg1(0b0)).Elif(CEP, carryout_o_reg(carryout_o), carrycascout_o_reg(carrycascout_o), qmultsignout_o_reg(multsignout_o_opmode), qp_o_reg1(alu_o))) if PREG == 0: carryout_o_mux(carryout_o) carrycascout_o_mux(carrycascout_o) multsignout_o_mux(multsignout_o_opmode) qp_o_mux(alu_o) elif PREG == 1: carryout_o_mux(carryout_o_reg) carrycascout_o_mux(carrycascout_o_reg) multsignout_o_mux(qmultsignout_o_reg) qp_o_mux(qp_o_reg1) else: raise AssertionError() carryout_x_o( Concat( carryout_o_mux[3], carryout_o_mux[2] if USE_SIMD == "FOUR12" else BIT.from_py(None), carryout_o_mux[1] if USE_SIMD in ["TWO24", "FOUR12"] else BIT.from_py(None), carryout_o_mux[0] if USE_SIMD == "FOUR12" else BIT.from_py(None), )) the_pattern(PATTERN if SEL_PATTERN == "PATTERN" else qc_o_mux) # selet mask if USE_PATTERN_DETECT == "NO_PATDET": the_mask(mask(48)) elif SEL_MASK == "MASK": the_mask(MASK) elif SEL_MASK == "C": the_mask(qc_o_mux) elif SEL_MASK == "ROUNDING_MODE1": the_mask(~qc_o_mux << 1) elif SEL_MASK == "ROUNDING_MODE2": the_mask(~qc_o_mux << 2) else: raise AssertionError() If( opmode_valid_flag, pdet_o(And(*(~(the_pattern ^ alu_o) | the_mask))), pdetb_o(And(*(the_pattern ^ alu_o | the_mask))), ).Else( pdet_o(None), pdetb_o(None), ) pdet_o_mux(pdet_o_reg1 if PREG == 1 else pdet_o) pdetb_o_mux(pdetb_o_reg1 if PREG == 1 else pdetb_o) #*** Output register PATTERN DETECT and UNDERFLOW / OVERFLOW If( clk_in._onRisingEdge(), If(RSTP._isOn() | the_auto_reset_patdet._isOn(), pdet_o_reg1(0b0), pdet_o_reg2(0b0), pdetb_o_reg1(0b0), pdetb_o_reg2(0b0)).Elif(CEP, pdet_o_reg2(pdet_o_reg1), pdet_o_reg1(pdet_o), pdetb_o_reg2(pdetb_o_reg1), pdetb_o_reg1(pdetb_o))) if PREG == 1 or USE_PATTERN_DETECT == "PATDET": overflow_o(pdet_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1), underflow_o(pdetb_o_reg2 & ~pdet_o_reg1 & ~pdetb_o_reg1) else: overflow_o(None), underflow_o(None)
def _rx_logic(self, rmii: Rmii, rx: VldSyncedDataErrLast, D_W: int, RMII_W: int, clk_edge): CNTR_W = D_W // RMII_W clk = (rmii.ref_clk, clk_edge) # register for all input signals din = self._reg("rx_din", Bits(RMII_W), clk=clk) din_vld = self._reg("rx_din_vld", clk=clk, def_val=0) din(rmii.rx.d) din_vld(rmii.rx.crs_dv) # register for temporary RX byte reg0 = self._reg("rx_reg0", Bits(D_W, signed=False), def_val=0, clk=clk) # register for Rx byte for clock edge sync reg1 = self._reg("rx_reg1", Bits(D_W, signed=False), def_val=0, clk=rmii.ref_clk) reg1_vld = self._reg("rx_reg1_vld", def_val=0) # one hot counter with rotating 1 cntr = self._reg("rx_cntr", Bits(CNTR_W, signed=False), def_val=1, clk=clk) # counter of preambule bytes preamble_cnt = self._reg("rx_preamble_cntr", Bits(log2ceil(8), signed=False), clk=clk) st_t = HEnum("rx_state_t", ["skip0", "preamble_and_sfd", "data", "error"]) st = self._reg("rx_state", st_t, def_val=st_t.skip0, clk=clk) last_in_B = cntr[CNTR_W - 1] & din_vld actual_rx_B = self._sig("rx_actual_val", dtype=Bits(8)) actual_rx_B(Concat(din, reg0[:RMII_W])) Switch(st)\ .Case(st_t.skip0, If(din_vld & (din != 0), st(st_t.preamble_and_sfd), preamble_cnt(8-1), ), ).Case(st_t.preamble_and_sfd, If(last_in_B, If(preamble_cnt._eq(0), If(actual_rx_B != ETH.SFD, st(st_t.error) ).Else( st(st_t.data) ) ).Elif(actual_rx_B != ETH.PREAMBLE_1B, st(st_t.error), ), preamble_cnt(preamble_cnt - 1) ) ).Case(st_t.error, If(~din_vld, st(st_t.skip0), ) ).Case(st_t.data, If(cntr[CNTR_W - 1] & ~din_vld, st(st_t.skip0) ) ) # bit collection logic If(st._eq(st_t.skip0), cntr(1<<1), reg0(Concat(din, Bits(D_W - RMII_W).from_py(0))), ).Elif(In(st, [st_t.preamble_and_sfd, st_t.data]), # shift in LSB first # :note: only D_W - RMII_W bits is captured in reg0 reg0(Concat(din, reg0[:RMII_W])), cntr(rol(cntr, 1)), ) reg1_vld(st._eq(st_t.data) & last_in_B) If(reg1_vld.next, reg1(actual_rx_B), ) err = st._eq(st_t.error) If(err, rx.data(None), ).Else( rx.data(reg1) ) rx.err(err) rx.last(~din_vld) rx.vld(reg1_vld | st._eq(st_t.error))
def _impl(self): propagateClkRstn(self) r, s = self._reg, self._sig req = self.rDatapump.req f = self.dataFifo dIn = self.rDatapump.r dBuffIn = f.dataIn ALIGN_BITS = self.addrAlignBits() ID = self.ID BUFFER_CAPACITY = self.BUFFER_CAPACITY BURST_LEN = BUFFER_CAPACITY // 2 ID_LAST = self.ID_LAST bufferHasSpace = s("bufferHasSpace") bufferHasSpace(f.size < (BURST_LEN + 1)) # we are counting base next addr as item as well inBlock_t = Bits(log2ceil(self.ITEMS_IN_BLOCK + 1)) ringSpace_t = Bits(self.PTR_WIDTH) downloadPending = r("downloadPending", def_val=0) baseIndex = r("baseIndex", Bits(self.ADDR_WIDTH - ALIGN_BITS)) inBlockRemain = r("inBlockRemain_reg", inBlock_t, def_val=self.ITEMS_IN_BLOCK) self.inBlockRemain(inBlockRemain) # Logic of tail/head rdPtr = r("rdPtr", ringSpace_t, def_val=0) wrPtr = r("wrPtr", ringSpace_t, def_val=0) If(self.wrPtr.dout.vld, wrPtr(self.wrPtr.dout.data)) self.wrPtr.din(wrPtr) self.rdPtr.din(rdPtr) # this means items are present in memory hasSpace = s("hasSpace") hasSpace(wrPtr != rdPtr) doReq = s("doReq") doReq(bufferHasSpace & hasSpace & ~downloadPending & req.rd) req.rem(0) self.dataOut(f.dataOut) # logic of baseAddr and baseIndex baseAddr = Concat(baseIndex, Bits(ALIGN_BITS).from_py(0)) req.addr(baseAddr) self.baseAddr.din(baseAddr) dataAck = dIn.valid & In(dIn.id, [ID, ID_LAST]) & dBuffIn.rd If(self.baseAddr.dout.vld, baseIndex(self.baseAddr.dout.data[:ALIGN_BITS])).Elif( dataAck & downloadPending, If(dIn.last & dIn.id._eq(ID_LAST), baseIndex(dIn.data[self.ADDR_WIDTH:ALIGN_BITS])).Else( baseIndex(baseIndex + 1))) sizeByPtrs = s("sizeByPtrs", ringSpace_t) sizeByPtrs(wrPtr - rdPtr) inBlockRemain_asPtrSize = fitTo(inBlockRemain, sizeByPtrs) constraingSpace = s("constraingSpace", ringSpace_t) If(inBlockRemain_asPtrSize < sizeByPtrs, constraingSpace(inBlockRemain_asPtrSize)).Else( constraingSpace(sizeByPtrs)) constrainedByInBlockRemain = s("constrainedByInBlockRemain") constrainedByInBlockRemain( fitTo(sizeByPtrs, inBlockRemain) >= inBlockRemain) If( constraingSpace > BURST_LEN, # download full burst req.id(ID), req.len(BURST_LEN - 1), If(doReq, inBlockRemain(inBlockRemain - BURST_LEN)) ).Elif( constrainedByInBlockRemain & (inBlockRemain < BURST_LEN), # we know that sizeByPtrs <= inBlockRemain thats why we can resize it # we will download next* as well req.id(ID_LAST), req.len(constraingSpace, fit=True), If(doReq, inBlockRemain(self.ITEMS_IN_BLOCK))).Else( # download data leftover req.id(ID), req.len(constraingSpace - 1, fit=True), If( doReq, inBlockRemain(inBlockRemain - fitTo(constraingSpace, inBlockRemain)))) # logic of req dispatching If(downloadPending, req.vld(0), If(dataAck & dIn.last, downloadPending(0))).Else( req.vld(bufferHasSpace & hasSpace), If(req.rd & bufferHasSpace & hasSpace, downloadPending(1))) # into buffer pushing logic dBuffIn.data(dIn.data) isMyData = s("isMyData") isMyData(dIn.id._eq(ID) | (~dIn.last & dIn.id._eq(ID_LAST))) If(self.rdPtr.dout.vld, rdPtr(self.rdPtr.dout.data)).Else( If(dIn.valid & downloadPending & dBuffIn.rd & isMyData, rdPtr(rdPtr + 1))) # push data into buffer and increment rdPtr StreamNode(masters=[dIn], slaves=[dBuffIn], extraConds={ dIn: downloadPending, dBuffIn: (dIn.id._eq(ID) | (dIn.id._eq(ID_LAST) & ~dIn.last)) & downloadPending }).sync()