diff --git a/src/ucis/report/coverage_report_builder.py b/src/ucis/report/coverage_report_builder.py index 0a01b93..f162ba0 100644 --- a/src/ucis/report/coverage_report_builder.py +++ b/src/ucis/report/coverage_report_builder.py @@ -6,9 +6,12 @@ from ucis.scope_type_t import ScopeTypeT from ucis.report.coverage_report import CoverageReport from ucis.coverpoint import Coverpoint +from ucis.cover_data import CoverData from ucis.cover_type_t import CoverTypeT from math import ceil from ucis.cross import Cross +from ucis.mem.mem_cover_index import MemCoverIndex +from collections import defaultdict class CoverageReportBuilder(object): @@ -32,11 +35,57 @@ def build(db : 'UCIS') ->'CoverageReport': def _build(self)->'CoverageReport': + self.update_coverage() for iscope in self.db.scopes(ScopeTypeT.INSTANCE): self.build_covergroups(iscope) return self.report + def update_coverage(self): + import copy + for inst in self.db.scopes(ScopeTypeT.INSTANCE): + for cg in inst.scopes(ScopeTypeT.COVERGROUP): + cps = dict() + crs = dict() + merged_cps = defaultdict(lambda: defaultdict(lambda: CoverData(CoverTypeT.CVGBIN, 0))) + merged_crs = defaultdict(lambda: defaultdict(lambda: CoverData(CoverTypeT.CVGBIN, 0))) + not_initialized = True + for ci in cg.scopes(ScopeTypeT.COVERINSTANCE): + if ci.getMergeInstances(): + if not_initialized: + for cp in ci.scopes(ScopeTypeT.COVERPOINT): + cp_m = cg.createCoverpoint( + cp.m_name, cp.m_srcinfo, cp.m_weight, cp.m_source) + cps[cp.m_name] = cp_m + for ci_n in cp.coverItems(CoverTypeT.CVGBIN): + cp_m.createNextCover(ci_n.name, copy.copy(ci_n.data), ci_n.srcinfo) + merged_cps[cp.m_name][ci_n.name] = copy.copy(ci_n.getCoverData()) + merged_cps[cp.m_name][ci_n.name].data = 0 + for cr in ci.scopes(ScopeTypeT.CROSS): + cr_m = cg.createCross( + cr.m_name, cr.m_srcinfo, cr.m_weight, cr.m_source, + copy.copy(cr.coverItems)) + crs[cr.m_name] = cr_m + for ci_n in cr.coverItems(CoverTypeT.CVGBIN): + cr_m.createNextCover(ci_n.name, copy.copy(ci_n.data), ci_n.srcinfo) + merged_cps[cr.m_name][ci_n.name] = copy.copy(ci_n.getCoverData()) + merged_cps[cr.m_name][ci_n.name].data = 0 + not_initialized = False + for cp in ci.scopes(ScopeTypeT.COVERPOINT): + for ci_n in cp.coverItems(CoverTypeT.CVGBIN): + merged_cps[cp.m_name][ci_n.name].data+= ci_n.getCoverData().data + for cr in ci.scopes(ScopeTypeT.CROSS): + for ci_n in cr.coverItems(CoverTypeT.CVGBIN): + merged_crs[cr.m_name][ci_n.name].data+= ci_n.getCoverData().data + for cp in cps.values(): + for ci_n in cp.coverItems(CoverTypeT.CVGBIN): + ci_n.data.data = merged_cps[cp.m_name][ci_n.name].data + cp.m_name += " (merged)" + for cr in crs.values(): + for ci_n in cr.coverItems(CoverTypeT.CVGBIN): + ci_n.data.data = merged_crs[cr.m_name][ci_n.name].data + cr.m_name += " (merged)" + def build_covergroups(self, iscope): @@ -65,11 +114,52 @@ def build_covergroup(self, cg_n)->CoverageReport.Covergroup: for cr_in in cg_n.scopes(ScopeTypeT.CROSS): cg_r.crosses.append(self.build_cross(cr_in)) + unmerged_ci = list() for cg_in in cg_n.scopes(ScopeTypeT.COVERINSTANCE): - cg_r.covergroups.append(self.build_covergroup(cg_in)) - + ci = self.build_coverinstance(cg_in) + if cg_in.getPerInstance(): + cg_r.covergroups.append(ci) + if not cg_in.getMergeInstances(): + unmerged_ci.append(ci) # Determine the covergroup coverage coverage = 0.0 + div = 0 + + for cp in cg_r.coverpoints: + if cp.weight > 0: + coverage += cp.coverage * cp.weight + div += cp.weight + + for cr in cg_r.crosses: + if cr.weight > 0: + coverage += cr.coverage * cr.weight + div += cr.weight + + for cg in unmerged_ci: + if cg.weight > 0: + coverage += cg.coverage * cg.weight + div += cg.weight + + if div > 0: coverage /= div + + cg_r.coverage = coverage + + return cg_r + + def build_coverinstance(self, cg_i)->CoverageReport.Covergroup: + cg_r = CoverageReport.Covergroup( + cg_i.getScopeName(), + cg_i.getScopeName()) + + cg_r.weight = cg_i.getWeight() + + for cp_in in cg_i.scopes(ScopeTypeT.COVERPOINT): + cg_r.coverpoints.append(self.build_coverpoint(cp_in)) + + for cr_in in cg_i.scopes(ScopeTypeT.CROSS): + cg_r.crosses.append(self.build_cross(cr_in)) + + coverage = 0.0 div = 0 for cp in cg_r.coverpoints: @@ -156,4 +246,4 @@ def build_cross(self, cr_n : Cross): - \ No newline at end of file + diff --git a/src/ucis/xml/xml_reader.py b/src/ucis/xml/xml_reader.py index fb21318..435d0f1 100644 --- a/src/ucis/xml/xml_reader.py +++ b/src/ucis/xml/xml_reader.py @@ -68,8 +68,8 @@ def read(self, file) -> UCIS: for histN in tree.iter("historyNodes"): self.readHistoryNode(histN) - for instN in tree.iter("instanceCoverages"): - self.readInstanceCoverage(instN) + for instX in tree.iter("instanceCoverages"): + self.readInstanceCoverage(instX) return self.db @@ -114,17 +114,14 @@ def readHistoryNode(self, histN): return ret - def readInstanceCoverage(self, instN): - name = instN.attrib["name"] - stmt_id = None - for stmt_idN in instN.iter("id"): - stmt_id = self.readStatementId(stmt_idN) - + def readInstanceCoverage(self, instX): + name = instX.attrib["name"] + stmt_id = self.readStatementId(instX.find('id')) srcinfo = None # TODO: Creating a coverage instance depends on # having a du_type - module_scope_name = self.getAttr(instN, "moduleName", "default") + module_scope_name = self.getAttr(instX, "moduleName", "default") type_scope = self.getScope( module_scope_name, @@ -137,58 +134,46 @@ def readInstanceCoverage(self, instN): UCIS_OTHER, type_scope) - for cg in instN.iter("covergroupCoverage"): - self.readCovergroup(cg, inst_scope, module_scope_name) + for cgX in instX.iter("covergroupCoverage"): + self.readCovergroup(cgX, inst_scope, module_scope_name) # self.setIntIfEx(instN, ret.setAli, name) - def readCovergroup(self, cg, inst_scope, module_scope_name): - # This entry is for a given covergroup type - - cg_typescope = None - covergroup_scope = None - - instances = [i for i in cg.iter("cgInstance")] - if len(instances) == 1: - cg_typescope = inst_scope.createCovergroup( - self.getAttr(instances[0], "name", "default"), - None, - 1, - UCIS_OTHER) - else: - cg_typescope = inst_scope.createCovergroup( - module_scope_name, None, 1, UCIS_OTHER) + def readCovergroup(self, cgX, inst_scope, module_scope_name): + + cg = inst_scope.createCovergroup( + module_scope_name, None, 1, UCIS_OTHER) - for cgN in instances: + for ciX in cgX.iter("cgInstance"): srcinfo = None - if len(instances) == 1: - covergroup_scope = cg_typescope - else: - covergroup_scope = cg_typescope.createCoverInstance( - self.getAttr(cgN, "name", "default"), - srcinfo, - 1, - UCIS_OTHER) - + ci = cg.createCoverInstance( + self.getAttr(ciX, "name", "default"), + srcinfo, + 1, + UCIS_OTHER) + ciX_options = ciX.find("options") + ci.m_per_instance = self.getAttrBool(ciX_options, 'per_instance') + ci.m_merge_instances = self.getAttrBool(ciX_options, 'merge_instances') + cp_m = {} - for cpN in cgN.iter("coverpoint"): - cp = self.readCoverpoint(cpN, covergroup_scope) - cp_m[self.getAttr(cpN, "name", "default")] = cp + for cpX in ciX.iter("coverpoint"): + cp = self.readCoverpoint(cpX, ci) + cp_m[self.getAttr(cpX, "name", "default")] = cp - for crN in cgN.iter("cross"): - self.readCross(crN, cp_m, covergroup_scope) + for crX in ciX.iter("cross"): + self.readCross(crX, cp_m, ci) - def readCoverpoint(self, cpN, covergroup_scope): + def readCoverpoint(self, cpX, ci): srcinfo = None - cp = covergroup_scope.createCoverpoint( - self.getAttr(cpN, "name", "default"), + cp = ci.createCoverpoint( + self.getAttr(cpX, "name", "default"), srcinfo, 1, # weight UCIS_OTHER) - for cpBin in cpN.iter("coverpointBin"): + for cpBin in cpX.iter("coverpointBin"): self.readCoverpointBin(cpBin, cp) return cp @@ -226,9 +211,9 @@ def readCoverpointBin(self, cpBin : Element, cp): self.getAttr(cpBin, "name", "default"), kind) - def readCross(self, crN, cp_m, covergroup_scope): - crossExpr = next(crN.iter("crossExpr")) - name = self.getAttr(crN, "name", "default") + def readCross(self, crX, cp_m, ci): + crossExpr = next(crX.iter("crossExpr")) + name = self.getAttr(crX, "name", "default") cp_l = [] for cp_n in crossExpr.text.split(','): @@ -240,22 +225,22 @@ def readCross(self, crN, cp_m, covergroup_scope): srcinfo = None - cr = covergroup_scope.createCross( + cr = ci.createCross( name, srcinfo, 1, # weight UCIS_OTHER, cp_l) - for crB in crN.iter("crossBin"): - self.readCrossBin(crB, cr) + for crbX in crX.iter("crossBin"): + self.readCrossBin(crbX, cr) return cr - def readCrossBin(self, crB, cr): - name = self.getAttr(crB, "name", "default") + def readCrossBin(self, crbX, cr): + name = self.getAttr(crbX, "name", "default") srcinfo = None - contentsN = next(crB.iter("contents")) + contentsN = next(crbX.iter("contents")) cr.createBin( name, @@ -265,10 +250,10 @@ def readCrossBin(self, crB, cr): "") # TODO: - def readStatementId(self, stmt_idN): - file_id = int(stmt_idN.attrib["file"]) - line = int(stmt_idN.attrib["line"]) - item = int(stmt_idN.attrib["inlineCount"]) + def readStatementId(self, stmt_idX): + file_id = int(stmt_idX.attrib["file"]) + line = int(stmt_idX.attrib["line"]) + item = int(stmt_idX.attrib["inlineCount"]) file = self.file_m[file_id] return StatementId(file, line, item)