Beispiel #1
0
    def configure_main(self):
        #Pass trellis tool options to yosys and nextpnr
        self.edam['tool_options'] = \
            {'yosys' : {
                'arch' : 'ecp5',
                'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []),
                'yosys_as_subtool' : True,
                'yosys_template' : self.tool_options.get('yosys_template'),
            },
             'nextpnr' : {
                 'nextpnr_options' : self.tool_options.get('nextpnr_options', [])
             },
             }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        nextpnr = Nextpnr(yosys.edam, self.work_root)
        nextpnr.flow_config = {'arch' : 'ecp5'}
        nextpnr.configure()

        # Write Makefile
        commands = self.EdaCommands()
        commands.commands = yosys.commands

        commands.commands += nextpnr.commands

        #Image generation
        depends = self.name+'.config'
        targets = self.name+'.bit'
        command = ['ecppack', '--svf', self.name+'.svf', depends, targets]
        commands.add(command, [targets], [depends])

        commands.set_default_target(self.name+'.bit')
        commands.write(os.path.join(self.work_root, 'Makefile'))
Beispiel #2
0
    def get_doc(cls, api_ver):
        if api_ver == 0:
            yosys_help = Yosys.get_doc(api_ver)
            icestorm_help = {
                    'members' : [
                        {'name' : 'pnr',
                         'type' : 'String',
                         'desc' : 'Select Place & Route tool. Legal values are *arachne* for Arachne-PNR, *next* for nextpnr or *none* to only perform synthesis. Default is next'}],
                    'lists' : [
                        {'name' : 'arachne_pnr_options',
                         'type' : 'String',
                         'desc' : 'Additional options for Arachnhe PNR'},
                        {'name' : 'nextpnr_options',
                         'type' : 'String',
                         'desc' : 'Additional options for nextpnr'},
                        {'name' : 'yosys_synth_options',
                         'type' : 'String',
                         'desc' : 'Additional options for the synth_ice40 command'},
                        ]}

            combined_members = icestorm_help['members']
            combined_lists = icestorm_help['lists']
            yosys_members = yosys_help['members']
            yosys_lists = yosys_help['lists']

            combined_members.extend(m for m in yosys_members if m['name'] not in [i['name'] for i in combined_members])
            combined_lists.extend(l for l in yosys_lists if l['name'] not in [i['name'] for i in combined_lists])

            return {'description' : "Open source toolchain for Lattice iCE40 FPGAs. Uses yosys for synthesis and arachne-pnr or nextpnr for Place & Route",
                    'members' : combined_members,
                    'lists' : combined_lists}
Beispiel #3
0
    def configure_main(self):
        # Pass apicula tool options to yosys and nextpnr
        self.edam["tool_options"] = {
            "yosys": {
                "arch": "gowin",
                "output_format": "json",
                "yosys_synth_options": [f"-json {self.name}.json"]
                + self.tool_options.get("yosys_synth_options", []),
                "yosys_as_subtool": True,
                "yosys_template": self.tool_options.get("yosys_template"),
            },
            "nextpnr": {
                "device": self.tool_options.get("device"),
                "nextpnr_options": self.tool_options.get("nextpnr_options", []),
            },
        }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        nextpnr = Nextpnr(yosys.edam, self.work_root)
        nextpnr.flow_config = {"arch": "gowin"}
        nextpnr.configure()

        # Write Makefile
        commands = EdaCommands()
        commands.commands = yosys.commands

        commands.commands += nextpnr.commands

        # Image generation
        depends = self.name + ".pack"
        targets = self.name + ".fs"
        command = [
            "gowin_pack",
            "-d",
            self.tool_options.get("device"),
            "-o",
            targets,
            depends,
        ]
        commands.add(command, [targets], [depends])

        commands.set_default_target(targets)
        commands.write(os.path.join(self.work_root, "Makefile"))
