diff --git a/dataflow_neuro/chips.act b/dataflow_neuro/chips.act index f68ab40..5091cd0 100644 --- a/dataflow_neuro/chips.act +++ b/dataflow_neuro/chips.act @@ -106,7 +106,7 @@ defproc chip_texel (bd in, out; NC_NRN = NC_NRN_X + NC_NRN_Y; nrn_hs_2d_array nrn_grid(.in = neurons, .supply = supply, .reset_B = reset_B); - encoder2d_simple encoder( + encoder2d_simple encoder( .inx = nrn_grid.outx, .iny = nrn_grid.outy, .reset_B = reset_B, .supply = supply diff --git a/dataflow_neuro/coders.act b/dataflow_neuro/coders.act index 676c7a8..23273c6 100644 --- a/dataflow_neuro/coders.act +++ b/dataflow_neuro/coders.act @@ -774,7 +774,7 @@ defproc decoder_2d_hybrid (avMx1of2 in; a1of1 out[Nx*Ny]; bool? dly_cfg } - export template + export template defproc encoder2d_simple(a1of1 inx[Nx]; a1of1 iny[Ny]; avMx1of2<(NxC + NyC)> out; power supply; bool reset_B) { @@ -827,6 +827,42 @@ defproc decoder_2d_hybrid (avMx1of2 in; a1of1 out[Nx*Ny]; bool? dly_cfg } + export template + defproc encoder1d_simple(a1of1 in[N]; avMx1of2 out; + power supply; bool reset_B) { + + bool _a_x, _r_x; + bool _r_x_B; + + buffer buf(.out = out, .supply = supply, .reset_B = reset_B); + + // Arbiters + arbtree Xarb(.supply = supply); + Xarb.out.a = _a_x; + Xarb.out.r = _r_x; + + // Encoders + dualrail_encoder Xenc(.supply = supply); + + // Wire up inputs to encoders and arb + (i:N: + Xarb.in[i].r = in[i].r; + Xarb.in[i].a = in[i].a; + Xenc.in[i] = in[i].a; + ) + + INV_X2 inv_buf(.a = buf.in.a, .vdd = supply.vdd, .vss = supply.vss); + + A_2C_RB_X1 a_x_Cel(.c1 = inv_buf.y, .c2 = _r_x, .y = _a_x, + .sr_B = reset_B, .pr_B = reset_B, .vdd = supply.vdd, .vss = supply.vss); + + // Wire up encoder to buffer + (i:Nc: + Xenc.out.d[i] = buf.in.d.d[i]; + ) + + } + /** * Neuron handshaking. @@ -839,14 +875,7 @@ defproc decoder_2d_hybrid (avMx1of2 in; a1of1 out[Nx*Ny]; bool? dly_cfg BUF_X2 reset_buf(.a = reset_B, .y = _reset_BX, .vdd = supply.vdd, .vss = supply.vss); bool _en, _req; - - // A_1C2N_RB_X1 A_ack(.c1 = _en, .n1 = _req, .n2 = in.r, .y = in.a, - // .pr_B = _reset_BX, .sr_B = _reset_BX, .vss = supply.vss, .vdd = supply.vdd); - // Switched it back - // Because had the problem that if the req was not removed in time, - // it would be recounted as a double spike, - // since in.req is still high after the out has been dealt with. A_2C1N_RB_X1 A_ack(.c1 = _en, .c2 = in.r, .n1 = _req, .y = in.a, .pr_B = _reset_BX, .sr_B = _reset_BX, .vss = supply.vss, .vdd = supply.vdd); @@ -858,19 +887,23 @@ defproc decoder_2d_hybrid (avMx1of2 in; a1of1 out[Nx*Ny]; bool? dly_cfg INV_X2 inv_x(.a = outx.a, .y = _x_a_B, .vss = supply.vss, .vdd = supply.vdd); INV_X2 inv_y(.a = outy.a, .y = _y_a_B, .vss = supply.vss, .vdd = supply.vdd); + + // WARNUNG WARNUNG WARNUNG // + // This neuron hs design has a fat timing assumption. + // Say that the neuron has sent out both reqs, and is now receiving the acks. + // _x_a_B and _y_a_B are then low, and _req starts to be pulled down to reset the hs. + // However, if the line pull downs at the end of the neuron row/column are fast enough, + // then seeing the high acks, they will pull the ack lines down. If the arbiter tree + // is sufficiently fast enough, then it will remove the ack lines. + // If this cell were rather tardy, then _req's pd would be cancelled midway, + // it missed its window of opportunity to switch, and would probably make the system hang. + // Or starts oscillating with the line pull down and goes brrrrapppppppp. + // This issue may be somewhat unavoidable, as from a black box perspective, + // we are giving the neuron acks, but then not listening to it at all to check + // that it has had time to act upon these acks. A_2C1P1N_RB_X1 A_req(.p1 = _x_a_B, .c1 = _en, .c2 = _y_a_B, .n1 = in.r, .y = _req, .pr_B = _reset_BX, .sr_B = _reset_BX, .vdd = supply.vdd, .vss = supply.vss); - // // y_req pull up - // NAND2_X1 nand_y(.a = _y_a_B, .b = _req, .vdd = supply.vdd, .vss = supply.vss); - // A_1P_U_X4 pu_y(.a = nand_y.y, .y = outy.r, .vdd = supply.vdd, .vss = supply.vss); - - // // x_req pull up - // NAND3_X1 nand_x(.a = _x_a_B, .b = _req, .c = outy.a, .vdd = supply.vdd, .vss = supply.vss); - // A_1P_U_X4 pu_x(.a = nand_x.y, .y = outx.r, .vdd = supply.vdd, .vss = supply.vss); - - // Better version with fewer timing assumptions - // Core change is that the out acks stop the pullups without any delay. // y_req pull up bool _reqB; INV_X1 req_inv(.a = _req, .y = _reqB, .vdd= supply.vdd, .vss = supply.vss);