Ejemplo n.º 1
0
def issue_588_coroutine_list(dut):
    """ Yield a list of triggers and coroutines."""

    # Record simulation time.
    current_time = utils.get_sim_time("ns")

    # Yield a list, containing a RisingEdge trigger and a coroutine.
    yield [sample_coroutine(dut), triggers.Timer(100, "ns")]

    # Make sure that only 5 ns passed, because the sample coroutine
    # terminated first.
    new_time = utils.get_sim_time("ns")
    if int(new_time - current_time) != 5:
        raise result.TestFailure("Did not yield coroutine in list.")
Ejemplo n.º 2
0
def test_time_in_external(dut):
    """Test that the simulation time does no advance if the wrapped external
    routine does not its self yield"""
    clk_gen = cocotb.fork(Clock(dut.clk, 100).start())
    yield Timer(10, 'ns')
    time = get_sim_time('ns')
    dut._log.info("Time at start of test = %d" % time)
    for i in range(1000):
        dut._log.info("Loop call %d" % i)
        yield external(test_print_sim_time)(dut, time)

    time_now = get_sim_time('ns')
    yield Timer(10, 'ns')

    if time != time_now:
        raise TestFailure("Time has elapsed over external call")
Ejemplo n.º 3
0
    def _advance(self, outcome):
        if not self.started:
            self.error_messages = []
            self.log.info("Starting test: \"%s\"\nDescription: %s" %
                          (self.funcname, self.__doc__))
            self.start_time = time.time()
            self.start_sim_time = get_sim_time('ns')
            self.started = True
        try:
            self.log.debug("Sending {}".format(outcome))
            return outcome.send(self._coro)
        except TestComplete as e:
            if isinstance(e, TestFailure):
                self.log.warning(str(e))
            else:
                self.log.info(str(e))

            buff = StringIO()
            for message in self.error_messages:
                print(message, file=buff)
            e.stderr.write(buff.getvalue())
            raise
        except StopIteration:
            raise TestSuccess()
        except Exception as e:
            raise raise_error(self, "Send raised exception:")
Ejemplo n.º 4
0
    def send(self, value):
        if not self.started:
            self.error_messages = []
            self.log.info("Starting test: \"%s\"\nDescription: %s" %
                          (self.funcname, self.__doc__))
            self.start_time = time.time()
            self.start_sim_time = get_sim_time('ns')
            self.started = True
        try:
            if isinstance(value, ExternalException):
                self.log.debug("Injecting ExternalException(%s)" % (repr(value)))
                return self._coro.throw(value.exception)
            self.log.debug("Sending trigger %s" % (str(value)))
            return self._coro.send(value)
        except TestComplete as e:
            if isinstance(e, TestFailure):
                self.log.warning(str(e))
            else:
                self.log.info(str(e))

            buff = StringIO()
            for message in self.error_messages:
                print(message, file=buff)
            e.stderr.write(buff.getvalue())
            raise
        except StopIteration:
            raise TestSuccess()
        except Exception as e:
            raise raise_error(self, "Send raised exception: %s" % (str(e)))
Ejemplo n.º 5
0
def test_print_sim_time(dut, base_time):
    # We are not calling out here so time should not advance
    # And should also remain consistent
    for _ in range(10):
        _t = get_sim_time('ns')
        dut._log.info("Time reported = %d", _t)
        if _t != base_time:
            raise TestFailure("Time reported does not match base_time %f != %f" %
                              (_t, base_time))
    dut._log.info("external function has ended")
Ejemplo n.º 6
0
def test_timer_with_units(dut):
    time_fs = get_sim_time(units='fs')

    # Yield for one simulation time step
    yield Timer(1)
    time_step = get_sim_time(units='fs') - time_fs

    try:
        # Yield for 2.5 timesteps, should throw exception
        yield Timer(2.5*time_step, units='fs')
        raise TestFailure("Timers should throw exception if time cannot be achieved with simulator resolution")
    except ValueError:
        dut._log.info("As expected, unable to create a timer of 2.5 simulator time steps")

    time_fs = get_sim_time(units='fs')

    yield Timer(3, "ns")

    if get_sim_time(units='fs') != time_fs+3000000.0:
        raise TestFailure("Expected a delay of 3 ns")

    time_fs = get_sim_time(units='fs')
    yield Timer(1.5, "ns")

    if get_sim_time(units='fs') != time_fs+1500000.0:
        raise TestFailure("Expected a delay of 1.5 ns")

    time_fs = get_sim_time(units='fs')
    yield Timer(10.0, "ps")

    if get_sim_time(units='fs') != time_fs+10000.0:
        raise TestFailure("Expected a delay of 10 ps")

    time_fs = get_sim_time(units='fs')
    yield Timer(1.0, "us")

    if get_sim_time(units='fs') != time_fs+1000000000.0:
        raise TestFailure("Expected a delay of 1 us")
Ejemplo n.º 7
0
    def _format(self, level, record, msg, coloured=False):
        time_ns = get_sim_time('ns')
        simtime = "%6.2fns" % (time_ns)
        prefix = simtime.rjust(10) + ' ' + level + ' '
        if not _suppress:
            prefix += self.ljust(record.name, _RECORD_CHARS) + \
                      self.rjust(os.path.split(record.filename)[1], _FILENAME_CHARS) + \
                      ':' + self.ljust(str(record.lineno), _LINENO_CHARS) + \
                      ' in ' + self.ljust(str(record.funcName), _FUNCNAME_CHARS) + ' '

        prefix_len = len(prefix)
        if coloured:
            prefix_len -= (len(level) - _LEVEL_CHARS)
        pad = "\n" + " " * (prefix_len)
        return prefix + pad.join(msg.split('\n'))
Ejemplo n.º 8
0
def test_clock_with_units(dut):
    clk_1mhz   = Clock(dut.clk, 1.0, units='us')
    clk_250mhz = Clock(dut.clk, 4.0, units='ns')

    if str(clk_1mhz) != "Clock(1.0 MHz)":
        raise TestFailure("{} != 'Clock(1.0 MHz)'".format(str(clk_1mhz)))
    else:
        dut._log.info('Created clock >{}<'.format(str(clk_1mhz)))

    if str(clk_250mhz) != "Clock(250.0 MHz)":
        raise TestFailure("{} != 'Clock(250.0 MHz)'".format(str(clk_250mhz)))
    else:
        dut._log.info('Created clock >{}<'.format(str(clk_250mhz)))

    clk_gen = cocotb.fork(clk_1mhz.start())

    start_time_ns = get_sim_time(units='ns')

    yield Timer(1)

    yield RisingEdge(dut.clk)

    edge_time_ns = get_sim_time(units='ns')
    if not isclose(edge_time_ns, start_time_ns + 1000.0):
        raise TestFailure("Expected a period of 1 us")

    start_time_ns = edge_time_ns

    yield RisingEdge(dut.clk)
    edge_time_ns = get_sim_time(units='ns')
    if not isclose(edge_time_ns, start_time_ns + 1000.0):
        raise TestFailure("Expected a period of 1 us")

    clk_gen.kill()

    clk_gen = cocotb.fork(clk_250mhz.start())

    start_time_ns = get_sim_time(units='ns')

    yield Timer(1)

    yield RisingEdge(dut.clk)

    edge_time_ns = get_sim_time(units='ns')
    if not isclose(edge_time_ns, start_time_ns + 4.0):
        raise TestFailure("Expected a period of 4 ns")

    start_time_ns = edge_time_ns

    yield RisingEdge(dut.clk)
    edge_time_ns = get_sim_time(units='ns')
    if not isclose(edge_time_ns, start_time_ns + 4.0):
        raise TestFailure("Expected a period of 4 ns")

    clk_gen.kill()
Ejemplo n.º 9
0
    def _log_sim_summary(self):
        real_time   = time.time() - self.start_time
        sim_time_ns = get_sim_time('ns')
        ratio_time  = sim_time_ns / real_time

        summary = ""

        summary += "*************************************************************************************\n"
        summary += "**                                 ERRORS : {0:<39}**\n".format(self.failures)
        summary += "*************************************************************************************\n"
        summary += "**                               SIM TIME : {0:<39}**\n".format('{0:.2f} NS'.format(sim_time_ns))
        summary += "**                              REAL TIME : {0:<39}**\n".format('{0:.2f} S'.format(real_time))
        summary += "**                        SIM / REAL TIME : {0:<39}**\n".format('{0:.2f} NS/S'.format(ratio_time))
        summary += "*************************************************************************************\n"

        self.log.info(summary)
Ejemplo n.º 10
0
    def _log_sim_summary(self):
        real_time = time.time() - self.start_time
        sim_time_ns = get_sim_time('ns')
        ratio_time = self._safe_divide(sim_time_ns, real_time)

        summary = ""

        summary += "*************************************************************************************\n"
        summary += "**                                 ERRORS : {0:<39}**\n".format(
            self.failures)
        summary += "*************************************************************************************\n"
        summary += "**                               SIM TIME : {0:<39}**\n".format(
            '{0:.2f} NS'.format(sim_time_ns))
        summary += "**                              REAL TIME : {0:<39}**\n".format(
            '{0:.2f} S'.format(real_time))
        summary += "**                        SIM / REAL TIME : {0:<39}**\n".format(
            '{0:.2f} NS/S'.format(ratio_time))
        summary += "*************************************************************************************\n"

        self.log.info(summary)
Ejemplo n.º 11
0
async def test_clock_with_units(dut):
    clk_1mhz = Clock(dut.clk, 1.0, units='us')
    clk_250mhz = Clock(dut.clk, 4.0, units='ns')

    assert str(clk_1mhz) == "Clock(1.0 MHz)"
    dut._log.info('Created clock >{}<'.format(str(clk_1mhz)))

    assert str(clk_250mhz) == "Clock(250.0 MHz)"
    dut._log.info('Created clock >{}<'.format(str(clk_250mhz)))

    clk_gen = cocotb.fork(clk_1mhz.start())

    start_time_ns = get_sim_time(units='ns')

    await Timer(1, "ns")
    await RisingEdge(dut.clk)

    edge_time_ns = get_sim_time(units='ns')
    assert isclose(edge_time_ns,
                   start_time_ns + 1000.0), "Expected a period of 1 us"

    start_time_ns = edge_time_ns

    await RisingEdge(dut.clk)
    edge_time_ns = get_sim_time(units='ns')
    assert isclose(edge_time_ns,
                   start_time_ns + 1000.0), "Expected a period of 1 us"

    clk_gen.kill()

    clk_gen = cocotb.fork(clk_250mhz.start())

    start_time_ns = get_sim_time(units='ns')

    await Timer(1, "ns")
    await RisingEdge(dut.clk)

    edge_time_ns = get_sim_time(units='ns')
    assert isclose(edge_time_ns,
                   start_time_ns + 4.0), "Expected a period of 4 ns"

    start_time_ns = edge_time_ns

    await RisingEdge(dut.clk)
    edge_time_ns = get_sim_time(units='ns')
    assert isclose(edge_time_ns,
                   start_time_ns + 4.0), "Expected a period of 4 ns"

    clk_gen.kill()
Ejemplo n.º 12
0
    def _start_test(self) -> None:
        # Want this to stand out a little bit
        start = ""
        end = ""
        if want_color_output():
            start = ANSI.COLOR_TEST
            end = ANSI.COLOR_DEFAULT
        self.log.info(
            "{start}running{end} {name} ({i}/{total}){description}".format(
                start=start,
                i=self.count,
                total=self.ntests,
                end=end,
                name=self._test.__qualname__,
                description=_trim(self._test.__doc__),
            ))

        self._test_start_time = time.time()
        self._test_start_sim_time = get_sim_time("ns")
        cocotb.scheduler._add_test(self._test_task)
Ejemplo n.º 13
0
    def _monitor_recv(self):
        """Capture all DUT to Host IRQ requests"""

        irq = self.dut.reg_host_irq

        # Wait for the logic to be reset
        yield ReadOnly()
        yield RisingEdge(self.dut.reset_n)

        while True:

            # Wait on the regfile to assert the IRQ
            while irq.value.integer != 1:
                yield RisingEdge(irq)

            # Signal any subscribers that the IRQ has fired
            self._recv({'time': get_sim_time('ns')})

            # Wait for the interrupt(s) to be cleared
            while irq.value.integer == 1:
                yield FallingEdge(irq)
Ejemplo n.º 14
0
    def handle_result(self, test: RunningTask) -> None:
        """Handle a test completing.

        Dump result to XML and schedule the next test (if any). Entered by the scheduler.

        Args:
            test: The test that completed
        """
        assert test is self._test_task

        real_time = time.time() - self._test_start_time
        sim_time_ns = get_sim_time("ns") - self._test_start_sim_time

        self._record_result(
            test=self._test,
            outcome=self._test_task._outcome,
            wall_time_s=real_time,
            sim_time_ns=sim_time_ns,
        )

        self.execute()
Ejemplo n.º 15
0
    def rx_model(self, transaction):
        rx = transaction["vec"]
        in_reset = transaction["reset"]
        self.dut._log.debug(
            "model called at time %s with transaction %s %s in reset" %
            (get_sim_time("ns"), rx, in_reset))
        if in_reset:
            self.dut._log.debug("output expected length: %d" %
                                len(self.output_expected))
            self.output_expected.append({"rcv": 0, "data": 0})
            self.bits = 0
            self.shift = 0
            self.last_reset = True
        else:
            self.shift = self.shift + (int(rx) << self.bits)
            self.dut._log.debug("bits %d, shift %x, rx %d" %
                                (self.bits, self.shift, rx))
            self.bits = (self.bits + 1) % 10
            if self.bits == 0:
                len_oe = len(self.output_expected)
                if len_oe == 1 and self.last_reset:
                    self.last_reset = False
                    popped = self.output_expected.pop()  #ugh
                    self.dut._log.warning(
                        "popping data from output expected: %r" % popped)
                elif len_oe > 1:
                    self.dut._log.error(
                        "some nonsense with output expected happened")
                self.dut._log.debug("expected output len: %d" %
                                    len(self.output_expected))

                if self.shift >= (1 << 9):
                    expected = (self.shift >> 1) % (1 << 8)
                    self.output_expected.append({"rcv": 1, "data": expected})
                    self.dut._log.debug("model expects uart output %s" %
                                        (bin(expected)))
                else:
                    self.dut._log.info("break mode detected")

                self.shift = 0
Ejemplo n.º 16
0
    def handle_result(self, test: RunningTask) -> None:
        """Handle a test completing.

        Dump result to XML and schedule the next test (if any). Entered by the scheduler.

        Args:
            test: The test that completed
        """
        assert test is self._test_task

        real_time = time.time() - self._test_start_time
        sim_time_ns = get_sim_time('ns') - self._test_start_sim_time

        # stop capturing log output
        cocotb.log.removeHandler(test.handler)

        self._record_result(test=self._test,
                            outcome=self._test_task._outcome,
                            wall_time_s=real_time,
                            sim_time_ns=sim_time_ns)

        self.execute()
Ejemplo n.º 17
0
    def host_expect_packet(self, packet, msg=None):
        self.monitor.prime()
        result = yield self.monitor.wait_for_recv(1e9)  # 1 ms max
        if result is None:
            current = get_sim_time("us")
            raise TestFailure(f"No full packet received @{current}")

        yield RisingEdge(self.dut.clk48_host)
        self.dut.usb_d_p = 1
        self.dut.usb_d_n = 0

        # Check the packet received matches
        expected = pp_packet(wrap_packet(packet))
        actual = pp_packet(result)
        nak = pp_packet(wrap_packet(handshake_packet(PID.NAK)))
        if (actual == nak) and (expected != nak):
            self.dut._log.warning("Got NAK, retry")
            yield Timer(self.RETRY_INTERVAL, 'us')
            return
        else:
            self.retry = False
            assertEqual(expected, actual, msg)
Ejemplo n.º 18
0
    def handle_result(self, test):
        """Handle a test completing.

        Dump result to XML and schedule the next test (if any). Entered by the scheduler.

        Args:
            test: The test that completed
        """
        assert test is self._running_test

        real_time = time.time() - test.start_time
        sim_time_ns = get_sim_time('ns') - test.start_sim_time
        ratio_time = self._safe_divide(sim_time_ns, real_time)

        self.xunit.add_testcase(name=test.funcname,
                                classname=test.module,
                                time=repr(real_time),
                                sim_time_ns=repr(sim_time_ns),
                                ratio_time=repr(ratio_time))

        # score test
        result_pass, sim_failed = self._score_test(test, test._outcome)

        # stop capturing log output
        cocotb.log.removeHandler(test.handler)

        # Save results
        self._store_test_result(test.__module__, test.__name__, result_pass,
                                sim_time_ns, real_time, ratio_time)
        if not result_pass:
            self.xunit.add_failure()
            self.failures += 1

        # Fail if required
        if sim_failed:
            self.tear_down()
            return

        self.execute()
Ejemplo n.º 19
0
    def push_input(self, data):
        self.stop_clk_cnt = False
        if re.search('[x,X,z,Z]', data[0].binstr) is not None:
            self.inputs_good['data'].append(0)
        else:
            self.inputs_good['data'].append(1)
        if re.search('[x,X,z,Z]', data[1].binstr) is not None:
            self.inputs_good['flush'].append(0)
        else:
            self.inputs_good['flush'].append(1)
        self.inputs['data'].append(data[0])
        self.inputs['flush'].append(data[1])
        self.input_times.append(get_sim_time())

        if len(self.inputs['data']) == self.block_size:
            self.dut._log.info("Block {} has been fed".format(self.curr_block))
            block = [el.signed_integer for el in self.inputs['data']]
            block_flush = [el.integer for el in self.inputs['flush']]
            self.input_blocks['data'].append(block)
            self.input_blocks['flush'].append(block_flush)
            self.push_expresp(block, block_flush)
            self.inputs['data'], self.inputs['flush'] = [], []
            self.curr_block += 1
Ejemplo n.º 20
0
 def push_output(self, data):
     assert len(
         self.outputs_act
     ) == self.curr_output, "Scoreboard: len(outputs_act) != curr_output - something is wrong!"
     if re.search('[x,X,z,Z]', data.binstr) is not None:
         self.outputs_good['data'].append(0)
     else:
         self.outputs_good['data'].append(1)
     self.outputs_act.append(data)
     t = get_sim_time()
     self.output_times.append(t)
     try:
         if self.outputs_exp[
                 self.
                 curr_output].integer != data.integer or self.outputs_good[
                     'data'][-1] != 1:
             if not self.silence_mismatch_warnings:
                 self.dut._log.warning(
                     "Output Mismatch! Expected: {}   Got: {}".format(
                         self.outputs_exp[self.curr_output].binstr,
                         data.binstr))
             self.mismatch_positions['output'].append(self.curr_output)
             self.mismatch_times['output'].append(t)
             if len(self.mismatch_positions['output']
                    ) == self.max_mismatches:
                 self.dut._log.warning(
                     "{} output Mismatches - silencing output".format(
                         len(self.mismatch_positions['output'])))
                 self.silence_mismatch_warnings = True
     except IndexError:
         self.dut._log.warning(
             "Trying to push output for which there is no ExpResp yet - skipped!"
         )
         pass
     self.curr_output += 1
     if self.curr_output == len(self.outputs_exp) and self.last_block:
         self.stop_clk_cnt = True
Ejemplo n.º 21
0
    async def _run(self):
        clock_edge_event = RisingEdge(self.clock)

        while True:
            await clock_edge_event

            self.ts_64_fns, self.ts_64_ns = math.modf(get_sim_time('ns'))

            self.ts_64_ns = int(self.ts_64_ns)
            self.ts_64_fns = int(self.ts_64_fns*0x10000)

            self.ts_96_s, self.ts_96_ns = divmod(self.ts_64_ns, 1000000000)
            self.ts_96_fns = self.ts_64_fns

            if self.ts_96 is not None:
                self.ts_96.value = (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns

            if self.ts_64 is not None:
                self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns

            if self.pps is not None:
                self.pps.value = int(self.last_ts_96_s != self.ts_96_s)

            self.last_ts_96_s = self.ts_96_s
Ejemplo n.º 22
0
async def test_div_int_simple(dut):

  log = cocotb.logging.getLogger("cocotb.test")
  log.info("Starting sqrt testbench")
  
  analyzer_root = eaAnalyzer("Analyzer root", 8, False, get_sim_time())
  analyzer_remainder = eaAnalyzer("Analyzer remainder", 8, False, get_sim_time())
  analyzer_valid = eaAnalyzer("Analyzer valid", 1, False, get_sim_time())

  clock = Clock(dut.clk, 10, units="ns")  # Create a 10ns period clock on port clk
  cocotb.fork(clock.start())  # Start the clock

  await ClockCycles(dut.clk, 10) 

  radicand = [0, 1, 121, 81, 90, 255]

  for i in range(len(radicand)):

    dut.rad <= radicand[i]
    
    # Set start for one clk cycle
    dut.start <= 1
    await ClockCycles(dut.clk, 1) 
    dut.start <= 0
    
    await cocotb.triggers.RisingEdge(dut.valid)
    await ClockCycles(dut.clk, 1) 

    log.info("{}:\tsqrt({}) = {} (rem = {})".format(get_sim_time(), dut.rad.value, dut.root.value, dut.rem.value));

    #assert dut.valid.value == 1
    analyzer_valid.add_sample(dut.valid.value, 1, get_sim_time())

    #assert dut.root.value == int(math.sqrt(radicand[i]))
    analyzer_root.add_sample(dut.root.value, int(math.sqrt(radicand[i])), get_sim_time())
    #assert dut.rem.value == (radicand[i] - int(math.sqrt(radicand[i]))**2)
    analyzer_remainder.add_sample(dut.rem.value, (radicand[i] - int(math.sqrt(radicand[i]))**2), get_sim_time())
  
  eaAnalyzersFinal()
Ejemplo n.º 23
0
 def check_phase(self):
     assert get_sim_time(units="ms") > 10
Ejemplo n.º 24
0
    def _log_test_summary(self) -> None:

        real_time = time.time() - self.start_time
        sim_time_ns = get_sim_time("ns")
        ratio_time = self._safe_divide(sim_time_ns, real_time)

        if len(self.test_results) == 0:
            return

        TEST_FIELD = "TEST"
        RESULT_FIELD = "STATUS"
        SIM_FIELD = "SIM TIME (ns)"
        REAL_FIELD = "REAL TIME (s)"
        RATIO_FIELD = "RATIO (ns/s)"
        TOTAL_NAME = f"TESTS={self.ntests} PASS={self.passed} FAIL={self.failures} SKIP={self.skipped}"

        TEST_FIELD_LEN = max(
            len(TEST_FIELD),
            len(TOTAL_NAME),
            len(max([x["test"] for x in self.test_results], key=len)),
        )
        RESULT_FIELD_LEN = len(RESULT_FIELD)
        SIM_FIELD_LEN = len(SIM_FIELD)
        REAL_FIELD_LEN = len(REAL_FIELD)
        RATIO_FIELD_LEN = len(RATIO_FIELD)

        header_dict = dict(
            a=TEST_FIELD,
            b=RESULT_FIELD,
            c=SIM_FIELD,
            d=REAL_FIELD,
            e=RATIO_FIELD,
            a_len=TEST_FIELD_LEN,
            b_len=RESULT_FIELD_LEN,
            c_len=SIM_FIELD_LEN,
            d_len=REAL_FIELD_LEN,
            e_len=RATIO_FIELD_LEN,
        )

        LINE_LEN = (3 + TEST_FIELD_LEN + 2 + RESULT_FIELD_LEN + 2 +
                    SIM_FIELD_LEN + 2 + REAL_FIELD_LEN + 2 + RATIO_FIELD_LEN +
                    3)

        LINE_SEP = "*" * LINE_LEN + "\n"

        summary = ""
        summary += LINE_SEP
        summary += "** {a:<{a_len}}  {b:^{b_len}}  {c:>{c_len}}  {d:>{d_len}}  {e:>{e_len}} **\n".format(
            **header_dict)
        summary += LINE_SEP

        test_line = "** {a:<{a_len}}  {start}{b:^{b_len}}{end}  {c:>{c_len}.2f}   {d:>{d_len}.2f}   {e:>{e_len}}  **\n"
        for result in self.test_results:
            hilite = ""
            lolite = ""

            if result["pass"] is None:
                ratio = "-.--"
                pass_fail_str = "SKIP"
                if want_color_output():
                    hilite = ANSI.COLOR_SKIPPED
                    lolite = ANSI.COLOR_DEFAULT
            elif result["pass"]:
                ratio = format(result["ratio"], "0.2f")
                pass_fail_str = "PASS"
                if want_color_output():
                    hilite = ANSI.COLOR_PASSED
                    lolite = ANSI.COLOR_DEFAULT
            else:
                ratio = format(result["ratio"], "0.2f")
                pass_fail_str = "FAIL"
                if want_color_output():
                    hilite = ANSI.COLOR_FAILED
                    lolite = ANSI.COLOR_DEFAULT

            test_dict = dict(
                a=result["test"],
                b=pass_fail_str,
                c=result["sim"],
                d=result["real"],
                e=ratio,
                a_len=TEST_FIELD_LEN,
                b_len=RESULT_FIELD_LEN,
                c_len=SIM_FIELD_LEN - 1,
                d_len=REAL_FIELD_LEN - 1,
                e_len=RATIO_FIELD_LEN - 1,
                start=hilite,
                end=lolite,
            )

            summary += test_line.format(**test_dict)

        summary += LINE_SEP

        summary += test_line.format(
            a=TOTAL_NAME,
            b="",
            c=sim_time_ns,
            d=real_time,
            e=format(ratio_time, "0.2f"),
            a_len=TEST_FIELD_LEN,
            b_len=RESULT_FIELD_LEN,
            c_len=SIM_FIELD_LEN - 1,
            d_len=REAL_FIELD_LEN - 1,
            e_len=RATIO_FIELD_LEN - 1,
            start="",
            end="",
        )

        summary += LINE_SEP

        self.log.info(summary)
Ejemplo n.º 25
0
async def run_seconds_increment(dut):

    tb = TB(dut)

    await tb.reset()

    await RisingEdge(dut.clk)

    dut.input_ts_96.value = 999990000 * 2**16
    dut.input_ts_96_valid.value = 1
    dut.input_ts_64.value = 999990000 * 2**16
    dut.input_ts_64_valid.value = 1

    await RisingEdge(dut.clk)

    dut.input_ts_96_valid.value = 0
    dut.input_ts_64_valid.value = 0

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)

    start_time = get_sim_time('sec')
    start_ts_96 = (dut.output_ts_96.value.integer >> 48) + (
        (dut.output_ts_96.value.integer & 0xffffffffffff) / 2**16 * 1e-9)
    start_ts_64 = dut.output_ts_64.value.integer / 2**16 * 1e-9

    saw_pps = False

    for k in range(3000):
        await RisingEdge(dut.clk)

        if dut.output_pps.value.integer:
            saw_pps = True
            assert dut.output_ts_96.value.integer >> 48 == 1
            assert dut.output_ts_96.value.integer & 0xffffffffffff < 10 * 2**16

    assert saw_pps

    stop_time = get_sim_time('sec')
    stop_ts_96 = (dut.output_ts_96.value.integer >> 48) + (
        (dut.output_ts_96.value.integer & 0xffffffffffff) / 2**16 * 1e-9)
    stop_ts_64 = dut.output_ts_64.value.integer / 2**16 * 1e-9

    time_delta = stop_time - start_time
    ts_96_delta = stop_ts_96 - start_ts_96
    ts_64_delta = stop_ts_64 - start_ts_64

    ts_96_diff = time_delta - ts_96_delta
    ts_64_diff = time_delta - ts_64_delta

    tb.log.info("sim time delta  : %g s", time_delta)
    tb.log.info("96 bit ts delta : %g s", ts_96_delta)
    tb.log.info("64 bit ts delta : %g s", ts_64_delta)
    tb.log.info("96 bit ts diff  : %g s", ts_96_diff)
    tb.log.info("64 bit ts diff  : %g s", ts_64_diff)

    assert abs(ts_96_diff) < 1e-12
    assert abs(ts_64_diff) < 1e-12

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)
Ejemplo n.º 26
0
    async def _run(self):
        frame = None
        self.active = False

        while True:
            await RisingEdge(self.clock)

            # read handshake signals
            tready_sample = (not hasattr(self.bus,
                                         "tready")) or self.bus.tready.value
            tvalid_sample = (not hasattr(self.bus,
                                         "tvalid")) or self.bus.tvalid.value

            if (tready_sample and tvalid_sample) or not tvalid_sample:
                if frame is None and not self.queue.empty():
                    frame = self.queue.get_nowait()
                    self.dequeue_event.set()
                    self.queue_occupancy_bytes -= len(frame)
                    self.queue_occupancy_frames -= 1
                    self.current_frame = frame
                    frame.sim_time_start = get_sim_time()
                    frame.sim_time_end = None
                    self.log.info("TX frame: %s", frame)
                    frame.normalize()
                    self.active = True

                if frame and not self.pause:
                    tdata_val = 0
                    tlast_val = 0
                    tkeep_val = 0
                    tid_val = 0
                    tdest_val = 0
                    tuser_val = 0

                    for offset in range(self.byte_lanes):
                        tdata_val |= (frame.tdata.pop(0) & self.byte_mask) << (
                            offset * self.byte_size)
                        tkeep_val |= (frame.tkeep.pop(0) & 1) << offset
                        tid_val = frame.tid.pop(0)
                        tdest_val = frame.tdest.pop(0)
                        tuser_val = frame.tuser.pop(0)

                        if len(frame.tdata) == 0:
                            tlast_val = 1
                            frame.sim_time_end = get_sim_time()
                            frame.handle_tx_complete()
                            frame = None
                            self.current_frame = None
                            break

                    self.bus.tdata <= tdata_val
                    if hasattr(self.bus, "tvalid"):
                        self.bus.tvalid <= 1
                    if hasattr(self.bus, "tlast"):
                        self.bus.tlast <= tlast_val
                    if hasattr(self.bus, "tkeep"):
                        self.bus.tkeep <= tkeep_val
                    if hasattr(self.bus, "tid"):
                        self.bus.tid <= tid_val
                    if hasattr(self.bus, "tdest"):
                        self.bus.tdest <= tdest_val
                    if hasattr(self.bus, "tuser"):
                        self.bus.tuser <= tuser_val
                else:
                    if hasattr(self.bus, "tvalid"):
                        self.bus.tvalid <= 0
                    if hasattr(self.bus, "tlast"):
                        self.bus.tlast <= 0
                    self.active = bool(frame)
                    if not frame and self.queue.empty():
                        self.idle_event.set()
Ejemplo n.º 27
0
    async def _run(self):
        frame = None
        ifg_cnt = 0
        deficit_idle_cnt = 0
        self.active = False

        while True:
            await RisingEdge(self.clock)

            if self.enable is None or self.enable.value:
                if ifg_cnt + deficit_idle_cnt > self.byte_width - 1 or (
                        not self.enable_dic and ifg_cnt > 4):
                    # in IFG
                    ifg_cnt = ifg_cnt - self.byte_width
                    if ifg_cnt < 0:
                        if self.enable_dic:
                            deficit_idle_cnt = max(deficit_idle_cnt + ifg_cnt,
                                                   0)
                        ifg_cnt = 0

                elif frame is None:
                    # idle
                    if self.queue:
                        # send frame
                        frame = self.queue.popleft()
                        self.queue_occupancy_bytes -= len(frame)
                        self.queue_occupancy_frames -= 1
                        frame.sim_time_start = get_sim_time()
                        frame.sim_time_sfd = None
                        frame.sim_time_end = None
                        self.log.info("TX frame: %s", frame)
                        frame.normalize()
                        frame.start_lane = 0
                        assert frame.data[0] == EthPre.PRE
                        assert frame.ctrl[0] == 0
                        frame.data[0] = XgmiiCtrl.START
                        frame.ctrl[0] = 1
                        frame.data.append(XgmiiCtrl.TERM)
                        frame.ctrl.append(1)

                        # offset start
                        if self.enable_dic:
                            min_ifg = 3 - deficit_idle_cnt
                        else:
                            min_ifg = 0

                        if self.byte_width > 4 and (ifg_cnt > min_ifg or
                                                    self.force_offset_start):
                            ifg_cnt = ifg_cnt - 4
                            frame.start_lane = 4
                            frame.data = bytearray(
                                [XgmiiCtrl.IDLE] * 4) + frame.data
                            frame.ctrl = [1] * 4 + frame.ctrl

                        if self.enable_dic:
                            deficit_idle_cnt = max(deficit_idle_cnt + ifg_cnt,
                                                   0)
                        ifg_cnt = 0
                        self.active = True
                    else:
                        # clear counters
                        deficit_idle_cnt = 0
                        ifg_cnt = 0

                if frame is not None:
                    d_val = 0
                    c_val = 0

                    for k in range(self.byte_width):
                        if frame is not None:
                            d = frame.data.pop(0)
                            if frame.sim_time_sfd is None and d == EthPre.SFD:
                                frame.sim_time_sfd = get_sim_time()
                            d_val |= d << k * 8
                            c_val |= frame.ctrl.pop(0) << k

                            if not frame.data:
                                ifg_cnt = max(self.ifg - (self.byte_width - k),
                                              0)
                                frame.sim_time_end = get_sim_time()
                                frame.handle_tx_complete()
                                frame = None
                        else:
                            d_val |= XgmiiCtrl.IDLE << k * 8
                            c_val |= 1 << k

                    self.data <= d_val
                    self.ctrl <= c_val
                else:
                    self.data <= self.idle_d
                    self.ctrl <= self.idle_c
                    self.active = False
