コード例 #1
0
ファイル: v93k_utils.py プロジェクト: catjake/PythonTools
def parsePinsField(a_string, full_pin_list, pin_group_dict):
    pin_list = expandToPins(re.sub("[\-\(\)]", "", a_string).split(), full_pin_list, pin_group_dict)
    # do we have any pins we're subtracting, i.e. -( aPin bPin....)
    if util.in_string(a_string, "-\("):
        p_string = re.sub("[\w\s]+-\(\s+", "", a_string)
        remove_pins = expandToPins(re.sub("\s+\)","", p_string.strip()).split(), full_pin_list, pin_group_dict)
        pin_list = list(set(pin_list) - set(remove_pins))
    return pin_list
コード例 #2
0
ファイル: v93k_utils.py プロジェクト: catjake/PythonTools
def getLevels(levels_file, spec_levels_groups, full_pin_list, pin_group_dict):
    """
    Parse out levels objects, split into EQN and SPS sections for a dictionary
    :param levels_file:
    :param spec_levels_groups:
    :return: big levels dict, containing all info pertaining to equation sets, level sets, pins, etc....
    """
    f = util.FileUtils(levels_file, True)
    g = util.m_re(f.contents)
    g.grep(spec_levels_groups["topLevel"])
    # with levels, the eqnset is broken down into two sets: Equation(EQN) and Spec(SPS)
    start_pts,stop_pts = util.find_blocks(
            g.m_groups, spec_levels_groups["startClause"], spec_levels_groups["stopClause"]
    )
    ref_dict = {"EQN":{}, "SPS":{}}
    for start, stop in zip(start_pts, stop_pts):
        contents = g.allLines[int(float(g.coordinates[start])-1): int(float(g.coordinates[stop])-1)]
        if util.in_string(g.lines[start], "EQN"):
            level_key = "EQN"
        else:
            level_key = "SPS"
        level_dict = spec_levels_groups[level_key]
        b = util.m_re(contents)
        for remove_expr in level_dict["remove"]:
            b.sub(remove_expr,"")
        contents = util.remove_from_list(contents, "^\s*$")
        b = util.m_re(contents)
        b.grep(level_dict["topLevel"])
        i_list = [int(float(a_num)-1) for a_num in b.coordinates]
        if len(i_list)>1:
            eqn_set_indices = [(a,b) for a,b in zip(i_list,i_list[1:]+[len(contents)])]
        else:
            eqn_set_indices = [(i_list[0], len(contents))]
        for (eq_start,eq_stop) in eqn_set_indices:
            eq_m = re.search("^\s*EQNSET\s+(?P<eq_num>\d+)\s*\"?(?P<eq_name>[\w\s\-\.]+)?\"?", contents[eq_start])
            eq_num, eq_name = -99, ""
            try:
                eq_dict = eq_m.groupdict()
                eq_num, eq_name = int(eq_dict["eq_num"]), eq_dict["eq_name"]
            except KeyError, e:
                if eq_num == -99:
                    print "Uh Oh, we should always have an EQNSET number\n{0}".format(e)
                    print "\n{0}".format(contents[eq_start])
                    raise
                else:
                    pass # may not always have an equation set name
            ref_dict[level_key][eq_num] = {"eq_name": eq_name, "sub_sections":[]}
            if level_key == "EQN":
                _getLevelEqnSet(
                    ref_dict[level_key][eq_num], contents, eq_start, eq_stop,
                    level_dict, full_pin_list, pin_group_dict
                )
            elif level_key == "SPS":
                _getLevelSpsSet(ref_dict[level_key][eq_num], contents, eq_start, eq_stop, level_dict)
コード例 #3
0
def parsePinsField(a_string, full_pin_list, pin_group_dict):
    pin_list = expandToPins(
        re.sub("[\-\(\)]", "", a_string).split(), full_pin_list,
        pin_group_dict)
    # do we have any pins we're subtracting, i.e. -( aPin bPin....)
    if util.in_string(a_string, "-\("):
        p_string = re.sub("[\w\s]+-\(\s+", "", a_string)
        remove_pins = expandToPins(
            re.sub("\s+\)", "", p_string.strip()).split(), full_pin_list,
            pin_group_dict)
        pin_list = list(set(pin_list) - set(remove_pins))
    return pin_list