Beispiel #4
0
    def configure_main(self):
        # Pass trellis tool options to yosys and nextpnr
        self.edam["tool_options"] = {
            "yosys": {
                "arch":
                "nexus",
                "output_format":
                "json",
                "yosys_synth_options":
                self.tool_options.get("yosys_synth_options", []),
                "yosys_as_subtool":
                True,
                "yosys_template":
                self.tool_options.get("yosys_template"),
            },
            "nextpnr": {
                "device": self.tool_options.get("device"),
                "nextpnr_options":
                self.tool_options.get("nextpnr_options", []),
            },
        }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        nextpnr = Nextpnr(yosys.edam, self.work_root)
        nextpnr.flow_config = {"arch": "nexus"}
        nextpnr.configure()

        # Write Makefile
        commands = EdaCommands()
        commands.commands = yosys.commands

        commands.commands += nextpnr.commands

        # Image generation
        depends = self.name + ".fasm"
        targets = self.name + ".bit"
        command = ["prjoxide", "pack", depends, targets]
        commands.add(command, [targets], [depends])

        commands.set_default_target(self.name + ".bit")
        commands.write(os.path.join(self.work_root, "Makefile"))
Beispiel #5
0
    def configure_main(self):
        # pass mistral tool option to yosys and nextpnr

        self.edam["tool_options"] = {
            "yosys": {
                "arch":
                "intel_alm",
                "output_format":
                "json",
                "yosys_synth_options":
                self.tool_options.get("yosys_synth_options", []),
                "yosys_as_subtool":
                True,
                "yosys_template":
                self.tool_options.get("yosys_template"),
            },
            "nextpnr": {
                "device": self.tool_options.get("device"),
                "nextpnr_options":
                self.tool_options.get("nextpnr_options", []),
            },
        }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        nextpnr = Nextpnr(yosys.edam, self.work_root)
        nextpnr.flow_config = {"arch": "mistral"}
        nextpnr.configure()

        # Write Makefile
        commands = EdaCommands()

        commands.commands = yosys.commands

        commands.commands += nextpnr.commands

        # Image generation

        commands.set_default_target(self.name + ".rbf")

        commands.write(os.path.join(self.work_root, "Makefile"))
Beispiel #6
0
    def configure_main(self):
        #Pass apicula tool options to yosys and nextpnr
        self.edam['tool_options'] = \
            {'yosys' : {
                'arch' : 'gowin',
                'yosys_synth_options' : [f"-json {self.name}.json"] + self.tool_options.get('yosys_synth_options',[]),
                'yosys_as_subtool' : True,
                'yosys_template' : self.tool_options.get('yosys_template'),
            },
             'nextpnr' : {
                 'device'          : self.tool_options.get('device'),
                 'nextpnr_options' : self.tool_options.get('nextpnr_options', [])
             },
             }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        nextpnr = Nextpnr(yosys.edam, self.work_root)
        nextpnr.flow_config = {'arch': 'gowin'}
        nextpnr.configure()

        # Write Makefile
        commands = self.EdaCommands()
        commands.commands = yosys.commands

        commands.commands += nextpnr.commands

        #Image generation
        depends = self.name + '.pack'
        targets = self.name + '.fs'
        command = [
            'gowin_pack', '-d',
            self.tool_options.get('device'), '-o', targets, depends
        ]
        commands.add(command, [targets], [depends])

        commands.set_default_target(targets)
        commands.write(os.path.join(self.work_root, 'Makefile'))
