Skip to content

Commit c7034a2

Browse files
First working version of regex_coprocessor with multiple basic blocks.
Fix problem with elapsed clock cycles. The problem arises from the fact that AXI_top once the coprocessor accept the string goes into STATUS_ACCEPTED from which it was possible to receive a new START. If the latency introduced by the AXI interface was so high that it's not possible to overwrite the command START, with a command NOP, before the regex_coprocessor has finished is duty, the AXI_top FSM may interpret command_START in the register as a new request of performing a new regular expression matching. To avoid that STATUS_ACCEPTED and STATUS_REJECTED have a different behaviour w.r.t. STATUS_IDLE and it is no longer possible to send CMD_START as soon as the regex_coprocessor work is over. For this reason a new command(CMD_RESTART) that moves from those states, to IDLE has been introduced. Add an overall description at the beginning of most complex modules in the design, and in some cases even illustration to better clarify component connections. Enhance readability of re2_driver introducing enums to carry constants and method wrapper to simplify the code. Add support in re2_driver for the new command Add support in re2_driver to reuse previously compiled regular expressions.
1 parent febe9d4 commit c7034a2

File tree

8 files changed

+1072
-926
lines changed

8 files changed

+1072
-926
lines changed

rtl_src/AXI_package.sv

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
`timescale 1ns/1ps
2-
2+
//contains signals used to interface regex_coprocessor
3+
//and software.
34
package AXI_package;
45
localparam REG_WIDTH = 32;
56
parameter CMD_NOP = 'h0000_0000 ;
@@ -8,6 +9,7 @@ parameter CMD_READ = 'h0000_0002 ;
89
parameter CMD_START = 'h0000_0003 ;
910
parameter CMD_RESET = 'h0000_0004 ;
1011
parameter CMD_READ_ELAPSED_CLOCK = 'h0000_0005 ;
12+
parameter CMD_RESTART = 'h0000_0006 ;
1113

1214

1315
parameter STATUS_IDLE = 'h0000_0000 ;

rtl_src/AXI_top.sv

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
import AXI_package::*;
44

5+
//component intended to decouple the regex_coprocessor and the AXI interface.
6+
//It contains the memory of the regex_coprocessor so that is possible to show outside the contetn of the memory
7+
//It implements some commands that are intended to drive the regex_coprocessor and other component from software.
8+
59
module AXI_top(
610
input logic clk,
7-
input logic reset, //reset has to be implemented using cmd_register?
11+
input logic reset,
812
input logic [REG_WIDTH-1:0] data_in_register,
913
input logic [REG_WIDTH-1:0] address_register,
1014
// input logic [REG_WIDTH-1:0] start_pc_register,
@@ -88,7 +92,7 @@ begin
8892
start_cc_pointer = { (BRAM_ADDR_WIDTH){1'b0} };
8993

9094
case(status_register)
91-
STATUS_IDLE, STATUS_ACCEPTED, STATUS_REJECTED:
95+
STATUS_IDLE:
9296
begin
9397
if(cmd_register == CMD_WRITE) // to write the content of memory write in seuqence addr_0, cmd_write, data_0,
9498
begin // addr_1, data_1, ..., cmd_nop.
@@ -114,7 +118,8 @@ begin
114118
bram_addr = memory_addr_from_coprocessor;
115119
bram_valid_in = memory_addr_from_coprocessor_valid;
116120
memory_addr_from_coprocessor_ready = 1'b1;
117-
121+
elapsed_cc_next = {(REG_WIDTH){1'b0}};
122+
118123
if( start_valid )
119124
begin
120125
status_register_next = STATUS_RUNNING;
@@ -125,6 +130,34 @@ begin
125130
data_o_register = elapsed_cc;
126131
end
127132

133+
end
134+
STATUS_ACCEPTED, STATUS_REJECTED:
135+
begin
136+
if(cmd_register == CMD_WRITE) // to write the content of memory write in seuqence addr_0, cmd_write, data_0,
137+
begin // addr_1, data_1, ..., cmd_nop.
138+
139+
bram_addr = address_register[0+:BRAM_ADDR_WIDTH]; //use low
140+
bram_in = { ^(data_in_register[31:24]),data_in_register[31:24], ^(data_in_register[23:16]), data_in_register[23:16], ^(data_in_register[15:8]), data_in_register[15:8], ^(data_in_register[7:0]), data_in_register[7:0] };
141+
bram_valid_in = 1'b1;
142+
bram_we = { (BRAM_WE_WIDTH) {1'b1} };
143+
data_o_register = bram_o_register;
144+
end
145+
else if(cmd_register == CMD_READ)
146+
begin
147+
bram_addr = address_register[0+:BRAM_ADDR_WIDTH]; //use low
148+
bram_valid_in = 1'b1;
149+
memory_addr_from_coprocessor_ready = 1'b0;
150+
data_o_register = bram_o_register;
151+
end
152+
else if(cmd_register == CMD_RESTART)
153+
begin
154+
status_register_next = STATUS_IDLE;
155+
end
156+
else if(cmd_register == CMD_READ_ELAPSED_CLOCK)
157+
begin
158+
data_o_register = elapsed_cc;
159+
end
160+
128161
end
129162
STATUS_RUNNING:
130163
begin
@@ -180,7 +213,6 @@ regex_coprocessor_single_bb #(
180213
.memory_data (bram_payload),
181214
.memory_valid (memory_addr_from_coprocessor_valid ),
182215
.start_ready (start_ready),
183-
//.start_pc (start_pc),
184216
.start_cc_pointer (start_cc_pointer),
185217
.start_valid (start_valid),
186218
.finish (finish),
@@ -195,7 +227,7 @@ regex_coprocessor_n_bb #(
195227
.MEMORY_ADDR_WIDTH (BRAM_ADDR_WIDTH ),
196228
.LATENCY_COUNT_WIDTH (7),
197229
.FIFO_COUNT_WIDTH (6),
198-
.BB_N (1)
230+
.BB_N (5)
199231
)a_regex_coprocessor (
200232
.clk (clk),
201233
.reset (reset_master),

rtl_src/basic_block.sv

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,40 @@
11
`timescale 1ns/1ps
2+
//wraps
3+
//1.a regex_cpu and
4+
//2.two fifos to save instructions in the form of their program counters
5+
// for current and next character.
6+
//
7+
// /-<memory_data
8+
// /--->memory_addr
9+
// +------------------------------------------>memory_valid
10+
//+----------------------------------|------------------------+ \---<memory_ready
11+
//| Basic block | |
12+
//| | |
13+
//| | |
14+
//| +-------|------+ |
15+
//| | Regex_cpu | | /--->output_pc_valid
16+
//| +-----> | ------>----------------------------->output_pc_and current
17+
//| | | | | \---<output_pc_ready
18+
//| | +--------------+ |
19+
//| | input_pc_and_current[0]
20+
//| | +------------------+ +-----+ |
21+
//| +---- curr_char_fifo <-----|--+ | |
22+
//| +------------------+ |demux| | | /---<input_pc_valid
23+
//| +------------------+ | <--------------------------<input_pc_and_current
24+
//| 0<--data_out_ready---| next_char_fifo <--------+ +----------------------->input_pc_ready
25+
//| +------------------+ | |
26+
//| | |
27+
//| even_in_ready | |
28+
//| and ---------------------+ |
29+
//| odd_in_ready |
30+
//| |
31+
//+-----------------------------------------------------------+
32+
//note that:
33+
//- curr_char_fifo and next_char_fifo are implemented by 2 fifos(called odd/even)
34+
// in which inputs/outputs are muxed/demuxed via cur_is_even_character (input)
35+
// not represented for sake of drawing simplicity
36+
37+
238
module basic_block #(
339
parameter PC_WIDTH = 8 ,
440
parameter LATENCY_COUNT_WIDTH = 8 ,
@@ -30,9 +66,10 @@ module basic_block #(
3066
input logic[LATENCY_COUNT_WIDTH-1:0] output_pc_latency
3167