コード例 #4
0
def determineSetups(testflow_file):
    """
    get levels and timing file reference(s) from setups in testflow file
    :param testflow_file"""
    # testflow section fields
    tfSectionFields = [
        "information", "declarations", "implicit_declarations", "flags",
        "testmethodparameters", "testmethodlimits", "testmethods",
        "test_suites", "bin_disconnect", "test_flow", "binning", "context",
        "hardware_bin_descriptions"
    ]
    contextDirDict = {
        "context_config_file": "configuration",
        "context_levels_file": "levels",
        "context_timing_file": "timing",
        "context_vector_file": "vectors",
        "context_analog_control_file": "analog_control",
        "context_routing_file": "routing",
        "context_testtable_file": "testtable",
        "context_channel_attrib_file": "ch_attributes"
    }
    testflowPath = os.path.dirname(testflow_file)
    devicePath = testflowPath.rpartition(os.path.sep)[0]
    f = util.FileUtils(testflow_file, True)
    setupIndex = util.find_index(f.contents, "^\s*setup\s*:\s*[\.\\/\w]+")
    setupsDict = {}
    if setupIndex > -1:
        setupFn = os.path.join(testflowPath,
                               f.contents[setupIndex].split(":")[-1].strip())
        f = util.FileUtils(setupFn, True)
        startPt = util.find_index(f.contents, "^\s*context\\b")
        stopPt = startPt + util.find_index(f.contents[startPt:], "^\s*end\\b")
        chkList = [
            ",".join([aWord.strip() for aWord in aRow.strip().split("=")
                      ]).replace(";", "").replace('"', '')
            for aRow in f.contents[startPt:stopPt]
            if util.in_string(aRow, "=")
        ]
        setupsDict = dict([tuple(aRow.split(",")) for aRow in chkList])
        for k, v in setupsDict.iteritems():
            setupsDict[k] = os.path.join(devicePath, contextDirDict[k], v)
    return setupsDict
コード例 #5
0
    if m:
        aDict = m.groupdict()
        if not binMapDict.has_key(aDict["name"]):
            binMapDict[aDict["name"]] = {"bin": int(aDict["bin"])}

# get lookup table for v93k test table and bin names
f = util.FileUtils("/home/jacob/Projects/q55xx/v93kLookUpTable.csv", True)
chkList = [a_row.strip().split(",") for a_row in f.contents]
v93kTestSuite2BinNameDict = dict([tuple(a_row) for a_row in chkList])

# line up D10 and V93K test names
v93kDlogFn = "/home/jacob/Projects/q55xx/dlogV93K_20151209.txt"
f = util.FileUtils(v93kDlogFn, True)
g = util.m_re(f.contents)
g.grep("(?:Started Testsuite|Test Name:)")
iList = [(i,int(float(a_coord)-1)) for (i,a_line), a_coord in zip(enumerate(g.lines), g.coordinates) if util.in_string(a_line, "Testsuite")]
testSuites = []
testSuiteDict = {}
for cStart, cStop in zip(iList[:-1], iList[1:]):
    iStart, m = cStart[0], re.search("^=+\s+Started Testsuite (?P<id>\w+) =+", g.lines[cStart[0]])
    iStop = cStop[0]
    if m:
        testSuite = m.groupdict()["id"]
        if not testSuiteDict.has_key(testSuite):
            testSuiteDict[testSuite] = []
    else:
        testSuite = "UhOh:{0}:{1}".format(cStart[0],cStart[1])
    testSuites.append(testSuite)
    for aLine in g.lines[iStart+1:iStop]:
        m = re.search("^-+\s+Test Name:\s+(?P<id>\w+)(?:@\w+)?:", aLine)
        if m:
