define ABC for cores to inherit from
This commit is contained in:
parent
b729deb144
commit
be79ba28b5
|
|
@ -3,7 +3,7 @@ from manta.utils import *
|
|||
from math import ceil
|
||||
|
||||
|
||||
class IOCore(Elaboratable):
|
||||
class IOCore(MantaCore):
|
||||
"""
|
||||
A module for setting and getting the values of registers of arbitrary size
|
||||
on a FPGA.
|
||||
|
|
@ -34,6 +34,14 @@ class IOCore(Elaboratable):
|
|||
|
||||
self._make_memory_map()
|
||||
|
||||
@property
|
||||
def top_level_ports(self):
|
||||
return self._inputs + self._outputs
|
||||
|
||||
@property
|
||||
def max_addr(self):
|
||||
return self._max_addr
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config, base_addr, interface):
|
||||
inputs = config.get("inputs", {})
|
||||
|
|
@ -173,21 +181,6 @@ class IOCore(Elaboratable):
|
|||
|
||||
return m
|
||||
|
||||
def get_top_level_ports(self):
|
||||
"""
|
||||
Return the Amaranth signals that should be included as ports in the
|
||||
top-level Manta module.
|
||||
"""
|
||||
return self._inputs + self._outputs
|
||||
|
||||
def get_max_addr(self):
|
||||
"""
|
||||
Return the maximum addresses in memory used by the core. The address
|
||||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
return self._max_addr
|
||||
|
||||
def set_probe(self, name, value):
|
||||
"""
|
||||
Set the value of an output probe on the FPGA. The value may be either
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from manta.logic_analyzer.fsm import LogicAnalyzerFSM, States, TriggerModes
|
|||
from manta.logic_analyzer.playback import LogicAnalyzerPlayback
|
||||
|
||||
|
||||
class LogicAnalyzerCore(Elaboratable):
|
||||
class LogicAnalyzerCore(MantaCore):
|
||||
"""
|
||||
A module for generating a logic analyzer on the FPGA, with configurable
|
||||
triggers, trigger position, and trigger modes.
|
||||
|
|
@ -44,6 +44,14 @@ class LogicAnalyzerCore(Elaboratable):
|
|||
interface=interface,
|
||||
)
|
||||
|
||||
@property
|
||||
def max_addr(self):
|
||||
return self._sample_mem.max_addr
|
||||
|
||||
@property
|
||||
def top_level_ports(self):
|
||||
return self._probes
|
||||
|
||||
def _check_config(self):
|
||||
# Check for unrecognized options
|
||||
valid_options = [
|
||||
|
|
@ -176,21 +184,6 @@ class LogicAnalyzerCore(Elaboratable):
|
|||
|
||||
return m
|
||||
|
||||
def get_top_level_ports(self):
|
||||
"""
|
||||
Return the Amaranth signals that should be included as ports in the
|
||||
top-level Manta module.
|
||||
"""
|
||||
return self._probes
|
||||
|
||||
def get_max_addr(self):
|
||||
"""
|
||||
Return the maximum addresses in memory used by the core. The address
|
||||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
return self._sample_mem.get_max_addr()
|
||||
|
||||
def capture(self, verbose=False):
|
||||
"""
|
||||
Performs a capture, recording the state of all input probes to the
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class LogicAnalyzerFSM(Elaboratable):
|
|||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
return self.registers.get_max_addr()
|
||||
return self.registers.max_addr
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class LogicAnalyzerTriggerBlock(Elaboratable):
|
|||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
return self.registers.get_max_addr()
|
||||
return self.registers.max_addr
|
||||
|
||||
def clear_triggers(self):
|
||||
# Reset all triggers to disabled with no argument
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ class Manta(Elaboratable):
|
|||
core = MemoryCore.from_config(attrs, base_addr, self.interface)
|
||||
|
||||
# Make sure we're not out of address space
|
||||
if core.get_max_addr() > (2**16) - 1:
|
||||
if core.max_addr > (2**16) - 1:
|
||||
raise ValueError(
|
||||
f"Ran out of address space to allocate to core {name}."
|
||||
)
|
||||
|
||||
# Make the next core's base address start one address after the previous one's
|
||||
base_addr = core.get_max_addr() + 1
|
||||
base_addr = core.max_addr + 1
|
||||
self._cores[name] = core
|
||||
|
||||
def _add_friendly_core_names(self):
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from manta.utils import *
|
|||
from math import ceil
|
||||
|
||||
|
||||
class MemoryCore(Elaboratable):
|
||||
class MemoryCore(MantaCore):
|
||||
"""
|
||||
A module for generating a memory on the FPGA, with a port tied to Manta's
|
||||
internal bus, and a port provided to user logic.
|
||||
|
|
@ -60,6 +60,14 @@ class MemoryCore(Elaboratable):
|
|||
self.user_write_enable,
|
||||
]
|
||||
|
||||
@property
|
||||
def top_level_ports(self):
|
||||
return self._top_level_ports
|
||||
|
||||
@property
|
||||
def max_addr(self):
|
||||
return self._max_addr
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config, base_addr, interface):
|
||||
# Check for unrecognized options
|
||||
|
|
@ -251,21 +259,6 @@ class MemoryCore(Elaboratable):
|
|||
self._tie_mems_to_user_logic(m)
|
||||
return m
|
||||
|
||||
def get_top_level_ports(self):
|
||||
"""
|
||||
Return the Amaranth signals that should be included as ports in the
|
||||
top-level Manta module.
|
||||
"""
|
||||
return self._top_level_ports
|
||||
|
||||
def get_max_addr(self):
|
||||
"""
|
||||
Return the maximum addresses in memory used by the core. The address
|
||||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
return self._max_addr
|
||||
|
||||
def _convert_user_to_bus_addr(self, addrs):
|
||||
"""
|
||||
Convert user address space to bus address space. For instance, for a
|
||||
|
|
|
|||
|
|
@ -1,9 +1,40 @@
|
|||
from amaranth import *
|
||||
from amaranth.sim import Simulator
|
||||
from amaranth.lib import data, enum
|
||||
from math import ceil
|
||||
from amaranth.lib import data
|
||||
from abc import ABC, abstractmethod
|
||||
import os
|
||||
|
||||
|
||||
class MantaCore(ABC, Elaboratable):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def max_addr(self):
|
||||
"""
|
||||
Return the maximum addresses in memory used by the core. The address
|
||||
space used by the core extends from `base_addr` to the number returned
|
||||
by this function (including the endpoints).
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def top_level_ports(self):
|
||||
"""
|
||||
Return the Amaranth signals that should be included as ports in the
|
||||
top-level Manta module.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def elaborate(self, platform):
|
||||
pass
|
||||
|
||||
# @abstractclassmethod
|
||||
# def from_config(cls):
|
||||
# pass
|
||||
|
||||
|
||||
class InternalBus(data.StructLayout):
|
||||
"""
|
||||
Describes the layout of Manta's internal bus, such that signals of
|
||||
|
|
|
|||
|
|
@ -96,5 +96,5 @@ def test_single_shot_capture():
|
|||
yield from write_register(la, 0, 1)
|
||||
yield from write_register(la, 0, 0)
|
||||
|
||||
for addr in range(la.get_max_addr()):
|
||||
for addr in range(la.max_addr):
|
||||
yield from print_data_at_addr(addr)
|
||||
|
|
|
|||
|
|
@ -2,15 +2,18 @@ from manta.memory_core import MemoryCore
|
|||
from manta.utils import *
|
||||
from random import randint, sample, choice
|
||||
|
||||
class MemoryCoreTests():
|
||||
|
||||
class MemoryCoreTests:
|
||||
def __init__(self, mem_core):
|
||||
self.mem_core = mem_core
|
||||
self.base_addr = mem_core._base_addr
|
||||
self.max_addr = mem_core.get_max_addr()
|
||||
self.max_addr = mem_core.max_addr
|
||||
self.width = self.mem_core._width
|
||||
self.depth = self.mem_core._depth
|
||||
|
||||
self.bus_addrs = list(range(self.base_addr, self.max_addr)) # include the endpoint!
|
||||
self.bus_addrs = list(
|
||||
range(self.base_addr, self.max_addr)
|
||||
) # include the endpoint!
|
||||
self.user_addrs = list(range(self.mem_core._depth))
|
||||
self.model = {}
|
||||
|
||||
|
|
@ -86,7 +89,10 @@ class MemoryCoreTests():
|
|||
|
||||
data = yield (self.mem_core.user_data_out)
|
||||
if data != expected_data:
|
||||
raise ValueError(f"Read from {addr} yielded {data} instead of {expected_data}")
|
||||
raise ValueError(
|
||||
f"Read from {addr} yielded {data} instead of {expected_data}"
|
||||
)
|
||||
|
||||
|
||||
mem_core = MemoryCore(
|
||||
mode="bidirectional",
|
||||
|
|
@ -98,6 +104,7 @@ mem_core = MemoryCore(
|
|||
|
||||
tests = MemoryCoreTests(mem_core)
|
||||
|
||||
|
||||
@simulate(mem_core)
|
||||
def test_bidirectional_testbench():
|
||||
yield from tests.check_each_address_on_bus_side_contains_zero()
|
||||
|
|
@ -106,6 +113,7 @@ def test_bidirectional_testbench():
|
|||
yield from tests.check_multiple_writes_then_multiple_reads()
|
||||
yield from tests.check_random_reads_random_writes_random_orders()
|
||||
|
||||
|
||||
# def test_sweep_core_widths():
|
||||
# for i in range(1, 64):
|
||||
# verify_mem_core(i, 128, 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue