Beispiel #1
0
 def __init__(self):
     self.write_port = LiteDRAMNativeWritePort(
         address_width=32, data_width=data_width)
     if pattern is not None:
         self.submodules.generator = _LiteDRAMPatternGenerator(
             self.write_port, pattern)
     else:
         self.submodules.generator = _LiteDRAMBISTGenerator(
             self.write_port)
     self.mem = DRAMMemory(data_width, len(mem_expected))
Beispiel #2
0
    def __init__(self,
                 mode="bist",
                 sdram_module="MT48LC16M16",
                 sdram_data_width=32,
                 bist_base=0x0000000,
                 bist_end=0x0100000,
                 bist_length=1024,
                 bist_random=False,
                 bist_alternating=False,
                 num_generators=1,
                 num_checkers=1,
                 access_pattern=None,
                 **kwargs):
        assert mode in ["bist", "pattern"]
        assert not (mode == "pattern" and access_pattern is None)

        # SimSoC -----------------------------------------------------------------------------------
        SimSoC.__init__(self,
                        with_sdram=True,
                        sdram_module=sdram_module,
                        sdram_data_width=sdram_data_width,
                        **kwargs)

        # BIST/Pattern Generator / Checker ---------------------------------------------------------
        if mode == "pattern":
            make_generator = lambda: _LiteDRAMPatternGenerator(
                self.sdram.crossbar.get_port(), init=access_pattern)
            make_checker = lambda: _LiteDRAMPatternChecker(
                self.sdram.crossbar.get_port(), init=access_pattern)
        if mode == "bist":
            make_generator = lambda: _LiteDRAMBISTGenerator(self.sdram.crossbar
                                                            .get_port())
            make_checker = lambda: _LiteDRAMBISTChecker(self.sdram.crossbar.
                                                        get_port())

        generators = [make_generator() for _ in range(num_generators)]
        checkers = [make_checker() for _ in range(num_checkers)]
        self.submodules += generators + checkers

        if mode == "pattern":

            def bist_config(module):
                return []

            if not bist_alternating:
                address_set = set()
                for addr, _ in access_pattern:
                    assert addr not in address_set, \
                        "Duplicate address 0x%08x in access_pattern, write will overwrite previous value!" % addr
                    address_set.add(addr)
        if mode == "bist":
            # Make sure that we perform at least one access
            bist_length = max(bist_length,
                              self.sdram.controller.interface.data_width // 8)

            def bist_config(module):
                return [
                    module.base.eq(bist_base),
                    module.end.eq(bist_end),
                    module.length.eq(bist_length),
                    module.random_addr.eq(bist_random),
                ]

            assert not (bist_random and not bist_alternating), \
                "Write to random address may overwrite previously written data before reading!"

            # Check address correctness
            assert bist_end > bist_base
            assert bist_end <= 2**(len(
                generators[0].end)) - 1, "End address outside of range"
            bist_addr_range = bist_end - bist_base
            assert bist_addr_range > 0 and bist_addr_range & (bist_addr_range - 1) == 0, \
                "Length of the address range must be a power of 2"

        def combined_read(modules, signal, operator):
            sig = Signal()
            self.comb += sig.eq(
                reduce(operator, (getattr(m, signal) for m in modules)))
            return sig

        def combined_write(modules, signal):
            sig = Signal()
            self.comb += [getattr(m, signal).eq(sig) for m in modules]
            return sig

        # Sequencer --------------------------------------------------------------------------------
        class LiteDRAMCoreControl(Module, AutoCSR):
            def __init__(self):
                self.init_done = CSRStorage()
                self.init_error = CSRStorage()

        self.submodules.ddrctrl = ddrctrl = LiteDRAMCoreControl()
        self.add_csr("ddrctrl")

        display = Signal()
        finish = Signal()
        self.submodules.fsm = fsm = FSM(reset_state="WAIT-INIT")
        fsm.act(
            "WAIT-INIT",
            If(
                self.ddrctrl.init_done.
                storage,  # Written by CPU when initialization is done
                NextState("BIST-GENERATOR")))
        if bist_alternating:
            # Force generators to wait for checkers and vice versa. Connect them in pairs, with each
            # unpaired connected to the first of the others.
            bist_connections = []
            for generator, checker in zip_longest(generators, checkers):
                g = generator or generators[0]
                c = checker or checkers[0]
                bist_connections += [
                    g.run_cascade_in.eq(c.run_cascade_out),
                    c.run_cascade_in.eq(g.run_cascade_out),
                ]

            fsm.act(
                "BIST-GENERATOR",
                combined_write(generators + checkers, "start").eq(1),
                *bist_connections, *map(bist_config, generators + checkers),
                If(combined_read(checkers, "done", and_),
                   NextState("DISPLAY")))
        else:
            fsm.act(
                "BIST-GENERATOR",
                combined_write(generators, "start").eq(1),
                *map(bist_config, generators),
                If(combined_read(generators, "done", and_),
                   NextState("BIST-CHECKER")))
            fsm.act(
                "BIST-CHECKER",
                combined_write(checkers, "start").eq(1),
                *map(bist_config, checkers),
                If(combined_read(checkers, "done", and_),
                   NextState("DISPLAY")))
        fsm.act("DISPLAY", display.eq(1), NextState("FINISH"))
        fsm.act("FINISH", finish.eq(1))

        # Simulation Results -----------------------------------------------------------------------
        def max_signal(signals):
            signals = iter(signals)
            s = next(signals)
            out = Signal(len(s))
            self.comb += out.eq(s)
            for curr in signals:
                prev = out
                out = Signal(max(len(prev), len(curr)))
                self.comb += If(prev > curr, out.eq(prev)).Else(out.eq(curr))
            return out

        generator_ticks = max_signal((g.ticks for g in generators))
        checker_errors = max_signal((c.errors for c in checkers))
        checker_ticks = max_signal((c.ticks for c in checkers))

        self.sync += [
            If(
                display,
                Display("BIST-GENERATOR ticks:  %08d", generator_ticks),
                Display("BIST-CHECKER errors:   %08d", checker_errors),
                Display("BIST-CHECKER ticks:    %08d", checker_ticks),
            )
        ]

        # Simulation End ---------------------------------------------------------------------------
        end_timer = WaitTimer(2**16)
        self.submodules += end_timer
        self.comb += end_timer.wait.eq(finish)
        self.sync += If(end_timer.done, Finish())