コード例 #6
0
def getTiming(timing_file, spec_timing_groups, full_pin_list, pin_group_dict,
              ref_eqn_dict):
    """
    ref_eqn_dict is a running copy of the ref_dict["EQN"] dictionary, and is treated as "read-only",
    with the sole purpose as a reference for the SPEC parameters that get determined in the 
    ref_dict["SPS"] dictionary.
    """
    ref_dict = {"EQN": {}, "SPS": {}, "WVT": {}}
    f = util.FileUtils(timing_file, True)
    g = util.m_re(f.contents)
    g.grep(spec_timing_groups["topLevel"])
    # with timing, the eqnset is broken down into two sets: Equation(EQN) and Spec(SPS)
    start_pts, stop_pts = util.find_blocks(g.m_groups,
                                           spec_timing_groups["startClause"],
                                           spec_timing_groups["stopClause"])
    for start, stop in zip(start_pts, stop_pts):
        contents = g.allLines[int(float(g.coordinates[start]) -
                                  1):int(float(g.coordinates[stop]) - 1)]
        if util.in_string(g.lines[start], "EQN"):
            timing_key = "EQN"
        elif util.in_string(g.lines[start], "WVT"):
            timing_key = "WVT"
            break
        else:
            timing_key = "SPS"
            b = util.m_re(contents)
            b.grep(spec_timing_groups["SPS"]["SPECIFICATION"])
            #-----------------------------------------------------------------------------------------------------------
            # rlogan .. 26apr2016 wrapped in try/catch to display offending code for OMAP5 FPC
            try:
                specName = re.sub("^\s*SPECIFICATION\s+\"|\"", "",
                                  b.m_groups[0]).strip()
            except KeyError:
                import sys
                sys.exit(contents)


#-----------------------------------------------------------------------------------------------------------
            ref_dict["SPS"] = {specName: {"GLOBALS": {}}}
        timing_dict = spec_timing_groups[timing_key]
        b = util.m_re(contents)
        for remove_expr in timing_dict["remove"]:
            b.sub(remove_expr, "")
        contents = util.remove_from_list(contents, "^\s*$")
        b = util.m_re(contents)
        b.grep(timing_dict["topLevel"])
        i_list = [int(float(a_num) - 1) for a_num in b.coordinates]
        if len(i_list) > 1:
            eqn_set_indices = [
                (a, b) for a, b in zip(i_list, i_list[1:] + [len(contents)])
            ]
        else:
            eqn_set_indices = [(i_list[0], len(contents))]
        if timing_key == "SPS":  # let's check for globals
            _getTimingGlobalSpecVars(
                ref_dict[timing_key][specName]["GLOBALS"],
                contents[util.find_index(contents, "{") + 1:i_list[0]])

        for (eq_start, eq_stop) in eqn_set_indices:
            eq_m = re.search(
                "^\s*EQNSET\s+(?P<eq_num>\d+)\s*\"?(?P<eq_name>[\w\s\-\.]+)?\"?",
                contents[eq_start])
            eq_num, eq_name = -99, ""
            try:
                eq_dict = eq_m.groupdict()
                eq_num, eq_name = int(eq_dict["eq_num"]), eq_dict["eq_name"]
            except KeyError, e:
                if eq_num == -99:
                    print "Uh Oh, we should always have an EQNSET number\n{0}".format(
                        e)
                    print "\n{0}".format(contents[eq_start])
                    raise
                else:
                    pass  # may not always have an equation set name
            if timing_key == "EQN":
                ref_dict[timing_key][eq_num] = {
                    "eq_name": eq_name,
                    "sub_sections": []
                }
                _getTimingEqnSet(ref_dict[timing_key][eq_num], contents,
                                 eq_start, eq_stop, timing_dict, full_pin_list,
                                 pin_group_dict)
            elif timing_key == "SPS":
                ref_dict[timing_key][specName][eq_num] = {"name": eq_name}
                _getTimingSpsSet(ref_dict[timing_key][specName][eq_num],
                                 contents[eq_start:eq_stop], timing_dict,
                                 ref_eqn_dict[eq_num]["SPECS"].keys())
