Exemple #1
0
 def run_syn_to_par_with_output(self, config_path: str, syn_rundir: str,
                                par_rundir: str, syn_out_path: str,
                                syn_to_par_out_path: str) -> None:
     # Check that running the CLIDriver executes successfully (code 0).
     with self.assertRaises(SystemExit) as cm:  # type: ignore
         CLIDriver().main(args=[
             "syn",  # action
             "-p",
             config_path,
             "--output",
             syn_out_path,
             "--syn_rundir",
             syn_rundir,
             "--par_rundir",
             par_rundir
         ])
     self.assertEqual(cm.exception.code, 0)
     # Now run syn-to-par with the main config as well as the outputs.
     with self.assertRaises(SystemExit) as cm:  # type: ignore
         CLIDriver().main(args=[
             "syn-to-par",  # action
             "-p",
             config_path,
             "-p",
             syn_out_path,
             "--output",
             syn_to_par_out_path,
             "--syn_rundir",
             syn_rundir,
             "--par_rundir",
             par_rundir
         ])
     self.assertEqual(cm.exception.code, 0)
Exemple #2
0
    def test_syn_to_par_full(self) -> None:
        """
        Test that syn-to-par works with the full JSON.
        """

        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()
        par_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")
        syn_out_full_path = os.path.join(syn_rundir, "syn-output-full.json")
        syn_to_par_out_path = os.path.join(syn_rundir, "syn_par_out.json")
        self.generate_dummy_config(syn_rundir, config_path, top_module)

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "syn",  # action
                "-p",
                config_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                par_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Now run syn-to-par with the main config as well as the outputs.
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "syn-to-par",  # action
                "-p",
                syn_out_full_path,
                "--output",
                syn_to_par_out_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                par_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # synthesis full output should keep other settings
        with open(syn_out_full_path, "r") as f:
            syn_output = json.loads(f.read())
            self.assertEqual(syn_output["synthesis.outputs.output_files"],
                             ["/dev/null"])
            self.assertEqual(syn_output["vlsi.core.technology"], "nop")
        # Generated par input should have other settings
        with open(syn_to_par_out_path, "r") as f:
            par_input = json.loads(f.read())
            self.assertEqual(par_input["par.inputs.top_module"], top_module)
            # par-input should preserve other settings
            self.assertEqual(par_input["vlsi.core.technology"], "nop")

        # Cleanup
        shutil.rmtree(syn_rundir)
        shutil.rmtree(par_rundir)
Exemple #3
0
    def test_syn_to_par_same_as_syn_par(self) -> None:
        """
        Test that syn-par generates the same par input as calling syn,
        syn-to-par.
        """

        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()
        par_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")
        syn_out_path = os.path.join(syn_rundir, "syn_out.json")
        syn_to_par_out_path = os.path.join(syn_rundir, "syn_par_out.json")
        self.generate_dummy_config(syn_rundir, config_path, top_module)

        # Run syn-to-par
        self.run_syn_to_par_with_output(config_path, syn_rundir, par_rundir,
                                        syn_out_path, syn_to_par_out_path)

        # Run syn-par
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "syn-par",  # action
                "-p",
                config_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                par_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that the syn-to-par generated par input and the syn-par
        # generated par input are the same, modulo any synthesis.outputs.*
        # settings since they don't matter for par input.
        with open(syn_to_par_out_path, "r") as f:
            with open(os.path.join(syn_rundir, "par-input.json"), "r") as f2:
                syn_to_par_output = json.loads(f.read())
                syn_to_par_output = dict(
                    filter(lambda i: "synthesis.outputs." not in i[0],
                           syn_to_par_output.items()))
                syn_par_output = json.loads(f2.read())
                syn_par_output = dict(
                    filter(lambda i: "synthesis.outputs." not in i[0],
                           syn_par_output.items()))
                self.assertEqual(syn_to_par_output, syn_par_output)

        # Cleanup
        shutil.rmtree(syn_rundir)
        shutil.rmtree(par_rundir)
Exemple #4
0
    def test_dump_macrosizes(self) -> None:
        """
        Test that dump-macrosizes works properly.
        """
        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        output_path = os.path.join(syn_rundir, "output.json")
        config_path = os.path.join(syn_rundir, "run_config.json")

        my_size = MacroSize(library='my_lib',
                            name='my_cell',
                            width=100.0,
                            height=100.0)

        def add_macro_sizes(d: Dict[str, Any]) -> Dict[str, Any]:
            output = deepdict(d)
            output["vlsi.technology.extra_macro_sizes"] = [
                my_size.to_setting()
            ]
            return output

        self.generate_dummy_config(syn_rundir,
                                   config_path,
                                   top_module,
                                   postprocessing_func=add_macro_sizes)

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "dump-macrosizes",  # action
                "-p",
                config_path,
                "--output",
                output_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                syn_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that dumped output should be same as what we read in.
        with open(output_path, "r") as f:
            dumped_output = json.loads(f.read())
            self.assertEqual(dumped_output, [my_size.to_setting()])

        # Cleanup
        shutil.rmtree(syn_rundir)
