add Run Length Encoding

This commit is contained in:
Florent Kermarrec 2013-03-23 13:57:59 +01:00
parent eeab7051be
commit 492a5acfe3
6 changed files with 178 additions and 65 deletions

1
README
View File

@ -36,6 +36,7 @@ to be ready to debug!
[> Status: [> Status:
Miio & Mila working on board with standard term. Miio & Mila working on board with standard term.
RLE working on board.
RangeDetector and EdgeDector terms not tested. RangeDetector and EdgeDector terms not tested.
[> Examples: [> Examples:

View File

@ -16,6 +16,7 @@ trig_w = 16
dat_w = 16 dat_w = 16
rec_size = 512 rec_size = 512
rec_offset = 32 rec_offset = 32
enable_rle = True
# Miscope Configuration # Miscope Configuration
# MiLa # MiLa
@ -35,6 +36,8 @@ def capture(size):
sum_tt = gen_truth_table("term") sum_tt = gen_truth_table("term")
mila.trigger.sum.set(sum_tt) mila.trigger.sum.set(sum_tt)
mila.recorder.reset() mila.recorder.reset()
if enable_rle:
mila.recorder.enable_rle()
recorder.set_size(rec_size) recorder.set_size(rec_size)
mila.recorder.set_offset(rec_offset) mila.recorder.set_offset(rec_offset)
mila.recorder.arm() mila.recorder.arm()
@ -46,7 +49,7 @@ def capture(size):
print("-Receiving Data...", end=' ') print("-Receiving Data...", end=' ')
sys.stdout.flush() sys.stdout.flush()
dat_vcd += mila.recorder.pull(size) dat_vcd += mila.recorder.pull(rec_size)
print("[Done]") print("[Done]")
print("Capturing ...") print("Capturing ...")
@ -61,6 +64,9 @@ mila_layout = [
("cnt", 8), ("cnt", 8),
] ]
if enable_rle:
dat_vcd = dat_vcd.decode_rle()
myvcd = Vcd() myvcd = Vcd()
myvcd.add_from_layout(mila_layout, dat_vcd) myvcd.add_from_layout(mila_layout, dat_vcd)
myvcd.write("test_mila.vcd") myvcd.write("test_mila.vcd")

View File

@ -81,24 +81,88 @@ class Storage:
return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment() return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment()
class RLE:
#
# Definition
#
def __init__(self, width, length):
self.width = width
self.length = length
# Control
self.enable = Signal()
# Input
self.dat_i = Signal(width)
# Output
self.stb_o = Signal()
self.dat_o = Signal(width)
def get_fragment(self):
# Register Input
dat_i_d = Signal(self.width)
sync =[dat_i_d.eq(self.dat_i)]
# Detect diff
diff = Signal()
comb = [diff.eq(~self.enable | (dat_i_d != self.dat_i))]
diff_rising = RisingEdge(diff)
diff_d = Signal()
sync +=[diff_d.eq(diff)]
# Generate RLE word
rle_cnt = Signal(max=self.length)
rle_max = Signal()
comb +=[If(rle_cnt == self.length, rle_max.eq(self.enable))]
sync +=[
If(diff | rle_max,
rle_cnt.eq(0)
).Else(
rle_cnt.eq(rle_cnt + 1)
)
]
# Mux RLE word and data
comb +=[
If(diff_rising.o & (~rle_max),
self.stb_o.eq(1),
self.dat_o[self.width-1].eq(1),
self.dat_o[:len(rle_cnt)].eq(rle_cnt)
).Elif(diff_d | rle_max,
self.stb_o.eq(1),
self.dat_o.eq(dat_i_d)
).Else(
self.stb_o.eq(0),
)
]
return Fragment(comb, sync) + diff_rising.get_fragment()
class Sequencer: class Sequencer:
# #
# Definition # Definition
# #
def __init__(self): def __init__(self):
# Controller interface # Control
self.rst = Signal() self.rst = Signal()
self.arm = Signal() self.arm = Signal()
# Trigger interface # Trigger
self.hit = Signal() self.hit = Signal()
# Recorder interface # Recorder
self.start = Signal() self.start = Signal()
self.done = Signal() self.done = Signal()
# Others # Internal
self.enable = Signal() self.enable = Signal()
def get_fragment(self): def get_fragment(self):
@ -129,12 +193,13 @@ class Sequencer:
REC_RST_BASE = 0x00 REC_RST_BASE = 0x00
REC_ARM_BASE = 0x01 REC_RLE_BASE = 0x01
REC_DONE_BASE = 0x02 REC_ARM_BASE = 0x02
REC_SIZE_BASE = 0x03 REC_DONE_BASE = 0x03
REC_OFFSET_BASE = 0x05 REC_SIZE_BASE = 0x04
REC_READ_BASE = 0x07 REC_OFFSET_BASE = 0x06
REC_READ_DATA_BASE = 0x08 REC_READ_BASE = 0x08
REC_READ_DATA_BASE = 0x09
class Recorder: class Recorder:
# #
@ -147,9 +212,11 @@ class Recorder:
self.storage = Storage(self.width, self.depth) self.storage = Storage(self.width, self.depth)
self.sequencer = Sequencer() self.sequencer = Sequencer()
self.rle = RLE(self.width, (2**(width-2)))
# csr interface # csr interface
self._rst = RegisterField("rst", reset=1) self._rst = RegisterField("rst", reset=1)
self._rle = RegisterField("rle", reset=0)
self._arm = RegisterField("arm", reset=0) self._arm = RegisterField("arm", reset=0)
self._done = RegisterField("done", reset=0, access_bus=READ_ONLY, self._done = RegisterField("done", reset=0, access_bus=READ_ONLY,
access_dev=WRITE_ONLY) access_dev=WRITE_ONLY)
@ -161,7 +228,7 @@ class Recorder:
self._pull_dat = RegisterField("pull_dat", self.width, reset=1, self._pull_dat = RegisterField("pull_dat", self.width, reset=1,
access_bus=READ_ONLY, access_dev=WRITE_ONLY) access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self.regs = [self._rst, self._arm, self._done, self._size, self._offset, self.regs = [self._rst, self._rle, self._arm, self._done, self._size, self._offset,
self._pull_stb, self._pull_dat] self._pull_stb, self._pull_dat]
# set address / interface # set address / interface
@ -188,6 +255,7 @@ class Recorder:
self.sequencer.rst.eq(self._rst.field.r), self.sequencer.rst.eq(self._rst.field.r),
self.storage.rst.eq(self._rst.field.r), self.storage.rst.eq(self._rst.field.r),
self.rle.enable.eq(self._rle.field.r),
self.sequencer.arm.eq(self._arm.field.r), self.sequencer.arm.eq(self._arm.field.r),
self.storage.offset.eq(self._offset.field.r), self.storage.offset.eq(self._offset.field.r),
self.storage.size.eq(self._size.field.r), self.storage.size.eq(self._size.field.r),
@ -204,13 +272,17 @@ class Recorder:
self.sequencer.done.eq(self.storage.done), self.sequencer.done.eq(self.storage.done),
self.sequencer.hit.eq(self.hit), self.sequencer.hit.eq(self.hit),
self.storage.push_stb.eq(self.sequencer.enable), self.rle.dat_i.eq(self.dat),
self.storage.push_dat.eq(self.dat)
self.storage.push_stb.eq(self.sequencer.enable & self.rle.stb_o),
self.storage.push_dat.eq(self.rle.dat_o)
] ]
return self.bank.get_fragment() + Fragment(comb) +\ return self.bank.get_fragment() + Fragment(comb) +\
self.storage.get_fragment() + self.sequencer.get_fragment() +\ self.storage.get_fragment() + self.sequencer.get_fragment() +\
_pull_stb_rising.get_fragment() _pull_stb_rising.get_fragment() + self.rle.get_fragment()
# #
# Driver # Driver
@ -218,7 +290,13 @@ class Recorder:
def reset(self): def reset(self):
self.interface.write(self.bank.get_base() + REC_RST_BASE, 1) self.interface.write(self.bank.get_base() + REC_RST_BASE, 1)
self.interface.write(self.bank.get_base() + REC_RST_BASE, 0) self.interface.write(self.bank.get_base() + REC_RST_BASE, 0)
def enable_rle(self):
self.interface.write(self.bank.get_base() + REC_RLE_BASE, 1)
def disable_rle(self):
self.interface.write(self.bank.get_base() + REC_RLE_BASE, 0)
def arm(self): def arm(self):
self.interface.write(self.bank.get_base() + REC_ARM_BASE, 1) self.interface.write(self.bank.get_base() + REC_ARM_BASE, 1)
self.interface.write(self.bank.get_base() + REC_ARM_BASE, 0) self.interface.write(self.bank.get_base() + REC_ARM_BASE, 0)

View File

@ -40,6 +40,25 @@ class VcdDat(list):
else: else:
raise KeyError raise KeyError
def decode_rle(self):
rle_bit = self[-1]
rle_dat = self[:self.width-1]
dat = VcdDat(self.width)
i=0
last = 0
for d in self:
if rle_bit[i]:
if len(dat) >= 1:
# FIX ME... why is rle_dat in reverse orderd...
for j in range(int(dec2bin(rle_dat[i])[::-1],2)):
dat.append(last)
else:
dat.append(d)
last = d
i +=1
return dat
class Var: class Var:
def __init__(self, name, width, values=[], type="wire", default="x"): def __init__(self, name, width, values=[], type="wire", default="x"):
self.type = type self.type = type

View File

@ -5,7 +5,7 @@ from migen.sim.generic import Simulator, PureSimulable, TopLevel
from migen.sim.icarus import Runner from migen.sim.icarus import Runner
from migen.bus.transactions import * from migen.bus.transactions import *
from miscope import recorder from miscope.recorder import *
arm_done = False arm_done = False
dat = 0 dat = 0
@ -14,23 +14,28 @@ rec_done = False
dat_rdy = False dat_rdy = False
rec_size = 128
def csr_transactions(): def csr_transactions():
#Reset # Reset
yield TWrite(0, 1) yield TWrite(REC_RST_BASE, 1)
yield TWrite(0, 0) yield TWrite(REC_RST_BASE, 0)
# RLE
yield TWrite(REC_RLE_BASE, 1)
#Size # Size
yield TWrite(3, 0) yield TWrite(REC_SIZE_BASE + 0, 0)
yield TWrite(4, 32) yield TWrite(REC_SIZE_BASE + 1, rec_size)
#Offset # Offset
yield TWrite(5, 0) yield TWrite(REC_OFFSET_BASE + 0, 0)
yield TWrite(6, 0) yield TWrite(REC_OFFSET_BASE + 1, 0)
#Arm # Arm
yield TWrite(1, 1) yield TWrite(REC_ARM_BASE, 1)
yield TWrite(1, 0) yield TWrite(REC_ARM_BASE, 0)
for t in range(10): for t in range(10):
yield None yield None
@ -43,14 +48,14 @@ def csr_transactions():
yield None yield None
global dat_rdy global dat_rdy
for t in range(32): for t in range(rec_size):
yield TWrite(7, 1) yield TWrite(REC_READ_BASE, 1)
dat_rdy = False dat_rdy = False
yield TWrite(7, 0) yield TWrite(REC_READ_BASE, 0)
yield TRead(8) yield TRead(REC_READ_DATA_BASE + 0)
yield TRead(9) yield TRead(REC_READ_DATA_BASE + 1)
yield TRead(10) yield TRead(REC_READ_DATA_BASE + 2)
yield TRead(11) yield TRead(REC_READ_DATA_BASE + 3)
dat_rdy = True dat_rdy = True
dat_rdy = False dat_rdy = False
@ -63,7 +68,7 @@ def main():
csr_master0 = csr.Initiator(csr_transactions()) csr_master0 = csr.Initiator(csr_transactions())
# Recorder # Recorder
recorder0 = recorder.Recorder(32, 1024) recorder0 = Recorder(32, 1024)
# Csr Interconnect # Csr Interconnect
csrcon0 = csr.Interconnect(csr_master0.bus, csrcon0 = csr.Interconnect(csr_master0.bus,
@ -79,16 +84,15 @@ def main():
arm_done = False arm_done = False
global dat global dat
s.wr(recorder0.dat,dat) s.wr(recorder0.dat, dat//5)
dat += 1 dat += 1
global rec_done global rec_done
if s.rd(recorder0.sequencer.rec_done) == 1: if s.rd(recorder0.sequencer.enable) == 0:
rec_done = True rec_done = True
if dat_rdy: if dat_rdy:
print("%08X" %s.rd(recorder0._pull_dat.field.w)) print("%08X" %s.rd(recorder0._pull_dat.field.w))
# Simulation # Simulation
def end_simulation(s): def end_simulation(s):

View File

@ -5,7 +5,8 @@ from migen.sim.generic import Simulator, PureSimulable, TopLevel
from migen.sim.icarus import Runner from migen.sim.icarus import Runner
from migen.bus.transactions import * from migen.bus.transactions import *
from miscope import trigger, recorder from miscope.trigger import *
from miscope.recorder import *
from miscope.tools.truthtable import * from miscope.tools.truthtable import *
from miscope.tools.vcd import * from miscope.tools.vcd import *
@ -15,7 +16,8 @@ RECORDER_ADDR = 0x0200
rec_done = False rec_done = False
dat_rdy = False dat_rdy = False
dat_vcd = [] dat_vcd = VcdDat(32)
rec_size = 64
def term_prog(off, dat): def term_prog(off, dat):
for i in range(4): for i in range(4):
@ -62,20 +64,23 @@ def csr_transactions(trigger0, recorder0):
# Recorder Prog # Recorder Prog
############################## ##############################
#Reset #Reset
yield TWrite(recorder0.address + 0, 1) yield TWrite(recorder0.address + REC_RST_BASE, 1)
yield TWrite(recorder0.address + 0, 0) yield TWrite(recorder0.address + REC_RST_BASE, 0)
# RLE
yield TWrite(REC_RLE_BASE, 0)
#Size #Size
yield TWrite(recorder0.address + 3, 0) yield TWrite(recorder0.address + REC_SIZE_BASE + 0, 0)
yield TWrite(recorder0.address + 4, 64) yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, rec_size)
#Offset #Offset
yield TWrite(recorder0.address + 5, 0) yield TWrite(recorder0.address + REC_OFFSET_BASE + 0, 0)
yield TWrite(recorder0.address + 6, 16) yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, 16)
#Arm #Arm
yield TWrite(recorder0.address + 1, 1) yield TWrite(recorder0.address + REC_ARM_BASE, 1)
yield TWrite(recorder0.address + 1, 0) yield TWrite(recorder0.address + REC_ARM_BASE, 0)
# Wait Record to be done # Wait Record to be done
############################## ##############################
@ -86,14 +91,14 @@ def csr_transactions(trigger0, recorder0):
# Read recorded data # Read recorded data
############################## ##############################
global dat_rdy global dat_rdy
for t in range(64): for t in range(rec_size):
yield TWrite(recorder0.address + 7, 1) yield TWrite(recorder0.address + REC_READ_BASE, 1)
dat_rdy = False dat_rdy = False
yield TWrite(recorder0.address + 7, 0) yield TWrite(recorder0.address + REC_READ_BASE, 0)
yield TRead(recorder0.address + 8) yield TRead(recorder0.address + REC_READ_DATA_BASE + 0)
yield TRead(recorder0.address + 9) yield TRead(recorder0.address + REC_READ_DATA_BASE + 1)
yield TRead(recorder0.address + 10) yield TRead(recorder0.address + REC_READ_DATA_BASE + 2)
yield TRead(recorder0.address + 11) yield TRead(recorder0.address + REC_READ_DATA_BASE + 3)
dat_rdy = True dat_rdy = True
dat_rdy = False dat_rdy = False
@ -108,14 +113,14 @@ trig_sig_val = 0
def main(): def main():
# Trigger # Trigger
term0 = trigger.Term(32) term0 = Term(32)
term1 = trigger.Term(32) term1 = Term(32)
term2 = trigger.Term(32) term2 = Term(32)
term3 = trigger.Term(32) term3 = Term(32)
trigger0 = trigger.Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR) trigger0 = Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR)
# Recorder # Recorder
recorder0 = recorder.Recorder(32, 1024, address=RECORDER_ADDR) recorder0 = Recorder(32, 1024, address=RECORDER_ADDR)
# Csr Master # Csr Master
csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0)) csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0))
@ -146,7 +151,7 @@ def main():
# Recorder Data # Recorder Data
def recorder_data(s): def recorder_data(s):
global rec_done global rec_done
if s.rd(recorder0.sequencer.rec_done) == 1: if s.rd(recorder0.sequencer.done) == 1:
rec_done = True rec_done = True
global dat_rdy global dat_rdy
@ -160,7 +165,7 @@ def main():
def end_simulation(s): def end_simulation(s):
s.interrupt = csr_master0.done s.interrupt = csr_master0.done
myvcd = Vcd() myvcd = Vcd()
myvcd.add(Var("wire", 32, "trig_dat", dat_vcd)) myvcd.add(Var("trig_dat", 32, dat_vcd))
f = open("tb_miscope_out.vcd", "w") f = open("tb_miscope_out.vcd", "w")
f.write(str(myvcd)) f.write(str(myvcd))
f.close() f.close()