Ejemplo n.º 28
0
    def handle_result(self, result):
        """Handle a test result

        Dumps result to XML and schedules the next test (if any)

        Args: result (TestComplete exception)
        """
        real_time   = time.time() - self._running_test.start_time
        sim_time_ns = get_sim_time('ns') - self._running_test.start_sim_time
        ratio_time  = sim_time_ns / real_time
        self.xunit.add_testcase(name=self._running_test.funcname,
                                classname=self._running_test.module,
                                time=repr(real_time),
                                sim_time_ns=repr(sim_time_ns),
                                ratio_time=repr(ratio_time))

        running_test_funcname = self._running_test.funcname

        # Helper for logging result
        def _result_was():
            result_was = ("%s (result was %s)" %
                          (running_test_funcname, result.__class__.__name__))
            return result_was

        result_pass = True

        if (isinstance(result, TestSuccess) and
                not self._running_test.expect_fail and
                not self._running_test.expect_error):
            self.log.info("Test Passed: %s" % running_test_funcname)

        elif (isinstance(result, TestFailure) and
                self._running_test.expect_fail):
            self.log.info("Test failed as expected: " + _result_was())

        elif (isinstance(result, TestSuccess) and
              self._running_test.expect_error):
            self.log.error("Test passed but we expected an error: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, TestSuccess):
            self.log.error("Test passed but we expected a failure: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, TestError) and self._running_test.expect_error:
            self.log.info("Test errored as expected: " + _result_was())

        elif isinstance(result, SimFailure):
            if self._running_test.expect_error:
                self.log.info("Test errored as expected: " + _result_was())
            else:
                self.log.error("Test error has lead to simulator shuttting us "
                               "down")
                self._add_failure(result)
                self._store_test_result(self._running_test.module, self._running_test.funcname, False, sim_time_ns, real_time, ratio_time)
                self.tear_down()
                return

        else:
            self.log.error("Test Failed: " + _result_was())
            self._add_failure(result)
            result_pass = False

        self._store_test_result(self._running_test.module, self._running_test.funcname, result_pass, sim_time_ns, real_time, ratio_time)

        self.execute()
Ejemplo n.º 29
0
    async def _run(self):
        frame = None
        self.active = False

        clock_edge_event = RisingEdge(self.clock)

        while True:
            await clock_edge_event

            if self.enable is None or self.enable.value:
                d_val = self.data.value.integer
                dv_val = self.dv.value.integer
                er_val = 0 if self.er is None else self.er.value.integer

                if frame is None:
                    if dv_val:
                        # start of frame
                        frame = GmiiFrame(bytearray(), [])
                        frame.sim_time_start = get_sim_time()
                else:
                    if not dv_val:
                        # end of frame

                        if self.mii_select is not None:
                            self.mii_mode = bool(self.mii_select.value.integer)

                        if self.mii_mode:
                            odd = True
                            sync = False
                            b = 0
                            be = 0
                            data = bytearray()
                            error = []
                            for n, e in zip(frame.data, frame.error):
                                odd = not odd
                                b = (n & 0x0F) << 4 | b >> 4
                                be |= e
                                if not sync and b == EthPre.SFD:
                                    odd = True
                                    sync = True
                                if odd:
                                    data.append(b)
                                    error.append(be)
                                    be = 0
                            frame.data = data
                            frame.error = error

                        frame.compact()
                        frame.sim_time_end = get_sim_time()
                        self.log.info("RX frame: %s", frame)

                        self.queue_occupancy_bytes += len(frame)
                        self.queue_occupancy_frames += 1

                        self.queue.put_nowait(frame)
                        self.active_event.set()

                        frame = None

                if frame is not None:
                    if frame.sim_time_sfd is None and d_val in (EthPre.SFD, 0xD):
                        frame.sim_time_sfd = get_sim_time()

                    frame.data.append(d_val)
                    frame.error.append(er_val)
Ejemplo n.º 30
0
    async def _run(self):
        frame = None
        self.active = False
        d_val = 0
        dv_val = 0
        er_val = 0

        while True:
            await RisingEdge(self.clock)

            # capture low nibble on rising edge
            d_val = self.data.value.integer
            dv_val = self.ctrl.value.integer

            await FallingEdge(self.clock)

            # capture high nibble on falling edge
            d_val |= self.data.value.integer << 4
            er_val = dv_val ^ self.ctrl.value.integer

            if self.enable is None or self.enable.value:

                if frame is None:
                    if dv_val:
                        # start of frame
                        frame = GmiiFrame(bytearray(), [])
                        frame.sim_time_start = get_sim_time()
                else:
                    if not dv_val:
                        # end of frame

                        if self.mii_select is not None:
                            self.mii_mode = bool(self.mii_select.value.integer)

                        if self.mii_mode:
                            odd = True
                            sync = False
                            b = 0
                            be = 0
                            data = bytearray()
                            error = []
                            for n, e in zip(frame.data, frame.error):
                                odd = not odd
                                b = (n & 0x0F) << 4 | b >> 4
                                be |= e
                                if not sync and b == EthPre.SFD:
                                    odd = True
                                    sync = True
                                if odd:
                                    data.append(b)
                                    error.append(be)
                                    be = 0
                            frame.data = data
                            frame.error = error

                        frame.compact()
                        frame.sim_time_end = get_sim_time()
                        self.log.info("RX frame: %s", frame)

                        self.queue_occupancy_bytes += len(frame)
                        self.queue_occupancy_frames += 1

                        self.queue.append(frame)
                        self.sync.set()

                        frame = None

                if frame is not None:
                    if frame.sim_time_sfd is None and d_val in (EthPre.SFD, 0xD, 0xDD):
                        frame.sim_time_sfd = get_sim_time()

                    frame.data.append(d_val)
                    frame.error.append(er_val)
Ejemplo n.º 31
0
    def handle_result(self, test):
        """Handle a test completing.

        Dump result to XML and schedule the next test (if any).

        Args:
            test: The test that completed
        """
        assert test is self._running_test

        real_time = time.time() - test.start_time
        sim_time_ns = get_sim_time('ns') - test.start_sim_time
        ratio_time = self._safe_divide(sim_time_ns, real_time)

        self.xunit.add_testcase(name=test.funcname,
                                classname=test.module,
                                time=repr(real_time),
                                sim_time_ns=repr(sim_time_ns),
                                ratio_time=repr(ratio_time))

        # Helper for logging result
        def _result_was():
            result_was = ("{} (result was {})".format(
                test.funcname, result.__class__.__name__))
            return result_was

        result_pass = True

        # check what exception the test threw
        try:
            test._outcome.get()
        except Exception as e:
            if sys.version_info >= (3, 5):
                result = remove_traceback_frames(e, ['handle_result', 'get'])
                # newer versions of the `logging` module accept plain exception objects
                exc_info = result
            elif sys.version_info >= (3, ):
                result = remove_traceback_frames(e, ['handle_result', 'get'])
                # newer versions of python have Exception.__traceback__
                exc_info = (type(result), result, result.__traceback__)
            else:
                # Python 2
                result = e
                exc_info = remove_traceback_frames(sys.exc_info(),
                                                   ['handle_result', 'get'])
        else:
            result = TestSuccess()

        if (isinstance(result, TestSuccess) and not test.expect_fail
                and not test.expect_error):
            self.log.info("Test Passed: %s" % test.funcname)

        elif (isinstance(result, AssertionError) and test.expect_fail):
            self.log.info("Test failed as expected: " + _result_was())

        elif (isinstance(result, TestSuccess) and test.expect_error):
            self.log.error("Test passed but we expected an error: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, TestSuccess):
            self.log.error("Test passed but we expected a failure: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, SimFailure):
            if isinstance(result, test.expect_error):
                self.log.info("Test errored as expected: " + _result_was())
            else:
                self.log.error(
                    "Test error has lead to simulator shutting us "
                    "down",
                    exc_info=exc_info)
                self._add_failure(result)
                self._store_test_result(test.module, test.funcname, False,
                                        sim_time_ns, real_time, ratio_time)
                self.tear_down()
                return

        elif test.expect_error:
            if isinstance(result, test.expect_error):
                self.log.info("Test errored as expected: " + _result_was())
            else:
                self.log.info("Test errored with unexpected type: " +
                              _result_was())
                self._add_failure(result)
                result_pass = False

        else:
            self.log.error("Test Failed: " + _result_was(), exc_info=exc_info)
            self._add_failure(result)
            result_pass = False

        self._store_test_result(test.module, test.funcname, result_pass,
                                sim_time_ns, real_time, ratio_time)

        self.execute()
Ejemplo n.º 32
0
def uvm_sim_time(units='NS'):
    if simulator is not None:
        return get_sim_time(units=units)
    return 0
Ejemplo n.º 33
0
    async def _run(self):
        frame = None
        ifg_cnt = 0
        self.active = False
        d = 0
        er = 0
        en = 0

        while True:
            await RisingEdge(self.clock)

            # send high nibble after rising edge, leading in to falling edge
            self.data <= d >> 4
            self.ctrl <= en ^ er

            if self.enable is None or self.enable.value:
                if ifg_cnt > 0:
                    # in IFG
                    ifg_cnt -= 1

                elif frame is None and self.queue:
                    # send frame
                    frame = self.queue.popleft()
                    self.queue_occupancy_bytes -= len(frame)
                    self.queue_occupancy_frames -= 1
                    frame.sim_time_start = get_sim_time()
                    frame.sim_time_sfd = None
                    frame.sim_time_end = None
                    self.log.info("TX frame: %s", frame)
                    frame.normalize()

                    if self.mii_select is not None:
                        self.mii_mode = bool(self.mii_select.value.integer)

                    if self.mii_mode:
                        mii_data = []
                        mii_error = []
                        for b, e in zip(frame.data, frame.error):
                            mii_data.append((b & 0x0F)*0x11)
                            mii_data.append((b >> 4)*0x11)
                            mii_error.append(e)
                            mii_error.append(e)
                        frame.data = mii_data
                        frame.error = mii_error

                    self.active = True

                if frame is not None:
                    d = frame.data.pop(0)
                    er = frame.error.pop(0)
                    en = 1

                    if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD, 0xDD):
                        frame.sim_time_sfd = get_sim_time()

                    if not frame.data:
                        ifg_cnt = max(self.ifg, 1)
                        frame.sim_time_end = get_sim_time()
                        frame.handle_tx_complete()
                        frame = None
                else:
                    d = 0
                    er = 0
                    en = 0
                    self.active = False

            await FallingEdge(self.clock)

            # send low nibble after falling edge, leading in to rising edge
            self.data <= d & 0x0F
            self.ctrl <= en
Ejemplo n.º 34
0
 def run_phase(self, phase):
     phase.raise_objection(self)
     yield Timer(10)
     print("{}: {} HI".format(get_sim_time(), self.get_full_name()))
     phase.drop_objection(self)
Ejemplo n.º 35
0
    async def _run(self):
        frame = None
        frame_offset = 0
        frame_data = None
        frame_error = None
        ifg_cnt = 0
        self.active = False
        d = 0
        er = 0
        en = 0

        clock_rising_edge_event = RisingEdge(self.clock)
        clock_falling_edge_event = FallingEdge(self.clock)

        while True:
            await clock_rising_edge_event

            # send high nibble after rising edge, leading in to falling edge
            self.data.value = d >> 4
            self.ctrl.value = en ^ er

            if self.enable is None or self.enable.value:
                if ifg_cnt > 0:
                    # in IFG
                    ifg_cnt -= 1

                elif frame is None and not self.queue.empty():
                    # send frame
                    frame = self.queue.get_nowait()
                    self.dequeue_event.set()
                    self.queue_occupancy_bytes -= len(frame)
                    self.queue_occupancy_frames -= 1
                    self.current_frame = frame
                    frame.sim_time_start = get_sim_time()
                    frame.sim_time_sfd = None
                    frame.sim_time_end = None
                    self.log.info("TX frame: %s", frame)
                    frame.normalize()

                    if self.mii_select is not None:
                        self.mii_mode = bool(self.mii_select.value.integer)

                    if self.mii_mode:
                        # convert to MII
                        frame_data = []
                        frame_error = []
                        for b, e in zip(frame.data, frame.error):
                            frame_data.append((b & 0x0F)*0x11)
                            frame_data.append((b >> 4)*0x11)
                            frame_error.append(e)
                            frame_error.append(e)
                    else:
                        frame_data = frame.data
                        frame_error = frame.error

                    self.active = True
                    frame_offset = 0

                if frame is not None:
                    d = frame_data[frame_offset]
                    er = frame_error[frame_offset]
                    en = 1
                    frame_offset += 1

                    if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD, 0xDD):
                        frame.sim_time_sfd = get_sim_time()

                    if frame_offset >= len(frame_data):
                        ifg_cnt = max(self.ifg, 1)
                        frame.sim_time_end = get_sim_time()
                        frame.handle_tx_complete()
                        frame = None
                        self.current_frame = None
                else:
                    d = 0
                    er = 0
                    en = 0
                    self.active = False
                    self.idle_event.set()

                await clock_falling_edge_event

                # send low nibble after falling edge, leading in to rising edge
                self.data.value = d & 0x0F
                self.ctrl.value = en
Ejemplo n.º 36
0
 def Heartbeat():
     while beat:
         yield Timer(1, units="ms")
         ct = get_sim_time("us")
         self.dut._log.info("Waiting, current time {:.0f}".format(ct))
Ejemplo n.º 37
0
def test_tree(dut):
    """Testing APBI2C core"""

    log = cocotb.logging.getLogger("cocotb.test")
    cocotb.fork(Clock(dut.PCLK, 1000).start())

    #instantiate the APB agent (monitor and driver) (see apb.py)
    apb = APBSlave(dut, name=None, clock=dut.PCLK)

    #instantiate the I2C monitor and driver (see i2c.py)
    i2c_monitor = I2CMonitor(dut, name="", clock=dut.PCLK)
    i2c_driver = I2CDriver(dut, name=None, clock=dut.PCLK)

    #write to config register via APB
    @cocotb.coroutine
    def config_write(addr, data):
        xaction = APBTransaction(addr, data, write=True)
        xaction.randomize()
        yield apb.send(xaction)

    #store observed I2C transactions
    received_i2c_xactions = []

    #the catcher for observerd I2C transaction on the interfece
    @I2CCoverage
    def i2c_xaction_catcher(i2c_xaction):
        if LOG_XACTION_ENABLE:
            log.info("I2C Monitor: Transaction 0x%08X" % i2c_xaction.data)
        received_i2c_xactions.append(i2c_xaction)

    #callback to the monitor to call the catcher when I2C transaction observed
    i2c_monitor.add_callback(i2c_xaction_catcher)

    #the catcher for observerd APB transaction on the interfece
    @APBCoverage
    def apb_xaction_catcher(apb_xaction):
        if LOG_XACTION_ENABLE:
            try:
                log.info("APB Transaction %s 0x%08X -> 0x%08X" %
                         ("Write" if apb_xaction.write else "Read ",
                          int(apb_xaction.addr), int(apb_xaction.data)))
            except:
                log.info("APB Transaction %s 0x%08X -> 0x%08s" %
                         ("Write" if apb_xaction.write else "Read ",
                          int(apb_xaction.addr), int(apb_xaction.data)))

    #callback to the monitor to call the catcher when APB transaction observed
    apb.add_callback(apb_xaction_catcher)

    #define "I2C Operation" as a bunch of r/ws with defined number of data
    #and a specific clock divider
    #this is the main stuff to be tested - we want to know if controller
    #correctly processes transfers with different directions, amount of
    #data and SCK period
    class I2C_Operation(Randomized):
        def __init__(self, direction='write', repeat=1, divider=1):
            Randomized.__init__(self)
            self.direction = direction
            self.repeat = repeat
            self.divider = divider
            self.repeat_range = (1, 3)
            self.divider_range = (1, 3)

            #I2C_Operation objects may be fully randomized
            self.addRand("direction", ["write", "read"])
            self.addRand("repeat_range", [(1, 3), (4, 7), (8, 11), (12, 15),
                                          (16, 23), (24, 31)])
            self.addRand("divider_range", [(1, 3), (4, 7), (8, 11), (12, 15),
                                           (16, 23), (24, 31)])

        #post_randomize to pick random values from already randomized ranges
        def post_randomize(self):
            self.repeat = random.randint(self.repeat_range[0],
                                         self.repeat_range[1])
            self.divider = random.randint(self.divider_range[0],
                                          self.divider_range[1])

    #list of completed operations for the summary
    operations_completed = []

    #function sampling operations order coverage (see coverage.py)
    @OperationsOrderCoverage
    def sample_operations_order_coverage(prev_operation, operation):
        pass

    #function sampling operations coverage (see coverage.py)
    @OperationsCoverage
    def sample_operation(operation, ok):
        operations_completed.append((operation, ok))
        if (len(operations_completed) > 1):
            sample_operations_order_coverage(operations_completed[-2][0],
                                             operations_completed[-1][0])
        if ok:
            log.info(
                "Operation %s of %d words, divider %d - OK!" %
                (operation.direction, operation.repeat, operation.divider))
        else:
            log.error(
                "Operation %s of %d words, divider %d - error!" %
                (operation.direction, operation.repeat, operation.divider))

    #a test sequence - complete I2C Write Operation
    @cocotb.coroutine
    def segment_i2c_write_operation(operation):
        expected_out = []
        yield config_write(8, 0x0001 | (operation.divider << 2))

        #create xaction objects and fill FIFO up via APB with data to be send
        apb_xaction = APBTransaction(0, 0, write=True)
        for i in range(operation.repeat):
            i2c_xaction = I2CTransaction(0, write=False)
            i2c_xaction.randomize()
            apb_xaction.data = i2c_xaction.data
            apb_xaction.randomize()
            yield apb.send(apb_xaction)
            expected_out.append(i2c_xaction)

        #wait for FIFO empty - meaning all data sent out
        guard_int = 0
        while not dut.INT_TX.value:
            guard_int = guard_int + 1
            yield RisingEdge(dut.PCLK)
            if guard_int == 50000:
                raise TestFailure("Controller hang-up!")

        #a simple scoreboarding...
        #compare data written to APB with catched on I2C interface
        ok = True
        received_xactions = received_i2c_xactions[-operation.repeat:]
        if len(received_xactions) < operation.repeat:
            ok = False
        else:
            for i in range(operation.repeat):
                if (received_xactions[i] != expected_out[i]):
                    ok = False
                    break

        #call sampling at the and of the sequence
        sample_operation(operation, ok)

    #a test sequence - complete I2C Read Operation
    @cocotb.coroutine
    def segment_i2c_read_operation(operation):
        expected_in = []
        yield config_write(8, 0x0002 | (operation.divider << 2))

        #create I2C xaction objects and send on the interface
        for i in range(operation.repeat):
            i2c_xaction = I2CTransaction(0, write=True)
            i2c_xaction.randomize()
            expected_in.append(i2c_xaction)
            yield i2c_driver.send(i2c_xaction)

        #a simple scoreboarding...
        #compare data written on I2C interface with read from FIFO
        ok = True
        apb_xaction = APBTransaction(0x04, 0, write=False)
        for i in range(operation.repeat):
            try:
                apb_xaction.randomize()
                rdata = yield apb.send(xaction)
                if (rdata != expected_in[i].data):
                    ok = False
            except:
                if LOG_XACTION_ENABLE:
                    log.error("APB read data from FIFO is 'X'")
                ok = False

        #call sampling at the and of the sequence
        sample_operation(operation, ok)

    #a test sequence - APB registers operation (sort of UVM_REG :) )
    @cocotb.coroutine
    def segment_apb_rw(repeat=1, addr=0xC):

        apb_xaction_wr = APBTransaction(addr, 0, write=True)
        apb_xaction_rd = APBTransaction(addr, 0, write=False)

        #just do some APB/RW
        for i in range(repeat):
            data = random.randint(0, 0xFFFFFFFF)
            apb_xaction_wr.randomize()
            apb_xaction_wr.data = data
            yield apb.send(apb_xaction_wr)
            apb_xaction_rd.randomize()
            rdata = yield apb.send(apb_xaction_rd)
            if LOG_XACTION_ENABLE:
                try:
                    if rdata != data:
                        log.error(
                            "APB read data @ 0x%08X does not match written value"
                            % addr)
                except:
                    log.error("APB read data @ 0x%08X is 'X'" % addr)

    #reset the DUT
    dut.PRESETn <= 0
    yield Timer(2000)
    dut.PRESETn <= 1

    yield config_write(12, 0x0100)

    #if checkpoints used, store them in the map, (see checkpoint.py)
    if ENABLE_CHECKPOINTS:
        checkpoints = {}
        get_checkpoint_hier(dut)
        #the fist checkpoint is just after reset
        checkpoints['init'] = (checkpoint(), None)

    #list of already covered operations, used to constraint the randomization
    already_covered = []

    #constraint for the operation randomization - do not use already
    #covered combinations
    def op_constraint(direction, divider_range, repeat_range):
        return not (direction, repeat_range, divider_range) in already_covered

    apb_cover_item = coverage_db["top.apb.writeXdelay"]
    top_cover_item = coverage_db["top"]

    #we define test end condition as reaching 99% coverage at the
    #top cover item
    cov_op = 0
    while cov_op < 90:

        #restore randomly selected checkpoint
        if ENABLE_CHECKPOINTS:
            if CHECKPOINTS_TREE_STRUCTURE:
                chkp_to_restore = random.choice(list(checkpoints.keys()))
            else:
                chkp_to_restore = 'init'

            log.info("Restoring a simulation checkpoint: " + chkp_to_restore)
            current_chceckpoint = checkpoints[chkp_to_restore]
            restore(current_chceckpoint[0])

        #create I2C operation object to be executed
        i2c_op = I2C_Operation()
        #if there is no tree structure, knowledge about already covered
        #cases cannot be used
        if ENABLE_CHECKPOINTS & CHECKPOINTS_TREE_STRUCTURE:
            try:
                i2c_op.randomize_with(op_constraint)
            except:
                i2c_op.randomize()
        else:
            i2c_op.randomize()
        already_covered.append(
            (i2c_op.direction, i2c_op.repeat_range, i2c_op.divider_range))

        #call test sequence
        if i2c_op.direction == "read":
            yield segment_i2c_read_operation(i2c_op)
        else:
            yield segment_i2c_write_operation(i2c_op)

        if ENABLE_CHECKPOINTS:
            #if status is OK, add this simulation point to the checkpoints list
            if operations_completed[-1][1]:
                chkp_name = str(get_sim_time('ns'))
                log.info("Creating a simulation checkpoint: " + chkp_name)
                checkpoints[chkp_name] = (checkpoint(), i2c_op)

        #call APB test sequence as long as cover item apb.writeXdelay
        #coverage level is below 100%
        if apb_cover_item.coverage * 100 / apb_cover_item.size < 100:
            yield segment_apb_rw(repeat=random.randint(1, 5))

        #update the coverage level

        cov_op_prev = cov_op
        cov_op = top_cover_item.coverage * 100.0 / top_cover_item.size
        log.info("Current overall coverage level = %f %%", cov_op)

    #print summary
    log.info("Opertions finished succesfully:")
    for elem in operations_completed:
        if elem[1]:
            log.info("   %s of %d words with divider %d" %
                     (elem[0].direction, elem[0].repeat, elem[0].divider))

    log.info("Opertions finished with error:")
    for elem in operations_completed:
        if not elem[1]:
            log.info("   %s of %d words with divider %d" %
                     (elem[0].direction, elem[0].repeat, elem[0].divider))

    log.info("Functional coverage details:")
    reportCoverage(log.info, bins=False)
Ejemplo n.º 38
0
    async def _run(self):
        frame = None
        frame_offset = 0
        frame_data = None
        frame_error = None
        ifg_cnt = 0
        self.active = False

        clock_edge_event = RisingEdge(self.clock)

        while True:
            await clock_edge_event

            if self.enable is None or self.enable.value:
                if ifg_cnt > 0:
                    # in IFG
                    ifg_cnt -= 1

                elif frame is None and not self.queue.empty():
                    # send frame
                    frame = self.queue.get_nowait()
                    self.dequeue_event.set()
                    self.queue_occupancy_bytes -= len(frame)
                    self.queue_occupancy_frames -= 1
                    self.current_frame = frame
                    frame.sim_time_start = get_sim_time()
                    frame.sim_time_sfd = None
                    frame.sim_time_end = None
                    self.log.info("TX frame: %s", frame)
                    frame.normalize()

                    # convert to MII
                    frame_data = []
                    frame_error = []
                    for b, e in zip(frame.data, frame.error):
                        frame_data.append(b & 0x0F)
                        frame_data.append(b >> 4)
                        frame_error.append(e)
                        frame_error.append(e)

                    self.active = True
                    frame_offset = 0

                if frame is not None:
                    d = frame_data[frame_offset]
                    if frame.sim_time_sfd is None and d == 0xD:
                        frame.sim_time_sfd = get_sim_time()
                    self.data.value = d
                    if self.er is not None:
                        self.er.value = frame_error[frame_offset]
                    self.dv.value = 1
                    frame_offset += 1

                    if frame_offset >= len(frame_data):
                        ifg_cnt = max(self.ifg, 1)
                        frame.sim_time_end = get_sim_time()
                        frame.handle_tx_complete()
                        frame = None
                        self.current_frame = None
                else:
                    self.data.value = 0
                    if self.er is not None:
                        self.er.value = 0
                    self.dv.value = 0
                    self.active = False
                    self.idle_event.set()
Ejemplo n.º 39
0
    def handle_result(self, result):
        """Handle a test result

        Dumps result to XML and schedules the next test (if any)

        Args: result (TestComplete exception)
        """
        real_time = time.time() - self._running_test.start_time
        sim_time_ns = get_sim_time('ns') - self._running_test.start_sim_time
        ratio_time = sim_time_ns / real_time
        self.xunit.add_testcase(name=self._running_test.funcname,
                                classname=self._running_test.module,
                                time=repr(real_time),
                                sim_time_ns=repr(sim_time_ns),
                                ratio_time=repr(ratio_time))

        running_test_funcname = self._running_test.funcname

        # Helper for logging result
        def _result_was():
            result_was = ("%s (result was %s)" %
                          (running_test_funcname, result.__class__.__name__))
            return result_was

        result_pass = True

        if (isinstance(result, TestSuccess)
                and not self._running_test.expect_fail
                and not self._running_test.expect_error):
            self.log.info("Test Passed: %s" % running_test_funcname)

        elif (isinstance(result, TestFailure)
              and self._running_test.expect_fail):
            self.log.info("Test failed as expected: " + _result_was())

        elif (isinstance(result, TestSuccess)
              and self._running_test.expect_error):
            self.log.error("Test passed but we expected an error: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, TestSuccess):
            self.log.error("Test passed but we expected a failure: " +
                           _result_was())
            self._add_failure(result)
            result_pass = False

        elif isinstance(result, TestError) and self._running_test.expect_error:
            self.log.info("Test errored as expected: " + _result_was())

        elif isinstance(result, SimFailure):
            if self._running_test.expect_error:
                self.log.info("Test errored as expected: " + _result_was())
            else:
                self.log.error("Test error has lead to simulator shutting us "
                               "down")
                self._add_failure(result)
                self._store_test_result(self._running_test.module,
                                        self._running_test.funcname, False,
                                        sim_time_ns, real_time, ratio_time)
                self.tear_down()
                return

        else:
            self.log.error("Test Failed: " + _result_was())
            self._add_failure(result)
            result_pass = False

        self._store_test_result(self._running_test.module,
                                self._running_test.funcname, result_pass,
                                sim_time_ns, real_time, ratio_time)

        self.execute()
Ejemplo n.º 40
0
    async def _run_transmit(self):
        await NullTrigger()
        while True:
            while self.tx_queue.empty() and not self.send_ack.is_set() and not self.send_fc.is_set() and self.fc_initialized:
                self.tx_queue_sync.clear()
                await First(self.tx_queue_sync.wait(), self.send_ack.wait(), self.send_fc.wait())

            pkt = None

            if self.send_ack.is_set():
                # Send ACK or NAK DLLP
                # Runs when
                #  - ACK timer expires
                #  - ACK/NAK transmit requested
                self.send_ack.clear()
                if self.nak_scheduled:
                    pkt = Dllp.create_nak((self.next_recv_seq-1) & 0xfff)
                else:
                    pkt = Dllp.create_ack((self.next_recv_seq-1) & 0xfff)
            elif self.send_fc.is_set() or (not self.fc_initialized and self.tx_queue.empty()):
                # Send FC DLLP
                # Runs when
                #  - FC timer expires
                #  - FC update DLLP transmit requested
                #  - FC init is not done AND no TLPs are queued for transmit
                if self.send_fc.is_set():
                    # Send FC update DLLP
                    for fc_ch in self.fc_state:
                        if not fc_ch.active or not fc_ch.fi2:
                            continue

                        sim_time = get_sim_time()
                        if fc_ch.next_fc_p_tx <= sim_time:
                            pkt = Dllp()
                            pkt.vc = self.fc_init_vc
                            pkt.type = DllpType.UPDATE_FC_P
                            pkt.hdr_fc = fc_ch.ph.rx_credits_allocated
                            pkt.data_fc = fc_ch.pd.rx_credits_allocated
                            fc_ch.next_fc_p_tx = sim_time + self.fc_update_steps
                            break
                        if fc_ch.next_fc_np_tx <= sim_time:
                            pkt = Dllp()
                            pkt.vc = self.fc_init_vc
                            pkt.type = DllpType.UPDATE_FC_NP
                            pkt.hdr_fc = fc_ch.nph.rx_credits_allocated
                            pkt.data_fc = fc_ch.npd.rx_credits_allocated
                            fc_ch.next_fc_np_tx = sim_time + self.fc_update_steps
                            break
                        if fc_ch.next_fc_cpl_tx <= sim_time:
                            pkt = Dllp()
                            pkt.vc = self.fc_init_vc
                            pkt.type = DllpType.UPDATE_FC_CPL
                            pkt.hdr_fc = fc_ch.cplh.rx_credits_allocated
                            pkt.data_fc = fc_ch.cpld.rx_credits_allocated
                            fc_ch.next_fc_cpl_tx = sim_time + self.fc_update_steps
                            break

                if not self.fc_initialized and not pkt:
                    # Send FC init DLLP
                    fc_ch = self.fc_state[self.fc_init_vc]
                    pkt = Dllp()
                    pkt.vc = self.fc_init_vc
                    if self.fc_init_type == FcType.P:
                        pkt.type = DllpType.INIT_FC1_P if not fc_ch.fi1 else DllpType.INIT_FC2_P
                        pkt.hdr_fc = fc_ch.ph.rx_credits_allocated
                        pkt.data_fc = fc_ch.pd.rx_credits_allocated
                        self.fc_init_type = FcType.NP
                    elif self.fc_init_type == FcType.NP:
                        pkt.type = DllpType.INIT_FC1_NP if not fc_ch.fi1 else DllpType.INIT_FC2_NP
                        pkt.hdr_fc = fc_ch.nph.rx_credits_allocated
                        pkt.data_fc = fc_ch.npd.rx_credits_allocated
                        self.fc_init_type = FcType.CPL
                    elif self.fc_init_type == FcType.CPL:
                        pkt.type = DllpType.INIT_FC1_CPL if not fc_ch.fi1 else DllpType.INIT_FC2_CPL
                        pkt.hdr_fc = fc_ch.cplh.rx_credits_allocated
                        pkt.data_fc = fc_ch.cpld.rx_credits_allocated
                        self.fc_init_type = FcType.P
                        # find next active VC that hasn't finished FC init
                        for k in range(8):
                            vc = (self.fc_init_vc+1+k) % 8
                            if self.fc_state[vc].active and not self.fc_state[vc].fi2:
                                self.fc_init_vc = vc
                                break

                    # check all active VC and report FC not initialized if any are not complete
                    self.fc_initialized = True
                    for vc in range(8):
                        if self.fc_state[vc].active and not self.fc_state[vc].fi2:
                            self.fc_initialized = False

                if not pkt:
                    # no more DLLPs to send, clear event
                    self.send_fc.clear()

            if pkt is not None:
                self.log.debug("Send DLLP %s", pkt)
            elif not self.tx_queue.empty():
                pkt = self.tx_queue.get_nowait()
                pkt.seq = self.next_transmit_seq
                self.log.debug("Send TLP %s", pkt)
                self.next_transmit_seq = (self.next_transmit_seq + 1) & 0xfff
                self.retry_buffer.put_nowait(pkt)

            if pkt:
                await self.handle_tx(pkt)