319 lines
7.7 KiB
Python
319 lines
7.7 KiB
Python
from migen.fhdl.structure import *
|
|
from migen.fhdl.specials import Memory
|
|
from migen.bus import csr
|
|
from migen.bank import description, csrgen
|
|
from migen.bank.description import *
|
|
from migen.genlib.misc import optree
|
|
|
|
|
|
class RegParams:
|
|
def __init__(self, name, base, width, nb):
|
|
self.name = name
|
|
self.base = base
|
|
self.width = width
|
|
self.nb = nb
|
|
|
|
self.size = nb*width
|
|
self.words = int(2**bits_for(self.width-1)/8)
|
|
|
|
def list_regs(objects):
|
|
r = []
|
|
for object in objects:
|
|
if "_reg" in object:
|
|
r.append(objects[object])
|
|
return r
|
|
|
|
class Term:
|
|
#
|
|
# Definition
|
|
#
|
|
def __init__(self, width):
|
|
self.width = width
|
|
self.interface = None
|
|
|
|
self.i = Signal(width)
|
|
self.t = Signal(width)
|
|
self.m = Signal(width)
|
|
self.o = Signal()
|
|
|
|
self.reg_p = RegParams("term_reg", 0, width, 2)
|
|
self.reg = None
|
|
|
|
def get_registers_comb(self):
|
|
comb = [self.t.eq(self.reg.field.r[0*self.width:1*self.width])]
|
|
comb += [self.m.eq(self.reg.field.r[1*self.width:2*self.width])]
|
|
return comb
|
|
|
|
def get_fragment(self):
|
|
comb = [self.o.eq((self.m & self.i) == self.t)]
|
|
comb += self.get_registers_comb()
|
|
return Fragment(comb)
|
|
|
|
#
|
|
# Driver
|
|
#
|
|
def set(self, dat, mask=None):
|
|
if mask is None:
|
|
mask = (2**self.width)-1
|
|
self.interface.write_n(self.reg_p.base, mask, self.width)
|
|
self.interface.write_n(self.reg_p.base + self.reg_p.words, dat, self.width)
|
|
|
|
class RangeDetector:
|
|
#
|
|
# Definition
|
|
#
|
|
def __init__(self, width):
|
|
self.width = width
|
|
self.pipe = pipe
|
|
self.interface = None
|
|
|
|
self.reg_p = RegParams("range_reg", 0, width, 2)
|
|
self.reg = None
|
|
|
|
self.i = Signal(width)
|
|
self.low = Signal(width)
|
|
self.high = Signal(width)
|
|
self.o = Signal()
|
|
|
|
def get_registers_comb(self):
|
|
comb = [self.low.eq(self.reg.field.r[0*self.width:1*self.width])]
|
|
comb += [self.low.eq(self.reg.field.r[1*self.width:2*self.width])]
|
|
return comb
|
|
|
|
def get_fragment(self):
|
|
comb = [self.o.eq((self.i >= self.low) & (self.i <= self.high))]
|
|
comb += self.get_registers_comb()
|
|
return Fragment(comb)
|
|
#
|
|
# Driver
|
|
#
|
|
def set_low(self, dat):
|
|
self.interface.write_n(self.reg_p.base, dat ,self.width)
|
|
|
|
def set_high(self, dat):
|
|
self.interface.write_n(self.reg_p.base + self.reg_p.words, dat ,self.width)
|
|
|
|
class EdgeDetector:
|
|
#
|
|
# Definition
|
|
#
|
|
def __init__(self, width, mode = "RFB"):
|
|
self.width = width
|
|
self.mode = mode
|
|
self.interface = None
|
|
|
|
self.reg_p = RegParams("edge_reg", 0, width, len(self.mode))
|
|
self.reg = None
|
|
|
|
self.i = Signal(self.width)
|
|
self.i_d = Signal(self.width)
|
|
if "R" in self.mode:
|
|
self.r_mask = Signal(self.width)
|
|
self.ro = Signal()
|
|
if "F" in self.mode:
|
|
self.f_mask = Signal(self.width)
|
|
self.fo = Signal()
|
|
if "B" in self.mode:
|
|
self.b_mask = Signal(self.width)
|
|
self.bo = Signal()
|
|
self.o = Signal()
|
|
|
|
def get_registers_comb(self):
|
|
comb = []
|
|
i = 0
|
|
if "R" in self.mode:
|
|
comb += [self.r_mask.eq(self.reg.field.r[i*self.width:(i+1)*self.width])]
|
|
i += 1
|
|
if "F" in self.mode:
|
|
comb += [self.f_mask.eq(self.reg.field.r[i*self.width:(i+1)*self.width])]
|
|
i += 1
|
|
if "B" in self.mode:
|
|
comb += [self.b_mask.eq(self.reg.field.r[i*self.width:(i+1)*self.width])]
|
|
i += 1
|
|
return comb
|
|
|
|
def get_fragment(self):
|
|
comb = []
|
|
sync = [self.i_d.eq(self.i)]
|
|
|
|
# Rising Edge
|
|
if "R" in self.mode:
|
|
comb += [self.ro.eq(self.r_mask & self.i & (~self.i_d))]
|
|
else:
|
|
comb += [self.ro.eq(0)]
|
|
|
|
# Falling Edge
|
|
if "F" in self.mode:
|
|
comb += [self.fo.eq(self.f_mask & (~self.i) & self.i_d)]
|
|
else:
|
|
comb += [self.fo.eq(0)]
|
|
|
|
# Both
|
|
if "B" in self.mode:
|
|
comb += [self.bo.eq((self.b_mask & self.i) != self.i_d)]
|
|
else:
|
|
comb += [self.bo.eq(0)]
|
|
|
|
# Output
|
|
comb += [self.o.eq(self.ro | self.fo | self.bo)]
|
|
|
|
# Registers
|
|
comb += self.get_registers_comb()
|
|
|
|
return Fragment(comb, sync)
|
|
|
|
#
|
|
# Driver
|
|
#
|
|
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
|
|
|
|
def set_r(self, dat):
|
|
self.interface.write_n(self.reg_p.base + self.get_offset("R"), dat ,self.width)
|
|
|
|
def set_f(self, dat):
|
|
self.interface.write_n(self.reg_p.base + self.get_offset("F"), dat ,self.width)
|
|
|
|
def set_b(self, dat):
|
|
self.interface.write_n(self.reg_p.base + self.get_offset("B"), dat ,self.width)
|
|
|
|
class Sum:
|
|
#
|
|
# Definition
|
|
#
|
|
def __init__(self, width=4):
|
|
self.width = width
|
|
self.interface = None
|
|
|
|
self.i = Signal(self.width)
|
|
self._o = Signal()
|
|
self.o = Signal()
|
|
|
|
self.reg_p = RegParams("sum_reg", 0, 8, 4)
|
|
self.reg = None
|
|
|
|
self.prog_stb = Signal()
|
|
self.prog_adr = Signal(width)
|
|
self.prog_dat = Signal()
|
|
|
|
self._mem = Memory(1, 2**self.width)
|
|
self._lut_port = self._mem.get_port()
|
|
self._prog_port = self._mem.get_port(write_capable=True)
|
|
|
|
def get_registers_comb(self):
|
|
comb = [
|
|
self.prog_adr.eq(self.reg.field.r[0:16]),
|
|
self.prog_dat.eq(self.reg.field.r[16]),
|
|
self.prog_stb.eq(self.reg.field.r[17])
|
|
]
|
|
return comb
|
|
|
|
def get_fragment(self):
|
|
comb = [
|
|
self._lut_port.adr.eq(self.i),
|
|
self._o.eq(self._lut_port.dat_r),
|
|
|
|
self._prog_port.adr.eq(self.prog_adr),
|
|
self._prog_port.we.eq(self.prog_stb),
|
|
self._prog_port.dat_w.eq(self.prog_dat),
|
|
|
|
self.o.eq(self._o)
|
|
]
|
|
comb += self.get_registers_comb()
|
|
return Fragment(comb, specials={self._mem})
|
|
|
|
#
|
|
# Driver
|
|
#
|
|
def set(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_p.base, we + dat + addr, self.reg_p.size)
|
|
self.interface.write_n(self.reg_p.base, dat + addr, self.reg_p.size)
|
|
|
|
class Trigger:
|
|
#
|
|
# Definition
|
|
#
|
|
def __init__(self, trig_w, ports, address=0x0000, interface=None):
|
|
self.trig_w = trig_w
|
|
self.ports = ports
|
|
|
|
self.sum = Sum(len(ports))
|
|
self.trig = Signal(self.trig_w)
|
|
self.hit = Signal()
|
|
|
|
# insert port number in port reg name
|
|
for i in range(len(self.ports)):
|
|
self.ports[i].reg_p.name += "_%d"%i
|
|
|
|
# generate ports csr registers fields
|
|
for port in self.ports:
|
|
rf = RegisterField(port.reg_p.name, port.reg_p.size, reset=0,
|
|
access_bus=WRITE_ONLY, access_dev=READ_ONLY)
|
|
setattr(self, port.reg_p.name, rf)
|
|
|
|
# generate sum csr registers fields
|
|
self.sum_reg = RegisterField(self.sum.reg_p.name, self.sum.reg_p.size, reset=0,
|
|
access_bus=WRITE_ONLY, access_dev=READ_ONLY)
|
|
|
|
# generate registers
|
|
self.regs = list_regs(self.__dict__)
|
|
self.bank = csrgen.Bank(self.regs, address=address)
|
|
|
|
# update base addr & interface
|
|
self.set_address(address)
|
|
self.set_interface(interface)
|
|
self.set_registers()
|
|
|
|
def set_address(self, address):
|
|
self.address = address
|
|
self.bank = csrgen.Bank(self.regs, address=self.address)
|
|
for port in self.ports:
|
|
port.reg_p.base = self.bank.get_base(port.reg_p.name)
|
|
self.sum.reg_p.base = self.bank.get_base(self.sum.reg_p.name)
|
|
|
|
def set_interface(self, interface):
|
|
self.interface = interface
|
|
for port in self.ports:
|
|
port.interface = self.interface
|
|
self.sum.interface = self.interface
|
|
|
|
def set_registers(self):
|
|
self.sum.reg=self.sum_reg
|
|
for port in self.ports:
|
|
port.reg=getattr(self, port.reg_p.name)
|
|
|
|
def get_fragment(self):
|
|
# connect trig to input of each trig element
|
|
comb = [port.i.eq(self.trig) for port in self.ports]
|
|
|
|
# connect output of trig elements to sum
|
|
comb += [self.sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))]
|
|
|
|
# connect sum ouput to hit
|
|
comb += [self.hit.eq(self.sum.o)]
|
|
|
|
# add ports & sum to frag
|
|
frag = self.bank.get_fragment()
|
|
frag += self.sum.get_fragment()
|
|
for port in self.ports:
|
|
frag += port.get_fragment()
|
|
|
|
return frag + Fragment(comb)
|