* Make the FFT size a bit larger. master
authorMatthijs Kooijman <matthijs@stdin.nl>
Tue, 8 Apr 2008 13:28:43 +0000 (15:28 +0200)
committerunknown <s0042331@.dynamic.ewi.utwente.nl>
Tue, 8 Apr 2008 13:28:43 +0000 (15:28 +0200)
 * Explicitely pass the addressing strategies to use for reading input and
   writing output on each stage. So far, only REGULAR_IN is supported for
   input (ie, no changes) and REGULAR_OUT and BITREVERSED_OUT are supported
   for output (ie, add support for bitreversing the last stage).

FFT.h
FFT.mc

diff --git a/FFT.h b/FFT.h
index 5941e934477ca462d6d600c5be0d26b7e5eab293..b94386e6f4e0d82bbe6f651f9aeaafc89ca930f4 100644 (file)
--- a/FFT.h
+++ b/FFT.h
@@ -8,7 +8,7 @@
 /* 2log of number of tiles */\r
 #define PARAM_q 2\r
 /** 2log of total FFT size */\r
 /* 2log of number of tiles */\r
 #define PARAM_q 2\r
 /** 2log of total FFT size */\r
-#define PARAM_n 6\r
+#define PARAM_n 12\r
 \r
 /* Note that the FFT size on each tile 2^(n-q) must be at least\r
  * 8 and always a multiple of 4. The number of stages on each \r
 \r
 /* Note that the FFT size on each tile 2^(n-q) must be at least\r
  * 8 and always a multiple of 4. The number of stages on each \r
        /* Values for the cycle_odd argument */\r
 #define EVEN_CYCLE 0\r
 #define ODD_CYCLE 1\r
        /* Values for the cycle_odd argument */\r
 #define EVEN_CYCLE 0\r
 #define ODD_CYCLE 1\r
+       \r
+enum in_strategy {     \r
+       REGULAR_IN,\r
+       DISTRIBUTED_IN,\r
+};\r
+\r
+enum out_strategy {\r
+       REGULAR_OUT,\r
+       DISTRIBUTED_OUT,\r
+       BITREVERSED_OUT,\r
+};\r
 \r
 #endif // !FFT_H_INCLUDED\r
 \r
 #endif // !FFT_H_INCLUDED\r
