Pyupgrade to 3.8+. NFCI

This commit is contained in:
Catherine 2023-11-14 12:58:53 +00:00
parent e55dec9615
commit f9da3c0d16
37 changed files with 240 additions and 240 deletions

View file

@ -34,7 +34,7 @@ class MustUse:
if get_linter_option(self._MustUse__context["filename"], if get_linter_option(self._MustUse__context["filename"],
self._MustUse__warning.__name__, bool, True): self._MustUse__warning.__name__, bool, True):
warnings.warn_explicit( warnings.warn_explicit(
"{!r} created but never used".format(self), self._MustUse__warning, f"{self!r} created but never used", self._MustUse__warning,
**self._MustUse__context) **self._MustUse__context)

View file

@ -23,8 +23,8 @@ def _convert_rtlil_text(rtlil_text, black_boxes, *, src_loc_at=0):
script = [] script = []
if black_boxes is not None: if black_boxes is not None:
for box_name, box_source in black_boxes.items(): for box_name, box_source in black_boxes.items():
script.append("read_ilang <<rtlil\n{}\nrtlil".format(box_source)) script.append(f"read_ilang <<rtlil\n{box_source}\nrtlil")
script.append("read_ilang <<rtlil\n{}\nrtlil".format(rtlil_text)) script.append(f"read_ilang <<rtlil\n{rtlil_text}\nrtlil")
script.append("write_cxxrtl") script.append("write_cxxrtl")
return yosys.run(["-q", "-"], "\n".join(script), src_loc_at=1 + src_loc_at) return yosys.run(["-q", "-"], "\n".join(script), src_loc_at=1 + src_loc_at)

View file

@ -29,15 +29,15 @@ def _signed(value):
elif isinstance(value, ast.Const): elif isinstance(value, ast.Const):
return value.signed return value.signed
else: else:
assert False, "Invalid constant {!r}".format(value) assert False, f"Invalid constant {value!r}"
def _const(value): def _const(value):
if isinstance(value, str): if isinstance(value, str):
return "\"{}\"".format(value.translate(_escape_map)) return f"\"{value.translate(_escape_map)}\""
elif isinstance(value, int): elif isinstance(value, int):
if value in range(0, 2**31-1): if value in range(0, 2**31-1):
return "{:d}".format(value) return f"{value:d}"
else: else:
# This code path is only used for Instances, where Verilog-like behavior is desirable. # This code path is only used for Instances, where Verilog-like behavior is desirable.
# Verilog ensures that integers with unspecified width are 32 bits wide or more. # Verilog ensures that integers with unspecified width are 32 bits wide or more.
@ -47,7 +47,7 @@ def _const(value):
value_twos_compl = value.value & ((1 << value.width) - 1) value_twos_compl = value.value & ((1 << value.width) - 1)
return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width) return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width)
else: else:
assert False, "Invalid constant {!r}".format(value) assert False, f"Invalid constant {value!r}"
class _Namer: class _Namer:
@ -58,7 +58,7 @@ class _Namer:
self._names = set() self._names = set()
def anonymous(self): def anonymous(self):
name = "U$${}".format(self._anon) name = f"U$${self._anon}"
assert name not in self._names assert name not in self._names
self._anon += 1 self._anon += 1
return name return name
@ -66,12 +66,12 @@ class _Namer:
def _make_name(self, name, local): def _make_name(self, name, local):
if name is None: if name is None:
self._index += 1 self._index += 1
name = "${}".format(self._index) name = f"${self._index}"
elif not local and name[0] not in "\\$": elif not local and name[0] not in "\\$":
name = "\\{}".format(name) name = f"\\{name}"
while name in self._names: while name in self._names:
self._index += 1 self._index += 1
name = "{}${}".format(name, self._index) name = f"{name}${self._index}"
self._names.add(name) self._names.add(name)
return name return name
@ -259,7 +259,7 @@ class _SwitchBuilder(_AttrBuilder, _ProxiedBuilder):
self._append("{}case\n", " " * (self.indent + 1)) self._append("{}case\n", " " * (self.indent + 1))
else: else:
self._append("{}case {}\n", " " * (self.indent + 1), self._append("{}case {}\n", " " * (self.indent + 1),
", ".join("{}'{}".format(len(value), value) for value in values)) ", ".join(f"{len(value)}'{value}" for value in values))
return _CaseBuilder(self.rtlil, self.indent + 2) return _CaseBuilder(self.rtlil, self.indent + 2)
@ -287,7 +287,7 @@ def _src(src_loc):
if src_loc is None: if src_loc is None:
return None return None
file, line = src_loc file, line = src_loc
return "{}:{}".format(file, line) return f"{file}:{line}"
class _LegalizeValue(Exception): class _LegalizeValue(Exception):
@ -332,7 +332,7 @@ class _ValueCompilerState:
else: else:
port_id = port_kind = None port_id = port_kind = None
if prefix is not None: if prefix is not None:
wire_name = "{}_{}".format(prefix, signal.name) wire_name = f"{prefix}_{signal.name}"
else: else:
wire_name = signal.name wire_name = signal.name
@ -416,9 +416,9 @@ class _ValueCompiler(xfrm.ValueVisitor):
if value.start == value.stop: if value.start == value.stop:
return "{}" return "{}"
elif value.start + 1 == value.stop: elif value.start + 1 == value.stop:
return "{} [{}]".format(sigspec, value.start) return f"{sigspec} [{value.start}]"
else: else:
return "{} [{}:{}]".format(sigspec, value.stop - 1, value.start) return f"{sigspec} [{value.stop - 1}:{value.start}]"
def on_ArrayProxy(self, value): def on_ArrayProxy(self, value):
index = self.s.expand(value.index) index = self.s.expand(value.index)
@ -661,11 +661,11 @@ class _LHSValueCompiler(_ValueCompiler):
else: # new_shape.width > value_shape.width else: # new_shape.width > value_shape.width
dummy_bits = new_shape.width - value_shape.width dummy_bits = new_shape.width - value_shape.width
dummy_wire = self.s.rtlil.wire(dummy_bits) dummy_wire = self.s.rtlil.wire(dummy_bits)
return "{{ {} {} }}".format(dummy_wire, self(value)) return f"{{ {dummy_wire} {self(value)} }}"
def on_Signal(self, value): def on_Signal(self, value):
if value not in self.s.driven: if value not in self.s.driven:
raise ValueError("No LHS wire for non-driven signal {}".format(repr(value))) raise ValueError(f"No LHS wire for non-driven signal {value!r}")
wire_curr, wire_next = self.s.resolve(value) wire_curr, wire_next = self.s.resolve(value)
return wire_next or wire_curr return wire_next or wire_curr
@ -683,7 +683,7 @@ class _LHSValueCompiler(_ValueCompiler):
return slice return slice
else: else:
dummy_wire = self.s.rtlil.wire(stop - len(value.value)) dummy_wire = self.s.rtlil.wire(stop - len(value.value))
return "{{ {} {} }}".format(dummy_wire, slice) return f"{{ {dummy_wire} {slice} }}"
else: else:
# Only so many possible parts. The amount of branches is exponential; if value.offset # Only so many possible parts. The amount of branches is exponential; if value.offset
# is large (e.g. 32-bit wide), trying to naively legalize it is likely to exhaust # is large (e.g. 32-bit wide), trying to naively legalize it is likely to exhaust
@ -813,12 +813,12 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
if isinstance(fragment, ir.Instance): if isinstance(fragment, ir.Instance):
port_map = OrderedDict() port_map = OrderedDict()
for port_name, (value, dir) in fragment.named_ports.items(): for port_name, (value, dir) in fragment.named_ports.items():
port_map["\\{}".format(port_name)] = value port_map[f"\\{port_name}"] = value
if fragment.type[0] == "$": if fragment.type[0] == "$":
return fragment.type, port_map return fragment.type, port_map
else: else:
return "\\{}".format(fragment.type), port_map return f"\\{fragment.type}", port_map
module_name = ".".join(name or "anonymous" for name in hierarchy) module_name = ".".join(name or "anonymous" for name in hierarchy)
module_attrs = OrderedDict() module_attrs = OrderedDict()
@ -898,7 +898,7 @@ def _convert_fragment(builder, fragment, name_map, hierarchy):
lhs_group_filter = xfrm.LHSGroupFilter(group_signals) lhs_group_filter = xfrm.LHSGroupFilter(group_signals)
group_stmts = lhs_group_filter(fragment.statements) group_stmts = lhs_group_filter(fragment.statements)
with module.process(name="$group_{}".format(group)) as process: with module.process(name=f"$group_{group}") as process:
with process.case() as case: with process.case() as case:
# For every signal in comb domain, assign \sig$next to the reset value. # For every signal in comb domain, assign \sig$next to the reset value.
# For every signal in sync domains, assign \sig$next to the current # For every signal in sync domains, assign \sig$next to the current

View file

