Ejemplo n.º 1
0
def generate_gtkw_savefile(builder, vns, trace_fst):
    from litex.build.sim import gtkwave as gtkw
    dumpfile = os.path.join(builder.gateware_dir, "sim.{}".format("fst" if trace_fst else "vcd"))
    savefile = os.path.join(builder.gateware_dir, "sim.gtkw")
    soc = builder.soc

    with gtkw.GTKWSave(vns, savefile=savefile, dumpfile=dumpfile) as save:
        save.clocks()
        save.fsm_states(soc)
        save.add(soc.bus.slaves["main_ram"], mappers=[gtkw.wishbone_sorter(), gtkw.wishbone_colorer()])

        if hasattr(soc, 'sdrphy'):
            # all dfi signals
            save.add(soc.sdrphy.dfi, mappers=[gtkw.dfi_sorter(), gtkw.dfi_in_phase_colorer()])

            # each phase in separate group
            with save.gtkw.group("dfi phaseX", closed=True):
                for i, phase in enumerate(soc.sdrphy.dfi.phases):
                    save.add(phase, group_name="dfi p{}".format(i), mappers=[
                        gtkw.dfi_sorter(phases=False),
                        gtkw.dfi_in_phase_colorer(),
                    ])

            # only dfi command/data signals
            def dfi_group(name, suffixes):
                save.add(soc.sdrphy.dfi, group_name=name, mappers=[
                    gtkw.regex_filter(gtkw.suffixes2re(suffixes)),
                    gtkw.dfi_sorter(),
                    gtkw.dfi_per_phase_colorer(),
                ])

            dfi_group("dfi commands", ["cas_n", "ras_n", "we_n"])
            dfi_group("dfi commands", ["wrdata"])
            dfi_group("dfi commands", ["wrdata_mask"])
            dfi_group("dfi commands", ["rddata"])
Ejemplo n.º 2
0
 def dfi_group(name, suffixes):
     save.add(soc.sdrphy.dfi,
              group_name=name,
              mappers=[
                  gtkw.regex_filter(gtkw.suffixes2re(suffixes)),
                  gtkw.dfi_sorter(),
                  gtkw.dfi_per_phase_colorer(),
              ])