Beispiel #7
0
    def get_doc(cls, api_ver):
        if api_ver == 0:
            yosys_help = Yosys.get_doc(api_ver)
            apicula_help = {
                'members': [
                    {
                        'name':
                        'device',
                        'type':
                        'String',
                        'desc':
                        'Required device option for nextpnr-gowin and gowin_pack command (e.g. GW1N-LV1QN48C6/I5)'
                    },
                ],
                'lists': [
                    {
                        'name': 'nextpnr_options',
                        'type': 'String',
                        'desc': 'Additional options for nextpnr'
                    },
                    {
                        'name': 'yosys_synth_options',
                        'type': 'String',
                        'desc':
                        'Additional options for the synth_gowin command'
                    },
                ]
            }

            combined_members = apicula_help['members']
            combined_lists = apicula_help['lists']
            yosys_members = yosys_help['members']
            yosys_lists = yosys_help['lists']

            combined_members.extend(
                m for m in yosys_members
                if m['name'] not in [i['name'] for i in combined_members])
            combined_lists.extend(
                l for l in yosys_lists
                if l['name'] not in [i['name'] for i in combined_lists])

            return {
                'description':
                "Open source toolchain for Gowin FPGAs. Uses yosys for synthesis and nextpnr for Place & Route",
                'members': combined_members,
                'lists': combined_lists
            }
Beispiel #8
0
    def get_doc(cls, api_ver):
        if api_ver == 0:
            yosys_help = Yosys.get_doc(api_ver)
            trellis_help = {
                'lists': [
                    {
                        'name': 'nextpnr_options',
                        'type': 'String',
                        'desc': 'Additional options for nextpnr'
                    },
                    {
                        'name': 'yosys_synth_options',
                        'type': 'String',
                        'desc': 'Additional options for the synth_ecp5 command'
                    },
                ]
            }

            combined_members = []
            combined_lists = trellis_help['lists']
            yosys_members = yosys_help['members']
            yosys_lists = yosys_help['lists']

            combined_members.extend(
                m for m in yosys_members
                if m['name'] not in [i['name'] for i in combined_members])
            combined_lists.extend(
                l for l in yosys_lists
                if l['name'] not in [i['name'] for i in combined_lists])

            return {
                'description':
                "Project Trellis enables a fully open-source flow for ECP5 FPGAs using Yosys for Verilog synthesis and nextpnr for place and route",
                'members': combined_members,
                'lists': combined_lists
            }
