Skip to content

Commit

Permalink
make it nicer :)
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Mar 28, 2024
1 parent 466ce46 commit 59b8b63
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 61 deletions.
12 changes: 12 additions & 0 deletions software/glasgow/gateware/hyperram.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ class CommandAddress(data.Struct):
address_space : AddressSpace
operation : Operation

@classmethod
def const(cls, init):
if isinstance(init, dict) and "address" in init:
init["address_low"] = init["address"] & 0b111
init["address_high"] = init["address"] >> 3
del init["address"]
return cls.as_shape().const(init)

@property
def address(self):
return Cat(self.address_low, self.address_high)
Expand Down Expand Up @@ -355,6 +363,10 @@ def elaborate(self, platform):
m = Module()
phy = self.phy

# The `rst` input resets both the sequencer, the PHY, and the RAM, which all contain bits
# of state of the interface and must be reset synchronously.
m.d.comb += phy.rst.eq(self.rst)

# The cycle counter performs double duty: it is used to time the Command/Address phase as
# well as the Latency phase after it. The counting of latency cycles starts from the third
# cycle of the Command/Address phase, so the counter starts at -1 to simplify comparisons.
Expand Down
115 changes: 54 additions & 61 deletions software/tests/gateware/test_hyperram.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@

class HyperRAMSequencerTestbench(wiring.Component):
ram_rst : In(1)
space : In(hyperram.AddressSpace)
mode : In(hyperram.Operation)
cmd_addr: In(hyperram.CommandAddress)
latency : In(range(3, 17))
start : In(24)
count : In(24)
length : In(24)
trigger : In(1) # posedge-triggered
remaining : Out(24)

def __init__(self, *, out_fifo, in_fifo):
self.out_fifo = out_fifo
Expand All @@ -34,30 +31,26 @@ def elaborate(self, platform):
m.submodules.seq = seq = hyperram.Sequencer(cs_count=1)
wiring.connect(m, seq.phy, phy)

trigger_reg = Signal.like(self.trigger)
m.d.sync += trigger_reg.eq(self.trigger)

m.d.comb += [
phy.rst.eq(self.ram_rst),
seq.rst.eq(self.ram_rst),
seq.ctl.payload.select.eq(1),
seq.ctl.payload.cmd_addr.address.eq(self.start),
seq.ctl.payload.cmd_addr.burst_type.eq(hyperram.BurstType.Linear),
seq.ctl.payload.cmd_addr.address_space.eq(self.space),
seq.ctl.payload.cmd_addr.operation.eq(self.mode),
seq.ctl.payload.cmd_addr.eq(self.cmd_addr),
seq.ctl.payload.latency.eq(self.latency),
]

trigger_reg = Signal.like(self.trigger)
m.d.sync += trigger_reg.eq(self.trigger)
with m.If(~trigger_reg & self.trigger):
m.d.sync += seq.ctl.valid.eq(1)
with m.Elif(seq.ctl.ready):
m.d.sync += seq.ctl.valid.eq(0)

with m.FSM(name="output_fsm"):
r_data_reg = Signal.like(self.out_fifo.r_data)
remaining = self.remaining # Signal.like(self.count)
remaining = Signal.like(self.length)

with m.State("Idle"):
m.d.sync += remaining.eq(self.count)
m.d.sync += remaining.eq(self.length)
with m.If(seq.ctl.valid & seq.ctl.ready):
with m.If(seq.ctl.payload.cmd_addr.operation == hyperram.Operation.Read):
m.next = "Read"
Expand Down Expand Up @@ -140,14 +133,11 @@ async def main():
HyperRAMSequencerTestbench(
out_fifo=target.fx2_crossbar.get_out_fifo(0, depth=1024, reset=reset),
in_fifo=target.fx2_crossbar.get_in_fifo(0, reset=reset))))
ram_rst_addr = target.registers.add_existing_rw(testbench.ram_rst)
space_addr = target.registers.add_existing_rw(testbench.space)
mode_addr = target.registers.add_existing_rw(testbench.mode)
latency_addr = target.registers.add_existing_rw(testbench.latency)
start_addr = target.registers.add_existing_rw(testbench.start)
count_addr = target.registers.add_existing_rw(testbench.count)
trigger_addr = target.registers.add_existing_rw(testbench.trigger)
remaining_addr = target.registers.add_existing_ro(testbench.remaining)
ram_rst_addr = target.registers.add_existing_rw(testbench.ram_rst)
cmd_addr_addr = target.registers.add_existing_rw(testbench.cmd_addr)
latency_addr = target.registers.add_existing_rw(testbench.latency)
length_addr = target.registers.add_existing_rw(testbench.length)
trigger_addr = target.registers.add_existing_rw(testbench.trigger)
await device.download_target(target.build_plan())

