Microthread IDs
Contents
Microthread IDs¶
On WSE-3 it is possible to explicitly specify the microthread ID of an
asynchronous DSD operation (i.e., a DSD operation with the .async
setting set to true
as explained in Asynchronous DSD Operations).
Constructor and Type¶
Microthread ID expressions have type ut_id
. Values of ut_id
type can be constructed from integers using
@get_ut_id
(see @get_ut_id).
Usage and Semantics¶
An asynchronous DSD operation can be assigned a microthread ID through
the .ut_id
setting of the DSD operation’s configuration struct
or through the .ut_id
setting of the @load_to_dsr
’s configuration
struct of explicit DSR operands. The value of the .ut_id
setting
must be comptime-known.
If multiple DSR operands have the .ut_id
setting specified then
the hardware will pick one of them according to the following order:
Destination operand
First source operand
Second source operand
The same order will be followed even if a DSD operation consists of
a mix of explicit DSR and DSD operands. In this case the DSD operands
will have the microthread ID specified by the .ut_id
setting of the
DSD operation’s configuration struct.
If the .ut_id
setting is not specified in the DSD operation’s
configuration struct or by any of the explicit DSR operands, then
the microthread ID will be the same as the queue ID of the first
fabric operand according to the operand ordering defined above.
Example¶
const ut0 = @get_ut_id(0);
const ut1 = @get_ut_id(1);
const ut2 = @get_ut_id(2);
const ut3 = @get_ut_id(3);
const ut4 = @get_ut_id(4);
// These asynchronous DSD operations use two different
// microthreads (i.e., ut0 and ut1) which means that they
// can be executed concurrently even if their queues
// are the same.
@mov16(out_dsd, in_dsd, .{.async = true, .ut_id = ut0});
@mov16(out_dsd, in_dsd, .{.async = true, .ut_id = ut1});
// In the case of explicit DSRs, the microthread ID can be
// specified as a setting to the @load_to_dsr calls.
@load_to_dsr(out_dsr, out_dsd, .{.async = true, .ut_id = ut2});
@load_to_dsr(in_dsr, in_dsd, .{.async = true, .ut_id = ut3});
// This operation will use the microthread ID specified by
// out_dsr according to the .ut_id setting of the respective
// @load_to_dsr call which is ut2. The microthread ID ut4
// will be ignored in this case.
@mov16(out_dsr, in_dsd, .{.async = true, .ut_id = ut4});
// This operation will use the microthread ID specified by
// the operations's .ut_id setting which is ut4. That's because
// out_dsd takes priority over in_dsr.
@mov16(out_dsd, in_dsr, .{.async = true, .ut_id = ut4});
// The .ut_id setting is not required. In this scenario, the
// microthread ID will be the same as the queue ID of the
// highest priority fabric operand (i.e., destination > first source >
// second source ... etc).
@mov16(out_dsd, in_dsd, .{.async = true});
Blocking and Unblocking Microthreads¶
Microthreads can be blocked/unblocked from a top-level comptime
block or at runtime using the @block
and @unblock
builtins (see @block and
@unblock). For example:
const ut0 = @get_ut_id(0);
var ut: ut_id;
task main() void {
// It is possible to block/unblock a microthread
// at runtime. The microthread ID may be comptime-known
// or not.
@unblock(ut0);
@block(ut);
}
comptime {
// Set microthread 'ut0' as blocked when the program starts.
@block(ut0);
}