| #!/usr/bin/env python3 |
| # -*- coding: utf-8 -*- |
| # |
| # Copyright (C) 2022 F4PGA Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| """ |
| Rename (ie. change) dependencies and values of a module. This module wraps another, |
| module whoose name is specified in `params.module` and changes the names of the |
| dependencies and values it relies on. The parmeters for the wrapped module can be |
| specified through `params.params`. dict. There are three mapping for the names: |
| * `params.rename_takes` - mapping for inputs ("takes") |
| * `params.rename_produces` - mapping for outputs ("products") |
| * `params.rename_values` - mapping for values |
| Keys represent the names visible to the wrpped module and values represent the |
| names visible to the modules outside. |
| Not specifying a mapping for a given entry will leave it with its original name. |
| |
| --------------- |
| |
| Accepted module parameters: |
| * `module` (string, required) |
| * `params` (dict[string -> any], optional) |
| * `rename_takes` (dict[string -> string], optional) |
| * `rename_produces` (dict[string -> string], optional) |
| * `rename_values` (dict[string -> string], optional) |
| |
| """ |
| |
| from argparse import Namespace |
| from types import SimpleNamespace |
| |
| from f4pga.flows.common import decompose_depname, resolve_modstr, with_qualifier |
| from f4pga.flows.module import Module, ModuleContext |
| from f4pga.flows.runner import get_module |
| |
| |
| def p_switch_keys(d: "dict[str, ]", renames: "dict[str, str]") -> "dict[str, ]": |
| newd = {} |
| for k, v in d.items(): |
| r = renames.get(k) |
| if r is not None: |
| newd[r] = v |
| else: |
| newd[k] = v |
| return newd |
| |
| |
| def p_switchback_attrs(d: Namespace, renames: "dict[str, str]") -> SimpleNamespace: |
| newn = SimpleNamespace() |
| for k, v in vars(d).items(): |
| setattr(newn, k, v) |
| for k, r in renames.items(): |
| if hasattr(newn, r): |
| v = getattr(newn, r) |
| delattr(newn, r) |
| setattr(newn, k, v) |
| return newn |
| |
| |
| def p_switch_entries(l: "list[str]", renames: "dict[str, str]") -> "list[str]": |
| newl = [] |
| for e in l: |
| r = renames.get(e) |
| if r is not None: |
| _, q = decompose_depname(e) |
| newl.append(with_qualifier(r, q)) |
| else: |
| newl.append(r if r is not None else e) |
| return newl |
| |
| |
| def p_or_empty_dict(d: "dict | None"): |
| return d if d is not None else {} |
| |
| |
| class IORenameModule(Module): |
| module: Module |
| rename_takes: "dict[str, str]" |
| rename_produces: "dict[str, str]" |
| rename_values: "dict[str, str]" |
| |
| def map_io(self, ctx: ModuleContext): |
| newctx = ctx.shallow_copy() |
| newctx.takes = p_switchback_attrs(ctx.takes, self.rename_takes) |
| newctx.values = p_switchback_attrs(ctx.values, self.rename_values) |
| r = self.module.map_io(newctx) |
| return p_switch_keys(r, self.rename_produces) |
| |
| def execute(self, ctx: ModuleContext): |
| newctx = ctx.shallow_copy() |
| newctx.takes = p_switchback_attrs(ctx.takes, self.rename_takes) |
| newctx.values = p_switchback_attrs(ctx.values, self.rename_values) |
| newctx.outputs = p_switchback_attrs(ctx.produces, self.rename_produces) |
| print(newctx.takes) |
| return self.module.execute(newctx) |
| |
| def __init__(self, params): |
| mod_path = resolve_modstr(params["module"]) |
| module_class = get_module(mod_path) |
| module: Module = module_class(params.get("params")) |
| |
| self.rename_takes = p_or_empty_dict(params.get("rename_takes")) |
| self.rename_produces = p_or_empty_dict(params.get("rename_produces")) |
| self.rename_values = p_or_empty_dict(params.get("rename_values")) |
| |
| self.module = module |
| self.name = f"{module.name}-io_renamed" |
| self.no_of_phases = module.no_of_phases |
| self.takes = p_switch_entries(module.takes, self.rename_takes) |
| self.produces = p_switch_entries(module.produces, self.rename_produces) |
| self.values = p_switch_entries(module.values, self.rename_values) |
| if hasattr(module, "prod_meta"): |
| self.prod_meta = p_switch_keys(module.prod_meta, self.rename_produces) |
| |
| |
| ModuleClass = IORenameModule |