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:
parent
6f0287fecd
commit
c5137773f6
|
@ -150,8 +150,9 @@ class _Storage(Module, AutoCSR):
|
|||
self.length = CSRStorage(bits_for(depth))
|
||||
self.offset = CSRStorage(bits_for(depth))
|
||||
|
||||
self.mem_valid = CSRStatus()
|
||||
self.mem_data = CSRStatus(data_width)
|
||||
read_width = min(32, 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
|
||||
done = Signal()
|
||||
level = Signal().like(self.mem_level.status)
|
||||
self.specials += MultiReg(done, self.done.status)
|
||||
self.specials += MultiReg(level, self.mem_level.status)
|
||||
|
||||
# Memory
|
||||
mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True)
|
||||
|
@ -178,6 +181,8 @@ class _Storage(Module, AutoCSR):
|
|||
{"write": "scope", "read": "sys"})(cdc)
|
||||
self.submodules += mem, cdc
|
||||
|
||||
self.comb += level.eq(mem.level)
|
||||
|
||||
# Flush
|
||||
mem_flush = WaitTimer(depth)
|
||||
mem_flush = ClockDomainsRenamer("scope")(mem_flush)
|
||||
|
@ -218,10 +223,21 @@ class _Storage(Module, AutoCSR):
|
|||
)
|
||||
|
||||
# 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.mem_valid.status.eq(cdc.source.valid),
|
||||
cdc.source.ready.eq(self.mem_data.we | ~self.enable.storage),
|
||||
self.mem_data.status.eq(cdc.source.data)
|
||||
self.w_conv.sink.data.eq(Cat(cdc.source.data, Constant(0, pad_bits))),
|
||||
self.w_conv.sink.valid.eq(cdc.source.valid),
|
||||
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)
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -152,16 +152,31 @@ class LiteScopeAnalyzerDriver:
|
|||
def upload(self):
|
||||
if self.debug:
|
||||
print("[uploading]...")
|
||||
length = self.storage_length.read()
|
||||
for position in range(1, length + 1):
|
||||
if self.debug:
|
||||
sys.stdout.write("[{}>{}] {}%\r".format('=' * (20*position//length),
|
||||
' ' * (20-20*position//length),
|
||||
100*position//length))
|
||||
sys.stdout.flush()
|
||||
if not self.storage_mem_valid.read():
|
||||
break
|
||||
self.data.append(self.storage_mem_data.read())
|
||||
|
||||
length = self.storage_mem_level.read()
|
||||
remaining = length
|
||||
swpw = (self.data_width + 31) // 32 # Sub-Words per word
|
||||
mwbl = 192 // swpw # Max Burst len (in # of words)
|
||||
|
||||
while remaining > 0:
|
||||
rdw = min(remaining, mwbl)
|
||||
rdsw = rdw * swpw
|
||||
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:
|
||||
print("")
|
||||
return self.data
|
||||
|
|
Loading…
Reference in New Issue