xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine
commit 19c4f1dea715e4e3d43732b20043d53ef87e7443
parent b37fdb4f722532ac3630160ba9fc41fdea36e368
Author: yash modi <yash3108m@gmail.com>
Date:   Tue, 31 Mar 2026 05:23:04 +0530

Week 2: Complete Verilog Emitter Optimization (Part 3: Finalizing)

Diffstat:
Msrc/emitter.cpp | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+), 0 deletions(-)

diff --git a/src/emitter.cpp b/src/emitter.cpp @@ -794,3 +794,121 @@ void Emitter::emitTopFPGA(const std::vector<std::unique_ptr<NFA>> &nfas, const s << " localparam S_TX_ARM = 4'd8;\n" << " localparam S_TX_WAIT = 4'd9;\n" << " localparam S_RESET_NFA = 4'd10;\n" + << " localparam S_QUERY_TX = 4'd11;\n\n" + << " reg [3:0] state = S_RESET_NFA;\n\n" + << " reg [" << busHigh << ":0] snap_match = " << numNFAs << "'b0;\n" + << " reg [31:0] snap_bytes = 32'd0;\n" + << " integer k;\n\n" + << " always @(posedge clk) begin\n" + << " tx_send <= 1'b0;\n" + << " fifo_rd_en <= 1'b0;\n" + << " nfa_en <= 1'b0;\n" + << " nfa_start <= 1'b0;\n\n" + << " if (rst_btn) begin\n" + << " state <= S_RESET_NFA;\n" + << " match_leds <= " << numNFAs << "'b0;\n" + << " byte_count <= 32'd0;\n" + << " for (k = 0; k < 16; k = k + 1)\n" + << " match_count[k] <= 16'd0;\n" + << " end else begin\n" + << " case (state)\n\n" + << " S_IDLE: begin\n" + << " nfa_end_of_str <= 1'b0;\n" + << " if (!fifo_empty) state <= S_FETCH;\n" + << " end\n\n" + << " S_FETCH: begin\n" + << " fifo_rd_en <= 1'b1;\n" + << " state <= S_DECODE;\n" + << " end\n\n" + << " S_DECODE: begin\n" + << " if (fifo_rd_data == 8'h0A || fifo_rd_data == 8'h0D) begin\n" + << " nfa_end_of_str <= 1'b1;\n" + << " state <= S_EOL_END;\n" + << " end else if (fifo_rd_data == 8'h3F) begin // '?'\n" + << " state <= S_QUERY_TX;\n" + << " end else begin\n" + << " nfa_char_in <= fifo_rd_data;\n" + << " state <= S_CHAR_LOAD;\n" + << " end\n" + << " end\n\n" + << " S_CHAR_LOAD: state <= S_CHAR_STEP;\n\n" + << " S_CHAR_STEP: begin\n" + << " nfa_en <= 1'b1;\n" + << " byte_count <= byte_count + 1;\n" + << " state <= S_IDLE;\n" + << " end\n\n" + << " S_EOL_END: begin\n" + << " nfa_en <= 1'b1;\n" + << " state <= S_EOL_MATCH;\n" + << " end\n\n" + << " S_EOL_MATCH: begin\n" + << " nfa_en <= 1'b1;\n" + << " nfa_end_of_str <= 1'b0;\n" + << " state <= S_EOL_LATCH;\n" + << " end\n\n" + << " S_EOL_LATCH: begin\n" + << " snap_match <= match_bus;\n" + << " snap_bytes <= byte_count;\n" + << " match_leds <= match_bus;\n" + << " for (k = 0; k < " << numNFAs << "; k = k + 1)\n" + << " if (match_bus[k]) match_count[k] <= match_count[k] + 16'd1;\n" + << " state <= S_TX_ARM;\n" + << " end\n\n" + << " S_TX_ARM: begin\n" + << " build_response(snap_match, snap_bytes);\n" + << " tx_send <= 1'b1;\n" + << " state <= S_TX_WAIT;\n" + << " end\n\n" + << " S_TX_WAIT:\n" + << " if (tx_state == TX_IDLE && !tx_send) state <= S_RESET_NFA;\n\n" + << " S_RESET_NFA: begin\n" + << " nfa_start <= 1'b1;\n" + << " nfa_en <= 1'b1;\n" + << " state <= S_IDLE;\n" + << " end\n\n" + << " S_QUERY_TX: begin\n" + << " build_response(" << numNFAs << "'b0, byte_count);\n" + << " tx_send <= 1'b1;\n" + << " state <= S_TX_WAIT;\n" + << " end\n\n" + << " default: state <= S_IDLE;\n" + << " endcase\n" + << " end\n" + << " end\n\n" + << "endmodule\n"; +} + +// ============================================================================= +// emitConstraints — constraints.xdc +// ============================================================================= +void Emitter::emitConstraints(const std::vector<std::unique_ptr<NFA>> &nfas, const std::filesystem::path &outputDir) +{ + auto filePath = outputDir / "constraints.xdc"; + std::ofstream out(filePath); + out.exceptions(std::ofstream::failbit | std::ofstream::badbit); + + out << "## Clock signal (Nexys A7 100MHz)\n" + << "set_property PACKAGE_PIN E3 [get_ports clk]\n" + << "set_property IOSTANDARD LVCMOS33 [get_ports clk]\n" + << "create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]\n\n"; + + out << "## USB-RS232 Interface (Nexys A7)\n" + << "set_property PACKAGE_PIN C4 [get_ports uart_rx_pin]\n" + << "set_property IOSTANDARD LVCMOS33 [get_ports uart_rx_pin]\n\n" + << "set_property PACKAGE_PIN D4 [get_ports uart_tx_pin]\n" + << "set_property IOSTANDARD LVCMOS33 [get_ports uart_tx_pin]\n\n"; + + out << "## Buttons (Nexys A7 Center Button - BTNC)\n" + << "set_property PACKAGE_PIN N17 [get_ports rst_btn]\n" + << "set_property IOSTANDARD LVCMOS33 [get_ports rst_btn]\n\n"; + + out << "## LEDs (Nexys A7 LED0 to LED15)\n"; + std::vector<std::string> led_pins = { + "H17", "K15", "J13", "N14", "R18", "V17", "U17", "U16", + "V16", "T15", "U14", "T16", "V15", "V14", "V12", "V11"}; + for (size_t i = 0; i < nfas.size() && i < led_pins.size(); ++i) + { + out << "set_property PACKAGE_PIN " << led_pins[i] << " [get_ports {match_leds[" << i << "]}]\n" + << "set_property IOSTANDARD LVCMOS33 [get_ports {match_leds[" << i << "]}]\n"; + } +}