Exemple #5
0
    def test_syn_par_config_dumping(self) -> None:
        """
        Test that the syn_par step (running both synthesis and place-and-route) dumps the intermediate config files,
        namely synthesis output config and par input config.
        """

        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()
        par_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")
        self.generate_dummy_config(syn_rundir, config_path, top_module)

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "syn-par",  # action
                "-p",
                config_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                par_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that the synthesis output and par input configs got dumped.
        with open(os.path.join(syn_rundir, "syn-output.json"), "r") as f:
            syn_output = json.loads(f.read())
            self.assertEqual(syn_output["synthesis.outputs.output_files"],
                             ["/dev/null"])
            # syn-output should NOT keep other settings
            self.assertFalse("vlsi.core.technology" in syn_output)
        with open(os.path.join(syn_rundir, "syn-output-full.json"), "r") as f:
            syn_output_full = json.loads(f.read())
            self.assertEqual(syn_output_full["synthesis.outputs.output_files"],
                             ["/dev/null"])
            # syn-output-full should preserve other settings
            self.assertEqual(syn_output_full["vlsi.core.technology"], "nop")
        with open(os.path.join(syn_rundir, "par-input.json"), "r") as f:
            par_input = json.loads(f.read())
            self.assertEqual(par_input["par.inputs.top_module"], top_module)
            # par-input should preserve other settings
            self.assertEqual(par_input["vlsi.core.technology"], "nop")

        # Cleanup
        shutil.rmtree(syn_rundir)
        shutil.rmtree(par_rundir)
Exemple #6
0
    def test_syn_par_config_dumping(self) -> None:
        """
        Test that the syn_par step (running both synthesis and place-and-route) dumps the intermediate config files,
        namely synthesis output config and par input config.
        """

        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()
        par_rundir = tempfile.mkdtemp()

        top_module = "dummy"
        config = {
            "vlsi.core.technology": "nop",
            "vlsi.core.synthesis_tool": "mocksynth",
            "vlsi.core.par_tool": "nop",
            "synthesis.inputs.top_module": top_module,
            "synthesis.inputs.input_files": ("/dev/null", ),
            "synthesis.mocksynth.temp_folder": syn_rundir
        }
        config_path = os.path.join(syn_rundir, "run_config.json")
        with open(config_path, "w") as f:
            f.write(json.dumps(config, indent=4))

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "syn-par",  # action
                "-p",
                config_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                par_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that the synthesis output and par input configs got dumped.
        with open(os.path.join(syn_rundir, "syn-output.json"), "r") as f:
            syn_output = json.loads(f.read())
            self.assertEqual(syn_output["synthesis.outputs.output_files"], [])
        with open(os.path.join(syn_rundir, "par-input.json"), "r") as f:
            par_input = json.loads(f.read())
            self.assertEqual(par_input["par.inputs.top_module"], top_module)

        # Cleanup
        shutil.rmtree(syn_rundir)
        shutil.rmtree(par_rundir)
Exemple #7
0
    def test_hier_dump_empty_constraints(self) -> None:
        """
        Test that hierarchical settings work properly even when no constraints
        are given.
        """
        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")

        def add_hier(d: Dict[str, Any]) -> Dict[str, Any]:
            output = deepdict(d)
            output["vlsi.inputs.default_output_load"] = 1
            output["vlsi.inputs.hierarchical.top_module"] = top_module
            output["vlsi.inputs.hierarchical.flat"] = "hierarchical"
            output["vlsi.inputs.hierarchical.config_source"] = "manual"
            output["vlsi.inputs.hierarchical.manual_modules"] = [{
                "mod1": ["m1s1", "m1s2"],
                "mod2": ["m2s1"],
                top_module: ["mod1", "mod2"]
            }]
            output[
                "vlsi.inputs.hierarchical.manual_placement_constraints"] = []
            output["vlsi.inputs.hierarchical.constraints"] = []
            return output

        self.generate_dummy_config(syn_rundir,
                                   config_path,
                                   top_module,
                                   postprocessing_func=add_hier)

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "auto",  # action
                "-p",
                config_path,
                "--obj_dir",
                syn_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Cleanup
        shutil.rmtree(syn_rundir)
