Solve a few bugs
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 13 Nov 2014 00:21:00 +0000 (19:21 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 13 Nov 2014 00:21:00 +0000 (19:21 -0500)
barectf/cli.py
barectf/templates.py

index 04cb52dc0a7f575262712c00a47b59284ffa6513..926063a29b97a48bfdae91cb5ab7549536ecd34d 100644 (file)
@@ -88,7 +88,7 @@ class _CLine(str):
 class BarectfCodeGenerator:
     _CTX_AT = 'ctx->at'
     _CTX_BUF = 'ctx->buf'
-    _CTX_BUF_SIZE = 'ctx->buf_size'
+    _CTX_BUF_SIZE = 'ctx->packet_size'
     _CTX_BUF_AT = '{}[{} >> 3]'.format(_CTX_BUF, _CTX_AT)
     _CTX_BUF_AT_ADDR = '&{}'.format(_CTX_BUF_AT)
     _CTX_CALL_CLOCK_CB = 'ctx->clock_cb(ctx->clock_cb_data)'
@@ -168,8 +168,7 @@ class BarectfCodeGenerator:
             raise RuntimeError('field "{}" is a dynamic array (not allowed here)'.format(fname))
         elif type(ftype) is pytsdl.tsdl.Array:
             # we need to check every element until we find a terminal one
-            element = ftype.element
-            self._validate_inner_struct_field(fname, element)
+            self._validate_inner_struct_field(fname, ftype.element)
         elif type(ftype) is pytsdl.tsdl.Variant:
             raise RuntimeError('field "{}" is a variant (unsupported)'.format(fname))
         elif type(ftype) is pytsdl.tsdl.String:
@@ -215,6 +214,18 @@ class BarectfCodeGenerator:
             elif type(ftype) is pytsdl.tsdl.Struct:
                 # validate inner structure against barectf constraints
                 self._validate_inner_struct(ftype)
+            elif type(ftype) is pytsdl.tsdl.Array or type(ftype) is pytsdl.tsdl.Sequence:
+                done = False
+                el = ftype
+
+                while not done:
+                    if type(el) is pytsdl.tsdl.Struct:
+                        self._validate_inner_struct(ftype)
+                    if type(el) is pytsdl.tsdl.Array or type(el) is pytsdl.tsdl.Sequence:
+                        el = el.element
+                        continue
+
+                    done = True
 
     # Validates a TSDL integer with optional constraints.
     #
@@ -805,9 +816,12 @@ class BarectfCodeGenerator:
     # Returns the offset alignment macro call string for a given alignment.
     #
     #   size: new alignment
-    def _get_align_offset(self, align):
+    def _get_align_offset(self, align, at=None):
+        if at is None:
+            at = self._CTX_AT
+
         fmt = '{}_ALIGN_OFFSET({}, {});'
-        ret = fmt.format(self._prefix.upper(), self._CTX_AT, align)
+        ret = fmt.format(self._prefix.upper(), at, align)
 
         return ret
 
@@ -889,45 +903,134 @@ class BarectfCodeGenerator:
         t = self._get_obj_param_ctype(floating_point)
         length = self._get_obj_size(floating_point)
 
+        if t == 'float':
+            t = 'uint32_t'
+        elif t == 'double':
+            t = 'uint64_t'
+
+        src_name_casted = '({}) {}'.format(t, src_name)
+
         return self._template_to_clines(barectf.templates.WRITE_INTEGER,
                                         sz=length, bo=bo, type=t,
-                                        src_name=src_name)
+                                        src_name=src_name_casted)
 
-    # Returns the C lines for writing a TSDL array field.
+    # Returns the C lines for writing either a TSDL array field or a
+    # TSDL sequence field.
     #
-    #   fname:    field name
-    #   src_name: C source pointer
-    #   struct:   TSDL array
-    def _write_field_array(self, fname, src_name, array, scope_prefix=None):
+    #   fname:        field name
+    #   src_name:     C source pointer
+    #   arrayseq:     TSDL array or sequence
+    #   scope_prefix: preferred scope prefix
+    def _write_field_array_sequence(self, fname, src_name, arrayseq,
+                                    scope_prefix):
+        def length_index_varname(index):
+            return 'lens_{}_{}'.format(fname, index)
+
+        # first pass: find all lengths to multiply
+        mulops = []
+        done = False
+
+        while not done:
+            mulops.append(arrayseq.length)
+            element = arrayseq.element
+            tel = type(element)
+
+            if tel is pytsdl.tsdl.Array or tel is pytsdl.tsdl.Sequence:
+                # another array/sequence; continue
+                arrayseq = element
+                continue
+
+            # found the end
+            done = True
+
+        # align the size of the repeating element (effective repeating size)
+        el_size = self._get_obj_size(element)
+        el_align = self._get_obj_alignment(element)
+        el_size = self._get_alignment(el_size, el_align)
+
+        # this effective size is part of the operands to multiply
+        mulops.append(el_size)
+
+        # clines
         clines = []
 
