artiq/artiq/gateware/drtio/rt_controller_master.py

241 lines
8.1 KiB
Python
Raw Normal View History

"""Real-time controller for master"""
2016-10-24 19:50:13 +08:00
from migen import *
2016-10-31 00:53:01 +08:00
from migen.genlib.cdc import MultiReg
from migen.genlib.misc import WaitTimer
2016-10-24 19:50:13 +08:00
from misoc.interconnect.csr import *
2016-11-22 22:46:50 +08:00
from artiq.gateware.rtio import cri
2016-10-24 19:50:13 +08:00
2016-10-31 18:09:36 +08:00
class _CSRs(AutoCSR):
def __init__(self):
2018-09-20 10:58:38 +08:00
self.reset = CSRStorage()
self.protocol_error = CSR(3)
2016-10-24 19:50:13 +08:00
self.set_time = CSR()
self.underflow_margin = CSRStorage(16, reset=300)
self.async_messages_ready = CSR()
2016-10-24 19:50:13 +08:00
self.force_destination = CSRStorage()
self.destination = CSRStorage(8)
2017-09-24 12:23:47 +08:00
self.o_get_buffer_space = CSR()
self.o_dbg_buffer_space = CSRStatus(16)
self.o_dbg_buffer_space_req_cnt = CSRStatus(32)
2016-10-31 18:09:36 +08:00
self.o_wait = CSRStatus()
2016-10-24 19:50:13 +08:00
class RTController(Module):
def __init__(self, tsc, rt_packet):
2016-10-31 18:09:36 +08:00
self.csrs = _CSRs()
2016-11-22 22:46:50 +08:00
self.cri = cri.Interface()
2016-10-31 18:09:36 +08:00
# protocol errors
err_unknown_packet_type = Signal()
err_packet_truncated = Signal()
2017-09-24 12:23:47 +08:00
signal_buffer_space_timeout = Signal()
err_buffer_space_timeout = Signal()
2018-09-20 10:58:38 +08:00
self.sync += [
If(self.csrs.protocol_error.re,
If(self.csrs.protocol_error.r[0], err_unknown_packet_type.eq(0)),
If(self.csrs.protocol_error.r[1], err_packet_truncated.eq(0)),
2017-09-24 12:23:47 +08:00
If(self.csrs.protocol_error.r[2], err_buffer_space_timeout.eq(0))
),
If(rt_packet.err_unknown_packet_type, err_unknown_packet_type.eq(1)),
If(rt_packet.err_packet_truncated, err_packet_truncated.eq(1)),
2017-09-24 12:23:47 +08:00
If(signal_buffer_space_timeout, err_buffer_space_timeout.eq(1))
]
self.comb += self.csrs.protocol_error.w.eq(
2017-09-24 12:23:47 +08:00
Cat(err_unknown_packet_type, err_packet_truncated, err_buffer_space_timeout))
2016-10-24 19:50:13 +08:00
# TSC synchronization
self.comb += [
rt_packet.tsc_value.eq(tsc.coarse_ts),
2017-03-13 00:10:07 +08:00
self.csrs.set_time.w.eq(rt_packet.set_time_stb)
2016-10-24 19:50:13 +08:00
]
self.sync += [
2017-03-13 00:10:07 +08:00
If(rt_packet.set_time_ack, rt_packet.set_time_stb.eq(0)),
If(self.csrs.set_time.re, rt_packet.set_time_stb.eq(1))
2016-10-24 19:50:13 +08:00
]
self.sync += [
If(rt_packet.async_messages_ready, self.csrs.async_messages_ready.w.eq(1)),
If(self.csrs.async_messages_ready.re, self.csrs.async_messages_ready.w.eq(0))
]
# chan_sel forcing
chan_sel = Signal(24)
self.comb += chan_sel.eq(Mux(self.csrs.force_destination.storage,
self.csrs.destination.storage << 16,
self.cri.chan_sel))
# common packet fields
2017-09-24 12:23:47 +08:00
rt_packet_buffer_request = Signal()
2017-03-13 23:54:44 +08:00
rt_packet_read_request = Signal()
2016-10-24 19:50:13 +08:00
self.comb += [
rt_packet.sr_chan_sel.eq(chan_sel),
2017-03-13 00:10:07 +08:00
rt_packet.sr_address.eq(self.cri.o_address),
rt_packet.sr_data.eq(self.cri.o_data),
If(rt_packet_read_request,
rt_packet.sr_timestamp.eq(self.cri.i_timeout)
).Else(
rt_packet.sr_timestamp.eq(self.cri.o_timestamp)
),
2017-09-24 12:23:47 +08:00
If(rt_packet_buffer_request,
2017-03-13 00:10:07 +08:00
rt_packet.sr_notwrite.eq(1),
rt_packet.sr_address.eq(0)
2017-03-13 23:54:44 +08:00
),
If(rt_packet_read_request,
rt_packet.sr_notwrite.eq(1),
rt_packet.sr_address.eq(1)
2016-10-24 19:50:13 +08:00
)
]
2017-03-13 23:54:44 +08:00
# output status
o_status_wait = Signal()
o_status_underflow = Signal()
2016-10-31 18:09:36 +08:00
self.comb += [
self.cri.o_status.eq(Cat(o_status_wait, o_status_underflow)),
2017-03-13 23:54:44 +08:00
self.csrs.o_wait.status.eq(o_status_wait)
2016-10-31 18:09:36 +08:00
]
2017-03-13 23:54:44 +08:00
o_underflow_set = Signal()
2018-09-20 10:58:38 +08:00
self.sync += [
If(self.cri.cmd == cri.commands["write"],
2017-09-24 12:23:47 +08:00
o_status_underflow.eq(0)
),
2017-09-24 12:23:47 +08:00
If(o_underflow_set, o_status_underflow.eq(1))
]
2016-10-24 19:50:13 +08:00
timeout_counter = WaitTimer(8191)
self.submodules += timeout_counter
2017-09-24 12:23:47 +08:00
cond_underflow = Signal()
self.comb += cond_underflow.eq((self.cri.o_timestamp[tsc.glbl_fine_ts_width:]
2022-12-17 15:39:54 +08:00
- self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts)
2016-10-24 19:50:13 +08:00
# buffer space
buffer_space = Memory(16, 256)
buffer_space_port = buffer_space.get_port(write_capable=True)
self.specials += buffer_space, buffer_space_port
buffer_space_load = Signal()
buffer_space_dec = Signal()
self.comb += [
buffer_space_port.adr.eq(chan_sel[16:]),
buffer_space_port.we.eq(buffer_space_load | buffer_space_dec),
If(buffer_space_load,
buffer_space_port.dat_w.eq(rt_packet.buffer_space)
).Else(
buffer_space_port.dat_w.eq(buffer_space_port.dat_r - 1)
)
]
2017-09-24 12:23:47 +08:00
2017-03-13 23:54:44 +08:00
# input status
i_status_wait_event = Signal()
i_status_overflow = Signal()
i_status_wait_status = Signal()
self.comb += self.cri.i_status.eq(Cat(
i_status_wait_event, i_status_overflow, i_status_wait_status))
2017-03-13 23:54:44 +08:00
load_read_reply = Signal()
2018-09-20 10:58:38 +08:00
self.sync += [
2017-03-13 23:54:44 +08:00
If(load_read_reply,
i_status_wait_event.eq(0),
i_status_overflow.eq(0),
If(rt_packet.read_no_event,
If(rt_packet.read_is_overflow,
i_status_overflow.eq(1)
).Else(
i_status_wait_event.eq(1)
)
),
self.cri.i_data.eq(rt_packet.read_data),
self.cri.i_timestamp.eq(rt_packet.read_timestamp)
)
]
# FSM
2018-09-20 10:58:38 +08:00
fsm = FSM()
2017-03-13 23:54:44 +08:00
self.submodules += fsm
2016-10-24 19:50:13 +08:00
fsm.act("IDLE",
2016-11-22 22:46:50 +08:00
If(self.cri.cmd == cri.commands["write"],
2017-09-24 12:23:47 +08:00
If(cond_underflow,
2017-03-13 23:54:44 +08:00
o_underflow_set.eq(1)
2016-10-24 19:50:13 +08:00
).Else(
NextState("WRITE")
)
),
If(self.cri.cmd == cri.commands["read"], NextState("READ")),
2017-09-24 12:23:47 +08:00
If(self.csrs.o_get_buffer_space.re, NextState("GET_BUFFER_SPACE"))
2016-10-24 19:50:13 +08:00
)
fsm.act("WRITE",
2017-03-13 23:54:44 +08:00
o_status_wait.eq(1),
2017-03-13 00:10:07 +08:00
rt_packet.sr_stb.eq(1),
If(rt_packet.sr_ack,
buffer_space_dec.eq(1),
If(buffer_space_port.dat_r <= 1,
2017-09-24 12:23:47 +08:00
NextState("GET_BUFFER_SPACE")
2016-10-24 19:50:13 +08:00
).Else(
NextState("IDLE")
)
)
)
2017-09-24 12:23:47 +08:00
fsm.act("GET_BUFFER_SPACE",
2017-03-13 23:54:44 +08:00
o_status_wait.eq(1),
2017-09-24 12:23:47 +08:00
rt_packet.buffer_space_not_ack.eq(1),
rt_packet_buffer_request.eq(1),
2017-03-13 00:10:07 +08:00
rt_packet.sr_stb.eq(1),
If(rt_packet.sr_ack,
2017-09-24 12:23:47 +08:00
NextState("GET_BUFFER_SPACE_REPLY")
2016-10-24 19:50:13 +08:00
)
)
2017-09-24 12:23:47 +08:00
fsm.act("GET_BUFFER_SPACE_REPLY",
2017-03-13 23:54:44 +08:00
o_status_wait.eq(1),
buffer_space_load.eq(1),
2017-09-24 12:23:47 +08:00
rt_packet.buffer_space_not_ack.eq(1),
If(rt_packet.buffer_space_not,
If(rt_packet.buffer_space != 0,
2016-10-24 19:50:13 +08:00
NextState("IDLE")
).Else(
2017-09-24 12:23:47 +08:00
NextState("GET_BUFFER_SPACE")
2016-10-24 19:50:13 +08:00
)
),
timeout_counter.wait.eq(1),
If(timeout_counter.done,
2017-09-24 12:23:47 +08:00
signal_buffer_space_timeout.eq(1),
NextState("IDLE")
2016-10-24 19:50:13 +08:00
)
)
2017-03-13 23:54:44 +08:00
fsm.act("READ",
i_status_wait_status.eq(1),
2017-03-14 14:14:43 +08:00
rt_packet.read_not_ack.eq(1),
2017-03-13 23:54:44 +08:00
rt_packet_read_request.eq(1),
rt_packet.sr_stb.eq(1),
If(rt_packet.sr_ack,
NextState("GET_READ_REPLY")
)
)
fsm.act("GET_READ_REPLY",
i_status_wait_status.eq(1),
2017-03-14 14:14:43 +08:00
rt_packet.read_not_ack.eq(1),
2018-09-20 10:58:38 +08:00
If(self.csrs.reset.storage | rt_packet.read_not,
2017-03-13 23:54:44 +08:00
load_read_reply.eq(1),
NextState("IDLE")
)
)
2016-10-24 19:50:13 +08:00
2017-09-24 12:23:47 +08:00
# debug CSRs
self.comb += self.csrs.o_dbg_buffer_space.status.eq(buffer_space_port.dat_r),
self.sync += \
2017-09-24 12:23:47 +08:00
If((rt_packet.sr_stb & rt_packet.sr_ack & rt_packet_buffer_request),
self.csrs.o_dbg_buffer_space_req_cnt.status.eq(
self.csrs.o_dbg_buffer_space_req_cnt.status + 1)
)
2016-10-24 19:50:13 +08:00
2016-10-31 18:09:36 +08:00
def get_csrs(self):
return self.csrs.get_csrs()