await device.write_register(ram_rst_addr, 1)
Expand All @@ -158,75 +148,78 @@ async def main():
device.usb_handle.claimInterface(0)
device.usb_handle.setInterfaceAltSetting(0, 1)

async def prepare(space, mode, latency, start, count):
async def prepare(addr_space, operation, latency, offset, length):
# 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)
await device.write_register(reset_addr, 0)

await device.write_register(space_addr, space.value)
await device.write_register(mode_addr, mode.value)
await device.write_register(cmd_addr_addr, hyperram.CommandAddress.const({
"operation": operation,
"burst_type": hyperram.BurstType.Linear,
"address_space": addr_space,
"address": offset,
}).as_value().value, width=6)
await device.write_register(latency_addr, latency)
await device.write_register(start_addr, start, width=3)
await device.write_register(count_addr, count, width=3)
await device.write_register(length_addr, length, width=3)
await device.write_register(trigger_addr, 1)

def display(space, mode, start, data):
def display(addr_space, operation, offset, data):
for o, n in enumerate(data):
op = (" <=" if mode == hyperram.Operation.Write else "=>")
if space == hyperram.AddressSpace.Register:
print(f"R[{start+o:#08x}] {op} {n:04x}")
if space == hyperram.AddressSpace.Memory:
print(f"M[{start+o:#010x}] {op} {n:04x}")

async def read(*, space, mode, start, count):
await prepare(space, hyperram.Operation.Read, 0, start, count)
op = (" <=" if operation == hyperram.Operation.Write else "=>")
if addr_space == hyperram.AddressSpace.Register:
print(f"R[{offset+o:#08x}] {op} {n:04x}")
if addr_space == hyperram.AddressSpace.Memory:
print(f"M[{offset+o:#010x}] {op} {n:04x}")

async def read(*, addr_space, operation, offset, length):
await prepare(addr_space, hyperram.Operation.Read, 0, offset, length)
data = b""
while len(data) < count * 2:
while len(data) < length * 2:
data += await device.bulk_read(0x86, 65536)
data = [n for (n,) in struct.iter_unpack(">H", data[:count * 2])]
# display(space, mode, start, data)
data = [n for (n,) in struct.iter_unpack(">H", data[:length * 2])]
# display(addr_space, operation, offset, data)
return data

async def write(*, space, mode, latency, start, data):
# display(space, mode, start, data)
await prepare(space, hyperram.Operation.Write, latency, start, len(data))
async def write(*, addr_space, operation, latency, offset, data):
# display(addr_space, operation, offset, data)
await prepare(addr_space, hyperram.Operation.Write, latency, offset, len(data))
data = b"".join(struct.pack(">H", n) for n in data)
await device.bulk_write(0x02, data)

async def read_reg(addr):
async def read_reg(offset):
value, = await read(
space=hyperram.AddressSpace.Register,
mode=hyperram.Operation.Read,
start=addr,
count=1
addr_space=hyperram.AddressSpace.Register,
operation=hyperram.Operation.Read,
offset=offset,
length=1
)
return value

async def write_reg(addr, value):
async def write_reg(offset, value):
await write(
space=hyperram.AddressSpace.Register,
mode=hyperram.Operation.Write,
addr_space=hyperram.AddressSpace.Register,
operation=hyperram.Operation.Write,
latency=0,
start=addr,
offset=offset,
data=[value]
)

async def read_mem(addr, length):
async def read_mem(offset, length):
return await read(
space=hyperram.AddressSpace.Memory,
mode=hyperram.Operation.Read,
start=addr,
count=length
addr_space=hyperram.AddressSpace.Memory,
operation=hyperram.Operation.Read,
offset=offset,
length=length
)

async def write_mem(start, data, *, latency):
async def write_mem(offset, data, *, latency):
await write(
space=hyperram.AddressSpace.Memory,
mode=hyperram.Operation.Write,
addr_space=hyperram.AddressSpace.Memory,
operation=hyperram.Operation.Write,
latency=latency,
start=start,
offset=offset,
data=data
)

Expand Down

0 comments on commit 59b8b63

Please sign in to comment.