def testbench(): from nmigen.sim.pysim import Settle, Simulator unit = NotGate() def bench(): yield unit.input.eq(0) yield Settle() assert (yield unit.output) yield unit.input.eq(1) yield Settle() assert not (yield unit.output) sim = Simulator(unit) sim.add_process(bench) with sim.write_vcd("notgate.vcd", "notgate.gtkw", traces=[unit.input, unit.output]): sim.run()
def elaborate(self, platform): m = Module() m.submodules += [ self.timing, self.still, ] return m if __name__ == '__main__': color_depth = 4 image = gradient(color_depth=color_depth) timing = VgaTiming(resolutions[ResolutionName.VGA_640_480p_60hz]) dut = TestBench( timing, Still(timing, color_depth=color_depth, image=image), ) sim = Simulator(dut) def proc(): for _ in range(800 * 40): yield sim.add_clock(1e-6, domain='pixel') sim.add_sync_process(proc, domain='pixel') with sim.write_vcd('still.vcd'): sim.run()
m.d.comb += dllpt.send.eq(1) sim = Simulator(m) sim.add_clock(1 / 125e6, domain="rx") # The other two DLLPs received from the ROCKPro64 # Refer to layouts.py for the layout of the dllp record dllp_1 = 0b1000011100000001000000000100 dllp_2 = 0b1000000100000001000000000101 def process(): yield dllpt.dllp.eq(dllp_1) #yield dllpt.dllp.valid.eq(0) for _ in range(20): print(hex((yield dllpt.source.symbol[0])), end="\t") print(hex((yield dllpt.source.symbol[1])), end="\t") print(hex((yield dllpt.source.symbol[2])), end="\t") print(hex((yield dllpt.source.symbol[3]))) print(hex((yield dllpt.dllp))) print(hex((yield dllpt.dllp.valid))) print(hex((yield dllpt.dllp_data))) #print(hex((yield dllpt.symbols[0])), end="\t") #print(hex((yield dllpt.symbols[1]))) #print(hex((yield dllpt.crc_out))) print() yield sim.add_sync_process(process, domain="rx") with sim.write_vcd("test.vcd", "test.gtkw"): sim.run()
class LunaGatewareTestCase(unittest.TestCase): domain = 'sync' # Convenience property: if set, instantiate_dut will automatically create # the relevant fragment with FRAGMENT_ARGUMENTS. FRAGMENT_UNDER_TEST = None FRAGMENT_ARGUMENTS = {} # Convenience properties: if not None, a clock with the relevant frequency # will automatically be added. FAST_CLOCK_FREQUENCY = None SYNC_CLOCK_FREQUENCY = 120e6 USB_CLOCK_FREQUENCY = None def instantiate_dut(self): """ Basic-most function to instantiate a device-under-test. By default, instantiates FRAGMENT_UNDER_TEST. """ return self.FRAGMENT_UNDER_TEST(**self.FRAGMENT_ARGUMENTS) def get_vcd_name(self): """ Return the name to use for any VCDs generated by this class. """ return "test_{}".format(self.__class__.__name__) def setUp(self): self.dut = self.instantiate_dut() self.sim = Simulator(self.dut) if self.USB_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.USB_CLOCK_FREQUENCY, domain="usb") if self.SYNC_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.SYNC_CLOCK_FREQUENCY, domain="sync") if self.FAST_CLOCK_FREQUENCY: self.sim.add_clock(1 / self.FAST_CLOCK_FREQUENCY, domain="fast") def initialize_signals(self): """ Provide an opportunity for the test apparatus to initialize siganls. """ yield Signal() def traces_of_interest(self): """ Returns an interable of traces to include in any generated output. """ # Default to including all signals. return self.sim._signal_names def simulate(self, *, vcd_suffix=None): """ Runs our core simulation. """ # If we're generating VCDs, run the test under a VCD writer. if os.getenv('GENERATE_VCDS', default=False): # Figure out the name of our VCD files... vcd_name = self.get_vcd_name() if vcd_suffix: vcd_name = "{}_{}".format(vcd_name, vcd_suffix) # ... and run the simulation while writing them. traces = self.traces_of_interest() with self.sim.write_vcd(vcd_name + ".vcd", vcd_name + ".gtkw", traces=traces): self.sim.run() else: self.sim.run() @staticmethod def pulse(signal, *, step_after=True): """ Helper method that asserts a signal for a cycle. """ yield signal.eq(1) yield yield signal.eq(0) if step_after: yield @staticmethod def advance_cycles(cycles): """ Helper methods that waits for a given number of cycles. """ for _ in range(cycles): yield @staticmethod def wait_until(strobe, *, timeout=None): """ Helper method that advances time until a strobe signal becomes true. """ cycles_passed = 0 while not (yield strobe): yield cycles_passed += 1 if timeout and cycles_passed > timeout: raise RuntimeError( f"Timeout waiting for '{strobe.name}' to go high!") def _ensure_clocks_present(self): """ Function that validates that a clock is present for our simulation domain. """ frequencies = { 'sync': self.SYNC_CLOCK_FREQUENCY, 'usb': self.USB_CLOCK_FREQUENCY, 'fast': self.FAST_CLOCK_FREQUENCY, } self.assertIsNotNone( frequencies[self.domain], f"no frequency provied for `{self.domain}`-domain clock!") def wait(self, time): """ Helper method that waits for a given number of seconds in a *_test_case. """ # Figure out the period of the clock we want to work with... if self.domain == 'sync': period = 1 / self.SYNC_CLOCK_FREQUENCY elif self.domain == 'usb': period = 1 / self.USB_CLOCK_FREQUENCY elif self.domain == 'fast': period = 1 / self.FAST_CLOCK_FREQUENCY # ... and, accordingly, how many cycles we want to delay. cycles = math.ceil(time / period) print(cycles) # Finally, wait that many cycles. yield from self.advance_cycles(cycles)
""" from nmigen import Signal, Elaboratable, Module from nmigen.sim.pysim import Simulator class Top(Elaboratable): def __init__(self): self.counter = Signal(range(10)) def elaborate(self, platform): m = Module() m.d.sync += self.counter.eq(self.counter + 1) return m if __name__ == '__main__': def process(): for tick in range(10): print(f"counter = {(yield dut.counter)}") yield dut = Top() sim = Simulator(dut) sim.add_clock(1e-6) sim.add_sync_process(process) with sim.write_vcd(f"{__file__[:-3]}.vcd"): sim.run()
# immediate=0, # ), # ], # ) timing = VgaTiming(res) dut = TestBench( PixelProcessor( timing, num_pixels=8, pixel_width=12, pixel_depth=4, # resolution=res, # pixel_depth=4, # stride=4, # instruction_depth=program_mem.depth, # program_mem=program_mem, ), timing, # PixelFifo(width=16, depth=16), ) sim = Simulator(dut) def proc(): yield from ppu_tb(dut) sim.add_clock(1e-6, domain='pixel') sim.add_sync_process(proc, domain='pixel') with sim.write_vcd('ppu.vcd'): sim.run()