@ -15,7 +15,7 @@ def _convert_rtlil_text(rtlil_text, *, strip_internal_attrs=False, write_verilog
yosys_version = yosys.version() yosys_version = yosys.version()
script = [] script = []
script.append("read_ilang <<rtlil\n{}\nrtlil".format(rtlil_text)) script.append(f"read_ilang <<rtlil\n{rtlil_text}\nrtlil")
if yosys_version >= (0, 17): if yosys_version >= (0, 17):
script.append("proc -nomux -norom") script.append("proc -nomux -norom")
else: else:

View file

@ -18,7 +18,7 @@ class Pins:
raise TypeError("Connector must be None or a pair of string (connector name) and " raise TypeError("Connector must be None or a pair of string (connector name) and "
"integer/string (connector number), not {!r}" "integer/string (connector number), not {!r}"
.format(conn)) .format(conn))
names = ["{}_{}:{}".format(conn_name, conn_number, name) for name in names] names = [f"{conn_name}_{conn_number}:{name}" for name in names]
if dir not in ("i", "o", "io", "oe"): if dir not in ("i", "o", "io", "oe"):
raise TypeError("Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not {!r}" raise TypeError("Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not {!r}"
@ -118,7 +118,7 @@ class Clock:
return 1 / self.frequency return 1 / self.frequency
def __repr__(self): def __repr__(self):
return "(clock {})".format(self.frequency) return f"(clock {self.frequency})"
class Subsignal: class Subsignal:
@ -173,7 +173,7 @@ class Subsignal:
return " ".join(parts) return " ".join(parts)
def __repr__(self): def __repr__(self):
return "(subsignal {} {})".format(self.name, self._content_repr()) return f"(subsignal {self.name} {self._content_repr()})"
class Resource(Subsignal): class Resource(Subsignal):
@ -205,7 +205,7 @@ class Resource(Subsignal):
self.number = number self.number = number
def __repr__(self): def __repr__(self):
return "(resource {} {} {})".format(self.name, self.number, self._content_repr()) return f"(resource {self.name} {self.number} {self._content_repr()})"
class Connector: class Connector:
@ -242,13 +242,13 @@ class Connector:
.format(conn)) .format(conn))
for conn_pin, plat_pin in mapping.items(): for conn_pin, plat_pin in mapping.items():
mapping[conn_pin] = "{}_{}:{}".format(conn_name, conn_number, plat_pin) mapping[conn_pin] = f"{conn_name}_{conn_number}:{plat_pin}"
self.mapping = mapping self.mapping = mapping
def __repr__(self): def __repr__(self):
return "(connector {} {} {})".format(self.name, self.number, return "(connector {} {} {})".format(self.name, self.number,
" ".join("{}=>{}".format(conn, plat) " ".join(f"{conn}=>{plat}"
for conn, plat in self.mapping.items())) for conn, plat in self.mapping.items()))
def __len__(self): def __len__(self):
@ -256,4 +256,4 @@ class Connector:
def __iter__(self): def __iter__(self):
for conn_pin, plat_pin in self.mapping.items(): for conn_pin, plat_pin in self.mapping.items():
yield "{}_{}:{}".format(self.name, self.number, conn_pin), plat_pin yield f"{self.name}_{self.number}:{conn_pin}", plat_pin

View file

@ -151,7 +151,7 @@ class Platform(ResourceManager, metaclass=ABCMeta):
pin_fragment = Fragment.get(pin_fragment, self) pin_fragment = Fragment.get(pin_fragment, self)
if not isinstance(pin_fragment, Instance): if not isinstance(pin_fragment, Instance):
pin_fragment.flatten = True pin_fragment.flatten = True
fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin.name)) fragment.add_subfragment(pin_fragment, name=f"pin_{pin.name}")
for pin, port, attrs, invert in self.iter_single_ended_pins(): for pin, port, attrs, invert in self.iter_single_ended_pins():
if pin.dir == "i": if pin.dir == "i":
@ -317,7 +317,7 @@ class TemplatedPlatform(Platform):
# This notice serves a dual purpose: to explain that the file is autogenerated, # This notice serves a dual purpose: to explain that the file is autogenerated,
# and to incorporate the Amaranth version into generated code. # and to incorporate the Amaranth version into generated code.
autogenerated = "Automatically generated by Amaranth {}. Do not edit.".format(__version__) autogenerated = f"Automatically generated by Amaranth {__version__}. Do not edit."
rtlil_text, self._name_map = rtlil.convert_fragment(fragment, name=name, emit_src=emit_src) rtlil_text, self._name_map = rtlil.convert_fragment(fragment, name=name, emit_src=emit_src)
@ -325,7 +325,7 @@ class TemplatedPlatform(Platform):
# expected_type parameter is used to assert the type of kwargs, passing `None` will disable # expected_type parameter is used to assert the type of kwargs, passing `None` will disable
# type checking. # type checking.
def _extract_override(var, *, expected_type): def _extract_override(var, *, expected_type):
var_env = "AMARANTH_{}".format(var) var_env = f"AMARANTH_{var}"
if var_env in os.environ: if var_env in os.environ:
# On Windows, there is no way to define an "empty but set" variable; it is tempting # On Windows, there is no way to define an "empty but set" variable; it is tempting
# to use a quoted empty string, but it doesn't do what one would expect. Recognize # to use a quoted empty string, but it doesn't do what one would expect. Recognize
@ -339,7 +339,7 @@ class TemplatedPlatform(Platform):
if issubclass(expected_type, str) and not isinstance(kwarg, str) and isinstance(kwarg, Iterable): if issubclass(expected_type, str) and not isinstance(kwarg, str) and isinstance(kwarg, Iterable):
kwarg = " ".join(kwarg) kwarg = " ".join(kwarg)
if not isinstance(kwarg, expected_type) and not expected_type is None: if not isinstance(kwarg, expected_type) and not expected_type is None:
raise TypeError("Override '{}' must be a {}, not {!r}".format(var, expected_type.__name__, kwarg)) raise TypeError(f"Override '{var}' must be a {expected_type.__name__}, not {kwarg!r}")
return kwarg return kwarg
else: else:
return jinja2.Undefined(name=var) return jinja2.Undefined(name=var)
@ -394,7 +394,7 @@ class TemplatedPlatform(Platform):
commands.append(template.format(env_var=env_var, name=name)) commands.append(template.format(env_var=env_var, name=name))
for index, command_tpl in enumerate(self.command_templates): for index, command_tpl in enumerate(self.command_templates):
command = render(command_tpl, origin="<command#{}>".format(index + 1), command = render(command_tpl, origin=f"<command#{index + 1}>",
syntax=syntax) syntax=syntax)
command = re.sub(r"\s+", " ", command) command = re.sub(r"\s+", " ", command)
if syntax == "sh": if syntax == "sh":
@ -410,9 +410,9 @@ class TemplatedPlatform(Platform):
def invoke_tool(context, name): def invoke_tool(context, name):
env_var = tool_env_var(name) env_var = tool_env_var(name)
if context.parent["syntax"] == "sh": if context.parent["syntax"] == "sh":
return "\"${}\"".format(env_var) return f"\"${env_var}\""
elif context.parent["syntax"] == "bat": elif context.parent["syntax"] == "bat":
return "%{}%".format(env_var) return f"%{env_var}%"
else: else:
assert False assert False
@ -430,7 +430,7 @@ class TemplatedPlatform(Platform):
if match.group(1) is None: if match.group(1) is None:
return match.group(2) return match.group(2)
else: else:
return "_{:02x}_".format(ord(match.group(1)[0])) return f"_{ord(match.group(1)[0]):02x}_"
return "".join(escape_one(m) for m in re.finditer(r"([^A-Za-z0-9_])|(.)", string)) return "".join(escape_one(m) for m in re.finditer(r"([^A-Za-z0-9_])|(.)", string))
def tcl_escape(string): def tcl_escape(string):
@ -462,7 +462,7 @@ class TemplatedPlatform(Platform):
compiled.environment.filters["tcl_escape"] = tcl_escape compiled.environment.filters["tcl_escape"] = tcl_escape
compiled.environment.filters["tcl_quote"] = tcl_quote compiled.environment.filters["tcl_quote"] = tcl_quote
except jinja2.TemplateSyntaxError as e: except jinja2.TemplateSyntaxError as e:
e.args = ("{} (at {}:{})".format(e.message, origin, e.lineno),) e.args = (f"{e.message} (at {origin}:{e.lineno})",)
raise raise
return compiled.render({ return compiled.render({
"name": name, "name": name,
@ -480,7 +480,7 @@ class TemplatedPlatform(Platform):
"autogenerated": autogenerated, "autogenerated": autogenerated,
}) })
plan = BuildPlan(script="build_{}".format(name)) plan = BuildPlan(script=f"build_{name}")
for filename_tpl, content_tpl in self.file_templates.items(): for filename_tpl, content_tpl in self.file_templates.items():
plan.add_file(render(filename_tpl, origin=filename_tpl), plan.add_file(render(filename_tpl, origin=filename_tpl),
render(content_tpl, origin=content_tpl)) render(content_tpl, origin=content_tpl))

View file