Ejemplo n.º 3
0
def generate_gtkw_savefile(builder, vns, trace_fst):
    from litex.build.sim import gtkwave as gtkw

    dumpfile = os.path.join(builder.gateware_dir,
                            "sim.{}".format("fst" if trace_fst else "vcd"))
    savefile = os.path.join(builder.gateware_dir, "sim.gtkw")
    soc = builder.soc
    wrphase = soc.sdram.controller.settings.phy.wrphase.reset.value

    with gtkw.GTKWSave(vns, savefile=savefile, dumpfile=dumpfile) as save:
        save.clocks()
        save.add(soc.bus.slaves["main_ram"],
                 mappers=[gtkw.wishbone_sorter(),
                          gtkw.wishbone_colorer()])
        save.fsm_states(soc)
        # all dfi signals
        save.add(soc.ddrphy.dfi,
                 mappers=[gtkw.dfi_sorter(),
                          gtkw.dfi_in_phase_colorer()])
        # each phase in separate group
        with save.gtkw.group("dfi phaseX", closed=True):
            for i, phase in enumerate(soc.ddrphy.dfi.phases):
                save.add(phase,
                         group_name="dfi p{}".format(i),
                         mappers=[
                             gtkw.dfi_sorter(phases=False),
                             gtkw.dfi_in_phase_colorer(),
                         ])
        # only dfi command signals
        save.add(soc.ddrphy.dfi,
                 group_name="dfi commands",
                 mappers=[
                     gtkw.regex_filter(
                         gtkw.suffixes2re(["cas_n", "ras_n", "we_n"])),
                     gtkw.dfi_sorter(),
                     gtkw.dfi_per_phase_colorer(),
                 ])
        # only dfi data signals
        save.add(soc.ddrphy.dfi,
                 group_name="dfi wrdata",
                 mappers=[
                     gtkw.regex_filter(
                         ["wrdata$", "p{}.*wrdata_en$".format(wrphase)]),
                     gtkw.dfi_sorter(),
                     gtkw.dfi_per_phase_colorer(),
                 ])
        save.add(soc.ddrphy.dfi,
                 group_name="dfi wrdata_mask",
                 mappers=[
                     gtkw.regex_filter(gtkw.suffixes2re(["wrdata_mask"])),
                     gtkw.dfi_sorter(),
                     gtkw.dfi_per_phase_colorer(),
                 ])
        save.add(soc.ddrphy.dfi,
                 group_name="dfi rddata",
                 mappers=[
                     gtkw.regex_filter(
                         gtkw.suffixes2re(["rddata", "p0.*rddata_valid"])),
                     gtkw.dfi_sorter(),
                     gtkw.dfi_per_phase_colorer(),
                 ])
        # serialization
        with save.gtkw.group("serialization", closed=True):
            if isinstance(soc.ddrphy, DoubleRateLPDDR4SimPHY):
                ser_groups = [("out 1x", soc.ddrphy._out),
                              ("out 2x", soc.ddrphy.out)]
            else:
                ser_groups = [("out", soc.ddrphy.out)]
            for name, out in ser_groups:
                save.group([
                    out.cs, out.dqs_o[0], out.dqs_oe, out.dmi_o[0], out.dmi_oe
                ],
                           group_name=name,
                           mappers=[
                               gtkw.regex_colorer({
                                   "yellow":
                                   gtkw.suffixes2re(["cs"]),
                                   "orange": ["_o[^e]"],
                                   "red":
                                   gtkw.suffixes2re(["oe"]),
                               })
                           ])
        with save.gtkw.group("deserialization", closed=True):
            if isinstance(soc.ddrphy, DoubleRateLPDDR4SimPHY):
                ser_groups = [("in 1x", soc.ddrphy._out),
                              ("in 2x", soc.ddrphy.out)]
            else:
                ser_groups = [("in", soc.ddrphy.out)]
            for name, out in ser_groups:
                save.group([out.dq_i[0], out.dq_oe, out.dqs_i[0], out.dqs_oe],
                           group_name=name,
                           mappers=[
                               gtkw.regex_colorer({
                                   "yellow": ["dqs"],
                                   "orange": ["dq[^s]"],
                               })
                           ])
        # dram pads
        save.group(
            [
                s for s in vars(soc.ddrphy.pads).values()
                if isinstance(s, Signal)
            ],
            group_name="pads",
            mappers=[
                gtkw.regex_filter(["clk_n$", "_[io]$"], negate=True),
                gtkw.regex_sorter(
                    gtkw.suffixes2re([
                        "cke", "odt", "reset_n", "clk_p", "cs", "ca", "dq",
                        "dqs", "dmi", "oe"
                    ])),
                gtkw.regex_colorer({
                    "yellow":
                    gtkw.suffixes2re(["cs", "ca"]),
                    "orange":
                    gtkw.suffixes2re(["dq", "dqs", "dmi"]),
                    "red":
                    gtkw.suffixes2re(["oe"]),
                }),
            ],
        )
