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)
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)
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)
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)
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)
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)
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)
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)
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)
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)