def test_preprocessing_SD(): name = f'ckt_{get_test_id()}'.upper() netlist = nested_swap_SD(name) constraints = constraints = [{ "constraint": "PowerPorts", "ports": ["D"] }, { "constraint": "GroundPorts", "ports": ["S"] }, { "constraint": "KeepDummyHierarchies", "isTrue": True }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) all_modules = set([name, "PARAM_MOS", "P_MOS"]) available_modules = set([ module.name for module in ckt_library if isinstance(module, SubCircuit) ]) assert available_modules == all_modules, f"{available_modules}" assert ckt_library.find("P_MOS").get_element( "MN1").parameters["NFIN"] == "12" assert ckt_library.find("P_MOS").get_element("MN1").pins == { "D": "D", "G": "G", "S": "S", "B": "B", } clean_data(name)
def test_cmp_2(): name = f'ckt_{get_test_id()}' netlist = circuits.comparator(name) setup = textwrap.dedent("""\ POWER = vccx GND = vssx """) constraints = [ {"constraint": "GroupBlocks", "instances": ["mn1", "mn2"], "name": "dp"}, {"constraint": "GroupBlocks", "instances": ["mn3", "mn4"], "name": "ccn"}, {"constraint": "GroupBlocks", "instances": ["mp5", "mp6"], "name": "ccp"}, {"constraint": "GroupBlocks", "instances": ["mn11", "mp13"], "name": "invp"}, {"constraint": "GroupBlocks", "instances": ["mn12", "mp14"], "name": "invn"}, {"constraint": "SameTemplate", "instances": ["mp7", "mp8"]}, {"constraint": "SameTemplate", "instances": ["mp9", "mp10"]}, {"constraint": "SameTemplate", "instances": ["invn", "invp"]}, {"constraint": "SymmetricBlocks", "direction": "V", "pairs": [["ccp"], ["ccn"], ["dp"], ["mn0"], ["invn", "invp"], ["mp7", "mp8"], ["mp9", "mp10"]]}, {"constraint": "Order", "direction": "top_to_bottom", "instances": ["invn", "ccp", "ccn", "dp", "mn0"]}, {"constraint": "Order", "direction": "top_to_bottom", "instances": ["invn", "mp9", "mp7", "mn0"]}, {"constraint": "MultiConnection", "nets": ["vcom"], "multiplier": 6}, {"constraint": "AspectRatio", "subcircuit": name, "ratio_low": 0.5, "ratio_high": 1.5} ] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup, area=5e9)
def test_multi_param_remove_dummy(): name = f'ckt_{get_test_id()}'.upper() netlist = multi_param_ckt(name) constraints = [{ "constraint": "PowerPorts", "ports": ["D"] }, { "constraint": "GroundPorts", "ports": ["S"] }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) all_modules = set([name]) available_modules = set([ module.name for module in ckt_library if isinstance(module, SubCircuit) ]) assert available_modules == all_modules, f"{available_modules}" ckt = ckt_library.find(name) assert ckt assert ckt.get_element( "MI1"), f"all instances{[ele.name for ele in ckt.elements]}" assert ckt.get_element("MI1").parameters["NFIN"] == "16" assert ckt.get_element("MI2") assert ckt.get_element("MI2").parameters["NFIN"] == "24" assert ckt.get_element("MI3") assert ckt.get_element("MI3").parameters["NFIN"] == "24" assert ckt.get_element("MI4") assert ckt.get_element("MI4").parameters["NFIN"] == "64" clean_data(name)
def test_tia(): name = f'ckt_{get_test_id()}' netlist = circuits.tia(name) setup = "" constraints = [] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup)
def test_cmp_0(): name = f'ckt_{get_test_id()}' netlist = circuits.comparator(name) setup = "" constraints = [] example = build_example(name, netlist, setup, constraints) ckt_dir, run_dir = run_example(example, cleanup=cleanup)
def test_add_symmetry_const(): name = f'ckt_{get_test_id()}' netlist = ota_six(name) constraints = [ {"constraint": "IsDigital", "isTrue": True} ] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) with set_context(ckt.constraints): x = constraint.SymmetricBlocks(direction="V", pairs=[["MN4", "MN3"]]) const_pairs = {"MN4": "MN3"} # skip dictionary element with pytest.raises(KeyError): add_or_revert_const(const_pairs, ckt.constraints, list()) assert len(ckt.constraints) == 1 const_pairs = [["MN4", "MN3"]] add_or_revert_const(const_pairs, ckt.constraints, list()) assert len(ckt.constraints) == 2 assert ckt.constraints[1] == x const_pairs = [["MN4", "MN5"]] # Skip unequal size add_or_revert_const(const_pairs, ckt.constraints, list()) assert len(ckt.constraints) == 2 const_pairs = [["VIN", "VIP"]] # Skip net add_or_revert_const(const_pairs, ckt.constraints, list()) assert len(ckt.constraints) == 2 clean_data(name)
def test_ro_1(): name = f'ckt_{get_test_id()}' setup = textwrap.dedent("""\ DONT_CONST = {name} """) netlist = textwrap.dedent(f"""\ .subckt ro_stage vi vo vccx vssx mp0 vo vi vccx vccx p w=360e-9 m=1 nf=2 mn0 vo vi vssx vssx n w=360e-9 m=1 nf=2 .ends .subckt {name} vo vccx vssx xi0 vo v1 vccx vssx ro_stage xi1 v1 v2 vccx vssx ro_stage xi2 v2 v3 vccx vssx ro_stage xi3 v3 v4 vccx vssx ro_stage xi4 v4 vo vccx vssx ro_stage .ends {name} """) constraints = { 'ro_stage': [ {"constraint": "Order", "direction": "left_to_right", "instances": ["mn0", "mp0"]}, ], name: [ {"constraint": "Order", "direction": "left_to_right", "instances": [f'xi{k}' for k in range(5)]}, ] } example = build_example(name, netlist, setup, constraints) ckt_dir, run_dir = run_example(example, cleanup=cleanup) with (run_dir / '3_pnr' / 'inputs' / 'RO_STAGE.pnr.const.json').open('rt') as fp: d = json.load(fp) assert len(d['constraints']) > 0, 'Where is the order constraint???'
def test_array_gen_ro_f(): name = f'ckt_{get_test_id()}' netlist = ring_oscillator_flat(name) constraints = [{ "constraint": "DoNotUseLib", "libraries": ["STAGE2_INV", "INV", "DP_PMOS", "DP_NMOS"] }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) assert ckt, f"No ckt {name} found in library" array_cl = process_arrays(ckt, dict()) array1 = array_cl.find_array('VCCX', ['VSSX']) assert array1 == [['MP0', 'MN0'], ['MP1', 'MN1'], ['MP2', 'MN2'], ['MP3', 'MN3'], ['MP4', 'MN4']] array_cl.add_align_block_const() array_cl.add_new_array_hier() assert ckt.get_element("X_ARRAY_HIER_VCCX") assert ckt_library.find("ARRAY_HIER_VCCX") assert ckt_library.find( "ARRAY_TEMPLATE" ), f"{set([inst.name for inst in ckt_library.find('ARRAY_TEMPLATE').elements])}" assert set([ inst.name for inst in ckt_library.find("ARRAY_TEMPLATE").elements ]) == {'MP0', 'MN0'} array_insts = [ 'X_ARRAY_TEMPLATE', 'X_ARRAY_TEMPLATE1', 'X_ARRAY_TEMPLATE2', 'X_ARRAY_TEMPLATE3', 'X_ARRAY_TEMPLATE4' ] assert [ inst.name for inst in ckt_library.find("ARRAY_HIER_VCCX").elements ] == array_insts clean_data(name)
def test_symm_net(): name = f'ckt_{get_test_id()}' netlist = ota_six(name) constraints = [ {"constraint": "IsDigital", "isTrue": True} ] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) G = Graph(ckt) pairs, pinsA, pinsB = symmnet_device_pairs(G, 'VIN', 'VIP', list(), None, True) assert pairs == {'VIN': 'VIP', 'MN4': 'MN3'} assert pinsA == ['MN4/G', 'VIN'] assert pinsB == ['MN3/G', 'VIP'] pairs, pinsA, pinsB = symmnet_device_pairs(G, 'VIN', 'VIP', [{'MN3', 'MN4'}], None) assert pairs == {'VIN': 'VIP', 'MN4': 'MN3'} pairs, pinsA, pinsB = symmnet_device_pairs(G, 'VIN', 'VIP', ['MN3'], None) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "VIN", "VIP", ["MN4"], None) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "VIN", "VIP", list(), ["MN4"]) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "VIN", "VIP", list(), ["MN3"]) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "IBIAS", "TAIL", list(), ["MN3"]) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "VON", "VOP", list(), ["MN3"]) assert pairs is None pairs, pinsA, pinsB = symmnet_device_pairs(G, "VIN", "VON", list(), ["MN3"]) assert pairs is None clean_data(name)
def test_multi_param_skip(): name = f'ckt_{get_test_id()}'.upper() netlist = multi_param_ckt_with_existing_name(name) constraints = [{ "constraint": "PowerPorts", "ports": ["D"] }, { "constraint": "GroundPorts", "ports": ["S"] }, { "constraint": "KeepDummyHierarchies", "isTrue": True }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) all_modules = set([name, "PARAM_MOS", "PARAM_MOS_1", "PARAM_MOS_2"]) available_modules = set([ module.name for module in ckt_library if isinstance(module, SubCircuit) ]) assert available_modules == all_modules, f"{available_modules}" assert ckt_library.find("PARAM_MOS").parameters["TF"] == "16" assert ckt_library.find("PARAM_MOS_1").parameters["TF"] == "32" assert ckt_library.find("PARAM_MOS_2").parameters["TF"] == "24" assert ckt_library.find("PARAM_MOS").get_element( "MN1").parameters["NFIN"] == "16" assert ckt_library.find("PARAM_MOS_1").get_element( "MN2").parameters["NFIN"] == "32" assert ckt_library.find("PARAM_MOS_2").get_element( "MN1").parameters["NFIN"] == "24" clean_data(name)
def test_cmp_pg(): name = f'ckt_{get_test_id()}' netlist = circuits.comparator(name) setup = textwrap.dedent("""\ POWER = vccx GND = vssx """) constraints = [] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup)
def test_aspect_ratio_high(): name = f'ckt_{get_test_id()}' netlist = circuits.cascode_amplifier(name) constraints = [{ "constraint": "AspectRatio", "subcircuit": "example_aspect_ratio_max", "ratio_high": 1 }] example = build_example(name, netlist, constraints) run_example(example)
def test_do_not_identify(): name = f'ckt_{get_test_id()}' netlist = circuits.ota_five(name) constraints = [{ "constraint": "AlignInOrder", "line": "left", "instances": ["mp1", "mn1"] }] example = build_example(name, netlist, constraints) run_example(example)
def test_boundary_max_height(): name = f'ckt_{get_test_id()}' netlist = circuits.cascode_amplifier(name) constraints = [{ "constraint": "Boundary", "subcircuit": "example_boundary_max_height", "max_height": 1.3 }] example = build_example(name, netlist, constraints) run_example(example)
def test_ldo_amp(): name = f'ckt_{get_test_id()}' netlist = circuits.ldo_amp(name) setup = textwrap.dedent("""\ POWER = vccx GND = vssx DONT_USE_CELLS = CASCODED_CMC_NMOS CMB_PMOS_2 LSB_PMOS_2 LSB_NMOS_2 """) constraints = [] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup)
def test_ota_six(): name = f'ckt_{get_test_id()}' netlist = circuits.ota_six(name) setup = textwrap.dedent(f"""\ DONT_CONST = {name} """) constraints = [ {"constraint": "GroupBlocks", "instances": ["mn1", "mn2"], "name": "g1"}, {"constraint": "GroupBlocks", "instances": ["mn3", "mn4"], "name": "g2"}, {"constraint": "GroupBlocks", "instances": ["mp5", "mp6"], "name": "g3"}, {"constraint": "AspectRatio", "subcircuit": name, "ratio_low": 0.01, "ratio_high": 100}] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup, log_level='DEBUG')
def test_cs_grid(): name = f'ckt_{get_test_id()}' netlist = circuits.common_source_mini(name) setup = textwrap.dedent("""\ POWER = vccx GND = vssx """) constraints = [{ "constraint": "AlignInOrder", "line": "left", "instances": ["mp0", "mn0"] }] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup)
def test_array_gen_ro(): name = f'ckt_{get_test_id()}' netlist = ring_oscillator(name) constraints = [] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) assert ckt, f"No ckt {name} found in library" array_cl = process_arrays(ckt, dict()) array1 = array_cl.find_array('VCCX', ['VSSX']) assert array1 == ['XI0', 'XI1', 'XI2', 'XI3', 'XI4'] array_cl.add_align_block_const() with set_context(ckt.constraints): x = constraint.Align(line="h_center", instances=array1) assert ckt.constraints == [x] clean_data(name)
def test_align_center(): name = f'ckt_{get_test_id()}' netlist = textwrap.dedent(f"""\ .subckt {name} vin vop vcc vss nbs pbs mp1 vop pbs vcc vcc p w=720e-9 nf=4 m=8 mn1 vop nbs vmd vss n w=720e-9 nf=4 m=6 mn0 vmd vin vss vss n w=720e-9 nf=4 m=16 .ends {name} """) constraints = [{ "constraint": "AlignInOrder", "direction": "vertical", "line": "center", "instances": ["mn0", "mn1", "mp1"] }] example = build_example(name, netlist, constraints) run_example(example)
def test_donotroute(): name = f'ckt_{get_test_id()}' netlist = textwrap.dedent(f"""\ .subckt inv vi vo vccx vssx mp0 vo vi vccx vccx p w=360e-9 m=1 nf=2 mn0 vo vi vssx vssx n w=360e-9 m=1 nf=2 .ends .subckt {name} vi vo vccx vssx xi0 vi v1 vccx vssx inv xi1 v1 vo vccx vssx inv .ends """) constraints = [{ "constraint": "AutoConstraint", "isTrue": False }, { "constraint": "PowerPorts", "ports": ["vccx"] }, { "constraint": "GroundPorts", "ports": ["vssx"] }, { "constraint": "DoNotRoute", "nets": ["v1", "vccx", "vssx"] }] example = build_example(name, netlist, constraints) _, run_dir = run_example(example, cleanup=False) # There should be opens in the generated layout with (run_dir / '3_pnr' / f'{name.upper()}_0.json').open('rt') as fp: d = json.load(fp) cv = CanvasPDK() cv.terminals = d['terminals'] cv.removeDuplicates() assert len(cv.rd.opens) > 0, 'Layout should have opens' # The generated and loaded files should be identical input_dir = run_dir / '3_pnr' / 'inputs' verilog_d = VerilogJsonTop.parse_file(input_dir / f'{name.upper()}.verilog.json') constraint_files_l, pnr_const_ds_l = load_constraint_files(input_dir) constraint_files_g, pnr_const_ds_g = gen_constraint_files( verilog_d, input_dir) assert constraint_files_l == constraint_files_g assert pnr_const_ds_l == pnr_const_ds_g
def test_dont_constrain_clk(): # TODO Do not constrain clock connected devices name = f'ckt_{get_test_id()}'.upper() netlist = ota_six(name) constraints = [{ "constraint": "PowerPorts", "ports": ["VCCX"] }, { "constraint": "GroundPorts", "ports": ["VSSX"] }, { "constraint": "ClockPorts", "ports": ["vin"] }] example = build_example(name, netlist, constraints) generate_hierarchy(example, name, out_path, False, pdk_path, False) clean_data(name) pass
def test_merge_parallel(): # TODO Do not identify array when setup set as false name = f'ckt_{get_test_id()}'.upper() netlist = ota_six(name) constraints = [{ "constraint": "PowerPorts", "ports": ["VCCX"] }, { "constraint": "GroundPorts", "ports": ["VSSX"] }, { "constraint": "MergeParallelDevices", "isTrue": False }] example = build_example(name, netlist, constraints) generate_hierarchy(example, name, out_path, False, pdk_path, False) clean_data(name) pass
def test_array_gen_ro_fh(): name = f'ckt_{get_test_id()}' netlist = ring_oscillator_flat(name) constraints = [{"constraint": "DoNotUseLib", "libraries": ["STAGE2_INV"]}] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) assert ckt, f"No ckt {name} found in library" array_cl = process_arrays(ckt, dict()) array1 = array_cl.find_array('VCCX', ['VSSX']) assert array1 == [ 'X_INV_MN0_MP0', 'X_INV_MN1_MP1', 'X_INV_MN2_MP2', 'X_INV_MN3_MP3', 'X_INV_MN4_MP4' ] array_cl.add_align_block_const() with set_context(ckt.constraints): x = constraint.Align(line="h_center", instances=array1) assert ckt.constraints[-1] == x clean_data(name)
def test_ota_six(): name = f'ckt_{get_test_id()}'.upper() netlist = ota_six(name) constraints = [{ "constraint": "PowerPorts", "ports": ["VCCX"] }, { "constraint": "GroundPorts", "ports": ["VSSX"] }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) all_modules = set([name, "SCM_NMOS", "SCM_PMOS", "DP_NMOS_B"]) available_modules = set([ module.name for module in ckt_library if isinstance(module, SubCircuit) ]) assert available_modules == all_modules, f"{available_modules}" clean_data(name)
def test_array_vga_equal(): name = f'ckt_{get_test_id()}' netlist = variable_gain_amplifier_equal(name) constraints = list() example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) ckt = ckt_library.find(name) assert ckt, f"No ckt {name} found in library" FindConst(ckt) all_arrays = [ module.name for module in ckt_library if isinstance(module, SubCircuit) and 'ARRAY' in module.name ] ARRAY_HIER = ckt_library.find("ARRAY_HIER_VOUT_VGA1") assert ARRAY_HIER, f"ARRAY_HIER_VOUT_VGA1 not found in {all_arrays}" TEMPLATE = ckt_library.find("ARRAY_TEMPLATE") assert TEMPLATE, f"TEMPLATE not found in {all_arrays}" insts = [inst.name for inst in TEMPLATE.elements] assert set(insts) == {'X_DP_NMOS_B_M00_M01', 'MSW0'} clean_data(name)
def test_cmp_3(): name = f'ckt_{get_test_id()}' netlist = circuits.comparator(name) setup = textwrap.dedent("""\ POWER = vccx GND = vssx CLOCK = clk """) constraints = [ {"constraint": "GroupBlocks", "instances": ["mn1", "mn2"], "name": "dp"}, {"constraint": "GroupBlocks", "instances": ["mn3", "mn4"], "name": "ccn"}, {"constraint": "GroupBlocks", "instances": ["mp5", "mp6"], "name": "ccp"}, {"constraint": "SymmetricBlocks", "direction": "V", "pairs": [["mn0"], ["dp"]]}, {"constraint": "SymmetricBlocks", "direction": "V", "pairs": [["ccp"], ["ccn"]]}, {"constraint": "Order", "direction": "top_to_bottom", "instances": ["mn0", "dp"]}, {"constraint": "Order", "direction": "top_to_bottom", "instances": ["ccp", "ccn"]}, {"constraint": "AlignInOrder", "line": "bottom", "instances": ["dp", "ccn"]} ] example = build_example(name, netlist, setup, constraints) run_example(example, cleanup=cleanup, area=3.5e9)
def test_dependencies(): name = f'ckt_{get_test_id()}' netlist = circuits.tia(name) setup = "" constraints = [] example = build_example(name, netlist, setup, constraints) ckt_dir, run_dir = run_example(example, cleanup=False) with (run_dir / '2_primitives' / '__primitives__.json').open('rt') as fp: primitives = json.load(fp) assert 'metadata' in primitives[ 'TFR_PRIM_L_1E06_W_1E06'], 'Metadata not found' with (run_dir / '3_pnr' / 'Results' / f'{name.upper()}_0.placement_verilog.json').open('rt') as fp: placement = json.load(fp) assert 'modules' in placement, 'modules not in placement' shutil.rmtree(run_dir) shutil.rmtree(ckt_dir)
def test_dont_const(): name = f'ckt_{get_test_id()}'.upper() netlist = ota_six(name) constraints = [{ "constraint": "PowerPorts", "ports": ["VCCX"] }, { "constraint": "GroundPorts", "ports": ["VSSX"] }, { "constraint": "AutoConstraint", "isTrue": False }] example = build_example(name, netlist, constraints) generate_hierarchy(example, name, out_path, False, pdk_path, False) gen_const_path = out_path / f'{name}.verilog.json' with open(gen_const_path, "r") as fp: gen_const = next(x for x in json.load(fp)['modules'] if x['name'] == name)["constraints"] assert len(gen_const) == 3, f"{gen_const}" clean_data(name)
def test_top_param(): name = f'ckt_{get_test_id()}'.upper() netlist = mos_ckt(name) constraints = [{ "constraint": "PowerPorts", "ports": ["D"] }, { "constraint": "GroundPorts", "ports": ["S"] }] example = build_example(name, netlist, constraints) ckt_library = compiler_input(example, name, pdk_path, config_path) all_modules = set([name]) available_modules = set([ module.name for module in ckt_library if isinstance(module, SubCircuit) ]) assert available_modules == all_modules, f"{available_modules}" assert ckt_library.find(name).get_element("MN1") assert ckt_library.find(name).get_element("MN1").parameters["NFIN"] == "12" clean_data(name)
def test_cmp_order(): """ mp7 and mp8 should not be identified as a primitive """ name = f'ckt_{get_test_id()}' netlist = circuits.comparator(name) setup = "" constraints = [{"constraint": "Order", "direction": "left_to_right", "instances": ["mp7", "mp8"]}] name = f'ckt_{get_test_id()}' example = build_example(name, netlist, setup, constraints) ckt_dir, run_dir = run_example(example, cleanup=False) with (run_dir / '1_topology' / f'{name.upper()}.verilog.json').open('rt') as fp: verilog_json = json.load(fp) module_found = False for module in verilog_json['modules']: if module['name'] == name.upper(): module_found = True instances = set([k['instance_name'] for k in module['instances']]) assert 'MP7' in instances and 'MP8' in instances, f'MP7 or MP8 not found in {instances}' assert module_found, f'Module {name.upper()} not found in {name.upper()}verilog.json' if cleanup: shutil.rmtree(run_dir) shutil.rmtree(ckt_dir)