|
33 | 33 | reg2hw_t = gen_rtl.get_iface_tx_type(block, if_name, False) |
34 | 34 | hw2reg_t = gen_rtl.get_iface_tx_type(block, if_name, True) |
35 | 35 |
|
| 36 | + racl_support = block.bus_interfaces.racl_support[if_name] |
| 37 | + |
36 | 38 | win_array_decl = f' [{num_wins}]' if num_wins > 1 else '' |
37 | 39 |
|
38 | 40 | # Calculate whether we're going to need an AW parameter. We use it if there |
|
115 | 117 | %> |
116 | 118 | `include "prim_assert.sv" |
117 | 119 |
|
118 | | -module ${mod_name} ( |
| 120 | +module ${mod_name}${' (' if not racl_support else ''} |
| 121 | +% if racl_support: |
| 122 | + # ( |
| 123 | + parameter bit EnableRacl = 1'b0, |
| 124 | + parameter bit RaclErrorRsp = 1'b1 |
| 125 | + ) ( |
| 126 | +% endif |
119 | 127 | input clk_i, |
120 | 128 | input rst_ni, |
121 | 129 | % if rb.has_internal_shadowed_reg(): |
@@ -147,6 +155,14 @@ module ${mod_name} ( |
147 | 155 | output logic shadowed_update_err_o, |
148 | 156 |
|
149 | 157 | %endif |
| 158 | +% if racl_support: |
| 159 | + // RACL interface |
| 160 | + input top_racl_pkg::racl_policy_vec_t racl_policies_i, |
| 161 | + input integer racl_policy_sel_vec_i[${len(rb.flat_regs)}], |
| 162 | + output logic racl_error_o, |
| 163 | + output top_racl_pkg::racl_error_log_t racl_error_log_o, |
| 164 | + |
| 165 | +% endif |
150 | 166 | // Integrity check errors |
151 | 167 | output logic intg_err_o |
152 | 168 | ); |
@@ -387,7 +403,12 @@ module ${mod_name} ( |
387 | 403 | .be_o (reg_be), |
388 | 404 | .busy_i (reg_busy), |
389 | 405 | .rdata_i (reg_rdata), |
| 406 | + % if racl_support: |
| 407 | + // Translate RACL error to TLUL error if enabled |
| 408 | + .error_i (reg_error | (RaclErrorRsp & racl_error_o)) |
| 409 | + % else: |
390 | 410 | .error_i (reg_error) |
| 411 | + % endif |
391 | 412 | ); |
392 | 413 |
|
393 | 414 | // cdc oversampling signals |
@@ -641,24 +662,81 @@ ${finst_gen(sr, field, finst_name, fsig_name, fidx)} |
641 | 662 | % endfor |
642 | 663 |
|
643 | 664 | logic [${len(regs_flat)-1}:0] addr_hit; |
| 665 | +% if racl_support: |
| 666 | + top_racl_pkg::racl_role_vec_t racl_role_vec; |
| 667 | + top_racl_pkg::racl_role_t racl_role; |
| 668 | + |
| 669 | + logic [${len(regs_flat)-1}:0] racl_addr_hit_read; |
| 670 | + logic [${len(regs_flat)-1}:0] racl_addr_hit_write; |
| 671 | + |
| 672 | + if (EnableRacl) begin : gen_racl_role_logic |
| 673 | + // Retrieve RACL role from user bits and one-hot encode that for the comparison bitmap |
| 674 | + assign racl_role = top_racl_pkg::tlul_extract_racl_role_bits(tl_i.a_user.rsvd); |
| 675 | + |
| 676 | + prim_onehot_enc #( |
| 677 | + .OneHotWidth( $bits(prim_onehot_enc) ) |
| 678 | + ) u_racl_role_encode ( |
| 679 | + .in_i ( racl_role ), |
| 680 | + .en_i ( 1'b1 ), |
| 681 | + .out_o( racl_role_vec ) |
| 682 | + ); |
| 683 | + end else begin : gen_no_racl_role_logic |
| 684 | + assign racl_role = '0; |
| 685 | + assign racl_role_vec = '0; |
| 686 | + end |
| 687 | + |
| 688 | +% endif |
644 | 689 | always_comb begin |
645 | 690 | addr_hit = '0; |
| 691 | + % if racl_support: |
| 692 | + racl_addr_hit_read = '0; |
| 693 | + racl_addr_hit_write = '0; |
| 694 | + % endif |
646 | 695 | % for i,r in enumerate(regs_flat): |
647 | | - addr_hit[${"{}".format(i).rjust(max_regs_char)}] = (reg_addr == ${ublock}_${r.name.upper()}_OFFSET); |
| 696 | +<% slice = '{}'.format(i).rjust(max_regs_char) %>\ |
| 697 | + addr_hit[${slice}] = (reg_addr == ${ublock}_${r.name.upper()}_OFFSET); |
648 | 698 | % endfor |
| 699 | + % if racl_support: |
| 700 | + |
| 701 | + if (EnableRacl) begin : gen_racl_hit |
| 702 | + % for i,r in enumerate(regs_flat): |
| 703 | +<% slice = '{}'.format(i).rjust(max_regs_char) %>\ |
| 704 | + racl_addr_hit_read [${slice}] = addr_hit[${slice}] & (|(racl_policies_i[racl_policy_sel_vec_i[${slice}]].read_perm & racl_role_vec)); |
| 705 | + racl_addr_hit_write[${slice}] = addr_hit[${slice}] & (|(racl_policies_i[racl_policy_sel_vec_i[${slice}]].write_perm & racl_role_vec)); |
| 706 | + % endfor |
| 707 | + end else begin : gen_no_racl |
| 708 | + racl_addr_hit_read = addr_hit; |
| 709 | + racl_addr_hit_write = addr_hit; |
| 710 | + end |
| 711 | + % endif |
649 | 712 | end |
650 | 713 |
|
651 | 714 | assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; |
| 715 | +% if racl_support: |
| 716 | + // Address hit but failed the RACL check |
| 717 | + assign racl_error_o = (|addr_hit) & ~(|(addr_hit & (racl_addr_hit_read | racl_addr_hit_write))); |
| 718 | + assign racl_error_log_o.racl_role = racl_role; |
| 719 | + |
| 720 | + if (EnableRacl) begin : gen_racl_log |
| 721 | + assign racl_error_log_o.ctn_uid = top_racl_pkg::tlul_extract_ctn_uid_bits(tl_i.a_user.rsvd); |
| 722 | + assign racl_error_log_o.read_not_write = tl_i.a_opcode == tlul_pkg::Get; |
| 723 | + end else begin : gen_no_racl_log |
| 724 | + assign racl_error_log_o.ctn_uid = '0; |
| 725 | + assign racl_error_log_o.read_not_write = 1'b0; |
| 726 | + end |
| 727 | +% endif |
652 | 728 |
|
653 | 729 | % if regs_flat: |
654 | 730 | <% |
655 | 731 | # We want to signal wr_err if reg_be (the byte enable signal) is true for |
656 | 732 | # any bytes that aren't supported by a register. That's true if a |
657 | 733 | # addr_hit[i] and a bit is set in reg_be but not in *_PERMIT[i]. |
658 | 734 |
|
659 | | - wr_err_terms = ['(addr_hit[{idx}] & (|({mod}_PERMIT[{idx}] & ~reg_be)))' |
| 735 | + wr_addr_hit = 'racl_addr_hit_write' if racl_support else 'addr_hit' |
| 736 | + wr_err_terms = ['({wr_addr_hit}[{idx}] & (|({mod}_PERMIT[{idx}] & ~reg_be)))' |
660 | 737 | .format(idx=str(i).rjust(max_regs_char), |
661 | | - mod=u_mod_base) |
| 738 | + mod=u_mod_base, |
| 739 | + wr_addr_hit=wr_addr_hit) |
662 | 740 | for i in range(len(regs_flat))] |
663 | 741 | wr_err_expr = (' |\n' + (' ' * 15)).join(wr_err_terms) |
664 | 742 | %>\ |
@@ -715,18 +793,19 @@ ${field_wd_gen(f, r.name.lower() + "_" + f.name.lower(), r.hwext, r.shadowed, r. |
715 | 793 | always_comb begin |
716 | 794 | reg_rdata_next = '0; |
717 | 795 | unique case (1'b1) |
| 796 | +<% read_addr_hit = 'racl_addr_hit_read' if racl_support else 'addr_hit' %>\ |
718 | 797 | % for i, r in enumerate(regs_flat): |
719 | 798 | % if r.async_clk: |
720 | | - addr_hit[${i}]: begin |
| 799 | + ${read_addr_hit}[${i}]: begin |
721 | 800 | reg_rdata_next = DW'(${r.name.lower()}_qs); |
722 | 801 | end |
723 | 802 | % elif len(r.fields) == 1: |
724 | | - addr_hit[${i}]: begin |
| 803 | + ${read_addr_hit}[${i}]: begin |
725 | 804 | ${rdata_gen(r.fields[0], r.name.lower())}\ |
726 | 805 | end |
727 | 806 |
|
728 | 807 | % else: |
729 | | - addr_hit[${i}]: begin |
| 808 | + ${read_addr_hit}[${i}]: begin |
730 | 809 | % for f in r.fields: |
731 | 810 | ${rdata_gen(f, r.name.lower() + "_" + f.name.lower())}\ |
732 | 811 | % endfor |
@@ -942,7 +1021,7 @@ ${bits.msb}\ |
942 | 1021 | mubi_expr = "1'b1" |
943 | 1022 | else: |
944 | 1023 | mubi_expr = "1'b0" |
945 | | - |
| 1024 | + |
946 | 1025 | # when async, the outputs are aggregated first by the cdc module |
947 | 1026 | async_suffix = '_int' if reg.async_clk else '' |
948 | 1027 | qs_expr = f'{clk_base_name}{finst_name}_qs{async_suffix}' if field.swaccess.allows_read() else '' |
@@ -1068,11 +1147,12 @@ ${bits.msb}\ |
1068 | 1147 | % endif |
1069 | 1148 | </%def>\ |
1070 | 1149 | <%def name="reg_enable_gen(reg, idx)">\ |
| 1150 | +<% wr_addr_hit = 'racl_addr_hit_write' if racl_support else 'addr_hit'%>\ |
1071 | 1151 | % if reg.needs_re(): |
1072 | | - assign ${reg.name.lower()}_re = addr_hit[${idx}] & reg_re & !reg_error; |
| 1152 | + assign ${reg.name.lower()}_re = ${wr_addr_hit}[${idx}] & reg_re & !reg_error; |
1073 | 1153 | % endif |
1074 | 1154 | % if reg.needs_we(): |
1075 | | - assign ${reg.name.lower()}_we = addr_hit[${idx}] & reg_we & !reg_error; |
| 1155 | + assign ${reg.name.lower()}_we = ${wr_addr_hit}[${idx}] & reg_we & !reg_error; |
1076 | 1156 | % endif |
1077 | 1157 | </%def>\ |
1078 | 1158 | <%def name="field_wd_gen(field, sig_name, hwext, shadowed, async_clk, reg_name, idx)">\ |
|
0 commit comments