示例#1
0
class DspBlockTB(object):
    def __init__(self, dut, debug=False):
        self.dut = dut
        self.stream_in = STDriver(dut,
                                  "ValNamein_0",
                                  dut.clock,
                                  name_map=axi4stream_chisel_name_map)
        self.backpressure = BitDriver(self.dut.out_0_ready, self.dut.clock)
        self.stream_out = STMonitor(dut,
                                    "out_0",
                                    dut.clock,
                                    name_map=axi4stream_chisel_name_map)

        self.csr = MemMaster(dut,
                             "ValNameioMem_0",
                             dut.clock,
                             name_map=axi4_chisel_name_map)
        self.set_rotation(0)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.stream_in_recovered = STMonitor(
            dut,
            "ValNamein_0",
            dut.clock,
            callback=self.model,
            name_map=axi4stream_chisel_name_map)

        # Create a scoreboard on the stream_out bus
        self.pkts_sent = 0
        self.expected_output = []
        self.scoreboard = Scoreboard(dut)
        self.scoreboard.add_interface(self.stream_out, self.expected_output)

        # Set verbosity on our various interfaces
        level = logging.DEBUG if debug else logging.WARNING
        self.stream_in.log.setLevel(level)
        self.stream_in_recovered.log.setLevel(level)

    def set_rotation(self, rotation):
        self.rotation = rotation
        return self.csr.write(0, self.rotation)

    def model(self, transaction):
        """Model the DUT based on the input transaction"""
        ## TODO apply rotation
        self.expected_output.append(transaction)
        self.pkts_sent += 1

    @cocotb.coroutine
    def reset(self, duration=10):
        self.dut._log.debug("Resetting DUT")
        self.dut.reset <= 1
        self.stream_in.bus.TVALID <= 0
        yield Timer(duration, units='ns')
        yield RisingEdge(self.dut.clock)
        self.dut.reset <= 0
        self.dut._log.debug("Out of reset")
示例#2
0
class BasebandTB(object):
    def __init__(self, dut, debug=False):
        self.dut = dut
        self.csrBase = 0x79040000
        self.stream_in = STDriver(dut,
                                  "adc_0",
                                  dut.clock,
                                  big_endian=False,
                                  **stream_names)
        self.csr = MemMaster(dut, "s_axi", dut.s_axi_aclk, **lower_axil)
        self.memory = np.arange(1024 * 1024 * 1024, dtype=np.dtype('b'))
        self.mem = MemSlave(dut,
                            "m_axi",
                            dut.s_axi_aclk,
                            memory=self.memory,
                            **lower_axi)

        # self.stream_in_recovered = STMonitor(dut, "adc_0", dut.clock, **stream_names)
        self.stream_out = STMonitor(
            dut, "dac_0", dut.clock,
            **stream_names)  #, callback = self.append_channel)
        self.expected_output = []
        self.txdata = []
        self.write_monitor = WriteMonitor(dut, "m_axi", dut.s_axi_aclk,
                                          **lower_axi)
        eq_block = dut.sAxiIsland.freqRx.freqRx.eq
        # self.eq_monitor_in = DecoupledMonitor(eq_block, "in", eq_block.clock, reset=eq_block.reset)
        fft_block = dut.sAxiIsland.freqRx.freqRx.fft
        # self.fft_mon = FFTMonitor(fft_block, fft_block.clock)

        self.scoreboard = Scoreboard(dut)
        # self.scoreboard.add_interface(self.stream_out, self.expected_output)
        # self.scoreboard.add_interface(self.write_monitor, self.txdata)
        level = logging.DEBUG if debug else logging.WARNING
        self.stream_in.log.setLevel(level)
        self.csr.log.setLevel(level)
        self.mem.log.setLevel(level)
        # self.stream_in_recovered.log.setLevel(level)

        self.channel_model = SISOChannel()

    @cocotb.coroutine
    def append_channel(self):
        yield ReadOnly()
        while True:
            if self.dut.dac_0_valid.value:
                data = self.dut.dac_0_data.value.get_value()
            else:
                data = 0
            # print("append_channel")
            self.channel_model.push_packed_sample(data)
            yield RisingEdge(self.dut.clock)
            yield ReadOnly()

    @cocotb.coroutine
    def get_channel(self):
        dataword = BinaryValue(n_bits=32)
        # self.stream_in.bus.TVALID <= 1
        while True:
            # print("get_channel")
            # dataword.assign(str(self.channel_model.pop_packed_sample()))
            # self.stream_in.bus.TDATA <= dataword
            data = self.channel_model.pop_packed_sample()
            yield self.stream_in._driver_send(data=data, sync=False)
            # yield RisingEdge(self.dut.clock)

    @cocotb.coroutine
    def dma_to_mm(self, *, base=0, size=None):
        if size is None:
            size = len(self.memory) // 4
        # base
        yield self.csr.write(self.csrBase + 4 * 4, base)
        # length
        yield self.csr.write(self.csrBase + 5 * 4, size - 1)
        # cycles
        yield self.csr.write(self.csrBase + 6 * 4, 0)
        # fixed
        yield self.csr.write(self.csrBase + 7 * 4, 0)
        # go
        yield self.csr.write(self.csrBase + 8 * 4, 1)

        while True:
            bytesLeft = yield self.csr.read(self.csrBase + 8 * 4)
            if not bytesLeft:
                break

    @cocotb.coroutine
    def dma_mm_to_dac(self, *, base=0, size=None):
        if size is None:
            size = len(self.memory) // 4
        # enable Tx / disable DMA passthrough
        yield self.csr.write(0x79040A00 + 0 * 4, 1)
        # base
        yield self.csr.write(self.csrBase + 0x9 * 4, base)
        # length
        yield self.csr.write(self.csrBase + 0xA * 4, size - 1)
        # cycles
        yield self.csr.write(self.csrBase + 0xB * 4, 100)
        # fixed
        yield self.csr.write(self.csrBase + 0xC * 4, 0)

        # skid disable
        yield self.csr.write(self.csrBase + 0x200, 0)
        # skid drain upstream queue
        yield self.csr.write(self.csrBase + 0x200 + 0x5 * 4, 1)
        # skid clear overflow register
        yield self.csr.write(self.csrBase + 0x200 + 0x3 * 4, 0)

        # go
        yield self.csr.write(self.csrBase + 0xD * 4, 0)
        # enable
        yield self.csr.write(self.csrBase + 0x0, 1)

        # skid enable
        yield self.csr.write(self.csrBase + 0x200, 1)

        # wait for end
        while True:
            yield ClockCycles(self.dut.s_axi_aclk, 50)
            out = yield self.csr.read(self.csrBase + 0xD * 4)
            if out == 0:
                break
        print("Done with TX")

    @cocotb.coroutine
    def set_aligner(self, base=0x100, *, en=True, cnt=1, cntPassthrough=False):
        if cntPassthrough:
            cntPassthrough = 1
        else:
            cntPassthrough = 0
        if en:
            en = 1
        else:
            en = 0
        if base < 0x70000000:
            base = base + self.csrBase
        yield self.csr.write(base + 0xC, cnt)
        yield self.csr.write(base + 0x10, cntPassthrough)
        yield self.csr.write(base, 1)

    @cocotb.coroutine
    def set_input_splitter_mux(self, base=0x900):
        if base < 0x70000000:
            base = base + self.csrBase
        yield self.csr.write(base, 0)

    @cocotb.coroutine
    def set_input_stream_mux(self, base=0x300):
        if base < 0x70000000:
            base = base + self.csrBase
        yield self.csr.write(base, 0)
        # yield self.csr.write(base + 4, 0)

    @cocotb.coroutine
    def set_schedule(self, base=0x800, *, length, time):
        if base < 0x70000000:
            base = base + self.csrBase
        yield self.csr.write(base, length)
        yield self.csr.write(base + 0x4, time)
        yield self.csr.write(base + 0xC, 1)  # go!

    @cocotb.coroutine
    def set_timerx(self, base=0x400, **kwargs):
        if base < 0x70000000:
            base = base + self.csrBase
        settings = {
            'autocorrFF': 0.9,
            'peakThreshold': 0.05,
            'peakOffset': 0.0,
            'freqMultiplier': 0.0,
            'autocorrDepthApart': 65,
            'autocorrDepthOverlap': 63,
            'peakDetectNumPeaks': 16,
            'peakDetectPeakDistance': 32,
            'packetLength': 222 + 7,
            'samplesToDrop': 0,
            'inputDelay': 74,
        }
        representations = {
            'autocorrFF': FixedPointRepresentation(bp=17),
            'peakThreshold': FixedPointRepresentation(bp=17),
            'peakOffset': FixedPointRepresentation(bp=17),
            'freqMultiplier': FixedPointRepresentation(bp=17),
            'autocorrDepthApart': IntRepresentation(),
            'autocorrDepthOverlap': IntRepresentation(),
            'peakDetectNumPeaks': IntRepresentation(),
            'peakDetectPeakDistance': IntRepresentation(),
            'packetLength': IntRepresentation(),
            'samplesToDrop': IntRepresentation(),
            'inputDelay': IntRepresentation()
        }

        settings = {**settings, **kwargs}
        for key in settings.keys():
            kwargs.pop(key, None)
        if len(kwargs) != 0:
            raise TypeError(f"Unexpected kwargs {kwargs}")

        for idx, (key, val) in enumerate(settings.items()):
            # print(f"Writing {representations[key](val)} ({val}) to {base + idx * 4}")
            yield self.csr.write(base + idx * 4, representations[key](val))
        # write globalCycleEn
        yield self.csr.write(base + len(settings) * 4, 1)

    @cocotb.coroutine
    def transmit(self, data):
        txdata = encode_tx(data, addPreamble=True)
        # txdata = encode_linear_seq(222)
        self.txdata.extend(data)

        for i in range(len(txdata)):
            self.memory[i] = txdata[i]

        yield self.dma_mm_to_dac(base=0, size=len(txdata) // 4 - 1)
        # self.dma_to_mm(base = 0 * 1024 * 4, size = len(txdata))

    @cocotb.coroutine
    def transmit_forever(self, data, wait_cycles=100):
        txdata = encode_tx(data, addPreamble=True)
        # txdata = encode_linear_seq(222)
        self.txdata.extend(data)

        for i in range(len(txdata)):
            self.memory[i] = txdata[i]

        while True:
            yield ClockCycles(self.dut.clock, wait_cycles)
            yield self.dma_mm_to_dac(base=0, size=len(txdata) // 4 - 1)

    @cocotb.coroutine
    def handle_packet_detect(self, *, base=0x400):
        if base < 0x70000000:
            base = base + self.csrBase
        while True:
            # check if an interrupt has fired
            if not self.dut.skid_ints_0.value:
                # if not, wait for one
                yield RisingEdge(self.dut.skid_ints_0)
            time = yield self.csr.read(base + 13 * 4)
            print(f"Saw packet at time {time.signed_integer}")

    @cocotb.coroutine
    def reset(self, duration=5):
        self.dut._log.debug("Resetting DUT")
        self.dut.reset <= 1
        self.dut.s_axi_aresetn <= 0
        self.stream_in.bus.TVALID <= 0
        yield ClockCycles(self.dut.clock, duration)
        self.dut.reset <= 0
        yield RisingEdge(self.dut.s_axi_aclk)
        self.dut.s_axi_aresetn <= 1
        self.dut.s_axi_awprot <= 0
        self.dut.dac_0_ready <= 1
        self.dut.dac_1_ready <= 1
        self.dut._log.debug("Setting registers to drain input streams")
        yield self.csr.write(self.csrBase + 0x200 + 0x5 * 4, 1)
        yield self.csr.write(self.csrBase + 0x200, 0)
        yield self.csr.write(self.csrBase + 0x100, 0)
        self.dut._log.debug("Out of reset")