-        # array index variable declaration
-        iv = 'ia_{}'.format(fname)
-        clines.append(_CLine('uint32_t {};'.format(iv)))
+        # fetch and save sequence lengths
+        emulops = []
 
-        # for loop using array's static length
-        line = 'for ({iv} = 0; {iv} < {l}; ++{iv}) {{'.format(iv=iv,
-                                                              l=array.length)
-        clines.append(_CLine(line))
+        for i in range(len(mulops)):
+            mulop = mulops[i]
 
-        # for loop statements
-        for_block = _CBlock()
+            if type(mulop) is list:
+                # offset variable to fetch
+                offvar = self._get_seq_length_src_name(mulop, scope_prefix)
 
-        # align bit index before writing to the buffer
-        element_align = self._get_obj_alignment(array.element)
-        cline = self._get_align_offset_cline(element_align)
-        for_block.append(cline)
+                # save buffer position
+                line = 'ctx_at_bkup = {};'.format(self._CTX_AT)
+                clines.append(_CLine(line))
 
-        # write element to the buffer
-        for_block += self._write_field_obj(fname, src_name, array.element,
-                                           scope_prefix)
-        clines.append(for_block)
+                # go back to field offset
+                line = '{} = {};'.format(self._CTX_AT, offvar)
+                clines.append(_CLine(line))
 
-        # for loop end
-        clines.append(_CLine('}'))
+                # read value into specific variable
+                varname = length_index_varname(i)
+                emulops.append(varname)
+                varctype = 'uint32_t'
+                fmt = '{ctype} {cname} = *(({ctype}*) ({ctxbufataddr}));'
+                line = fmt.format(ctype=varctype, cname=varname,
+                                  ctxbufataddr=self._CTX_BUF_AT_ADDR)
+                clines.append(_CLine(line))
+
+                # restore buffer position
+                line = '{} = ctx_at_bkup;'.format(self._CTX_AT)
+                clines.append(_CLine(line))
+            else:
+                emulops.append(str(mulop))
+
+        # write multiplication of sizes in bits
+        mul = ' * '.join(emulops)
+        sz_bits_varname = 'sz_bits_{}'.format(fname)
+        sz_bytes_varname = 'sz_bytes_{}'.format(fname)
+        line = 'uint32_t {} = {};'.format(sz_bits_varname, mul)
+        clines.append(_CLine(line))
+        line = 'uint32_t {} = {};'.format(sz_bytes_varname, sz_bits_varname)
+        clines.append(_CLine(line))
+        line = self._get_align_offset(8, at=sz_bytes_varname)
+        clines.append(_CLine(line))
+        line = '{} >>= 3;'.format(sz_bytes_varname)
+        clines.append(_CLine(line))
+
+        # memcpy()
+        dst = self._CTX_BUF_AT_ADDR
+        line = 'memcpy({}, {}, {});'.format(dst, src_name, sz_bytes_varname)
+        clines.append(_CLine(line))
+        line = '{} += {};'.format(self._CTX_AT, sz_bits_varname)
+        clines.append(_CLine(line))
+
+        # TODO: continue this
 
         return clines
 
+    # Returns the C lines for writing a TSDL array field.
+    #
+    #   fname:        field name
+    #   src_name:     C source pointer
+    #   array:        TSDL array
+    #   scope_prefix: preferred scope prefix
+    def _write_field_array(self, fname, src_name, array, scope_prefix=None):
+        return self._write_field_array_sequence(fname, src_name, array,
+                                                scope_prefix)
+
+    # Returns the C lines for writing a TSDL sequence field.
+    #
+    #   fname:        field name
+    #   src_name:     C source pointer
+    #   sequence:     TSDL sequence
+    #   scope_prefix: preferred scope prefix
+    def _write_field_sequence(self, fname, src_name, sequence, scope_prefix):
+        return self._write_field_array_sequence(fname, src_name, sequence,
+                                                scope_prefix)
+
     # Returns a trace packet header C source name out of a sequence length
     # expression.
     #
@@ -1002,46 +1105,6 @@ class BarectfCodeGenerator:
 
         return self._get_offvar_name_from_expr(length, scope_prefix)
 
