2015-09-16 13 views
10

मैं एआरएम कॉर्टेक्स-एम 4 (या कॉर्टेक्स-एम 3) प्रोसेसर पर निष्पादित प्रति चक्र निर्देशों की संख्या गिनना चाहता हूं।एआरएम एम 4 निर्देश प्रति चक्र (आईपीसी) काउंटर

यह क्या जरूरत है: कोड के निर्देश (रनटाइम पर निष्पादित) के संख्या मैं प्रोफ़ाइल करना चाहते हैं और उस कोड निष्पादित करने के लिए लेता है चक्र की संख्या।

1 - साइकिल

की संख्या का प्रयोग करें चक्र काउंटर काफी आसान और सरल है।

volatile unsigned int *DWT_CYCCNT ; 
volatile unsigned int *DWT_CONTROL ; 
volatile unsigned int *SCB_DEMCR ; 

void reset_timer(){ 
    DWT_CYCCNT = (int *)0xE0001004; //address of the register 
    DWT_CONTROL = (int *)0xE0001000; //address of the register 
    SCB_DEMCR = (int *)0xE000EDFC; //address of the register 
    *SCB_DEMCR = *SCB_DEMCR | 0x01000000; 
    *DWT_CYCCNT = 0; // reset the counter 
    *DWT_CONTROL = 0; 
} 

void start_timer(){ 
    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter 
} 

void stop_timer(){ 
    *DWT_CONTROL = *DWT_CONTROL | 0 ; // disable the counter  
} 

unsigned int getCycles(){ 
    return *DWT_CYCCNT; 
} 

main(){ 
    .... 
    reset_timer(); //reset timer 
    start_timer(); //start timer 
    //Code to profile 
    ... 
    myFunction(); 
    ... 
    stop_timer(); //stop timer 
    numCycles = getCycles(); //read number of cycles 
    ... 
} 

2 - निर्देश

मैं इंटरनेट पर सर्फिंग हाथ प्रांतस्था-एम 3 द्वारा निष्पादित निर्देश और की संख्या की गणना करने के लिए प्रांतस्था-एम 4 (link) कुछ प्रलेखन पाया की संख्या:

# instructions = CYCCNT - CPICNT - EXCCNT - SLEEPCNT - LSUCNT + FOLDCNT 

वे जिन रजिस्टरों का उल्लेख करते हैं उन्हें here (पृष्ठ 11-13 से) दस्तावेज किया गया है और इन्हें एक्सेस करने के लिए स्मृति पते हैं:

DWT_CYCCNT = 0xE0001004 
DWT_CONTROL = 0xE0001000 
SCB_DEMCR = 0xE000EDFC 
DWT_CPICNT = 0xE0001008 
DWT_EXCCNT = 0xE000100C 
DWT_SLEEPCNT = 0xE0001010 
DWT_LSUCNT = 0xE0001014 
DWT_FOLDCNT = 0xE0001018 

DWT_CONTROL रजिस्टर काउंटर को सक्षम करने के लिए उपयोग किया जाता है, विशेष रूप से साइकिल काउंटर here दस्तावेज के रूप में।

लेकिन जब मैंने प्रति चक्र निष्पादित निर्देशों की संख्या गिनने के लिए सभी को एक साथ रखने की कोशिश की तो मैं सफल नहीं हुआ।

Here जीडीबी से उनका उपयोग करने के तरीके पर एक छोटी सी मार्गदर्शिका है।

क्या आसान नहीं है कि कुछ रजिस्ट्रार 8 बिट रजिस्ट्रार (DWT_CPICNT, DWT_EXCCNT, DWT_SLEEPCNT, DWT_LSUCNT, DWT_FOLDCNT) हैं और जब वे बहते हैं तो वे एक ईवेंट ट्रिगर करते हैं। मुझे उस घटना को इकट्ठा करने का कोई रास्ता नहीं मिला। कोई कोड स्निपेट नहीं है जो बताता है कि ऐसा कैसे करें या इसके लिए उपयुक्त रूटीन को बाधित करें।

ऐसा लगता है कि उन रजिस्टरों के पते पर gdb से watchpoints का उपयोग करना काम नहीं करता है। रजिस्ट्रार मूल्य बदलते समय gdb रुकने में सक्षम नहीं है। जैसे

(gdb) watch *0xE0001014 

अपडेट:: DWT_LSUCNT पर मैं डीडब्ल्यूटी, आईटीएम और ETM इकाइयों का उपयोग करने का तरीका बताने GitHub पर इस project पाया। लेकिन मैंने यह नहीं देखा कि यह काम करता है या नहीं! मैं अपडेट पोस्ट करूंगा।

उनका उपयोग करने के तरीके पर कोई विचार?

