/ coreblocks / interface / layouts.py
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