Beispiel #9
0
    def configure_main(self):

        synth_tool = self.tool_options.get("synth", "vivado")

        if synth_tool == "yosys":

            self.edam['tool_options']['yosys'] = {
                'arch' : 'xilinx',
                'output_format' : 'edif',
                'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []),
                'yosys_as_subtool' : True,
            }

            yosys = Yosys(self.edam, self.work_root)
            yosys.configure()
            self.files = yosys.edam['files']

        src_files = []
        incdirs = []
        edif_files = []
        has_vhdl2008 = False
        has_xci = False
        unused_files = []

        for f in self.files:
            cmd = ""
            if f['file_type'].startswith('verilogSource'):
                cmd = 'read_verilog'
            elif f['file_type'].startswith('systemVerilogSource'):
                cmd = 'read_verilog -sv'
            elif f['file_type'] == 'tclSource':
                cmd = 'source'
            elif f['file_type'] == 'edif':
                cmd = 'read_edif'
                edif_files.append(f['name'])
            elif f['file_type'].startswith('vhdlSource'):
                cmd = 'read_vhdl'
                if f['file_type'] == 'vhdlSource-2008':
                    has_vhdl2008 = True
                    cmd += ' -vhdl2008'
                if f.get('logical_name'):
                    cmd += ' -library '+f['logical_name']
            elif f['file_type'] == 'xci':
                cmd = 'read_ip'
                has_xci = True
            elif f['file_type'] == 'xdc':
                cmd = 'read_xdc'
            elif f['file_type'] == 'SDC':
                cmd = 'read_xdc -unmanaged'
            elif f['file_type'] == 'mem':
                cmd = 'read_mem'

            if cmd:
                if not self._add_include_dir(f, incdirs):
                    src_files.append(cmd + ' {' + f['name'] + '}')
            else:
                unused_files.append(f)

        template_vars = {
            'name'         : self.name,
            'src_files'    : '\n'.join(src_files),
            'incdirs'      : incdirs+['.'],
            'tool_options' : self.tool_options,
            'toplevel'     : self.toplevel,
            'vlogparam'    : self.vlogparam,
            'vlogdefine'   : self.vlogdefine,
            'generic'      : self.generic,
            'netlist_flow' : bool(edif_files),
            'has_vhdl2008' : has_vhdl2008,
            'has_xci'      : has_xci,
        }

        self.render_template('vivado-project.tcl.j2',
                             self.name+'.tcl',
                             template_vars)

        jobs = self.tool_options.get('jobs', None)

        run_template_vars = {
            'jobs' : ' -jobs ' + str(jobs) if jobs is not None else ''
        }

        self.render_template('vivado-run.tcl.j2',
                             self.name+"_run.tcl",
                             run_template_vars)

        synth_template_vars = {
            'jobs' : ' -jobs ' + str(jobs) if jobs is not None else ''
        }

        self.render_template('vivado-synth.tcl.j2',
                             self.name+"_synth.tcl",
                             synth_template_vars)

        # Write Makefile
        commands = self.EdaCommands()

        vivado_command = ['vivado', '-notrace', '-mode', 'batch', '-source']

        #Create project file
        project_file = self.name+'.xpr'
        tcl_file = [self.name+'.tcl']
        commands.add(vivado_command+tcl_file, [project_file], tcl_file + edif_files)

        #Synthesis target
        if synth_tool == 'yosys':
            commands.commands += yosys.commands
            commands.add([], ['synth'], edif_files)
        else:
            depends = [f'{self.name}_synth.tcl', project_file]
            targets = [f'{self.name}.runs/synth_1/__synthesis_is_complete__']
            commands.add(vivado_command+depends, targets, depends)
            commands.add([], ['synth'], targets)

        #Bitstream generation
        run_tcl = self.name+'_run.tcl'
        depends = [run_tcl, project_file]
        bitstream = self.name+'.bit'
        commands.add(vivado_command+depends, [bitstream], depends)

        commands.add(['vivado', project_file], ['build-gui'], [project_file])

        depends = [self.name+'_pgm.tcl', bitstream]
        command = ['vivado', '-quiet', '-nolog', '-notrace', '-mode', 'batch',
                   '-source', f'{self.name}_pgm.tcl', '-tclargs']

        part = self.tool_options.get('part', "")
        command += [part] if part else []
        command += [bitstream]
        commands.add(command, ['pgm'], depends)

        commands.set_default_target(bitstream)
        commands.write(os.path.join(self.work_root, 'Makefile'))

        self.render_template('vivado-program.tcl.j2',
                             self.name+"_pgm.tcl")
Beispiel #10
0
    def configure_main(self):
        (src_files, incdirs) = self._get_fileset_files()
        synth_out = self.name + "_synth.v"

        device = self.tool_options.get("device")
        if not device:
            raise RuntimeError("Missing required option 'device' for p_r")

        match = re.search("^CCGM1A([1-9]{1,2})$", device)
        if not match:
            raise RuntimeError("{} is not known device name".format(device))

        device_number = match.groups()[0]
        if device_number not in ["1", "2", "4", "9", "16", "25"]:
            raise RuntimeError(
                "Rel. size {} is not unsupported".format(device_number))

        ccf_file = None

        for f in src_files:
            if f.file_type == "CCF":
                if ccf_file:
                    raise RuntimeError(
                        "p_r only supports one ccf file. Found {} and {}".
                        format(ccf_file, f.name))
                else:
                    ccf_file = f.name

        # Pass trellis tool options to yosys
        self.edam["tool_options"] = {
            "yosys": {
                "arch":
                "gatemate",
                "output_format":
                "verilog",
                "output_name":
                synth_out,
                "yosys_synth_options":
                self.tool_options.get("yosys_synth_options", []),
                "yosys_as_subtool":
                True,
                "yosys_template":
                self.tool_options.get("yosys_template"),
            },
        }

        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        # Write Makefile
        commands = EdaCommands()
        commands.commands = yosys.commands

        # PnR & image generation
        targets = self.name + "_00.cfg.bit"
        command = [
            "p_r",
            "-A",
            device_number,
            "-i",
            synth_out,
            "-o",
            self.name,
            "-lib",
            "ccag",
            " ".join(self.tool_options.get("p_r_options", "")),
        ]
        if ccf_file is not None:
            command += ["-ccf", ccf_file]
        commands.add(command, [targets], [synth_out])

        commands.set_default_target(targets)
        commands.write(os.path.join(self.work_root, "Makefile"))
