From 1c9015dae6791817e20f2f12ed3a3caecf69b3ed Mon Sep 17 00:00:00 2001 From: Catherine Date: Fri, 10 Nov 2023 22:34:37 +0000 Subject: [PATCH] tmp --- software/glasgow/gateware/hyperram.py | 46 +++++++------ software/tests/gateware/test_hyperram.py | 87 +++++++++++++++++++----- 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/software/glasgow/gateware/hyperram.py b/software/glasgow/gateware/hyperram.py index f2be04c5f..a7ee6946d 100644 --- a/software/glasgow/gateware/hyperram.py +++ b/software/glasgow/gateware/hyperram.py @@ -57,8 +57,6 @@ class PHYx1(wiring.Component): All of the inputs and outputs are registered, with one cycle of latency. """ - gearing = 1 - def __init__(self, resource, *, cs_count=1): if not isinstance(cs_count, int) or not cs_count >= 1: raise ValueError(f"CS# count must be a positive integer, not {cs_count!r}") @@ -174,20 +172,16 @@ def elaborate(self, platform): pins_cs_n.o.eq(~Cat(self.select == n for n in range(1, self.cs_count + 1))), pins_rwds.oe.eq(self.rwds.oe), pins_rwds.o.eq(self.rwds.o[1]), - self.rwds.i.eq(Cat(reg_rwds_i0, reg_rwds_i1)), + self.rwds.i.eq(Cat(reg_rwds_i0, pins_rwds.i)), pins_dq.oe.eq(self.data.oe), pins_dq.o.eq(self.data.o[8:]), - self.data.i.eq(Cat(reg_dq_i0, reg_dq_i1)), + self.data.i.eq(Cat(reg_dq_i0, pins_dq.i)), ] m.d.sync += [ reg_rwds_oe.eq(self.rwds.oe), reg_rwds_o.eq(self.rwds.o[0]), reg_dq_oe.eq(self.data.oe), reg_dq_o.eq(self.data.o[:8]), - reg_rwds_i0.eq(pins_rwds.i), - reg_rwds_i1.eq(reg_rwds_i0), - reg_dq_i0.eq(pins_dq.i), - reg_dq_i1.eq(reg_dq_i0), ] m.d.comb += [ self.ready.eq(1), @@ -198,6 +192,10 @@ def elaborate(self, platform): pins_cs_n.en.eq(1), ] with m.If(self.valid): + m.d.sync += [ + reg_rwds_i1.eq(pins_rwds.i), + reg_dq_i1.eq(pins_dq.i), + ] m.d.comb += [ pins_rwds.en.eq(1), pins_dq.en.eq(1), @@ -207,13 +205,6 @@ def elaborate(self, platform): pins.ck_n.o1.eq(0), ] m.next = "Falling" - with m.Else(): - m.d.comb += [ - pins.ck_p.o0.eq(0), - pins.ck_p.o1.eq(0), - pins.ck_n.o0.eq(1), - pins.ck_n.o1.eq(1), - ] with m.State("Falling"): m.d.comb += [ @@ -224,15 +215,13 @@ def elaborate(self, platform): pins_dq.o.eq(reg_dq_o), self.data.i.eq(Cat(reg_dq_i0, reg_dq_i1)), ] + # The HyperBus specification forbids pausing or stopping the clock in the non-idle + # state, so after the rising edge is generated, this state machine unconditionally + # falls through to generating the falling edge. m.d.sync += [ reg_rwds_i0.eq(pins_rwds.i), - reg_rwds_i1.eq(reg_rwds_i0), reg_dq_i0.eq(pins_dq.i), - reg_dq_i1.eq(reg_dq_i0), ] - # The HyperBus specification forbids pausing or stopping the clock in the non-idle - # state, so after the rising edge is generated, this state machine unconditionally - # falls through to generating the falling edge. m.d.comb += [ pins_rwds.en.eq(1), pins_dq.en.eq(1), @@ -409,13 +398,28 @@ def elaborate(self, platform): with m.If(cycle == 3): m.next = "Read" + # with m.State("Read1"): + # m.d.comb += [ + # phy.valid.eq(1), + # phy.select.eq(select), + # ] + # with m.If(phy.ready & (phy.rwds.i == Cat(0, 1))): + # m.next = "Read" + with m.State("Read"): m.d.comb += [ phy.valid.eq(self.read.ready), phy.select.eq(select), self.read.payload.data.eq(phy.data.i), - self.read.valid.eq(phy.ready & (phy.rwds.i == Cat(0, 1))), # im snbity :|3 + self.read.valid.eq(phy.ready), ] + # with m.If(phy.ready & (phy.rwds.i != Cat(0, 1))): # im snbity :|3 + # # 'Prime' the memory by clocking it until it outputs the next data word + # # whenever it responds with a latency cycle. + # m.d.comb += [ + # phy.valid.eq(1), + # self.read.valid.eq(0), + # ] with m.If(self.control.valid): m.next = "Idle" diff --git a/software/tests/gateware/test_hyperram.py b/software/tests/gateware/test_hyperram.py index bdd9f4206..2158049a9 100644 --- a/software/tests/gateware/test_hyperram.py +++ b/software/tests/gateware/test_hyperram.py @@ -18,9 +18,10 @@ class HyperRAMSequencerTestbench(wiring.Component): # - target? (sometimes it's source) # - ? - def __init__(self, *, out_fifo, in_fifo): + def __init__(self, *, out_fifo, in_fifo, ila_fifo): self.out_fifo = out_fifo self.in_fifo = in_fifo + self.ila_fifo = ila_fifo super().__init__() @@ -29,7 +30,7 @@ def elaborate(self, platform): m = Module() - m.submodules.phy = phy = hyperram.PHYx1(resource=("hyperram", 0)) + m.submodules.phy = Fragment.get(phy := hyperram.PHYx1(resource=("hyperram", 0)), platform) m.submodules.seq = seq = hyperram.Sequencer(phy) trigger_r = Signal.like(self.trigger) @@ -40,8 +41,9 @@ def elaborate(self, platform): Cat(seq.control.payload.cmd_addr.address_low, seq.control.payload.cmd_addr.address_high).eq(self.first), seq.control.payload.cmd_addr.burst_type.eq(hyperram.BurstType.Linear), - seq.control.payload.cmd_addr.address_space.eq(hyperram.AddressSpace.Register), + seq.control.payload.cmd_addr.address_space.eq(hyperram.AddressSpace.Memory), seq.control.payload.cmd_addr.operation.eq(self.mode), + # seq.control.payload.cmd_addr.eq(0x800000000001), seq.control.payload.latency.eq(7), # FIXME: configurable? seq.control.valid.eq(~trigger_r & self.trigger), ] @@ -55,7 +57,7 @@ def elaborate(self, platform): m.d.comb += [ self.out_fifo.r_en.eq(1), ] - with m.If(self.out_fifo.r_rdy): + with m.If(self.out_fifo.r_rdy & self.out_fifo.r_en): m.next = "LSB" with m.State("LSB"): @@ -65,7 +67,7 @@ def elaborate(self, platform): seq.write.valid.eq(self.out_fifo.r_rdy), self.out_fifo.r_en.eq(seq.write.ready), ] - with m.If(self.out_fifo.r_rdy): + with m.If(self.out_fifo.r_rdy & self.out_fifo.r_en): m.next = "MSB" with m.FSM(name="read_fsm"): @@ -73,8 +75,9 @@ def elaborate(self, platform): m.d.comb += [ self.in_fifo.w_data.eq(seq.read.payload.data[8:]), self.in_fifo.w_en.eq(seq.read.valid), + seq.read.ready.eq(0), ] - with m.If(seq.read.valid & self.in_fifo.w_rdy): + with m.If(self.in_fifo.w_rdy & self.in_fifo.w_en): m.next = "LSB" # moth m.State("LSB"): # moth state bc transient @@ -84,9 +87,47 @@ def elaborate(self, platform): self.in_fifo.w_en.eq(1), seq.read.ready.eq(self.in_fifo.w_rdy), ] - with m.If(self.in_fifo.w_rdy): + with m.If(self.in_fifo.w_rdy & self.in_fifo.w_en): m.next = "MSB" + m.submodules.ila_mem = ila_mem = fifo.SyncFIFOBuffered(depth=256, width=16) + + with m.FSM() as ila_upload_fsm: + with m.State("MSB"): + m.d.comb += [ + self.ila_fifo.w_data.eq(ila_mem.r_data[8:]), + self.ila_fifo.w_en.eq(ila_mem.r_rdy), + ila_mem.r_en.eq(0), + ] + with m.If(self.ila_fifo.w_rdy & self.ila_fifo.w_en): + m.next = "LSB" + + with m.State("LSB"): + m.d.comb += [ + self.ila_fifo.w_data.eq(ila_mem.r_data[:8]), + self.ila_fifo.w_en.eq(1), + ila_mem.r_en.eq(self.ila_fifo.w_rdy), + ] + with m.If(self.ila_fifo.w_rdy & self.ila_fifo.w_en): + m.next = "MSB" + + with m.FSM() as ila_sample_fsm: + with m.State("Idle"): + with m.If(self.trigger): + m.next = "Sampling" + with m.State("Sampling"): + with m.If(~ila_mem.w_rdy): + m.next = "Done" + with m.State("Done"): + pass + + m.d.comb += [ + # ila_mem.w_data.eq(Cat(phy.pins_dq.i, phy.pins_rwds.i, phy.pins_cs_n.i)), + # ila_mem.w_data.eq(seq.read.payload), + ila_mem.w_data.eq(Cat(phy.data.i[:12], 0, 0, 0, phy.ready)), + ila_mem.w_en.eq(ila_sample_fsm.ongoing("Sampling")), + ] + return m @@ -105,7 +146,8 @@ async def main(): target.add_submodule(testbench := ResetInserter(reset)( HyperRAMSequencerTestbench( out_fifo=target.fx2_crossbar.get_out_fifo(0, reset=reset), - in_fifo=target.fx2_crossbar.get_in_fifo(0, reset=reset, auto_flush=True)))) + in_fifo=target.fx2_crossbar.get_in_fifo(0, reset=reset, auto_flush=False), + ila_fifo=target.fx2_crossbar.get_in_fifo(1, reset=reset, auto_flush=False)))) mode_addr = target.registers.add_existing_rw(testbench.mode) first_addr = target.registers.add_existing_rw(testbench.first) count_addr = target.registers.add_existing_rw(testbench.count) @@ -113,30 +155,43 @@ async def main(): await device.download_target(target.build_plan()) print("Running...") + device.usb_handle.setConfiguration(1) device.usb_handle.claimInterface(0) + device.usb_handle.claimInterface(1) device.usb_handle.setInterfaceAltSetting(0, 1) + device.usb_handle.setInterfaceAltSetting(1, 1) + + async def download_ila(): + for index, (word,) in enumerate(struct.iter_unpack(">H", await device.bulk_read(0x88, 512))): + print(f"{word>>8:02x}.{word&0xff:02x}", end="\n" if index % 16 == 15 else " ") async def prepare(mode, first, count): # reset testbench and clear FIFOs await device.write_register(reset_addr, 1) + await device.write_register(trigger_addr, 0) device.usb_handle.setInterfaceAltSetting(0, 1) + device.usb_handle.setInterfaceAltSetting(1, 1) await device.write_register(reset_addr, 0) - await device.write_register(mode_addr, mode) - await device.write_register(first_addr, first) - await device.write_register(count_addr, count) - await device.write_register(trigger_addr, 0) - await device.write_register(trigger_addr, 1) + await device.write_register(mode_addr, mode.value) + await device.write_register(first_addr, first, width=3) + await device.write_register(count_addr, count, width=3) async def read(first, count): await prepare(hyperram.Operation.Read, first, count) - return list(struct.iter_unpack(">H", await device.bulk_read(0x86, count * 2))) + await device.write_register(trigger_addr, 1) + await download_ila() + data = await device.bulk_read(0x86, 512) + return [n for (n,) in struct.iter_unpack(">H", data[:count * 2])] async def write(first, data): await prepare(hyperram.Operation.Write, first, len(data)) - await device.bulk_write(0x82, b"".join(struct.pack(">H", n) for n in data)) # lolficiency + await device.bulk_write(0x02, b"".join(struct.pack(">H", n) for n in data)) # lolficiency + await device.write_register(trigger_addr, 1) + await download_ila() - print(await read(0, 8)) + await write(0, list(range(0x5510, 0x5520))) + print(await read(0, 16)) # class HyperRAMHardwareTestbench(Elaboratable):