-    # Returns the C lines for writing a TSDL sequence field.
-    #
-    #   fname:        field name
-    #   src_name:     C source pointer
-    #   sequence:     TSDL sequence
-    #   scope_prefix: preferred scope prefix
-    def _write_field_sequence(self, fname, src_name, sequence, scope_prefix):
-        clines = []
-
-        # sequence index variable declaration
-        iv = 'is_{}'.format(fname)
-        clines.append(_CLine('uint32_t {};'.format(iv)))
-
-        # sequence length offset variable
-        length_offvar = self._get_seq_length_src_name(sequence.length,
-                                                     scope_prefix)
-
-        # for loop using sequence's static length
-        line = 'for ({iv} = 0; {iv} < {l}; ++{iv}) {{'.format(iv=iv,
-                                                              l=length_offvar)
-        clines.append(_CLine(line))
-
-        # for loop statements
-        for_block = _CBlock()
-
-        # align bit index before writing to the buffer
-        element_align = self._get_obj_alignment(sequence.element)
-        cline = self._get_align_offset_cline(element_align)
-        for_block.append(cline)
-
-        # write element to the buffer
-        for_block += self._write_field_obj(fname, src_name, sequence.element,
-                                           scope_prefix)
-        clines.append(for_block)
-
-        # for loop end
-        clines.append(_CLine('}'))
-
-        return clines
-
     # Returns the C lines for writing a TSDL string field.
     #
     #   fname:        field name
@@ -1147,13 +1210,13 @@ class BarectfCodeGenerator:
             for lname, offset in offvars.items():
                 offvar = self._get_offvar_name('_'.join([fname, lname]),
                                                scope_prefix)
-                fmt = 'uint32_t {} = {} + {};'
+                fmt = 'uint32_t {} = (uint32_t) {} + {};'
                 line = fmt.format(offvar, self._CTX_AT, offset);
                 clines.append(_CLine(line))
         elif type(ftype) is pytsdl.tsdl.Integer:
             # offset of this simple field is the current bit index
             offvar = self._get_offvar_name(fname, scope_prefix)
-            line = 'uint32_t {} = {};'.format(offvar, self._CTX_AT)
+            line = 'uint32_t {} = (uint32_t) {};'.format(offvar, self._CTX_AT)
             clines.append(_CLine(line))
 
         clines += self._write_field_obj(fname, pname, ftype, scope_prefix)
@@ -1249,7 +1312,7 @@ class BarectfCodeGenerator:
 
         if not self._manual_clock:
             ctype = self._get_clock_ctype(stream)
-            fmt = '\t{} (*clock_cb)(void*),\n\tvoid* clock_cb_data;'
+            fmt = '\t{} (*clock_cb)(void*);\n\tvoid* clock_cb_data;'
             clock_cb = fmt.format(ctype)
 
         # fill template
@@ -1318,7 +1381,7 @@ class BarectfCodeGenerator:
             if fname == 'packet_size':
                 fclines = self._field_to_clines(fname, ftype, scope_name,
                                                 scope_prefix,
-                                                lambda x: 'ctx->buffer_size')
+                                                lambda x: 'ctx->packet_size')
                 fcline_groups.append(fclines)
 
             # content size (skip)
@@ -1425,7 +1488,7 @@ class BarectfCodeGenerator:
         clines.append(_CLine(''))
         clines.append(_CLine("/* barectf context parameters */"))
         clines.append(_CLine('ctx->buf = buf;'))
-        clines.append(_CLine('ctx->buf_size = buf_size * 8;'))
+        clines.append(_CLine('ctx->packet_size = buf_size * 8;'))
         clines.append(_CLine('{} = 0;'.format(self._CTX_AT)))
 
         if not self._manual_clock:
@@ -1581,7 +1644,7 @@ class BarectfCodeGenerator:
 
             # write timestamp_end
             timestamp_end_integer = stream.packet_context['timestamp_end']
