From 5928dc9f42d26a4d0152cd811443839338c60cb4 Mon Sep 17 00:00:00 2001 From: alexmadison Date: Mon, 21 Feb 2022 15:54:10 +0100 Subject: [PATCH] init rewriting tree gates --- dataflow_neuro/treegates.act | 229 +++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 dataflow_neuro/treegates.act diff --git a/dataflow_neuro/treegates.act b/dataflow_neuro/treegates.act new file mode 100644 index 0000000..d68557c --- /dev/null +++ b/dataflow_neuro/treegates.act @@ -0,0 +1,229 @@ +/************************************************************************* + * + * This file is part of ACT dataflow neuro library + * + * Copyright (c) 2022 University of Groningen - Ole Richter + * Copyright (c) 2021 Rajit Manohar + * + * 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. + * + ************************************************************************** +namespace std { + +export namespace gates { + +/* + * Build an OR-gate tree (NOR/NAND/optional INV) + */ +export template +defproc ortree (bool? in[N]; bool out) +{ + bool tout; + + { N > 0 : "What?" }; + + pint i, end, j; + pbool isinv; + isinv = false; + i = 0; + end = N-1; + + /* dynamic array that holds all the nodes in the completion tree */ + bool tmp[N]; + (k:N:tmp[k] = in[k];) + + /* Invariant: i <= end */ + + *[ 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; + bool tmp[end+j..end+j]; + [ i+2 >= end -> + /*-- last piece: use either a 2 or 3 input NAND/NOR gate --*/ + [isinv -> + prs { (&k:i..end:tmp[k]) => tmp[end+j]- } + [] else -> + prs { (|k:i..end:tmp[k]) => tmp[end+j]- } + ] + i = end; + [] else -> + /*-- more to come; so use a two input C-element --*/ + [isinv -> + prs { (&k:i..i+1:tmp[k]) => tmp[end+j]- } + [] else -> + prs { (|k:i..i+1:tmp[k]) => tmp[end+j]- } + ] + i = i + 2; + ] + sizing { + leak_adjust <- 1; + p_n_mode <- 1; + tmp[end+j]{-1} + } + ] + /*-- we just added an inverting layer --*/ + isinv = ~isinv; + + /*-- update range that has to be combined --*/ + i = end+1; + end = end+j; + j = 0; + ] + + isinv = invert ? ~isinv : isinv; + + /*-- invert the signal if needed --*/ + [isinv -> prs { tmp[end] => out- } + [] else -> tmp[end] = out; + ] + [isinv -> + sizing { + leak_adjust <- 1; + p_n_mode <- 1; + out{-1} + } + ] +} + +/* + * Build a completion tree using a combination of 2-input and 3-input + * C-elements + */ +export template +defproc ctree (bool? in[N]; bool out) +{ + bool tout; + + { N > 0 : "What?" }; + + pint i, end, j; + pbool isinv; + isinv = invert; + i = 0; + end = N-1; + + pint lenTree2Count, lenTree3Count; + /* Pre"calculate" the number of C cells required, look below if confused */ + *[ i != end -> + j = 0; + *[ i < end -> + j = j + 1; + [ i+1 >= end -> + i = end; + lenTree2Count = lenTree2Count +1; + [] i+2 >= end -> + i = end; + lenTree3Count = lenTree3Count +1; + [] else -> + i = i + 2; + lenTree2Count = lenTree2Count +1; + ] + ] + /*-- update range that has to be combined --*/ + i = end+1; + end = end+j; + j = 0; + ] + + /* array that holds ALL the nodes in the completion tree */ + bool tmp[end]; + (k:N:tmp[k] = in[k];) + + /* array to hold the actual C-elments, either A2C or A3C */ + A_2C_B_X1 C2Els[lenTree2Count]; + A_3C_B_X1 C3Els[lenTree3Count]; + + /* Reset the variables we just stole lol */ + i = 0; + end = N-1; + j = 0; + pint tree2Index = 0; + pint tree3Index = 0; + + /* Invariant: i <= end */ + + *[ 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; + bool tmp[end+j..end+j]; + [ i+1 >= end -> + /*-- last piece: use either a 2 input C-element --*/ + C2Els[tree2Index](.c1 = tmp[i], .c2 = tmp[i+1], .y = tmp[end+j]) + tree2Index = tree2Index +1; + i = end; + [] i+2 >= end -> + /*-- last piece: use either a 3 input C-element --*/ + C3Els[tree3Index](.c1 = tmp[i], .c2 = tmp[i+1], .c3 = tmp[i+2], .y = tmp[end+j]) + tree3Index = tree3Index +1; + i = end; + [] else -> + /*-- more to come; so use a two input C-element --*/ + C2Els[tree2Index](.c1 = tmp[i], .c2 = tmp[i+1], .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; + ] +} + +export template +defproc sigbuf (bool? in; bool! out; power supply) +{ + + { N >= 0 : "sigbuf: parameter error" }; + { N <= 43 : "sigbuf: parameter error, N too big" }; + + /* -- just use a sized driver here -- */ + [ N <= 4 -> + BUF_X1 buf; + + [] N >= 5 & N <= 7 -> + BUF_X2 buf; + [] N >= 8 & N <= 10 -> + BUF_X3 buf; + [] N >= 11 & N <= 14 -> + BUF_X4 buf; + [] N >= 15 & N <= 18 -> + BUF_X6 buf; + [] N >= 19 & N <= 29 -> + BUF_X8 buf; + [] N >= 30 & N <= 42 -> + BUF_X12 buf; + ] + buf.a = in; + buf.y = out; + buf.vdd = supply.vdd; + buf.vss = supply.vss; +} +