# HG changeset patch # User Edouard TISSERANT # Date 1259781748 -3600 # Node ID 18583d13f0fa2b47a3ae5c837888a71e1a85248d # Parent 9d5036e86c3db6466887ebe73a834832a057e569 Preliminary accessor support for debug diff -r 9d5036e86c3d -r 18583d13f0fa plugger.py --- a/plugger.py Wed Dec 02 13:07:57 2009 +0100 +++ b/plugger.py Wed Dec 02 20:22:28 2009 +0100 @@ -1303,7 +1303,7 @@ # Fill in IEC<->C translation dicts IEC_path=attrs["IEC_path"] Idx=int(attrs["num"]) - self._IECPathToIdx[IEC_path]=Idx + self._IECPathToIdx[IEC_path]=(Idx, attrs["type"]) except Exception,e: self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n")) self.logger.write_error(traceback.format_exc()) @@ -1331,10 +1331,15 @@ len(self._VariablesList), "variables_pointer_type_table_count": len(self._VariablesList), - "variables_pointer_type_table_initializer":"\n".join([ - {"PT":" variable_table[%(num)s].ptrvalue = (void*)(%(C_path)s);\n", - "VAR":" variable_table[%(num)s].ptrvalue = (void*)(&%(C_path)s);\n"}[v["vartype"]]%v + - " variable_table[%(num)s].type = %(type)s_ENUM;\n"%v + "for_each_variable_do_code":"\n".join([ + {"PT":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n", + "VAR":" (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v + for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypes ]), + "find_variable_case_code":"\n".join([ + " case %(num)s:\n"%v+ + " varp = (void*)&%(C_path)s;\n"%v+ + {"PT":" return %(type)s_P_ENUM;\n", + "VAR":" return %(type)s_ENUM;\n"}[v["vartype"]]%v for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypes ])} return debug_code @@ -1596,16 +1601,17 @@ IECPathsToPop.append(IECPath) elif IECPath != "__tick__": # Convert - Idx = self._IECPathToIdx.get(IECPath,None) + Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None)) if Idx is not None: - Idxs.append(Idx) - self.TracedIECPath.append(IECPath) + Idxs.append((Idx, IEC_Type, IECPath)) else: self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath) for IECPathToPop in IECPathsToPop: self.IECdebug_datas.pop(IECPathToPop) - self._connector.SetTraceVariablesList(Idxs) + Idxs.sort() + self.TracedIECPath = zip(Idxs)[2] + self._connector.SetTraceVariablesList(zip(zip(Idxs)[0:1])) self.IECdebug_lock.release() #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems(): @@ -1629,7 +1635,7 @@ to a WeakKeyDictionary linking weakly referenced callables to optionnal args """ - if IECPath != "__tick__" and self._IECPathToIdx.get(IECPath, None) is None: + if IECPath != "__tick__" and not self._IECPathToIdx.has_key(IECPath): return None self.IECdebug_lock.acquire() diff -r 9d5036e86c3d -r 18583d13f0fa runtime/PLCObject.py --- a/runtime/PLCObject.py Wed Dec 02 13:07:57 2009 +0100 +++ b/runtime/PLCObject.py Wed Dec 02 20:22:28 2009 +0100 @@ -131,15 +131,12 @@ self._RegisterDebugVariable.restype = None self._RegisterDebugVariable.argtypes = [ctypes.c_int] - self._IterDebugData = self.PLClibraryHandle.IterDebugData - self._IterDebugData.restype = ctypes.c_void_p - self._IterDebugData.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_char_p)] - self._FreeDebugData = self.PLClibraryHandle.FreeDebugData self._FreeDebugData.restype = None - self._WaitDebugData = self.PLClibraryHandle.WaitDebugData - self._WaitDebugData.restype = ctypes.c_int + self._GetDebugData = self.PLClibraryHandle.GetDebugData + self._GetDebugData.restype = ctypes.c_int + self._GetDebugData.argtypes = [ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_void_p)] self._suspendDebug = self.PLClibraryHandle.suspendDebug self._suspendDebug.restype = None @@ -165,7 +162,7 @@ self._RegisterDebugVariable = lambda x:None self._IterDebugData = lambda x,y:None self._FreeDebugData = lambda:None - self._WaitDebugData = lambda:-1 + self._GetDebugData = lambda:-1 self._suspendDebug = lambda:None self._resumeDebug = lambda:None self._PythonIterator = lambda:"" @@ -339,7 +336,7 @@ # keep a copy of requested idx self._Idxs = idxs[:] self._ResetDebugVariables() - for idx in idxs: + for idx,iectype in idxs: self._RegisterDebugVariable(idx) self._resumeDebug() @@ -378,21 +375,21 @@ """ if self.PLCStatus == "Started": self.PLClibraryLock.acquire() - tick = ctypes.c_int() - #PLCprint("Debug tick : %d"%tick) - if self._WaitDebugData(ctypes.byref(tick)) != 0: - idx = ctypes.c_int() - typename = ctypes.c_char_p() - res = [] - for given_idx in self._Idxs: - buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename)) - c_type,unpack_func = self.TypeTranslator.get(typename.value, (None,None)) - if c_type is not None and given_idx == idx.value: - res.append(unpack_func(ctypes.cast(buffer, + tick = ctypes.c_uint32() + size = ctypes.c_uint32() + buffer = ctypes.c_void_p() + if self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : + offset = 0 + for idx, iectype in self._Idxs: + cursor = ctypes.c_void_p(buffer.value + offset) + c_type,unpack_func = self.TypeTranslator.get(iectype, (None,None)) + if c_type is not None and offset < size: + res.append(unpack_func(ctypes.cast(cursor, ctypes.POINTER(c_type)).contents)) + offset += ctypes.sizeof(c_type) else: - PLCprint("Debug error idx : %d, expected_idx %d, type : %s"%(idx.value, given_idx,typename.value)) - res.append(None) + PLCprint("Debug error !") + break self._FreeDebugData() self.PLClibraryLock.release() return self.PLCStatus, tick, res diff -r 9d5036e86c3d -r 18583d13f0fa targets/plc_debug.c --- a/targets/plc_debug.c Wed Dec 02 13:07:57 2009 +0100 +++ b/targets/plc_debug.c Wed Dec 02 20:22:28 2009 +0100 @@ -30,11 +30,6 @@ /* Buffer's cursor*/ static char* buffer_cursor = debug_buffer; -typedef struct{ - void* ptrvalue; - __IEC_types_enum type; -}struct_plcvar; - /*** * Declare programs **/ @@ -45,15 +40,23 @@ **/ %(extern_variables_declarations)s -static int subscription_table[MAX_SUBSCRIBTION]; -static int* latest_subscription = subscription_table; -static int* subscription_cursor = subscription_table; +typedef void(*__for_each_variable_do_fp)(void*, __IEC_types_enum); +__for_each_variable_do(__for_each_variable_do_fp fp) +{ +%(for_each_variable_do_code)s +} -struct_plcvar variable_table[%(variables_pointer_type_table_count)d]; +__IEC_types_enum __find_variable(unsigned int varindex, void ** varp) +{ + switch(varindex){ +%(find_variable_case_code)s + } + *varp = NULL; + return UNKNOWN_ENUM; +} void __init_debug(void) { -%(variables_pointer_type_table_initializer)s buffer_state = BUFFER_FREE; } @@ -71,6 +74,44 @@ extern void InitiateDebugTransfer(void); extern unsigned long __tick; + +#define __BufferDebugDataIterator_case_t(TYPENAME) \ + case TYPENAME##_ENUM :\ + flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\ + ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value; + +#define __BufferDebugDataIterator_case_p(TYPENAME)\ + case TYPENAME##_P_ENUM :\ + flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\ + ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value; + +void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype) +{ + void *ptrvalue = NULL; + char flags = 0; + /* find data to copy*/ + switch(vartype){ + ANY(__BufferDebugDataIterator_case_t) + ANY(__BufferDebugDataIterator_case_p) + } + if(flags && __IEC_DEBUG_FLAG){ + USINT size = __get_type_enum_size(vartype); + /* compute next cursor positon*/ + char* next_cursor = buffer_cursor + size; + /* if buffer not full */ + if(next_cursor <= debug_buffer + BUFFER_SIZE) + { + /* copy data to the buffer */ + memcpy(buffer_cursor, ptrvalue, size); + /* increment cursor according size*/ + buffer_cursor = next_cursor; + }else{ + /*TODO : signal overflow*/ + } + } +} + + void __publish_debug(void) { /* Check there is no running debugger re-configuration */ @@ -84,38 +125,10 @@ /* If buffer was free */ if(latest_state == BUFFER_FREE) { - int* subscription; - /* Reset buffer cursor */ buffer_cursor = debug_buffer; - - /* iterate over subscriptions */ - for(subscription=subscription_table; - subscription < latest_subscription; - subscription++) - { - /* get variable descriptor */ - struct_plcvar* my_var = &variable_table[*subscription]; - char* next_cursor; - /* get variable size*/ - USINT size = __get_type_enum_size(my_var->type); - /* compute next cursor positon*/ - next_cursor = buffer_cursor + size; - /* if buffer not full */ - if(next_cursor <= debug_buffer + BUFFER_SIZE) - { - /* copy data to the buffer */ - memcpy(buffer_cursor, my_var->ptrvalue, size); - /* increment cursor according size*/ - buffer_cursor = next_cursor; - }else{ - /*TODO : signal overflow*/ - } - } - - /* Reset buffer cursor again (for IterDebugData)*/ - buffer_cursor = debug_buffer; - subscription_cursor = subscription_table; + /* Iterate over all variables to fill debug buffer */ + __for_each_variable_do(BufferDebugDataIterator); /* Leave debug section, * Trigger asynchronous transmission @@ -126,21 +139,41 @@ } } +#define __RegisterDebugVariable_case_t(TYPENAME) \ + case TYPENAME##_ENUM :\ + ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_DEBUG_FLAG; +#define __RegisterDebugVariable_case_p(TYPENAME)\ + case TYPENAME##_P_ENUM :\ + ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_DEBUG_FLAG; void RegisterDebugVariable(int idx) { - /*If subscription table not full */ - if(latest_subscription - subscription_table < MAX_SUBSCRIBTION) - { - *(latest_subscription++) = idx; - /* TODO pre-calc buffer size and signal overflow*/ - }else{ - /*TODO : signal subscription overflow*/ + void *varp; + switch(__find_variable(idx, varp)){ + ANY(__RegisterDebugVariable_case_t) + ANY(__RegisterDebugVariable_case_p) + } +} + +#define __ResetDebugVariablesIterator_case_t(TYPENAME) \ + case TYPENAME##_ENUM :\ + ((__IEC_##TYPENAME##_t *)varp)->flags &= ~__IEC_DEBUG_FLAG; + +#define __ResetDebugVariablesIterator_case_p(TYPENAME)\ + case TYPENAME##_P_ENUM :\ + ((__IEC_##TYPENAME##_p *)varp)->flags &= ~__IEC_DEBUG_FLAG;\ + +void ResetDebugVariablesIterator(void* varp, __IEC_types_enum vartype) +{ + /* force debug flag to 0*/ + switch(vartype){ + ANY(__ResetDebugVariablesIterator_case_t) + ANY(__ResetDebugVariablesIterator_case_p) } } void ResetDebugVariables(void) { - latest_subscription = subscription_table; + __for_each_variable_do(ResetDebugVariablesIterator); } void FreeDebugData(void) @@ -153,29 +186,11 @@ BUFFER_FREE); } -void* IterDebugData(int* idx, const char **type_name) -{ - struct_plcvar* my_var; - USINT size; - if(subscription_cursor < latest_subscription){ - char* old_cursor = buffer_cursor; - *idx = *subscription_cursor; - my_var = &variable_table[*(subscription_cursor++)]; - *type_name = __get_type_enum_name(my_var->type); - /* get variable size*/ - size = __get_type_enum_size(my_var->type); - /* compute next cursor position*/ - buffer_cursor = buffer_cursor + size; - if(old_cursor < debug_buffer + BUFFER_SIZE) - { - return old_cursor; - }else{ - //printf("%%d > %%d\n", old_cursor - debug_buffer, BUFFER_SIZE); - return NULL; - } - } - *idx = -1; - *type_name = NULL; - return NULL; +/* Wait until debug data ready and return pointer to it */ +int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){ + int res = WaitDebugData(tick); + *size = buffer_cursor - debug_buffer; + *buffer = NULL; + return res; }