Download pcie/rtl/bitacc_pcie_core.sv from Snapkitty/bit-string-accelerator: direct link, hf CLI and curl.
- Browser
- Download file 5.93 kB
-
https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/pcie/rtl/bitacc_pcie_core.sv
- Command line
-
hf download hf://Snapkitty/bit-string-accelerator/pcie/rtl/bitacc_pcie_core.sv
-
curl -L -o bitacc_pcie_core.sv https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/pcie/rtl/bitacc_pcie_core.sv
5.93 kB
| // PCIe-facing wrapper around bitacc_engine: 128-bit DMA streams and a small | |
| // register interface. Transport-independent: LiteX/LitePCIe connects the | |
| // streams to its DMA reader (host -> card) and writer (card -> host), but any | |
| // 128-bit valid/ready stream source works. | |
| // | |
| // Descriptor (one per 128-bit input beat, little-endian), format version 3: | |
| // [63:0] a: bit address (single-bit and bit-range operations; the host | |
| // computes (base << 3) + offset), or dst word (BULK) | |
| // [67:64] opcode: 0 GET, 1 TEST, 2 SET, 3 CLEAR, 4 TOGGLE, | |
| // 8 COUNT, 9 FIND1, 10 FIND0, 11 SETR, 12 CLEARR, 13 FLIPR, 14 BULK, | |
| // 15 MATCH (only with WITH_MATCH; otherwise an error), | |
| // 5-7 undefined (no write, result "error") | |
| // [68] dry: BULK computes and counts without writing | |
| // [71:69] fn: BULK function (0 COPY, 1 AND, 2 OR, 3 XOR, 4 ANDN); | |
| // MATCH result (0 number of matches, 1 first match) | |
| // [103:72] len: range length in bits, or in words for BULK | |
| // [127:104] src word (BULK source; MATCH pattern, with the mask in src + 1) | |
| // Semantics and errors: see bitacc_engine.sv. | |
| // | |
| // Results: 8 bytes per descriptor, in descriptor order, 2 per output beat | |
| // (bytes 0-7 of a beat = the first descriptor of the pair): | |
| // [7:0] 0xA0 | error << 1 | bit (same status byte as the UART builds) | |
| // [63:8] value (range operations; 0 otherwise) | |
| // A batch must hold an even number of descriptors; hosts pad with opcode 7 | |
| // (no write, result "error") and drop the padding results. | |
| // | |
| // Registers (driven by CSRs in the SoC): | |
| // host_word / host_wdata / host_write_stb / host_read_stb : word access to | |
| // the bit store, accepted only while idle; host_rdata valid when | |
| // host_rdata_valid rises (sticky until the next access). | |
| module bitacc_pcie_core #( | |
| parameter int LANES = 8, | |
| parameter int WORDS_PER_LANE = 2048, | |
| parameter int ROB_DEPTH = 32, | |
| parameter bit WITH_MATCH = 1'b1, | |
| parameter int MATCH_LANES = LANES | |
| )( | |
| input logic clk, | |
| input logic reset, | |
| input logic in_valid, | |
| output logic in_ready, | |
| input logic [127:0] in_data, | |
| output logic out_valid, | |
| input logic out_ready, | |
| output logic [127:0] out_data, | |
| input logic [$clog2(LANES*WORDS_PER_LANE)-1:0] host_word, | |
| input logic [63:0] host_wdata, | |
| input logic host_write_stb, | |
| input logic host_read_stb, | |
| output logic [63:0] host_rdata, | |
| output logic host_rdata_valid, | |
| output logic host_busy, // an access is pending | |
| output logic idle, | |
| output logic [31:0] ops_accepted, | |
| output logic [31:0] results_sent | |
| ); | |
| localparam int WW = $clog2(LANES * WORDS_PER_LANE); | |
| // ---------------------------------------------------------------- engine | |
| logic res_valid, res_ready, res_error, res_bit; | |
| logic [55:0] res_value; | |
| logic h_valid, h_ready, h_write, h_rvalid; | |
| logic [WW-1:0] h_word; | |
| logic [63:0] h_wdata, h_rdata; | |
| logic eng_idle; | |
| bitacc_engine #(.LANES(LANES), .WORDS_PER_LANE(WORDS_PER_LANE), .ROB_DEPTH(ROB_DEPTH), | |
| .WITH_MATCH(WITH_MATCH), .MATCH_LANES(MATCH_LANES)) u_engine ( | |
| .clk, .reset, | |
| .cmd_valid(in_valid), .cmd_ready(in_ready), | |
| .cmd_op(in_data[67:64]), .cmd_base(64'd0), .cmd_offset(in_data[63:0]), | |
| .cmd_len(in_data[103:72]), .cmd_src(in_data[127:104]), .cmd_fn(in_data[71:69]), .cmd_dry(in_data[68]), | |
| .res_valid, .res_ready, .res_error, .res_bit, .res_value, | |
| .host_valid(h_valid), .host_ready(h_ready), .host_write(h_write), | |
| .host_word(h_word), .host_wdata(h_wdata), | |
| .host_rvalid(h_rvalid), .host_rdata(h_rdata), | |
| .idle(eng_idle)); | |
| // ---------------------------------------------------------------- result packer | |
| logic [127:0] pack; | |
| logic fill; // results already in pack | |
| logic full; // pack holds 2 results waiting for out_ready | |
| // A beat leaving this cycle frees the pack for the next result. | |
| assign res_ready = !full || out_ready; | |
| assign out_valid = full; | |
| assign out_data = pack; | |
| always_ff @(posedge clk) begin | |
| if (reset) begin | |
| pack <= '0; fill <= '0; full <= 1'b0; | |
| end else begin | |
| if (full && out_ready) full <= 1'b0; | |
| if (res_valid && res_ready) begin | |
| pack[{fill, 6'b000000} +: 64] <= {res_value, 6'b101000, res_error, res_bit}; | |
| fill <= !fill; | |
| if (fill) full <= 1'b1; | |
| end | |
| end | |
| end | |
| // ---------------------------------------------------------------- host word access | |
| // A strobe is latched and issued when the engine is idle. | |
| logic pend, pend_write; | |
| logic [WW-1:0] pend_word; | |
| logic [63:0] pend_wdata; | |
| assign h_valid = pend; | |
| assign h_write = pend_write; | |
| assign h_word = pend_word; | |
| assign h_wdata = pend_wdata; | |
| assign host_busy = pend; | |
| always_ff @(posedge clk) begin | |
| if (reset) begin | |
| pend <= 1'b0; pend_write <= 1'b0; pend_word <= '0; pend_wdata <= '0; | |
| host_rdata <= '0; host_rdata_valid <= 1'b0; | |
| end else begin | |
| if (!pend && (host_write_stb || host_read_stb)) begin | |
| pend <= 1'b1; | |
| pend_write <= host_write_stb; | |
| pend_word <= host_word; | |
| pend_wdata <= host_wdata; | |
| host_rdata_valid <= 1'b0; | |
| end else if (pend && h_ready) begin | |
| pend <= 1'b0; | |
| end | |
| if (h_rvalid) begin | |
| host_rdata <= h_rdata; | |
| host_rdata_valid <= 1'b1; | |
| end | |
| end | |
| end | |
| // ---------------------------------------------------------------- status | |
| assign idle = eng_idle && !full && !fill && !pend; | |
| always_ff @(posedge clk) begin | |
| if (reset) begin | |
| ops_accepted <= '0; results_sent <= '0; | |
| end else begin | |
| if (in_valid && in_ready) ops_accepted <= ops_accepted + 1'b1; | |
| if (out_valid && out_ready) results_sent <= results_sent + 32'd2; | |
| end | |
| end | |
| endmodule | |