diff --git a/dataflow_neuro/primitives.act b/dataflow_neuro/primitives.act index 7d3a97b..833a450 100644 --- a/dataflow_neuro/primitives.act +++ b/dataflow_neuro/primitives.act @@ -507,6 +507,122 @@ namespace tmpl { BUF_X1 reset_buf(.a=reset_B, .y=_reset_BX,.vdd=supply.vdd,.vss=supply.vss); } + // A tree composed by arbiters. The first layer takes N signals + export template + defproc arbiter_tree(a1of1 in[N]; a1of1 out; power supply) + { + + bool tout; + + { N > 0 : "Invalid N, should be greater than 0" }; + + /* We calculate here how many arbiters we need to create for the full tree */ + pint inputs_in_layer, end, elements_in_layer; + pint odd_element_idx = 0; + pint odd_element_flag = 0; + inputs_in_layer = 0; + end = N-1; + pint element_counter = 0; + // Here we start a for loop to count the elements in the tree + // The loop iterates for every successive layer + // i is the variable used to iterate the inputs, + // j counts the elements in the layer + *[ inputs_in_layer != end -> + elements_in_layer = 0; // At every layer the counter of the elements is resetted + *[ inputs_in_layer < end -> + [ inputs_in_layer + 1 >= end -> + //In this case, the number of input is even: the layer finishes + inputs_in_layer = end; + odd_element_flag = 0; + [] inputs_in_layer + 2 >= end -> + //In this case, we arrived at the last input, this means the inputs are odd + //We need to save the odd input index and move it to the next layer, + //up to when the resulting number is even + odd_element_idx = end; + odd_element_flag = 1; + inputs_in_layer = end; + [] else -> + //If we are not close to the end, analyzes the next two inputs + inputs_in_layer = inputs_in_layer +2; + ] + elements_in_layer = elements_in_layer + 1; //At every step the elements count is updated + + ] + //Move the inputs_in_layer to the next layer + //Increase the end to account for the next layer elements + //If there was an odd element, count it also in the end + inputs_in_layer = end + 1; + end = end + elements_in_layer + odd_element_flag; + element_counter = element_counter + elements_in_layer; + ] + + { element_counter = 4 : "Michele you did wrong" }; + + // Creating the elements of the tree + arbiter_handshake arb_array[element_counter]; + (i:element_counter:arb_array[i].supply = supply;) + // These are the wires that connect one element of the tree to the others + a1of1 channels[element_counter*2]; + + //Connecting the first channels to the inputs + (i:N:channels[i] = in[i];) + channels[element_counter*2-1] = out; + //Now we redo the for loop but here to assign the channels to the elements + odd_element_idx = 0; + odd_element_flag = 0; + inputs_in_layer = 0; + end = N-1; + { end=4 : "Michele you did wrong" }; + // Here we start a for loop to count the elements in the tree + // The loop iterates for every successive layer + // i is the variable used to iterate the inputs, + // j counts the elements in the layer + *[ inputs_in_layer != end -> + elements_in_layer = 0; // At every layer the counter of the elements is resetted + *[ inputs_in_layer < end -> + [ inputs_in_layer + 1 >= end -> + //In this case, the number of input is even: the layer finishes + [ odd_element_flag >= 1 -> + arb_array[elements_in_layer].in1 = channels[inputs_in_layer]; + arb_array[elements_in_layer].in2 = channels[odd_element_idx]; + [] else -> + arb_array[elements_in_layer].in1 = channels[inputs_in_layer]; + arb_array[elements_in_layer].in2 = channels[inputs_in_layer+1]; + ] + inputs_in_layer = end; + odd_element_flag = 0; + [] inputs_in_layer + 2 >= end -> + //In this case, we arrived at the last input, this means the inputs are odd + //We need to save the odd input index and move it to the next layer, + //up to when the resulting number is even + odd_element_idx = end; + odd_element_flag = 1; + { end<8 : "Michele you did wrong" }; + { odd_element_idx=4 : "Michele you did wrong" }; + arb_array[elements_in_layer].in1 = channels[inputs_in_layer]; + arb_array[elements_in_layer].in2 = channels[inputs_in_layer+1]; + inputs_in_layer = end; + [] else -> + //If we are not close to the end, analyzes the next two inputs + arb_array[elements_in_layer].in1 = channels[inputs_in_layer]; + arb_array[elements_in_layer].in2 = channels[inputs_in_layer+1]; + inputs_in_layer = inputs_in_layer +2; + + ] + elements_in_layer = elements_in_layer + 1; //At every step the elements count is updated + + ] + //Move the inputs_in_layer to the next layer + //Increase the end to account for the next layer elements + //If there was an odd element, count it also in the end + inputs_in_layer = end + 1; + end = end + elements_in_layer + odd_element_flag; + element_counter = element_counter + elements_in_layer; + ] + + + + } export template defproc merge (avMx1of2 in1; avMx1of2 in2; avMx1of2 out ; bool? reset_B; power supply) { diff --git a/test/unit_tests/arbiter_tree_test/run/test.prs b/test/unit_tests/arbiter_tree_test/run/test.prs new file mode 100644 index 0000000..02d06ef --- /dev/null +++ b/test/unit_tests/arbiter_tree_test/run/test.prs @@ -0,0 +1,3 @@ += "GND" "GND" += "Vdd" "Vdd" += "Reset" "Reset" diff --git a/test/unit_tests/arbiter_tree_test/test.act b/test/unit_tests/arbiter_tree_test/test.act new file mode 100644 index 0000000..249aa2d --- /dev/null +++ b/test/unit_tests/arbiter_tree_test/test.act @@ -0,0 +1,62 @@ +/************************************************************************* + * + * This file is part of ACT dataflow neuro library. + * It's the testing facility for cell_lib_std.act + * + * Copyright (c) 2022 University of Groningen - Ole Richter + * Copyright (c) 2022 University of Groningen - Hugh Greatorex + * Copyright (c) 2022 University of Groningen - Michele Mastella + * Copyright (c) 2022 University of Groningen - Madison Cotteret + * + * This source describes Open Hardware and is licensed under the CERN-OHL-W v2 or later + * + * You may redistribute and modify this documentation and make products + * using it under the terms of the CERN-OHL-W v2 (https:/cern.ch/cern-ohl). + * This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY + * AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-W v2 + * for applicable conditions. + * + * Source location: https://git.web.rug.nl/bics/actlib_dataflow_neuro + * + * As per CERN-OHL-W v2 section 4.1, should You produce hardware based on + * these sources, You must maintain the Source Location visible in its + * documentation. + * + ************************************************************************** + */ + +import "../../dataflow_neuro/primitives.act"; +import globals; + +open tmpl::dataflow_neuro; + + +defproc arbiter_treee (a1of1 in[5]; a1of1 out) +{ + a1of1 _in[5]; + power _supply + _supply.vdd = Vdd; + _supply.vss = GND; + + fifo_t<2> fifo_to_tree[5]; + (i:5: + fifo_to_tree[i].in = in[i]; + fifo_to_tree[i].out = _in[i]; + fifo_to_tree.supply = _supply; + fifo_to_tree.reset_B = _reset_B; + ) + + arbiter_tree<5> at_cell(.in=_in, .out = out); + + //Low active Reset + bool _reset_B; + prs { + Reset => _reset_B- + } + + at_cell.supply = _supply; + +} + +arbiter_treee my_tree; diff --git a/test/unit_tests/arbiter_tree_test/test.prsim b/test/unit_tests/arbiter_tree_test/test.prsim new file mode 100644 index 0000000..65294dd --- /dev/null +++ b/test/unit_tests/arbiter_tree_test/test.prsim @@ -0,0 +1,64 @@ + +watchall +set Reset 1 +set my_tree.in[0].r 0 +set my_tree.in[1].r 0 +set my_tree.in[2].r 0 +set my_tree.in[3].r 0 +set my_tree.in[4].r 0 +set my_tree.out.a 0 + +cycle + +assert my_tree.in[0].a 0 +assert my_tree.in[1].a 0 +assert my_tree.in[2].a 0 +assert my_tree.in[3].a 0 +assert my_tree.in[4].a 0 +assert my_tree.out.r 0 + +system "echo '-------------------------------------------------'" +system "echo '[0] System initialized'" + +set Reset 0 +cycle +system "echo '-------------------------------------------------'" +system "echo '[1] System reset completed'" + +set in[0].r 1 +set in[2].r 1 +set in[4].r 1 + +cycle + +assert out.r 1 +set out.a 1 +cycle + +assert out.r 0 +set out.a 0 + +cycle + +assert out.r 1 +set out.a 1 +cycle + +assert out.r 0 +set out.a 0 + +cycle + +assert out.r 1 +set out.a 1 +cycle + +assert out.r 0 +set out.a 0 + +cycle + + +system "echo '-------------------------------------------------'" +system "echo '[3] Sent three inputs, received 3 outputs'" +