diff --git a/litescope/core.py b/litescope/core.py index 2c6bd42..1ae3f63 100644 --- a/litescope/core.py +++ b/litescope/core.py @@ -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) # # # @@ -167,8 +168,10 @@ class _Storage(Module, AutoCSR): self.specials += MultiReg(self.offset.storage, offset, "scope") # Status re-synchronization - done = Signal() + 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.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 += [ - 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) + read_source.ready.eq(self.mem_data.we | ~self.enable.storage), + self.mem_data.status.eq(read_source.data) ] diff --git a/litescope/software/driver/analyzer.py b/litescope/software/driver/analyzer.py index ee9d9ec..f3bebfd 100644 --- a/litescope/software/driver/analyzer.py +++ b/litescope/software/driver/analyzer.py @@ -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