/
bsg_trace_replay.v
199 lines (174 loc) · 6.6 KB
/
bsg_trace_replay.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
`include "bsg_defines.v"
// MBT 11/26/2014, bsg_fsb_node_trace_replay
// Shaolin 01/06/2018, generalized from the bsg_trace_replay
// trace format (see enum below)
//
module bsg_trace_replay
#( parameter payload_width_p =80
, parameter rom_addr_width_p=6
, parameter counter_width_p=`BSG_MIN(payload_width_p,16)
//The operation code is always 4 bits.
, parameter opcode_width_lp = 4
)
( input clk_i
, input reset_i
, input en_i
// input channel
, input v_i
, input [payload_width_p-1:0] data_i
, output logic ready_o
// output channel
, output logic v_o
, output logic [payload_width_p-1:0] data_o
, input yumi_i
// connection to rom
// note: asynchronous reads
, output [rom_addr_width_p-1:0] rom_addr_o
, input [payload_width_p+4-1:0] rom_data_i
// true outputs
, output logic done_o
, output logic error_o
);
// 0: wait one cycle
// 1: send data
// 2: receive data (and check its value)
// 3: assert done_o; test complete.
// 4: end test; call $finish
// 5: decrement cycle counter; wait for cycle_counter == 0
// 6: initialized cycle counter with 16 bits
// in theory, we could add branching, etc.
// before we know it, we have a processor =)
typedef enum logic [opcode_width_lp-1:0] {
eNop=4'd0,
eSend=4'd1,
eReceive=4'd2,
eDone=4'd3,
eFinish=4'd4,
eCycleDec=4'd5,
eCycleInit=4'd6
} eOp;
logic [counter_width_p-1:0] cycle_ctr_r, cycle_ctr_n;
logic [rom_addr_width_p-1:0] addr_r, addr_n;
logic done_r, done_n;
logic error_r, error_n;
assign rom_addr_o = addr_r;
assign data_o = rom_data_i[0+:payload_width_p];
assign done_o = done_r;
assign error_o = error_r;
always_ff @(posedge clk_i) begin
if (reset_i) begin
addr_r <= 0;
done_r <= 0;
error_r <= 0;
cycle_ctr_r <= 16'b1;
end else begin
addr_r <= addr_n;
done_r <= done_n;
error_r <= error_n;
cycle_ctr_r <= cycle_ctr_n;
end
end // always_ff @
logic [3:0] op;
assign op = rom_data_i[payload_width_p+:4];
logic instr_completed;
assign addr_n = instr_completed ? (addr_r+1'b1) : addr_r;
// handle outputs
always_comb begin
// defaults; not sending and not receiving unless done
v_o = 1'b0;
ready_o = done_r;
done_n = done_r;
if (!done_r & en_i & ~reset_i) begin
case (op)
eSend: v_o = 1'b1;
eReceive: ready_o = 1'b1;
eDone: done_n = 1'b1;
default:
begin
end
endcase
end
end // always_comb
// next instruction logic
always_comb begin
instr_completed = 1'b0;
error_n = error_r;
cycle_ctr_n = cycle_ctr_r;
if (!done_r & en_i & ~reset_i) begin
case (op)
eNop: instr_completed = 1'b1;
eSend: if (yumi_i) instr_completed = 1'b1;
eReceive: begin
if (v_i)
begin
instr_completed = 1'b1;
if (error_r == 0)
error_n = data_i != data_o;
end
end
eDone: instr_completed = 1'b1;
eFinish: instr_completed = 1'b1;
eCycleDec:
begin
cycle_ctr_n = cycle_ctr_r - 1'b1;
instr_completed = ~(|cycle_ctr_r);
end
eCycleInit:
begin
cycle_ctr_n = rom_data_i[counter_width_p-1:0];
instr_completed = 1;
end
default:
begin
end
endcase // case (op)
end
end
// non-synthesizeable components
always @(negedge clk_i) begin
if (instr_completed & ~reset_i & ~done_r) begin
case(op)
eSend: $display("### bsg_trace_replay SEND %d'b%b (%m)", payload_width_p,data_o);
eReceive: begin
if (data_i !== data_o) begin
$display("############################################################################");
$display("### bsg_trace_replay RECEIVE unmatched (%m) ");
$display("### ");
$display("### FAIL (trace mismatch) = %h", data_i);
$display("### expected = %h\n", data_o);
$display("############################################################################");
$finish();
end else begin
$display("### bsg_trace_replay RECEIVE matched %h (%m)", data_o);
end // else: !if(data_i != data_o)
end
eDone: begin
$display("############################################################################");
$display("###### bsg_trace_replay DONE done_o=1 (trace finished addr=%x) (%m)",rom_addr_o);
$display("############################################################################");
end
eFinish: begin
$display("############################################################################");
$display("###### bsg_trace_replay FINISH (trace finished; CALLING $finish) (%m)");
$display("############################################################################");
$finish;
end
eCycleDec: begin
$display("### bsg_trace_replay CYCLE DEC cycle_ctr_r = %x (%m)",cycle_ctr_r);
end
eCycleInit: begin
$display("### bsg_trace_replay CYCLE INIT = %x (%m)",cycle_ctr_n);
end
default:
begin
end
endcase // case (op)
case (op)
eNop, eSend, eReceive, eDone, eFinish, eCycleDec, eCycleInit:
begin
end
default: $display("### bsg_trace_replay UNKNOWN op %x (%m)\n", op);
endcase // case (op)
end // if (instr_completed & ~reset_i & ~done_r)
end // always @ (negedge clk_i)
endmodule