3268
);
69+
//output latency is unused by basic block.
3370
wire [LATENCY_COUNT_WIDTH-1:0] output_pc_latency_unused;
3471
assign output_pc_latency_unused = output_pc_latency;
35-
72+
//sub signals of input_pc_and_current, output_pc_and_current
3673
logic [PC_WIDTH-1:0] output_pc, input_pc;
3774
logic input_pc_is_directed_to_current, output_pc_is_directed_to_current;
3875

@@ -75,9 +112,6 @@ module basic_block #(
75112
logic [FIFO_COUNT_WIDTH-1:0]fifo_next_char_data_count ;
76113

77114
//FIFO even instantiation
78-
assign fifo_even_data_in_ready = ~ fifo_even_data_in_not_ready ;
79-
assign fifo_even_data_out_valid = ~ fifo_even_data_out_not_valid;
80-
81115
fifo #(
82116
.DWIDTH(PC_WIDTH),
83117
.COUNT_WIDTH(FIFO_COUNT_WIDTH)
@@ -89,13 +123,14 @@ module basic_block #(
89123
.wr_en (fifo_even_data_in_valid ), //equivalent to data_in_valid
90124
.rd_en (fifo_even_data_out_ready ), //equivalent to data_out_ready
91125
.dout (fifo_even_data_out ),
92-
.data_count (fifo_even_data_count ),
93-
.empty (fifo_even_data_out_not_valid) //equivalent to not data_out_valid
126+
.empty (fifo_even_data_out_not_valid), //equivalent to not data_out_valid
127+
.data_count (fifo_even_data_count )
94128
);
129+
//conclusion fifo even instatiation convert negated not_ready/not_valid signals to "standard" ready/valid interface.
130+
assign fifo_even_data_in_ready = ~ fifo_even_data_in_not_ready ;
131+
assign fifo_even_data_out_valid = ~ fifo_even_data_out_not_valid;
132+
95133
//FIFO odd instantiation
96-
assign fifo_odd_data_in_ready = ~ fifo_odd_data_in_not_ready ;
97-
assign fifo_odd_data_out_valid = ~ fifo_odd_data_out_not_valid;
98-
99134
fifo #(
100135
.DWIDTH(PC_WIDTH),
101136
.COUNT_WIDTH(FIFO_COUNT_WIDTH)
@@ -110,12 +145,15 @@ module basic_block #(
110145
.data_count (fifo_odd_data_count ),
111146
.empty (fifo_odd_data_out_not_valid) //equivalent to not data_out_valid
112147
);
148+
//conclusion fifo odd instatiation convert negated not_ready/not_valid signals to "standard" ready/valid interface.
149+
assign fifo_odd_data_in_ready = ~ fifo_odd_data_in_not_ready ;
150+
assign fifo_odd_data_out_valid = ~ fifo_odd_data_out_not_valid;
113151

