From b7fcd8ba92c751e78d1c84860270dced1f8f87d9 Mon Sep 17 00:00:00 2001 From: Marek Materzok Date: Tue, 25 Jul 2023 14:36:53 +0200 Subject: [PATCH] Synthesis benchmark for FUs (#449) --- constants/ecp5_pinout.py | 38 +++----- constants/ecp5_platforms.py | 115 +++++++++++++++++------ coreblocks/fu/div_unit.py | 2 +- coreblocks/params/configurations.py | 2 +- scripts/synthesize.py | 140 +++++++++++++++++++++++----- stubs/amaranth/build/__init__.pyi | 8 ++ stubs/amaranth/build/dsl.pyi | 107 +++++++++++++++++++++ stubs/amaranth/build/plat.pyi | 99 ++++++++++++++++++++ stubs/amaranth/build/res.pyi | 58 ++++++++++++ 9 files changed, 489 insertions(+), 80 deletions(-) create mode 100644 stubs/amaranth/build/__init__.pyi create mode 100644 stubs/amaranth/build/dsl.pyi create mode 100644 stubs/amaranth/build/plat.pyi create mode 100644 stubs/amaranth/build/res.pyi diff --git a/constants/ecp5_pinout.py b/constants/ecp5_pinout.py index 96cd9683d..17fe0d90f 100644 --- a/constants/ecp5_pinout.py +++ b/constants/ecp5_pinout.py @@ -1,25 +1,17 @@ -ecp5_bg381_pins = """ - A4 A5 B5 C5 C4 A3 B4 B3 E4 C3 D5 D3 F4 E5 E3 - F5 A2 B2 B1 C2 C1 D2 D1 E1 H4 H5 G5 H3 G3 F2 - F3 E2 G2 H2 F1 G1 J4 J3 J5 K3 H1 K2 J1 K1 K4 - L4 K5 L5 M5 M4 N4 N5 P5 N3 L3 M3 L2 N2 L1 M1 - N1 P1 P2 P3 P4 R1 U1 T1 V1 W1 V2 Y2 W2 T2 R2 - U2 R3 T3 V3 U3 Y3 R4 V4 R5 W4 W5 T8 Y6 Y7 T9 - Y8 W8 T10 W9 W10 W11 Y11 Y12 W13 T11 W14 Y14 - T12 Y15 Y16 T13 Y17 W17 T14 W18 Y19 W20 T17 - U16 U17 U18 T18 R18 U19 T19 U20 R20 T20 P20 - P18 N20 P19 N19 T16 R17 P16 R16 N17 P17 M17 - N18 N16 M18 L17 L18 L16 M19 M20 L19 L20 K20 - K19 J20 J19 K18 H20 J18 G19 G20 F19 F20 E20 - E19 D19 D20 C20 K17 K16 J16 H17 J17 H18 H16 - G18 G16 F17 F18 E17 E18 D18 F16 E16 D17 C18 - B20 B19 A19 A18 B18 C17 A17 B17 D16 B16 C16 - A16 E15 C15 D15 B15 A15 E14 C14 D14 A14 E13 - C13 D13 B13 A13 E12 A12 D12 C12 E11 B12 D11 - C11 A11 B11 A10 B10 C10 A9 B9 E10 D10 C9 E9 - A8 D9 A7 B8 D8 C8 E8 C7 D7 C6 E7 D6 B6 E6 A6 +ecp5_bg756_pins = """ +C17 A17 A18 E17 P27 N27 R26 P28 R7 P5 P6 N6 AK32 AJ32 AM30 AL30 AK31 AJ31 AM31 AL32 AG28 AG29 AJ28 AH28 AH30 AG30 +AK29 AK30 AH32 AG32 AJ2 AK2 AJ29 AJ30 AG3 AH3 AJ3 AK3 AL3 AG1 AH1 AJ1 AK1 AM28 AM29 AL28 AK28 AL1 AM2 C5 D5 C4 C3 +D4 E4 F4 F5 B1 C2 D3 D2 F3 E3 C1 D1 F2 E1 F1 H1 H2 H3 J3 K3 K2 J1 K1 L1 L2 L3 J4 K4 H6 H5 J7 J6 K6 K7 K5 L4 N3 N4 +L7 L6 N7 P7 P4 T7 R6 T6 U6 U7 R4 T5 T4 U5 U4 V4 V6 V7 P2 P3 R3 T3 N1 P1 U2 U3 R1 T2 W3 Y3 T1 U1 V1 W1 Y7 Y6 Y5 W5 +Y4 W4 AB7 AC6 AB5 AB6 AC7 AD7 AD6 AE6 AE5 AE4 AB3 AB4 AC5 AD4 W2 Y1 AD3 AE3 AC3 AB2 AC2 AE2 AB1 AC1 AD1 AE1 C28 D28 +C29 C30 D29 E29 F29 F28 B32 C31 D30 D31 F30 E30 C32 D32 F31 E32 F32 H32 H31 H30 J30 K30 K31 J32 K32 L32 L31 L30 J29 +K29 H27 H28 J26 J27 K27 K26 K28 L29 N30 N29 L26 L27 N26 P26 P29 T26 R27 T27 U27 U26 R29 T28 T29 U28 U29 V29 V27 V26 +P31 P30 R30 T30 N32 P32 U31 U30 R32 T31 W30 Y30 T32 U32 V32 W32 Y26 Y27 Y28 W28 Y29 W29 AB26 AC27 AB28 AB27 AC26 +AD26 AD27 AE27 AE28 AE29 AB30 AB29 AC28 AD29 W31 Y32 AD30 AE30 AC30 AB31 AC31 AE31 AB32 AC32 AD32 AE32 A24 C24 D24 +F24 A25 B25 C25 D25 E25 A26 B26 C26 D26 A28 A29 A30 A31 D7 C7 B29 B30 B7 A7 F8 E8 D8 C8 B8 A8 F9 D9 C9 A9 F10 E10 +D10 C10 B10 A10 F11 E11 D11 C11 B11 A11 F13 D13 C13 A13 F14 E14 D14 C14 B14 A14 B3 B4 F15 D15 C15 A15 F16 E16 D16 +C16 B16 A16 B17 D17 F17 A2 A3 C18 D18 F18 A19 B19 C19 D19 E19 F19 A20 C20 D20 F20 A22 B22 C22 D22 E22 F22 A23 B23 +C23 D23 E23 F23 A4 A5 """.split() -ecp5_bg381_pclk = """ - G3 F2 G2 H2 L19 L20 J20 J19 B12 D11 B11 A10 -""".split() +ecp5_bg756_pclk = "C17 A17 A18 E17 P27 N27 R26 P28 R7 P5 P6 N6".split() diff --git a/constants/ecp5_platforms.py b/constants/ecp5_platforms.py index c05972186..55ad94478 100644 --- a/constants/ecp5_platforms.py +++ b/constants/ecp5_platforms.py @@ -1,10 +1,14 @@ +from collections.abc import Callable, Iterable +from itertools import chain +from typing import TypeAlias from amaranth.build.dsl import Subsignal from amaranth.vendor.lattice_ecp5 import LatticeECP5Platform from amaranth.build import Resource, Attrs, Pins, Clock, PinsN -from constants.ecp5_pinout import ecp5_bg381_pins, ecp5_bg381_pclk +from constants.ecp5_pinout import ecp5_bg756_pins, ecp5_bg756_pclk from coreblocks.peripherals.wishbone import WishboneParameters +from coreblocks.transactions.lib import AdapterBase __all__ = ["make_ecp5_platform"] @@ -31,51 +35,102 @@ def WishboneResource( # noqa: N802 return Resource.family(*args, default_name="wishbone", ios=io) -def make_ecp5_platform(wb_params: WishboneParameters): - pin_bag = ecp5_bg381_pins[:] +def AdapterResource(*args, en, done, data_in, data_out, conn=None): # noqa: N802 + io = [] + + io.append(Subsignal("en", Pins(en, dir="i", conn=conn, assert_width=1))) + io.append(Subsignal("done", Pins(done, dir="o", conn=conn, assert_width=1))) + if data_in: + io.append(Subsignal("data_in", Pins(data_in, dir="i", conn=conn))) + if data_out: + io.append(Subsignal("data_out", Pins(data_out, dir="o", conn=conn))) + + return Resource.family(*args, default_name="adapter", ios=io) + - def p(count: int = 1): - return " ".join([pin_bag.pop() for _ in range(count)]) +class PinManager: + def __init__(self, pins: Iterable[str]): + self.pin_bag = list(pins) - def named_pin(names: list[str]): + def p(self, count: int = 1): + return " ".join([self.pin_bag.pop() for _ in range(count)]) + + def named_pin(self, names: list[str]): for name in names: - if name in pin_bag: - pin_bag.remove(name) + if name in self.pin_bag: + self.pin_bag.remove(name) return name + +ResourceBuilder: TypeAlias = Callable[[PinManager], list[Resource]] + + +def wishbone_resources(wb_params: WishboneParameters): + def make_resources(pins: PinManager) -> list[Resource]: + return [ + WishboneResource( + 0, + dat_r=pins.p(wb_params.data_width), + dat_w=pins.p(wb_params.data_width), + rst=pins.p(), + ack=pins.p(), + adr=pins.p(wb_params.addr_width), + cyc=pins.p(), + stall=pins.p(), + err=pins.p(), + lock=pins.p(), + rty=pins.p(), + sel=pins.p(wb_params.data_width // wb_params.granularity), + stb=pins.p(), + we=pins.p(), + ), + ] + + return make_resources + + +def adapter_resources(adapter: AdapterBase, number: int): + def make_resources(pins: PinManager) -> list[Resource]: + return [ + AdapterResource( + number, + en=pins.p(), + done=pins.p(), + data_in=pins.p(adapter.data_in.shape().width), + data_out=pins.p(adapter.data_out.shape().width), + ) + ] + + return make_resources + + +def append_resources(*args: ResourceBuilder): + def make_resources(pins: PinManager): + return list(chain.from_iterable(map(lambda f: f(pins), args))) + + return make_resources + + +def make_ecp5_platform(resource_builder: ResourceBuilder): + pins = PinManager(ecp5_bg756_pins) + # Tutorial for synthesis in amaranth: # https://github.com/RobertBaruch/amaranth-tutorial/blob/main/9_synthesis.md - class ECP5BG381Platform(LatticeECP5Platform): + class ECP5BG756Platform(LatticeECP5Platform): device = "LFE5UM5G-85F" - package = "BG381" + package = "BG756" speed = "8" default_clk = "clk" default_rst = "rst" resources = [ - Resource("rst", 0, PinsN(p(), dir="i"), Attrs(IO_TYPE="LVCMOS33")), - Resource("clk", 0, Pins(named_pin(ecp5_bg381_pclk), dir="i"), Clock(12e6), Attrs(IO_TYPE="LVCMOS33")), - WishboneResource( - 0, - dat_r=p(wb_params.data_width), - dat_w=p(wb_params.data_width), - rst=p(), - ack=p(), - adr=p(wb_params.addr_width), - cyc=p(), - stall=p(), - err=p(), - lock=p(), - rty=p(), - sel=p(wb_params.data_width // wb_params.granularity), - stb=p(), - we=p(), - ), - ] + Resource("rst", 0, PinsN(pins.p(), dir="i"), Attrs(IO_TYPE="LVCMOS33")), + Resource("clk", 0, Pins(pins.named_pin(ecp5_bg756_pclk), dir="i"), Clock(12e6), Attrs(IO_TYPE="LVCMOS33")), + ] + resource_builder(pins) connectors = [] def toolchain_program(self): pass - return ECP5BG381Platform + return ECP5BG756Platform diff --git a/coreblocks/fu/div_unit.py b/coreblocks/fu/div_unit.py index 7cbfe3e1f..12019e984 100644 --- a/coreblocks/fu/div_unit.py +++ b/coreblocks/fu/div_unit.py @@ -138,7 +138,7 @@ def _abs(s: Value) -> Value: @dataclass class DivComponent(FunctionalComponentParams): _: KW_ONLY - ipc: int = 4 # iterations per cycle + ipc: int = 3 # iterations per cycle div_fn = DivFn() def get_module(self, gen_params: GenParams) -> FuncUnit: diff --git a/coreblocks/params/configurations.py b/coreblocks/params/configurations.py index 1f5bb71e4..7d463a03f 100644 --- a/coreblocks/params/configurations.py +++ b/coreblocks/params/configurations.py @@ -116,7 +116,7 @@ def replace(self, **kwargs): RSBlockComponent( [ MulComponent(mul_unit_type=MulType.SEQUENCE_MUL), - DivComponent(ipc=3), + DivComponent(), ], rs_entries=2, ), diff --git a/scripts/synthesize.py b/scripts/synthesize.py index 43ce88b7b..dec8104f1 100755 --- a/scripts/synthesize.py +++ b/scripts/synthesize.py @@ -1,23 +1,38 @@ #!/usr/bin/env python3 +from collections.abc import Callable import os import sys import argparse from amaranth.build import Platform -from amaranth import Module, Elaboratable - +from amaranth import * if __name__ == "__main__": parent = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, parent) +from coreblocks.utils.utils import ModuleConnector from coreblocks.params.genparams import GenParams +from coreblocks.params.fu_params import FunctionalComponentParams from coreblocks.core import Core +from coreblocks.fu.alu import ALUComponent +from coreblocks.fu.div_unit import DivComponent +from coreblocks.fu.mul_unit import MulComponent, MulType +from coreblocks.fu.shift_unit import ShiftUnitComponent +from coreblocks.fu.zbc import ZbcComponent +from coreblocks.fu.zbs import ZbsComponent from coreblocks.transactions import TransactionModule +from coreblocks.transactions.lib import AdapterBase, AdapterTrans from coreblocks.peripherals.wishbone import WishboneArbiter, WishboneBus -from constants.ecp5_platforms import make_ecp5_platform +from constants.ecp5_platforms import ( + ResourceBuilder, + adapter_resources, + append_resources, + wishbone_resources, + make_ecp5_platform, +) from coreblocks.params.configurations import * @@ -28,40 +43,106 @@ } -class TestElaboratable(Elaboratable): - def __init__(self, gen_params: GenParams): - self.gen_params = gen_params +class WishboneConnector(Elaboratable): + def __init__(self, wb: WishboneBus, number: int): + self.wb = wb + self.number = number def elaborate(self, platform: Platform): m = Module() - tm = TransactionModule(m) - self.wb_instr = WishboneBus(self.gen_params.wb_params) - self.wb_data = WishboneBus(self.gen_params.wb_params) + pins = platform.request("wishbone", self.number) + assert isinstance(pins, Record) + + m.d.comb += self.wb.connect(pins) + + return m + + +class AdapterConnector(Elaboratable): + def __init__(self, adapter: AdapterBase, number: int): + self.adapter = adapter + self.number = number + + @staticmethod + def with_resources(adapter: AdapterBase, number: int): + return AdapterConnector(adapter, number), adapter_resources(adapter, number) + + def elaborate(self, platform: Platform): + m = Module() + + m.submodules.adapter = self.adapter + + pins = platform.request("adapter", self.number) + assert isinstance(pins, Record) + + m.d.comb += self.adapter.en.eq(pins.en) + m.d.comb += pins.done.eq(self.adapter.done) + if "data_in" in pins.fields: + m.d.comb += self.adapter.data_in.eq(pins.data_in) + if "data_out" in pins.fields: + m.d.comb += pins.data_out.eq(self.adapter.data_out) + + return m + + +UnitCore = Callable[[GenParams], tuple[ResourceBuilder, Elaboratable]] - self.core = Core(gen_params=self.gen_params, wb_instr_bus=self.wb_instr, wb_data_bus=self.wb_data) - # Combine Wishbone buses with an arbiter - wb = WishboneBus(self.gen_params.wb_params) - self.wb_arbiter = WishboneArbiter(wb, [self.wb_instr, self.wb_data]) +def unit_core(gen_params: GenParams): + resources = wishbone_resources(gen_params.wb_params) - # Request platform pins - wb_pins = platform.request("wishbone", 0) + wb_instr = WishboneBus(gen_params.wb_params) + wb_data = WishboneBus(gen_params.wb_params) - # Connect pins to the core - m.d.comb += wb.connect(wb_pins) + core = Core(gen_params=gen_params, wb_instr_bus=wb_instr, wb_data_bus=wb_data) - m.submodules.wb_arbiter = self.wb_arbiter - m.submodules.c = self.core + wb = WishboneBus(gen_params.wb_params) + wb_arbiter = WishboneArbiter(wb, [wb_instr, wb_data]) + wb_connector = WishboneConnector(wb, 0) - return tm + module = ModuleConnector(core=core, wb_arbiter=wb_arbiter, wb_connector=wb_connector) + return resources, TransactionModule(module) -def synthesize(core_config: CoreConfiguration, platform: str): + +def unit_fu(unit_params: FunctionalComponentParams): + def unit(gen_params: GenParams): + fu = unit_params.get_module(gen_params) + + issue_connector, issue_resources = AdapterConnector.with_resources(AdapterTrans(fu.issue), 0) + accept_connector, accept_resources = AdapterConnector.with_resources(AdapterTrans(fu.accept), 1) + + resources = append_resources(issue_resources, accept_resources) + + module = ModuleConnector(fu=fu, issue_connector=issue_connector, accept_connector=accept_connector) + + return resources, TransactionModule(module) + + return unit + + +core_units = { + "core": unit_core, + "alu_basic": unit_fu(ALUComponent(False, False)), + "alu_full": unit_fu(ALUComponent(True, True)), + "mul_shift": unit_fu(MulComponent(MulType.SHIFT_MUL)), + "mul_sequence": unit_fu(MulComponent(MulType.SEQUENCE_MUL)), + "mul_recursive": unit_fu(MulComponent(MulType.RECURSIVE_MUL)), + "div": unit_fu(DivComponent()), + "shift_basic": unit_fu(ShiftUnitComponent(False)), + "shift_full": unit_fu(ShiftUnitComponent(True)), + "zbs": unit_fu(ZbsComponent()), + "zbc": unit_fu(ZbcComponent()), +} + + +def synthesize(core_config: CoreConfiguration, platform: str, core: UnitCore): gen_params = GenParams(core_config) + resource_builder, module = core(gen_params) if platform == "ecp5": - make_ecp5_platform(gen_params.wb_params)().build(TestElaboratable(gen_params)) + make_ecp5_platform(resource_builder)().build(module) def main(): @@ -77,10 +158,16 @@ def main(): parser.add_argument( "-c", "--config", - action="store", default="basic", help="Select core configuration. " - + f"Available configurations: {', '.join(list(str_to_coreconfig.keys()))}. Default: %(default)s", + + f"Available configurations: {', '.join(str_to_coreconfig.keys())}. Default: %(default)s", + ) + + parser.add_argument( + "-u", + "--unit", + default="core", + help="Select core unit." + f"Available units: {', '.join(core_units.keys())}. Default: %(default)s", ) parser.add_argument( @@ -97,7 +184,10 @@ def main(): if args.config not in str_to_coreconfig: raise KeyError(f"Unknown config '{args.config}'") - synthesize(str_to_coreconfig[args.config], args.platform) + if args.unit not in core_units: + raise KeyError(f"Unknown core unit '{args.unit}'") + + synthesize(str_to_coreconfig[args.config], args.platform, core_units[args.unit]) if __name__ == "__main__": diff --git a/stubs/amaranth/build/__init__.pyi b/stubs/amaranth/build/__init__.pyi new file mode 100644 index 000000000..f08463f31 --- /dev/null +++ b/stubs/amaranth/build/__init__.pyi @@ -0,0 +1,8 @@ +""" +This type stub file was generated by pyright. +""" + +from .dsl import * +from .res import ResourceError +from .plat import * + diff --git a/stubs/amaranth/build/dsl.pyi b/stubs/amaranth/build/dsl.pyi new file mode 100644 index 000000000..9669a9f2c --- /dev/null +++ b/stubs/amaranth/build/dsl.pyi @@ -0,0 +1,107 @@ +""" +This type stub file was generated by pyright. +""" + +from collections import OrderedDict +from collections.abc import Iterator, Mapping +from typing import Optional + +__all__ = ["Pins", "PinsN", "DiffPairs", "DiffPairsN", "Attrs", "Clock", "Subsignal", "Resource", "Connector"] +class Pins: + def __init__(self, names: str, *, dir: str=..., invert: bool=..., conn: Optional[tuple[str, int|str]]=..., assert_width: Optional[int]=...) -> None: + ... + + def __len__(self) -> int: + ... + + def __iter__(self) -> Iterator[str]: + ... + + def map_names(self, mapping: Mapping[str, str], resource) -> list[str]: + ... + + def __repr__(self) -> str: + ... + + + +def PinsN(*args, **kwargs) -> Pins: + ... + +class DiffPairs: + def __init__(self, p: str, n: str, *, dir: str=..., invert: bool=..., conn: Optional[tuple[str, int|str]]=..., assert_width: Optional[int]=...) -> None: + ... + + def __len__(self) -> int: + ... + + def __iter__(self) -> Iterator[tuple[str, str]]: + ... + + def __repr__(self) -> str: + ... + + + +def DiffPairsN(*args, **kwargs) -> DiffPairs: + ... + +class Attrs(OrderedDict): + def __init__(self, **attrs) -> None: + ... + + def __repr__(self) -> str: + ... + + + +class Clock: + def __init__(self, frequency: float | int) -> None: + ... + + @property + def period(self) -> float: + ... + + def __repr__(self) -> str: + ... + + + +class Subsignal: + def __init__(self, name: str, *args: Pins | DiffPairs | Subsignal | Attrs | Clock) -> None: + ... + + def __repr__(self) -> str: + ... + + + +class Resource(Subsignal): + @classmethod + def family(cls, name_or_number: str | int, number: Optional[int]=..., *, ios, default_name: str, name_suffix: str=...): # -> Self@Resource: + ... + + def __init__(self, name, number, *args) -> None: + ... + + def __repr__(self) -> str: + ... + + + +class Connector: + def __init__(self, name: str, number: int, io: str | dict[str, str], *, conn: Optional[tuple[str, int|str]]=...) -> None: + ... + + def __repr__(self) -> str: + ... + + def __len__(self) -> int: + ... + + def __iter__(self) -> Iterator[tuple[str, str]]: + ... + + + diff --git a/stubs/amaranth/build/plat.pyi b/stubs/amaranth/build/plat.pyi new file mode 100644 index 000000000..34f1b5f76 --- /dev/null +++ b/stubs/amaranth/build/plat.pyi @@ -0,0 +1,99 @@ +""" +This type stub file was generated by pyright. +""" + +from abc import ABCMeta, abstractmethod +from .._toolchain import * +from ..hdl import * +from .res import * +from .run import * + +__all__ = ["Platform", "TemplatedPlatform"] +class Platform(ResourceManager, metaclass=ABCMeta): + resources = ... + connectors = ... + default_clk = ... + default_rst = ... + required_tools = ... + def __init__(self) -> None: + ... + + @property + def default_clk_constraint(self): + ... + + @property + def default_clk_frequency(self): + ... + + def add_file(self, filename, content): # -> None: + ... + + def iter_files(self, *suffixes): # -> Generator[Unknown, Any, None]: + ... + + def build(self, elaboratable, name=..., build_dir=..., do_build=..., program_opts=..., do_program=..., **kwargs): # -> None: + ... + + def has_required_tools(self): # -> bool: + ... + + def create_missing_domain(self, name): # -> Module | None: + ... + + def prepare(self, elaboratable, name=..., **kwargs): + ... + + @abstractmethod + def toolchain_prepare(self, fragment, name, **kwargs): + """ + Convert the ``fragment`` and constraints recorded in this :class:`Platform` into + a :class:`BuildPlan`. + """ + ... + + def toolchain_program(self, products, name, **kwargs): + """ + Extract bitstream for fragment ``name`` from ``products`` and download it to a target. + """ + ... + + def get_input(self, pin, port, attrs, invert): # -> Module: + ... + + def get_output(self, pin, port, attrs, invert): # -> Module: + ... + + def get_tristate(self, pin, port, attrs, invert): # -> Module: + ... + + def get_input_output(self, pin, port, attrs, invert): # -> Module: + ... + + def get_diff_input(self, pin, port, attrs, invert): # -> None: + ... + + def get_diff_output(self, pin, port, attrs, invert): # -> None: + ... + + def get_diff_tristate(self, pin, port, attrs, invert): # -> None: + ... + + def get_diff_input_output(self, pin, port, attrs, invert): # -> None: + ... + + + +class TemplatedPlatform(Platform): + toolchain = ... + file_templates = ... + command_templates = ... + build_script_templates = ... + def iter_clock_constraints(self): # -> Generator[tuple[Unknown, Unknown | None, Unknown], Any, None]: + ... + + def toolchain_prepare(self, fragment, name, **kwargs): # -> BuildPlan: + ... + + + diff --git a/stubs/amaranth/build/res.pyi b/stubs/amaranth/build/res.pyi new file mode 100644 index 000000000..41b734ca9 --- /dev/null +++ b/stubs/amaranth/build/res.pyi @@ -0,0 +1,58 @@ +""" +This type stub file was generated by pyright. +""" + +from typing import Any +from ..hdl.ast import * +from ..hdl.rec import * +from ..lib.io import * +from .dsl import * +from collections.abc import Iterable, Iterator + +__all__ = ["ResourceError", "ResourceManager"] +class ResourceError(Exception): + ... + + +class ResourceManager: + def __init__(self, resources: Iterable[Resource], connectors: Iterable[Connector]) -> None: + ... + + def add_resources(self, resources: Iterable[Resource]) -> None: + ... + + def add_connectors(self, connectors: Iterable[Connector]) -> None: + ... + + def lookup(self, name: str, number: int=...) -> Resource: + ... + + def request(self, name: str, number: int=..., *, dir=..., xdr=...) -> Record | Pin: + ... + + def iter_single_ended_pins(self): # -> Generator[tuple[Unknown, Unknown, Unknown, Unknown], Any, None]: + ... + + def iter_differential_pins(self): # -> Generator[tuple[Unknown, Unknown, Unknown, Unknown], Any, None]: + ... + + def should_skip_port_component(self, port, attrs, component) -> bool: + ... + + def iter_ports(self): # -> Generator[Unknown, Any, None]: + ... + + def iter_port_constraints(self): # -> Generator[tuple[Unknown, Unknown, Unknown], Any, None]: + ... + + def iter_port_constraints_bits(self): # -> Generator[tuple[Unknown, Unknown, Unknown] | tuple[str, Unknown, Unknown], Any, None]: + ... + + def add_clock_constraint(self, clock: Signal, frequency: int | float) -> None: + ... + + def iter_clock_constraints(self) -> Iterator[tuple[Signal, Any, int | float]]: + ... + + +