diff --git a/FFT.mc b/FFT.mc
index 8fb50f1ee8f598b938b95d7f7ae69546309d02ce..a76377e1c70e3c26b829cd043dff8154b3699d29 100644 (file)
--- a/FFT.mc
+++ b/FFT.mc
@@ -45,23 +45,50 @@ INLINE struct bf_out butterfly(struct bf_in in) {
  * locations.\r
  * @param  second_half   Are we in the second half of the stage?\r
  */\r
  * locations.\r
  * @param  second_half   Are we in the second half of the stage?\r
  */\r
-INLINE void write_output_regular(struct mems m, struct bf_out res, bool second_half) {\r
-       add_offset(m.output_a_re, 2);\r
-       add_offset(m.output_a_im, 2);\r
-       add_offset(m.output_b_re, 2);\r
-       add_offset(m.output_b_im, 2);\r
-       \r
-       if (!second_half) {\r
-               write_mem(m.output_a_re, res.a_re);\r
-               write_mem(m.output_a_im, res.a_im);\r
-               write_mem(m.output_b_re, res.b_re);\r
-               write_mem(m.output_b_im, res.b_im);\r
+INLINE void write_output_regular(struct mems m, struct bf_out res, bool second_half, enum out_strategy out_s) {\r
+       if (out_s == REGULAR_OUT) {\r
+               /* Skip a memory on each cycle during the regular stages */\r
+               add_offset(m.output_a_re, 2);\r
+               add_offset(m.output_a_im, 2);\r
+               add_offset(m.output_b_re, 2);\r
+               add_offset(m.output_b_im, 2);\r
        } else {\r
        } else {\r
-               /* Write a results to memory b and v.v. */\r
+               /* Simply write output linearly */\r
+               add_offset(m.output_a_re, 1);\r
+               add_offset(m.output_a_im, 1);\r
+               add_offset(m.output_b_re, 1);\r
+               add_offset(m.output_b_im, 1);\r
+       }\r
+       if (out_s == BITREVERSED_OUT) {\r
+               /* \r
+                 Use the memories (which are n_t - 1 bits wide) bitreversed.\r
+                 Since we are generating the samples in sequence (0, 1, 2, 3,\r
+                 ...) but are writing them to two different memories (0, 8,\r
+                 1, 9, ...) The last bit is already bitreversed, so in effect\r
+                 we have fully bitreversed the results. Note that this holds\r
+                 in the non-distributed case (Q = 1), but might also hold in\r
+                 the distributed case (if the tile numbers are bitreversed\r
+                 before concatenating memory).\r
+               */\r
+               use_bitreverse(m.output_a_re, PARAM_n_t - 1);\r
+               use_bitreverse(m.output_a_im, PARAM_n_t - 1);\r
+               use_bitreverse(m.output_b_re, PARAM_n_t - 1);\r
+               use_bitreverse(m.output_b_im, PARAM_n_t - 1);\r
+       }\r
+       \r
+       if (out_s == REGULAR_OUT && second_half) {\r
+               /* When in the regular stages, reverse memory a and b during\r
+                * the second half */\r
                write_mem(m.output_a_re, res.b_re);\r
                write_mem(m.output_a_im, res.b_im);\r
                write_mem(m.output_b_re, res.a_re);\r
                write_mem(m.output_b_im, res.a_im);\r
                write_mem(m.output_a_re, res.b_re);\r
                write_mem(m.output_a_im, res.b_im);\r
                write_mem(m.output_b_re, res.a_re);\r
                write_mem(m.output_b_im, res.a_im);\r
+       } else {\r
+               /* Simply write a to mem a and b to mem b */\r
+               write_mem(m.output_a_re, res.a_re);\r
+               write_mem(m.output_a_im, res.a_im);\r
+               write_mem(m.output_b_re, res.b_re);\r
+               write_mem(m.output_b_im, res.b_im);\r
        }\r
 }\r
 \r
        }\r
 }\r
 \r
@@ -132,36 +159,46 @@ INLINE void init_input_addresses_regular(struct mems m) {
  * Initializes the addresses for reading the inputs. This function must be\r
  * called twice per stage, since halfway the stage the addressing changes.\r
  */\r
  * Initializes the addresses for reading the inputs. This function must be\r
  * called twice per stage, since halfway the stage the addressing changes.\r
  */\r
-INLINE void init_output_addresses_regular(struct mems m, bool second_half) {\r
+INLINE void init_output_addresses_regular(struct mems m, bool second_half, enum out_strategy out_s) {\r
+       /* Only reset the memory addresses for the second half for the regular\r
+        * stages */\r
+       if (out_s != REGULAR_OUT && second_half)\r
+               return;\r
        /* \r
         * For the second half of the stage, the starting addresses are \r
         * reversed. write_output_regular above will also swap the output\r
         * memories.\r
         * TODO: Better comments :-)\r
         */\r
        /* \r
         * For the second half of the stage, the starting addresses are \r
         * reversed. write_output_regular above will also swap the output\r
         * memories.\r
         * TODO: Better comments :-)\r
         */\r
-\r
        set_base(m.output_a_re, 0);\r
        set_base(m.output_a_im, 0);\r
        set_base(m.output_b_re, 0);\r
        set_base(m.output_b_im, 0);\r
        set_base(m.output_a_re, 0);\r
        set_base(m.output_a_im, 0);\r
        set_base(m.output_b_re, 0);\r
        set_base(m.output_b_im, 0);\r
-       \r
-       /* We subtract two from every address, since write_output_regular \r
-        * adds two to the offset before writing the first (and every other) \r
-        * result. */\r
-       if (second_half) {\r
-               set_offset(m.output_a_re, 1-2);\r
-               set_offset(m.output_a_im, 1-2);\r
-               set_offset(m.output_b_re, 0-2);\r
-               set_offset(m.output_b_im, 0-2);\r
+       if (out_s == REGULAR_OUT) {\r
+               /* We subtract two from every address, since write_output_regular \r
+                * adds two to the offset before writing the first (and every other) \r
+                * result. */\r
+               if (second_half) {\r
+                       set_offset(m.output_a_re, 1-2);\r
+                       set_offset(m.output_a_im, 1-2);\r
+                       set_offset(m.output_b_re, 0-2);\r
+                       set_offset(m.output_b_im, 0-2);\r
+               } else {\r
+                       set_offset(m.output_a_re, 0-2);\r
+                       set_offset(m.output_a_im, 0-2);\r
+                       set_offset(m.output_b_re, 1-2);\r
+                       set_offset(m.output_b_im, 1-2);\r
+               }\r
        } else {\r
        } else {\r
-               set_offset(m.output_a_re, 0-2);\r
-               set_offset(m.output_a_im, 0-2);\r
-               set_offset(m.output_b_re, 1-2);\r
-               set_offset(m.output_b_im, 1-2);\r
+               /* Write sequentially, starting at 0 for both memories */\r
+               set_offset(m.output_a_re, 0-1);\r
+               set_offset(m.output_a_im, 0-1);\r
+               set_offset(m.output_b_re, 0-1);\r
+               set_offset(m.output_b_im, 0-1);\r
        }\r
 }\r
 \r
        }\r
 }\r
 \r
-INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){\r
+INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half, enum in_strategy in_s, enum out_strategy out_s){\r
         /*\r
         * We are doing two cycles in each iteration, so we can alternate the\r
         * cycle_odd argument (which only works with constants, I don't expect\r
         /*\r
         * We are doing two cycles in each iteration, so we can alternate the\r
         * cycle_odd argument (which only works with constants, I don't expect\r
@@ -177,7 +214,7 @@ INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){
         */\r
 \r
        /* Initialize output addresses, this must be done twice per stage */\r
         */\r
 \r
        /* Initialize output addresses, this must be done twice per stage */\r
-       init_output_addresses_regular(m, second_half);\r
+       init_output_addresses_regular(m, second_half, out_s);\r
 \r
        /* First cycle (no previous output to write) */\r
        struct bf_in in = read_input_regular(m, EVEN_CYCLE, stage);\r
 \r
        /* First cycle (no previous output to write) */\r
        struct bf_in in = read_input_regular(m, EVEN_CYCLE, stage);\r
@@ -189,7 +226,7 @@ INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){
        init_loop(LC2, (PARAM_N_t / 8) - 1 - 1);\r
        do {\r
                /* Write outputs of previous cycle */\r
        init_loop(LC2, (PARAM_N_t / 8) - 1 - 1);\r
        do {\r
                /* Write outputs of previous cycle */\r
-               write_output_regular(m, out, second_half);\r
+               write_output_regular(m, out, second_half, out_s);\r
 \r
                /* Odd cycle */\r
                in = read_input_regular(m, ODD_CYCLE, stage);\r
 \r
                /* Odd cycle */\r
                in = read_input_regular(m, ODD_CYCLE, stage);\r
@@ -197,7 +234,7 @@ INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){
                next_cycle();\r
 \r
                /* Write outputs of previous cycle */\r
                next_cycle();\r
 \r
                /* Write outputs of previous cycle */\r
-               write_output_regular(m, out, second_half);\r
+               write_output_regular(m, out, second_half, out_s);\r
 \r
                /* Even cycle */\r
                in = read_input_regular(m, EVEN_CYCLE, stage);\r
 \r
                /* Even cycle */\r
                in = read_input_regular(m, EVEN_CYCLE, stage);\r
@@ -205,7 +242,7 @@ INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){
        } while (loop_next(LC2));\r
        \r
        /* Write outputs of previous cycle */\r
        } while (loop_next(LC2));\r
        \r
        /* Write outputs of previous cycle */\r
-       write_output_regular(m, out, second_half);\r
+       write_output_regular(m, out, second_half, out_s);\r
 \r
        /* Last cycle */\r
        in = read_input_regular(m, ODD_CYCLE, stage);\r
 \r
        /* Last cycle */\r
        in = read_input_regular(m, ODD_CYCLE, stage);\r
@@ -213,7 +250,7 @@ INLINE void do_half_regular_stage(struct mems m, int stage, bool second_half){
        next_cycle();\r
 \r
        /* Write outputs of last cycle */\r
        next_cycle();\r
 \r
        /* Write outputs of last cycle */\r
-       write_output_regular(m, out, second_half);\r
+       write_output_regular(m, out, second_half, out_s);\r
        \r
        /* Force the next cycle, because the next stage must read from\r
         * the memory we just wrote to */\r
        \r
        /* Force the next cycle, because the next stage must read from\r
         * the memory we just wrote to */\r
@@ -254,22 +291,23 @@ INLINE struct mems init_mem_mapping(int stage){
        return res;\r
 }\r
 \r
        return res;\r
 }\r
 \r
-INLINE void do_regular_stage(int stage)\r
+INLINE void do_regular_stage(int stage, enum in_strategy in_s, enum out_strategy out_s)\r
 {\r
        struct mems m = init_mem_mapping(stage);\r
        init_input_addresses_regular(m);\r
        /* do_half_regular_stage will init output addresses */\r
        next_cycle();\r
 {\r
        struct mems m = init_mem_mapping(stage);\r
        init_input_addresses_regular(m);\r
        /* do_half_regular_stage will init output addresses */\r
        next_cycle();\r
-       do_half_regular_stage(m, stage, FIRST_HALF);\r
-       do_half_regular_stage(m, stage, SECOND_HALF);\r
+       do_half_regular_stage(m, stage, FIRST_HALF, in_s, out_s);\r
+       do_half_regular_stage(m, stage, SECOND_HALF, in_s, out_s);\r
 }\r
 }\r
+\r
 void run() {\r
        do { freeze(); } while (gpi(0) == 0);\r
 \r
 void run() {\r
        do { freeze(); } while (gpi(0) == 0);\r
 \r
-       do_regular_stage(1);\r
-       do_regular_stage(2);\r
-       do_regular_stage(3);\r
-       do_regular_stage(4);\r
+       do_regular_stage(1, REGULAR_IN, REGULAR_OUT);\r
+       do_regular_stage(2, REGULAR_IN, REGULAR_OUT);\r
+       do_regular_stage(3, REGULAR_IN, REGULAR_OUT);\r
+       do_regular_stage(4, REGULAR_IN, BITREVERSED_OUT);\r
        \r
        set_gpo(0);\r
        next_cycle();\r
        \r
        set_gpo(0);\r
        next_cycle();\r