Multithreaded data dependencies

Hint instructions and a decoder circuit manage resource dependencies in multi-threaded environments, enabling efficient parallelization of loop iterations by ensuring resource availability, thus optimizing microthread execution.

JP2026510890APending Publication Date: 2026-04-10ARM LTD
View PDF 0 Cites 0 Cited by

Patent Information

Authority / Receiving Office
JP · JP
Patent Type
Applications
Current Assignee / Owner
Filing Date
2024-02-27
Publication Date
2026-04-10

AI Technical Summary

Technical Problem

In multi-threaded environments, data dependencies across loop iterations complicate parallelization, as data required in subsequent iterations may not be available until previous iterations complete, leading to inefficiencies and potential disabling of microthreading.

Method used

Introduce hint instructions to indicate resource availability and requirements across loop iterations, using a decoder circuit to manage microthreads and a mailbox circuit to enforce virtual dependencies, allowing parallel execution despite data dependencies.

Benefits of technology

Enables effective parallelization of loop iterations by ensuring resources are available when needed, minimizing resource waiting times and maximizing microthread execution efficiency.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure 2026510890000001_ABST
    Figure 2026510890000001_ABST
Patent Text Reader

Abstract

The data processing unit includes a multithreaded processing circuit for executing processing operations of multiple microthreads, each microthread operating in a corresponding execution context that defines the architectural state. The decoder circuit generates a first microthread for a first block of instructions in response to a first occurrence of a detach instruction, and a second microthread for a second block of instructions in response to a second occurrence of a detach instruction. The second block of instructions includes data dependencies for resources accessed in the first block of instructions. A data processing unit is also provided, having an input circuit that receives input codes, which include a first block of instructions and a second block of instructions. The output circuit generates output codes corresponding to the first block of instructions and the second block of instructions. The processing circuit generates output codes based on the input codes. The processing circuit generates a first hint instruction in the output code corresponding to the first block of instructions, indicating resource availability, and a second hint instruction in the output code corresponding to the second block of instructions, indicating resource requirements. The second block of instructions has data dependencies for resources accessed in the first block of instructions.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0005] ,

[0004] , ,

[0001] This technology relates particularly to data processing in a multi-threaded environment.

[0002] It is desirable to provide a multi-threaded environment for a microarchitecture. Since it is a microarchitecture, the environment need not be visible to the programmer, nor even known to the programmer. However, as a result, data dependencies can be difficult to detect and respond to.

[0003] Viewed from a first exemplary configuration, a data processing apparatus is provided, the data processing apparatus comprising: a multi-thread processing circuit for executing processing operations of a plurality of microthreads, each microthread operating in a corresponding execution context defining an architectural state; and a decoder circuit for generating a first microthread regarding a first block of instructions in response to a first occurrence of a detach instruction, and generating a second microthread regarding a second block of instructions in response to a second occurrence of the detach instruction, wherein the second block of instructions includes a data dependency regarding a resource accessed in the first block of instructions.

