core: Change upload protocol to allow bursting through xBone

Instead of using a very wide CSR, we force it to max 32 bits
and read each captured words as several sub-words.

Also, instead of checking for 'valid' flag every time, we
just read the 'level' of the memory buffer. Given the way
LiteScope works, we know capture is done and this is how many
words there is to read.

All in all this means that reading the data off the
buffer is just reading the same address over and over meaning
we can use very long bursts which helps _a_lot_ to speed things
up.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2022-03-09 22:07:27 +01:00
parent 6f0287fecd
commit c5137773f6
2 changed files with 47 additions and 16 deletions

View File

@ -150,8 +150,9 @@ class _Storage(Module, AutoCSR):
self.length = CSRStorage(bits_for(depth)) self.length = CSRStorage(bits_for(depth))
self.offset = CSRStorage(bits_for(depth)) self.offset = CSRStorage(bits_for(depth))
self.mem_valid = CSRStatus() read_width = min(32, data_width)
self.mem_data = CSRStatus(data_width) self.mem_level = CSRStatus(bits_for(depth))
self.mem_data = CSRStatus(read_width)
# # # # # #
@ -168,7 +169,9 @@ class _Storage(Module, AutoCSR):
# Status re-synchronization # Status re-synchronization
done = Signal() done = Signal()
level = Signal().like(self.mem_level.status)
self.specials += MultiReg(done, self.done.status) self.specials += MultiReg(done, self.done.status)
self.specials += MultiReg(level, self.mem_level.status)
# Memory # Memory
mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True) mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True)
@ -178,6 +181,8 @@ class _Storage(Module, AutoCSR):
{"write": "scope", "read": "sys"})(cdc) {"write": "scope", "read": "sys"})(cdc)
self.submodules += mem, cdc self.submodules += mem, cdc
self.comb += level.eq(mem.level)
# Flush # Flush
mem_flush = WaitTimer(depth) mem_flush = WaitTimer(depth)
mem_flush = ClockDomainsRenamer("scope")(mem_flush) mem_flush = ClockDomainsRenamer("scope")(mem_flush)
@ -218,10 +223,21 @@ class _Storage(Module, AutoCSR):
) )
# Memory read # Memory read
if data_width > read_width:
pad_bits = - data_width % read_width
self.submodules.w_conv = w_conv = stream.Converter(data_width + pad_bits, read_width)
self.comb += [ self.comb += [
self.mem_valid.status.eq(cdc.source.valid), self.w_conv.sink.data.eq(Cat(cdc.source.data, Constant(0, pad_bits))),
cdc.source.ready.eq(self.mem_data.we | ~self.enable.storage), self.w_conv.sink.valid.eq(cdc.source.valid),
self.mem_data.status.eq(cdc.source.data) cdc.source.ready.eq(self.w_conv.sink.ready),
]
read_source = w_conv.source
else:
read_source = cdc.source
self.comb += [
read_source.ready.eq(self.mem_data.we | ~self.enable.storage),
self.mem_data.status.eq(read_source.data)
] ]

View File

@ -152,16 +152,31 @@ class LiteScopeAnalyzerDriver:
def upload(self): def upload(self):
if self.debug: if self.debug:
print("[uploading]...") print("[uploading]...")
length = self.storage_length.read()
for position in range(1, length + 1): length = self.storage_mem_level.read()
if self.debug: remaining = length
sys.stdout.write("[{}>{}] {}%\r".format('=' * (20*position//length), swpw = (self.data_width + 31) // 32 # Sub-Words per word
' ' * (20-20*position//length), mwbl = 192 // swpw # Max Burst len (in # of words)
100*position//length))
sys.stdout.flush() while remaining > 0:
if not self.storage_mem_valid.read(): rdw = min(remaining, mwbl)
break rdsw = rdw * swpw
self.data.append(self.storage_mem_data.read()) datas = self.storage_mem_data.readfn(self.storage_mem_data.addr, length=rdsw, burst="fixed")
for i, sv in enumerate(datas):
j = i % swpw
if j == 0:
v = 0
v |= sv << (32 * j)
if j == (swpw - 1):
self.data.append(v)
remaining -= rdw
sys.stdout.write("[{}>{}] {}%\r".format('=' * (20-20*remaining//length),
' ' * (20*remaining//length),
100-(100*remaining//length)))
if self.debug: if self.debug:
print("") print("")
return self.data return self.data