धन्यवाद!

+1

शायद बहुत स्पष्ट है, लेकिन आप हमेशा reset_timer() किसी अन्य समारोह के निष्पादित होने से पहले, सही कहते हैं? क्या आप कम से कम उदाहरण के रूप में कॉलिंग कोड पोस्ट कर सकते हैं? – Lundin

+3

मैं रजिस्ट्रार को '# परिभाषित DWT_CYCCNT (* (अस्थिर uint32_t *) 0xE0001004ul) के बजाय घोषित करने का सुझाव दूंगा। – Lundin

+0

क्या ईवेंट ऐसी घटनाओं को डीबग नहीं करते हैं जो डीबग मॉनिटर अपवाद को ट्रिगर करेंगे? – Notlikethat

उत्तर

1

मुझे नहीं पता कि रजिस्टरों का उपयोग किस प्रकार आप करना चाहते हैं। लेकिन, यहां मैं चक्र मापने के साथ कैसे निपटता हूं।

सुनिश्चित करें कि आप SysTick Control and Status Register पर काउंटर सक्षम करें। उचित शीर्षकों के साथ, आपको एक संरचना के रूप में SysTick रजिस्टरों तक पहुंच प्राप्त करनी चाहिए।

काउंटर फ़ंक्शन द्वारा उठाए गए चक्रों की संख्या को मापें। बाद में इसे किसी भी माप से घटाया जाता है।

SysTick->VAL = 0; // set 0 
    // Measure delay on measurement 
    __disable_irq(); 
    a = (uint32_t) SysTick->VAL; 
    //... measuring zero instructions 
    b = (uint32_t) SysTick->VAL; 
    __enable_irq(); 
    measure_delay = a - b; 

अब एक फ़ंक्शन को मापें।

SysTick->VAL = 0; 
__disable_irq(); 
a = (uint32_t) SysTick->VAL; 

//Assuming this function doesn't require interruptions 

// INSERT CODE TO BE PROFILED 
function_to_be_examined(); 

b = (uint32_t) SysTick->VAL; 
__enable_irq(); 
cycles_profiled_code = a - b - measure_delay; 

मुझे आशा है कि इससे मदद मिलती है।

+0

ध्यान दें कि बहुत मोटे ग्रैन्युलरिटी के साथ यह उपाय, क्योंकि SysTick "सामान्य रूप से" प्रत्येक उदाहरण को ओवरफ़्लो करने के लिए सेट है 1ms। प्रश्न में कोड सटीक चक्र गणना का आकलन करता है। – Darhuuk

+0

अच्छी तरह से ध्यान दिया। सही बात। असल में, अगर प्रोसेसर की गति 100 मेगाहट्र्ज है, तो 1 एमएमएस लगभग 100,000 चक्रों को मापने की अनुमति देगा। यह विधि उन कार्यों के लिए सटीक है जो हजारों चक्रों तक ले जाती हैं। – Toani

2

कोड नमूना आपके द्वारा दी गई सक्षम सा समाशोधन में एक समस्या है। आप स्पष्ट करना चाहिए सा गाना 'और' नहीं 'या':

*DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter by clearing the enable bit 
1

मुझे लगता है कि अगर आप सटीकता चक्र आकलन करना चाहते हैं, डिबगर का उपयोग कर एक अच्छा विकल्प है। कील-एमडीके राज्य रजिस्टर जमा कर सकता है और बह जाएगा नहीं। डीब्यूटर का परिणाम डीडब्ल्यूटी का उपयोग कर परिणाम के समान है।

यदि आप अन्य मूल्यों का आकलन करना चाहते यानी FOLDCNT, Keil-MDK में ट्रेस का उपयोग कर -> डीबग -> सेटिंग -> ट्रेस -> ट्रेस सक्षम करें।

इसी के साथ

, जबकि डीबगिंग, ट्रेस Windows में ट्रेस घटना चुनते हैं, उन 8 बिट का मान रजिस्टर एकत्र और Keil द्वारा एक साथ जोड़ा जा सकता है।

यह थोड़ा बेवकूफ लगता है लेकिन मुझे नहीं पता कि ओवरफ्लो की घटना को कैसे एकत्र किया जाए, मुझे लगता है कि यह घटना केवल आईटीएम को भेजी जा सकती है, क्योंकि या तो डीडब्ल्यूटी या आईटीएम कार्यक्रम से अलग घटक है। अगर हम ग्राहक कार्यक्रम में घटना एकत्र करना चाहते हैं, तो संग्रह कार्रवाई को परिणाम की सटीकता को प्रभावित करना होगा।

आईटीएम? ETM? CoreSight? डीडब्ल्यूटी? AHB?

संबंधित मुद्दे