コード例 #7
0
def _getTimingSpsSet(t_dict, eq_contents, specs_timing_dict, spec_list):
    # spec_hdr_keys = ["specname", "actual", "minimum", "maximum", "units"]
    spec_hdr_keys = ["specname", "actual", "units"]
    eq_g = util.m_re(eq_contents)
    eq_g.grep("[{}]")  #pull out {} blocks, such as SYNC { ..... }
    if eq_g.pattern_count >= 2:
        start_pts, stop_pts = util.find_blocks(eq_g.m_groups, "{", "}")
        i_list = [(int(float(eq_g.coordinates[s_a]) - 2),
                   int(float(eq_g.coordinates[s_b])))
                  for s_a, s_b in zip(start_pts, stop_pts)]
        del_indices = []
        for (x, y) in i_list:
            del_indices += range(x, y)
        eq_contents = [
            eq_contents[i] for i in list(
                sorted(set(xrange(len(eq_contents))) - set(del_indices)))
        ]
        eq_g = util.m_re(eq_contents)
    else:
        eq_g.clear_cache()
    eq_g.grep(specs_timing_dict["subSections"]
              )  # get all eqnset references with SPECIFICATION block
    t_dict["sub_sections"] = [
        a_row.split()[0].strip() for a_row in eq_g.m_groups
    ]
    if not util.in_list(t_dict["sub_sections"], "SPECNAME"):
        t_dict["sub_sections"].append(
            "SPECNAME, missing actual # SPECNAME comment")
        eq_g.m_groups.append("# SPECNAME")
        eq_g.coordinates.append("-1.1")
    for a_grp, i in zip(eq_g.m_groups,
                        [int(float(a_num) - 1) for a_num in eq_g.coordinates]):
        if not util.in_string(a_grp, "SPECNAME"):
            sub_section_type = a_grp.split()[0].strip()
        else:
            sub_section_type = "SPECS"
        if sub_section_type == "WAVETBL":
            t_dict[sub_section_type] = re.sub(
                "\"", "",
                a_grp.partition(" ")[-1]).strip()
        elif sub_section_type == "PORT":
            t_dict[sub_section_type] = re.sub("^\s*PORT\s+", "", a_grp).split()
        elif sub_section_type == "SPECS":
            t_dict[sub_section_type] = {}
            # hdr_i = util.find_index(eq_contents, "# SPECNAME\s+\*+ACTUAL")
            # hdr_slices = getSpecHeaderSpan(eq_contents[hdr_i])
            # spec_lines = util.remove_from_list(
            #     [re.sub("\s*#\s*.*$", "", a_row) for a_row in eq_contents[hdr_i+1:]],
            #     "^\s*$"
            # )
            spec_lines = util.keep_in_list(
                eq_contents, "^\s*(?:{0})\s+".format("|".join(spec_list)))
            for a_line in spec_lines:
                # a_dict = dict([
                #     (a_key, re.sub("[\[\]]", "", a_line[a_slice]).strip())
                #     for a_key,a_slice in zip(spec_hdr_keys,hdr_slices)
                # ])
                spec_name, _dummy, a_string = re.sub(
                    "\t", "    ", a_line.strip()).partition(" ")
                actual_value, _dummy, a_string = a_string.strip().partition(
                    " ")
                units = None
                u_m = re.search("\[\s*(?P<units>\w+)?\s*\]", a_string)
                if u_m:
                    units = u_m.groupdict()["units"]
                a_dict = {
                    "specname": spec_name,
                    "actual": actual_value,
                    "units": units if not units is None else ""
                }
                key_list = list(set(a_dict.iterkeys()) - {"specname"})
                t_dict[sub_section_type][a_dict["specname"]] = dict([
                    (a_key, a_dict[a_key]) for a_key in key_list
                ])
    pass
コード例 #8
0
def getLevels(levels_file, spec_levels_groups, full_pin_list, pin_group_dict):
    """
    Parse out levels objects, split into EQN and SPS sections for a dictionary
    :param levels_file:
    :param spec_levels_groups:
    :return: big levels dict, containing all info pertaining to equation sets, level sets, pins, etc....
    """
    f = util.FileUtils(levels_file, True)
    g = util.m_re(f.contents)
    g.grep(spec_levels_groups["topLevel"])
    # with levels, the eqnset is broken down into two sets: Equation(EQN) and Spec(SPS)
    start_pts, stop_pts = util.find_blocks(g.m_groups,
                                           spec_levels_groups["startClause"],
                                           spec_levels_groups["stopClause"])
    ref_dict = {"EQN": {}, "SPS": {}}
    for start, stop in zip(start_pts, stop_pts):
        contents = g.allLines[int(float(g.coordinates[start]) -
                                  1):int(float(g.coordinates[stop]) - 1)]
        if util.in_string(g.lines[start], "EQN"):
            level_key = "EQN"
        else:
            level_key = "SPS"
        level_dict = spec_levels_groups[level_key]
        b = util.m_re(contents)
        for remove_expr in level_dict["remove"]:
            b.sub(remove_expr, "")
        contents = util.remove_from_list(contents, "^\s*$")
        b = util.m_re(contents)
        b.grep(level_dict["topLevel"])
        i_list = [int(float(a_num) - 1) for a_num in b.coordinates]
        if len(i_list) > 1:
            eqn_set_indices = [
                (a, b) for a, b in zip(i_list, i_list[1:] + [len(contents)])
            ]
        else:
            eqn_set_indices = [(i_list[0], len(contents))]
        for (eq_start, eq_stop) in eqn_set_indices:
            eq_m = re.search(
                "^\s*EQNSET\s+(?P<eq_num>\d+)\s*\"?(?P<eq_name>[\w\s\-\.]+)?\"?",
                contents[eq_start])
            eq_num, eq_name = -99, ""
            try:
                eq_dict = eq_m.groupdict()
                eq_num, eq_name = int(eq_dict["eq_num"]), eq_dict["eq_name"]
            except KeyError, e:
                if eq_num == -99:
                    print "Uh Oh, we should always have an EQNSET number\n{0}".format(
                        e)
                    print "\n{0}".format(contents[eq_start])
                    raise
                else:
                    pass  # may not always have an equation set name
            ref_dict[level_key][eq_num] = {
                "eq_name": eq_name,
                "sub_sections": []
            }
            if level_key == "EQN":
                _getLevelEqnSet(ref_dict[level_key][eq_num], contents,
                                eq_start, eq_stop, level_dict, full_pin_list,
                                pin_group_dict)
            elif level_key == "SPS":
                _getLevelSpsSet(ref_dict[level_key][eq_num], contents,
                                eq_start, eq_stop, level_dict)
