diff options
| author | Rajarshi Das <drajarshi@in.ibm.com> | 2016-09-21 21:55:39 +0530 |
|---|---|---|
| committer | Santosh Sivaraj <santosiv@in.ibm.com> | 2016-12-09 10:48:27 +0530 |
| commit | 33a362c8afa5e72df379e441563bde389bb017f4 (patch) | |
| tree | 8a294e9c6cedf56564d908522f7858a24fe478de | |
| parent | bec99529562b22d8355f18c3c38a478f64eebb37 (diff) | |
| download | ima-catalog-33a362c8afa5e72df379e441563bde389bb017f4.tar.gz ima-catalog-33a362c8afa5e72df379e441563bde389bb017f4.zip | |
Add support to generate DTS file from catalog lid
Also include a readme.
Signed-off-by: Rajarshi Das <drajarshi@in.ibm.com>
Signed-off-by: Santosh Sivaraj <santosh@santosiv@in.ibm.com>
| -rw-r--r-- | README.md | 40 | ||||
| -rw-r--r-- | catalog/catalog.py | 21 | ||||
| -rw-r--r-- | catalog/generate_dts.py | 328 |
3 files changed, 388 insertions, 1 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..b94b815 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +## Catalog generation and dump ## + +### How to ### +In order to generate a new lid: + +``` +$ python read.py v8.lid +``` + +This generates three csv files namely `events.csv`, `groups.csv`, and `formulae.csv`. + +Make changes to these csv files if required and generate the new catalog using +the following command. + +``` +$ python catalog.py <version of the new catalog> <old_lid> <new_file_prefix> +``` +E.g. + +``` +$ python catalog.py 8 v8.lid e8100619_test +``` + +This generates a new lid file named e8100619_test.lid and a new dts file named e8100619_test.dts +using the csv files previously generated. + +Note: Use the same lid file as the old lid (or one which has the same schema) which was used to +generate the csv files. + +--- + +### Revision History ### + +##### v1 ##### + + * Initial catalog generation from CSV files and dumping catalog into CSV files + +#### v2 #### + + * Add support to generate DTS file from the catalog lid diff --git a/catalog/catalog.py b/catalog/catalog.py index cb5e9aa..f1bf056 100644 --- a/catalog/catalog.py +++ b/catalog/catalog.py @@ -1,3 +1,14 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Santosh Sivaraj <santosiv@in.ibm.com> +# Copyright (C) 2016 Rajarshi Das <drajarshi@in.ibm.com> +# Copyright (C) 2016 IBM Corporation +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. + import struct import time import sys @@ -6,6 +17,7 @@ from common import * from events import pack_events from groups import pack_groups from formulae import pack_formulae +from generate_dts import gen_dts def dump_schema(cat_file): f = open(cat_file) @@ -52,14 +64,21 @@ def create_catalog(version, old_lid): if __name__ == "__main__": if len(sys.argv) <= 3: print "Usage: ./%s version old_lid out_file" % (sys.argv[0]) + print "\nThe new LID and DTS files will be named as <out_file>.lid and <out_file>.dts" exit(1) + lid_filename = str(sys.argv[3]) + '.lid' + dts_filename = str(sys.argv[3]) + '.dts' + # get the version for the new build, and older catalog file to extract the # schema data c = create_catalog(int(sys.argv[1]), sys.argv[2]) padlen = 64 - len(c) / PAGE_SIZE c += struct.pack('%dx' % (padlen * PAGE_SIZE)) - f = open(sys.argv[3], 'wt') + f = open(lid_filename, 'wt') f.write(c) f.close() + + # Specify input filename (new lid), verbose flag, and dts output filename + gen_dts(lid_filename, False, dts_filename) diff --git a/catalog/generate_dts.py b/catalog/generate_dts.py new file mode 100644 index 0000000..ec3834b --- /dev/null +++ b/catalog/generate_dts.py @@ -0,0 +1,328 @@ +#!/usr/bin/python +# +# Copyright (C) 2016 Madhavan Srinivasan <maddy@linux.vnet.ibm.com>, IBM +# (C) 2016 Hemant K. Shaw <hemant@linux.vnet.ibm.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. + +import sys, getopt +import string +from struct import * +from collections import namedtuple + +event_domain_1 = [] #Chip IMA events +event_domain_2 = [] #Core IMA event (PDBAR) +event_domain_2_a = [] #Thread IMA event (LDBAR) +event_domain_3 = [] #per-thread PMU events +event_domain_4 = [] #OCC Sensors evenst +group_chip = [] #Chip IMA Group + +nest_units = { + "MCS":0, + "PowerBus":1, + "Pumps_and":1, + "X-link":2, + "A-link":3, + "PHB":4, + "Unknown":5 +} + +nest_unit_names = ["mcs", "powerbus", "xlink", "alink","phb"] + +nest_mcs_scale = "1.2207e-4" +nest_mcs_unit = "MiB" +core_ima_scale = "128" + +pvr_list = ["4D0200"] + +# Filter out the raw (non-ascii) byes +def get_name(st): + res = set(string.printable) + return filter(lambda x: x in res, st) + +class Page0: + def __init__(self, data): + self.page0_format = 'I I Q 16s 32s H H H 2s H H H 2s H H H 2s \ + H H H 2s I I I I I I 8s' + self.page0_str = 'desc len ver build res1 sd_off sd_len sd_cnt\ + res2 ed_off ed_len ed_cnt res3 gd_off\ + gd_len gd_cnt res4 fr_off fr_len fr_cnt\ + res5 coree_off th_off che_off coreg_off\ + thg_off chg_off res6' + self.page0_arr = namedtuple('page0_arr', self.page0_str) + self.page0 = self.page0_arr._make(unpack("> "+self.page0_format, data)) + + def get_events_start(self): + return (self.page0.ed_off * 4096) + + def get_events_count(self): + return (self.page0.ed_cnt) + + def get_group_start(self): + return (self.page0.gd_off * 4096) + + def get_group_count(self): + return (self.page0.gd_cnt) + +class Event: + def __init__(self, fn, offset): + self.offset = offset + self.event_hformat = 'H H B s H H H I H H H' + self.event_str = 'len fr domain res1 st_off ev_len ev_off flag \ + pr_idx grp_cnt ev_name_len' + self.event_arr = namedtuple('event_arr', self.event_str) + fn.seek(0) + fn.seek(self.offset) + self._event = self.event_arr._make(unpack("> "+self.event_hformat, + fn.read(calcsize(self.event_hformat)))) + self._ev_offset = self._event.st_off + self._event.ev_off + self._ev_name_r = fn.read(self._event.ev_name_len - 2) + self._ev_name = get_name(self._ev_name_r) + self._ev_desc_ft = 'H' + self._ev_desc_str = 'len' + self._ev_desc = namedtuple('_ev_desc', self._ev_desc_str) + self._ev_des = self._ev_desc._make(unpack("> "+self._ev_desc_ft, + fn.read(calcsize(self._ev_desc_ft)))) + self._ev_description = fn.read(self._ev_des.len-2) + self._ev_description = get_name(self._ev_description) + self._ev_des_d = self._ev_desc._make(unpack("> "+self._ev_desc_ft, + fn.read(calcsize(self._ev_desc_ft)))) + self._ev_de_desc = fn.read(self._ev_des_d.len) + ev_list = [self._ev_name, self._ev_offset, self._ev_description] + if (self._event.domain == 1): + event_domain_1.append(ev_list) + elif (self._event.domain == 2): + event_domain_2.append(ev_list) + event_domain_2_a.append(ev_list) + elif (self._event.domain == 3): + event_domain_3.append(ev_list) + else: + print "Unknown Domain" + + +class Events: + def __init__(self, fn, offset, cnt): + self.offset = offset + self.cnt = cnt + self.event_hformat = 'H' + self.event_str = 'len' + self.event_arr = namedtuple('event_arr', self.event_str) + for i in range(0, cnt): + fn.seek(0) + fn.seek(self.offset) + self._event = self.event_arr._make(unpack("> "+self.event_hformat, + fn.read(calcsize(self.event_hformat)))) + Event(fn, self.offset) + self.offset += self._event.len + +class Group: + def __init__(self, fn, offset): + self.offset = offset + self.grp_hformat = 'H 2s I B s H H B B HHHHHHHHHHHHHHHH H' + self.grp_str = 'len res1 flag domain res2 sta_off gr_len sc_idx\ + ev_cnt ev_idx0 ev_idx1 ev_idx2 ev_idx3\ + ev_idx4 ev_idx5 ev_idx6 ev_idx7 ev_idx8\ + ev_idx9 ev_idx10 ev_idx11 ev_idx12\ + ev_idx13 ev_idx14 ev_idx15 name_len' + self.grp_arr = namedtuple('grp_arr', self.grp_str) + fn.seek(0) + fn.seek(self.offset) + self._group = self.grp_arr._make(unpack("> "+self.grp_hformat, + fn.read(calcsize(self.grp_hformat)))) + self._grp_name_r = fn.read(self._group.name_len - 2) + self._grp_name = self._grp_name_r.strip("0") + self.dt_index = -1 + for key, value in nest_units.items(): + if self._grp_name.startswith(key): + self.dt_index = value + if ( self.dt_index == -1): + return + + arr = [] + arr.append(self._group.ev_idx0) + arr.append(self._group.ev_idx1) + arr.append(self._group.ev_idx2) + arr.append(self._group.ev_idx3) + arr.append(self._group.ev_idx4) + arr.append(self._group.ev_idx5) + arr.append(self._group.ev_idx6) + arr.append(self._group.ev_idx7) + arr.append(self._group.ev_idx8) + arr.append(self._group.ev_idx9) + arr.append(self._group.ev_idx10) + arr.append(self._group.ev_idx11) + arr.append(self._group.ev_idx12) + arr.append(self._group.ev_idx13) + arr.append(self._group.ev_idx14) + arr.append(self._group.ev_idx15) + + for i in range(0, self._group.ev_cnt): + group_chip[self.dt_index].append(arr[i]) + + +class Groups: + def __init__(self, fn, offset, cnt): + self.offset = offset + self.cnt = cnt + self.group_len = 'H' + self.group_str = 'len' + self.group_arr = namedtuple('group_arr', self.group_str) + for i in range(0, len(nest_units)): + group_chip.append([]) + + for i in range(0, cnt): + fn.seek(0) + fn.seek(self.offset) + self._group = self.group_arr._make(unpack("> "+self.group_len, + fn.read(calcsize(self.group_len)))) + Group(fn, self.offset) + self.offset += self._group.len + + +def dt_event(tabs, name, reg, size, unit, scale, desc): + s = "" + s += '\t' * tabs +'%s@%x {\n'% (name, reg) + s += '\t' * (tabs+1) + 'reg = <0x%x 0x%x>;\n'%(reg,size) + if unit != '' and unit.strip() : + s += '\t' * (tabs+1) + 'unit = "%s" ;\n'%(unit) + if scale != '' and scale.strip() : + s += '\t' * (tabs+1) + 'scale = "%s" ;\n'%(scale) + s += '\t' * (tabs + 1) + 'desc = "%s" ;\n' % (desc) + s += '\t' * tabs + '};' + return s + +def dt_unit(tabs,unit,events, compat): + s = "" + tabs += 1 + s += '\t' * tabs +'%s {\n'% (nest_unit_names[unit]) + tabs += 1 + s += '\t' * tabs + "compatible = \"%s\";\n"%compat + s += '\t' * tabs + "ranges;\n" + s += '\t' * tabs + "#address-cells = <0x1>;\n" + s += '\t' * tabs + "#size-cells = <0x1>;\n\n" + event_scale = '' + event_unit = '' + if nest_unit_names[unit] == "mcs": + event_scale = nest_mcs_scale + event_unit = nest_mcs_unit + for i in events: + event = event_domain_1[i] + s += dt_event((tabs), event[0], event[1], 8, event_unit, + event_scale, event[2]) + s += "\n" + + s += '\t' * (tabs-1) + "};\n" + return s + +def core_ima_dt_unit(tabs, events): + s = "" + tabs += 1 + s += '\t' * tabs + '%s {\n' % ("core_ima") + tabs +=1 + s += '\t' * tabs + "compatble = \"%s\";\n" % "ibm,nest-counters-core-ima" + s += '\t' * tabs + "ranges;\n" + s += '\t' * tabs + "#address-cells = <0x1>;\n" + s += '\t' * tabs + "#size-cells = <0x1>;\n\n" + for i in events: + s += dt_event(tabs, i[0], i[1], 8, '', core_ima_scale, i[2]) + s += "\n" + + s += '\t' * (tabs - 1) + "};\n" + return s + +def thread_ima_dt_unit(tabs, events): + s = "" + tabs += 1 + s += '\t' * tabs + '%s {\n' % ("thread_ima") + tabs +=1 + s += '\t' * tabs + "compatble = \"%s\";\n" % "ibm,nest-counters-thread-ima" + s += '\t' * tabs + "ranges;\n" + s += '\t' * tabs + "#address-cells = <0x1>;\n" + s += '\t' * tabs + "#size-cells = <0x1>;\n\n" + for i in events: + s += dt_event(tabs, i[0], i[1], 8, '', '', i[2]) + s += "\n" + + s += '\t' * (tabs - 1) + "};\n" + return s + + +def gen_dts(ifname, verbose, ofname): + try: + fn = open(ifname, "rb") + except: + print 'Input filename missing. Specify -i <catalog lid file name> and retry.. Exiting.' + exit(-1) + + try: + of = open(ofname, "w") + except: + print 'Output filename missing. Specify -o <output file name> and retry.. Exiting.' + exit(-1) + + # the page0 catalog is 128 bytes long + page0 = Page0(fn.read(128)) + Events(fn, page0.get_events_start(), page0.get_events_count()) + Groups(fn, page0.get_group_start(), page0.get_group_count()) + + s =\ +""" +/dts-v1/; + +/ { +\tname = ""; +\tcompatible = \"ibm,opal-in-memory-counters\"; +\t#address-cells = <0x1>; +\t#size-cells = <0x1>;\n +""" + + for pvr in pvr_list: + pvr_str = '\tpvr@' + pvr + ' {' + pvr_node =\ +""" +\t\t#address-cells = <0x1>; +\t\t#size-cells = <0x1>; +\t\tima-nest-offset = <0x320000>; +\t\tima-nest-size = <0x30000>; +\t\tversion-id = \"\"; +""" + s += pvr_str + s += pvr_node + s += '\t\ttarget-pvr = <0x' + pvr + '>;\n\n' + tabs = 1 + for i in range(len(nest_units)): + if i < len(nest_unit_names): + if (len(group_chip[i])): + s += dt_unit(tabs,i,group_chip[i], "ibm,nest-counters-chip-ima") + s += core_ima_dt_unit(1, event_domain_2) + s += thread_ima_dt_unit(1, event_domain_2_a) + s += "\t};\n" + s += "};\n" + + # print s + + of.write(s) + of.close + +if __name__ == "__main__": + ifname = "" # input file name + ofname = "" # output file name + verbose = False + + options, remainder = getopt.getopt(sys.argv[1:], 'i:vo:', ['input=', + 'verbose', + 'output', + ]) + + for opt, arg in options: + if opt in ('-i', '--input'): + ifname = arg + elif opt in ('-v', '--verbose'): + verbose = True + elif opt in ('-o', '--output'): + ofname = arg + + gen_dts(ifname, verbose, ofname) |