Beispiel #11
0
    def configure_main(self):
        # Write yosys script file
        yosys_synth_options = self.tool_options.get('yosys_synth_options', '')

        #Pass icestorm tool options to yosys and nextpnr
        self.edam['tool_options'] = \
            {'yosys' : {
                'arch' : 'ice40',
                'yosys_synth_options' : yosys_synth_options,
                'yosys_as_subtool' : True,
                'yosys_template' : self.tool_options.get('yosys_template'),
            },
             'nextpnr' : {
                 'nextpnr_options' : self.tool_options.get('nextpnr_options', [])
             },
             }
        yosys = Yosys(self.edam, self.work_root)
        yosys.configure()

        pnr = self.tool_options.get('pnr', 'next')
        part = self.tool_options.get('part', None)
        if not pnr in ['arachne', 'next', 'none']:
            raise RuntimeError(
                "Invalid pnr option '{}'. Valid values are 'arachne' for Arachne-pnr, 'next' for nextpnr or 'none' to only perform synthesis"
                .format(pnr))

        # Write Makefile
        commands = self.EdaCommands()
        commands.commands = yosys.commands

        if pnr == 'arachne':
            depends = self.name + '.blif'
            targets = self.name + '.asc'
            command = ['arachne-pnr']
            command += self.tool_options.get('arachne_pnr_options', [])
            command += ['-p', depends, '-o', targets]
            commands.add(command, [depends], [targets])
            set_default_target(self.name + '.bin')
        elif pnr == 'next':
            nextpnr = Nextpnr(yosys.edam, self.work_root)
            nextpnr.flow_config = {'arch': 'ice40'}
            nextpnr.configure()
            commands.commands += nextpnr.commands
            commands.set_default_target(self.name + '.bin')
        else:
            commands.set_default_target(self.name + '.json')

        #Image generation
        depends = self.name + '.asc'
        targets = self.name + '.bin'
        command = ['icepack', depends, targets]
        commands.add(command, [targets], [depends])

        #Timing analysis
        depends = self.name + '.asc'
        targets = self.name + '.tim'
        command = ['icetime', '-tmd', part or '', depends, targets]
        commands.add(command, [targets], [depends])
        commands.add([], ["timing"], [targets])

        #Statistics
        depends = self.name + '.asc'
        targets = self.name + '.stat'
        command = ['icebox_stat', depends, targets]
        commands.add(command, [targets], [depends])
        commands.add([], ["stats"], [targets])

        commands.write(os.path.join(self.work_root, 'Makefile'))
