Skip to content

Commit 0886d5e

Browse files
authored
[ESI] Add skid buffer to Cosim_Endpoint_ToHost (llvm#8983)
* [ESI] Add skid buffer to Cosim_Endpoint_ToHost It has been observed that some simulators (verilator) does not handle combinational driving from DPI well (resulting in non-determinism wrt. some of the combinational outputs being dropped/replicated). Questa does not show this behavior. A mitigation is to add a skid buffer to decouple the DPI interface from the output interface. Use the existing skid buffer from ESIPrimitives. * doc cleanup --------- Co-authored-by: John Demme <[email protected]>
1 parent 2b2a4d9 commit 0886d5e

File tree

1 file changed

+62
-15
lines changed

1 file changed

+62
-15
lines changed

lib/Dialect/ESI/runtime/cosim_dpi_server/Cosim_Endpoint.sv

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// Package: Cosim_DpiPkg
1010
//
1111
// Main cosim <--> dpi bridge module.
12+
13+
1214
//
1315
//===----------------------------------------------------------------------===//
1416

@@ -118,9 +120,8 @@ module Cosim_Endpoint_FromHost
118120
$error("Cosim endpoint (%s) register failed: %d", ENDPOINT_ID, rc);
119121
end
120122

121-
/// *******************
122-
/// Data out management.
123-
///
123+
/// ***********************
124+
/// Useful constants.
124125

125126
localparam int FROM_HOST_SIZE_BYTES = int'((FROM_HOST_SIZE_BITS+7)/8);
126127
// The number of bits over a byte.
@@ -129,13 +130,30 @@ module Cosim_Endpoint_FromHost
129130
localparam int FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS
130131
= FROM_HOST_SIZE_BYTES_FLOOR * 8;
131132

133+
// Buffer to hold incoming data directly from the DPI calls.
132134
byte unsigned DataOutBuffer[FROM_HOST_SIZE_BYTES-1:0];
135+
136+
// Pipeline interface signals for buffering DataOut.
137+
// DataOut_a_valid is asserted when a complete message is available in
138+
// DataOut_a buffer and waiting to be accepted by the skid buffer.
139+
logic DataOut_a_valid;
140+
// Packed representation of the byte buffer to feed the skid input.
141+
logic [FROM_HOST_SIZE_BITS-1:0] DataOut_a;
142+
// Ready/valid wires between this module and the skid buffer.
143+
wire DataOut_a_ready;
144+
wire DataOut_x_valid;
145+
wire [FROM_HOST_SIZE_BITS-1:0] DataOut_x;
146+
133147
always @(posedge clk) begin
134148
if (~rst) begin
135-
if (DataOutValid && DataOutReady) // A transfer occurred.
136-
DataOutValid <= 1'b0;
137-
138-
if (!DataOutValid || DataOutReady) begin
149+
// If the skid buffer accepted the input token this cycle, clear the
150+
// internal valid that indicates we have buffered data.
151+
if (DataOut_a_valid && DataOut_a_ready)
152+
DataOut_a_valid <= 1'b0;
153+
154+
// Only attempt to fetch data from the host when the skid buffer can
155+
// accept it (DataOut_a_ready).
156+
if (!DataOut_a_valid && DataOut_a_ready) begin
139157
int data_limit;
140158
int rc;
141159

@@ -149,7 +167,7 @@ module Cosim_Endpoint_FromHost
149167
ENDPOINT_ID, FROM_HOST_SIZE_BYTES, data_limit, rc);
150168
end else if (rc == 0) begin
151169
if (data_limit == FROM_HOST_SIZE_BYTES)
152-
DataOutValid <= 1'b1;
170+
DataOut_a_valid <= 1'b1;
153171
else if (data_limit == 0)
154172
begin end // No message.
155173
else
@@ -159,24 +177,53 @@ module Cosim_Endpoint_FromHost
159177
end
160178
end
161179
end else begin
162-
DataOutValid <= 1'b0;
180+
DataOut_a_valid <= 1'b0;
163181
end
164182
end
165183

166-
// Assign packed output bit array from unpacked byte array.
184+
// Pack the byte array into a single vector that will be handed to the
185+
// skid buffer as its input payload.
167186
genvar iOut;
168187
generate
169188
for (iOut=0; iOut<FROM_HOST_SIZE_BYTES_FLOOR; iOut++)
170-
assign DataOut[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
189+
assign DataOut_a[((iOut+1)*8)-1:iOut*8] = DataOutBuffer[iOut];
171190
if (FROM_HOST_SIZE_BITS_DIFF != 0)
172-
// If the type is not a multiple of 8, we've got to copy the extra bits.
173-
assign DataOut[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
174-
FROM_HOST_SIZE_BITS_DIFF - 1) :
175-
FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
191+
// If the type is not a multiple of 8, copy the extra bits.
192+
assign DataOut_a[(FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS +
193+
FROM_HOST_SIZE_BITS_DIFF - 1) :
194+
FROM_HOST_SIZE_BYTES_FLOOR_IN_BITS]
176195
= DataOutBuffer[FROM_HOST_SIZE_BYTES - 1]
177196
[FROM_HOST_SIZE_BITS_DIFF - 1 : 0];
178197
endgenerate
179198

199+
/// *******************
200+
/// Data out management.
201+
///
202+
/// It has been observed that some simulators (verilator) does not handle
203+
/// combinational driving from DPI well (resulting in non-determinism wrt
204+
/// some of the combinational outputs being dropped/replicated). Questa does
205+
/// not show this behavior.
206+
/// A mitigation is to add a skid buffer to decouple the DPI interface
207+
/// from the output interface.
208+
209+
// Instantiate a single-stage pipeline to buffer tokens that arrive from
210+
// the host and present them to the module's output with proper
211+
// ready/valid handshaking.
212+
ESI_PipelineStage #(.WIDTH(FROM_HOST_SIZE_BITS)) out_pipe (
213+
.clk(clk),
214+
.rst(rst),
215+
.a_valid(DataOut_a_valid),
216+
.a(DataOut_a),
217+
.a_ready(DataOut_a_ready),
218+
.x_valid(DataOut_x_valid),
219+
.x(DataOut_x),
220+
.x_ready(DataOutReady)
221+
);
222+
223+
// Drive the module's outward-facing signals from the pipeline output.
224+
assign DataOutValid = DataOut_x_valid;
225+
assign DataOut = DataOut_x;
226+
180227
initial begin
181228
$display("FROM_HOST_SIZE_BITS: %d", FROM_HOST_SIZE_BITS);
182229
$display("FROM_HOST_SIZE_BYTES: %d", FROM_HOST_SIZE_BYTES);

0 commit comments

Comments
 (0)