def __init__(self, dut, ta, tt):
     self.clk_i = dut.clk_i
     self.rst_ni = dut.rst_ni
     self.data_i = dut.data_i
     self.last_i = dut.last_i
     self.vld_i = dut.vld_i
     self.rdy_o = dut.rdy_o
     self.znz_data_o = dut.znz_data_o
     self.znz_vld_o = dut.znz_vld_o
     self.znz_rdy_i = dut.znz_rdy_i
     self.bpc_data_o = dut.bpc_data_o
     self.bpc_vld_o = dut.bpc_vld_o
     self.bpc_rdy_i = dut.bpc_rdy_i
     self.ta = ta
     self.tt = tt
     self.in_drv = HandshakeInputDriver(clk=self.clk_i,
                                        signals=[self.data_i, self.last_i],
                                        vld=self.vld_i,
                                        rdy=self.rdy_o,
                                        ta=self.ta,
                                        tt=self.tt)
     self.bpc_out_drv = HandshakeOutputDriver(clk=self.clk_i,
                                              vld=self.bpc_vld_o,
                                              rdy=self.bpc_rdy_i,
                                              ta=self.ta,
                                              tt=self.tt)
     self.znz_out_drv = HandshakeOutputDriver(clk=self.clk_i,
                                              vld=self.znz_vld_o,
                                              rdy=self.znz_rdy_i,
                                              ta=self.ta,
                                              tt=self.tt)
     self.apply_defaults()
class BPCDecoderDriver:
    def __init__(self, dut, ta, tt):
        self.clk_i = dut.clk_i
        self.rst_ni = dut.rst_ni
        self.bpc_i = dut.bpc_i
        self.bpc_vld_i = dut.bpc_vld_i
        self.bpc_rdy_o = dut.bpc_rdy_o
        self.data_o = dut.data_o
        self.vld_o = dut.vld_o
        self.rdy_i = dut.rdy_i
        self.clr_i = dut.clr_i
        self.dut = dut
        self.ta = ta
        self.tt = tt
        self.bpc_i_drv = HandshakeInputDriver(clk=self.clk_i, signals=[self.bpc_i], vld=self.bpc_vld_i, rdy=self.bpc_rdy_o, ta=self.ta, tt=self.tt)
        self.out_drv = HandshakeOutputDriver(clk=self.clk_i, vld=self.vld_o, rdy=self.rdy_i, ta=self.ta, tt=self.tt)
        self.apply_defaults()

    def apply_defaults(self):
        self.bpc_i <= 0
        self.bpc_vld_i <= 0
        self.rdy_i <= 0
        self.clr_i <= 0


    @cocotb.coroutine
    def drive_input(self, values, tmin, tmax):
        # values: list of values to feed
        # tmin:   minimum # of clock cycles to wait between input applications
        # tmax:   maximum # of clock cycles to wait between applications
        assert self.rst_ni.value == 1, "BPCDecoderDriver Error: rst_ni is not high in drive_input!"
        for val in values:
            yield wait_cycles(self.clk_i, random.randint(tmin,tmax))
            yield self.bpc_i_drv.write_input(val)

    @cocotb.coroutine
    def read_outputs(self, num, tmin, tmax):
    #num: how many output values to read
    #tmin: minimum # of clock cycles to wait between reads
    #tmax: maximum # of clock cycles to wait between reads
        assert self.rst_ni.value == 1, "BPCEncoderDriver Error: rst_ni is not high in read_outputs!"
        k = 0
        for i in range(num):
            yield wait_cycles(self.clk_i, random.randint(tmin, tmax))
            yield self.out_drv.read_output()
            k+= 1
        return k

    @cocotb.coroutine
    def clear(self):
        yield apply_signal(dut.clr_i, 1, TA)
        yield wait_cycles(dut.clk_i, 1)
        yield apply_signal(dut.clr_i, 0, TA)
 def __init__(self, dut, ta, tt):
     self.clk_i = dut.clk_i
     self.rst_ni = dut.rst_ni
     self.bpc_i = dut.bpc_i
     self.bpc_vld_i = dut.bpc_vld_i
     self.bpc_last_i = dut.bpc_last_i
     self.bpc_rdy_o = dut.bpc_rdy_o
     self.znz_i = dut.znz_i
     self.znz_vld_i = dut.znz_vld_i
     self.znz_last_i = dut.znz_last_i
     self.znz_rdy_o = dut.znz_rdy_o
     self.data_o = dut.data_o
     self.last_o = dut.last_o
     self.vld_o = dut.vld_o
     self.rdy_i = dut.rdy_i
     self.num_words_i = dut.num_words_i
     self.num_words_vld_i = dut.num_words_vld_i
     self.num_words_rdy_o = dut.num_words_rdy_o
     self.dut = dut
     self.ta = ta
     self.tt = tt
     self.bpc_i_drv = HandshakeInputDriver(
         clk=self.clk_i,
         signals=[self.bpc_i, self.bpc_last_i],
         vld=self.bpc_vld_i,
         rdy=self.bpc_rdy_o,
         ta=self.ta,
         tt=self.tt)
     self.num_words_drv = HandshakeInputDriver(clk=self.clk_i,
                                               signals=[self.num_words_i],
                                               vld=self.num_words_vld_i,
                                               rdy=self.num_words_rdy_o,
                                               ta=self.ta,
                                               tt=self.tt)
     self.znz_i_drv = HandshakeInputDriver(
         clk=self.clk_i,
         signals=[self.znz_i, self.znz_last_i],
         vld=self.znz_vld_i,
         rdy=self.znz_rdy_o,
         ta=self.ta,
         tt=self.tt)
     self.out_drv = HandshakeOutputDriver(clk=self.clk_i,
                                          vld=self.vld_o,
                                          rdy=self.rdy_i,
                                          ta=self.ta,
                                          tt=self.tt)
