diff options
Diffstat (limited to 'platform/wavelet3d/gfx_raster.sv')
| -rw-r--r-- | platform/wavelet3d/gfx_raster.sv | 930 |
1 files changed, 0 insertions, 930 deletions
diff --git a/platform/wavelet3d/gfx_raster.sv b/platform/wavelet3d/gfx_raster.sv deleted file mode 100644 index a57a672..0000000 --- a/platform/wavelet3d/gfx_raster.sv +++ /dev/null @@ -1,930 +0,0 @@ -module gfx_raster -( - input logic clk, - rst_n, - - gfx_pkts.rx geometry, - - gfx_pkts.tx coverage -); - - import gfx::*; - - gfx_raster_bounds setup_bounds - ( - .clk, - .rst_n, - - .geometry, - - .edges_ref(bounds_edges_ref), - .edges_vtx(bounds_edges_vtx), - .edges_span(bounds_edges_span), - .edges_ready(bounds_edges_ready), - .edges_valid(bounds_edges_valid), - .edges_geom_id(bounds_edges_geom_id) - ); - - word bounds_edges_geom_id; - logic bounds_edges_ready, bounds_edges_valid; - vtx_xy bounds_edges_vtx; - fixed_xy bounds_edges_ref; - raster_prec_xy bounds_edges_span; - - gfx_raster_edges setup_edges - ( - .clk, - .rst_n, - - .bounds_ref(bounds_edges_ref), - .bounds_vtx(bounds_edges_vtx), - .bounds_span(bounds_edges_span), - .bounds_ready(bounds_edges_ready), - .bounds_valid(bounds_edges_valid), - .bounds_geom_id(bounds_edges_geom_id), - - .coarse_ref(edges_coarse_ref), - .coarse_base(edges_coarse_base), - .coarse_span(edges_coarse_span), - .coarse_ready(edges_coarse_ready), - .coarse_valid(edges_coarse_valid), - .coarse_geom_id(edges_coarse_geom_id), - .coarse_offsets(edges_coarse_offsets) - ); - - word edges_coarse_geom_id; - fixed edges_coarse_base; - logic edges_coarse_ready, edges_coarse_valid; - fixed_xy edges_coarse_ref; - raster_prec_xy edges_coarse_span; - raster_offsets_xy edges_coarse_offsets; - - gfx_raster_coarse coarse - ( - .clk, - .rst_n, - - .edges_ref(edges_coarse_ref), - .edges_base(edges_coarse_base), - .edges_span(edges_coarse_span), - .edges_ready(edges_coarse_ready), - .edges_valid(edges_coarse_valid), - .edges_geom_id(edges_coarse_geom_id), - .edges_offsets(edges_coarse_offsets), - - .fine_ref(coarse_fine_ref), - .fine_ready(coarse_fine_ready), - .fine_valid(coarse_fine_valid), - .fine_corner(coarse_fine_corner), - .fine_geom_id(coarse_fine_geom_id), - .fine_offsets(coarse_fine_offsets) - ); - - word coarse_fine_geom_id; - fixed coarse_fine_corner; - logic coarse_fine_ready, coarse_fine_valid; - fixed_xy coarse_fine_ref; - raster_offsets_xy coarse_fine_offsets; - - gfx_raster_fine fine - ( - .clk, - .rst_n, - - .coarse_ref(coarse_fine_ref), - .coarse_ready(coarse_fine_ready), - .coarse_valid(coarse_fine_valid), - .coarse_corner(coarse_fine_corner), - .coarse_geom_id(coarse_fine_geom_id), - .coarse_offsets(coarse_fine_offsets), - - .coverage - ); - -endmodule - -module gfx_raster_bounds -( - input logic clk, - rst_n, - - gfx_pkts.rx geometry, - - input logic edges_ready, - output logic edges_valid, - output gfx::word edges_geom_id, - output gfx::fixed_xy edges_ref, - output gfx::raster_prec_xy edges_span, - output gfx::vtx_xy edges_vtx -); - - import gfx::*; - - enum int unsigned - { - IN_GEOM_ID, - IN_DIM_X, - IN_DIM_Y - } in_state; - - enum int unsigned - { - VTX_A, - VTX_B, - VTX_C - } vtx_state; - - logic a_lt_b, a_lt_c, b_lt_c, edges_handshake, geom_complete, geom_last, - geom_recv, in_vtx, next_dim, new_vtx; - - logic end_new_dim, end_valid, vtx_valid, lt_new_dim, lt_valid, minmax_new_dim, minmax_valid; - - fixed geom_data; - vtx_fixed dim_vtx, dim_vtx_x, dim_vtx_y; - raster_prec max, min; - - assign geom_recv = geometry.tready & geometry.tvalid; - assign edges_handshake = edges_valid & edges_ready; - - assign edges_vtx.a.x = dim_vtx_x.a; - assign edges_vtx.a.y = dim_vtx_y.a; - assign edges_vtx.b.x = dim_vtx_x.b; - assign edges_vtx.b.y = dim_vtx_y.b; - assign edges_vtx.c.x = dim_vtx_x.c; - assign edges_vtx.c.y = dim_vtx_y.c; - - assign geometry.tready = edges_handshake | ~geom_complete; - - always_comb begin - unique case (vtx_state) - VTX_C: next_dim = geom_recv; - default: next_dim = 0; - endcase - - unique case (in_state) - IN_DIM_Y: geom_last = next_dim; - default: geom_last = 0; - endcase - end - - always_ff @(posedge clk or negedge rst_n) - if (~rst_n) begin - in_state <= IN_GEOM_ID; - vtx_state <= VTX_A; - - in_vtx <= 0; - new_vtx <= 0; - geom_complete <= 0; - - lt_valid <= 0; - end_valid <= 0; - vtx_valid <= 0; - edges_valid <= 0; - minmax_valid <= 0; - - lt_new_dim <= 0; - end_new_dim <= 0; - minmax_new_dim <= 0; - - edges_geom_id <= 'x; - end else begin - end_valid <= 0; - vtx_valid <= end_valid; - lt_valid <= vtx_valid; - minmax_valid <= lt_valid; - - if (~edges_valid | edges_ready) - edges_valid <= minmax_valid; - - geom_complete <= (geom_complete | geom_last) & ~edges_handshake; - - unique case (in_state) - IN_GEOM_ID: - if (geom_recv) begin - in_state <= IN_DIM_X; - - in_vtx <= 1; - edges_geom_id <= geometry.tdata; - end - - IN_DIM_X: - if (next_dim) - in_state <= IN_DIM_Y; - - IN_DIM_Y: - if (next_dim) begin - in_state <= IN_GEOM_ID; - - in_vtx <= 0; - end_valid <= 1; - end - endcase - - new_vtx <= 0; - - lt_new_dim <= 0; - minmax_new_dim <= lt_new_dim; - end_new_dim <= minmax_new_dim; - - unique case (vtx_state) - VTX_A: begin - if (in_vtx & geom_recv) begin - new_vtx <= 1; - vtx_state <= VTX_B; - end - - if (new_vtx) begin - dim_vtx.c <= geom_data; - lt_new_dim <= 1; - end - end - - VTX_B: begin - if (geom_recv) begin - new_vtx <= 1; - vtx_state <= VTX_C; - end - - if (new_vtx) - dim_vtx.a <= geom_data; - end - - VTX_C: begin - if (geom_recv) begin - new_vtx <= 1; - vtx_state <= VTX_A; - end - - if (new_vtx) - dim_vtx.b <= geom_data; - end - endcase - - if (in_state == IN_DIM_Y & next_dim) - assert (geometry.tlast); - end - - always_ff @(posedge clk) begin - geom_data <= geometry.tdata; - - a_lt_b <= $signed(dim_vtx.a) < $signed(dim_vtx.b); - a_lt_c <= $signed(dim_vtx.a) < $signed(dim_vtx.c); - b_lt_c <= $signed(dim_vtx.b) < $signed(dim_vtx.c); - - // Realmente no son 'x' o 'y' hasta cuando edges_valid = 1 - if (lt_new_dim) begin - dim_vtx_y <= dim_vtx; - dim_vtx_x <= dim_vtx_y; - end - - if (a_lt_b) begin - min <= a_lt_c ? dim_vtx_y.a : dim_vtx_y.c; - max <= b_lt_c ? dim_vtx_y.c : dim_vtx_y.b; - end else begin - min <= b_lt_c ? dim_vtx_y.b : dim_vtx_y.c; - max <= a_lt_c ? dim_vtx_y.c : dim_vtx_y.a; - end - - {min.fine, min.sub} <= '0; - {max.fine, max.sub} <= '0; - - if (end_new_dim) begin - edges_ref.y <= min; - edges_ref.x <= edges_ref.y; - - edges_span.y <= max - min; - edges_span.x <= edges_span.y; - end - end - -endmodule - -module gfx_raster_edges -( - input logic clk, - rst_n, - - input logic bounds_valid, - input gfx::word bounds_geom_id, - input gfx::fixed_xy bounds_ref, - input gfx::raster_prec_xy bounds_span, - input gfx::vtx_xy bounds_vtx, - output logic bounds_ready, - - input logic coarse_ready, - output logic coarse_valid, - output gfx::word coarse_geom_id, - output gfx::fixed_xy coarse_ref, - output gfx::raster_prec_xy coarse_span, - output gfx::fixed coarse_base, - output gfx::raster_offsets_xy coarse_offsets -); - - import gfx::*; - - enum int unsigned - { - EDGE_AB, - EDGE_BC, - EDGE_CA, - // EDGE_CA cumple doble función como OFFSETS_AB - OFFSETS_BC, - OFFSETS_CA, - OUT - } state; - - struct - { - fixed_xy cur, - delay1, - delay2; - } inc; - - logic coarse_handshake, coarse_stall, offsets_flow; - fixed_xy delta, p, q; - - // - 2 porque coarse valid va al final - logic[FIXED_DOTADD_DEPTH - 2:0] dotadd_valid; - - assign coarse_stall = coarse_valid & ~coarse_ready; - assign coarse_handshake = coarse_valid & coarse_ready; - - gfx_fixed_dotadd edge_base - ( - .clk, - .c(0), - .q(coarse_base), - .a0(delta.x), - .b0(inc.cur.x), - .a1(delta.y), - .b1(inc.cur.y), - .stall(coarse_stall) - ); - - always_comb - unique case (state) - OUT: offsets_flow = coarse_handshake; - default: offsets_flow = 1; - endcase - - always_ff @(posedge clk or negedge rst_n) - if (~rst_n) begin - state <= EDGE_AB; - - p <= 'x; - q <= 'x; - coarse_ref <= 'x; - coarse_geom_id <= 'x; - - bounds_ready <= 0; - coarse_valid <= 0; - - for (int i = 0; i < $bits(dotadd_valid) - 1; ++i) - dotadd_valid[i] <= 0; - end else begin - for (int i = 1; i < $bits(dotadd_valid); ++i) - dotadd_valid[i] <= dotadd_valid[i - 1]; - - if (~coarse_stall) - coarse_valid <= dotadd_valid[$bits(dotadd_valid) - 1]; - - bounds_ready <= 0; - dotadd_valid[0] <= 0; - - unique case (state) - EDGE_AB: begin - if (bounds_valid) - state <= EDGE_BC; - - coarse_ref <= bounds_ref; - coarse_span <= bounds_span; - coarse_geom_id <= bounds_geom_id; - - p <= bounds_vtx.a; - q <= bounds_vtx.b; - end - - EDGE_BC: begin - state <= EDGE_CA; - bounds_ready <= 1; - - p <= bounds_vtx.b; - q <= bounds_vtx.c; - end - - EDGE_CA: begin - state <= OFFSETS_BC; - - p <= bounds_vtx.c; - q <= bounds_vtx.a; - - // Esto ocurre justamente en un momento en que ab, bc, ca - // quedan todos en sus lugares correctos en la pipeline - dotadd_valid[0] <= 1; - end - - OFFSETS_BC: - state <= OFFSETS_CA; - - OFFSETS_CA: - state <= OUT; - - OUT: - if (coarse_handshake) - state <= EDGE_AB; - endcase - end - - always_ff @(posedge clk) begin - delta.x <= coarse_ref.x - q.x; - delta.y <= coarse_ref.y - q.y; - - inc.cur.x <= p.y - q.y; - inc.cur.y <= q.x - p.x; - - //TODO: top-left rule - if (offsets_flow) begin - inc.delay1 <= inc.cur; - inc.delay2 <= inc.delay1; - - coarse_offsets.x <= make_raster_offsets(inc.delay2.x); - coarse_offsets.y <= make_raster_offsets(inc.delay2.y); - end - end - -endmodule - -module gfx_raster_coarse -( - input logic clk, - rst_n, - - input logic edges_valid, - input gfx::word edges_geom_id, - input gfx::fixed_xy edges_ref, - input gfx::raster_prec_xy edges_span, - input gfx::fixed edges_base, - input gfx::raster_offsets_xy edges_offsets, - output logic edges_ready, - - input logic fine_ready, - output logic fine_valid, - output gfx::word fine_geom_id, - output gfx::fixed_xy fine_ref, - output gfx::fixed fine_corner, - output gfx::raster_offsets_xy fine_offsets -); - - import gfx::*; - - enum int unsigned - { - SETUP, - TEST_AB, - TEST_BC, - TEST_CA, - OUT - } state; - - struct - { - fixed cur, - next, - prev; - } corner, edge_fn, vertical; - - struct - { - raster_offsets_xy cur, - next, - prev; - } offsets; - - logic edges_recv, end_block, end_x, end_y, first_run, - mask, mask_reset, new_geom, test_flow, out_flow; - - fixed edge_test, reference_x, vertical_inc; - fixed_xy max_offset, min_offset, test_offset; - raster_coarse_xy stride; - raster_coarse_dim width; - raster_offsets_xy next_offsets; - - function fixed coarse_offset(raster_offsets offsets); - return raster_idx(offsets, RASTER_BITS'(1)) << RASTER_BITS; - endfunction - - assign end_x = stride.x == '0; - assign end_y = stride.y == '0; - assign end_block = end_x & end_y; - - assign edge_test = edge_fn.cur + test_offset.x + test_offset.y; - assign vertical_inc = vertical.cur + coarse_offset(offsets.cur.y); - - assign fine_corner = corner.cur; - assign fine_offsets = offsets.cur; // Vuelve a cur luego de 3 ciclos - - assign min_offset.x = raster_idx(next_offsets.x, RASTER_BITS'(0)); - assign min_offset.y = raster_idx(next_offsets.y, RASTER_BITS'(0)); - assign max_offset.x = raster_idx(next_offsets.x, RASTER_BITS'(RASTER_SIZE - 1)); - assign max_offset.y = raster_idx(next_offsets.y, RASTER_BITS'(RASTER_SIZE - 1)); - assign next_offsets = edges_recv ? edges_offsets : offsets.next; - - always_comb begin - unique case (state) - SETUP: new_geom = 1; - default: new_geom = 0; - endcase - - unique case (state) - TEST_AB: mask_reset = 1; - default: mask_reset = 0; - endcase - - unique case (state) - SETUP: edges_ready = 1; - default: edges_ready = 0; - endcase - - unique case (state) - SETUP: - edges_recv = 1; - - TEST_AB, TEST_BC: - edges_recv = first_run; - - default: - edges_recv = 0; - endcase - - unique case (state) - OUT: fine_valid = mask; - default: fine_valid = 0; - endcase - - unique case (state) - OUT: begin - out_flow = ~mask | fine_ready; - test_flow = 0; - end - - default: begin - out_flow = 0; - test_flow = 1; - end - endcase - end - - always_ff @(posedge clk or negedge rst_n) - if (~rst_n) begin - state <= SETUP; - first_run <= 1; - end else - unique case (state) - SETUP: - if (edges_valid) - state <= TEST_AB; - - TEST_AB: - state <= TEST_BC; - - TEST_BC: - state <= TEST_CA; - - TEST_CA: - state <= OUT; - - OUT: begin - first_run <= end_block; - if (out_flow) - state <= end_block ? SETUP : TEST_AB; - end - endcase - - always_ff @(posedge clk) begin - if (new_geom) begin - width <= edges_span.x.coarse; - stride.x <= edges_span.x.coarse; - stride.y <= edges_span.y.coarse; - reference_x <= edges_ref.x; - - fine_ref <= edges_ref; - fine_geom_id <= edges_geom_id; - end - - if (out_flow) begin - stride.x <= stride.x - 1; - fine_ref.x.fint <= fine_ref.x.fint + ($bits(fixed_int))'(RASTER_SIZE); - - if (end_x) begin - fine_ref.x <= reference_x; - fine_ref.y.fint <= fine_ref.y.fint + ($bits(fixed_int))'(RASTER_SIZE); - - stride.x <= width; - stride.y <= stride.y - 1; - end - end - - if (test_flow) begin - offsets.cur <= next_offsets; - offsets.next <= offsets.prev; - offsets.prev <= offsets.cur; - - vertical.cur <= vertical.next; - vertical.next <= vertical.prev; - vertical.prev <= vertical.cur; - - edge_fn.cur <= edge_fn.next; - edge_fn.next <= edge_fn.prev; - edge_fn.prev <= edge_fn.cur + coarse_offset(offsets.cur.x); - - if (end_x) begin - edge_fn.prev <= vertical_inc; - vertical.prev <= vertical_inc; - end - - corner.cur <= corner.next; - corner.next <= corner.prev; - corner.prev <= edge_fn.cur; - - if (coarse_offset(next_offsets.x) >= 'sd0) - test_offset.x <= max_offset.x; - else - test_offset.x <= min_offset.x; - - if (coarse_offset(next_offsets.y) >= 'sd0) - test_offset.y <= max_offset.y; - else - test_offset.y <= min_offset.y; - - mask <= (mask | mask_reset) & 1/*(edge_test >= 'sd0)*/; - end - - if (edges_recv) begin - edge_fn.cur <= edges_base; - vertical.cur <= edges_base; - end - end - -endmodule - -module gfx_raster_fine -( - input logic clk, - rst_n, - - input logic coarse_valid, - input gfx::word coarse_geom_id, - input gfx::fixed_xy coarse_ref, - input gfx::fixed coarse_corner, - input gfx::raster_offsets_xy coarse_offsets, - output logic coarse_ready, - - gfx_pkts.tx coverage -); - - import gfx::*; - - enum int unsigned - { - IN_C, - IN_A, - IN_B, - IN_MASK - } in_state; - - enum int unsigned - { - OUT_ACCEPT, - OUT_GEOM_ID, - OUT_POS, - OUT_MASK, - OUT_BARY_C, - OUT_BARY_A, - OUT_BARY_B - } out_state; - - struct - { - fixed cur, - next, - prev; - } corner; - - struct - { - raster_offsets_xy cur, - next, - prev; - } offsets; - - logic begin_bary, hold_block, in_valid, mask_in_clean, - mask_in_reset, new_block, out_last; - - word geom_id; - fixed bary_coord; - lane_no lane, lane_ctz, lane_hold; - fixed_xy block_ref; - lane_mask mask_in, mask, mask_ctz; - raster_index lane_x, lane_y; - logic[$bits(lane_ctz):0] ctz_count; - - function shword ref_half(raster_prec dim); - return dim.coarse[$bits(shword) - 1:0]; - endfunction - - assign lane_ctz = ctz_count[$bits(lane_ctz) - 1:0]; - assign in_valid = mask_in_clean & |mask_in; - assign out_last = ~|mask; - assign {lane_y, lane_x} = lane; - - // **IMPORTANTE**: Esto va a fallar a partir de RASTER_BITS >= 3, - // ya que la fsm asume que ctz termina en 3 ciclos o menos - - gfx_ctz #(RASTER_COARSE_FRAGS) ctz - ( - .clk, - .value(mask_ctz), - .ctz(ctz_count) - ); - - always_comb begin - unique case (out_state) - OUT_ACCEPT: new_block = 1; - default: new_block = 0; - endcase - - unique case (out_state) - OUT_ACCEPT: mask_ctz = mask_in; - default: mask_ctz = mask; - endcase - - unique case (out_state) - OUT_ACCEPT: coverage.tvalid = 0; - default: coverage.tvalid = 1; - endcase - - unique case (out_state) - OUT_MASK, OUT_BARY_B: - begin_bary = coverage.tready; - - default: - begin_bary = 0; - endcase - - unique case (out_state) - OUT_BARY_B: coverage.tlast = out_last; - default: coverage.tlast = 0; - endcase - - unique case (out_state) - OUT_GEOM_ID: - coverage.tdata = geom_id; - - OUT_POS: - coverage.tdata = {ref_half(coarse_ref.y), ref_half(block_ref.x)}; - - OUT_MASK: - coverage.tdata = {{($bits(word) - $bits(mask)){1'b0}}, mask}; - - OUT_BARY_C, OUT_BARY_A, OUT_BARY_B: - coverage.tdata = bary_coord; - - default: - coverage.tdata = 'x; - endcase - - unique case (out_state) - OUT_MASK: - lane = lane_ctz; - - default: - lane = lane_hold; - endcase - - unique case (in_state) - IN_C: coarse_ready = new_block; - default: coarse_ready = 0; - endcase - - unique case (in_state) - IN_C: hold_block = new_block; - IN_A: hold_block = 1; - IN_B: hold_block = 1; - IN_MASK: hold_block = 0; - endcase - - unique case (in_state) - IN_C: mask_in_reset = 1; - default: mask_in_reset = 0; - endcase - - unique case (in_state) - IN_MASK: mask_in_clean = 1; - default: mask_in_clean = 0; - endcase - end - - always_ff @(posedge clk or negedge rst_n) - if (~rst_n) begin - in_state <= IN_C; - out_state <= OUT_ACCEPT; - end else begin - unique case (in_state) - IN_C: - if (coarse_valid & new_block) - in_state <= IN_A; - - IN_A: - in_state <= IN_B; - - IN_B: - in_state <= IN_MASK; - - IN_MASK: - in_state <= IN_C; - endcase - - unique case (out_state) - OUT_ACCEPT: - if (in_valid) - out_state <= OUT_GEOM_ID; - - OUT_GEOM_ID: - if (coverage.tready) - out_state <= OUT_POS; - - OUT_POS: - if (coverage.tready) - out_state <= OUT_MASK; - - OUT_MASK: - if (coverage.tready) - out_state <= OUT_BARY_C; - - OUT_BARY_C: - if (coverage.tready) - out_state <= OUT_BARY_A; - - OUT_BARY_A: - if (coverage.tready) - out_state <= OUT_BARY_B; - - OUT_BARY_B: - if (coverage.tready) - out_state <= out_last ? OUT_ACCEPT : OUT_BARY_C; - endcase - end - - always_ff @(posedge clk) begin - // Prueba paralela de signos, esto hace el heavy lifting de fine raster - // Nótese que muchos sumadores serán eliminados en síntesis - for (int i = 0; i < RASTER_SIZE; ++i) - for (int j = 0; j < RASTER_SIZE; ++j) - mask_in[i * RASTER_SIZE + j] <= - (mask_in[i * RASTER_SIZE + j] | mask_in_reset) - & (coarse_corner - + raster_idx(coarse_offsets.y, RASTER_BITS'(i)) - + raster_idx(coarse_offsets.x, RASTER_BITS'(j)) - >= 'sd0); - - // Recalculamos las coordenadas baricéntricas de cada fragmento que - // no haya sido descartado. La razón de esto es evitar almacenar y - // luego multiplexar las coordenadas de un bloque entero (48 words). - if (coverage.tready) - bary_coord <= corner.next - + raster_idx(offsets.next.y, RASTER_BITS'(lane_y)) - + raster_idx(offsets.next.x, RASTER_BITS'(lane_x)); - - if (new_block & mask_in_reset) begin - geom_id <= coarse_geom_id; - block_ref <= coarse_ref; - end - - // new_block = 0 => coverage.tvalid = 1 - if (new_block | coverage.tready) begin - corner.cur <= corner.next; - corner.next <= corner.prev; - corner.prev <= corner.cur; - - offsets.cur <= offsets.next; - offsets.next <= offsets.prev; - offsets.prev <= offsets.cur; - end - - if (hold_block) begin - // Para prev en vez de cur para que los primeros valores queden en - // cur justamente al llegar a OUT_BARY_C - corner.prev <= coarse_corner; - offsets.prev <= coarse_offsets; - end - - if (new_block) - mask <= mask_in; - - if (begin_bary) begin - mask <= mask & (mask - 1); - lane_hold <= lane_ctz; - end - end - -endmodule |