[0004] Viewed from a second exemplary configuration, a method is provided, the method comprising: executing processing operations of a plurality of microthreads, each microthread operating in a corresponding execution context defining an architectural state; and generating a first microthread regarding a first block of instructions in response to a first occurrence of a detach instruction, and generating a second microthread regarding a second block of instructions in response to a second occurrence of the detach instruction, wherein the second block of instructions includes a data dependency regarding a resource accessed in the first block of instructions. [[ID=​​Viewed from a third exemplary configuration, a non-temporary computer-readable medium for storing computer-readable code for the manufacture of a data processing device is provided, the data processing device comprising: a multithreaded processing circuit for performing processing operations of a plurality of microthreads, each microthread operating in a corresponding execution context that defines an architectural state; and a decoder circuit that generates a first microthread for a first block of instructions in response to a first occurrence of a detach instruction, and generates a second microthread for a second block of instructions in response to a second occurrence of a detach instruction, wherein the second block of instructions includes data dependencies for resources accessed in the first block of instructions.

[0006] Viewed from a fourth exemplary configuration, a data processing device is provided, comprising: an input circuit configured to receive an input code including a first block of instructions and a second block of instructions; an output circuit configured to create output codes corresponding to the first block of instructions and the second block of instructions; and a processing circuit configured to generate output codes based on the input code, wherein the processing circuit is configured to generate a first hint instruction in the output code corresponding to the first block of instructions, configured to indicate resource availability, and a second hint instruction in the output code corresponding to the second block of instructions, configured to indicate resource requirements, wherein the second block of instructions includes data dependencies relating to resources accessed in the first block of instructions.

[0007] Viewed from a fifth exemplary configuration, a method is provided that includes receiving an input code comprising a first block of instructions and a second block of instructions; creating an output code corresponding to the first block of instructions and the second block of instructions; and generating an output code based on the input code, wherein the output code includes a first hint instruction configured to indicate resource availability in the output code corresponding to the first block of instructions, and a second hint instruction configured to indicate resource requirements in the output code corresponding to the second block of instructions, and the second block of instructions includes data dependencies relating to resources accessed in the first block of instructions.

[0008] Viewed from the sixth exemplary configuration, a non-temporary computer-readable medium for storing computer-readable code for the manufacture of a data processing device is provided, the data processing device comprising: an input circuit configured to receive input code including a first block of instructions and a second block of instructions; an output circuit configured to produce output code corresponding to the first block of instructions and the second block of instructions; and a processing circuit configured to generate output code based on the input code, wherein the processing circuit is configured to produce a first hint instruction in the output code corresponding to the first block of instructions, configured to indicate resource availability, and a second hint instruction in the output code corresponding to the second block of instructions, configured to indicate resource requirements, wherein the second block of instructions includes data dependencies relating to resources accessed in the first block of instructions. [Brief explanation of the drawing]

[0009] The present technology will be further described, merely as an example, with reference to the embodiments shown in the attached drawings. [Figure 1] A schematic diagram of a data processing device that can embody various embodiments of this technique is shown. [Figure 2]This section outlines the detailed operation of a thread control circuit that can embody various embodiments of this technique. [Figure 3A] This section outlines the details of epoch identifier assignment, which can embody various embodiments of this technique. [Figure 3B] This section outlines the details of epoch identifier assignment, which can embody various embodiments of this technique. [Figure 4] This section outlines the details of microthreaded execution, which can embody various embodiments of this technique. [Figure 5] This section outlines the details of microthreaded execution, which can embody various embodiments of this technique. [Figure 6] Here are two examples of hint instructions that can help overcome the limitations of data dependencies. [Figure 7] An example of execution is shown. [Figure 8] This shows an implementation of a data processing unit for handling two microthreads. [Figure 9] Two other hint instructions are shown that can be used to indicate the availability of other resources, such as memory addresses or blocks of code, and to indicate requests for other resources. [Figure 10] An example of an 8-bit register (tkn) used to support 8 semaphores is shown. [Figure 11] Here is another example of execution. [Figure 12] This shows the compiler. [Figure 13A] This shows the compiler's behavior regarding the placement of hint instructions. [Figure 13B] This shows the compiler's behavior regarding the placement of hint instructions. [Figure 14] This shows another mechanism that can be used to handle dependencies. [Figure 15] A pair of flowcharts are shown.

[0010] Before discussing embodiments with reference to the attached drawings, embodiments and their related advantages are described below.

[0011] According to one exemplary configuration, a data processing device is provided, comprising a multithreaded processing circuit for performing processing operations of multiple microthreads, each microthread operating in a corresponding execution context that defines the architectural state, and a decoder circuit that, upon a first occurrence of a detach instruction, generates a first microthread for one iteration of the loop, and upon a second occurrence of a detach instruction, generates a second microthread for another iteration of the loop, the loop includes loop-carry data dependencies on resources that extend across the loop iterations. The creation of microthreads via detach instructions may be used to parallelize tasks such as executing code belonging to the loop. Such parallelization may be handled by the microarchitecture via detach instructions and therefore may not be visible to the operating system. Such parallelization can be problematic in loops where data dependencies extend across the loop iterations. For example, if data provided in a previous iteration of the loop is needed in one iteration of the loop, it is obvious that the previous iteration of the loop should be completed before the "current" iteration of the loop can be executed. In other words, if the necessary data is not available until the previous iteration is complete, the current iteration, which depends on that necessary data, cannot be executed. This technique introduces one or more mechanisms that allow the aforementioned parallelization to still be performed regardless of data dependencies.

[0012] In some examples, a loop-carry data dependency is a read-after-write data dependency on a resource. That is, a resource is written to in one iteration of the loop, and read from in a subsequent iteration of the loop. Therefore, the value read in a subsequent iteration of the loop is derived from (or is actually written from) the value written in the previous iteration.

[0013] In some examples, a decoder circuit responds to a first hint instruction configured to indicate resource availability when executed in a first microthread, and a second hint instruction configured to indicate resource requirements when executed in a second microthread. The first hint instruction is used to indicate that the resource is available. This may occur, for example, after the resource has been written. The second hint instruction is used to indicate that the resource is needed. This may occur, for example, before the resource has been read. By using the two instructions across loop iterations, it is possible to signal that the resource is desired / provided across the iterations.

[0014] In some examples, a resource is one of the following: a register, a variable, a memory location, or a block of code. By treating a block of code as a resource, it is possible to control access to that code so that only one microthread can exist within the block at a time. This can be used, for example, to avoid race conditions between microthreads. A variable may be stored in memory, for example. This adds another level of complexity because, due to the dynamic nature of memory access, it may not be known at compile time whether there are dependencies. It is possible to improve the parallelism of microthreads by supporting dependencies through memory.

[0015] In some examples, depending on whether a condition is met, the decoder circuit responds to a second hint instruction by creating a virtual dependency, and depending on whether a condition is met, the decoder circuit responds to a first hint instruction by resolving the virtual dependency. Dependencies can be used to control how hint instructions are processed by the microarchitecture. Virtual dependencies allow control over the execution order of instructions and other instructions on which those instructions depend.

[0016] In some examples, the virtual dependency is a virtual dependency on a register. Regardless of the nature of the resource, a virtual dependency (e.g., between a hint instruction and thus other instructions that the hint instruction depends on) can itself depend on a register. That is, while the hinting mechanism that exists is implemented based on registers, in fact, a register can simply indicate the availability (or non-availability) of another resource such as a variable or a block of code.

[0017] In some examples, the register is a physical register. A physical register is a register backed up by a physical device. This is different from a logical / architecture register which is a conceptual (virtual) register. Typically, an instruction will refer to an architecture register that indicates how registers are logically related to each other. A renaming circuit is responsible for mapping architecture registers to physical registers and replacing references to architecture registers with references to physical registers at runtime to remove incorrect instruction dependencies.

[0018] In some examples, a data processing device includes a mailbox circuit configured to store made-available resources, where a first hint instruction is prevented from being issued until there is free space in the mailbox circuit, and upon issuance of the first hint instruction, a new entry for the resource is inserted into the mailbox circuit; a second hint instruction cannot be issued until a corresponding entry for the resource exists in the mailbox circuit, and upon completion of the second hint instruction, the corresponding entry for the resource is removed from the mailbox circuit. The mailbox circuit can be used to implement virtual dependencies. In particular, when a first hint instruction is issued (which requires the mailbox circuit to have free space), a new entry is inserted into the mailbox circuit to indicate the availability of the resource specified by the first hint instruction. A second hint instruction cannot be executed until the resource mentioned by the second hint instruction is listed in the mailbox circuit (thus indicating its availability). When the second hint instruction completes (for example, when execution finishes), the resource entry is removed from the mailbox circuit (which may include invalidation in the mailbox circuit), thus revoking the resource's "availability" (marking the resource as unavailable again). Subsequent instructions within each microthread that reference the same resource are prevented from being issued due to their dependencies on the resource. Other instructions that do not depend on the resource can be executed freely, and thus a limited form of parallelism may occur. In some examples, the second hint instruction cannot be issued until the corresponding entry for the resource from the previous iteration exists in the mailbox circuit. If multiple microthreads are waiting for the resource, availability is indicated to the microthread with the previous epoch ID (an epoch ID is assigned to each microthread to reflect the order in the original program of the code being executed by that microthread).

[0019] In some examples, the virtual dependency can only be resolved as a result of the execution of the first hint instruction. That is, there is no other way for the resource to become available other than through the first hint instruction. This enables strict control of the resource, such that one iteration of the loop can use the resource only when the resource is explicitly shown to be available by a previous iteration.

[0020] In some examples, the decoder circuit indicates the availability of each resource used by a particular microthread of an instruction to a newer microthread of the instruction in response to a reattach instruction within the particular microthread of the instruction and terminates the particular microthread of the instruction. As a fail-safe mechanism, when no explicit first hint instruction is provided, the operation of reattaching a particular microthread (e.g., ending the parallelism of a particular microthread) functions as an implicit first hint instruction for all resources used by that microthread. That is, if a resource is not explicitly made available by the microthread executing for iteration N of the loop, all resources used by that microthread are shown to be available for iterations >N within the loop. Note that in some embodiments, the resource will be made available for iteration N+1, i.e., the next iteration of the loop.

[0021] In some examples, depending on the condition not being satisfied, the decoder circuit responds to the first hint instruction and the second hint instruction by generating a no-operation signal. If the condition is not satisfied, the hint instruction may have no effect at all by being decoded in the same way as a no-operation instruction. Thus, there is no need to follow the hint instruction and, in fact, it can even be completely ignored. In some embodiments, there may be several different conditions that all need to be satisfied for the hint instruction to be executed as something other than a no-operation instruction.

[0022] In some cases, the condition is whether parallelism of multiple microthreads is permitted. For example, the microarchitecture may be disabled or unable to support microthreads. In this situation, microthread instructions may be ignored altogether. Such control can be easily determined by registers or bits within registers. In some cases, parallelism may be disabled, for example, if the overhead of implementing parallelism is particularly high.

[0023] In some examples, the data processing unit includes a register checking circuit configured to respond to the retrieval of an expired register value by setting an expired register flag, and the decoder circuit determines whether the expired register flag is set in response to a reattach instruction within a particular microthread of the instruction, and, if the expired register flag is set, causes the particular microthread of the instruction to be re-executed. In such embodiments, rather than providing a mechanism that can explicitly make resources available, explicitly indicate a need for resources, and combine supply and demand hints, the system simply assumes that the desired resource will become available. In many situations, this is not an unreasonable assumption. After all, microthreads for each iteration of a loop may be created sequentially. Therefore, instructions in a preceding iteration of the loop that provide data required by a subsequent iteration of the loop are likely to have already been executed. In these examples, the register checking circuit determines whether an outdated register value has been accessed, taking into account the expired register value, i.e., the sequential ordering of the program. When this occurs and the microthread terminates (e.g., through a reattach instruction), the situation is detected and the microthread is executed again. In this situation, it is highly likely that the correct value will be stored in the register, and therefore, when the microthread is executed, the register will take the correct value. Note that, as in other embodiments, the value stored in the register can be used to exercise control over other resources, such as values ​​stored in memory or even blocks of code.

[0024] According to another exemplary configuration, a data processing device is provided, comprising: an input circuit configured to receive an input code including a loop; an output circuit configured to create an output code including a loop; and a processing circuit configured to generate an output code based on the input code, wherein the processing circuit is configured to generate a first hint instruction configured to indicate resource availability and a second hint instruction configured to indicate resource requirements, within the body of the loop in the output code, and the loop includes a loop-carry data dependency on a resource that extends across the iterations of the loop.

[0025] In these examples, the data processing unit can take the form of a compiler (which may be a just-in-time compiler) or even part of a pipeline that dynamically processes incoming instructions to provide hints to a later part of the pipeline. Here, code, which can take the form of source code, bytecode, assembly code, or even processor instructions, is provided to the input circuit. The code contains loops. The loop body contains a set of instructions that are executed repeatedly. Each iteration of the loop may contain slightly different parameters. The processing circuit is used to modify at least part of the input code to produce output code. The output code also contains loops, although it may be in a different format. The loop itself has loop-carry data dependencies regarding resources. These dependencies are propagated across the loop iterations; that is, data required by one iteration of the loop is provided by another iteration of the loop. The processing performed by the processing circuit includes introducing two hint instructions in the output code: one hint instruction indicating resource availability and another hint instruction indicating resource requirements.

[0026] In some examples, the loop-carry data dependency is a read-after-write data dependency depending on the resource. Thus, in one iteration of the loop, the resource is written, and in a subsequent iteration, the resource is read. Therefore, the write of the resource in the previous iteration affects the parameters used by the subsequent iteration.

[0027] In some examples, the processing circuit is configured to place a second hint instruction before or during the first use of a resource in the body of the loop, and the processing circuit is configured to place a first hint instruction during or after the last use of the resource in the body of the loop. Placing the first hint instruction in such a position causes a second instruction indicating a request for the resource to occur before the resource is used in the body of the loop. Similarly, placing the second hint instruction before or during the first use of the resource in the body causes a first instruction indicating the availability of the resource to occur when the resource has finished being provided. In some embodiments, the second hint instruction occurs before or during the first time the resource is read in the loop. Also, in some embodiments, the first hint instruction occurs after or during the last time the resource is written to the loop. Note that hint instructions may be provided "on" a particular occasion, for example, if the instruction performs multiple functions. For example, a particular instruction may indicate the availability of the resource and write the resource at the same time, and therefore function as a first hint instruction.

[0028] In some examples, the processing circuit is configured to position the second and first hint instructions such that at least a portion of the loop body lies outside the region defined between the first and second hint instructions. For example, the entire loop body may not fit within the first and second hint instructions. It is this movement of instructions outside the region defined between the two hint instructions that enables successful parallelization. In particular, even if a particular microthread is unable to execute code that fits within the region (due to unavailability of resources), it may still be possible to execute instructions outside that region while resources become available. As a result, parallelization can be achieved. Note that in some embodiments, the first and second hint instructions are positioned to minimize the number of instructions in the loop between the first and second hint instructions. This not only minimizes the number of operations that must be performed by one microthread before a resource becomes available to another microthread, but also increases the number of instructions that can be executed by a microthread while waiting for the resource to become available to another microthread, thus naturally leading to the greatest potential for parallelization.

[0029] Here, a specific embodiment will be described with reference to the drawings.

[0030] Figure 1 schematically shows a data processing device 10 that can embody various embodiments of this technique. The data processing device 10 comprises a multithreaded processing circuit 12 and a thread control circuit 14. The thread control circuit 14 is adapted to support multiple microthreaded contexts 16. The multithreaded processing circuit 12 is a set of multithreaded execution resources and comprises multiple execution pipelines 18, a set of physical registers 20, an instruction cache 22, a level 1 data cache 26, and a level 2 cache 24. Each of the multiple execution pipelines includes a fetch circuit 28 that fetches instructions from the instruction cache 22. The fetched instructions are passed to a decode circuit 30 and a rename circuit 32 that generate control signals for other components of the multithreaded processing circuit, including the thread control circuit 14. The rename circuit 32 maps several physical registers 20 to a corresponding set of architectural registers associated with the execution context running on the pipeline 18, then passes the decoded instruction to the issue circuit 43, which issues it to the execution circuit 36. The execution circuit may include, but is not limited to, arithmetic logic units, floating-point units, and load / store units. Once the instructions have completed execution, they are passed to the rewrite circuit 40. The pipelines of components 28, 30, 32, 34, 36, and 40 are intended to be examples of a typical multithreaded data processing unit, and it will be readily apparent to those skilled in the art that any pipeline component may be a dedicated component provided for each pipeline, or may be shared among any number of pipelines 18. For example, each pipeline 18 may have several dedicated pipeline components and several components shared with one or more other pipelines 18. However, additional structures not explicitly shown may be added to the data processing unit 10. It will be readily apparent to those skilled in the art that the multithreaded processing circuit 12 may also include a single pipeline 18 that interleaves its resources across multiple microthread contexts.

[0031] Figure 2 schematically illustrates the operation details of a thread control circuit 14 that can embody various embodiments of the present technique. In some embodiments, this thread control circuit 42 may provide the thread control circuit 14 of Figure 1. The thread control circuit 42 stores several counters used to control and track different microthreads running on the data processing unit 10. In particular, the thread control circuit 42 uses an epoch counter 44 to track the oldest epoch identifier issued to a microthread having that region identifier and the newest epoch identifier issued to a microthread having that region identifier for a set of currently executing code indicated by an instruction (detach, reattach) pair. In this way, an in-flight epoch identifier may be maintained for each region identifier, as further described in relation to Figure 3A. In addition, the thread control circuit 42 may maintain an execution context table 46 showing each execution context currently maintained by the multithreading unit, the corresponding epoch identifier, and the corresponding region identifier. It will be readily apparent to those skilled in the art that the information indicated to be held in the execution context table 46 is not exhaustive, and any information associated with an execution context may also be stored there. For example, the execution context table 46 may maintain a mapping between physical registers and architectural registers assigned to each execution context. In addition, the thread control circuit maintains runtime data 48 based on performance metrics related to processing operations. The runtime data may be continuously updated based on the currently executing instruction and / or maintained independently for each region identifier. In this way, the thread control circuit can control and maintain, for each region identifier, whether additional microthreads are created, and, if so, which epoch identifiers are associated with which execution contexts and which region identifiers.

[0032] Figures 3A and 3B schematically illustrate the details of epoch identifier assignment, which can embody various embodiments of this technique. Starting from Figure 3A, the epoch identifier 50 is processed cyclically. The thread control circuit assigns epoch identifiers in ascending order as new microthreads are created, and wraps around when the largest supported epoch identifier is reached. This scheme is implemented using two counters that track the oldest epoch identifier 52 and the newest epoch identifier 54. When a new epoch identifier is assigned, the newest epoch identifier is incremented, and when the oldest epoch identifier is assigned, it wraps around to 0. When a microthread is committed (this happens in order), the oldest epoch identifier is incremented, thereby freeing the epoch identifier for use by subsequent microthreads. As shown in Figure 2, the newest epoch counter 54 and the oldest epoch counter 52 are maintained for each region identifier.

[0033] As shown in Figure 3B, in embodiments that support nested parallelization regions, the epoch identifier 56 associated with each microthread may be defined hierarchically. In the illustrated embodiment, the epoch identifier 56 is defined by the outermost identifier 58 associated with the outermost pair of (detach, reattach) instructions, the outer identifier 60 defined by the outer pair of (detach, reattach) instructions nested within the outermost pair of (detach, reattach) instructions, the inner identifier 62 associated with the inner pair of (detach, reattach) instructions nested within the outer pair of (detach, reattach) instructions, and the innermost identifier 64 associated with the innermost pair of (detach, reattach) instructions nested within the inner pair of (detach, reattach) instructions. It will be readily apparent to those skilled in the art that the definition of the four layers of epoch identifiers associated with nested pairs of (detach, reattach) instructions is for illustrative purposes only, and that any number of sets of nested pairs of (detach, reattach) instructions can be supported based on the mechanism described. In some embodiments, the bit width assigned to each layer of epoch identifiers may be dynamically changed by hardware at runtime, while in other embodiments, the bit width assigned to each layer of epoch identifiers may be statically determined. Similar to the example considered in relation to Figure 3A, each of the outermost identifier 58, outermost identifier 60, innermost identifier 62, and innermost identifier 64 maintains a pair of counters associated with the oldest and newest epoch identifiers. In particular, the outermost epoch identifier 58 is one of the available set of outermost identifiers 66, associated with the oldest outermost identifier 68 and the newest outermost identifier 70. Similarly, the assignments of the outer identifier 60, the inner identifier 62, and the innermost identifier 64 are maintained through the corresponding outer oldest identifier and outer newest identifier, the inner oldest identifier and inner newest identifier, and the innermost oldest identifier 74 and innermost newest identifier 76.

[0034] Figures 4 and 5 schematically illustrate details of microthreaded execution examples that can embody various embodiments of this technique. In particular, these figures are based on the following exemplary C code with corresponding assembly code.

[0035] [Table 1]

[0036] In the illustrated examples, the compiler makes the following modifications to the assembly code in order to utilize the task-level parallelization described in some embodiments of the present invention.

[0037] [Table 2]

[0038] The detach instruction used in the modified assembly code above contains multiple inputs. The loop_body and loop_cont fields are the addresses of the instruction's detach block and continuation block, respectively. These can be encoded using a program counter-based offset to represent such addresses. The detach block field can be omitted if it corresponds to an instruction following the detach instruction in program order. The region_id field is a region identifier that must be unique at runtime and associated with a particular annotated region. In practice, it is sufficient for the region identifier to be unique only within a region nest, meaning that the same region identifier can be reused across different nests. Metadata fields may capture extra information that can be passed to the thread control circuit. In particular, metadata can be used to encode a parallelization confidence level, representing the likelihood of dynamic dependencies materializing at runtime, based on profiling data, for example, to encode a parallelization value level by including additional information about the estimated length of parallel paths expressed in terms of the number of instructions, which may include both the best-case and worst-case number of instructions, and other information related to the expected types of dependencies within a region, such as the presence or absence of read-after-write hazards. Similarly, the reattach instruction specifies the loop_cont address and region identifier, while the synchronization instruction specifies the region identifier.

[0039] Figure 4 schematically illustrates an example of microthread execution that can embody an embodiment of this technique. In particular, the thread executing the detach instruction (initially uthread 0) continues execution from loop_body without changing its epoch identifier. The generated microthread (initially uthread 1) starts execution from loop_cont using the newly assigned epoch identifier, reflecting the fact that in the original serial program, the continuation path would have been executed after the detach path in program order. In this case, uthread 0 continues until it reaches the reattach instruction, uthread 1 starts at the continuation address, increments the value stored in register x10 by 1, compares the value stored in x10 with the value stored in x3, and updates the condition flag based on the result before branching to loop_head (assuming successful execution without data hazards). Execution of uthread 1 continues from loop_head with the issuance of a detach instruction that creates microthread uthread 2, before uthread 1's execution continues from loop_body (assuming no data hazards and successful execution) until it reaches the reattach instruction. As illustrated, the creation of a new microthread by each previous microthread continues until the condition flag associated with the b.ne instruction is set to 0, i.e., the value held in register x10 is equal to x3. At this point, the execution of the microthread issuing the synchronization instruction (in this case, uthread n) is paused until all microthreads with old epoch identifiers have completed, i.e., successfully executed the reattach instruction.

[0040] Figure 5 schematically illustrates the details of an example of microthread execution that can embody various embodiments of this technique. In particular, the thread executing the detach instruction (in this case, uthread 0) continues execution starting from a continuation path (loop_cont) with a newly assigned epoch identifier, reflecting the fact that in the original serial program, the continuation path would have been executed after the detach path (loop body) in program order. The generated microthread (uthread 1) starts execution from the detach path (loop_body) with an epoch identifier inherited from the parent microthread. In this exemplary embodiment, uthread 0 executes the instruction after loop_cont, increments the value initially stored in x10 by 1, compares the value of x10 with x3, and updates the condition flag based on the result before branching to loop_head and re-executing the detach instruction. This generates a new microthread, uthread 2, which continues from loop_body with the updated value in register x10 imported from the execution context associated with uthread 0 to the execution context associated with uthread 2. As illustrated, the creation of the microthread by uthread 0 continues until the condition flag associated with the b.ne instruction is set to 0, i.e., the value held in register x10 is equal to x3. At this point, a synchronization instruction is issued, and the execution of uthread 0 is paused until all microthreads with old epoch identifiers have completed, i.e., until the microthreads have successfully executed the reattach instruction.

[0041] In these examples, the detach instruction results in the creation of a microthread.

[0042] The reattach command terminates the currently executing microthread.

[0043] Using the techniques described above, it may be appropriate to provide additional mechanisms for handling more complex dependencies of resources (e.g., registers, memory, blocks of code). One situation in which this may occur is when each iteration of a loop depends on data modified in the previous iteration; that is, the loop body contains raw data dependencies that extend across the loop's iterations. For example, consider the following code:

[0044] [Table 3]

[0045] In this example, the variable "d" is used within a call to the complex_update function in each iteration. The result of the complex_update function call is then stored as the new value of variable "d", and therefore the new value of variable "d" is used in the next iteration. Depending on the nature of variable "d", particularly where it is stored, handling such read-after-write dependencies can be inefficient to resolve (and thus may block the use of microthreads) or remain unresolved. For example, if variable "d" is stored in memory, the raw dependency may be detectable, and if detected, it may result in newer microthreads being squashed and restarted. This could result in all microthreads being squashed, and thus potentially leading to the microthreading being disabled. If variable "d" is stored in a register, the raw dependency may not be detected because it is usually assumed that such hazards are removed from the code at compile time.

[0046] Figure 6 shows examples of two hint commands that can help overcome these limitations. Hint commands indicate the availability (sending) and request (receiving) of a specific resource.

[0047] These instructions allow the propagation of resources in the form of registers and their stored values ​​between microthreads (e.g., between loop iterations) (if microthreading is permitted to enable parallel execution). If microthreading is not permitted, the instructions are ignored entirely (decoded, for example, as in the case of a NOP instruction).

[0048] In these examples, the architecture state of a microthread when it starts is not exactly the same as the architecture state at the end of the previous iteration. In particular, resources (e.g., registers) <registerid>The registers (and their stored values) are not available for subsequent iterations and will be provided later via an receive instruction. Until a microthread encounters an receive instruction, the registers cannot be read within that microthread. Note that other instructions that do not depend on resources can still be executed. Therefore, a certain level of parallelism can still be achieved. The send instruction thereby indicates that the sequential program flow should wait until it is indicated that a resource (e.g., a register) is available.

[0049] In contrast, the send command creates an indication that the resource is available. This indication is sent to the next iteration of the loop.

[0050] value <regionid>The ID is a value used to uniquely identify a loop or other data structure, and can therefore be used to eliminate ambiguity between inner and outer loops. The ID may be the program counter value at the starting address of the loop's continuation block (typically a block of code that handles loop maintenance / induction variable updates when the loop should be repeated rather than terminated).

[0051] parameters <messageid>This can be used to represent further information, such as a unique identifier. (Parameter) <messageid>This can be used to distinguish return values ​​from a series of function calls, all of which may be returned through a specific register (e.g., x0). Parameter <messageid>It can also be used for more explicit data parallelism, for example, by relying on explicit data flow propagation.

[0052] <metadata>Fields can be used to propagate additional information from the compiler or programmer. For example, this could indicate the expected expansion of a variable to enable value prediction at the receiving site.

[0053] Therefore, the example previously given in C can be converted to assembly as follows (inserting send and receive hint instructions):

[0054] [Table 4]

[0055] In the example above, the send and receive instructions pass the value stored in register w20 (corresponding to variable d). As shown in the C code, variable d is passed between loop iterations. Both instructions also provide ".continuation" (e.g., the program counter value of .continuation) to remove ambiguity between nested loops (although in this example, ambiguity removal is not necessary). As a result, the second microthread executing the second iteration of the loop will, upon encountering a receive instruction, halt until it receives notification that resource / register w20 is available. The first microthread executing the first iteration of the loop ignores the receive instruction but, upon encountering a send instruction related to resource / register w20, will signal such availability. The first microthread may be identified as having the oldest epoch ID after the very first detach for the new parallel region (the latter is identified by its unique region ID == continuation address). In fact, at the very first detachment, the microarchitecture knows that there were no active threads (sequential mode), and therefore it is easy to identify the microthread that will be responsible for handling iteration 0. This information can be stored in a flag of a particular microthread, and as a result, that particular microthread knows that the receive should be ignored.

[0056] Figure 7 shows how the above code can be executed. In the first microthread, the detach code is executed. This creates a second microthread with epoch ID 1. In this second microthread, the continuation code is executed and i is immediately updated. To reduce redundancy, the update function is not shown, but in this example, the update function would increment i (in register w19) by 1, according to the assembly code shown above. Next, a check is performed to see if i is less than n (1024). If so, the process proceeds to the detach instruction which creates a third microthread (epochID=2). The second microthread then proceeds to the loop header and body. If i is greater than or equal to n, the second microthread executes the exit code, which results in synchronization between the microthreads.

[0057] In the loop body, the second microthread (epoch ID=1) reaches the received instruction. This instruction cannot be executed because the signal that the resource ("d") is available has not yet been received (and therefore none of the subsequent instructions can be executed).

[0058] Meanwhile, in the first microthread, after executing the detach instruction, the microthread proceeds to the loop body. After executing the complex_update function, it encounters a send instruction indicating that resource "d" is now available. The process by which this message is communicated to other microthreads will be discussed in more detail below. The first microthread then enters the exit block.

[0059] When the send command is executed in the first microthread, the receive command in the second microthread becomes executable. This then allows the send command in the second microthread to be executed, thereby enabling the third microthread to proceed beyond its receive command (and so on). Once the send command in the second microthread is completed, the reattach command is executed, which terminates the second microthread as described above.

[0060] This model of microthread generation will be understood to follow the one shown with respect to Figure 4. This technique, including the use of send and receive commands, is equally applicable to other execution models, such as the one shown with respect to Figure 5.

[0061] Figure 8 shows an implementation of a data processing unit for handling two microthreads (threadlets). Fetch and decode circuits 705a and 705b are provided for each threadlet. These fetch and decode instructions are sent to issue queues 710a and 710b, which store the fetched and decoded instructions in (for example) program order. An instruction picker 735 picks instructions for execution, forming issue queues 710a and 710b. The input operands of the picked instructions are associated with each other and stored in reservation stations 740a and 740b. These enable out-of-order execution of instructions by storing instruction input operands and monitoring the results generated by the execution pipeline for operand transfer. The reservation stations are associated with execution units 745a and 745b (for example, one reservation station per execution unit). Therefore, when the operands of an instruction in the reservation station become available, they may be provided to the associated execution unit for execution.

[0062] Out-of-order execution can be achieved at each reservation station via a rename circuit. Like other elements of System 700, the rename circuit is replicated for each microthread that can run concurrently. Thus, architecture register files 715a, 715b are provided, showing non-speculative values ​​of the architecture registers (e.g., mappings of physical registers to architecture registers for instructions that have been successfully executed and committed in program order). In the case of pipeline flushing, the values ​​of the ARF are restored. Reorder buffers 725a, 725b track the original program order of issued instructions and store the speculative results of each instruction. When an instruction is committed, the speculative result is propagated from the ROB entry to a designated register in the ARF. Within each ROB, the commit pointer points to the next entry (instruction) to be committed (e.g., in program order). The issue pointer, on the other hand, points to the next position where the instruction will be added to the ROB. Finally, the register alias tables 720a and 720b indicate where the latest mappings for the architecture registers can be found. RAT entries can point to mappings in ARF715a and 715b, or entries in ROB725a and 725b, respectively, depending on whether instructions writing to the architecture registers are committed. Incorrect dependencies can be eliminated by creating a new entry in RAT720a and 720b for each new value generated by an instruction. In this way, each new value generated by an instruction is stored in a new (physical) register.

[0063] Therefore, instructions exiting the execution circuits 745a and 745b are stored in the associated ROBs 725a and 725b, depending on which microthread the instruction was being executed for. The RATs 720a and 720b will point to that instruction in the ROB until the time when the instruction is committed. At that point, the RAT of that register will point to an entry in the RAF that provides a mapping from architecture registers to physical registers.

[0064] Only one threadlet is allowed to be globally non-speculative. When a sync instruction is executed by a microthread or threadlet, and all other microthreads or threadlets execute a reattach instruction, the architectural state of the threadlets must be merged. In the case of registers, this means that the contents of the ARF must be merged. If a register has been written to by a threadlet since its creation, that register will hold the most recent value for that particular epoch; otherwise, the register value for that epoch should be recursively collected from older microthreads. This behavior may be enabled by adding a write bit to the entry in the ARF that is set when the corresponding register is written to. Thus, if multiple microthreads have written to a register, the "true" value of the register after reattachment will be the value stored by the most recent microthread that wrote to the register. Obviously, if no microthreads have written to a register, the value of that register remains unchanged.

[0065] Within this system, send and receive commands use mailbox circuits 730a and 730b, provided for each microthread or threadlet executing concurrently. When a send command is encountered, the command can proceed only if there is an available entry in that microthread's mailbox 720a or 730b. If space exists, a new entry is added to that microthread's mailbox once the send command is completed. The entry contains a message ID that indicates the resource to which the send command relates. For example, if the resource is a register, this could be a register ID. The entry also contains a message type that indicates what the resource type is. If the resource is a register, an optional register value field allows specifying the register value, thus allowing the register value to be efficiently passed around. Finally, a validity entry can be used to indicate whether the entry in the mailbox is valid.

[0066] Instead of waiting for the send command to complete before adding an entry, it is also possible to add the entry to the mailbox as part of the execution of the send command. In this case, additional metadata needs to be provided to track the speculative state of the send command and respond appropriately in case of misspeculation. Part of responding to misspeculation (e.g., following an incorrect branch in branch prediction) would involve squashing the command across threadlets. The link between the send and receive pairs may be stored as an additional field in the mailbox circuit, and as a result, the command executed as a result of a mispredicted send command may also be squashed.

[0067] When an incoming command is encountered by a younger (i.e., newer) threadlet or microthread, the microthread or threadlet stalls until an entry corresponding to the desired resource is marked as valid in the mailbox belonging to the microthread that is the direct ancestor microthread of the microthread that issued the incoming command. Once the incoming command is complete, the mailbox entry for the outgoing command that enabled the dispatch (or issuance) of the incoming command is invalidated.

[0068] It is also possible that the message ID field is associated with a set of resources, rather than each entry in the mailbox being associated with a single resource. One way to do this is, for example, to implement the message ID field as a FIFO queue, which assumes that send commands are executed in programmatic order. In this way, it is possible to increase the isolation between microthreads / threadlets and, therefore, further increase parallelism.

[0069] Please note that the above system 700 is just one example of how processing of multiple microthreads or threadlets can be achieved.

[0070] In the previous assembly code example, one of the hint instructions in the form of a receive instruction was explicitly provided. However, this is not always necessary. Instead, the detach instruction itself can include a hint (for example, in the detach instruction's metadata) that the resource will be provided later. For example,

[0071] [Table 5]

[0072] In such an example, the first instruction attempting to read the listed resource (w20) will stall. In this example, the instruction "mov w0, w20" will stall as described above. The instruction will be allowed to be issued when the corresponding entry for w20 is found in the mailbox of the microthread from the previous iteration.

[0073] In another variation, the receiving list is provided before the loop.

[0074] [Table 6]

[0075] In yet another variation, both the send and receive instructions can be removed, and operands can be added to instructions that make resources available (e.g., perform the last write to a register) and instructions that require resources (e.g., perform the first read to a register). For example,

[0076] [Table 7]

[0077] Encountering an instruction with the .receive operand means that, as with a receive instruction, the instruction will be suspended until the requested resource (w20) is made available. Encountering an instruction with the .send operand means that the instruction indicates the availability of the specified resource (w20) to the receiving microthread. In this variation, there is no indication of which loop the hint belongs to. Therefore, this information must be inferred. For example, one could assume that such a hint applies to the outermost loop.

[0078] Up to this point, it has been commonly assumed that the resource in question is a register identified by its register ID. However, this is not necessarily the case; in fact, it can indicate the availability of other resources, such as data values ​​stored in memory, or even blocks of code, and await their availability.

[0079] As mentioned above, an alternative to providing dedicated mailboxes 730a and 730b is for the ROB itself to function as a mailbox. In this scenario, it is necessary to record the link (between send / receive pairs) across microthreads. Furthermore, a send command is prevented from committing until the corresponding receive command has also committed; otherwise, the register value will be lost from the ROB.

[0080] Figure 9 shows two other hint instructions that can be used to indicate the availability (signaling) of other resources, such as memory addresses or blocks of code, and requests (waits) for other resources. Similar to the hint instructions shown in Figure 6, these hint instructions allow the propagation of resources identified by a semaphore ID and its value (if any) between microthreads (e.g., between loop iterations) (if microthreading is permitted to enable parallel execution). If microthreading is not permitted, the instructions are ignored entirely (decoded, for example, as in the case of a NOP instruction).

[0081] <semaphoreid>The field is used to provide an identifier to each signal / wait pair and can therefore be used to identify specific resources. A wait instruction for a particular identifier will wait until the corresponding signal instruction (identifying the same identifier) ​​is executed. In this case, the wait prevents any subsequent instructions from being executed until the wait is resolved. That is, the wait acts like a barrier that prevents subsequent instructions from being executed in program order until the wait is complete. This can be achieved, for example, by setting a specific flag within the ROB entry. As a result, semaphores can be used not only to "guard" variables but also to "guard" critical sections of code where only one microthread may be executing at a time.

[0082] Similar to the instructions shown in Figure 6, <regionid>The field is used to uniquely identify a loop or other data structure, and therefore can be used to eliminate ambiguity between the inner and outer loops.

[0083] Optional <epochdistance>The value can be used to indicate that propagated dependencies lie between iterations (e.g., epochs) separated by a set interval (EpochDistance), rather than between adjacent iterations. For example, in iteration n, a wait hint with an EpochDistance of 4 indicates that a signal with a matching SemaphoreID that needs to be synchronized is in iteration n-4, not n-1. Similarly, if the EpochDistance is 4 for a signal instruction in iteration n, this indicates that the corresponding wait instruction will be in a future iteration n+4. Thus, this can capture more complex memory dependencies such as A[i+3]=A[i]+B[i]. An EpochDistance of 0 can be used in situations where a conflict is certain to occur, causing the current iteration to wait until all previous iterations have signaled (or reattached).

[0084] Similar to the instructions in Figure 6, optional <metadata>Fields can be used to propagate additional information from the compiler or programmer.

[0085] For example, consider the following code.

[0086] [Table 8]

[0087] In this example, the variable "x" is used in most iterations in the `read_modify_write` function call. This reads the variable x, modifies it, and then writes it back, and therefore the written-back value is (potentially) used in the next iteration. Note that the function `frequently_true` returns true with a fairly high probability, and therefore `read_modify_write` occurs with a fairly high frequency. If `read_modify_write` does not occur frequently, the overhead associated with "guarding" the variable may be high, which may be a condition under which the hint instruction can be ignored. Such situations can be monitored, for example, using resource monitoring.

[0088] Therefore, the example previously given in C can be converted to assembly as follows (inserting signal hint instructions and wait hint instructions):

[0089] [Table 9]

[0090] In the example above, the signal and wait instructions signal and wait on a semaphore with the ID tkn0 (corresponding to variable x). Both instructions also provide ".continuation" (e.g., the program counter value of .continuation) as the region ID to remove the ambiguity of nested loops (although in this example, disambiguation is not necessary). As a result, the second microthread executing the second iteration of the loop will, upon encountering the wait instruction, suspend until it receives notification that the resource / variable tkn0 is available. The first microthread executing the first iteration of the loop (which is the first microthread of the loop) will ignore the wait command and, upon encountering the signal instruction associated with the resource / variable tkn0, will signal the availability of tkn0.

[0091] In practice, the SemaphoreID is mapped to a register (or part thereof). That is, wait hint instructions and signal hint instructions use registers to create virtual dependencies.

[0092] This is illustrated in Figure 10, which shows an example of an 8-bit register (tkn) used to support eight semaphores. The "signal" hint instruction causes the corresponding semaphore in the tkn register (0 in this example) to flip from 0 to 1, and the "wait" hint instruction causes the reverse to happen.

[0093] The same mailboxes 730a and 730b shown in Figure 8 can be used for semaphore implementation. Here, a special "type" is given to semaphore signaling, in contrast to the register signaling shown earlier, where a semaphore ID is given instead of a register ID for the message ID. Furthermore, the EpochDistance parameter is considered to control which of these is used.

[0094] Figure 11 shows how the above code can be executed. In the first microthread, the detach code is executed. This creates a second microthread with epoch ID 1. In this second microthread, the continuation code is executed and i is immediately updated. To reduce redundancy, the update function is not shown, but in this example, the update function would increment i (in register w19) by 1, according to the assembly code shown above. Next, a check is performed to see if i is less than n (1024). If so, the process proceeds to the detach instruction which creates a third microthread (epochID=2). The second microthread then proceeds to the loop header and body. If i is greater than or equal to n, the second microthread executes the exit code, which causes synchronization between the microthreads.

[0095] In the body of the loop, the second microthread (epoch ID=1) reaches the wait instruction. This instruction cannot be executed because it has not yet received the signal that x (guarded by semaphore "tkn0") is available (and therefore cannot execute any subsequent instructions).

[0096] Meanwhile, in the first microthread, after executing the detach instruction, the microthread proceeds to the body of the loop (since it is the first microthread, it ignores the wait instruction). Here, we assume that the frequently_true function always returns true. Therefore, the next operation performed by the first microthread is the read_modify_write operation, which is performed on the variable x. At that point, it encounters a signal instruction to indicate that resource x, guarded by the semaphore "tkn0", is now available. This can be achieved using the aforementioned mailboxes 730a and 730b. The first microthread then enters the exit block.

[0097] When a signal instruction is executed in the first microthread, a wait instruction becomes available for the second microthread. This then allows the second microthread to finally execute its signal instruction, thereby enabling the third microthread to proceed beyond its hint instruction (and so on). Once the signal instruction in the second microthread is completed, a reattach instruction is executed, which terminates the second microthread as described above.

[0098] This model of microthread generation will be understood to follow the one shown with respect to Figure 4. This technique, including the use of signal and wait instructions, is equally applicable to other execution models, such as the one shown with respect to Figure 5.

[0099] Figure 12 shows a compiler 1200, which is one example of a data processing device claimed by the patent. The compiler could be, for example, a regular compiler or a just-in-time compiler. The data processing device could also be embodied as, for example, part of a pipeline. Within compiler 1200, an input circuit receives input code, the input code is processed by a processing circuit 1220 to produce output code, and the output code is output by an output circuit 1230. The input code contains a block of instructions (which may be the same). The output code corresponds to the input code but also contains hints, the aforementioned hint instructions to indicate dependencies. In the case of a compiler, dependencies can be seen more easily because the whole picture of the code is all seen at the same time. One simple way to do this is to look for loops (e.g., for loops, while loops, or recursive function calls) in which a particular variable is read before it is written. The nature of the (looped) code will often suggest raw dependencies across the loop iterations.

[0100] Figures 13A and 13B illustrate the compiler 1200's behavior regarding the placement of hint instructions (in this case, in the form of wait and signal instructions). In Figure 13A, the wait instruction is placed before the first instruction that reads the guarded resource (x), and the signal instruction is placed after the last instruction that writes the guarded resource (x). A small block of instructions 1300 lies within a for loop that is not between the wait and signal instructions. These instructions are before the wait instructions and may be executed in parallel across microthreads. Figure 13B shows an alternative behavior in which the aforementioned requirements are met, but the number of instructions between the wait and signal instructions is minimized. As a result, the block of instructions 1310 that may be executed in parallel is expanded compared to the example in Figure 13A, leading to greater parallelism that can be achieved.

[0101] Figure 14 shows another mechanism that can be used to handle dependencies. This mechanism can be used as an alternative to the previously presented mechanism. In particular, the ARF is extended with additional bit fields 1400, 1410 used to indicate whether the first access to a particular register is a read (1) or not (0). A RAW dependency should not be possible if the first access to a register is a write. A RAW dependency exists if, when the microthreads are synchronized during reattachment, the register has an asserted expire bit (1) and the same register was also written to by an older microthread.

[0102] In situations where the aforementioned messaging system is used, for example, the availability of a resource (register) can be indicated by determining whether a message has been sent using mailboxes 730a and 730b shown in Figure 8. This can be achieved by not allowing the removal of entries from mailboxes 730a and 730b until a reattachment occurs (provided that the validity bit of the entry is also set to 0), or by using, for example, another tracking mechanism.

[0103] In situations where the aforementioned messaging system is not used, no dependency mechanism is provided, and therefore, younger (newer) threadlets must be re-executed. This is likely because the values ​​obtained for the registers were incorrect.

[0104] Figure 15 shows a pair of flowcharts 1500 and 1565 illustrating the behavior of the compiler 1200 and the data processing unit 10, respectively. In this particular example, it is assumed that the mechanism described with reference to Figure 14 is not used.

[0105] In step 1505, the input code is received by the compiler 1200. In step 1510, the input code is processed to produce the output code. This process includes at least adding hints to the code. Then, in step 1515, the output code is output. The output code may be input further downstream in the pipeline (in which case the compiler 1200 and the device 10 are the same data processing device), or it may be output as an executable file (for example) that is later executed by the device 10. In either case, in step 1520, the next instruction is executed by the device 10. In step 1525, if the instruction is a receive instruction or a wait instruction, in step 1530 it is determined whether the specified resource is indicated as available. If not, the execution of the instruction is suspended until the specified resource becomes available. Otherwise, in step 1535 the instruction is executed, and the process returns to step 1520. If, in step 1525, the instruction is not a receive instruction or a wait instruction, then in step 1540, it is determined whether the instruction is a send instruction or a signal instruction. If so, in step 1545, it is indicated that the specified resource is available, and the process proceeds to step 1535. If, in step 1450, the instruction is determined whether it is guarded. In particular, it is determined whether the instruction is between a send / receive pair or a signal / wait pair. If it is not between, the instruction is executed in step 1535. Otherwise, in step 1555, it is determined whether the instruction is within a signal / wait block. If it is within a block, the flow waits in step 1560 until the resource is available, and then the process proceeds to step 1535. Otherwise, in step 1565, it is determined whether the instruction is performing a read of a guarded register. If it is not, the process proceeds to step 1535. Otherwise, the flow waits in step 1570 until a register becomes available, and once it becomes available, the flow proceeds to step 1535.

[0106] The concepts described herein may be embodied in computer-readable code for the fabrication of devices that embody the described concepts. For example, the computer-readable code can be used in one or more stages of a semiconductor design and fabrication process, including an electronic design automation (EDA) stage, to fabricate an integrated circuit comprising a device that embodies the concepts. The computer-readable code described herein may additionally or alternatively enable the definition, modeling, simulation, verification, and / or testing of devices that embody the concepts described herein.

[0107] For example, computer-readable code for fabricating a device embodying a concept described herein may be embodyed by code that defines a hardware description language (HDL) representation of the concept. For example, the code may define register-transfer-level (RTL) abstractions of one or more logic circuits for defining a device embodying a concept. The code may define HDL representations of one or more logic circuits embodying the device in Verilog, SystemVerilog, Chisel, or an intermediate representation such as Very High-Speed ​​Integrated Circuit Hardware Description Language (VHDL) and FIRRTL. The computer-readable code may provide definitions that embody the concept using system-level modeling languages ​​such as SystemC and SystemVerilog, or other behavioral representations of the concept that may be interpreted by a computer to enable simulation, functional and / or formal verification, and testing of the concept.

[0108] Additionally or alternatively, computer-readable code may define low-level descriptions of integrated circuit components that embody the concepts described herein, such as one or more netlists or integrated circuit layout definitions, including representations such as GDSII. One or more netlists or other computer-readable representations of integrated circuit components may be generated by applying one or more logic synthesis processes to the RTL representations to generate definitions used for fabricating devices that embody the invention. Alternatively or additionally, one or more logic synthesis processes can generate bitstreams from computer-readable code that are loaded into a field-programmable gate array (FPGA) to configure the FPGA to embody the concepts described herein. The FPGA may be deployed for the purpose of verifying and testing the concept before fabrication in an integrated circuit, or the FPGA may be deployed directly into a product.

[0109] Computer-readable code may include a mixture of code representations for the fabrication of a device, for example, a mixture of one or more RTL representations, netlist representations, or other computer-readable definitions used in semiconductor design and fabrication processes for fabricating a device embodying the present invention. Alternatively or additionally, the concept may be defined as a combination of computer-readable definitions used in semiconductor design and fabrication processes for fabricating a device and computer-readable code that defines instructions to be executed by the device once it is fabricated.

[0110] Such computer-readable code may be placed on any known temporary computer-readable medium (such as wired or wireless transmission of code over a network) or on a non-temporary computer-readable medium such as a semiconductor, magnetic disk, or optical disk. Integrated circuits fabricated using computer-readable code may include components such as a central processing unit, a graphics processing unit, a neural processing unit, a digital signal processor, or one or more other components that individually or collectively embody a concept.

[0111] In this application, the phrase "configured to..." is used to mean that an element of the device has a configuration that enables it to perform a defined operation. In this context, "configuration" means the arrangement or interconnection of hardware or software. For example, the device may have dedicated hardware to provide the defined operation, or a processor or other processing device may be programmed to perform the function. "Configured to" does not mean that an element of the device must be modified in any way to provide the defined operation.

[0112] While exemplary embodiments of the present invention have been described in detail herein with reference to the accompanying drawings, it should be understood that the present invention is not limited to those exact embodiments, and that various changes, additions, and modifications may be made by those skilled in the art without departing from the scope and spirit of the invention as defined by the appended claims. For example, various combinations of the features of the dependent claims may be made together with the features of the independent claims without departing from the scope of the present invention.< / metadata> < / epochdistance> < / regionid> < / semaphoreid> < / metadata> < / messageid> < / messageid> < / messageid> < / regionid> < / registerid>

Claims

1. A data processing device, A multithreaded processing circuit for executing the processing operations of multiple microthreads, where each microthread operates in a corresponding execution context that defines the architectural state, The system includes a decoder circuit that generates a first microthread for a first block of instructions in response to a first detach instruction, and generates a second microthread for a second block of instructions in response to a second detach instruction, A data processing device in which the second block of an instruction includes data dependencies relating to resources accessed in the first block of the instruction.

2. The first block of the instruction and the second block of the instruction are iterations of the same loop. The data processing apparatus according to claim 1, wherein the data dependency extends over the iterations of the loop.

3. The data processing apparatus according to claim 1 or 2, wherein the data dependency is a read-after-write data dependency relating to the resource.

4. The decoder circuit, A first hint instruction, which is configured to indicate the availability of the resource when executed in the first microthread, A data processing device according to any one of claims 1 to 3, which responds to a second hint instruction configured to indicate resource requirements when executed in the second microthread.

5. The data processing apparatus according to claim 4, wherein the resource is one of a register, a variable, a memory location, and a block of code.

6. Depending on whether the condition is met, the decoder circuit responds to the second hint instruction by creating a virtual dependency. The data processing device according to claim 4 or 5, wherein, in response to the fulfillment of the above conditions, the decoder circuit responds to the first hint instruction by resolving the virtual dependency.

7. The data processing apparatus according to any one of claims 6, wherein the virtual dependency is a virtual dependency to a register.

8. The data processing apparatus according to claim 7, wherein the register is a physical register.

9. A mailbox circuit configured to store the resources that have been made available, The first hint command is prevented from being issued until there is available capacity in the mailbox circuit. In response to the issuance of the first hint instruction, a new entry is inserted into the mailbox circuit with respect to the resource. The second hint instruction cannot be issued until the corresponding entry for the resource exists in the mailbox circuit. The data processing device according to any one of claims 4 to 8, wherein the corresponding entry of the resource is deleted from the mailbox circuit in response to the completion of the second hint instruction.

10. The data processing apparatus according to any one of claims 4 to 9, wherein the virtual dependency can only be resolved as a result of the execution of the first hint instruction.

11. The data processing device according to any one of claims 1 to 9, wherein the decoder circuit, in response to a reattachment instruction within a specific microthread of the instruction, indicates to a newer microthread of the instruction the availability of each resource used by that specific microthread of the instruction, and terminates the specific microthread of the instruction.

12. The data processing device according to any one of claims 6 to 11, wherein the decoder circuit responds to the first hint command and the second hint command by generating a no-operation signal, depending on whether the above condition is not met.

13. The data processing apparatus according to any one of claims 6 to 12, wherein the condition is whether the parallelization of the plurality of microthreads is permitted.

14. The system includes a register check circuit configured to respond to the acquisition of an expired register value by setting an expired register flag, and The data processing device according to any one of claims 1 to 13, wherein the decoder circuit determines whether the expired register flag is set in response to a reattachment instruction within a specific microthread of the instruction, and, in response to the expired register flag being set, causes the specific microthread of the instruction to be re-executed.

15. It is a method, This involves multiple microthreads, each microthread operating within a corresponding execution context that defines the architectural state, and performing the processing operations of multiple microthreads. In response to the first occurrence of a detach instruction, a first microthread is generated for the first block of instructions, This includes generating a second microthread relating to a second block of instructions in response to a second occurrence of the detach instruction, A method wherein the second block of the instruction includes data dependencies relating to resources accessed in the first block of the instruction.

16. A non-temporary computer-readable medium for storing computer-readable code for the manufacture of a data processing device, wherein the data processing device is A multithreaded processing circuit for executing the processing operations of multiple microthreads, where each microthread operates in a corresponding execution context that defines the architectural state, A decoder circuit that generates a first microthread for a first block of instructions in response to a first occurrence of a detach instruction, and generates a second microthread for a second block of instructions in response to a second occurrence of the detach instruction, A non-temporary computer-readable medium in which the second block of the instruction includes data dependencies relating to resources accessed in the first block of the instruction.

17. A data processing device, An input circuit configured to receive an input code, including a first block of instructions and a second block of instructions, An output circuit configured to generate output code corresponding to the first block and the second block of the instruction, The system comprises a processing circuit configured to generate the output code based on the input code, The aforementioned processing circuit is A first hint instruction configured to indicate resource availability within the output code corresponding to the first block of instruction, and It is configured to generate a second hint instruction in the output code corresponding to the second block of the instruction, which is configured to indicate the resource requirements, and A data processing device in which the second block of an instruction includes data dependencies relating to resources accessed in the first block of the instruction.

18. The data processing apparatus according to claim 17, wherein the data dependency is a read-after-write data dependency according to the resource.

19. The first block of the instruction and the second block of the instruction are iterations of the same loop. The data processing apparatus according to claim 17 or 18, wherein the data dependency extends over the iterations of the loop.

20. The processing circuit is configured to place the second hint instruction before or during the first use of the resource in the body of the loop. The data processing device according to claim 19, wherein the processing circuit is configured to place the first hint instruction at the time of the final use of the resource in the main body of the loop, or after the final use.

21. The data processing device according to claim 20, wherein the processing circuit is configured to arrange the second hint instruction and the first hint instruction such that at least a portion of the body of the loop lies outside the region defined between the first hint instruction and the second hint instruction.

22. It is a method, Receiving an input code including a first block of instructions and a second block of instructions, To create output code corresponding to the first block and the second block of the instruction, This includes generating the output code based on the input code, The aforementioned output code is, A first hint instruction configured to indicate resource availability within the output code corresponding to the first block of instruction, and The output code corresponding to the second block of instructions includes a second hint instruction configured to indicate the resource requirements, and A method wherein the second block of the instruction includes data dependencies relating to resources accessed in the first block of the instruction.

23. A non-temporary computer-readable medium for storing computer-readable code for the manufacture of a data processing device, wherein the data processing device is An input circuit configured to receive an input code, including a first block of instructions and a second block of instructions, An output circuit configured to generate output code corresponding to the first block and the second block of the instruction, The processing circuit includes a processing circuit configured to generate the output code based on the input code, The aforementioned processing circuit is A first hint instruction configured to indicate resource availability within the output code corresponding to the first block of instruction, and It is configured to generate a second hint instruction in the output code corresponding to the second block of the instruction, which is configured to indicate the resource requirements, and A non-temporary computer-readable medium in which the second block of the instruction includes data dependencies relating to resources accessed in the first block of the instruction.