Create trigger blocks only for defined triggers.

Adds YAML option 'trigger_pruned' support for the logic analyser to prevent the creation of trigger
blocks for probes not listed as triggers. This pruning allows much higher fmax for the designs.
This commit is contained in:
Carlos Azevedo 2024-11-06 03:01:48 +00:00
parent 599384ecc2
commit c3fe68d73d
3 changed files with 36 additions and 10 deletions

View File

@ -1,7 +1,7 @@
from amaranth import *
from manta.logic_analyzer.capture import LogicAnalyzerCapture
from manta.logic_analyzer.fsm import LogicAnalyzerFSM, TriggerModes
from manta.logic_analyzer.fsm import LogicAnalyzerFSM, TriggerModes, TriggerPrune
from manta.logic_analyzer.trigger_block import LogicAnalyzerTriggerBlock
from manta.memory_core import MemoryCore
from manta.utils import *
@ -39,6 +39,7 @@ class LogicAnalyzerCore(MantaCore):
self._trigger_location = sample_depth // 2
self._trigger_mode = TriggerModes.IMMEDIATE
self._triggers = []
self._trigger_pruned = TriggerPrune.FALSE
# Bus Input/Output
self.bus_i = Signal(InternalBus())
@ -58,6 +59,7 @@ class LogicAnalyzerCore(MantaCore):
"type": "logic_analyzer",
"sample_depth": self._sample_depth,
"probes": {p.name: len(p) for p in self._probes},
"trigger_pruned": self._trigger_pruned,
}
if self._trigger_mode == TriggerModes.INCREMENTAL:
@ -81,6 +83,7 @@ class LogicAnalyzerCore(MantaCore):
"triggers",
"trigger_location",
"trigger_mode",
"trigger_pruned",
]
for option in config:
if option not in valid_options:
@ -116,12 +119,13 @@ class LogicAnalyzerCore(MantaCore):
core = cls(sample_depth, probes)
# If any trigger-related configuration was provided, set the triggers with it
keys = ["trigger_mode", "triggers", "trigger_location"]
keys = ["trigger_mode", "triggers", "trigger_location", "trigger_pruned"]
if any([key in config for key in keys]):
core.set_triggers(
trigger_mode=config.get("trigger_mode"),
triggers=triggers,
trigger_location=config.get("trigger_location"),
trigger_pruned=config.get("trigger_pruned"),
)
return core
@ -137,6 +141,7 @@ class LogicAnalyzerCore(MantaCore):
probes=self._probes,
base_addr=self._fsm.max_addr + 1,
interface=self.interface,
trig_names=[n[0] for n in self._triggers] if self._trigger_pruned else None,
)
self._sample_mem = MemoryCore(
@ -215,7 +220,7 @@ class LogicAnalyzerCore(MantaCore):
else:
raise ValueError(f"Unable to interpret trigger condition '{trigger}'.")
def set_triggers(self, trigger_mode=None, triggers=None, trigger_location=None):
def set_triggers(self, trigger_mode=None, triggers=None, trigger_location=None, trigger_pruned=None):
"""
Args:
trigger_mode (TriggerMode | str):
@ -223,6 +228,8 @@ class LogicAnalyzerCore(MantaCore):
triggers (Optional[Sequence[Sequence[str | int]]]):
trigger_location (Optional[int]):
trigger_pruned (Optional[TriggerPrune]):
"""
# Obtain trigger mode
if isinstance(trigger_mode, TriggerModes):
@ -234,6 +241,11 @@ class LogicAnalyzerCore(MantaCore):
else:
raise ValueError(f"Unrecognized trigger mode {trigger_mode} provided.")
# Obtain trigger pruning
if not isinstance(trigger_pruned, bool) and (trigger_pruned != None):
raise ValueError(f"Unrecognized trigger pruning {trigger_pruned} provided.")
self._trigger_pruned = trigger_pruned or TriggerPrune.FALSE
# Peform checks based on trigger mode
if mode == TriggerModes.IMMEDIATE:
# Warn on triggers
@ -275,7 +287,7 @@ class LogicAnalyzerCore(MantaCore):
# Validate triggers
self._validate_triggers(triggers)
self.trigger_mode = mode
self._trigger_mode = mode
self._triggers = triggers
self._trigger_location = trigger_location or self._sample_depth // 2

View File

@ -1,5 +1,5 @@
from amaranth import *
from amaranth.lib.enum import IntEnum
from amaranth.lib.enum import IntEnum, Flag
from manta.io_core import IOCore
@ -18,6 +18,11 @@ class TriggerModes(IntEnum):
IMMEDIATE = 2
class TriggerPrune(Flag):
TRUE = True
FALSE = False
class LogicAnalyzerFSM(Elaboratable):
"""
A module containing the state machine for a LogicAnalyzerCore. Primarily

View File

@ -12,10 +12,14 @@ class LogicAnalyzerTriggerBlock(Elaboratable):
the triggers to be reprogrammed without reflashing the FPGA.
"""
def __init__(self, probes, base_addr, interface):
def __init__(self, probes, base_addr, interface, trig_names):
# Instantiate a bunch of trigger blocks
self._trig_names = trig_names
self._probes = probes
self._triggers = [LogicAnalyzerTrigger(p) for p in self._probes]
if trig_names is None:
self._triggers = [LogicAnalyzerTrigger(p) for p in self._probes]
else:
self._triggers = [LogicAnalyzerTrigger(p) for p in self._probes if p.name in trig_names]
# Make IO core for everything
ops = [t.op for t in self._triggers]
@ -37,9 +41,14 @@ class LogicAnalyzerTriggerBlock(Elaboratable):
def set_triggers(self, triggers):
# Reset all triggers to disabled with no argument
for p in self._probes:
self.registers.set_probe(p.name + "_op", Operations.DISABLE)
self.registers.set_probe(p.name + "_arg", 0)
if self._trig_names is None:
for p in self._probes:
self.registers.set_probe(p.name + "_op", Operations.DISABLE)
self.registers.set_probe(p.name + "_arg", 0)
else:
for n in self._trig_names:
self.registers.set_probe(n + "_op", Operations.DISABLE)
self.registers.set_probe(n + "_arg", 0)
# Set triggers
for trigger in triggers: