From 0acc30501201399d16d033304a06eddc9f63af25 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 18 Mar 2019 00:21:54 -0700 Subject: [PATCH] add more type annotations --- nmigen/__init__.pyi | 4 +++ nmigen/hdl/ast.pyi | 20 +++++++++-- nmigen/hdl/cd.pyi | 22 ++++++++++++ nmigen/hdl/dsl.pyi | 17 +++++++-- nmigen/hdl/ir.pyi | 77 +++++++++++++++++++++++++++++++++++++++ nmigen/hdl/mem.pyi | 58 ++++++++++++++++++++++++++++++ nmigen/hdl/rec.pyi | 88 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 nmigen/hdl/cd.pyi create mode 100644 nmigen/hdl/ir.pyi create mode 100644 nmigen/hdl/mem.pyi create mode 100644 nmigen/hdl/rec.pyi diff --git a/nmigen/__init__.pyi b/nmigen/__init__.pyi index 97420dc..14f0227 100644 --- a/nmigen/__init__.pyi +++ b/nmigen/__init__.pyi @@ -9,3 +9,7 @@ from .hdl.ast import (Value as Value, Signal as Signal, ClockSignal as ClockSignal, ResetSignal as ResetSignal) +from .hdl.cd import ClockDomain as ClockDomain +from .hdl.ir import Fragment as Fragment, Instance as Instance +from .hdl.mem import Memory as Memory +from .hdl.rec import Record as Record diff --git a/nmigen/hdl/ast.pyi b/nmigen/hdl/ast.pyi index 97cfb10..b978956 100644 --- a/nmigen/hdl/ast.pyi +++ b/nmigen/hdl/ast.pyi @@ -15,6 +15,10 @@ ShapeResult = Tuple[int, bool] class Value(metaclass=ABCMeta): + @staticmethod + def wrap(obj: Any) -> 'Value': + ... + def __invert__(self) -> 'Value': ... @@ -102,7 +106,7 @@ class Value(metaclass=ABCMeta): def __len__(self) -> int: ... - def __getitem__(self, key: Union[slice, int]) -> 'Value': + def __getitem__(self, key: Union[slice, int, str]) -> 'Value': ... def bool(self) -> 'Value': @@ -130,6 +134,10 @@ class Const(Value): nbits: int signed: bool + @staticmethod + def normalize(value: int, shape: Tuple[int, bool]) -> int: + ... + def __init__(self, value: int, shape: Optional[ShapeArgument] = None) -> None: ... @@ -213,11 +221,17 @@ class ResetSignal(Value): ... -class Statement: +StatementOrStatementList = Union[Iterable['Statement'], 'Statement'] + + +class _StatementList(list): pass -StatementOrStatementList = Union[Iterable[Statement], Statement] +class Statement: + @staticmethod + def wrap(obj: StatementOrStatementList) -> _StatementList: + ... class Assign(Statement): diff --git a/nmigen/hdl/cd.pyi b/nmigen/hdl/cd.pyi new file mode 100644 index 0000000..c60f01d --- /dev/null +++ b/nmigen/hdl/cd.pyi @@ -0,0 +1,22 @@ +from .ast import Signal +from typing import Optional + +__all__ = ["ClockDomain", "DomainError"] + + +class DomainError(Exception): + pass + + +class ClockDomain: + clk: Signal + rst: Optional[Signal] + + def __init__(self, + name: Optional[str] = None, + reset_less: bool = False, + async_reset: bool = False): + ... + + def rename(self, new_name: str) -> None: + ... diff --git a/nmigen/hdl/dsl.pyi b/nmigen/hdl/dsl.pyi index f7e6f70..cb22701 100644 --- a/nmigen/hdl/dsl.pyi +++ b/nmigen/hdl/dsl.pyi @@ -1,5 +1,5 @@ -from .ast import Statement, ValueOrLiteral -from typing import Iterable, Union, Any +from .ast import Statement, ValueOrLiteral, Signal +from typing import Iterable, Union, Any, Mapping from contextlib import ContextDecorator __all__ = ["Module"] @@ -37,6 +37,19 @@ class _ValuelessContext: ... +class FSM: + def __init__(self, + state: Signal, + encoding: Mapping[str, int], + decoding: Mapping[int, str]): + self.state = state + self.encoding = encoding + self.decoding = decoding + + def ongoing(self, name: str) -> bool: + ... + + class Module(_ModuleBuilderRoot): submodules: Any diff --git a/nmigen/hdl/ir.pyi b/nmigen/hdl/ir.pyi new file mode 100644 index 0000000..59cd892 --- /dev/null +++ b/nmigen/hdl/ir.pyi @@ -0,0 +1,77 @@ +from typing import Optional, Generator, Any, Tuple, Iterable, Union, List +from .ast import Signal, Statement +from .cd import ClockDomain +from .dsl import FSM + +__all__ = ["Fragment", "Instance", "DriverConflict"] + + +class DriverConflict(UserWarning): + pass + + +class Fragment: + @staticmethod + def get(obj: Any, platform: Any) -> 'Fragment': + ... + + def add_ports(self, *ports: Any, dir: str) -> None: + ... + + def iter_ports(self, + dir: Optional[str] = None) -> Generator[Signal, None, None]: + ... + + def add_driver(self, + signal: Signal, domain: Optional[str] = None) -> None: + ... + + def iter_drivers(self) -> Generator[Tuple[Optional[str], Signal], + None, None]: + ... + + def iter_comb(self) -> Generator[Signal, None, None]: + ... + + def iter_sync(self) -> Generator[Tuple[str, Signal], None, None]: + ... + + def iter_signals(self) -> Iterable[Signal]: + ... + + def add_domains(self, + *domains: Iterable[Union[Iterable[ClockDomain], + ClockDomain]]) -> None: + ... + + def iter_domains(self) -> Generator[str, None, None]: + ... + + def add_statements(self, + *stmts: Iterable[Union[Iterable[Statement], + Statement]]) -> None: + ... + + def add_subfragment(self, + subfragment: 'Fragment', + name: Optional[str] = None) -> None: + ... + + def find_subfragment(self, name_or_index: Union[int, str]) -> 'Fragment': + ... + + def find_generated(self, *path: List[Union[int, str]]) -> FSM: + ... + + def elaborate(self, platform: Any) -> 'Fragment': + ... + + def prepare(self, + ports: Iterable[Signal] = (), + ensure_sync_exists: bool = True) -> 'Fragment': + ... + + +class Instance(Fragment): + def __init__(self, type: str, **kwargs: Any): + ... diff --git a/nmigen/hdl/mem.pyi b/nmigen/hdl/mem.pyi new file mode 100644 index 0000000..8ebdff0 --- /dev/null +++ b/nmigen/hdl/mem.pyi @@ -0,0 +1,58 @@ +from typing import Optional, Iterable, List, Union +from .ast import Signal, Const + +__all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"] + + +class ReadPort: + memory: 'Memory' + domain: str + synchronous: bool + transparent: bool + addr: Signal + data: Signal + en: Union[Signal, Const] + + +class WritePort: + memory: 'Memory' + domain: str + priority: int + granularity: int + addr: Signal + data: Signal + en: Signal + + +class Memory: + width: int + depth: int + name: str + + def __init__(self, + width: int, + depth: int, + init: Optional[Iterable[int]] = None, + name: Optional[str] = None, + simulate: bool = True): + ... + + @property + def init(self) -> List[int]: + ... + + @init.setter + def init(self, new_init: Optional[Iterable[int]]) -> None: + ... + + def read_port(self, + domain: str = "sync", + synchronous: bool = True, + transparent: bool = True) -> ReadPort: + ... + + def write_port(self, + domain: str = "sync", + priority: int = 0, + granularity: Optional[int] = None) -> WritePort: + ... diff --git a/nmigen/hdl/rec.pyi b/nmigen/hdl/rec.pyi new file mode 100644 index 0000000..577a543 --- /dev/null +++ b/nmigen/hdl/rec.pyi @@ -0,0 +1,88 @@ +import enum +from typing import List, Union, Tuple, Any, Dict, Optional +from .ast import Signal, Value + +__all__ = ["Direction", "DIR_NONE", "DIR_FANOUT", + "DIR_FANIN", "Layout", "Record"] + + +class Direction(enum.Enum): + NONE = enum.auto() + FANOUT = enum.auto() + FANIN = enum.auto() + + +DIR_NONE = Direction.NONE +DIR_FANOUT = Direction.FANOUT +DIR_FANIN = Direction.FANIN + +# recursive types are not yet supported by mypy, manually recurse a few times +LayoutInputFields0 = List[Union[Tuple[str, + Union[int, + Tuple[int, bool], + Any]], + Tuple[str, + Union[int, + Tuple[int, bool]], + Direction]]] + +LayoutInputFields1 = List[Union[Tuple[str, + Union[int, + Tuple[int, bool], + LayoutInputFields0]], + Tuple[str, + Union[int, + Tuple[int, bool]], + Direction]]] + +LayoutInputFields2 = List[Union[Tuple[str, + Union[int, + Tuple[int, bool], + LayoutInputFields1]], + Tuple[str, + Union[int, + Tuple[int, bool]], + Direction]]] + +LayoutInputFields3 = List[Union[Tuple[str, + Union[int, + Tuple[int, bool], + LayoutInputFields2]], + Tuple[str, + Union[int, + Tuple[int, bool]], + Direction]]] + +LayoutInputFields = List[Union[Tuple[str, + Union[int, + Tuple[int, bool], + LayoutInputFields3]], + Tuple[str, + Union[int, + Tuple[int, bool]], + Direction]]] + + +class Layout: + fields: Dict[str, Tuple[Union[int, Tuple[int, bool], 'Layout'], Direction]] + + def __init__(self, fields: LayoutInputFields) -> None: + ... + + +class Record(Value): + layout: Layout + fields: Dict[str, Union[Record, Signal]] + + def __init__(self, layout: LayoutInputFields, name: Optional[str] = None): + ... + + def shape(self) -> Tuple[int, bool]: + ... + + def __getattr__(self, name: str) -> Union[Record, Signal]: + ... + + def __getitem__(self, + name: Union[slice, int, str]) -> Union[Record, Signal]: + ... -- 2.30.2