# Copyright 2017 The Meson development team # 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. from __future__ import annotations import itertools import typing as T from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import build from .. import mesonlib from ..interpreter.type_checking import CT_INPUT_KW from ..interpreterbase.decorators import KwargInfo, typed_kwargs, typed_pos_args if T.TYPE_CHECKING: from typing_extensions import TypedDict from . import ModuleState from ..interpreter import Interpreter from ..programs import ExternalProgram class ProjectKwargs(TypedDict): sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] constraint_file: T.Union[mesonlib.FileOrString, build.GeneratedTypes] class IceStormModule(ExtensionModule): INFO = ModuleInfo('FPGA/Icestorm', '0.45.0', unstable=True) def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = {} self.methods.update({ 'project': self.project, }) def detect_tools(self, state: ModuleState) -> None: self.tools['yosys'] = state.find_program('yosys') self.tools['arachne'] = state.find_program('arachne-pnr') self.tools['icepack'] = state.find_program('icepack') self.tools['iceprog'] = state.find_program('iceprog') self.tools['icetime'] = state.find_program('icetime') @typed_pos_args('icestorm.project', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) @typed_kwargs( 'icestorm.project', CT_INPUT_KW.evolve(name='sources'), KwargInfo( 'constraint_file', (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), required=True, ) ) def project(self, state: ModuleState, args: T.Tuple[str, T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]], kwargs: ProjectKwargs) -> ModuleReturnValue: if not self.tools: self.detect_tools(state) proj_name, arg_sources = args all_sources = self.interpreter.source_strings_to_files( list(itertools.chain(arg_sources, kwargs['sources']))) blif_target = build.CustomTarget( f'{proj_name}_blif', state.subdir, state.subproject, state.environment, [self.tools['yosys'], '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@'], all_sources, [f'{proj_name}.blif'], ) asc_target = build.CustomTarget( f'{proj_name}_asc', state.subdir, state.subproject, state.environment, [self.tools['arachne'], '-q', '-d', '1k', '-p', '@INPUT@', '-o', '@OUTPUT@'], [kwargs['constraint_file'], blif_target], [f'{proj_name}.asc'], ) bin_target = build.CustomTarget( f'{proj_name}_bin', state.subdir, state.subproject, state.environment, [self.tools['icepack'], '@INPUT@', '@OUTPUT@'], [asc_target], [f'{proj_name}.bin'], build_by_default=True, ) upload_target = build.RunTarget( f'{proj_name}-upload', [self.tools['iceprog'], bin_target], [], state.subdir, state.subproject, state.environment, ) time_target = build.RunTarget( f'{proj_name}-time', [self.tools['icetime'], bin_target], [], state.subdir, state.subproject, state.environment, ) return ModuleReturnValue( None, [blif_target, asc_target, bin_target, upload_target, time_target]) def initialize(interp: Interpreter) -> IceStormModule: return IceStormModule(interp)