@ -37,7 +37,7 @@ class ResourceManager:
def add_resources(self, resources): def add_resources(self, resources):
for res in resources: for res in resources:
if not isinstance(res, Resource): if not isinstance(res, Resource):
raise TypeError("Object {!r} is not a Resource".format(res)) raise TypeError(f"Object {res!r} is not a Resource")
if (res.name, res.number) in self.resources: if (res.name, res.number) in self.resources:
raise NameError("Trying to add {!r}, but {!r} has the same name and number" raise NameError("Trying to add {!r}, but {!r} has the same name and number"
.format(res, self.resources[res.name, res.number])) .format(res, self.resources[res.name, res.number]))
@ -46,7 +46,7 @@ class ResourceManager:
def add_connectors(self, connectors): def add_connectors(self, connectors):
for conn in connectors: for conn in connectors:
if not isinstance(conn, Connector): if not isinstance(conn, Connector):
raise TypeError("Object {!r} is not a Connector".format(conn)) raise TypeError(f"Object {conn!r} is not a Connector")
if (conn.name, conn.number) in self.connectors: if (conn.name, conn.number) in self.connectors:
raise NameError("Trying to add {!r}, but {!r} has the same name and number" raise NameError("Trying to add {!r}, but {!r} has the same name and number"
.format(conn, self.connectors[conn.name, conn.number])) .format(conn, self.connectors[conn.name, conn.number]))
@ -120,7 +120,7 @@ class ResourceManager:
fields = OrderedDict() fields = OrderedDict()
for sub in resource.ios: for sub in resource.ios:
fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name], fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name],
name="{}__{}".format(name, sub.name), name=f"{name}__{sub.name}",
attrs={**attrs, **sub.attrs}) attrs={**attrs, **sub.attrs})
rec = Record([ rec = Record([
(f_name, f.layout) for (f_name, f) in fields.items() (f_name, f.layout) for (f_name, f) in fields.items()
@ -178,7 +178,7 @@ class ResourceManager:
value = resolve(resource, value = resolve(resource,
*merge_options(resource, dir, xdr), *merge_options(resource, dir, xdr),
name="{}_{}".format(resource.name, resource.number), name=f"{resource.name}_{resource.number}",
attrs=resource.attrs) attrs=resource.attrs)
self._requested[resource.name, resource.number] = value self._requested[resource.name, resource.number] = value
return value return value
@ -232,13 +232,13 @@ class ResourceManager:
yield port_name, pin_names[0], attrs yield port_name, pin_names[0], attrs
else: else:
for bit, pin_name in enumerate(pin_names): for bit, pin_name in enumerate(pin_names):
yield "{}[{}]".format(port_name, bit), pin_name, attrs yield f"{port_name}[{bit}]", pin_name, attrs
def add_clock_constraint(self, clock, frequency): def add_clock_constraint(self, clock, frequency):
if not isinstance(clock, Signal): if not isinstance(clock, Signal):
raise TypeError("Object {!r} is not a Signal".format(clock)) raise TypeError(f"Object {clock!r} is not a Signal")
if not isinstance(frequency, (int, float)): if not isinstance(frequency, (int, float)):
raise TypeError("Frequency must be a number, not {!r}".format(frequency)) raise TypeError(f"Frequency must be a number, not {frequency!r}")
if clock in self._clocks: if clock in self._clocks:
raise ValueError("Cannot add clock constraint on {!r}, which is already constrained " raise ValueError("Cannot add clock constraint on {!r}, which is already constrained "

View file

@ -98,10 +98,10 @@ class BuildPlan:
# Without "call", "cmd /c {}.bat" will return 0. # Without "call", "cmd /c {}.bat" will return 0.
# See https://stackoverflow.com/a/30736987 for a detailed explanation of why. # See https://stackoverflow.com/a/30736987 for a detailed explanation of why.
# Running the script manually from a command prompt is unaffected. # Running the script manually from a command prompt is unaffected.
subprocess.check_call(["cmd", "/c", "call {}.bat".format(self.script)], subprocess.check_call(["cmd", "/c", f"call {self.script}.bat"],
env=os.environ if env is None else env) env=os.environ if env is None else env)
else: else:
subprocess.check_call(["sh", "{}.sh".format(self.script)], subprocess.check_call(["sh", f"{self.script}.sh"],
env=os.environ if env is None else env) env=os.environ if env is None else env)
return LocalBuildProducts(os.getcwd()) return LocalBuildProducts(os.getcwd())
@ -135,7 +135,7 @@ class BuildPlan:
def mkdir_exist_ok(path): def mkdir_exist_ok(path):
try: try:
sftp.mkdir(str(path)) sftp.mkdir(str(path))
except IOError as e: except OSError as e:
# mkdir fails if directory exists. This is fine in amaranth.build. # mkdir fails if directory exists. This is fine in amaranth.build.
# Reraise errors containing e.errno info. # Reraise errors containing e.errno info.
if e.errno: if e.errno:

View file

@ -103,7 +103,7 @@ class CompatMemory(NativeMemory, Elaboratable):
assert mode != NO_CHANGE assert mode != NO_CHANGE
rdport = self.read_port(domain="comb" if async_read else clock_domain, rdport = self.read_port(domain="comb" if async_read else clock_domain,
transparent=mode == WRITE_FIRST) transparent=mode == WRITE_FIRST)
rdport.addr.name = "{}_addr".format(self.name) rdport.addr.name = f"{self.name}_addr"
adr = rdport.addr adr = rdport.addr
dat_r = rdport.data dat_r = rdport.data
if write_capable: if write_capable:

View file

@ -16,11 +16,11 @@ class MultiReg(NativeFFSynchronizer):
old_opts = [] old_opts = []
new_opts = [] new_opts = []
if odomain != "sync": if odomain != "sync":
old_opts.append(", odomain={!r}".format(odomain)) old_opts.append(f", odomain={odomain!r}")
new_opts.append(", o_domain={!r}".format(odomain)) new_opts.append(f", o_domain={odomain!r}")
if n != 2: if n != 2:
old_opts.append(", n={!r}".format(n)) old_opts.append(f", n={n!r}")
new_opts.append(", stages={!r}".format(n)) new_opts.append(f", stages={n!r}")
warnings.warn("instead of `MultiReg(...{})`, use `FFSynchronizer(...{})`" warnings.warn("instead of `MultiReg(...{})`, use `FFSynchronizer(...{})`"
.format("".join(old_opts), "".join(new_opts)), .format("".join(old_opts), "".join(new_opts)),
DeprecationWarning, stacklevel=2) DeprecationWarning, stacklevel=2)

View file

@ -81,9 +81,9 @@ class _LowerNext(ValueTransformer, StatementTransformer):
except KeyError: except KeyError:
related = node.target if isinstance(node.target, Signal) else None related = node.target if isinstance(node.target, Signal) else None
next_value = Signal(node.target.shape(), next_value = Signal(node.target.shape(),
name=None if related is None else "{}_fsm_next".format(related.name)) name=None if related is None else f"{related.name}_fsm_next")
next_value_ce = Signal( next_value_ce = Signal(
name=None if related is None else "{}_fsm_next_ce".format(related.name)) name=None if related is None else f"{related.name}_fsm_next_ce")
self.registers.append((node.target, next_value_ce, next_value)) self.registers.append((node.target, next_value_ce, next_value))
return next_value.eq(node.value), next_value_ce.eq(1) return next_value.eq(node.value), next_value_ce.eq(1)
else: else:
@ -161,10 +161,10 @@ class FSM(CompatModule):
@_ignore_deprecated @_ignore_deprecated
def do_finalize(self): def do_finalize(self):
nstates = len(self.actions) nstates = len(self.actions)
self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys())) self.encoding = {s: n for n, s in enumerate(self.actions.keys())}
self.decoding = {n: s for s, n in self.encoding.items()} self.decoding = {n: s for s, n in self.encoding.items()}
decoder = lambda n: "{}/{}".format(self.decoding[n], n) decoder = lambda n: f"{self.decoding[n]}/{n}"
self.state = Signal(range(nstates), reset=self.encoding[self.reset_state], decoder=decoder) self.state = Signal(range(nstates), reset=self.encoding[self.reset_state], decoder=decoder)
self.next_state = Signal.like(self.state) self.next_state = Signal.like(self.state)
@ -183,7 +183,7 @@ class FSM(CompatModule):
return _LowerNext(self.next_state, self.encoding, self.state_aliases) return _LowerNext(self.next_state, self.encoding, self.state_aliases)
def _finalize_sync(self, ls): def _finalize_sync(self, ls):
cases = dict((self.encoding[k], ls.on_statement(v)) for k, v in self.actions.items() if v) cases = {self.encoding[k]: ls.on_statement(v) for k, v in self.actions.items() if v}
self.comb += [ self.comb += [
self.next_state.eq(self.state), self.next_state.eq(self.state),
Case(self.state, cases).makedefault(self.encoding[self.reset_state]) Case(self.state, cases).makedefault(self.encoding[self.reset_state])

View file

@ -136,7 +136,7 @@ class Record:
def connect(self, *slaves, keep=None, omit=None): def connect(self, *slaves, keep=None, omit=None):
if keep is None: if keep is None:
_keep = set([f[0] for f in self.layout]) _keep = {f[0] for f in self.layout}
elif isinstance(keep, list): elif isinstance(keep, list):
_keep = set(keep) _keep = set(keep)
else: else:

View file

@ -82,9 +82,9 @@ class Layout:
field_reprs = [] field_reprs = []
for name, shape, dir in self: for name, shape, dir in self:
if dir == DIR_NONE: if dir == DIR_NONE:
field_reprs.append("({!r}, {!r})".format(name, shape)) field_reprs.append(f"({name!r}, {shape!r})")
else: else:
field_reprs.append("({!r}, {!r}, Direction.{})".format(name, shape, dir.name)) field_reprs.append(f"({name!r}, {shape!r}, Direction.{dir.name})")
return "Layout([{}])".format(", ".join(field_reprs)) return "Layout([{}])".format(", ".join(field_reprs))
@ -101,7 +101,7 @@ class Record(ValueCastable):
def concat(a, b): def concat(a, b):
if a is None: if a is None:
return b return b
return "{}__{}".format(a, b) return f"{a}__{b}"
fields = {} fields = {}
for field_name in other.fields: for field_name in other.fields:
@ -125,7 +125,7 @@ class Record(ValueCastable):
def concat(a, b): def concat(a, b):
if a is None: if a is None:
return b return b
return "{}__{}".format(a, b) return f"{a}__{b}"
self.layout = Layout.cast(layout, src_loc_at=1 + src_loc_at) self.layout = Layout.cast(layout, src_loc_at=1 + src_loc_at)
self.fields = OrderedDict() self.fields = OrderedDict()
@ -158,7 +158,7 @@ class Record(ValueCastable):
if self.name is None: if self.name is None:
reference = "Unnamed record" reference = "Unnamed record"
else: else:
reference = "Record '{}'".format(self.name) reference = f"Record '{self.name}'"
raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?" raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?"
.format(reference, item, ", ".join(self.fields))) from None .format(reference, item, ", ".join(self.fields))) from None
elif isinstance(item, tuple): elif isinstance(item, tuple):
@ -174,7 +174,7 @@ class Record(ValueCastable):
if self.name is None: if self.name is None:
reference = "Unnamed record" reference = "Unnamed record"
else: else:
reference = "Record '{}'".format(self.name) reference = f"Record '{self.name}'"
raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?" raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?"
.format(reference, item, ", ".join(self.fields))) from None .format(reference, item, ", ".join(self.fields))) from None
@ -211,7 +211,7 @@ class Record(ValueCastable):
if record.name is None: if record.name is None:
return "unnamed record" return "unnamed record"
else: else:
return "record '{}'".format(record.name) return f"record '{record.name}'"
for field in include or {}: for field in include or {}:
if field not in self.fields: if field not in self.fields:

View file

@ -130,16 +130,16 @@ class Shape:
# defined as subclasses of lib.enum.Enum with no explicitly specified shape. # defined as subclasses of lib.enum.Enum with no explicitly specified shape.
return Shape._cast_plain_enum(obj) return Shape._cast_plain_enum(obj)
else: else:
raise TypeError("Object {!r} cannot be converted to an Amaranth shape".format(obj)) raise TypeError(f"Object {obj!r} cannot be converted to an Amaranth shape")
if new_obj is obj: if new_obj is obj:
raise RecursionError("Shape-castable object {!r} casts to itself".format(obj)) raise RecursionError(f"Shape-castable object {obj!r} casts to itself")
obj = new_obj obj = new_obj
def __repr__(self): def __repr__(self):
if self.signed: if self.signed:
return "signed({})".format(self.width) return f"signed({self.width})"
else: else:
return "unsigned({})".format(self.width) return f"unsigned({self.width})"
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, Shape) and return (isinstance(other, Shape) and
@ -194,9 +194,9 @@ class Value(metaclass=ABCMeta):
elif isinstance(obj, int): elif isinstance(obj, int):
return Const(obj) return Const(obj)
else: else:
raise TypeError("Object {!r} cannot be converted to an Amaranth value".format(obj)) raise TypeError(f"Object {obj!r} cannot be converted to an Amaranth value")
if new_obj is obj: if new_obj is obj:
raise RecursionError("Value-castable object {!r} casts to itself".format(obj)) raise RecursionError(f"Value-castable object {obj!r} casts to itself")
obj = new_obj obj = new_obj
def __init__(self, *, src_loc_at=0): def __init__(self, *, src_loc_at=0):
@ -323,7 +323,7 @@ class Value(metaclass=ABCMeta):
return Cat(self[i] for i in range(start, stop, step)) return Cat(self[i] for i in range(start, stop, step))
return Slice(self, start, stop, src_loc_at=1) return Slice(self, start, stop, src_loc_at=1)
else: else:
raise TypeError("Cannot index value with {}".format(repr(key))) raise TypeError(f"Cannot index value with {key!r}")
def as_unsigned(self): def as_unsigned(self):
"""Conversion to unsigned. """Conversion to unsigned.
@ -510,7 +510,7 @@ class Value(metaclass=ABCMeta):
If the amount is positive, the input shifted left. Otherwise, the input shifted right. If the amount is positive, the input shifted left. Otherwise, the input shifted right.
""" """
if not isinstance(amount, int): if not isinstance(amount, int):
raise TypeError("Shift amount must be an integer, not {!r}".format(amount)) raise TypeError(f"Shift amount must be an integer, not {amount!r}")
if amount < 0: if amount < 0:
return self.shift_right(-amount) return self.shift_right(-amount)
if self.shape().signed: if self.shape().signed:
@ -532,7 +532,7 @@ class Value(metaclass=ABCMeta):
If the amount is positive, the input shifted right. Otherwise, the input shifted left. If the amount is positive, the input shifted right. Otherwise, the input shifted left.
""" """
if not isinstance(amount, int): if not isinstance(amount, int):
raise TypeError("Shift amount must be an integer, not {!r}".format(amount)) raise TypeError(f"Shift amount must be an integer, not {amount!r}")
if amount < 0: if amount < 0:
return self.shift_left(-amount) return self.shift_left(-amount)
if self.shape().signed: if self.shape().signed:
@ -554,7 +554,7 @@ class Value(metaclass=ABCMeta):
If the amount is positive, the input rotated left. Otherwise, the input rotated right. If the amount is positive, the input rotated left. Otherwise, the input rotated right.
""" """
if not isinstance(amount, int): if not isinstance(amount, int):
raise TypeError("Rotate amount must be an integer, not {!r}".format(amount)) raise TypeError(f"Rotate amount must be an integer, not {amount!r}")
if len(self) != 0: if len(self) != 0:
amount %= len(self) amount %= len(self)
return Cat(self[-amount:], self[:-amount]) # meow :3 return Cat(self[-amount:], self[:-amount]) # meow :3
@ -573,7 +573,7 @@ class Value(metaclass=ABCMeta):
If the amount is positive, the input rotated right. Otherwise, the input rotated right. If the amount is positive, the input rotated right. Otherwise, the input rotated right.
""" """
if not isinstance(amount, int): if not isinstance(amount, int):
raise TypeError("Rotate amount must be an integer, not {!r}".format(amount)) raise TypeError(f"Rotate amount must be an integer, not {amount!r}")
if len(self) != 0: if len(self) != 0:
amount %= len(self) amount %= len(self)
return Cat(self[amount:], self[:amount]) return Cat(self[amount:], self[:amount])
@ -635,7 +635,7 @@ class Value(metaclass=ABCMeta):
pass # :nocov: pass # :nocov:
def _lhs_signals(self): def _lhs_signals(self):
raise TypeError("Value {!r} cannot be used in assignments".format(self)) raise TypeError(f"Value {self!r} cannot be used in assignments")
@abstractmethod @abstractmethod
def _rhs_signals(self): def _rhs_signals(self):
@ -691,7 +691,7 @@ class Const(Value):
width += len(const) width += len(const)
return Const(value, width) return Const(value, width)
else: else:
raise TypeError("Value {!r} cannot be converted to an Amaranth constant".format(obj)) raise TypeError(f"Value {obj!r} cannot be converted to an Amaranth constant")
def __init__(self, value, shape=None, *, src_loc_at=0): def __init__(self, value, shape=None, *, src_loc_at=0):
# We deliberately do not call Value.__init__ here. # We deliberately do not call Value.__init__ here.
@ -856,22 +856,22 @@ def Mux(sel, val1, val0):
class Slice(Value): class Slice(Value):
def __init__(self, value, start, stop, *, src_loc_at=0): def __init__(self, value, start, stop, *, src_loc_at=0):
if not isinstance(start, int): if not isinstance(start, int):
raise TypeError("Slice start must be an integer, not {!r}".format(start)) raise TypeError(f"Slice start must be an integer, not {start!r}")
if not isinstance(stop, int): if not isinstance(stop, int):
raise TypeError("Slice stop must be an integer, not {!r}".format(stop)) raise TypeError(f"Slice stop must be an integer, not {stop!r}")
value = Value.cast(value) value = Value.cast(value)
n = len(value) n = len(value)
if start not in range(-n, n+1): if start not in range(-n, n+1):
raise IndexError("Cannot start slice {} bits into {}-bit value".format(start, n)) raise IndexError(f"Cannot start slice {start} bits into {n}-bit value")
if start < 0: if start < 0:
start += n start += n
if stop not in range(-n, n+1): if stop not in range(-n, n+1):
raise IndexError("Cannot stop slice {} bits into {}-bit value".format(stop, n)) raise IndexError(f"Cannot stop slice {stop} bits into {n}-bit value")
if stop < 0: if stop < 0:
stop += n stop += n
if start > stop: if start > stop:
raise IndexError("Slice start {} must be less than slice stop {}".format(start, stop)) raise IndexError(f"Slice start {start} must be less than slice stop {stop}")
super().__init__(src_loc_at=src_loc_at) super().__init__(src_loc_at=src_loc_at)
self.value = value self.value = value
@ -888,16 +888,16 @@ class Slice(Value):
return self.value._rhs_signals() return self.value._rhs_signals()
def __repr__(self): def __repr__(self):
return "(slice {} {}:{})".format(repr(self.value), self.start, self.stop) return f"(slice {self.value!r} {self.start}:{self.stop})"
@final @final
class Part(Value): class Part(Value):
def __init__(self, value, offset, width, stride=1, *, src_loc_at=0): def __init__(self, value, offset, width, stride=1, *, src_loc_at=0):
if not isinstance(width, int) or width < 0: if not isinstance(width, int) or width < 0:
raise TypeError("Part width must be a non-negative integer, not {!r}".format(width)) raise TypeError(f"Part width must be a non-negative integer, not {width!r}")
if not isinstance(stride, int) or stride <= 0: if not isinstance(stride, int) or stride <= 0:
raise TypeError("Part stride must be a positive integer, not {!r}".format(stride)) raise TypeError(f"Part stride must be a positive integer, not {stride!r}")
value = Value.cast(value) value = Value.cast(value)
offset = Value.cast(offset) offset = Value.cast(offset)
@ -1067,7 +1067,7 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
super().__init__(src_loc_at=src_loc_at) super().__init__(src_loc_at=src_loc_at)
if name is not None and not isinstance(name, str): if name is not None and not isinstance(name, str):
raise TypeError("Name must be a string, not {!r}".format(name)) raise TypeError(f"Name must be a string, not {name!r}")
self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal") self.name = name or tracer.get_var_name(depth=2 + src_loc_at, default="$signal")
orig_shape = shape orig_shape = shape
@ -1178,7 +1178,7 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
return SignalSet((self,)) return SignalSet((self,))
def __repr__(self): def __repr__(self):
return "(sig {})".format(self.name) return f"(sig {self.name})"
@final @final
@ -1197,9 +1197,9 @@ class ClockSignal(Value):
def __init__(self, domain="sync", *, src_loc_at=0): def __init__(self, domain="sync", *, src_loc_at=0):
super().__init__(src_loc_at=src_loc_at) super().__init__(src_loc_at=src_loc_at)
if not isinstance(domain, str): if not isinstance(domain, str):
raise TypeError("Clock domain name must be a string, not {!r}".format(domain)) raise TypeError(f"Clock domain name must be a string, not {domain!r}")
if domain == "comb": if domain == "comb":
raise ValueError("Domain '{}' does not have a clock".format(domain)) raise ValueError(f"Domain '{domain}' does not have a clock")
self.domain = domain self.domain = domain
def shape(self): def shape(self):
@ -1212,7 +1212,7 @@ class ClockSignal(Value):
raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov: raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
def __repr__(self): def __repr__(self):
return "(clk {})".format(self.domain) return f"(clk {self.domain})"
@final @final
@ -1233,9 +1233,9 @@ class ResetSignal(Value):
def __init__(self, domain="sync", allow_reset_less=False, *, src_loc_at=0): def __init__(self, domain="sync", allow_reset_less=False, *, src_loc_at=0):
super().__init__(src_loc_at=src_loc_at) super().__init__(src_loc_at=src_loc_at)
if not isinstance(domain, str): if not isinstance(domain, str):
raise TypeError("Clock domain name must be a string, not {!r}".format(domain)) raise TypeError(f"Clock domain name must be a string, not {domain!r}")
if domain == "comb": if domain == "comb":
raise ValueError("Domain '{}' does not have a reset".format(domain)) raise ValueError(f"Domain '{domain}' does not have a reset")
self.domain = domain self.domain = domain
self.allow_reset_less = allow_reset_less self.allow_reset_less = allow_reset_less
@ -1249,7 +1249,7 @@ class ResetSignal(Value):
raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov: raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
def __repr__(self): def __repr__(self):
return "(rst {})".format(self.domain) return f"(rst {self.domain})"
class Array(MutableSequence): class Array(MutableSequence):
@ -1543,7 +1543,7 @@ class Statement:
if isinstance(obj, Statement): if isinstance(obj, Statement):
return _StatementList([obj]) return _StatementList([obj])
else: else:
raise TypeError("Object {!r} is not an Amaranth statement".format(obj)) raise TypeError(f"Object {obj!r} is not an Amaranth statement")
@final @final
@ -1560,7 +1560,7 @@ class Assign(Statement):
return self.lhs._rhs_signals() | self.rhs._rhs_signals() return self.lhs._rhs_signals() | self.rhs._rhs_signals()
def __repr__(self): def __repr__(self):
return "(eq {!r} {!r})".format(self.lhs, self.rhs) return f"(eq {self.lhs!r} {self.rhs!r})"
class UnusedProperty(UnusedMustUse): class UnusedProperty(UnusedMustUse):
@ -1580,10 +1580,10 @@ class Property(Statement, MustUse):
raise TypeError("Property name must be a string or None, not {!r}" raise TypeError("Property name must be a string or None, not {!r}"
.format(self.name)) .format(self.name))
if self._check is None: if self._check is None:
self._check = Signal(reset_less=True, name="${}$check".format(self._kind)) self._check = Signal(reset_less=True, name=f"${self._kind}$check")
self._check.src_loc = self.src_loc self._check.src_loc = self.src_loc
if _en is None: if _en is None:
self._en = Signal(reset_less=True, name="${}$en".format(self._kind)) self._en = Signal(reset_less=True, name=f"${self._kind}$en")
self._en.src_loc = self.src_loc self._en.src_loc = self.src_loc
def _lhs_signals(self): def _lhs_signals(self):
@ -1594,8 +1594,8 @@ class Property(Statement, MustUse):
def __repr__(self): def __repr__(self):
if self.name is not None: if self.name is not None:
return "({}: {} {!r})".format(self.name, self._kind, self.test) return f"({self.name}: {self._kind} {self.test!r})"
return "({} {!r})".format(self._kind, self.test) return f"({self._kind} {self.test!r})"
@final @final
@ -1670,9 +1670,9 @@ class Switch(Statement):
def case_repr(keys, stmts): def case_repr(keys, stmts):
stmts_repr = " ".join(map(repr, stmts)) stmts_repr = " ".join(map(repr, stmts))
if keys == (): if keys == ():
return "(default {})".format(stmts_repr) return f"(default {stmts_repr})"
elif len(keys) == 1: elif len(keys) == 1:
return "(case {} {})".format(keys[0], stmts_repr) return f"(case {keys[0]} {stmts_repr})"
else: else:
return "(case ({}) {})".format(" ".join(keys), stmts_repr) return "(case ({}) {})".format(" ".join(keys), stmts_repr)
case_reprs = [case_repr(keys, stmts) for keys, stmts in self.cases.items()] case_reprs = [case_repr(keys, stmts) for keys, stmts in self.cases.items()]
@ -1730,7 +1730,7 @@ class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
return len(self._storage) return len(self._storage)
def __repr__(self): def __repr__(self):
pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()] pairs = [f"({k!r}, {v!r})" for k, v in self.items()]
return "{}.{}([{}])".format(type(self).__module__, type(self).__name__, return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
", ".join(pairs)) ", ".join(pairs))
@ -1864,7 +1864,7 @@ class ValueKey:
raise TypeError("Object {!r} cannot be used as a key in value collections") raise TypeError("Object {!r} cannot be used as a key in value collections")
def __repr__(self): def __repr__(self):
return "<{}.ValueKey {!r}>".format(__name__, self.value) return f"<{__name__}.ValueKey {self.value!r}>"
class ValueDict(_MappedKeyDict): class ValueDict(_MappedKeyDict):
@ -1887,7 +1887,7 @@ class SignalKey:
elif type(signal) is ResetSignal: elif type(signal) is ResetSignal:
self._intern = (2, signal.domain) self._intern = (2, signal.domain)
else: else:
raise TypeError("Object {!r} is not an Amaranth signal".format(signal)) raise TypeError(f"Object {signal!r} is not an Amaranth signal")
def __hash__(self): def __hash__(self):
return hash(self._intern) return hash(self._intern)
@ -1899,11 +1899,11 @@ class SignalKey:
def __lt__(self, other): def __lt__(self, other):
if type(other) is not SignalKey: if type(other) is not SignalKey:
raise TypeError("Object {!r} cannot be compared to a SignalKey".format(other)) raise TypeError(f"Object {other!r} cannot be compared to a SignalKey")
return self._intern < other._intern return self._intern < other._intern
def __repr__(self): def __repr__(self):
return "<{}.SignalKey {!r}>".format(__name__, self.signal) return f"<{__name__}.SignalKey {self.signal!r}>"
class SignalDict(_MappedKeyDict): class SignalDict(_MappedKeyDict):

