make_sim.py 6.61 KB
Newer Older
1
"""Module providing the simulation functionality for writing Makefiles"""
2

3
from __future__ import absolute_import
4
import os
5
import sys
6
import string
7
import logging
8

9
from .makefile import ToolMakefile
10
from hdlmake.util import shell
11
from hdlmake.srcfile import VerilogFile, VHDLFile, SVFile
12 13 14 15 16


def _check_simulation_manifest(manifest_dict):
    """Check if the simulation keys are provided by the top manifest"""
    if not manifest_dict["sim_top"]:
17
        raise Exception("sim_top variable must be set in the top manifest.")
18
    if not manifest_dict["sim_tool"]:
19
        raise Exception("sim_tool variable must be set in the top manifest.")
20

21

22
class ToolSim(ToolMakefile):
23 24 25 26 27

    """Class that provides the Makefile writing methods and status"""

    def __init__(self):
        super(ToolSim, self).__init__()
28
        self._simulator_controls = {}
29

30
    def write_makefile(self, config, fileset, filename=None):
31
        """Execute the simulation action"""
32 33
        _check_simulation_manifest(config)
        self.makefile_setup(config, fileset, filename=filename)
34
        self.makefile_check_tool('sim_path')
35
        self.makefile_includes()
36 37 38 39 40 41 42 43 44 45
        self._makefile_sim_top()
        self._makefile_sim_options()
        self._makefile_sim_local()
        self._makefile_sim_sources()
        self._makefile_sim_compilation()
        self._makefile_sim_command()
        self._makefile_sim_clean()
        self._makefile_sim_phony()

    def _makefile_sim_top(self):
46
        """Generic method to write the simulation Makefile top section"""
47 48 49 50 51
        top_parameter = string.Template("""\
TOP_MODULE := ${top_module}
PWD := $$(shell pwd)
""")
        self.writeln(top_parameter.substitute(
52
            top_module=self.manifest_dict["sim_top"]))
53

54
    def _makefile_sim_options(self):
55 56 57
        """End stub method to write the simulation Makefile options section"""
        pass

58
    def _makefile_sim_compilation(self):
59 60
        """End stub method to write the simulation Makefile compilation
        section"""
61 62
        pass

63
    def _makefile_sim_local(self):
64
        """Generic method to write the simulation Makefile local target"""
65 66
        self.writeln("#target for performing local simulation\n"
                     "local: sim_pre_cmd simulation sim_post_cmd\n")
67

68
    def _makefile_sim_sources(self):
69
        """Generic method to write the simulation Makefile HDL sources"""
70
        fileset = self.fileset
71
        self.write("VERILOG_SRC := ")
72
        for vlog in fileset.filter(VerilogFile):
73 74
            if not vlog.is_include:
                self.writeln(vlog.rel_path() + " \\")
75
        self.writeln()
76
        self.write("VERILOG_OBJ := ")
77
        for vlog in fileset.filter(VerilogFile):
78 79
            if vlog.is_include:
                continue
80 81 82 83 84
            # make a file compilation indicator (these .dat files are made even
            # if the compilation process fails) and add an ending according
            # to file's extension (.sv and .vhd files may have the same
            # corename and this causes a mess
            self.writeln(
85
                os.path.join(
86 87
                    vlog.library,
                    vlog.purename,
88
                    "." +
89
                    vlog.purename +
90
                    "_" +
91
                    vlog.extension(
92
                    )) +
93 94
                " \\")
        self.writeln()
95 96 97 98 99 100 101 102
        self.write("VHDL_SRC := ")
        for vhdl in fileset.filter(VHDLFile):
            self.write(vhdl.rel_path() + " \\\n")
        self.writeln()
        # list vhdl objects (_primary.dat files)
        self.write("VHDL_OBJ := ")
        for vhdl in fileset.filter(VHDLFile):
            # file compilation indicator (important: add _vhd ending)
103
            self.writeln(
104 105 106 107 108 109 110 111
                os.path.join(
                    vhdl.library,
                    vhdl.purename,
                    "." +
                    vhdl.purename +
                    "_" +
                    vhdl.extension(
                    )) +
112 113
                " \\")
        self.writeln()
114

115
    def _makefile_sim_dep_files(self):
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
        """Print dummy targets to handle file dependencies"""
        fileset = self.fileset
        for file_aux in fileset:
            if any(isinstance(file_aux, file_type)
                   for file_type in self._hdl_files):
                self.write("%s: %s" % (os.path.join(
                    file_aux.library, file_aux.purename,
                    ".%s_%s" % (file_aux.purename, file_aux.extension())),
                    file_aux.rel_path()))
                # list dependencies, do not include the target file
                for dep_file in [dfile for dfile in file_aux.depends_on
                                 if dfile is not file_aux]:
                    if dep_file in fileset:
                        name = dep_file.purename
                        extension = dep_file.extension()
                        self.write(" \\\n" + os.path.join(
                            dep_file.library, name, ".%s_%s" %
                            (name, extension)))
                    else:
                        # the file is included -> we depend directly on it
                        self.write(" \\\n" + dep_file.rel_path())
                self.writeln()
138
                is_include = False
139 140 141 142
                if isinstance(file_aux, VHDLFile):
                    command_key = 'vhdl'
                elif (isinstance(file_aux, VerilogFile) or
                      isinstance(file_aux, SVFile)):
143
                    is_include = file_aux.is_include
144
                    command_key = 'vlog'
145 146
                if is_include:
                    continue
147
                self.writeln("\t\t" + self._simulator_controls[command_key])
148 149
                self.write("\t\t@" + shell.mkdir_command() + " $(dir $@)")
                self.writeln(" && " + shell.touch_command()  + " $@ \n")
150 151
                self.writeln()

152
    def _makefile_sim_command(self):
153
        """Generic method to write the simulation Makefile user commands"""
154 155
        sim_pre_cmd = self.manifest_dict.get("sim_pre_cmd", '')
        sim_post_cmd = self.manifest_dict.get("sim_post_cmd", '')
156 157 158 159 160 161 162 163 164
        sim_command = string.Template("""# USER SIM COMMANDS
sim_pre_cmd:
\t\t${sim_pre_cmd}
sim_post_cmd:
\t\t${sim_post_cmd}
""")
        self.writeln(sim_command.substitute(sim_pre_cmd=sim_pre_cmd,
                                            sim_post_cmd=sim_post_cmd))

165
    def _makefile_sim_clean(self):
166
        """Generic method to write the simulation Makefile user clean target"""
167 168
        self.makefile_clean()
        self.makefile_mrproper()
169

170
    def _makefile_sim_phony(self):
171 172 173
        """Print simulation PHONY target list to the Makefile"""
        self.writeln(
            ".PHONY: mrproper clean sim_pre_cmd sim_post_cmd simulation")