-            clines += self._gen_write_ctx_field_integer('clk_value', 'pc',
+            clines += self._gen_write_ctx_field_integer('clk_value', 'spc',
                                                         'timestamp_end',
                                                         timestamp_end_integer)
 
@@ -1589,10 +1652,14 @@ class BarectfCodeGenerator:
         clines.append(_CLine(''))
         clines.append(_CLine("/* update packet context's content_size */"))
         content_size_integer = stream.packet_context['content_size']
-        clines += self._gen_write_ctx_field_integer('ctx_at_bkup', 'pc',
+        clines += self._gen_write_ctx_field_integer('ctx_at_bkup', 'spc',
                                                     'content_size',
                                                     content_size_integer)
 
+        # return 0
+        clines.append(_CLine('\n'))
+        clines.append(_CLine('return 0;'))
+
         # get source
         cblock = _CBlock(clines)
         src = self._cblock_to_source(cblock)
@@ -1671,6 +1738,8 @@ class BarectfCodeGenerator:
     def _gen_barectf_func_trace_event_body(self, stream, event):
         clines = []
 
+        clines.append(_CLine('uint32_t ctx_at_bkup;'))
+
         # get clock value ASAP
         clk_type = self._get_clock_ctype(stream)
         clk = self._gen_get_clock_value()
@@ -1840,14 +1909,21 @@ class BarectfCodeGenerator:
 
         return funcs
 
+    # Generate all barectf functions
+    #
+    #   gen_body: also generate function bodies
+    def _gen_barectf_functions(self, gen_body):
+        init_funcs = self._gen_barectf_funcs_init(gen_body)
+        open_funcs = self._gen_barectf_funcs_open(gen_body)
+        close_funcs = self._gen_barectf_funcs_close(gen_body)
+        trace_funcs = self._gen_barectf_funcs_trace(gen_body)
+
+        return init_funcs + open_funcs + close_funcs + trace_funcs
+
     # Generates the barectf header C source
     def _gen_barectf_header(self):
         ctx_structs = self._gen_barectf_contexts_struct()
-        init_funcs = self._gen_barectf_funcs_init(self._static_inline)
-        open_funcs = self._gen_barectf_funcs_open(self._static_inline)
-        close_funcs = self._gen_barectf_funcs_close(self._static_inline)
-        trace_funcs = self._gen_barectf_funcs_trace(self._static_inline)
-        functions = init_funcs + open_funcs + close_funcs + trace_funcs
+        functions = self._gen_barectf_functions(self._static_inline)
         functions_str = '\n\n'.join(functions)
         t = barectf.templates.HEADER
         header = t.format(prefix=self._prefix, ucprefix=self._prefix.upper(),
@@ -1870,6 +1946,16 @@ class BarectfCodeGenerator:
 
         return header
 
+    # Generates the main barectf C source file.
+    def _gen_barectf_tu(self):
+        functions = self._gen_barectf_functions(True)
+        functions_str = '\n\n'.join(functions)
+        t = barectf.templates.CSRC
+        csrc = t.format(prefix=self._prefix, ucprefix=self._prefix.upper(),
+                        functions=functions_str)
+
+        return csrc
+
     # Writes a file to the generator's output.
     #
     #   name:     file name
@@ -1971,8 +2057,8 @@ class BarectfCodeGenerator:
         # generate C source file
         if not self._static_inline:
             _pinfo('generating barectf translation unit')
-
-            pass
+            csrc = self._gen_barectf_tu()
+            self._write_file('{}.c'.format(self._prefix), csrc)
 
         _psuccess('done')
 
index 8496636790ffb0eb1298b5df06211eda799b0d84..7b5b185778ed75abd1d38492f02ecabd896ee905 100644 (file)
@@ -3,7 +3,7 @@ BARECTF_CTX = """struct {prefix}{sid}_ctx {{
        uint8_t* buf;
 
        /* buffer size in bits */
-       uint32_t buf_size;
+       uint32_t packet_size;
 
        /* current position from beginning of buffer in bits */
        uint32_t at;
@@ -28,7 +28,7 @@ FUNC_OPEN = """{si}int {prefix}{sid}_open(
        struct {prefix}{sid}_ctx* ctx{params}
 )"""
 
-FUNC_CLOSE = """{si}void {prefix}{sid}_close(
+FUNC_CLOSE = """{si}int {prefix}{sid}_close(
        struct {prefix}{sid}_ctx* ctx{params}
 )"""
 
@@ -36,14 +36,15 @@ FUNC_TRACE = """{si}int {prefix}{sid}_trace_{evname}(
        struct {prefix}{sid}_ctx* ctx{params}
 )"""
 
-WRITE_INTEGER = """{ucprefix}_CHK_OFFSET_V(ctx->at, ctx->buf_size, {sz});
-{prefix}_bt_bitfield_write_{bo}(ctx->buf, {type}, ctx->at, {sz}, {src_name});
+WRITE_INTEGER = """{ucprefix}_CHK_OFFSET_V(ctx->at, ctx->packet_size, {sz});
+{prefix}_bt_bitfield_write_{bo}(ctx->buf, uint8_t, ctx->at, {sz}, {src_name});
 ctx->at += {sz};"""
 
 HEADER = """#ifndef _{ucprefix}_H
 #define _{ucprefix}_H
 
 #include <stdint.h>
+#include <string.h>
 
 #include "{prefix}_bitfield.h"
 
@@ -74,7 +75,10 @@ HEADER = """#ifndef _{ucprefix}_H
 #endif /* _{ucprefix}_H */
 """
 
-CSRC = """#include "{prefix}.h"
+CSRC = """#include <stdint.h>
+#include <string.h>
+
+#include "{prefix}.h"
 
 {functions}
 """
@@ -109,6 +113,7 @@ BITFIELD = """#ifndef _$PREFIX$_BITFIELD_H
  */
 
 #include <stdint.h>    /* C99 5.2.4.2 Numerical limits */
+#include <limits.h>
 
 #define $PREFIX$_BYTE_ORDER $ENDIAN_DEF$
 
This page took 0.028862 seconds and 4 git commands to generate.