View file

@ -45,7 +45,7 @@ class ClockDomain:
if domain_name == "sync": if domain_name == "sync":
return signal_name return signal_name
else: else:
return "{}_{}".format(domain_name, signal_name) return f"{domain_name}_{signal_name}"
def __init__(self, name=None, *, clk_edge="pos", reset_less=False, async_reset=False, def __init__(self, name=None, *, clk_edge="pos", reset_less=False, async_reset=False,
local=False): local=False):
@ -57,7 +57,7 @@ class ClockDomain:
if name.startswith("cd_"): if name.startswith("cd_"):
name = name[3:] name = name[3:]
if name == "comb": if name == "comb":
raise ValueError("Domain '{}' may not be clocked".format(name)) raise ValueError(f"Domain '{name}' may not be clocked")
if clk_edge not in ("pos", "neg"): if clk_edge not in ("pos", "neg"):
raise ValueError("Domain clock edge must be one of 'pos' or 'neg', not {!r}" raise ValueError("Domain clock edge must be one of 'pos' or 'neg', not {!r}"

View file

@ -358,10 +358,10 @@ class Module(_ModuleBuilderRoot, Elaboratable):
def FSM(self, reset=None, domain="sync", name="fsm"): def FSM(self, reset=None, domain="sync", name="fsm"):
self._check_context("FSM", context=None) self._check_context("FSM", context=None)
if domain == "comb": if domain == "comb":
raise ValueError("FSM may not be driven by the '{}' domain".format(domain)) raise ValueError(f"FSM may not be driven by the '{domain}' domain")
fsm_data = self._set_ctrl("FSM", { fsm_data = self._set_ctrl("FSM", {
"name": name, "name": name,
"signal": Signal(name="{}_state".format(name), src_loc_at=2), "signal": Signal(name=f"{name}_state", src_loc_at=2),
"reset": reset, "reset": reset,
"domain": domain, "domain": domain,
"encoding": OrderedDict(), "encoding": OrderedDict(),
@ -391,7 +391,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
src_loc = tracer.get_src_loc(src_loc_at=1) src_loc = tracer.get_src_loc(src_loc_at=1)
fsm_data = self._get_ctrl("FSM") fsm_data = self._get_ctrl("FSM")
if name in fsm_data["states"]: if name in fsm_data["states"]:
raise NameError("FSM state '{}' is already defined".format(name)) raise NameError(f"FSM state '{name}' is already defined")
if name not in fsm_data["encoding"]: if name not in fsm_data["encoding"]:
fsm_data["encoding"][name] = len(fsm_data["encoding"]) fsm_data["encoding"][name] = len(fsm_data["encoding"])
try: try:
@ -468,7 +468,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
fsm_signal.reset = fsm_encoding[fsm_reset] fsm_signal.reset = fsm_encoding[fsm_reset]
# The FSM is encoded such that the state with encoding 0 is always the reset state. # The FSM is encoded such that the state with encoding 0 is always the reset state.
fsm_decoding.update((n, s) for s, n in fsm_encoding.items()) fsm_decoding.update((n, s) for s, n in fsm_encoding.items())
fsm_signal.decoder = lambda n: "{}/{}".format(fsm_decoding[n], n) fsm_signal.decoder = lambda n: f"{fsm_decoding[n]}/{n}"
self._statements.append(Switch(fsm_signal, self._statements.append(Switch(fsm_signal,
OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items()), OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items()),
src_loc=src_loc, case_src_locs={fsm_encoding[name]: fsm_state_src_locs[name] src_loc=src_loc, case_src_locs={fsm_encoding[name]: fsm_state_src_locs[name]
@ -513,18 +513,18 @@ class Module(_ModuleBuilderRoot, Elaboratable):
self._anon_submodules.append(submodule) self._anon_submodules.append(submodule)
else: else:
if name in self._named_submodules: if name in self._named_submodules:
raise NameError("Submodule named '{}' already exists".format(name)) raise NameError(f"Submodule named '{name}' already exists")
self._named_submodules[name] = submodule self._named_submodules[name] = submodule
def _get_submodule(self, name): def _get_submodule(self, name):
if name in self._named_submodules: if name in self._named_submodules:
return self._named_submodules[name] return self._named_submodules[name]
else: else:
raise AttributeError("No submodule named '{}' exists".format(name)) raise AttributeError(f"No submodule named '{name}' exists")
def _add_domain(self, cd): def _add_domain(self, cd):
if cd.name in self._domains: if cd.name in self._domains:
raise NameError("Clock domain named '{}' already exists".format(cd.name)) raise NameError(f"Clock domain named '{cd.name}' already exists")
self._domains[cd.name] = cd self._domains[cd.name] = cd
def _flush(self): def _flush(self):

View file

@ -50,9 +50,9 @@ class Fragment:
code = obj.elaborate.__code__ code = obj.elaborate.__code__
new_obj = obj.elaborate(platform) new_obj = obj.elaborate(platform)
else: else:
raise AttributeError("Object {!r} cannot be elaborated".format(obj)) raise AttributeError(f"Object {obj!r} cannot be elaborated")
if new_obj is obj: if new_obj is obj:
raise RecursionError("Object {!r} elaborates to itself".format(obj)) raise RecursionError(f"Object {obj!r} elaborates to itself")
if new_obj is None and code is not None: if new_obj is None and code is not None:
warnings.warn_explicit( warnings.warn_explicit(
message=".elaborate() returned None; missing return statement?", message=".elaborate() returned None; missing return statement?",
@ -140,12 +140,12 @@ class Fragment:
if name_or_index < len(self.subfragments): if name_or_index < len(self.subfragments):
subfragment, name = self.subfragments[name_or_index] subfragment, name = self.subfragments[name_or_index]
return subfragment return subfragment
raise NameError("No subfragment at index #{}".format(name_or_index)) raise NameError(f"No subfragment at index #{name_or_index}")
else: else:
for subfragment, name in self.subfragments: for subfragment, name in self.subfragments:
if name == name_or_index: if name == name_or_index:
return subfragment return subfragment
raise NameError("No subfragment with name '{}'".format(name_or_index)) raise NameError(f"No subfragment with name '{name_or_index}'")
def find_generated(self, *path): def find_generated(self, *path):
if len(path) > 1: if len(path) > 1:
@ -203,7 +203,7 @@ class Fragment:
flatten_subfrags = set() flatten_subfrags = set()
for i, (subfrag, name) in enumerate(self.subfragments): for i, (subfrag, name) in enumerate(self.subfragments):
if name is None: if name is None:
name = "<unnamed #{}>".format(i) name = f"<unnamed #{i}>"
subfrag_hierarchy = hierarchy + (name,) subfrag_hierarchy = hierarchy + (name,)
if subfrag.flatten: if subfrag.flatten:
@ -264,14 +264,14 @@ class Fragment:
def _propagate_domains_up(self, hierarchy=("top",)): def _propagate_domains_up(self, hierarchy=("top",)):
from .xfrm import DomainRenamer from .xfrm import DomainRenamer
domain_subfrags = defaultdict(lambda: set()) domain_subfrags = defaultdict(set)
# For each domain defined by a subfragment, determine which subfragments define it. # For each domain defined by a subfragment, determine which subfragments define it.
for i, (subfrag, name) in enumerate(self.subfragments): for i, (subfrag, name) in enumerate(self.subfragments):
# First, recurse into subfragments and let them propagate domains up as well. # First, recurse into subfragments and let them propagate domains up as well.
hier_name = name hier_name = name
if hier_name is None: if hier_name is None:
hier_name = "<unnamed #{}>".format(i) hier_name = f"<unnamed #{i}>"
subfrag._propagate_domains_up(hierarchy + (hier_name,)) subfrag._propagate_domains_up(hierarchy + (hier_name,))
# Second, classify subfragments by domains they define. # Second, classify subfragments by domains they define.
@ -288,7 +288,7 @@ class Fragment:
names = [n for f, n, i in subfrags] names = [n for f, n, i in subfrags]
if not all(names): if not all(names):
names = sorted("<unnamed #{}>".format(i) if n is None else "'{}'".format(n) names = sorted(f"<unnamed #{i}>" if n is None else f"'{n}'"
for f, n, i in subfrags) for f, n, i in subfrags)
raise DomainError("Domain '{}' is defined by subfragments {} of fragment '{}'; " raise DomainError("Domain '{}' is defined by subfragments {} of fragment '{}'; "
"it is necessary to either rename subfragment domains " "it is necessary to either rename subfragment domains "
@ -296,7 +296,7 @@ class Fragment:
.format(domain_name, ", ".join(names), ".".join(hierarchy))) .format(domain_name, ", ".join(names), ".".join(hierarchy)))
if len(names) != len(set(names)): if len(names) != len(set(names)):
names = sorted("#{}".format(i) for f, n, i in subfrags) names = sorted(f"#{i}" for f, n, i in subfrags)
raise DomainError("Domain '{}' is defined by subfragments {} of fragment '{}', " raise DomainError("Domain '{}' is defined by subfragments {} of fragment '{}', "
"some of which have identical names; it is necessary to either " "some of which have identical names; it is necessary to either "
"rename subfragment domains explicitly, or give distinct names " "rename subfragment domains explicitly, or give distinct names "
@ -304,7 +304,7 @@ class Fragment:
.format(domain_name, ", ".join(names), ".".join(hierarchy))) .format(domain_name, ", ".join(names), ".".join(hierarchy)))
for subfrag, name, i in subfrags: for subfrag, name, i in subfrags:
domain_name_map = {domain_name: "{}_{}".format(name, domain_name)} domain_name_map = {domain_name: f"{name}_{domain_name}"}
self.subfragments[i] = (DomainRenamer(domain_name_map)(subfrag), name) self.subfragments[i] = (DomainRenamer(domain_name_map)(subfrag), name)
# Finally, collect the (now unique) subfragment domains, and merge them into our domains. # Finally, collect the (now unique) subfragment domains, and merge them into our domains.
@ -337,7 +337,7 @@ class Fragment:
continue continue
value = missing_domain(domain_name) value = missing_domain(domain_name)
if value is None: if value is None:
raise DomainError("Domain '{}' is used but not defined".format(domain_name)) raise DomainError(f"Domain '{domain_name}' is used but not defined")
if type(value) is ClockDomain: if type(value) is ClockDomain:
self.add_domains(value) self.add_domains(value)
# And expose ports on the newly added clock domain, since it is added directly # And expose ports on the newly added clock domain, since it is added directly
@ -350,8 +350,8 @@ class Fragment:
raise DomainError( raise DomainError(
"Fragment returned by missing domain callback does not define " "Fragment returned by missing domain callback does not define "
"requested domain '{}' (defines {})." "requested domain '{}' (defines {})."
.format(domain_name, ", ".join("'{}'".format(n) for n in defined))) .format(domain_name, ", ".join(f"'{n}'" for n in defined)))
self.add_subfragment(new_fragment, "cd_{}".format(domain_name)) self.add_subfragment(new_fragment, f"cd_{domain_name}")
self.add_domains(new_fragment.domains.values()) self.add_domains(new_fragment.domains.values())
return new_domains return new_domains

View file

@ -250,11 +250,11 @@ class ReadPort(Elaboratable):
self.transparent = transparent self.transparent = transparent
self.addr = Signal(range(memory.depth), self.addr = Signal(range(memory.depth),
name="{}_r_addr".format(memory.name), src_loc_at=1 + src_loc_at) name=f"{memory.name}_r_addr", src_loc_at=1 + src_loc_at)
self.data = Signal(memory.width, self.data = Signal(memory.width,
name="{}_r_data".format(memory.name), src_loc_at=1 + src_loc_at) name=f"{memory.name}_r_data", src_loc_at=1 + src_loc_at)
if self.domain != "comb": if self.domain != "comb":
self.en = Signal(name="{}_r_en".format(memory.name), reset=1, self.en = Signal(name=f"{memory.name}_r_en", reset=1,
src_loc_at=1 + src_loc_at) src_loc_at=1 + src_loc_at)
else: else:
self.en = Const(1) self.en = Const(1)
@ -317,11 +317,11 @@ class WritePort(Elaboratable):
self.granularity = granularity self.granularity = granularity
self.addr = Signal(range(memory.depth), self.addr = Signal(range(memory.depth),
name="{}_w_addr".format(memory.name), src_loc_at=1 + src_loc_at) name=f"{memory.name}_w_addr", src_loc_at=1 + src_loc_at)
self.data = Signal(memory.width, self.data = Signal(memory.width,
name="{}_w_data".format(memory.name), src_loc_at=1 + src_loc_at) name=f"{memory.name}_w_data", src_loc_at=1 + src_loc_at)
self.en = Signal(memory.width // granularity, self.en = Signal(memory.width // granularity,
name="{}_w_en".format(memory.name), src_loc_at=1 + src_loc_at) name=f"{memory.name}_w_en", src_loc_at=1 + src_loc_at)
memory._write_ports.append(self) memory._write_ports.append(self)
@ -348,8 +348,8 @@ class DummyPort:
name = tracer.get_var_name(depth=2, default="dummy") name = tracer.get_var_name(depth=2, default="dummy")
self.addr = Signal(addr_width, self.addr = Signal(addr_width,
name="{}_addr".format(name), src_loc_at=1) name=f"{name}_addr", src_loc_at=1)
self.data = Signal(data_width, self.data = Signal(data_width,
name="{}_data".format(name), src_loc_at=1) name=f"{name}_data", src_loc_at=1)
self.en = Signal(data_width // granularity, self.en = Signal(data_width // granularity,
name="{}_en".format(name), src_loc_at=1) name=f"{name}_en", src_loc_at=1)

View file

@ -74,7 +74,7 @@ class ValueVisitor(metaclass=ABCMeta):
pass # :nocov: pass # :nocov:
def on_unknown_value(self, value): def on_unknown_value(self, value):
raise TypeError("Cannot transform value {!r}".format(value)) # :nocov: raise TypeError(f"Cannot transform value {value!r}") # :nocov:
def replace_value_src_loc(self, value, new_value): def replace_value_src_loc(self, value, new_value):
return True return True
@ -186,7 +186,7 @@ class StatementVisitor(metaclass=ABCMeta):
pass # :nocov: pass # :nocov:
def on_unknown_statement(self, stmt): def on_unknown_statement(self, stmt):
raise TypeError("Cannot transform statement {!r}".format(stmt)) # :nocov: raise TypeError(f"Cannot transform statement {stmt!r}") # :nocov:
def replace_statement_src_loc(self, stmt, new_stmt): def replace_statement_src_loc(self, stmt, new_stmt):
return True return True
@ -300,7 +300,7 @@ class FragmentTransformer:
value._transforms_.append(self) value._transforms_.append(self)
return value return value
else: else:
raise AttributeError("Object {!r} cannot be elaborated".format(value)) raise AttributeError(f"Object {value!r} cannot be elaborated")
class TransformedElaboratable(Elaboratable): class TransformedElaboratable(Elaboratable):
@ -425,9 +425,9 @@ class DomainRenamer(FragmentTransformer, ValueTransformer, StatementTransformer)
domain_map = {"sync": domain_map} domain_map = {"sync": domain_map}
for src, dst in domain_map.items(): for src, dst in domain_map.items():
if src == "comb": if src == "comb":
raise ValueError("Domain '{}' may not be renamed".format(src)) raise ValueError(f"Domain '{src}' may not be renamed")
if dst == "comb": if dst == "comb":
raise ValueError("Domain '{}' may not be renamed to '{}'".format(src, dst)) raise ValueError(f"Domain '{src}' may not be renamed to '{dst}'")
self.domain_map = OrderedDict(domain_map) self.domain_map = OrderedDict(domain_map)
def on_ClockSignal(self, value): def on_ClockSignal(self, value):
@ -531,9 +531,9 @@ class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
def _name_reset(self, value): def _name_reset(self, value):
if isinstance(value, Const): if isinstance(value, Const):
return "c${}".format(value.value), value.value return f"c${value.value}", value.value
elif isinstance(value, Signal): elif isinstance(value, Signal):
return "s${}".format(value.name), value.reset return f"s${value.name}", value.reset
elif isinstance(value, ClockSignal): elif isinstance(value, ClockSignal):
return "clk", 0 return "clk", 0
elif isinstance(value, ResetSignal): elif isinstance(value, ResetSignal):
@ -554,7 +554,7 @@ class SampleLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
else: else:
assert value.domain is not None assert value.domain is not None
sampled_name, sampled_reset = self._name_reset(value.value) sampled_name, sampled_reset = self._name_reset(value.value)
name = "$sample${}${}${}".format(sampled_name, value.domain, value.clocks) name = f"$sample${sampled_name}${value.domain}${value.clocks}"
sample = Signal.like(value.value, name=name, reset_less=True, reset=sampled_reset) sample = Signal.like(value.value, name=name, reset_less=True, reset=sampled_reset)
sample.attrs["amaranth.sample_reg"] = True sample.attrs["amaranth.sample_reg"] = True

View file

@ -86,7 +86,7 @@ class FFSynchronizer(Elaboratable):
.format(type(platform).__name__)) .format(type(platform).__name__))
m = Module() m = Module()
flops = [Signal(self.i.shape(), name="stage{}".format(index), flops = [Signal(self.i.shape(), name=f"stage{index}",
reset=self._reset, reset_less=self._reset_less) reset=self._reset, reset_less=self._reset_less)
for index in range(self._stages)] for index in range(self._stages)]
for i, o in zip((self.i, *flops), flops): for i, o in zip((self.i, *flops), flops):
@ -161,7 +161,7 @@ class AsyncFFSynchronizer(Elaboratable):
m = Module() m = Module()
m.domains += ClockDomain("async_ff", async_reset=True, local=True) m.domains += ClockDomain("async_ff", async_reset=True, local=True)
flops = [Signal(1, name="stage{}".format(index), reset=1) flops = [Signal(1, name=f"stage{index}", reset=1)
for index in range(self._stages)] for index in range(self._stages)]
for i, o in zip((0, *flops), flops): for i, o in zip((0, *flops), flops):
m.d.async_ff += o.eq(i) m.d.async_ff += o.eq(i)

View file

@ -233,7 +233,7 @@ class Parameters:
crc = self._initial_crc << self._data_width crc = self._initial_crc << self._data_width
for word in data: for word in data:
if not 0 <= word <= word_max: if not 0 <= word <= word_max:
raise ValueError("data word must be between 0 and {}".format(word_max - 1)) raise ValueError(f"data word must be between 0 and {word_max - 1}")
if self._reflect_input: if self._reflect_input:
word = self._reflect(word, self._data_width) word = self._reflect(word, self._data_width)

View file

@ -446,7 +446,7 @@ class ArrayLayout(Layout):
if key < 0: if key < 0:
key += self._length key += self._length
return Field(self._elem_shape, key * Shape.cast(self._elem_shape).width) return Field(self._elem_shape, key * Shape.cast(self._elem_shape).width)
raise TypeError("Cannot index array layout with {!r}".format(key)) raise TypeError(f"Cannot index array layout with {key!r}")
@property @property
def size(self): def size(self):
@ -531,7 +531,7 @@ class FlexibleLayout(Layout):
def __getitem__(self, key): def __getitem__(self, key):
if isinstance(key, (int, str)): if isinstance(key, (int, str)):
return self._fields[key] return self._fields[key]
raise TypeError("Cannot index flexible layout with {!r}".format(key)) raise TypeError(f"Cannot index flexible layout with {key!r}")
def __repr__(self): def __repr__(self):
return f"FlexibleLayout({self._size}, {self._fields!r})" return f"FlexibleLayout({self._size}, {self._fields!r})"

View file

@ -466,8 +466,8 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
r_empty.eq(consume_r_gry == produce_r_gry), r_empty.eq(consume_r_gry == produce_r_gry),
] ]
m.d[self._w_domain] += self.w_level.eq((produce_w_bin - consume_w_bin)) m.d[self._w_domain] += self.w_level.eq(produce_w_bin - consume_w_bin)
m.d.comb += self.r_level.eq((produce_r_bin - consume_r_bin)) m.d.comb += self.r_level.eq(produce_r_bin - consume_r_bin)
storage = Memory(width=self.width, depth=self.depth) storage = Memory(width=self.width, depth=self.depth)
w_port = m.submodules.w_port = storage.write_port(domain=self._w_domain) w_port = m.submodules.w_port = storage.write_port(domain=self._w_domain)

View file

@ -31,7 +31,7 @@ def _pin_signature(width, dir, xdr=0):
members["i"] = In(width) members["i"] = In(width)
else: else:
for n in range(xdr): for n in range(xdr):
members["i{}".format(n)] = In(width) members[f"i{n}"] = In(width)
if dir in ("o", "oe", "io"): if dir in ("o", "oe", "io"):
if xdr > 0: if xdr > 0:
members["o_clk"] = Out(1) members["o_clk"] = Out(1)
@ -41,7 +41,7 @@ def _pin_signature(width, dir, xdr=0):
members["o"] = Out(width) members["o"] = Out(width)
else: else:
for n in range(xdr): for n in range(xdr):
members["o{}".format(n)] = Out(width) members[f"o{n}"] = Out(width)
if dir in ("oe", "io"): if dir in ("oe", "io"):
members["oe"] = Out(1) members["oe"] = Out(1)
return Signature(members) return Signature(members)

View file

@ -20,7 +20,7 @@ def _collect_modules(names):
py_class = py_module.__dict__[py_class_name] py_class = py_module.__dict__[py_class_name]
if not issubclass(py_class, Elaboratable): if not issubclass(py_class, Elaboratable):
continue continue
modules["{}.{}".format(py_module_name, py_class_name)] = py_class modules[f"{py_module_name}.{py_class_name}"] = py_class
else: else:
py_class = py_module.__dict__[py_class_name] py_class = py_module.__dict__[py_class_name]
if not isinstance(py_class, type) or not issubclass(py_class, Elaboratable): if not isinstance(py_class, type) or not issubclass(py_class, Elaboratable):
@ -77,7 +77,7 @@ def _serve_yosys(modules):
rtlil_text = rtlil.convert(elaboratable, name=module_name, ports=ports) rtlil_text = rtlil.convert(elaboratable, name=module_name, ports=ports)
response = {"frontend": "ilang", "source": rtlil_text} response = {"frontend": "ilang", "source": rtlil_text}
except Exception as error: except Exception as error:
response = {"error": "{}: {}".format(type(error).__name__, str(error))} response = {"error": f"{type(error).__name__}: {str(error)}"}
else: else:
return {"error": "Unrecognized method {!r}".format(request["method"])} return {"error": "Unrecognized method {!r}".format(request["method"])}

View file

@ -41,7 +41,7 @@ class PyCoroProcess(BaseProcess):
frame = coroutine.gi_frame frame = coroutine.gi_frame
if inspect.iscoroutine(coroutine): if inspect.iscoroutine(coroutine):
frame = coroutine.cr_frame frame = coroutine.cr_frame
return "{}:{}".format(inspect.getfile(frame), inspect.getlineno(frame)) return f"{inspect.getfile(frame)}:{inspect.getlineno(frame)}"
def add_trigger(self, signal, trigger=None): def add_trigger(self, signal, trigger=None):
self.state.add_trigger(self, signal, trigger=trigger) self.state.add_trigger(self, signal, trigger=trigger)

View file

@ -195,7 +195,7 @@ class _RHSValueCompiler(_ValueCompiler):
if value.operator == "m": if value.operator == "m":
sel, val1, val0 = value.operands sel, val1, val0 = value.operands
return f"({sign(val1)} if {mask(sel)} else {sign(val0)})" return f"({sign(val1)} if {mask(sel)} else {sign(val0)})"
raise NotImplementedError("Operator '{}' not implemented".format(value.operator)) # :nocov: raise NotImplementedError(f"Operator '{value.operator}' not implemented") # :nocov:
def on_Slice(self, value): def on_Slice(self, value):
return f"({(1 << len(value)) - 1:#x} & ({self(value.value)} >> {value.start}))" return f"({(1 << len(value)) - 1:#x} & ({self(value.value)} >> {value.start}))"
@ -475,7 +475,7 @@ class _FragmentCompiler:
for subfragment_index, (subfragment, subfragment_name) in enumerate(fragment.subfragments): for subfragment_index, (subfragment, subfragment_name) in enumerate(fragment.subfragments):
if subfragment_name is None: if subfragment_name is None:
subfragment_name = "U${}".format(subfragment_index) subfragment_name = f"U${subfragment_index}"
processes.update(self(subfragment)) processes.update(self(subfragment))
return processes return processes

View file

@ -27,7 +27,7 @@ class Delay(Command):
if self.interval is None: if self.interval is None:
return "(delay ε)" return "(delay ε)"
else: else:
return "(delay {:.3}us)".format(self.interval * 1e6) return f"(delay {self.interval * 1e6:.3}us)"
class Tick(Command): class Tick(Command):
@ -39,7 +39,7 @@ class Tick(Command):
self.domain = domain self.domain = domain
def __repr__(self): def __repr__(self):
return "(tick {})".format(self.domain) return f"(tick {self.domain})"
class Passive(Command): class Passive(Command):

View file

@ -41,7 +41,7 @@ class _NameExtractor:
for subfragment_index, (subfragment, subfragment_name) in enumerate(fragment.subfragments): for subfragment_index, (subfragment, subfragment_name) in enumerate(fragment.subfragments):
if subfragment_name is None: if subfragment_name is None:
subfragment_name = "U${}".format(subfragment_index) subfragment_name = f"U${subfragment_index}"
self(subfragment, hierarchy=(*hierarchy, subfragment_name)) self(subfragment, hierarchy=(*hierarchy, subfragment_name))
return self.names return self.names
@ -54,9 +54,9 @@ class _VCDWriter:
def __init__(self, fragment, *, vcd_file, gtkw_file=None, traces=()): def __init__(self, fragment, *, vcd_file, gtkw_file=None, traces=()):
if isinstance(vcd_file, str): if isinstance(vcd_file, str):
vcd_file = open(vcd_file, "wt") vcd_file = open(vcd_file, "w")
if isinstance(gtkw_file, str): if isinstance(gtkw_file, str):
gtkw_file = open(gtkw_file, "wt") gtkw_file = open(gtkw_file, "w")
self.vcd_vars = SignalDict() self.vcd_vars = SignalDict()
self.vcd_file = vcd_file self.vcd_file = vcd_file
@ -101,7 +101,7 @@ class _VCDWriter:
if suffix is None: if suffix is None:
var_name_suffix = var_name var_name_suffix = var_name
else: else:
var_name_suffix = "{}${}".format(var_name, suffix) var_name_suffix = f"{var_name}${suffix}"
if signal not in self.vcd_vars: if signal not in self.vcd_vars:
vcd_var = self.vcd_writer.register_var( vcd_var = self.vcd_writer.register_var(
scope=var_scope, name=var_name_suffix, scope=var_scope, name=var_name_suffix,
@ -140,7 +140,7 @@ class _VCDWriter:
self.gtkw_save.treeopen("top") self.gtkw_save.treeopen("top")
for signal in self.traces: for signal in self.traces:
if len(signal) > 1 and not signal.decoder: if len(signal) > 1 and not signal.decoder:
suffix = "[{}:0]".format(len(signal) - 1) suffix = f"[{len(signal) - 1}:0]"
else: else:
suffix = "" suffix = ""
self.gtkw_save.trace(".".join(self.gtkw_names[signal]) + suffix) self.gtkw_save.trace(".".join(self.gtkw_names[signal]) + suffix)

View file

@ -6,7 +6,7 @@ def log2_int(n, need_pow2=True):
return 0 return 0
r = (n - 1).bit_length() r = (n - 1).bit_length()
if need_pow2 and (1 << r) != n: if need_pow2 and (1 << r) != n:
raise ValueError("{} is not a power of 2".format(n)) raise ValueError(f"{n} is not a power of 2")
return r return r

View file

@ -86,7 +86,7 @@ class GowinPlatform(TemplatedPlatform):
def _chipdb_device(self): def _chipdb_device(self):
# GW1NR series does not have its own chipdb file, but works with GW1N # GW1NR series does not have its own chipdb file, but works with GW1N
if self.series == "GW1NR": if self.series == "GW1NR":
return "GW1N-{}{}".format(self.size, self.subseries_f) return f"GW1N-{self.size}{self.subseries_f}"
return self.family return self.family
_dev_osc_mapping = { _dev_osc_mapping = {
@ -473,11 +473,11 @@ class GowinPlatform(TemplatedPlatform):
i = o = t = None i = o = t = None
if "i" in pin.dir: if "i" in pin.dir:
i = Signal(pin.width, name="{}_xdr_i".format(pin.name)) i = Signal(pin.width, name=f"{pin.name}_xdr_i")
if "o" in pin.dir: if "o" in pin.dir:
o = Signal(pin.width, name="{}_xdr_o".format(pin.name)) o = Signal(pin.width, name=f"{pin.name}_xdr_o")
if pin.dir in ("oe", "io"): if pin.dir in ("oe", "io"):
t = Signal(1, name="{}_xdr_t".format(pin.name)) t = Signal(1, name=f"{pin.name}_xdr_t")
if pin.xdr == 0: if pin.xdr == 0:
if "i" in pin.dir: if "i" in pin.dir:
@ -511,7 +511,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("IBUF",
i_I=port.io[bit], i_I=port.io[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -523,7 +523,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, port.io, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, port.io, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("OBUF",
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
) )
@ -535,7 +535,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("TBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("TBUF",
i_OEN=t, i_OEN=t,
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
@ -548,7 +548,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("IOBUF",
i_OEN=t, i_OEN=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],
@ -562,7 +562,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(pin.wodth): for bit in range(pin.wodth):
m.submodules["{}_{}".format(pin.name,bit)] = Instance("TLVDS_IBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("TLVDS_IBUF",
i_I=port.p[bit], i_I=port.p[bit],
i_IB=port.n[bit], i_IB=port.n[bit],
o_O=i[bit] o_O=i[bit]
@ -575,7 +575,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name,bit)] = Instance("TLVDS_OBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("TLVDS_OBUF",
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
o_OB=port.n[bit], o_OB=port.n[bit],
@ -588,7 +588,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name,bit)] = Instance("TLVDS_TBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("TLVDS_TBUF",
i_OEN=t, i_OEN=t,
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
@ -602,7 +602,7 @@ class GowinPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name,bit)] = Instance("TLVDS_IOBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("TLVDS_IOBUF",
i_OEN=t, i_OEN=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],

View file

@ -323,8 +323,8 @@ class IntelPlatform(TemplatedPlatform):
) )
return i_sdr return i_sdr
elif pin.xdr == 2: elif pin.xdr == 2:
i_ddr = Signal(pin.width, name="{}_i_ddr".format(pin.name)) i_ddr = Signal(pin.width, name=f"{pin.name}_i_ddr")
m.submodules["{}_i_ddr".format(pin.name)] = Instance("altddio_in", m.submodules[f"{pin.name}_i_ddr"] = Instance("altddio_in",
p_width=pin.width, p_width=pin.width,
i_datain=i_ddr, i_datain=i_ddr,
i_inclock=pin.i_clk, i_inclock=pin.i_clk,
@ -347,7 +347,7 @@ class IntelPlatform(TemplatedPlatform):
if pin.xdr == 0: if pin.xdr == 0:
return get_oneg(pin.o) return get_oneg(pin.o)
elif pin.xdr == 1: elif pin.xdr == 1:
o_sdr = Signal(pin.width, name="{}_o_sdr".format(pin.name)) o_sdr = Signal(pin.width, name=f"{pin.name}_o_sdr")
m.submodules += Instance("$dff", m.submodules += Instance("$dff",
p_CLK_POLARITY=1, p_CLK_POLARITY=1,
p_WIDTH=pin.width, p_WIDTH=pin.width,
@ -357,8 +357,8 @@ class IntelPlatform(TemplatedPlatform):
) )
return o_sdr return o_sdr
elif pin.xdr == 2: elif pin.xdr == 2:
o_ddr = Signal(pin.width, name="{}_o_ddr".format(pin.name)) o_ddr = Signal(pin.width, name=f"{pin.name}_o_ddr")
m.submodules["{}_o_ddr".format(pin.name)] = Instance("altddio_out", m.submodules[f"{pin.name}_o_ddr"] = Instance("altddio_out",
p_width=pin.width, p_width=pin.width,
o_dataout=o_ddr, o_dataout=o_ddr,
i_outclock=pin.o_clk, i_outclock=pin.o_clk,
@ -374,7 +374,7 @@ class IntelPlatform(TemplatedPlatform):
if pin.xdr == 0: if pin.xdr == 0:
return pin.oe.replicate(pin.width) return pin.oe.replicate(pin.width)
elif pin.xdr in (1, 2): elif pin.xdr in (1, 2):
oe_reg = Signal(pin.width, name="{}_oe_reg".format(pin.name)) oe_reg = Signal(pin.width, name=f"{pin.name}_oe_reg")
oe_reg.attrs["useioff"] = "1" oe_reg.attrs["useioff"] = "1"
m.submodules += Instance("$dff", m.submodules += Instance("$dff",
p_CLK_POLARITY=1, p_CLK_POLARITY=1,

View file

@ -513,11 +513,11 @@ class LatticeECP5Platform(TemplatedPlatform):
i = o = t = None i = o = t = None
if "i" in pin.dir: if "i" in pin.dir:
i = Signal(pin.width, name="{}_xdr_i".format(pin.name)) i = Signal(pin.width, name=f"{pin.name}_xdr_i")
if "o" in pin.dir: if "o" in pin.dir:
o = Signal(pin.width, name="{}_xdr_o".format(pin.name)) o = Signal(pin.width, name=f"{pin.name}_xdr_o")
if pin.dir in ("oe", "io"): if pin.dir in ("oe", "io"):
t = Signal(pin.width, name="{}_xdr_t".format(pin.name)) t = Signal(pin.width, name=f"{pin.name}_xdr_t")
if pin.xdr == 0: if pin.xdr == 0:
if "i" in pin.dir: if "i" in pin.dir:
@ -565,7 +565,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB", m.submodules[f"{pin.name}_{bit}"] = Instance("IB",
i_I=port.io[bit], i_I=port.io[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -577,7 +577,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB", m.submodules[f"{pin.name}_{bit}"] = Instance("OB",
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
) )
@ -589,7 +589,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ", m.submodules[f"{pin.name}_{bit}"] = Instance("OBZ",
i_T=t[bit], i_T=t[bit],
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
@ -602,7 +602,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB", m.submodules[f"{pin.name}_{bit}"] = Instance("BB",
i_T=t[bit], i_T=t[bit],
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],
@ -616,7 +616,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB", m.submodules[f"{pin.name}_{bit}"] = Instance("IB",
i_I=port.p[bit], i_I=port.p[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -628,7 +628,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB", m.submodules[f"{pin.name}_{bit}"] = Instance("OB",
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
) )
@ -640,7 +640,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ", m.submodules[f"{pin.name}_{bit}"] = Instance("OBZ",
i_T=t[bit], i_T=t[bit],
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
@ -653,7 +653,7 @@ class LatticeECP5Platform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB", m.submodules[f"{pin.name}_{bit}"] = Instance("BB",
i_T=t[bit], i_T=t[bit],
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],

View file

@ -378,7 +378,7 @@ class LatticeICE40Platform(TemplatedPlatform):
m.submodules += Instance("SB_HFOSC", m.submodules += Instance("SB_HFOSC",
i_CLKHFEN=1, i_CLKHFEN=1,
i_CLKHFPU=1, i_CLKHFPU=1,
p_CLKHF_DIV="0b{0:02b}".format(self.hfosc_div), p_CLKHF_DIV=f"0b{self.hfosc_div:02b}",
o_CLKHF=clk_i) o_CLKHF=clk_i)
delay = int(100e-6 * self.default_clk_frequency) delay = int(100e-6 * self.default_clk_frequency)
# Internal low-speed clock: 10 KHz. # Internal low-speed clock: 10 KHz.
@ -441,7 +441,7 @@ class LatticeICE40Platform(TemplatedPlatform):
def get_ineg(y, invert): def get_ineg(y, invert):
if invert_lut: if invert_lut:
a = Signal.like(y, name_suffix="_x{}".format(1 if invert else 0)) a = Signal.like(y, name_suffix=f"_x{1 if invert else 0}")
for bit in range(len(y)): for bit in range(len(y)):
m.submodules += Instance("SB_LUT4", m.submodules += Instance("SB_LUT4",
p_LUT_INIT=Const(0b01 if invert else 0b10, 16), p_LUT_INIT=Const(0b01 if invert else 0b10, 16),
@ -460,7 +460,7 @@ class LatticeICE40Platform(TemplatedPlatform):
def get_oneg(a, invert): def get_oneg(a, invert):
if invert_lut: if invert_lut:
y = Signal.like(a, name_suffix="_x{}".format(1 if invert else 0)) y = Signal.like(a, name_suffix=f"_x{1 if invert else 0}")
for bit in range(len(a)): for bit in range(len(a)):
m.submodules += Instance("SB_LUT4", m.submodules += Instance("SB_LUT4",
p_LUT_INIT=Const(0b01 if invert else 0b10, 16), p_LUT_INIT=Const(0b01 if invert else 0b10, 16),
@ -566,9 +566,9 @@ class LatticeICE40Platform(TemplatedPlatform):
io_args.append(("i", "OUTPUT_ENABLE", pin.oe)) io_args.append(("i", "OUTPUT_ENABLE", pin.oe))
if is_global_input: if is_global_input:
m.submodules["{}_{}".format(pin.name, bit)] = Instance("SB_GB_IO", *io_args) m.submodules[f"{pin.name}_{bit}"] = Instance("SB_GB_IO", *io_args)
else: else:
m.submodules["{}_{}".format(pin.name, bit)] = Instance("SB_IO", *io_args) m.submodules[f"{pin.name}_{bit}"] = Instance("SB_IO", *io_args)
def get_input(self, pin, port, attrs, invert): def get_input(self, pin, port, attrs, invert):
self._check_feature("single-ended input", pin, attrs, self._check_feature("single-ended input", pin, attrs,

View file

@ -209,7 +209,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
if osch_freq not in self._supported_osch_freqs: if osch_freq not in self._supported_osch_freqs:
raise ValueError("Frequency {!r} is not valid for OSCH clock. Valid frequencies are {!r}" raise ValueError("Frequency {!r} is not valid for OSCH clock. Valid frequencies are {!r}"
.format(osch_freq, self._supported_osch_freqs)) .format(osch_freq, self._supported_osch_freqs))
osch_freq_param = "{:.2f}".format(float(osch_freq)) osch_freq_param = f"{float(osch_freq):.2f}"
m.submodules += [ Instance("OSCH", p_NOM_FREQ=osch_freq_param, i_STDBY=Const(0), o_OSC=clk_i, o_SEDSTDBY=Signal()) ] m.submodules += [ Instance("OSCH", p_NOM_FREQ=osch_freq_param, i_STDBY=Const(0), o_OSC=clk_i, o_SEDSTDBY=Signal()) ]
# GSR implicitly connects to every appropriate storage element. As such, the sync # GSR implicitly connects to every appropriate storage element. As such, the sync
# domain is reset-less; domains driven by other clocks would need to have dedicated # domain is reset-less; domains driven by other clocks would need to have dedicated
@ -308,11 +308,11 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
i = o = t = None i = o = t = None
if "i" in pin.dir: if "i" in pin.dir:
i = Signal(pin.width, name="{}_xdr_i".format(pin.name)) i = Signal(pin.width, name=f"{pin.name}_xdr_i")
if "o" in pin.dir: if "o" in pin.dir:
o = Signal(pin.width, name="{}_xdr_o".format(pin.name)) o = Signal(pin.width, name=f"{pin.name}_xdr_o")
if pin.dir in ("oe", "io"): if pin.dir in ("oe", "io"):
t = Signal(1, name="{}_xdr_t".format(pin.name)) t = Signal(1, name=f"{pin.name}_xdr_t")
if pin.xdr == 0: if pin.xdr == 0:
if "i" in pin.dir: if "i" in pin.dir:
@ -350,7 +350,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(len(port)): for bit in range(len(port)):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB", m.submodules[f"{pin.name}_{bit}"] = Instance("IB",
i_I=port.io[bit], i_I=port.io[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -362,7 +362,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(len(port)): for bit in range(len(port)):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB", m.submodules[f"{pin.name}_{bit}"] = Instance("OB",
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
) )
@ -374,7 +374,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(len(port)): for bit in range(len(port)):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ", m.submodules[f"{pin.name}_{bit}"] = Instance("OBZ",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
@ -387,7 +387,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(len(port)): for bit in range(len(port)):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB", m.submodules[f"{pin.name}_{bit}"] = Instance("BB",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],
@ -401,7 +401,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB", m.submodules[f"{pin.name}_{bit}"] = Instance("IB",
i_I=port.p[bit], i_I=port.p[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -413,7 +413,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB", m.submodules[f"{pin.name}_{bit}"] = Instance("OB",
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
) )
@ -425,7 +425,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ", m.submodules[f"{pin.name}_{bit}"] = Instance("OBZ",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_O=port.p[bit],
@ -438,7 +438,7 @@ class LatticeMachXO2Or3LPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB", m.submodules[f"{pin.name}_{bit}"] = Instance("BB",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],

View file

@ -125,9 +125,9 @@ class XilinxPlatform(TemplatedPlatform):
@property @property
def _part(self): def _part(self):
if self.family in {"ultrascale", "ultrascaleplus"}: if self.family in {"ultrascale", "ultrascaleplus"}:
return "{}-{}-{}".format(self.device, self.package, self.speed) return f"{self.device}-{self.package}-{self.speed}"
else: else:
return "{}{}-{}".format(self.device, self.package, self.speed) return f"{self.device}{self.package}-{self.speed}"
@property @property
def vendor_toolchain(self): def vendor_toolchain(self):
@ -365,7 +365,7 @@ class XilinxPlatform(TemplatedPlatform):
elif self._part.startswith("xc7s"): elif self._part.startswith("xc7s"):
return "spartan7" return "spartan7"
else: else:
print("Unknown bitstream device for part {}".format(self._part)) print(f"Unknown bitstream device for part {self._part}")
raise ValueError raise ValueError
# device naming according to part_db.yml of f4pga project # device naming according to part_db.yml of f4pga project
@ -378,7 +378,7 @@ class XilinxPlatform(TemplatedPlatform):
elif self._part.startswith("xc7a200"): elif self._part.startswith("xc7a200"):
return "xc7a200t_test" return "xc7a200t_test"
else: else:
print("Unknown symbiflow device for part {}".format(self._part)) print(f"Unknown symbiflow device for part {self._part}")
raise ValueError raise ValueError
@ -576,7 +576,7 @@ class XilinxPlatform(TemplatedPlatform):
elif device.startswith("xq"): elif device.startswith("xq"):
device = device[2:] device = device[2:]
else: else:
raise ValueError("Device '{}' is not recognized".format(self.device)) raise ValueError(f"Device '{self.device}' is not recognized")
# Do actual name matching. # Do actual name matching.
if device.startswith("2vp"): if device.startswith("2vp"):
self.family = "virtex2p" self.family = "virtex2p"
@ -635,16 +635,16 @@ class XilinxPlatform(TemplatedPlatform):
assert toolchain in ("Vivado", "ISE", "Symbiflow", "Xray") assert toolchain in ("Vivado", "ISE", "Symbiflow", "Xray")
if toolchain == "Vivado": if toolchain == "Vivado":
if self.family in ISE_FAMILIES: if self.family in ISE_FAMILIES:
raise ValueError("Family '{}' is not supported by the Vivado toolchain, please use ISE instead".format(self.family)) raise ValueError(f"Family '{self.family}' is not supported by the Vivado toolchain, please use ISE instead")
elif toolchain == "ISE": elif toolchain == "ISE":
if self.family not in ISE_FAMILIES and self.family != "series7": if self.family not in ISE_FAMILIES and self.family != "series7":
raise ValueError("Family '{}' is not supported by the ISE toolchain, please use Vivado instead".format(self.family)) raise ValueError(f"Family '{self.family}' is not supported by the ISE toolchain, please use Vivado instead")
elif toolchain == "Symbiflow": elif toolchain == "Symbiflow":
if self.family != "series7": if self.family != "series7":
raise ValueError("Family '{}' is not supported by the Symbiflow toolchain".format(self.family)) raise ValueError(f"Family '{self.family}' is not supported by the Symbiflow toolchain")
elif toolchain == "Xray": elif toolchain == "Xray":
if self.family != "series7": if self.family != "series7":
raise ValueError("Family '{}' is not supported by the yosys nextpnr toolchain".format(self.family)) raise ValueError(f"Family '{self.family}' is not supported by the yosys nextpnr toolchain")
self.toolchain = toolchain self.toolchain = toolchain
@ -926,11 +926,11 @@ class XilinxPlatform(TemplatedPlatform):
i = o = t = None i = o = t = None
if "i" in pin.dir: if "i" in pin.dir:
i = Signal(pin.width, name="{}_xdr_i".format(pin.name)) i = Signal(pin.width, name=f"{pin.name}_xdr_i")
if "o" in pin.dir: if "o" in pin.dir:
o = Signal(pin.width, name="{}_xdr_o".format(pin.name)) o = Signal(pin.width, name=f"{pin.name}_xdr_o")
if pin.dir in ("oe", "io"): if pin.dir in ("oe", "io"):
t = Signal(1, name="{}_xdr_t".format(pin.name)) t = Signal(1, name=f"{pin.name}_xdr_t")
if pin.xdr == 0: if pin.xdr == 0:
if "i" in pin.dir: if "i" in pin.dir:
@ -1037,7 +1037,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("IBUF",
i_I=port.io[bit], i_I=port.io[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -1050,7 +1050,7 @@ class XilinxPlatform(TemplatedPlatform):
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert)
if self.vendor_toolchain: if self.vendor_toolchain:
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("OBUF",
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
) )
@ -1067,7 +1067,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFT", m.submodules[f"{pin.name}_{bit}"] = Instance("OBUFT",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=port.io[bit] o_O=port.io[bit]
@ -1083,7 +1083,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUF", m.submodules[f"{pin.name}_{bit}"] = Instance("IOBUF",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],
@ -1100,7 +1100,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), i_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), i_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUFDS", m.submodules[f"{pin.name}_{bit}"] = Instance("IBUFDS",
i_I=port.p[bit], i_IB=port.n[bit], i_I=port.p[bit], i_IB=port.n[bit],
o_O=i[bit] o_O=i[bit]
) )
@ -1115,7 +1115,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFDS", m.submodules[f"{pin.name}_{bit}"] = Instance("OBUFDS",
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_OB=port.n[bit] o_O=port.p[bit], o_OB=port.n[bit]
) )
@ -1130,7 +1130,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFTDS", m.submodules[f"{pin.name}_{bit}"] = Instance("OBUFTDS",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=port.p[bit], o_OB=port.n[bit] o_O=port.p[bit], o_OB=port.n[bit]
@ -1146,7 +1146,7 @@ class XilinxPlatform(TemplatedPlatform):
m = Module() m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), i_invert=invert, o_invert=invert) i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD", "LVDS_25"), i_invert=invert, o_invert=invert)
for bit in range(pin.width): for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUFDS", m.submodules[f"{pin.name}_{bit}"] = Instance("IOBUFDS",
i_T=t, i_T=t,
i_I=o[bit], i_I=o[bit],
o_O=i[bit], o_O=i[bit],
@ -1168,7 +1168,7 @@ class XilinxPlatform(TemplatedPlatform):
def get_ff_sync(self, ff_sync): def get_ff_sync(self, ff_sync):
m = Module() m = Module()
flops = [Signal(ff_sync.i.shape(), name="stage{}".format(index), flops = [Signal(ff_sync.i.shape(), name=f"stage{index}",
reset=ff_sync._reset, reset_less=ff_sync._reset_less, reset=ff_sync._reset, reset_less=ff_sync._reset_less,
attrs={"ASYNC_REG": "TRUE"}) attrs={"ASYNC_REG": "TRUE"})
for index in range(ff_sync._stages)] for index in range(ff_sync._stages)]
@ -1190,7 +1190,7 @@ class XilinxPlatform(TemplatedPlatform):
def get_async_ff_sync(self, async_ff_sync): def get_async_ff_sync(self, async_ff_sync):
m = Module() m = Module()
m.domains += ClockDomain("async_ff", async_reset=True, local=True) m.domains += ClockDomain("async_ff", async_reset=True, local=True)
flops = [Signal(1, name="stage{}".format(index), reset=1, flops = [Signal(1, name=f"stage{index}", reset=1,
attrs={"ASYNC_REG": "TRUE"}) attrs={"ASYNC_REG": "TRUE"})
for index in range(async_ff_sync._stages)] for index in range(async_ff_sync._stages)]
if self.toolchain == "Vivado": if self.toolchain == "Vivado":

View file

@ -139,7 +139,7 @@ class AttrsTestCase(FHDLTestCase):
fn = lambda self: "FOO" fn = lambda self: "FOO"
a = Attrs(FOO=fn) a = Attrs(FOO=fn)
self.assertEqual(a["FOO"], fn) self.assertEqual(a["FOO"], fn)
self.assertEqual(repr(a), "(attrs FOO={!r})".format(fn)) self.assertEqual(repr(a), f"(attrs FOO={fn!r})")
def test_wrong_value(self): def test_wrong_value(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,