class EBPCDecoderDriver:
    def __init__(self, dut, ta, tt):
        self.clk_i = dut.clk_i
        self.rst_ni = dut.rst_ni
        self.bpc_i = dut.bpc_i
        self.bpc_vld_i = dut.bpc_vld_i
        self.bpc_last_i = dut.bpc_last_i
        self.bpc_rdy_o = dut.bpc_rdy_o
        self.znz_i = dut.znz_i
        self.znz_vld_i = dut.znz_vld_i
        self.znz_last_i = dut.znz_last_i
        self.znz_rdy_o = dut.znz_rdy_o
        self.data_o = dut.data_o
        self.last_o = dut.last_o
        self.vld_o = dut.vld_o
        self.rdy_i = dut.rdy_i
        self.num_words_i = dut.num_words_i
        self.num_words_vld_i = dut.num_words_vld_i
        self.num_words_rdy_o = dut.num_words_rdy_o
        self.dut = dut
        self.ta = ta
        self.tt = tt
        self.bpc_i_drv = HandshakeInputDriver(
            clk=self.clk_i,
            signals=[self.bpc_i, self.bpc_last_i],
            vld=self.bpc_vld_i,
            rdy=self.bpc_rdy_o,
            ta=self.ta,
            tt=self.tt)
        self.num_words_drv = HandshakeInputDriver(clk=self.clk_i,
                                                  signals=[self.num_words_i],
                                                  vld=self.num_words_vld_i,
                                                  rdy=self.num_words_rdy_o,
                                                  ta=self.ta,
                                                  tt=self.tt)
        self.znz_i_drv = HandshakeInputDriver(
            clk=self.clk_i,
            signals=[self.znz_i, self.znz_last_i],
            vld=self.znz_vld_i,
            rdy=self.znz_rdy_o,
            ta=self.ta,
            tt=self.tt)
        self.out_drv = HandshakeOutputDriver(clk=self.clk_i,
                                             vld=self.vld_o,
                                             rdy=self.rdy_i,
                                             ta=self.ta,
                                             tt=self.tt)

    def apply_defaults(self):
        self.bpc_i <= 0
        self.bpc_vld_i <= 0
        self.bpc_last_i <= 0
        self.znz_i <= 0
        self.znz_vld_i <= 0
        self.znz_last_i <= 0
        self.num_words_i <= 0
        self.num_words_vld_i <= 0
        self.rdy_i <= 0

    @cocotb.coroutine
    def drive_bpc(self, values, last, tmin, tmax):
        # values: list of values to feed
        # last:   list of 'last' bits to feed
        # tmin:   minimum # of clock cycles to wait between input applications
        # tmax:   maximum # of clock cycles to wait between applications
        assert self.rst_ni.value == 1, "BPCDecoderDriver Error: rst_ni is not high in drive_bpc!"
        for inp in zip(values, last):
            yield wait_cycles(self.clk_i, random.randint(tmin, tmax))
            yield self.bpc_i_drv.write_input(inp)

    @cocotb.coroutine
    def drive_znz(self, values, last, tmin, tmax):
        # values: list of values to feed
        # last:   list of 'last' bits to feed
        # tmin:   minimum # of clock cycles to wait between input applications
        # tmax:   maximum # of clock cycles to wait between applications
        assert self.rst_ni.value == 1, "BPCDecoderDriver Error: rst_ni is not high in drive_znz!"
        for inp in zip(values, last):
            yield wait_cycles(self.clk_i, random.randint(tmin, tmax))
            yield self.znz_i_drv.write_input(inp)

    @cocotb.coroutine
    def write_num_words(self, n, tmin, tmax):
        # values: list of values to feed
        # tmin:   minimum # of clock cycles to wait between input applications
        # tmax:   maximum # of clock cycles to wait between applications
        assert self.rst_ni.value == 1, "BPCDecoderDriver Error: rst_ni is not high in write_num_words!"
        yield wait_cycles(self.clk_i, random.randint(tmin, tmax))
        yield self.num_words_drv.write_input(n)

    @cocotb.coroutine
    def read_outputs(self, num, tmin, tmax):
        #num: max number of output values to read
        #tmin: minimum # of clock cycles to wait between reads
        #tmax: maximum # of clock cycles to wait between reads
        assert self.rst_ni.value == 1, "BPCEncoderDriver Error: rst_ni is not high in read_outputs!"
        k = 0
        for i in range(num):
            yield wait_cycles(self.clk_i, random.randint(tmin, tmax))
            yield self.out_drv.read_output()
            k += 1
            if self.dut.last_o.value == 1:
                return k
        return k