Ejemplo n.º 4
0
    def run_test(self, dut, dfi_sys, dfi_expected, dfi_input=None, **kwargs):
        assert callable(
            dut), "dut must be a callable that returns new Dut instance"
        dfi = DFISequencer(dfi_sys)

        # Add GTKWave savefile for debugging if we are creating a VCD dumpfile (requires pyvcd installed)
        if kwargs.get("vcd_name", False):
            dumpfile = kwargs["vcd_name"]
            savefile = os.path.splitext(dumpfile)[0] + ".gtkw"
            # Create a separate dut just for the purpose of generaing a savefile
            tmp_dut = dut()
            vns = verilog.convert(tmp_dut).ns

            with gtkw.GTKWSave(vns,
                               savefile=savefile,
                               dumpfile=dumpfile,
                               prefix="") as save:
                save.clocks()
                for grp_dfi, grp_name in [(tmp_dut.dfi, "dfi new"),
                                          (tmp_dut.dfi_old, "dfi old")]:
                    with save.gtkw.group(grp_name):
                        # each phase in separate group
                        with save.gtkw.group("dfi phaseX", closed=True):
                            for i, phase in enumerate(grp_dfi.phases):
                                save.add(phase,
                                         group_name="dfi p{}".format(i),
                                         mappers=[
                                             gtkw.dfi_sorter(phases=False),
                                             gtkw.dfi_in_phase_colorer(),
                                         ])
                        # only dfi command signals
                        save.add(grp_dfi,
                                 group_name="dfi commands",
                                 mappers=[
                                     gtkw.regex_filter(
                                         gtkw.suffixes2re(
                                             ["cas_n", "ras_n", "we_n"])),
                                     gtkw.dfi_sorter(),
                                     gtkw.dfi_per_phase_colorer(),
                                 ])
                        # only dfi data signals
                        save.add(grp_dfi,
                                 group_name="dfi wrdata",
                                 mappers=[
                                     gtkw.regex_filter(["wrdata$"]),
                                     gtkw.dfi_sorter(),
                                     gtkw.dfi_per_phase_colorer(),
                                 ])
                        save.add(grp_dfi,
                                 group_name="dfi wrdata_mask",
                                 mappers=[
                                     gtkw.regex_filter(
                                         gtkw.suffixes2re(["wrdata_mask"])),
                                     gtkw.dfi_sorter(),
                                     gtkw.dfi_per_phase_colorer(),
                                 ])
                        save.add(grp_dfi,
                                 group_name="dfi rddata",
                                 mappers=[
                                     gtkw.regex_filter(
                                         gtkw.suffixes2re(
                                             ["rddata", "p0.*rddata_valid"])),
                                     gtkw.dfi_sorter(),
                                     gtkw.dfi_per_phase_colorer(),
                                 ])

        def checker(dfi):
            fail = False

            history = defaultdict(list)
            reference = defaultdict(list)

            # first cycle has undefined data until DFISequencer drives the signals
            yield

            for i, dfi_phases in enumerate(dfi_expected):
                for phase in range(len(dfi.phases)):
                    values = dfi_reset_values()
                    values.update(dfi_phases.get(phase, {}))
                    for name, ref in values.items():
                        # if name in ["rddata", "rddata_valid"]:
                        #     continue
                        val = (yield getattr(dfi.phases[phase], name))
                        msg = f"Cycle {i}, dfi.p{phase}.{name} = {val} != {ref}"
                        history[name].append(val)
                        reference[name].append(ref)
                        if not fail and val != ref:
                            fail = (val, ref, msg)
                yield

            def split_cycles(hist):
                s = ""
                for i, val in enumerate(hist):
                    s += str(val)
                    if (i + 1) % len(dfi.phases) == 0:
                        s += " "
                return s

            if fail:
                print()
                for sig in history:
                    if len(getattr(dfi.phases[0], sig)) == 1:
                        print(f"{sig:12}: {split_cycles(history[sig])}")
                        print(" " * 14 + f"{split_cycles(reference[sig])}")
                self.assertEqual(*fail)

        dut = dut()
        run_simulation(dut.ratio,
                       dut,
                       generators={
                           "sys":
                           [dfi.generator(dut.dfi),
                            dfi.reader(dut.dfi)],
                           f"sys{dut.ratio}x": [
                               checker(dut.dfi_old),
                               DFISequencer.input_generator(
                                   dut.dfi_old, dfi_input or [])
                           ],
                       },
                       **kwargs)
        dfi.assert_ok(self)