114152
//select fifo current and fifo next according to cur_is_even_character signal
115153
always_comb begin : selector_fifo_current_fifo_next
116154

117155
if ( cur_is_even_character == 1'b1 )
118-
begin
156+
begin //even is current and odd is next_char
119157
fifo_cur_char_data_in_ready = fifo_even_data_in_ready ;
120158
fifo_even_data_in = fifo_cur_char_data_in ;
121159
fifo_even_data_in_valid = fifo_cur_char_data_in_valid ;
@@ -133,7 +171,7 @@ module basic_block #(
133171
fifo_next_char_data_count = fifo_odd_data_count ;
134172
end
135173
else
136-
begin
174+
begin //odd is current and even is next_char
137175
fifo_cur_char_data_in_ready = fifo_odd_data_in_ready ;
138176
fifo_odd_data_in = fifo_cur_char_data_in ;
139177
fifo_odd_data_in_valid = fifo_cur_char_data_in_valid ;
@@ -152,45 +190,50 @@ module basic_block #(
152190
end
153191
end
154192

155-
// make so that pc referring to next char are not consumed.
193+
// make so that content of fifo_next_char is not consumed.
156194
assign fifo_next_char_data_out_ready = 1'b0;
157195

158-
//ouput pc is redirected toward output after having concatenated
196+
//output_pc is redirected toward output after having concatenated with output_pc_is_directed_to_current
159197
assign output_pc_and_current = {output_pc, output_pc_is_directed_to_current};
160-
//input pc and current is splitted in input_pc and input_pc_is_directed_to_current
198+
//input_pc_and_current is splitted in input_pc and input_pc_is_directed_to_current
161199
assign input_pc_is_directed_to_current = input_pc_and_current[0];
162200
assign input_pc = input_pc_and_current[1+:PC_WIDTH] ;
163201

164-
//demux
202+
//demux to drive input_pc_and_current toward correct fifo.
203+
//to avoid a combinational loop (switches can decide to move data toward one or the other output port depending on output ready, but in principle output ready depends also on targeted fifo which is specified in data).
204+
//conservative(certain instruction which in principle could have been stored are refused) but correct
205+
assign input_pc_ready = fifo_cur_char_data_in_ready && fifo_next_char_data_in_ready;
165206
always_comb begin : demux_for_pc_in
166207
fifo_cur_char_data_in = { PC_WIDTH{1'b0} };
167208
fifo_next_char_data_in = { PC_WIDTH{1'b0} };
168-
//to avoid a combinational loop
169-
input_pc_ready = fifo_cur_char_data_in_ready && fifo_next_char_data_in_ready;
209+
170210
if(input_pc_is_directed_to_current)
171211
begin
172212
fifo_cur_char_data_in = input_pc ;
173-
fifo_cur_char_data_in_valid = input_pc_valid ;
213+
fifo_cur_char_data_in_valid = input_pc_valid && input_pc_ready; //since for outside bb input is ready if both fifo_cur_char and fifo_next_char are ready, their valid has to take into account that to avoid that fifo_latches it
174214

175215
fifo_next_char_data_in_valid= 1'b0;
176216
end
177217
else
178218
begin
179219
fifo_next_char_data_in = input_pc ;
180-
fifo_next_char_data_in_valid = input_pc_valid ;
220+
fifo_next_char_data_in_valid = input_pc_valid && input_pc_ready; //since for outside bb input is ready if both fifo_cur_char and fifo_next_char are ready, their valid has to take into account that to avoid that fifo_latches it
181221

182222
fifo_cur_char_data_in_valid = 1'b0;
183223
end
184224
end
185225

186-
//compute the approximate latency seen outside
226+
//compute the approximate latency seen outside thought of max between odd and even but lead to high fanout-> setup violation
227+
//opted for a simpler computation: consider only fifo_cur_char length.
187228
//always_comb begin : latency_computation
188229
// if( fifo_odd_data_count > fifo_even_data_count) input_pc_latency = fifo_odd_data_count + 1;
189230
// else input_pc_latency = fifo_even_data_count + 1;
190231
//end
191232
assign input_pc_latency = fifo_cur_char_data_count + 1 ;
192-
//running if regex_cpu has taken some instruction and the data_out_ready=0
193-
// or some instructions are saved in curr character fifo
233+
234+
235+
//running if regex_cpu has taken some instruction and hence the data_out_ready=0
236+
// or some instructions are saved in curr character fifo and hence fifo_cur_char_data_out_valid=1
194237
always_comb begin : running_definition
195238
running = fifo_cur_char_data_out_valid || ~fifo_cur_char_data_out_ready;
196239
end

rtl_src/fifo.sv

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
`timescale 1ns/1ps
2-
2+
//This module implements a parametric queue
3+
//It provides also an output which signals how many values have been
4+
//stored inside the queue.
35
module fifo #(
4-
parameter DWIDTH = 16,
6+
parameter DWIDTH = 16,
57
parameter COUNT_WIDTH = 5
68
)(
79
input logic clk,
@@ -16,9 +18,9 @@ module fifo #(
1618
);
1719

1820
logic [COUNT_WIDTH-1:0] head;
19-
logic [COUNT_WIDTH :0] head_incremented;
21+
logic [COUNT_WIDTH-1:0] head_incremented;
2022
logic [COUNT_WIDTH-1:0] tail;
21-
logic [COUNT_WIDTH :0] tail_incremented;
23+
logic [COUNT_WIDTH-1:0] tail_incremented;
2224
logic [DWIDTH-1:0] content [(1<<COUNT_WIDTH)-1:0];
2325

2426
always_ff @( posedge clk ) begin
@@ -33,7 +35,7 @@ always_ff @( posedge clk ) begin
3335
if(wr_en == 1'b1 && full == 1'b0 )
3436
begin
3537
content[tail] <= din;
36-
tail <= tail_incremented[0+:COUNT_WIDTH];
38+
tail <= tail_incremented;
3739
end
3840
else
3941
begin
@@ -43,7 +45,7 @@ always_ff @( posedge clk ) begin
4345
if(rd_en == 1'b1 && empty == 1'b0 )
4446
begin
4547
//content[head] <= { DWIDTH {1'b0} };
46-
head <= head_incremented[0+:COUNT_WIDTH];
48+
head <= head_incremented;
4749
end
4850
else
4951
begin
@@ -61,11 +63,11 @@ always_comb begin
6163
//for fall through
6264
dout = content[head];
6365
//empty
64-
if( head == tail ) empty = 1'b1;
65-
else empty = 1'b0;
66+
if( head == tail ) empty = 1'b1;
67+
else empty = 1'b0;
6668
//full
67-
if( head == tail_incremented[0+:COUNT_WIDTH]) full = 1'b1;
68-
else full = 1'b0;
69+
if( head == tail_incremented) full = 1'b1;
70+
else full = 1'b0;
6971

7072
end
7173

0 commit comments

Comments
 (0)