Exemple #8
0
    def test_dump(self) -> None:
        """
        Test that dump works properly.
        """
        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        output_path = os.path.join(syn_rundir, "output.json")
        config_packed_path = os.path.join(syn_rundir, "run_config_packed.json")
        config_path = os.path.join(syn_rundir, "run_config.json")
        self.generate_dummy_config(syn_rundir, config_packed_path, top_module)
        # Equivalent config to above but not unpacked
        with open(config_packed_path, "r") as f:
            unpacked_config = hammer_config.reverse_unpack(json.loads(
                f.read()))
        with open(config_path, "w") as f:
            f.write(
                json.dumps(unpacked_config, cls=HammerJSONEncoder, indent=4))

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "dump",  # action
                "-p",
                config_path,
                "--output",
                output_path,
                "--syn_rundir",
                syn_rundir,
                "--par_rundir",
                syn_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that dumped output should be same as what we read in.
        with open(output_path, "r") as f:
            dumped_output = json.loads(f.read())
        with open(config_packed_path, "r") as f:
            packed_output = json.loads(f.read())
        self.assertEqual(packed_output, dumped_output)

        # Cleanup
        shutil.rmtree(syn_rundir)
Exemple #9
0
    def test_syn_to_par_improper(self) -> None:
        """
        Test that appropriate error messages are raised when syn-to-par
        is used on a config that does not have outputs.
        """

        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()
        par_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")
        log_path = os.path.join(syn_rundir, "log.txt")
        self.generate_dummy_config(syn_rundir, config_path, top_module)

        with HammerLoggingCaptureContext() as c:
            # Running syn-to-par on a not-output config should fail.
            with self.assertRaises(SystemExit) as cm:  # type: ignore
                CLIDriver().main(args=[
                    "syn-to-par",  # action
                    "-p",
                    config_path,
                    "--log",
                    log_path,
                    "--syn_rundir",
                    syn_rundir,
                    "--par_rundir",
                    par_rundir
                ])
            self.assertEqual(cm.exception.code, 1)
        self.assertTrue(
            c.log_contains(
                "Input config does not appear to contain valid synthesis outputs"
            ))

        # Cleanup
        shutil.rmtree(syn_rundir)
        shutil.rmtree(par_rundir)
Exemple #10
0
    def test_hier_dump(self) -> None:
        """
        Test that hierarchical settings work properly.
        """
        # Set up some temporary folders for the unit test.
        syn_rundir = tempfile.mkdtemp()

        # Generate a config for testing.
        top_module = "dummy"
        config_path = os.path.join(syn_rundir, "run_config.json")

        def add_hier(d: Dict[str, Any]) -> Dict[str, Any]:
            output = deepdict(d)
            dummy_placement = PlacementConstraint(
                path="dummy",
                type=PlacementConstraintType.Dummy,
                x=0.0,
                y=0.0,
                width=10.0,
                height=10.0,
                orientation=None,
                margins=None,
                layers=None,
                obs_types=None).to_dict()
            output["vlsi.inputs.default_output_load"] = 1
            output["vlsi.inputs.hierarchical.top_module"] = top_module
            output["vlsi.inputs.hierarchical.flat"] = "hierarchical"
            output["vlsi.inputs.hierarchical.config_source"] = "manual"
            output["vlsi.inputs.hierarchical.manual_modules"] = [{
                "mod1": ["m1s1", "m1s2"],
                "mod2": ["m2s1"],
                top_module: ["mod1", "mod2"]
            }]
            manual_constraints = [{
                "mod1": [dummy_placement]
            }, {
                "mod2": [dummy_placement]
            }, {
                "m1s1": [dummy_placement]
            }, {
                "m1s2": [dummy_placement]
            }, {
                "m2s1": [dummy_placement]
            }, {
                top_module: [dummy_placement]
            }]
            output[
                "vlsi.inputs.hierarchical.manual_placement_constraints"] = manual_constraints
            output["vlsi.inputs.hierarchical.constraints"] = [{
                "mod1": [{
                    "vlsi.inputs.default_output_load": 2
                }]
            }, {
                "m2s1": [{
                    "vlsi.inputs.default_output_load": 3
                }]
            }]
            return output

        self.generate_dummy_config(syn_rundir,
                                   config_path,
                                   top_module,
                                   postprocessing_func=add_hier)

        # Check that running the CLIDriver executes successfully (code 0).
        with self.assertRaises(SystemExit) as cm:  # type: ignore
            CLIDriver().main(args=[
                "auto",  # action
                "-p",
                config_path,
                "--obj_dir",
                syn_rundir
            ])
        self.assertEqual(cm.exception.code, 0)

        # Check that dumped output should be same as what we read in.
        with open(os.path.join(syn_rundir, "syn-m2s1/full_config.json"),
                  "r") as f:
            dumped_output = json.loads(f.read())
        self.assertEqual(dumped_output['vlsi.inputs.default_output_load'], 3)
        with open(os.path.join(syn_rundir, "syn-m1s1/full_config.json"),
                  "r") as f:
            dumped_output = json.loads(f.read())
        self.assertEqual(dumped_output['vlsi.inputs.default_output_load'], 1)
        with open(os.path.join(syn_rundir, "syn-mod1/full_config.json"),
                  "r") as f:
            dumped_output = json.loads(f.read())
        self.assertEqual(dumped_output['vlsi.inputs.default_output_load'], 2)

        # Cleanup
        shutil.rmtree(syn_rundir)