void sci_errhandler(psci_handle phandle, const char * func, enum sci_err err) { enum sci_err my_sci_err = SCI_SUCCESS; printf("SCILib failure %d in function: %s \n", err, func ); if (NULL != phandle) my_sci_err = sci_close(&phandle); if ( my_sci_err ) exit(-2); else exit (-3); }
/* * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE */ static ACPI_STATUS valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc) { ACPI_STATUS rv; uint32_t result, status, value; rv = sci_open(sc); if (ACPI_FAILURE(rv)) aprint_error_dev(sc->sc_dev, "Cannot open SCI: %s\n", AcpiFormatException(rv)); rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result); if (ACPI_FAILURE(rv)) aprint_error_dev(sc->sc_dev, "Cannot get SCI touchpad status: %s\n", AcpiFormatException(rv)); switch (value) { case HCI_ENABLE: status = HCI_DISABLE; break; case HCI_DISABLE: status = HCI_ENABLE; break; default: status = HCI_ENABLE; break; } rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result); if (ACPI_FAILURE(rv)) aprint_error_dev(sc->sc_dev, "Cannot set SCI touchpad status: %s\n", AcpiFormatException(rv)); rv = sci_close(sc); if (ACPI_FAILURE(rv)) aprint_error_dev(sc->sc_dev, "Cannot close SCI: %s\n", AcpiFormatException(rv)); return rv; }
void sci_killhandler(void) { unsigned int i; if (option_accumulation_type == 1) dump_buffer(); mem_unmap_32k(addr_32k); if (option_nosleep_32k) nosleep_32k_disable(); for (i = 0; i < valid_usecase_cnt; i++) { sci_remove_usecase( psci_hdl, &my_usecase_key[i]); } sci_global_disable(psci_hdl); sci_close(&psci_hdl); powerdm_emu_disable(); }
int statcoll_main(int argc, char **argv) { struct sci_config my_sci_config; enum sci_err my_sci_err; int c, option_index = 0; static int longopt_flag; unsigned int option_delay_us; unsigned int option_overflow_delay_us; unsigned int option_iterations; unsigned int option_disable = 0; unsigned int option_min_addr; unsigned int option_max_addr; unsigned int describe_loop; // Default values of options option_delay_us = 1000000; // 1 second option_overflow_delay_us = 1000000; // 1 second option_overflow_iterations = option_overflow_delay_us / option_delay_us; option_accumulation_type = 2; // dump on terminal option_iterations = 0; // infinite iterations option_overflow_counter_index[0] = 0; // check counter 0 for overflow option_overflow_counter_index[1] = 0; option_overflow_threshold[0] = 0; // reset at each capture option_overflow_threshold[1] = 0; static struct option long_options[] = { /* These options set a flag. */ {"m0", required_argument, &longopt_flag, 'm'}, {"m1", required_argument, &longopt_flag, 'm'}, {"m2", required_argument, &longopt_flag, 'm'}, {"m3", required_argument, &longopt_flag, 'm'}, {"m4", required_argument, &longopt_flag, 'm'}, {"m5", required_argument, &longopt_flag, 'm'}, {"m6", required_argument, &longopt_flag, 'm'}, {"m7", required_argument, &longopt_flag, 'm'}, {"tr0", required_argument, &longopt_flag, 'q'}, {"tr1", required_argument, &longopt_flag, 'q'}, {"tr2", required_argument, &longopt_flag, 'q'}, {"tr3", required_argument, &longopt_flag, 'q'}, {"tr4", required_argument, &longopt_flag, 'q'}, {"tr5", required_argument, &longopt_flag, 'q'}, {"tr", required_argument, &longopt_flag, 'q'}, {"p0", required_argument, &longopt_flag, 'p'}, {"p1", required_argument, &longopt_flag, 'p'}, {"p2", required_argument, &longopt_flag, 'p'}, {"p3", required_argument, &longopt_flag, 'p'}, {"p4", required_argument, &longopt_flag, 'p'}, {"p5", required_argument, &longopt_flag, 'p'}, {"p6", required_argument, &longopt_flag, 'p'}, {"p7", required_argument, &longopt_flag, 'p'}, {"allcounters", no_argument, &longopt_flag, '8'}, {"overflow_delay", required_argument, &longopt_flag, '1'}, {0, 0, 0, 0} }; while ((c = getopt_long (argc, argv, "hnm:d:a:i:o:t:r:p:q:D", long_options, &option_index)) != -1) { // small trick to merge long options with short options of same doaain (-m and --m0 --m1 ...) unsigned int long_opt = 0; if (c == 0) { long_opt = 1; c = long_options[option_index].val; } switch (c) { case 'h': { unsigned int loop = 0; printf("\n\tomapconf trace bw [-h] [<-m | --m<x>> <0xyy | ma_mpu | alldmm | dss | iva | ...>] [<-p | --p<x> <emif1 | emif2>] [<--tr | --tr<x>> <r|w|r+w>] [-d x] [--overflow_delay x] [-a 1 or 2] [-i x] [-o x -t y] [-r 0xaaaaaaaa-0xbbbbbbbb] [-n]\n"); printf("\n\t-m, -p, -q sets all 8 counters while -m0, --p0, --q0 to --m7, --tr7, --p5 set 1 counter only\n"); printf("\n\t-m <0xyy | ma_mpu | alldmm | dss | iva | ...> (MA_MPU_1_2 deprecated)\n"); printf("\t\tMaster initiator monitored. WARNING: All DMM traffic includes DSS, IVA, GPU, ... but not MA_MPU, which requires parallel monitoring \n"); printf("\t\tma_mpu (MA_MPU_1_2 deprecated) - Non DMM MPU memory traffic, see Examples\n"); while (match_master[loop].name != NULL) { printf("\t\t%s 0x%x\n", match_master[loop].name, match_master[loop].value); loop++; } printf("\n\t-d xxx or 0.xx\n"); printf("\t\tDelay in ms between 2 captures, can be float\n"); printf("\n\t--overflow_delay xxx or 0.xx\n"); printf("\t\tDelay in ms after which HW IP is reset to avoid overflow. Disables -o -t options. Can be float.\n"); printf("\n\t-p <emif1 | emif2> or --p<x> <emif1 | emif2>\n"); printf("\t\tProbed channel. 1 counter can monitor only EMIF1 or EMIF2\n"); printf("\n\t--tr <r|w|r+w> or --tr<x> <r|w|r+w>\n"); printf("\t\tTransaction qualifier. Rd or Wr or Rd+Wr monitoring. HW implementation prevents changing this on last 2 counters\n"); printf("\n\t-a 1 or 2\n"); printf("\t\taccumulation type. 2: dump at every capture. 1: dump only at end\n"); printf("\n\t-i x\n"); printf("\t\tnumber of iterations (for -a 1). You can Ctrl-C during test, current captures will be displayed\n"); printf("\n\t-o x -t y \n"); printf("\t\tindex for overflow handling + threshold to reset HW. Disables auto-reset of HW IP based on time (--overflow_delay). You MUST use them for -a 1\n"); printf("\t\tUse this option twice to set 2 different thresholds on 2 different counters\n"); printf("\n\t-r 0xaa-0xbb\n"); printf("\t\taddress filtering, like 0x9b000000-0x9f000000\n"); printf("\n\t-n\n"); printf("\t\tno sleep of 32kHz (work-around for 32kHz reading HW bug). MANDATORY for OMAP5 until fix is found\n"); printf("\n\t-D\n"); printf("\t\tdisable statcol (deprecated)\n"); printf("\n\tExamples:\n"); printf("\tDefault: --p7 emif2 (this forces use of 8 counters and counter 7 is using emif2 as default probed channel)\n"); printf("\t\tCounter: 0 Master: alldmm Transaction: w Probe: emif1\n"); printf("\t\tCounter: 1 Master: alldmm Transaction: w Probe: emif2\n"); printf("\t\tCounter: 2 Master: alldmm Transaction: r Probe: emif1\n"); printf("\t\tCounter: 3 Master: alldmm Transaction: r Probe: emif2\n"); printf("\t\tCounter: 4 Master: alldmm Transaction: w Probe: emif1\n"); printf("\t\tCounter: 5 Master: alldmm Transaction: w Probe: emif2\n"); printf("\t\tCounter: 6 Master: alldmm Transaction: r+w Probe: emif1\n"); printf("\t\tCounter: 7 Master: alldmm Transaction: r+w Probe: emif2\n"); printf("\n\t-m 0x70 -d 1000 -a 2 (often used as -m 0x70 only)\n"); printf("\t\taccumulation 2 is reading of registers and tracing them immediately\n"); printf("\t\tFormat is time: time_start time_end delta_time -> Wr_DMM_EMIF1 Wr_DMM_EMIF2 Rd_DMM_EMIF1 Rd_DMM_EMIF2 (MB/s)\n"); printf("\n\t-m dss -d 0.3 -a 1 -i 40000 -o 2 -t 3000000000\n"); printf("\t\taccumulation 1 is reading of registers and storing in RAM. Result is dumped at the end with CCS format to reuse\n"); printf("\t\texisting post-processing. So you must set iterations. Overflow is taken into account. Suits small delays\n"); printf("\n\t-m MA_MPU -d 1000 -a 2 --overflow_delay 500\n"); printf("\t\tMA_MPU is MPU memory adaptor, a direct path to EMIF. MA_MPU will display:\n"); printf("\t\tWr_MA_MPU_EMIF1 Wr_MA_MPU_EMIF2 Rd_MA_MPU_EMIF Rd_MA_MPU_EMIF2 (MB/s)\n"); printf("\n\t--tr r+w -p emif1 --m0 ma_mpu --m1 ma_mpu --tr1 w --p1 emif2 --m2 gpu_p1 --m3 dss --m4 alldmm --m5 alldmm --p5 emif2\n"); printf("\t\tCounter: 0 Master: ma_mpu Transaction: r+w Probe: emif1\n"); printf("\t\tCounter: 1 Master: ma_mpu Transaction: w Probe: emif2\n"); printf("\t\tCounter: 2 Master: gpu_p1 Transaction: r+w Probe: emif1\n"); printf("\t\tCounter: 3 Master: dss Transaction: r+w Probe: emif1\n"); printf("\t\tCounter: 4 Master: alldmm Transaction: r+w Probe: emif1\n"); printf("\t\tCounter: 5 Master: alldmm Transaction: r+w Probe: emif2\n"); printf("\n\t2 masters + all traffic on EMIF1 and EMIF2: --tr r+w --m0 dss --m1 dss --m2 iva --m3 iva --m6 ma_mpu --m7 ma_mpu\n"); printf("\tNote that you can monitor more masters if you have identified earlier that traffic is well balanced over EMIF1 and EMIF2, i.e. traffic for this master = 2 * EMIF1 = 2 * EMIF2\n"); printf("\n\tDefault settings:\n"); printf("\t\t-m 0xcd -d 1000 -a 2 -i 0 --overflow_delay 1000\n"); printf("\t\tall initiators, 1000ms delay, accumulation 2, infinite iterations, auto-reset IP after 1 s, i.e. always stop/restart HW IP after 1 capture\n"); printf("\n\tPost-processing (for -a 1):\n"); printf("\t\tgit clone git://gitorious.tif.ti.com/omap-video-perf/runperf.git, instrumentation/bandwidth/BWstats_ccsv5.py\n"); printf("\t\tpython-matplotlib is needed\n"); printf("\n\tWiki:\n"); printf("\t\t<http://opbuwiki.dal.design.ti.com/index.php/L3_bus_monitoring_SW_tool>\n\n"); //sci_global_disable(psci_hdl); //sci_close(&psci_hdl); return 0; } case 'm': { unsigned int index; if (long_opt == 1) { index = long_options[option_index].name[1] - '0'; // go up to 6 couhters if ((index + 1) > num_use_cases) num_use_cases = index + 1; } if (!strstr(optarg, "ma_mpu")) { unsigned int loop = 0; if (strstr(optarg, "0x")) { unsigned int a; sscanf(optarg, "%x", &a); while (match_master[loop].name != NULL) { if (match_master[loop].value == a) break; loop++; } } else { while (match_master[loop].name != NULL) { if (!strcmp(match_master[loop].name, optarg)) break; loop++; } } if (match_master[loop].name != NULL) { if (long_opt == 1) { pmy_cfg[index]->filter[0].mstr_addr_match = match_master[loop].value; if (pmy_cfg[index]->probe_id == SCI_MA_MPU_P1) pmy_cfg[index]->probe_id = SCI_EMIF1; if (pmy_cfg[index]->probe_id == SCI_MA_MPU_P2) pmy_cfg[index]->probe_id = SCI_EMIF2; } else { unsigned int i; for (i = 0; i < sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); i++) { pmy_cfg[i]->filter[0].mstr_addr_match = match_master[loop].value; if (pmy_cfg[i]->probe_id == SCI_MA_MPU_P1) pmy_cfg[i]->probe_id = SCI_EMIF1; if (pmy_cfg[i]->probe_id == SCI_MA_MPU_P2) pmy_cfg[i]->probe_id = SCI_EMIF2; } } } // parsing error else { printf("ERROR: %s option of -m is not recognized\n", optarg); goto END; } } else if ( (!strcmp(optarg, "ma_mpu_1_2")) && (long_opt == 0) ) { my_config_emif1.probe_id = SCI_MA_MPU_P1; my_config_emif1.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif2.probe_id = SCI_MA_MPU_P2; my_config_emif2.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif3.probe_id = SCI_MA_MPU_P1; my_config_emif3.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif4.probe_id = SCI_MA_MPU_P2; my_config_emif5.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif5.probe_id = SCI_MA_MPU_P1; my_config_emif6.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif6.probe_id = SCI_MA_MPU_P2; my_config_emif6.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif7.probe_id = SCI_MA_MPU_P1; my_config_emif7.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif8.probe_id = SCI_MA_MPU_P2; my_config_emif8.filter[0].mstr_addr_match = SCI_MASTID_ALL; } else if (!strcmp(optarg, "ma_mpu")) { if (long_opt == 1) { pmy_cfg[index]->filter[0].mstr_addr_match = SCI_MASTID_ALL; if (pmy_cfg[index]->probe_id == SCI_EMIF1) pmy_cfg[index]->probe_id = SCI_MA_MPU_P1; if (pmy_cfg[index]->probe_id == SCI_EMIF2) pmy_cfg[index]->probe_id = SCI_MA_MPU_P2; } else { unsigned int i; for (i = 0; i < sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); i++) { pmy_cfg[i]->filter[0].mstr_addr_match = SCI_MASTID_ALL; if (pmy_cfg[i]->probe_id == SCI_EMIF1) pmy_cfg[i]->probe_id = SCI_MA_MPU_P1; if (pmy_cfg[i]->probe_id == SCI_EMIF2) pmy_cfg[i]->probe_id = SCI_MA_MPU_P2; } } } else { printf("ERROR: %s option of -m is not recognized\n", optarg); goto END; } } break; case 'q': { unsigned int loop = 0; unsigned int index; if (!strcmp(long_options[option_index].name, "tr")) long_opt = 0; if (long_opt == 1) { index = long_options[option_index].name[2] - '0'; // go up to 6 couhters if ((index + 1) > num_use_cases) num_use_cases = index + 1; } while (match_qualifier[loop].name != NULL) { if (!strcmp(match_qualifier[loop].name, optarg)) break; loop++; } if (match_qualifier[loop].name != NULL) { if (long_opt == 1) { pmy_cfg[index]->filter[0].trans_qual = match_qualifier[loop].value; } else { unsigned int i; for (i = 0; i < sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); i++) { pmy_cfg[i]->filter[0].trans_qual = match_qualifier[loop].value; } } } else { printf("ERROR: %s option of -q/--qx not recognized\n", optarg); goto END; } } break; case 'p': { unsigned int loop = 0; unsigned int index; if (long_opt == 1) { index = long_options[option_index].name[1] - '0'; // go up to 6 couhters if ((index + 1) > num_use_cases) num_use_cases = index + 1; } while (match_probe[loop].name != NULL) { if (!strcmp(match_probe[loop].name, optarg)) break; loop++; } if (match_probe[loop].name != NULL) { if (long_opt == 1) { if (pmy_cfg[index]->probe_id == SCI_MA_MPU_P1) { if (match_probe[loop].value == SCI_EMIF2) pmy_cfg[index]->probe_id = SCI_MA_MPU_P2; } else if (pmy_cfg[index]->probe_id == SCI_MA_MPU_P2) { if (match_probe[loop].value == SCI_EMIF1) pmy_cfg[index]->probe_id = SCI_MA_MPU_P1; } else if (pmy_cfg[index]->probe_id != SCI_MA_MPU_P1 && pmy_cfg[index]->probe_id != SCI_MA_MPU_P2) { pmy_cfg[index]->probe_id = match_probe[loop].value; } } else { unsigned int i; for (i = 0; i < sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); i++) { if ( (pmy_cfg[i]->probe_id == SCI_MA_MPU_P1) && (match_probe[loop].value == SCI_EMIF2) ) pmy_cfg[i]->probe_id = SCI_MA_MPU_P2; else if ( (pmy_cfg[i]->probe_id == SCI_MA_MPU_P2) && (match_probe[loop].value == SCI_EMIF1) ) pmy_cfg[i]->probe_id = SCI_MA_MPU_P1; else if (pmy_cfg[index]->probe_id != SCI_MA_MPU_P1 && pmy_cfg[index]->probe_id != SCI_MA_MPU_P2) pmy_cfg[i]->probe_id = match_probe[loop].value; } } } else { printf("ERROR: %s option of -p/--px not recognized\n", optarg); goto END; } } break; case 'd': { float a; if ( (sscanf(optarg, "%f", &a) > 0) && (a > 0)) option_delay_us = a * 1000; else { printf("ERROR: %s option of -d not recognized or wrong\n", optarg); goto END; } if (option_overflow_iterations > 0) option_overflow_iterations = option_overflow_delay_us / option_delay_us; } break; case 'a': sscanf(optarg, "%u", &option_accumulation_type); if ((option_accumulation_type != 1) && (option_accumulation_type != 2)) { printf("ERROR: %s option of -a not recognized or wrong\n", optarg); goto END; } break; case 'i': if (sscanf(optarg, "%u", &option_iterations) == 0) { printf("ERROR: %s option of -i not recognized\n", optarg); goto END; } break; case 'o': { static unsigned int o_count = 0; unsigned int result; if ((sscanf(optarg, "%u", &result) == 0) || (result > 7)) { printf("ERROR: %s option of -o not recognized or too high\n", optarg); goto END; } option_overflow_counter_index[1] = result; if (o_count++ == 0) option_overflow_counter_index[0] = result; option_overflow_delay_us = 0; option_overflow_iterations = 0; } break; case 't': { static unsigned int t_count = 0; unsigned int result; if (sscanf(optarg, "%u", &result) == 0) { printf("ERROR: %s option of -t not recognized\n", optarg); goto END; } option_overflow_threshold[1] = result; if (t_count++ == 0) option_overflow_threshold[0] = result; option_overflow_delay_us = 0; option_overflow_iterations = 0; } break; case 'n': option_nosleep_32k = 1; break; case '8': num_use_cases = sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); break; case '1': { float a; if ( (sscanf(optarg, "%f", &a) > 0) && (a > 0)) { option_overflow_delay_us = a * 1000; option_overflow_iterations = option_overflow_delay_us / option_delay_us; } else { printf("ERROR: %s option of --overflow_delay not recognized or wrong\n", optarg); goto END; } } break; case 'r': sscanf(optarg, "0x%x-0x%x", &option_min_addr, &option_max_addr); my_config_emif1.addr_filter_min = option_min_addr; my_config_emif2.addr_filter_min = option_min_addr; my_config_emif3.addr_filter_min = option_min_addr; my_config_emif4.addr_filter_min = option_min_addr; my_config_emif5.addr_filter_min = option_min_addr; my_config_emif6.addr_filter_min = option_min_addr; my_config_emif1.addr_filter_max = option_max_addr; my_config_emif2.addr_filter_max = option_max_addr; my_config_emif3.addr_filter_max = option_max_addr; my_config_emif4.addr_filter_max = option_max_addr; my_config_emif5.addr_filter_max = option_max_addr; my_config_emif6.addr_filter_max = option_max_addr; my_config_emif1.addr_filter_enable = true; my_config_emif2.addr_filter_enable = true; my_config_emif3.addr_filter_enable = true; my_config_emif4.addr_filter_enable = true; my_config_emif5.addr_filter_enable = true; my_config_emif6.addr_filter_enable = true; break; case 'D': option_disable = 1; default: printf("ERROR: Unknown option\n"); goto END; } } // Error checking, are there still elements ? if (optind < argc) { printf ("ERROR: non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); putchar ('\n'); goto END; } // Even if above chhanges config of counter 7 and 8, we restore default as they can't filter my_config_emif7.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif7.filter[0].trans_qual = SCI_RD_OR_WR_DONTCARE; my_config_emif8.filter[0].mstr_addr_match = SCI_MASTID_ALL; my_config_emif8.filter[0].trans_qual = SCI_RD_OR_WR_DONTCARE; // Describe configuration of counters in human readable format for (describe_loop = 0; describe_loop < num_use_cases; describe_loop++) { unsigned int a, b, c; char *a_name, *b_name, *c_name; unsigned int loop = 0, loop_transaction = 0; a = pmy_cfg[describe_loop]->filter[0].mstr_addr_match; b = pmy_cfg[describe_loop]->filter[0].trans_qual; c = pmy_cfg[describe_loop]->probe_id; while (match_probe[loop].name != NULL) { if (match_probe[loop].value == c) break; loop++; } if (match_probe[loop].name != NULL) { c_name = match_probe[loop].name; strcpy(msg[describe_loop], match_probe[loop].name_ccs); strcpy(msg_overflow[describe_loop], match_probe[loop].name_ccs); } else { c_name = "ERROR"; strcpy(msg[describe_loop], "ERROR"); strcpy(msg_overflow[describe_loop], "ERROR"); } loop_transaction = 0; while (match_qualifier[loop_transaction].name != NULL) { if (match_qualifier[loop_transaction].value == b) break; loop_transaction++; } if (match_qualifier[loop_transaction].name != NULL) { char temp[20]; b_name = match_qualifier[loop_transaction].name; sprintf(temp, ":%s:", match_qualifier[loop_transaction].name_ccs); strcat(msg[describe_loop], temp); sprintf(temp, ":%s:", match_qualifier[loop_transaction].name); strcat(msg_overflow[describe_loop], temp); } else { b_name = "ERROR"; strcat(msg[describe_loop], ":ERROR:"); strcat(msg_overflow[describe_loop], ":ERROR:"); } loop = 0; while (match_master[loop].name != NULL) { if (match_master[loop].value == a) break; loop++; } if (match_master[loop].name != NULL) { a_name = match_master[loop].name; strcat(msg[describe_loop], match_master[loop].name_ccs); strcat(msg_overflow[describe_loop], match_master[loop].name_ccs); } else { a_name = "ERROR"; strcat(msg[describe_loop], "ERROR"); strcat(msg_overflow[describe_loop], "ERROR"); } if ( (pmy_cfg[describe_loop]->filter[0].mstr_addr_match == SCI_MASTID_ALL) && (pmy_cfg[describe_loop]->probe_id == SCI_MA_MPU_P1)) { printf("Counter: %d Master: ma_mpu Transaction: %s Probe: emif1\n", describe_loop, b_name); sprintf(msg[describe_loop], "EMIF 0:%s:MA_MPU", match_qualifier[loop_transaction].name_ccs); sprintf(msg_overflow[describe_loop], "EMIF 0:%s:MA_MPU", match_qualifier[loop_transaction].name); continue; } if ( (pmy_cfg[describe_loop]->filter[0].mstr_addr_match == SCI_MASTID_ALL) && (pmy_cfg[describe_loop]->probe_id == SCI_MA_MPU_P2)) { printf("Counter: %d Master: ma_mpu Transaction: %s Probe: emif2\n", describe_loop, b_name); sprintf(msg[describe_loop], "EMIF 1:%s:MA_MPU", match_qualifier[loop_transaction].name_ccs); sprintf(msg_overflow[describe_loop], "EMIF 1:%s:MA_MPU", match_qualifier[loop_transaction].name); continue; } printf("Counter: %d Master: %s Transaction: %s Probe: %s\n", describe_loop, a_name, b_name, c_name); } printf("delay in us: %u\n", option_delay_us); if (option_overflow_iterations > 0) printf("overflow delay in us: %u (iterations=%u)\n", option_overflow_delay_us, option_overflow_iterations); else printf("overflow delay in us: DISABLED (-o -t used)\n"); printf("accumulation type: %u\n", option_accumulation_type); printf("iterations (0=infinite): %u\n", option_iterations); if (option_overflow_iterations == 0) { printf("Overflow counter index: %u %u\n", option_overflow_counter_index[0], option_overflow_counter_index[1]); printf("Overflow threshold: %u %u\n", option_overflow_threshold[0], option_overflow_threshold[1]); } else { printf("Overflow counter index: DISABLED (overflow delay used)\n"); printf("Overflow threshold: DISABLED (overflow delay used)\n"); } if (option_iterations > MAX_ITERATIONS) { option_iterations = MAX_ITERATIONS; printf("WARNING: MAX_ITERATIONS(%d) exceeded\n", option_iterations); } powerdm_emu_enable(); ///////////////////////////////////////////////////// //Make sure DebugSS is powered up and enabled // ///////////////////////////////////////////////////// my_sci_config.errhandler = sci_errhandler; my_sci_config.data_options = 0; //Disable options my_sci_config.trigger_enable = false; my_sci_config.sdram_msg_rate = 1; my_sci_config.mstr_msg_rate = 1; my_sci_config.mode = SCI_MODE_DUMP; addr_32k = mem_map_32k(); my_sci_err = sci_open(&psci_hdl, &my_sci_config); if (SCI_SUCCESS != my_sci_err) exit(-1); { uint32_t plib_major_ver; uint32_t plib_minor_ver; uint32_t plib_func_id; uint32_t pmod_func_id; sci_get_version(psci_hdl, &plib_major_ver, &plib_minor_ver, &plib_func_id, &pmod_func_id ); if ( plib_func_id != pmod_func_id ) { printf ("Error - func missmatch with device %d %d\n", plib_func_id, pmod_func_id); sci_close(&psci_hdl); powerdm_emu_disable(); exit(-1); } } // Test { unsigned int i, j; for (i = 0; i < num_use_cases; i++) { my_sci_err = sci_reg_usecase_sdram(psci_hdl, pmy_cfg[i], &my_usecase_key[i] ); if ( SCI_SUCCESS != my_sci_err) break; valid_usecase_cnt++; } /* If you kill the process, statcoll is left running. this is an option to disable it. We should intercept and handle signal */ if (option_disable == 1) { sci_global_disable(psci_hdl); sci_close(&psci_hdl); return 0; } /* And this is an ugly hack to disable it so that it will reset counters at enable */ sci_global_disable(psci_hdl); if (option_nosleep_32k) nosleep_32k_enable(); if (valid_usecase_cnt == num_use_cases) { uint32_t *counters_current = counters; unsigned int tests_overflow = 1; if (option_accumulation_type == 1) { for (tests = 0; tests < (option_iterations * 9); tests++) counters[tests] = 0; my_sci_err = sci_global_enable(psci_hdl); for (tests = 0; tests < option_iterations; tests++) { usleep(option_delay_us); *(counters_current + TIMESTAMP_INDEX) = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + COUNTER_INDEX); if ( ( (option_overflow_iterations > 0) && (tests_overflow > option_overflow_iterations) ) || ( (option_overflow_iterations == 0) && ( (*(counters_current + COUNTER_INDEX + option_overflow_counter_index[0]) >= option_overflow_threshold[0]) || (*(counters_current + COUNTER_INDEX + option_overflow_counter_index[1]) >= option_overflow_threshold[1]) ) ) ) { sci_global_disable(psci_hdl); sci_global_enable(psci_hdl); counters_current += SAMPLE_SIZE; *(counters_current + TIMESTAMP_INDEX) = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + COUNTER_INDEX); tests++; tests_overflow = 1; //printf("overflow %u\n", *counters_current - counters[0]); } counters_current += SAMPLE_SIZE; tests_overflow++; } } else { uint32_t *counters_prev; uint32_t *counters_overflow; unsigned int overflow_on; uint32_t delta_time; unsigned int tests_overflow = 1; for (i = 0; i < sizeof(counters)/4; i++) counters[i] = 0; counters_prev = counters; counters_current = counters + SAMPLE_SIZE; counters_overflow = counters + 2 * SAMPLE_SIZE; sci_global_enable(psci_hdl); *(counters_prev + TIMESTAMP_INDEX) = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_prev + COUNTER_INDEX); for (;;) { tests_overflow++; usleep(option_delay_us); *(counters_current + TIMESTAMP_INDEX) = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + COUNTER_INDEX); if ( ( (option_overflow_iterations > 0) && (tests_overflow > option_overflow_iterations) ) || ( (option_overflow_iterations == 0) && ( (*(counters_current + COUNTER_INDEX + option_overflow_counter_index[0]) >= option_overflow_threshold[0]) || (*(counters_current + COUNTER_INDEX + option_overflow_counter_index[1]) >= option_overflow_threshold[1]) ) ) ) { sci_global_disable(psci_hdl); sci_global_enable(psci_hdl); *(counters_overflow + TIMESTAMP_INDEX) = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_overflow + COUNTER_INDEX); overflow_on = 1; tests_overflow = 1; } /* trace current - prev */ delta_time = *(counters_current + TIMESTAMP_INDEX) - *(counters_prev + TIMESTAMP_INDEX); printf("time: %u %u %u -> ", *(counters_current + TIMESTAMP_INDEX), *(counters_prev + TIMESTAMP_INDEX), delta_time); for (j = 0; j < num_use_cases; j++) { printf("%.2f ", ((float)(*(counters_current + COUNTER_INDEX + j) - *(counters_prev + COUNTER_INDEX + j))/1000000)*32768.0/delta_time); } printf("\n"); for (j = 0; j < num_use_cases; j++) { if (*(counters_current + COUNTER_INDEX + j) == 0xFFFFFFFF) { fprintf(stderr, "ERROR: counter %d %s overflowed at time %u, don't trust results\n", j, msg[j], *(counters_current + TIMESTAMP_INDEX)); printf("ERROR: counter %d %s overflowed at time %u, don't trust results\n", j, msg[j], *(counters_current + TIMESTAMP_INDEX)); } } /* pointers increment */ if (overflow_on == 1) { overflow_on = 0; counters_current = counters_overflow; } // offset all pointers by 1 sample counters_prev = counters_current; if ((unsigned int)(counters_current - counters) == (2 * SAMPLE_SIZE)) counters_current = counters; else counters_current += SAMPLE_SIZE; counters_overflow = counters_current; if ((unsigned int)(counters_overflow - counters) == (2 * SAMPLE_SIZE)) counters_overflow = counters; else counters_overflow += SAMPLE_SIZE; } } } else { printf(" SCI Lib Error %d\n", my_sci_err); } } sci_killhandler(); END: exit(0); }
int statcoll_main(int argc, char **argv) { struct sci_config my_sci_config; enum sci_err my_sci_err; int c; unsigned int delay_us; unsigned int iterations; unsigned int overflow_threshold; unsigned int disable = 0; unsigned int min_addr; unsigned int max_addr; delay_us = 1000000; accumulation_type = 2; iterations = 0; overflow_counter_index = 1; overflow_threshold = 0; while ((c = getopt (argc, argv, "hnm:d:a:i:o:t:r:D")) != -1) { switch (c) { case 'h': printf("\n\tomapconf trace bw [-h] [-m 0xyy or MA_MPU_1_2] [-d x] [-a 1 or 2] [-i x] [-o x -t y] [-r 0xaaaaaaaa-0xbbbbbbbb] [-n]\n"); printf("\n\t-m 0xaa or MA_MPU_1_2\n"); printf("\t\tMaster initiator\n"); printf("\t\tMA_MPU_1_2 - Non DMM MPU memory traffic, see Examples\n"); printf("\t\tSCI_MASTID_ALL 0x%x\n", SCI_MASTID_ALL); printf("\t\tSCI_MSTID_MPUSS 0x%x\n",SCI_MSTID_MPUSS ); printf("\t\tSCI_MSTID_DAP 0x%x\n", SCI_MSTID_DAP); printf("\t\tSCI_MSTID_DSP 0x%x\n", SCI_MSTID_DSP); printf("\t\tSCI_MSTID_IVA 0x%x\n", SCI_MSTID_IVA); printf("\t\tSCI_MSTID_ISS 0x%x\n", SCI_MSTID_ISS); printf("\t\tSCI_MSTID_IPU 0x%x\n", SCI_MSTID_IPU); printf("\t\tSCI_MSTID_FDIF 0x%x\n", SCI_MSTID_FDIF); printf("\t\tSCI_MSTID_SDMA_RD 0x%x\n", SCI_MSTID_SDMA_RD); printf("\t\tSCI_MSTID_SDMA_WR 0x%x\n", SCI_MSTID_SDMA_WR); printf("\t\tSCI_MSTID_GPU_P1 0x%x\n", SCI_MSTID_GPU_P1); printf("\t\tSCI_MSTID_GPU_P2 0x%x\n", SCI_MSTID_GPU_P2); printf("\t\tSCI_MSTID_BB2D_P1 0x%x (GC320)\n", SCI_MSTID_BB2D_P1); printf("\t\tSCI_MSTID_BB2D_P2 0x%x (GC320)\n", SCI_MSTID_BB2D_P2); printf("\t\tSCI_MSTID_DSS 0x%x\n", SCI_MSTID_DSS); printf("\t\tSCI_MSTID_C2C 0x%x\n", SCI_MSTID_C2C); printf("\t\tSCI_MSTID_LLI 0x%x\n", SCI_MSTID_LLI); printf("\t\tSCI_MSTID_HSI 0x%x\n", SCI_MSTID_HSI); printf("\t\tSCI_MSTID_UNIPRO1 0x%x\n", SCI_MSTID_UNIPRO1); printf("\t\tSCI_MSTID_UNIPRO2 0x%x\n", SCI_MSTID_UNIPRO2); printf("\t\tSCI_MSTID_MMC1 0x%x\n", SCI_MSTID_MMC1); printf("\t\tSCI_MSTID_MMC2 0x%x\n", SCI_MSTID_MMC2); printf("\t\tSCI_MSTID_SATA 0x%x\n", SCI_MSTID_SATA); printf("\t\tSCI_MSTID_USB_HOST_HS 0x%x\n", SCI_MSTID_USB_HOST_HS); printf("\t\tSCI_MSTID_USB_OTG_HS 0x%x\n", SCI_MSTID_USB_OTG_HS); printf("\n\t-d xxx or 0.xx\n"); printf("\t\tDelay in ms between 2 captures, can be float\n"); printf("\n\t-a 1 or 2\n"); printf("\t\taccumulation type. 2: dump at every capture. 1: dump only at end\n"); printf("\n\t-i x\n"); printf("\t\tnumber of iterations (for -a 1). You can Ctrl-C during test, current captures will be displayed\n"); printf("\n\t-o x -t y \n"); printf("\t\tindex for overflow handling (0=Wr_EMIF0,1=Wr_EMIF1,2=Rd_EMIF0,3=Rd_EMIF1) + threshold to reset HW. You must use them for -a 1\n"); printf("\n\t-r 0xaa-0xbb\n"); printf("\t\taddress filtering, like 0x9b000000-0x9f000000\n"); printf("\n\t-n\n"); printf("\t\tno sleep of 32kHz (work-around for 32kHz reading HW bug). MANDATORY for OMAP5 until fix is found\n"); printf("\n\t-D\n"); printf("\t\tdisable statcol (deprecated)\n"); printf("\n\tExamples:\n"); printf("\t-m 0x70 -d 0.3 -a 1 -i 40000 -o 2 -t 3000000000\n"); printf("\t\taccumulation 1 is reading of registers and storing in RAM. Result is dumped at the end with CCS format to reuse\n"); printf("\t\texisting post-processing. So you must set iterations. Overflow is taken into account. Suits small delays\n"); printf("\n\t-m 0x70 -d 1000 -a 2 -o 2 -t 3000000000 (often used as -m 0x70 only)\n"); printf("\t\taccumulation 2 is reading of registers and tracing them immediately\n"); printf("\t\tFormat is time: time_start time_end delta_time -> Wr_EMIF0 Wr_EMIF1 Rd_EMIF0 Rd_EMIF1 (MB/s)\n"); printf("\n\t-m MA_MPU_1_2 -d 1000 -a 2 -o 2 -t 3000000000\n"); printf("\t\tMA_MPU is MPU memory adaptor, a direct path to EMIF. There are 2 MA. MA_MPU_1_2 will display:\n"); printf("\t\tWr_MA_MPU_1 Wr_MA_MPU_2 Rd_MA_MPU_1 Rd_MA_MPU_2 (MB/s)\n"); printf("\n\tDefault settings:\n"); printf("\t\t-m 0xcd -d 1000 -a 2 -i 0 -o 0 -t 0\n"); printf("\t\tall initiators, 1000ms delay, accumulation 2, infinite iterations, overflow on counter 0, threshold=0 i.e. always stop/restart HW IP after 1 capture\n"); printf("\n\tPost-processing (for -a 1):\n"); printf("\t\tgit clone git://gitorious.tif.ti.com/omap-video-perf/runperf.git, instrumentation/bandwidth/BWstats_ccsv5.py\n"); printf("\t\tpython-matplotlib is needed\n"); printf("\n\tWiki:\n"); printf("\t\t<http://opbuwiki.dal.design.ti.com/index.php/L3_bus_monitoring_SW_tool>\n\n"); sci_global_disable(psci_hdl); sci_close(&psci_hdl); return 0; case 'm': if (strstr(optarg, "0x")) { int a; sscanf(optarg, "%x", &a); my_config_emif1.filter[0].mstr_addr_match = a; my_config_emif2.filter[0].mstr_addr_match = a; my_config_emif3.filter[0].mstr_addr_match = a; my_config_emif4.filter[0].mstr_addr_match = a; printf("Master: %x\n", a); } else if (strstr(optarg, "ma_mpu_1_2")) { my_config_emif1.probe_id = SCI_MA_MPU_P1; my_config_emif2.probe_id = SCI_MA_MPU_P2; my_config_emif3.probe_id = SCI_MA_MPU_P1; my_config_emif4.probe_id = SCI_MA_MPU_P2; printf("Master: MA_MPU_1 and MA_MPU_2\n"); } break; case 'd': { float a; sscanf(optarg, "%f", &a); delay_us = a * 1000; } break; case 'a': sscanf(optarg, "%u", &accumulation_type); break; case 'i': sscanf(optarg, "%u", &iterations); break; case 'o': sscanf(optarg, "%u", &overflow_counter_index); break; case 't': sscanf(optarg, "%u", &overflow_threshold); break; case 'n': nosleep_32k = 1; break; case 'r': sscanf(optarg, "0x%x-0x%x", &min_addr, &max_addr); my_config_emif1.addr_filter_min = min_addr; my_config_emif2.addr_filter_min = min_addr; my_config_emif3.addr_filter_min = min_addr; my_config_emif4.addr_filter_min = min_addr; my_config_emif1.addr_filter_max = max_addr; my_config_emif2.addr_filter_max = max_addr; my_config_emif3.addr_filter_max = max_addr; my_config_emif4.addr_filter_max = max_addr; my_config_emif1.addr_filter_enable = true; my_config_emif2.addr_filter_enable = true; my_config_emif3.addr_filter_enable = true; my_config_emif4.addr_filter_enable = true; break; case 'D': disable = 1; default: printf("Unknown option\n"); } } printf("delay in us: %u\n", delay_us); printf("accumulation type: %u\n", accumulation_type); printf("iterations (0=infinite): %u\n", iterations); printf("Overflow counter index: %u\n", overflow_counter_index); printf("Overflow threshold: %u\n", overflow_threshold); if ((accumulation_type == 1) && (overflow_threshold == 0)) printf("WARNING: it is not recommended to set -a 1 with -t 0 if -d is small. HW is reset at every capture !\n"); if (iterations > MAX_ITERATIONS) { iterations = MAX_ITERATIONS; printf("WARNING: MAX_ITERATIONS(%d) exceeded\n", iterations); } omapconf_emu_enable_domain(); ///////////////////////////////////////////////////// //Make sure DebugSS is powered up and enabled // ///////////////////////////////////////////////////// my_sci_config.errhandler = sci_errhandler; my_sci_config.data_options = 0; //Disable options my_sci_config.trigger_enable = false; my_sci_config.sdram_msg_rate = 1; my_sci_config.mstr_msg_rate = 1; my_sci_config.mode = SCI_MODE_DUMP; addr_32k = mem_map_32k(); my_sci_err = sci_open(&psci_hdl, &my_sci_config); if (SCI_SUCCESS != my_sci_err) exit(-1); { uint32_t plib_major_ver; uint32_t plib_minor_ver; uint32_t plib_func_id; uint32_t pmod_func_id; sci_get_version(psci_hdl, &plib_major_ver, &plib_minor_ver, &plib_func_id, &pmod_func_id ); if ( plib_func_id != pmod_func_id ) { printf ("Error - func missmatch with device %d %d\n", plib_func_id, pmod_func_id); sci_close(&psci_hdl); exit(-1); } } // Test { unsigned int i, j; num_use_cases = sizeof(pmy_cfg)/sizeof(struct sci_config_sdram *); for (i = 0; i < num_use_cases; i++) { my_sci_err = sci_reg_usecase_sdram(psci_hdl, pmy_cfg[i], &my_usecase_key[i] ); if ( SCI_SUCCESS != my_sci_err) break; valid_usecase_cnt++; } /* If you kill the process, statcoll is left running. this is an option to disable it. We should intercept and handle signal */ if (disable == 1) { sci_global_disable(psci_hdl); sci_close(&psci_hdl); return 0; } /* And this is an ugly hack to disable it so that it will reset counters at enable */ sci_global_disable(psci_hdl); if (nosleep_32k) nosleep_32k_enable(); if (valid_usecase_cnt == num_use_cases) { uint32_t *counters_current = counters; if (accumulation_type == 1) { for (tests = 0; tests < (iterations * 9); tests++) counters[tests] = 0; my_sci_err = sci_global_enable(psci_hdl); for (tests = 0; tests < iterations; tests++) { usleep(delay_us); *counters_current = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + 1); if (*(counters_current + 1 + overflow_counter_index) >= overflow_threshold) { sci_global_disable(psci_hdl); sci_global_enable(psci_hdl); counters_current += 1 + num_use_cases; *counters_current = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + 1); tests++; //printf("overflow %u\n", *counters_current - counters[0]); } counters_current += 1 + num_use_cases; } } else { uint32_t *counters_prev; uint32_t *counters_overflow; unsigned int overflow_on; uint32_t delta_time; for (i = 0; i < sizeof(counters)/4; i++) counters[i] = 0; counters_prev = counters; counters_current = counters + 1 + num_use_cases; counters_overflow = counters + 2 + 2 * num_use_cases; sci_global_enable(psci_hdl); *counters_prev = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_prev + 1); for (;;) { usleep(delay_us); *counters_current = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_current + 1); if (*(counters_current + 1 + overflow_counter_index ) >= overflow_threshold) { //printf("DEBUG1 %u %u %u %u\n", *counters_prev, *(counters_prev + 1), *(counters_prev + 2), *(counters_prev + 3)); //printf("DEBUG2 %u %u %u %u\n", *counters_current, *(counters_current + 1), *(counters_current + 2), *(counters_current + 3)); sci_global_disable(psci_hdl); sci_global_enable(psci_hdl); *counters_overflow = GET_32K; sci_dump_sdram_cntrs(num_use_cases, counters_overflow + 1); overflow_on = 1; } /* trace current - prev */ delta_time = *counters_current - *counters_prev; printf("time: %u %u %u -> ", *counters_current, *counters_prev, delta_time); for (j = 0; j < num_use_cases; j++) { printf("%.2f ", ((float)(*(counters_current + 1 + j) - *(counters_prev + 1 + j))/1000000)*32768.0/delta_time); } printf("\n"); /* pointers increment */ if (overflow_on == 1) { overflow_on = 0; printf("Warning: statcoll HW IP reset to avoid overflow (user defined through -o -t)\n"); counters_current = counters_overflow; } counters_prev = counters_current; if ((unsigned int)(counters_current - counters) == (2 + 2 * num_use_cases)) counters_current = counters; else counters_current += 1 + num_use_cases; counters_overflow = counters_current; if ((unsigned int)(counters_overflow - counters) == (2 + 2 * num_use_cases)) counters_overflow = counters; else counters_overflow += 1 + num_use_cases; } } } else { printf(" SCI Lib Error %d\n", my_sci_err); } } sci_killhandler(); exit(0); }