litex/migScope/trigger.py

377 lines
8.7 KiB
Python
Raw Normal View History

2012-08-26 15:30:23 -04:00
from migen.fhdl.structure import *
from migen.bus import csr
from migen.bank import description, csrgen
from migen.bank.description import *
from migen.corelogic.misc import optree
class Term:
2012-09-17 11:00:47 -04:00
#
# Definition
#
2012-08-26 15:30:23 -04:00
def __init__(self, width, pipe=False):
self.width = width
self.pipe = pipe
2012-09-14 06:57:09 -04:00
self.interface = None
2012-08-26 15:30:23 -04:00
2012-09-09 08:37:55 -04:00
self.reg_name = "term_reg"
self.reg_base = 0
2012-09-17 12:37:23 -04:00
self.reg_size = 2*width
2012-09-14 06:57:09 -04:00
self.words = int(2**bits_for(width-1)/8)
2012-09-09 08:37:55 -04:00
2012-08-26 15:30:23 -04:00
self.i = Signal(BV(self.width))
self.t = Signal(BV(self.width))
2012-09-17 12:37:23 -04:00
self.m = Signal(BV(self.width))
2012-08-26 15:30:23 -04:00
self.o = Signal()
2012-09-17 11:00:47 -04:00
2012-08-26 15:30:23 -04:00
def get_fragment(self):
frag = [
2012-09-17 12:37:23 -04:00
self.o.eq((self.m & self.i) == self.t)
2012-08-26 15:30:23 -04:00
]
if self.pipe:
return Fragment(sync=frag)
else:
return Fragment(comb=frag)
2012-09-09 08:37:55 -04:00
def connect_to_reg(self, reg):
comb = []
comb += [self.t.eq(reg.field.r[0*self.width:1*self.width])]
2012-09-17 12:37:23 -04:00
comb += [self.m.eq(reg.field.r[1*self.width:2*self.width])]
2012-09-09 08:37:55 -04:00
return comb
2012-09-17 11:00:47 -04:00
#
#Driver
#
2012-09-17 12:37:23 -04:00
def write(self, dat, mask = None):
if mask == None:
mask = (2**self.width)-1
self.interface.write_n(self.reg_base + self.words, dat ,self.width)
self.interface.write_n(self.reg_base, mask ,self.width)
2012-08-26 15:30:23 -04:00
class RangeDetector:
2012-09-17 11:00:47 -04:00
#
# Definition
#
2012-08-26 15:30:23 -04:00
def __init__(self, width, pipe=False):
self.width = width
self.pipe = pipe
2012-09-14 06:57:09 -04:00
self.interface = None
2012-09-09 08:37:55 -04:00
self.reg_name = "range_reg"
self.reg_base = 0
self.reg_size = 2*width
2012-09-14 06:57:09 -04:00
self.words = int(2**bits_for(width-1)/8)
2012-09-09 08:37:55 -04:00
2012-08-26 15:30:23 -04:00
self.i = Signal(BV(self.width))
self.low = Signal(BV(self.width))
self.high = Signal(BV(self.width))
self.o = Signal()
2012-09-14 06:57:09 -04:00
2012-08-26 15:30:23 -04:00
def get_fragment(self):
frag = [
self.o.eq((self.i >= self.low) & ((self.i <= self.high)))
]
if self.pipe:
return Fragment(sync=frag)
else:
return Fragment(comb=frag)
2012-09-09 08:37:55 -04:00
def connect_to_reg(self, reg):
comb = []
comb += [self.low.eq(reg.field.r[0*self.width:1*self.width])]
comb += [self.low.eq(reg.field.r[1*self.width:2*self.width])]
return comb
2012-09-17 11:00:47 -04:00
#
#Driver
#
def write_low(self, dat):
self.interface.write_n(self.reg_base, dat ,self.width)
def write_high(self, dat):
self.interface.write_n(self.reg_base + self.words, dat ,self.width)
2012-08-26 15:30:23 -04:00
class EdgeDetector:
2012-09-17 11:00:47 -04:00
#
# Definition
#
2012-08-26 15:30:23 -04:00
def __init__(self, width, pipe=False, mode = "RFB"):
self.width = width
self.pipe = pipe
self.mode = mode
2012-09-14 06:57:09 -04:00
self.interface = None
2012-08-26 15:30:23 -04:00
2012-09-09 08:37:55 -04:00
self.reg_name = "edge_reg"
self.reg_base = 0
self.reg_size = len(self.mode)*width
2012-08-26 15:30:23 -04:00
self.i = Signal(BV(self.width))
self.i_d = Signal(BV(self.width))
2012-09-14 06:57:09 -04:00
if "R" in self.mode:
2012-08-26 15:30:23 -04:00
self.r_mask = Signal(BV(self.width))
self.ro = Signal()
2012-09-14 06:57:09 -04:00
if "F" in self.mode:
2012-08-26 15:30:23 -04:00
self.f_mask = Signal(BV(self.width))
self.fo = Signal()
2012-09-14 06:57:09 -04:00
if "B" in self.mode:
2012-08-26 15:30:23 -04:00
self.b_mask = Signal(BV(self.width))
self.bo = Signal()
self.o = Signal()
2012-09-14 06:57:09 -04:00
2012-08-26 15:30:23 -04:00
def get_fragment(self):
comb = []
sync = []
sync += [self.i_d.eq(self.i)]
# Rising Edge
if "R" in self.mode:
r_eq = [self.ro.eq(self.r_mask & self.i & (~self.i_d))]
if self.pipe:
sync += r_eq
else:
comb += r_eq
else:
comb += [self.ro.eq(0)]
# Falling Edge
if "F" in self.mode:
f_eq = [self.fo.eq(self.f_mask & (~ self.i) & self.i_d)]
if self.pipe:
sync += f_eq
else:
comb += f_eq
else:
comb += [self.fo.eq(0)]
# Both
if "B" in self.mode:
b_eq = [self.bo.eq(self.b_mask & self.i != self.i_d)]
if self.pipe:
sync += b_eq
else:
comb += b_eq
else:
comb += [self.bo.eq(0)]
#Output
comb += [self.o.eq(self.ro | self.fo | self.bo)]
return Fragment(comb, sync)
2012-09-17 11:00:47 -04:00
2012-09-09 08:37:55 -04:00
def connect_to_reg(self, reg):
comb = []
i = 0
if "R" in self.mode:
comb += [self.r_mask.eq(reg.field.r[i*self.width:(i+1)*self.width])]
i += 1
if "F" in self.mode:
comb += [self.f_mask.eq(reg.field.r[i*self.width:(i+1)*self.width])]
i += 1
if "B" in self.mode:
comb += [self.b_mask.eq(reg.field.r[i*self.width:(i+1)*self.width])]
i += 1
return comb
2012-09-17 11:00:47 -04:00
#
#Driver
#
2012-09-17 12:37:23 -04:00
def get_offset(self, type):
if type == "R":
r = 0
r = r+self.words if "F" in self.mode else r
r = r+self.words if "B" in self.mode else r
return r
elif type == "F":
r = 0
r = r+self.words if "B" in self.mode else r
return r
elif type == "B":
r = 0
return r
return 0
2012-09-17 11:00:47 -04:00
def write_r(self, dat):
2012-09-17 12:37:23 -04:00
self.interface.write_n(self.reg_base + self.get_offset("R"), dat ,self.width)
2012-09-17 11:00:47 -04:00
def write_f(self, dat):
2012-09-17 12:37:23 -04:00
self.interface.write_n(self.reg_base + self.get_offset("F"), dat ,self.width)
2012-09-17 11:00:47 -04:00
def write_b(self, dat):
2012-09-17 12:37:23 -04:00
self.interface.write_n(self.reg_base + self.get_offset("B"), dat ,self.width)
2012-08-26 15:30:23 -04:00
class Timer:
2012-09-17 11:00:47 -04:00
#
# Definition
#
2012-08-26 15:30:23 -04:00
def __init__(self, width):
self.width = width
2012-09-14 06:57:09 -04:00
self.interface = None
2012-08-26 15:30:23 -04:00
self.start = Signal()
self.stop = Signal()
self.clear = Signal()
self.enable = Signal()
self.cnt = Signal(BV(self.width))
self.cnt_max = Signal(BV(self.width))
self.o = Signal()
2012-09-14 06:57:09 -04:00
2012-08-26 15:30:23 -04:00
def get_fragment(self):
comb = []
sync = []
sync += [
If(self.stop,
self.enable.eq(0),
self.cnt.eq(0),
self.o.eq(0)
).Elif(self.clear,
self.cnt.eq(0),
self.o.eq(0)
).Elif(self.start,
self.enable.eq(1)
).Elif(self.enable,
If(self.cnt <= self.cnt_max,
self.cnt.eq(self.cnt+1)
).Else(
self.o.eq(1)
)
),
If(self.enable,
self.enable.eq(0),
self.cnt.eq(0)
).Elif(self.clear,
self.cnt.eq(0)
).Elif(self.start,
self.enable.eq(1)
)
]
return Fragment(comb, sync)
class Sum:
2012-09-17 11:00:47 -04:00
#
# Definition
#
2012-08-26 15:30:23 -04:00
def __init__(self,width=4,pipe=False):
self.width = width
self.pipe = pipe
2012-09-14 06:57:09 -04:00
self.interface = None
2012-08-26 15:30:23 -04:00
self.i = Signal(BV(self.width))
self._o = Signal()
self.o = Signal()
self._lut_port = MemoryPort(adr=self.i, dat_r=self._o)
2012-09-09 08:37:55 -04:00
self.reg_name = "sum_reg"
self.reg_base = 0
self.reg_size = 32
2012-08-26 15:30:23 -04:00
self.prog = Signal()
self.prog_adr = Signal(BV(width))
self.prog_dat = Signal()
self._prog_port = MemoryPort(adr=self.prog_adr, we=self.prog, dat_w=self.prog_dat)
self._mem = Memory(1, 2**self.width, self._lut_port, self._prog_port)
def get_fragment(self):
comb = []
sync = []
memories = [self._mem]
if self.pipe:
sync += [self.o.eq(self._o)]
else:
comb += [self.o.eq(self._o)]
2012-09-09 17:46:26 -04:00
return Fragment(comb=comb, sync=sync, memories=memories)
2012-08-26 15:30:23 -04:00
2012-09-09 08:37:55 -04:00
def connect_to_reg(self, reg):
comb = []
comb += [
self.prog_adr.eq(reg.field.r[0:16]),
self.prog_dat.eq(reg.field.r[16]),
self.prog.eq(reg.field.r[17])
]
return comb
2012-09-17 11:00:47 -04:00
#
#Driver
#
def write(self, truth_table):
for i in range(len(truth_table)):
val = truth_table[i]
we = 1<<17
dat = val<<16
addr = i
self.interface.write_n(self.reg_base, we + dat + addr,self.reg_size)
self.interface.write_n(self.reg_base, dat + addr, self.reg_size)
2012-09-09 08:37:55 -04:00
2012-08-26 15:30:23 -04:00
class Trigger:
2012-09-17 11:00:47 -04:00
#
# Definition
#
def __init__(self, trig_width, ports, address = 0x0000, interface = None):
2012-08-26 15:30:23 -04:00
self.address = address
self.trig_width = trig_width
self.ports = ports
2012-09-14 06:57:09 -04:00
self.interface = interface
2012-09-09 14:38:01 -04:00
self.sum = Sum(len(self.ports))
2012-08-26 15:30:23 -04:00
self.in_trig = Signal(BV(self.trig_width))
self.hit = Signal()
2012-09-09 08:37:55 -04:00
# Update port reg_name
2012-08-26 15:30:23 -04:00
for i in range(len(self.ports)):
2012-09-09 08:37:55 -04:00
self.ports[i].reg_name += "_%d"%i
# Csr interface
for port in self.ports:
setattr(self,port.reg_name,RegisterField(port.reg_name, port.reg_size, reset=0,
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
2012-09-09 17:46:26 -04:00
self.sum_reg = RegisterField(self.sum.reg_name, self.sum.reg_size, reset=0, access_bus=WRITE_ONLY, access_dev=READ_ONLY)
2012-08-26 15:30:23 -04:00
2012-09-17 11:00:47 -04:00
self.regs = []
2012-08-26 15:30:23 -04:00
objects = self.__dict__
for object in sorted(objects):
if "_reg" in object:
2012-09-17 11:00:47 -04:00
self.regs.append(objects[object])
self.bank = csrgen.Bank(self.regs,address=self.address)
2012-09-09 08:37:55 -04:00
# Update base addr
2012-09-17 11:00:47 -04:00
self.set_address(self.address)
# Update interface
self.set_interface(self.interface)
def set_address(self, address):
self.address = address
self.bank = csrgen.Bank(self.regs,address=self.address)
2012-09-09 08:37:55 -04:00
for port in self.ports:
2012-09-09 14:38:01 -04:00
port.reg_base = self.bank.get_base(port.reg_name)
self.sum.reg_base = self.bank.get_base(self.sum.reg_name)
2012-08-26 15:30:23 -04:00
2012-09-17 11:00:47 -04:00
def set_interface(self, interface):
self.interface = interface
2012-09-14 06:57:09 -04:00
for port in self.ports:
port.interface = self.interface
self.sum.interface = self.interface
2012-08-26 15:30:23 -04:00
def get_fragment(self):
comb = []
sync = []
# Connect in_trig to input of trig elements
comb+= [port.i.eq(self.in_trig) for port in self.ports]
# Connect output of trig elements to sum
2012-09-09 14:38:01 -04:00
comb+= [self.sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))]
2012-08-26 15:30:23 -04:00
# Connect sum ouput to hit
2012-09-09 14:38:01 -04:00
comb+= [self.hit.eq(self.sum.o)]
2012-08-26 15:30:23 -04:00
# Add ports & sum to frag
frag = self.bank.get_fragment()
2012-09-09 14:38:01 -04:00
frag += self.sum.get_fragment()
2012-08-26 15:30:23 -04:00
for port in self.ports:
frag += port.get_fragment()
#Connect Registers
2012-09-09 08:37:55 -04:00
for port in self.ports:
comb += port.connect_to_reg(getattr(self, port.reg_name))
2012-09-09 14:38:01 -04:00
comb += self.sum.connect_to_reg(self.sum_reg)
2012-08-26 15:30:23 -04:00
return frag + Fragment(comb=comb, sync=sync)