コード例 #9
0
ファイル: v93k_utils.py プロジェクト: catjake/PythonTools
def getTiming(timing_file, spec_timing_groups, full_pin_list, pin_group_dict, ref_eqn_dict):
    """
    ref_eqn_dict is a running copy of the ref_dict["EQN"] dictionary, and is treated as "read-only",
    with the sole purpose as a reference for the SPEC parameters that get determined in the 
    ref_dict["SPS"] dictionary.
    """
    ref_dict = {"EQN":{}, "SPS":{}, "WVT":{}}
    f = util.FileUtils(timing_file, True)
    g = util.m_re(f.contents)
    g.grep(spec_timing_groups["topLevel"])
    # with timing, the eqnset is broken down into two sets: Equation(EQN) and Spec(SPS)
    start_pts,stop_pts = util.find_blocks(
            g.m_groups, spec_timing_groups["startClause"], spec_timing_groups["stopClause"]
    )
    for start, stop in zip(start_pts, stop_pts):
        contents = g.allLines[int(float(g.coordinates[start])-1): int(float(g.coordinates[stop])-1)]
        if util.in_string(g.lines[start], "EQN"):
            timing_key = "EQN"
        elif util.in_string(g.lines[start], "WVT"):
            timing_key = "WVT"
            break
        else:
            timing_key = "SPS"
            b = util.m_re(contents)
            b.grep(spec_timing_groups["SPS"]["SPECIFICATION"])
            specName = re.sub("^\s*SPECIFICATION\s+\"|\"", "", b.m_groups[0]).strip()
            ref_dict["SPS"] = {specName:{"GLOBALS":{}}}
        timing_dict = spec_timing_groups[timing_key]
        b = util.m_re(contents)
        for remove_expr in timing_dict["remove"]:
            b.sub(remove_expr,"")
        contents = util.remove_from_list(contents, "^\s*$")
        b = util.m_re(contents)
        b.grep(timing_dict["topLevel"])
        i_list = [int(float(a_num)-1) for a_num in b.coordinates]
        if len(i_list)>1:
            eqn_set_indices = [(a,b) for a,b in zip(i_list,i_list[1:]+[len(contents)])]
        else:
            eqn_set_indices = [(i_list[0], len(contents))]
        if timing_key == "SPS": # let's check for globals
            _getTimingGlobalSpecVars(ref_dict[timing_key][specName]["GLOBALS"], contents[util.find_index(contents,"{")+1:i_list[0]])

        for (eq_start,eq_stop) in eqn_set_indices:
            eq_m = re.search("^\s*EQNSET\s+(?P<eq_num>\d+)\s*\"?(?P<eq_name>[\w\s\-\.]+)?\"?", contents[eq_start])
            eq_num, eq_name = -99, ""
            try:
                eq_dict = eq_m.groupdict()
                eq_num, eq_name = int(eq_dict["eq_num"]), eq_dict["eq_name"]
            except KeyError, e:
                if eq_num == -99:
                    print "Uh Oh, we should always have an EQNSET number\n{0}".format(e)
                    print "\n{0}".format(contents[eq_start])
                    raise
                else:
                    pass # may not always have an equation set name
            if timing_key == "EQN":
                ref_dict[timing_key][eq_num] = {"eq_name": eq_name, "sub_sections":[]}
                _getTimingEqnSet(
                        ref_dict[timing_key][eq_num], contents, eq_start, eq_stop,
                        timing_dict, full_pin_list, pin_group_dict
                )
            elif timing_key == "SPS":
                ref_dict[timing_key][specName][eq_num] = {"name":eq_name}
                _getTimingSpsSet(ref_dict[timing_key][specName][eq_num], contents[eq_start:eq_stop], timing_dict, ref_eqn_dict[eq_num]["SPECS"].keys())
