Breaking the Norm with a RISC-V Chip

(Source: chipsandcheese)Condor Computing is a subsidiary of Andes Technology, dedicated to developing licensable RISC-V cores, with a business model similar to that of Arm and SiFive. Andes Technology established Condor in 2023, making it relatively young in the RISC-V field. However, Andes Technology had RISC-V design experience prior to the establishment of Condor and has developed several RISC-V cores over the past few years.Condor will showcase its Cuzco core at Hot Chips 2025. This core is a heavyweight product in the RISC-V domain, featuring extensive out-of-order execution capabilities, advanced branch predictors, and some new time-based techniques. It is on par with high-performance RISC-V designs such as SiFive’s P870 and Veyron’s V1. Like these cores, Cuzco is expected to outperform currently silicon-implemented RISC-V cores, such as Alibaba’s T-HEAD C910 and SiFive’s P550.Breaking the Norm with a RISC-V ChipIn addition to employing a wide out-of-order design, Cuzco primarily uses static scheduling in the backend to save power and reduce complexity. Condor refers to this as a “time-based” scheduling scheme. I will elaborate on this later, but it is important to note that this is purely an implementation detail. It does not require modifications to the ISA or compiler for special handling to achieve optimal performance.Core OverviewCuzco is an 8-wide out-of-order core with 256 ROB entries, targeting a clock speed of approximately 2 GHz SS (slow-slow) to 2.5 GHz (typical-typical) on TSMC’s 5nm process. The pipeline consists of 12 stages from instruction fetch to data cache access completion. However, a 10-cycle misprediction penalty may more accurately describe the pipeline length of this core relative to its competitors.Breaking the Norm with a RISC-V ChipAs a licensable core, Cuzco is designed for high configurability to expand its target market. The core consists of a variable number of execution slices. Customization options also include L2 TLB size, off-cluster bus width, and L2/L3 capacity. Condor can also adjust the sizes of various internal core structures to meet customer performance requirements. The Cuzco core is arranged in clusters, accommodating up to 8 cores. Clusters connect to the system via the CHI bus, allowing customers to implement their own on-chip network (NoC) for higher core counts through multi-cluster setups.Breaking the Norm with a RISC-V ChipFrontendThe frontend of Cuzco begins with a complex branch predictor, which is typical for modern cores targeting any reasonable performance level. Conditional branches are handled by a TAGE-SC-L predictor. TAGE stands for “Tag Geometry,” a technique that uses multiple tables to handle different history lengths. It aims to efficiently utilize the storage space of the branch predictor by selecting the most suitable history length for each branch, contrasting with older techniques that use fixed history lengths. The SC (Statistical Corrector) part is responsible for handling a small subset of branches where TAGE does not perform well; it can reverse predictions if TAGE frequently mispredicts in certain cases. Finally, L refers to the loop predictor, which is simply a set of counters that count branches that have executed a certain number of times but have not executed once. If the branch predictor detects this looping behavior, the loop predictor can avoid mispredictions in the last iteration of the loop. Essentially, TAGE-SC-L is an enhanced version of the basic TAGE predictor.AMD’s Zen 2, Ampere’s AmpereOne, and Qualcomm’s Oryon also utilize some form of TAGE predictor and achieve excellent branch prediction accuracy. AMD, Ampere, and Qualcomm may also have enhanced the basic TAGE prediction strategy in some way. The performance of Cuzco’s TAGE predictor depends on the size of its history tables and the tuning of the predictor (selection of index bits versus tag bits, history lengths, allocation of storage budgets between TAGE tables, etc.). For Cuzco, they disclosed that the foundational components of the TAGE predictor use a 16K bimodal counter entry table.Breaking the Norm with a RISC-V ChipThe branch target cache on Cuzco is provided by an 8K entry branch target buffer (BTB) divided into two levels. Condor’s slides show that BTB hits/misses occur within cycles after instruction cache access begins, so executed branch instructions are likely to create a pipeline bubble. Return values are predicted using a 32-entry return stack. Cuzco also features an indirect branch predictor, which is common in modern CPUs.The instruction fetch logic of Cuzco is fed by a 64 KB 8-way set associative instruction cache and accelerated address translation through a 64-entry fully associative TLB. The instruction fetch stage pulls the entire 64B cache line into the ICQ (Instruction Cache Queue), from which instructions are pulled into the instruction queue (XIQ). The decoder is fed by the XIQ, capable of processing up to 8 instructions per cycle.Renaming and AllocationMost operations demonstrated by Condor relate to the renaming and allocation stage, which serves as a bridge between the frontend and the out-of-order backend. In most out-of-order cores, the renamer performs register renaming and allocates resources in the backend. The backend then dynamically schedules instructions when their dependencies are available. Cuzco’s renamer goes a step further by predicting instruction scheduling.Breaking the Norm with a RISC-V ChipSimilarly, Nvidia’s static scheduling in Kepler and subsequent GPU architectures simplifies scheduling by informing instructions of their future execution over a certain number of cycles, rather than allowing hardware to dynamically check dependencies. However, since GPU ISAs have not been standardized, Nvidia performs this in its compiler. Cuzco still uses hardware to create dynamic scheduling but shifts this task to the renaming/allocation stage instead of the backend scheduler. In traditional out-of-order CPUs, the scheduler can be an expensive structure as it must check every cycle whether instructions are ready to execute. On Cuzco, the backend scheduler only needs to wait a specified number of cycles before issuing an instruction, knowing that dependencies will be ready by then.Breaking the Norm with a RISC-V ChipTo execute time-based scheduling, Cuzco maintains a Time Resource Matrix (TRM) that tracks the utilization of various resources (such as execution ports, functional units, and data buses) over a specified number of future cycles. The TRM can predict up to 256 cycles ahead, controlling storage requirements. Since searching a 256-row matrix in hardware is extremely costly, Cuzco only looks for available resources in a small window after the dependencies of the predicted instruction are ready. Condor found that searching an eight-cycle window is a good trade-off. Since the renamer can handle up to eight instructions, it must access 64 rows in the TRM each cycle at most. If the renamer cannot find available resources in the search window, the instruction will stall at the ID2 stage.Another potential limitation is the size of the TRM, which may limit long-latency instructions. However, the longest-latency instructions are often cache-miss load instructions. Cuzco always assumes TRM scheduling has L1D hits and uses replay to handle L1D misses. This means that stalls at ID2 due to TRM size limitations should also be rare.Breaking the Norm with a RISC-V ChipCompared to the hypothetical “greedy” setup, in this setup, the core can create perfect scheduling while considering execution resource limitations, while limiting the TRM search window leads to a few percentage points of performance loss. Condor points out that creating a core capable of achieving “greedy” levels may even be impossible. Traditional out-of-order cores are not subject to TRM-related limitations but may struggle to create optimal scheduling for other reasons. For example, distributed schedulers may prepare multiple micro-operations in one scheduling queue, even when there may be idle execution units in other scheduling queues, facing “false” latencies.Breaking the Norm with a RISC-V ChipStatic scheduling is only effective when instruction latencies are known in advance. Certain instructions have variable latencies, such as those that may miss caches or TLBs, encounter storage conflicts, or require store forwarding for load instructions. As mentioned earlier, Cuzco uses instruction replay to handle variable-latency instructions and their associated dynamic behaviors. The renamer does take some measures to reduce replay, such as checking whether load instructions obtain addresses from the same register as previous store instructions. However, it does not attempt to predict memory dependencies like Intel’s Core 2 nor does it try to predict whether load instructions will miss caches.Out-of-order BackendOut-of-order execution in Cuzco is relatively straightforward since the renaming/allocation stage determines the execution timing of instructions. Each instruction only needs to be held in the scheduler until a specified number of cycles have passed before being sent for execution. If the renaming/allocation stage guesses incorrectly, it will replay through a “poison” bit. The result data of incorrectly executed instructions is marked as “poison,” and any instructions using that data will be re-executed. Replay instructions consume power and waste execution throughput, so ideally, replay should occur infrequently. A replay rate of 70.07 times per 1000 instructions seems a bit high, but it may not be a significant issue since execution resources are rarely a limiting factor for out-of-order cores. Considering that most modern chips rarely utilize their core widths continuously, occupying about 7% more execution resources may be an acceptable trade-off.Breaking the Norm with a RISC-V ChipExecution resources are grouped into multiple slices, each with a pair of pipelines. A slice can execute all RISC-V instructions supported by the core, so execution resources can be easily scaled by changing the number of slices. Each slice consists of a set of execution queues (XEQ) that hold micro-operations waiting for functional units. Each functional unit in Cuzco has its own XEQ, which differs from traditional designs that typically have a scheduling queue providing data for all functional units connected to execution ports. Four register read ports provide operands to the slices, while two write ports handle result write-backs. Bus conflicts are also managed by the TRM. A slice cannot execute more than two micro-operations per cycle, even if doing so would not oversubscribe the register read ports. For example, a slice cannot issue an integer addition, branch, and load in the same cycle, even if this only requires four register inputs.The size of the XEQ can be adjusted based on workload characteristics, similar to adjusting distributed schedulers. While the size of the XEQ can be set according to customer needs, Condor provides data for some benchmark configurations. The ALU has 16 entry queues, while the branch and load/store units (LS) have 8 entry queues. The size of the XEQ can be adjusted in powers of 2, ranging from 2 to 32 entries. Inter-slice forwarding typically has only a one-cycle latency. The core can be configured for zero-cycle inter-slice forwarding, but this would be very challenging.In terms of vectors, Cuzco supports 256/512-bit VLEN through multiple micro-operations distributed across various execution slices. The native width of the execution units is 64 bits. Each slice has one FMA unit, resulting in a peak throughput of 8 FMA operations per cycle for FP32, or 16 FLOPS when counting additions and multiplications separately. The execution latency for FP addition is 2 cycles, while the latency for FP multiplication and FMA is 4 cycles. The two-cycle FP addition latency is impressive, comparable to the latest cores like Neoverse N1 and Intel Golden Cove, despite being at a much lower clock frequency.Load/StoreThe load/store unit of Cuzco includes a 64-entry load queue, a 64-entry store queue, and a 64-entry data cache miss queue. After accessing the data cache, load operations may leave the load queue, potentially leading to behavior similar to AMD’s Zen series processors. In the Zen series processors, the number of pending load operations in the out-of-order backend can far exceed the officially stated capacity of the load queue. The core adopts a four-slice configuration, with four load/store pipelines, or one pipeline per slice configuration. The maximum load bandwidth is 64B/cycle, which can be achieved through vector loads.Breaking the Norm with a RISC-V ChipL1D employs a Physical Index and Physical Tag (PIPT) mechanism, so address translation must be completed before L1D access. To speed up address translation, Cuzco is equipped with a fully associative data TLB containing 64 entries. The L2 TLB uses a 4-way set associative mechanism and can contain 1K, 2K, or 4K entries. Cuzco’s core-private unified L2 cache also has configurable capacity. For example, on TSMC’s 5nm process, a 2MB L2 occupies 1.04 square millimeters of area.Breaking the Norm with a RISC-V ChipEach cluster’s eight cores share an L3 cache, which is split into multiple slices to handle bandwidth demands from multiple cores. Each slice can provide 64B/cycle of bandwidth, with the number of slices matching the number of cores. Thus, Cuzco enjoys 64B/cycle load bandwidth across the entire cache hierarchy, although L3 bandwidth may decrease if accesses from different cores conflict with the same slice. The cores within a cluster and the L3 slices are connected via crossbar switches. The L3 cache can operate at the core clock frequency. System requests are issued through a 64B/cycle CHI interface. The system topology outside the cluster is determined by the implementer.Breaking the Norm with a RISC-V ChipCache miss replay is achieved by rescheduling data consumers to a later time when the expected data is ready. Therefore, an L3 hit results in the consumer instruction executing three times: once for the predicted L1D hit, once for the predicted L2 hit, and finally for the correct data L3 hit.Final ThoughtsHigh-performance CPU design has gradually stabilized over the past few decades, ultimately converging on a single out-of-order execution model. Undeniably, out-of-order execution is very challenging. Over the years, many alternatives have been attempted but have failed to endure. Intel’s Itanium processor tried to use an ISA-based approach but failed to replace the company’s own out-of-order x86 cores. Nvidia’s Denver processor attempted to dynamically compile ARM instructions into microcode packets, but this approach did not persist. Today, all successful high-performance designs typically use the same out-of-order execution strategy, despite many variations. This is driven by the requirements of ISA compatibility and the need to provide high single-thread performance across a wide range of applications. Breaking the norm is clearly fraught with danger.Condor seeks to break the norm, but its breakthrough lies in its deep core, which is invisible to software from a functional perspective and nearly invisible from a performance perspective. The Condor core runs RISC-V instructions, benefiting from the software ecosystem unlike Itanium. It does not rely on a compiled microcode cache like Denver, so its performance does not degrade as much as typical OoO cores when dealing with poorly localized code. Finally, instruction replay effectively creates dynamic scheduling and handles cache misses.

Leave a Comment