Beispiel #12
0
    def configure_main(self):
        """
        Configuration is the first phase of the build.

        This writes the project TCL files and Makefile. It first collects all
        sources, IPs and constraints and then writes them to the TCL file along
        with the build steps.
        """
        synth_tool = self.tool_options.get("synth", "vivado")

        if synth_tool == "yosys":

            self.edam["tool_options"]["yosys"] = {
                "arch":
                "xilinx",
                "output_format":
                "edif",
                "yosys_synth_options":
                self.tool_options.get("yosys_synth_options", []),
                "yosys_as_subtool":
                True,
            }

            yosys = Yosys(self.edam, self.work_root)
            yosys.configure()
            self.files = yosys.edam["files"]

        src_files = []
        incdirs = []
        edif_files = []
        has_vhdl2008 = False
        has_xci = False
        unused_files = []

        for f in self.files:
            cmd = ""
            if f["file_type"].startswith("verilogSource"):
                cmd = "read_verilog"
            elif f["file_type"].startswith("systemVerilogSource"):
                cmd = "read_verilog -sv"
            elif f["file_type"] == "tclSource":
                cmd = "source"
            elif f["file_type"] == "edif":
                cmd = "read_edif"
                edif_files.append(f["name"])
            elif f["file_type"].startswith("vhdlSource"):
                cmd = "read_vhdl"
                if f["file_type"] == "vhdlSource-2008":
                    has_vhdl2008 = True
                    cmd += " -vhdl2008"
                if f.get("logical_name"):
                    cmd += " -library " + f["logical_name"]
            elif f["file_type"] == "xci":
                cmd = "read_ip"
                has_xci = True
            elif f["file_type"] == "xdc":
                cmd = "read_xdc"
            elif f["file_type"] == "SDC":
                cmd = "read_xdc -unmanaged"
            elif f["file_type"] == "mem":
                cmd = "read_mem"

            if cmd:
                if not self._add_include_dir(f, incdirs):
                    src_files.append(cmd + " {" + f["name"] + "}")
            else:
                unused_files.append(f)

        template_vars = {
            "name": self.name,
            "src_files": "\n".join(src_files),
            "incdirs": incdirs + ["."],
            "tool_options": self.tool_options,
            "toplevel": self.toplevel,
            "vlogparam": self.vlogparam,
            "vlogdefine": self.vlogdefine,
            "generic": self.generic,
            "netlist_flow": bool(edif_files),
            "has_vhdl2008": has_vhdl2008,
            "has_xci": has_xci,
        }

        self.render_template("vivado-project.tcl.j2", self.name + ".tcl",
                             template_vars)

        jobs = self.tool_options.get("jobs", None)

        run_template_vars = {
            "jobs": " -jobs " + str(jobs) if jobs is not None else ""
        }

        self.render_template("vivado-run.tcl.j2", self.name + "_run.tcl",
                             run_template_vars)

        synth_template_vars = {
            "jobs": " -jobs " + str(jobs) if jobs is not None else ""
        }

        self.render_template("vivado-synth.tcl.j2", self.name + "_synth.tcl",
                             synth_template_vars)

        # Write Makefile
        commands = EdaCommands()

        vivado_command = ["vivado", "-notrace", "-mode", "batch", "-source"]

        # Create project file
        project_file = self.name + ".xpr"
        tcl_file = [self.name + ".tcl"]
        commands.add(vivado_command + tcl_file, [project_file],
                     tcl_file + edif_files)

        # Synthesis target
        if synth_tool == "yosys":
            commands.commands += yosys.commands
            commands.add([], ["synth"], edif_files)
        else:
            depends = [f"{self.name}_synth.tcl", project_file]
            targets = [f"{self.name}.runs/synth_1/__synthesis_is_complete__"]
            commands.add(vivado_command + depends, targets, depends)
            commands.add([], ["synth"], targets)

        # Bitstream generation
        run_tcl = self.name + "_run.tcl"
        depends = [run_tcl, project_file]
        bitstream = self.name + ".bit"
        commands.add(vivado_command + depends, [bitstream], depends)

        commands.add(["vivado", project_file], ["build-gui"], [project_file])

        depends = [self.name + "_pgm.tcl", bitstream]
        command = [
            "vivado",
            "-quiet",
            "-nolog",
            "-notrace",
            "-mode",
            "batch",
            "-source",
            f"{self.name}_pgm.tcl",
            "-tclargs",
        ]

        part = self.tool_options.get("part", "")
        command += [part] if part else []
        command += [bitstream]
        commands.add(command, ["pgm"], depends)

        commands.set_default_target(bitstream)
        commands.write(os.path.join(self.work_root, "Makefile"))

        self.render_template("vivado-program.tcl.j2", self.name + "_pgm.tcl")