コード例 #10
0
ファイル: v93k_utils.py プロジェクト: catjake/PythonTools
def _getTimingSpsSet(t_dict, eq_contents, specs_timing_dict, spec_list):
    # spec_hdr_keys = ["specname", "actual", "minimum", "maximum", "units"]
    spec_hdr_keys = ["specname", "actual", "units"]
    eq_g = util.m_re(eq_contents)
    eq_g.grep("[{}]")  #pull out {} blocks, such as SYNC { ..... }
    if eq_g.pattern_count >= 2:
        start_pts,stop_pts = util.find_blocks(eq_g.m_groups, "{", "}")
        i_list = [
            (int(float(eq_g.coordinates[s_a])-2), int(float(eq_g.coordinates[s_b])))
            for s_a,s_b in zip(start_pts, stop_pts)
            ]
        del_indices=[]
        for (x,y) in i_list:
            del_indices += range(x,y)
        eq_contents = [
            eq_contents[i] for i in list(sorted(set(xrange(len(eq_contents))) - set(del_indices)))
            ]
        eq_g = util.m_re(eq_contents)
    else:
        eq_g.clear_cache()
    eq_g.grep(specs_timing_dict["subSections"]) # get all eqnset references with SPECIFICATION block
    t_dict["sub_sections"] = [a_row.split()[0].strip() for a_row in eq_g.m_groups]
    if not util.in_list(t_dict["sub_sections"], "SPECNAME"):
        t_dict["sub_sections"].append("SPECNAME, missing actual # SPECNAME comment")
        eq_g.m_groups.append("# SPECNAME")
        eq_g.coordinates.append("-1.1")
    for a_grp,i in zip(eq_g.m_groups, [int(float(a_num)-1) for a_num in eq_g.coordinates]):
        if not util.in_string(a_grp, "SPECNAME"):
            sub_section_type = a_grp.split()[0].strip()
        else:
            sub_section_type = "SPECS"
        if sub_section_type == "WAVETBL":
            t_dict[sub_section_type] = re.sub("\"", "", a_grp.partition(" ")[-1]).strip()
        elif sub_section_type == "PORT":
            t_dict[sub_section_type] = re.sub("^\s*PORT\s+", "", a_grp).split()
        elif sub_section_type == "SPECS":
            t_dict[sub_section_type] = {}
            # hdr_i = util.find_index(eq_contents, "# SPECNAME\s+\*+ACTUAL")
            # hdr_slices = getSpecHeaderSpan(eq_contents[hdr_i])
            # spec_lines = util.remove_from_list(
            #     [re.sub("\s*#\s*.*$", "", a_row) for a_row in eq_contents[hdr_i+1:]],
            #     "^\s*$"
            # )
            spec_lines = util.keep_in_list(eq_contents, "^\s*(?:{0})\s+".format("|".join(spec_list)))
            for a_line in spec_lines:
                # a_dict = dict([
                #     (a_key, re.sub("[\[\]]", "", a_line[a_slice]).strip())
                #     for a_key,a_slice in zip(spec_hdr_keys,hdr_slices)
                # ])
                spec_name, _dummy, a_string = re.sub("\t","    ",a_line.strip()).partition(" ")
                actual_value,_dummy, a_string = a_string.strip().partition(" ")
                units = None
                u_m = re.search("\[\s*(?P<units>\w+)?\s*\]",a_string)
                if u_m:
                    units = u_m.groupdict()["units"]
                a_dict = {
                    "specname": spec_name,
                    "actual": actual_value,
                    "units": units if not units is None else ""
                }
                key_list = list(set(a_dict.iterkeys()) - {"specname"})
                t_dict[sub_section_type][a_dict["specname"]] = dict([(a_key, a_dict[a_key]) for a_key in key_list])
    pass