layouts.py
1 from amaranth import signed 2 from amaranth.lib.data import ArrayLayout 3 from amaranth.lib.enum import IntFlag, auto 4 from coreblocks.params import GenParams 5 from coreblocks.arch import * 6 from transactron.utils import LayoutList, LayoutListField, layout_subset 7 from transactron.utils.transactron_helpers import make_layout, extend_layout 8 9 __all__ = [ 10 "CommonLayoutFields", 11 "AddressTranslationLayouts", 12 "SchedulerLayouts", 13 "ROBLayouts", 14 "FetchLayouts", 15 "DecodeLayouts", 16 "FuncUnitLayouts", 17 "RSInterfaceLayouts", 18 "RetirementLayouts", 19 "RSLayouts", 20 "RFLayouts", 21 "UnsignedMulUnitLayouts", 22 "RATLayouts", 23 "LSULayouts", 24 "CSRRegisterLayouts", 25 "CSRUnitLayouts", 26 "ICacheLayouts", 27 "JumpBranchLayouts", 28 "PrivUnitLayouts", 29 ] 30 31 32 class CommonLayoutFields: 33 """Commonly used layout fields.""" 34 35 def __init__(self, gen_params: GenParams): 36 self.op_type: LayoutListField = ("op_type", OpType) 37 """Decoded operation type.""" 38 39 self.funct3: LayoutListField = ("funct3", Funct3) 40 """RISC V funct3 value.""" 41 42 self.funct7: LayoutListField = ("funct7", Funct7) 43 """RISC V funct7 value.""" 44 45 self.rl_s1: LayoutListField = ("rl_s1", gen_params.isa.reg_cnt_log) 46 """Logical register number of first source operand.""" 47 48 self.rl_s2: LayoutListField = ("rl_s2", gen_params.isa.reg_cnt_log) 49 """Logical register number of second source operand.""" 50 51 self.rl_dst: LayoutListField = ("rl_dst", gen_params.isa.reg_cnt_log) 52 """Logical register number of destination operand.""" 53 54 self.rp_s1: LayoutListField = ("rp_s1", gen_params.phys_regs_bits) 55 """Physical register number of first source operand.""" 56 57 self.rp_s2: LayoutListField = ("rp_s2", gen_params.phys_regs_bits) 58 """Physical register number of second source operand.""" 59 60 self.rp_dst: LayoutListField = ("rp_dst", gen_params.phys_regs_bits) 61 """Physical register number of destination operand.""" 62 63 self.imm: LayoutListField = ("imm", gen_params.isa.xlen) 64 """Immediate value.""" 65 66 self.csr: LayoutListField = ("csr", gen_params.isa.csr_alen) 67 """CSR number.""" 68 69 self.pc: LayoutListField = ("pc", gen_params.isa.xlen) 70 """Program counter value.""" 71 72 self.rob_id: LayoutListField = ("rob_id", gen_params.rob_entries_bits) 73 """Reorder buffer entry identifier.""" 74 75 self.fb_addr: LayoutListField = ("fb_addr", gen_params.isa.xlen - gen_params.fetch_block_bytes_log) 76 """Address of a fetch block""" 77 78 self.fb_instr_idx: LayoutListField = ("fb_instr_idx", gen_params.fetch_width_log) 79 """Offset of an instruction (counted in number of instructions) in a fetch block""" 80 81 self.s1_val: LayoutListField = ("s1_val", gen_params.isa.xlen) 82 """Value of first source operand.""" 83 84 self.s2_val: LayoutListField = ("s2_val", gen_params.isa.xlen) 85 """Value of second source operand.""" 86 87 self.reg_val: LayoutListField = ("reg_val", gen_params.isa.xlen) 88 """Value of some physical register.""" 89 90 self.addr: LayoutListField = ("addr", gen_params.isa.xlen) 91 """Memory address.""" 92 93 self.vaddr: LayoutListField = ("vaddr", gen_params.isa.xlen) 94 """Memory address - used when both virtual and physical addresses are present.""" 95 96 self.paddr: LayoutListField = ("paddr", gen_params.phys_addr_bits) 97 """Physical memory address.""" 98 99 self.data: LayoutListField = ("data", gen_params.isa.xlen) 100 """Piece of data.""" 101 102 self.instr: LayoutListField = ("instr", gen_params.isa.ilen) 103 """RISC V instruction.""" 104 105 self.exec_fn_layout = make_layout(self.op_type, self.funct3, self.funct7) 106 """Decoded instruction, in layout form.""" 107 108 self.exec_fn: LayoutListField = ("exec_fn", self.exec_fn_layout) 109 """Decoded instruction.""" 110 111 self.regs_l: LayoutListField = ("regs_l", [self.rl_s1, self.rl_s2, self.rl_dst]) 112 """Logical register numbers - as described in the RISC V manual. They index the RATs.""" 113 114 self.regs_p: LayoutListField = ("regs_p", [self.rp_s1, self.rp_s2, self.rp_dst]) 115 """Physical register numbers. They index the register file.""" 116 117 self.reg_id: LayoutListField = ("reg_id", gen_params.phys_regs_bits) 118 """Physical register ID.""" 119 120 self.exception: LayoutListField = ("exception", 1) 121 """Exception is raised for this instruction.""" 122 123 self.cause: LayoutListField = ("cause", ExceptionCause) 124 """Exception cause.""" 125 126 self.error: LayoutListField = ("error", 1) 127 """Request ended with an error.""" 128 129 self.side_fx: LayoutListField = ("side_fx", 1) 130 """Side effects are enabled.""" 131 132 self.rvc: LayoutListField = ("rvc", 1) 133 """Instruction is a compressed (two-byte) one.""" 134 135 self.predicted_taken: LayoutListField = ("predicted_taken", 1) 136 """If the branch was predicted taken.""" 137 138 self.cfi_idx: LayoutListField = ("cfi_idx", gen_params.fetch_width_log) 139 """An index of a CFI instruction in a fetch block.""" 140 141 self.cfi_target: LayoutListField = ("cfi_target", gen_params.isa.xlen) 142 """Target of a CFI instruction.""" 143 144 self.cfi_type: LayoutListField = ("cfi_type", CfiType) 145 """Type of a CFI instruction""" 146 147 self.branch_mask: LayoutListField = ("branch_mask", gen_params.fetch_width) 148 """A mask denoting which instruction in a fetch blocks is a branch.""" 149 150 self.tag: LayoutListField = ("tag", gen_params.tag_bits) 151 """Instruction tag. Identifies speculation path of the instruction.""" 152 153 self.rollback_tag: LayoutListField = ("rollback_tag", gen_params.tag_bits) 154 """Target tag of last rollback that happened before instruction. 155 For tracking rollbacks in scheduler/CRAT only.""" 156 157 self.rollback_tag_v: LayoutListField = ("rollback_tag_v", 1) 158 """Valid bit for `rollback_tag`. 159 It is set only for first instruction that exits fetch after rollback to `rollback_tag`.""" 160 161 self.tag_increment: LayoutListField = ("tag_increment", 1) 162 """Compressed tag representation used in ROB. 163 Instruction with this bit set has tag of previous instruction incremented by one.""" 164 165 self.commit_checkpoint: LayoutListField = ("commit_checkpoint", 1) 166 """New checkpoint should be made for this instruction""" 167 168 169 class AddressTranslationLayouts: 170 """Layouts used by virtual-to-physical address translation methods.""" 171 172 def __init__(self, gen_params: GenParams): 173 fields = gen_params.get(CommonLayoutFields) 174 175 self.request = make_layout(fields.addr) 176 177 self.accept = make_layout( 178 fields.vaddr, 179 fields.paddr, 180 ("page_fault", 1), 181 ("access_fault", 1), 182 ) 183 184 185 class SchedulerLayouts: 186 """Layouts used in the scheduler.""" 187 188 def __init__(self, gen_params: GenParams): 189 fields = gen_params.get(CommonLayoutFields) 190 191 self.rs_selected: LayoutListField = ("rs_selected", gen_params.rs_number_bits) 192 """Reservation Station number for the instruction.""" 193 194 self.rs_entry_id: LayoutListField = ("rs_entry_id", gen_params.max_rs_entries_bits) 195 """Reservation station entry ID for the instruction.""" 196 197 self.regs_p_alloc_out: LayoutListField = ("regs_p", [fields.rp_dst]) 198 """Physical register number for the destination operand, after allocation.""" 199 200 self.regs_l_rob_in: LayoutListField = ( 201 "regs_l", 202 [ 203 fields.rl_dst, 204 ("rl_dst_v", 1), 205 ], 206 ) 207 """Logical register number for the destination operand, before ROB allocation.""" 208 209 self.reg_alloc_in_data = make_layout( 210 fields.exec_fn, 211 fields.regs_l, 212 fields.imm, 213 fields.csr, 214 fields.pc, 215 fields.rollback_tag, 216 fields.rollback_tag_v, 217 fields.commit_checkpoint, 218 ) 219 220 self.reg_alloc_in = self.scheduler_in = make_layout( 221 ("count", range(gen_params.frontend_superscalarity + 1)), 222 ("data", ArrayLayout(self.reg_alloc_in_data, gen_params.frontend_superscalarity)), 223 ) 224 225 self.instr_tag_in_data = make_layout( 226 fields.exec_fn, 227 fields.regs_l, 228 self.regs_p_alloc_out, 229 fields.imm, 230 fields.csr, 231 fields.pc, 232 fields.rollback_tag, 233 fields.rollback_tag_v, 234 fields.commit_checkpoint, 235 ) 236 237 self.reg_alloc_out = self.instr_tag_in = make_layout( 238 ("count", range(gen_params.frontend_superscalarity + 1)), 239 ("data", ArrayLayout(self.instr_tag_in_data, gen_params.frontend_superscalarity)), 240 ) 241 242 self.renaming_in_data = make_layout( 243 fields.exec_fn, 244 fields.regs_l, 245 self.regs_p_alloc_out, 246 fields.imm, 247 fields.csr, 248 fields.pc, 249 fields.tag, 250 fields.tag_increment, 251 fields.commit_checkpoint, 252 ) 253 254 self.renaming_in = self.instr_tag_out = make_layout( 255 ("count", range(gen_params.frontend_superscalarity + 1)), 256 ("data", ArrayLayout(self.renaming_in_data, gen_params.frontend_superscalarity)), 257 ) 258 259 self.rob_allocate_in_data = make_layout( 260 fields.exec_fn, 261 self.regs_l_rob_in, 262 fields.regs_p, 263 fields.imm, 264 fields.csr, 265 fields.pc, 266 fields.tag, 267 fields.tag_increment, 268 ) 269 270 self.renaming_out = self.rob_allocate_in = make_layout( 271 ("count", range(gen_params.frontend_superscalarity + 1)), 272 ("data", ArrayLayout(self.rob_allocate_in_data, gen_params.frontend_superscalarity)), 273 ) 274 275 self.rs_select_in_data = make_layout( 276 fields.exec_fn, 277 fields.regs_p, 278 fields.rob_id, 279 fields.imm, 280 fields.csr, 281 fields.pc, 282 fields.tag, 283 ) 284 285 self.rob_allocate_out = self.rs_select_in = make_layout( 286 ("count", range(gen_params.frontend_superscalarity + 1)), 287 ("data", ArrayLayout(self.rs_select_in_data, gen_params.frontend_superscalarity)), 288 ) 289 290 self.rs_insert_in_data = make_layout( 291 fields.exec_fn, 292 fields.regs_p, 293 fields.rob_id, 294 self.rs_selected, 295 self.rs_entry_id, 296 fields.imm, 297 fields.csr, 298 fields.pc, 299 fields.tag, 300 ) 301 302 self.rs_insert_in = self.rs_select_out = make_layout( 303 ("count", range(gen_params.frontend_superscalarity + 1)), 304 ("data", ArrayLayout(self.rs_insert_in_data, gen_params.frontend_superscalarity)), 305 ) 306 307 self.free_rf_layout = make_layout(("ident", gen_params.phys_regs_bits)) 308 309 310 class RFLayouts: 311 """Layouts used in the register file.""" 312 313 def __init__(self, gen_params: GenParams): 314 fields = gen_params.get(CommonLayoutFields) 315 316 self.valid: LayoutListField = ("valid", 1) 317 """Physical register was assigned a value.""" 318 319 self.rf_read_in = make_layout(fields.reg_id) 320 self.rf_free = make_layout(fields.reg_id) 321 self.rf_read_out = make_layout(fields.reg_val, self.valid) 322 self.rf_write = make_layout(fields.reg_id, fields.reg_val) 323 324 325 class RATLayouts: 326 """Layouts used in the register alias tables.""" 327 328 def __init__(self, gen_params: GenParams): 329 fields = gen_params.get(CommonLayoutFields) 330 331 self.old_rp_dst: LayoutListField = ("old_rp_dst", gen_params.phys_regs_bits) 332 """Physical register previously associated with the given logical register in RRAT.""" 333 334 self.active_tags_bitmask: LayoutListField = ("active_tags", ArrayLayout(1, 2**gen_params.tag_bits)) 335 """Bitmask, when bit is set when corresponding tag is on the current speculation/execution 336 path and reset when instruction was already rolled back (is not included in current FRAT)""" 337 338 self.active_rename_layout = make_layout(("valid", 1), fields.rl_dst, fields.rp_dst) 339 340 self.frat_rename_in = make_layout( 341 fields.rl_s1, 342 fields.rl_s2, 343 fields.rl_dst, 344 fields.rp_dst, 345 ) 346 self.frat_rename_out = make_layout(fields.rp_s1, fields.rp_s2) 347 348 self.rrat_commit_in = make_layout(fields.rl_dst, fields.rp_dst) 349 self.rrat_commit_out = make_layout(self.old_rp_dst) 350 351 self.rrat_peek_in = make_layout(fields.rl_dst) 352 self.rrat_peek_out = self.rrat_commit_out 353 354 self.rollback_in = make_layout(fields.tag) 355 self.get_active_tags_out = make_layout(self.active_tags_bitmask) 356 357 self.crat_commit_checkpoint_in = make_layout(fields.tag, fields.commit_checkpoint) 358 359 self.crat_rename_in = self.frat_rename_in 360 self.crat_rename_out = self.frat_rename_out 361 362 self.crat_tag_in = (fields.rollback_tag, fields.rollback_tag_v, fields.commit_checkpoint) 363 self.crat_tag_out = make_layout(fields.tag, fields.tag_increment, fields.commit_checkpoint) 364 365 self.crat_flush_restore = make_layout(fields.rl_dst, fields.rp_dst) 366 367 368 class ROBLayouts: 369 """Layouts used in the reorder buffer.""" 370 371 def __init__(self, gen_params: GenParams): 372 fields = gen_params.get(CommonLayoutFields) 373 374 self.data_layout = make_layout( 375 fields.rl_dst, 376 fields.rp_dst, 377 fields.tag_increment, 378 ) 379 380 self.rob_data: LayoutListField = ("rob_data", self.data_layout) 381 """Data stored in a reorder buffer entry.""" 382 383 self.done: LayoutListField = ("done", 1) 384 """Instruction has executed, but is not committed yet.""" 385 386 self.start: LayoutListField = ("start", gen_params.rob_entries_bits) 387 """Index of the first (the earliest) entry in the reorder buffer.""" 388 389 self.end: LayoutListField = ("end", gen_params.rob_entries_bits) 390 """Index of the entry following the last (the latest) entry in the reorder buffer.""" 391 392 self.put_count: LayoutListField = ("count", range(gen_params.frontend_superscalarity + 1)) 393 """Number of ROB entries to put into ROB.""" 394 395 self.retire_count: LayoutListField = ("count", range(gen_params.retirement_superscalarity + 1)) 396 """Number of ROB entries to retire.""" 397 398 self.peek_data = make_layout( 399 self.rob_data, 400 fields.rob_id, 401 fields.exception, 402 ) 403 404 self.id_layout = make_layout(fields.rob_id) 405 406 self.retire_layout = make_layout(self.retire_count) 407 408 self.mark_done_layout = make_layout( 409 fields.rob_id, 410 fields.exception, 411 ) 412 413 self.peek_layout = make_layout( 414 self.retire_count, ("entries", ArrayLayout(self.peek_data, gen_params.retirement_superscalarity)) 415 ) 416 417 self.put_layout = make_layout( 418 self.put_count, ("entries", ArrayLayout(self.data_layout, gen_params.frontend_superscalarity)) 419 ) 420 421 self.put_out_layout = make_layout(("entries", ArrayLayout(self.id_layout, gen_params.frontend_superscalarity))) 422 423 self.get_indices = make_layout(self.start, self.end) 424 425 426 class RSLayoutFields: 427 """Layout fields used in the reservation station.""" 428 429 def __init__(self, gen_params: GenParams, *, rs_entries: int, data_fields: set[str]): 430 full_data = gen_params.get(RSFullDataLayout) 431 432 self.data_layout = layout_subset(full_data.data_layout, fields=data_fields) 433 434 self.rs_data: LayoutListField = ("rs_data", self.data_layout) 435 """Data about an instruction stored in a reservation station (RS).""" 436 437 self.rs_entry_id: LayoutListField = ("rs_entry_id", range(rs_entries)) 438 """Index in a reservation station (RS).""" 439 440 441 class RSFullDataLayout: 442 """Full data layout for functional blocks. Blocks can use a subset.""" 443 444 def __init__(self, gen_params: GenParams): 445 fields = gen_params.get(CommonLayoutFields) 446 447 self.data_layout = make_layout( 448 fields.rp_s1, 449 fields.rp_s2, 450 ("rp_s1_reg", gen_params.phys_regs_bits), 451 ("rp_s2_reg", gen_params.phys_regs_bits), 452 fields.rp_dst, 453 fields.rob_id, 454 fields.exec_fn, 455 fields.s1_val, 456 fields.s2_val, 457 fields.imm, 458 fields.csr, 459 fields.pc, 460 fields.tag, 461 ) 462 463 464 class RSInterfaceLayouts: 465 """Layouts used in functional blocks.""" 466 467 def __init__(self, gen_params: GenParams, *, rs_entries: int, data_fields: set[str]): 468 fields = gen_params.get(CommonLayoutFields) 469 rs_fields = gen_params.get(RSLayoutFields, rs_entries=rs_entries, data_fields=data_fields) 470 471 self.data_layout = rs_fields.data_layout 472 473 self.select_out = make_layout(rs_fields.rs_entry_id) 474 475 self.insert_in = make_layout(rs_fields.rs_data, rs_fields.rs_entry_id) 476 477 self.update_in = make_layout(fields.reg_id, fields.reg_val) 478 479 480 class RetirementLayouts: 481 """Layouts used in the retirement module.""" 482 483 def __init__(self, gen_params: GenParams): 484 fields = gen_params.get(CommonLayoutFields) 485 486 self.precommit_in = make_layout(fields.rob_id) 487 488 self.precommit_out = make_layout(fields.side_fx) 489 490 self.flushing = ("flushing", 1) 491 """ Core is currently flushed """ 492 493 self.core_state: LayoutList = [self.flushing] 494 495 496 class RSLayouts: 497 """Layouts used in the reservation station.""" 498 499 def __init__(self, gen_params: GenParams, *, rs_entries: int): 500 data_fields = { 501 "rp_s1", 502 "rp_s2", 503 "rp_dst", 504 "rob_id", 505 "exec_fn", 506 "s1_val", 507 "s2_val", 508 "imm", 509 "pc", 510 "tag", 511 } 512 513 self.rs = gen_params.get(RSInterfaceLayouts, rs_entries=rs_entries, data_fields=data_fields) 514 rs_fields = gen_params.get(RSLayoutFields, rs_entries=rs_entries, data_fields=data_fields) 515 516 self.ready_list: LayoutListField = ("ready_list", rs_entries) 517 """Bitmask of reservation station entries containing instructions which are ready to run.""" 518 519 self.take_in = make_layout(rs_fields.rs_entry_id) 520 521 self.take_out = layout_subset( 522 self.rs.data_layout, 523 fields={ 524 "s1_val", 525 "s2_val", 526 "rp_dst", 527 "rob_id", 528 "exec_fn", 529 "imm", 530 "pc", 531 "tag", 532 }, 533 ) 534 535 self.get_ready_list_out = make_layout(self.ready_list) 536 537 538 class ICacheLayouts: 539 """Layouts used in the instruction cache.""" 540 541 def __init__(self, gen_params: GenParams): 542 fields = gen_params.get(CommonLayoutFields) 543 544 self.last: LayoutListField = ("last", 1) 545 """This is the last cache refill result.""" 546 547 self.fetch_block: LayoutListField = ("fetch_block", gen_params.fetch_block_bytes * 8) 548 """The block of data the fetch unit operates on.""" 549 550 self.issue_req = make_layout(fields.paddr) 551 552 self.accept_res = make_layout( 553 self.fetch_block, 554 fields.error, 555 ) 556 557 self.start_refill = make_layout( 558 fields.paddr, 559 ) 560 561 self.accept_refill = make_layout( 562 fields.paddr, 563 self.fetch_block, 564 fields.error, 565 self.last, 566 ) 567 568 569 class FetchLayouts: 570 """Layouts used in the fetcher.""" 571 572 class FaultFlag(IntFlag): 573 # standard access fault when accessing instruction 574 # from beginning (exception pc = instruction pc) (fault on full instruction or first half) 575 ACCESS_FAULT = auto() 576 # standard page fault when accessing instruction 577 # from beginning (exception pc = instruction pc) (fault on full instruction or first half) 578 PAGE_FAULT = auto() 579 # with C extension (2-byte alignment enabled) fault condition 580 # could only affect second half of 4-byte instruction. 581 # Bit set if this is the case 582 EXCEPTION_ON_SECOND_HALF = auto() 583 584 def __init__(self, gen_params: GenParams): 585 fields = gen_params.get(CommonLayoutFields) 586 587 self.access_fault: LayoutListField = ("access_fault", FetchLayouts.FaultFlag) 588 """Instruction fetch errors. See `FetchLayouts.FaultFlag` fields documentation""" 589 590 self.raw_instr = make_layout( 591 fields.instr, 592 fields.pc, 593 self.access_fault, 594 fields.rvc, 595 fields.predicted_taken, 596 fields.cfi_type, 597 ) 598 599 self.fetch_result = make_layout( 600 ("count", range(gen_params.frontend_superscalarity + 1)), 601 ("data", ArrayLayout(self.raw_instr, gen_params.frontend_superscalarity)), 602 ) 603 604 self.fetch_request = make_layout(fields.pc) 605 self.fetch_writeback = make_layout(("redirect", 1), ("redirect_target", gen_params.isa.xlen)) 606 self.redirect = make_layout(fields.pc) 607 self.resume = make_layout(fields.pc) 608 609 self.predecoded_instr = make_layout(fields.cfi_type, ("cfi_offset", signed(21)), ("unsafe", 1)) 610 611 self.bpu_prediction = make_layout( 612 fields.branch_mask, fields.cfi_idx, fields.cfi_type, fields.cfi_target, ("cfi_target_valid", 1) 613 ) 614 615 self.pred_checker_i = make_layout( 616 fields.fb_addr, 617 ("instr_block_cross", 1), 618 ("instr_valid", gen_params.fetch_width), 619 ("predecoded", ArrayLayout(self.predecoded_instr, gen_params.fetch_width)), 620 ("prediction", self.bpu_prediction), 621 ) 622 623 self.pred_checker_o = make_layout( 624 ("mispredicted", 1), 625 ("stall", 1), 626 fields.fb_instr_idx, 627 ("redirect_target", gen_params.isa.xlen), 628 ) 629 630 631 class DecodeLayouts: 632 """Layouts used in the decoder.""" 633 634 def __init__(self, gen_params: GenParams): 635 fields = gen_params.get(CommonLayoutFields) 636 637 self.decoded_instr = make_layout( 638 fields.exec_fn, 639 fields.regs_l, 640 fields.imm, 641 fields.csr, 642 fields.pc, 643 ) 644 645 self.decode_result = make_layout( 646 ("count", range(gen_params.frontend_superscalarity + 1)), 647 ("data", ArrayLayout(self.decoded_instr, gen_params.frontend_superscalarity)), 648 ) 649 650 # TODO: move tag fields to tagged_decode_result 651 self.tagged_decoded_instr = make_layout( 652 fields.exec_fn, 653 fields.regs_l, 654 fields.imm, 655 fields.csr, 656 fields.pc, 657 fields.rollback_tag, 658 fields.rollback_tag_v, 659 fields.commit_checkpoint, 660 ) 661 662 self.tagged_decode_result = make_layout( 663 ("count", range(gen_params.frontend_superscalarity + 1)), 664 ("data", ArrayLayout(self.tagged_decoded_instr, gen_params.frontend_superscalarity)), 665 ) 666 667 668 class FuncUnitLayouts: 669 """Layouts used in functional units.""" 670 671 def __init__(self, gen_params: GenParams): 672 fields = gen_params.get(CommonLayoutFields) 673 674 self.result: LayoutListField = ("result", gen_params.isa.xlen) 675 """The result value produced in a functional unit.""" 676 677 self.issue = make_layout( 678 fields.s1_val, 679 fields.s2_val, 680 fields.rp_dst, 681 fields.rob_id, 682 fields.exec_fn, 683 fields.imm, 684 fields.pc, 685 fields.tag, 686 ) 687 688 self.push_result = make_layout( 689 fields.rob_id, 690 self.result, 691 fields.rp_dst, 692 fields.exception, 693 ) 694 695 696 class UnsignedMulUnitLayouts: 697 def __init__(self, gen_params: GenParams): 698 self.issue = make_layout( 699 ("i1", gen_params.isa.xlen), 700 ("i2", gen_params.isa.xlen), 701 ) 702 703 self.accept = make_layout( 704 ("o", 2 * gen_params.isa.xlen), 705 ) 706 707 708 class DivUnitLayouts: 709 def __init__(self, gen_params: GenParams): 710 self.issue = make_layout( 711 ("dividend", gen_params.isa.xlen), 712 ("divisor", gen_params.isa.xlen), 713 ) 714 715 self.accept = make_layout( 716 ("quotient", gen_params.isa.xlen), 717 ("remainder", gen_params.isa.xlen), 718 ) 719 720 721 class JumpBranchLayouts: 722 def __init__(self, gen_params: GenParams): 723 fields = gen_params.get(CommonLayoutFields) 724 725 self.predicted_jump_target_req = make_layout() 726 self.predicted_jump_target_resp = make_layout(fields.cfi_target, ("valid", 1)) 727 728 self.verify_branch = make_layout( 729 ("from_pc", gen_params.isa.xlen), ("next_pc", gen_params.isa.xlen), ("misprediction", 1) 730 ) 731 """ Hint for Branch Predictor about branch result """ 732 733 self.funct7_info = make_layout( 734 fields.rvc, 735 fields.predicted_taken, 736 ) 737 """Information passed from the frontend to the jumpbranch unit. Encoded in the funct7 field.""" 738 739 740 class LSULayouts: 741 """Layouts used in the load-store unit.""" 742 743 def __init__(self, gen_params: GenParams): 744 fields = gen_params.get(CommonLayoutFields) 745 746 self.store: LayoutListField = ("store", 1) 747 748 self.issue = make_layout(fields.paddr, fields.vaddr, fields.data, fields.funct3, self.store) 749 750 self.issue_out = make_layout(fields.exception, fields.cause) 751 752 self.accept = make_layout(fields.data, fields.exception, fields.cause, fields.addr) 753 754 755 class CSRRegisterLayouts: 756 """Layouts used in the control and status registers.""" 757 758 def __init__(self, gen_params: GenParams, *, data_width: int): 759 self.data: LayoutListField = ("data", data_width) 760 761 self.read = make_layout( 762 self.data, 763 ("read", 1), 764 ("written", 1), 765 ) 766 767 self.write = make_layout(self.data) 768 769 self.fu_read = make_layout(self.data) 770 self.fu_write = make_layout(self.data) 771 self.fu_access_valid_i = make_layout(("priv_mode", PrivilegeLevel)) 772 self.fu_access_valid_o = make_layout(("valid", 1)) 773 774 775 class CSRUnitLayouts: 776 """Layouts used in the control and status functional unit.""" 777 778 def __init__(self, gen_params: GenParams): 779 self.rs_entries = 0 780 781 data_fields = { 782 "rp_s1", 783 "rp_s1_reg", 784 "rp_dst", 785 "rob_id", 786 "exec_fn", 787 "s1_val", 788 "imm", 789 "csr", 790 "pc", 791 "tag", 792 } 793 794 self.rs = gen_params.get(RSInterfaceLayouts, rs_entries=self.rs_entries, data_fields=data_fields) 795 796 self.data_layout = self.rs.data_layout 797 798 self.imm_layout = make_layout( 799 ("imm", 5), 800 ("_1", gen_params.isa.xlen - 5 - 2 * gen_params.isa.reg_cnt_log), 801 ("rd", gen_params.isa.reg_cnt_log), 802 ("rs1", gen_params.isa.reg_cnt_log), 803 ) 804 """Immediate layout used for CSR instructions. 805 Needed for re-encoding the instruction for xtval, when access is illegal. 806 """ 807 assert self.imm_layout.size == gen_params.isa.xlen 808 809 810 class ExceptionRegisterLayouts: 811 """Layouts used in the exception information register.""" 812 813 def __init__(self, gen_params: GenParams): 814 fields = gen_params.get(CommonLayoutFields) 815 816 self.mtval: LayoutListField = ("mtval", gen_params.isa.xlen) 817 """ Value to set for mtval CSR register """ 818 819 self.valid: LayoutListField = ("valid", 1) 820 821 self.report = make_layout( 822 fields.cause, 823 fields.rob_id, 824 fields.pc, 825 self.mtval, 826 ) 827 828 self.get = extend_layout(self.report, self.valid) 829 830 831 class InternalInterruptControllerLayouts: 832 def __init__(self, gen_params: GenParams): 833 self.cause: LayoutListField = ("cause", gen_params.isa.xlen) 834 """ Async interrupt cause code """ 835 836 self.interrupt_cause = make_layout(self.cause) 837 838 839 class CoreInstructionCounterLayouts: 840 def __init__(self, gen_params: GenParams): 841 self.increment_in = [("count", range(gen_params.frontend_superscalarity + 1))] 842 self.decrement_in = [("count", range(gen_params.retirement_superscalarity + 1))] 843 self.decrement_out = [("empty", 1)] 844 845 846 class PrivUnitLayouts: 847 """Layouts used in the control and status functional unit.""" 848 849 def __init__(self, gen_params: GenParams): 850 self.sfencevma_imm_layout = make_layout( 851 ("_1", gen_params.isa.xlen - 2 * gen_params.isa.reg_cnt_log), 852 ("rs1", gen_params.isa.reg_cnt_log), 853 ("rs2", gen_params.isa.reg_cnt_log), 854 ) 855 """Immediate layout used for SFENCE.VMA instruction. 856 Needed for re-encoding the instruction for xtval, when access is illegal. 857 """ 858 assert self.sfencevma_imm_layout.size == gen_params.isa.xlen