diff --git a/dataflow_neuro/primitives.act b/dataflow_neuro/primitives.act index a76a1c6..ea23e93 100644 --- a/dataflow_neuro/primitives.act +++ b/dataflow_neuro/primitives.act @@ -507,6 +507,107 @@ 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 : "What?" }; + + /* We calculate here how many elements we need to create the full tree */ + pint i, end, j; + i = 0; + end = N-1; + + pint lenTree2Count, lenTree3Count; + pint odd_one_idx = 0; + pbool odd_one_flag = 0; + lenTree2Count = 0; + *[ i != end -> + j = 0; + *[ i < end -> + j = j + 1; + [ i+1 >= end -> + i = end; + lenTree2Count = lenTree2Count +1; + + [] i >= end -> + i = end; + odd_one_idx = i; + odd_one_flag = 1; + [] else -> + i = i + 2; + lenTree2Count = lenTree2Count +1; + ] + ] + /*-- update range that has to be combined --*/ + i = end+1; + end = end+j+odd_one_flag; + ] + /* array that holds ALL the wires in the completion tree */ + a1of1 wire[end+1]; + // Connecting the first nodes to the input + (l:N: + wire[l] = in[l]; + ) + [lenTree2Count > 0 -> + arbiter_handshake arb_array[lenTree2Count]; + ] + (h:lenTree2Count:arb_array[h].vdd = supply.vdd;) + (h:lenTree2Count:arb_array[h].vss = supply.vss;) + + /* Reset the variables before the assigmnent of the nodes to the cells */ + i = 0; + end = N-1; + j = 0; + pint tree2Index = 0; + pint tree3Index = 0; + *[ i != end -> + /* + * Invariant: tmp[i..end] has the current signals that need to be + * combined together, and "isinv" specifies if they are the inverted + * sense or not + */ + j = 0; + *[ i < end -> + /*-- there are still signals that need to be combined --*/ + j = j + 1; + [ i+1 >= end -> + /*-- last piece: use either a 2 input C-element --*/ + C2Els[tree2Index].a = wire[i]; + C2Els[tree2Index].b = wire[i+1]; + C2Els[tree2Index].y = wire[end+j]; + tree2Index = tree2Index +1; + i = end; + [] i+2 >= end -> + /*-- last piece: use either a 3 input C-element --*/ + C3Els[tree3Index].a = tmp[i]; + C3Els[tree3Index].b = tmp[i+1]; + C3Els[tree3Index].c = tmp[i+2]; + C3Els[tree3Index].y = tmp[end+j]; + + tree3Index = tree3Index +1; + i = end; + [] else -> + /*-- more to come; so use a two input C-element --*/ + C2Els[tree2Index].a = tmp[i]; + C2Els[tree2Index].b = tmp[i+1]; + C2Els[tree2Index].y = tmp[end+j]; + tree2Index = tree2Index +1; + i = i + 2; + ] + ] + /*-- update range that has to be combined --*/ + i = end+1; + end = end+j; + j = 0; + ] + + out = tmp[end]; + + } export template defproc merge (avMx1of2 in1; avMx1of2 in2; avMx1of2 out ; bool? reset_B; power supply) {