@@ -52,6 +52,7 @@ module rv_iommu_cdw_pc #(
5252 input logic caps_msi_flat_i,
5353 input logic caps_amo_hwad_i,
5454 input logic caps_end_i, fctl_be_i,
55+ input logic caps_gipc_i,
5556
5657 // PC checks
5758 input logic dc_sxl_i,
@@ -85,6 +86,7 @@ module rv_iommu_cdw_pc #(
8586
8687 // from DC (for PC walks)
8788 input logic en_stage2_i, // Second-stage translation is enabled
89+ input logic gipc_i, // GIPC is enabled
8890 input logic [riscv :: PPNW - 1 : 0 ] pdtp_ppn_i, // PPN from DC.fsc.PPN
8991 input logic [3 : 0 ] pdtp_mode_i, // PDT levels from DC.fsc.MODE
9092
@@ -110,6 +112,7 @@ module rv_iommu_cdw_pc #(
110112
111113 rv_iommu :: pc_ta_t pc_ta_q, pc_ta_n;
112114 rv_iommu :: fsc_t pc_fsc_q, pc_fsc_n;
115+ rv_iommu :: iohgatp_t pc_iohgatp_q, pc_iohgatp_n;
113116
114117 // DDTC / PDTC Update
115118 assign up_did_o = device_id_q;
@@ -118,6 +121,7 @@ module rv_iommu_cdw_pc #(
118121
119122 assign up_pc_content_o.ta = pc_ta_q;
120123 assign up_pc_content_o.fsc = pc_fsc_q;
124+ assign up_pc_content_o.iohgatp = pc_iohgatp_q;
121125
122126 // Cast read port to corresponding data structure
123127 rv_iommu :: tc_t dc_tc;
@@ -127,6 +131,7 @@ module rv_iommu_cdw_pc #(
127131
128132 rv_iommu :: pc_ta_t pc_ta;
129133 rv_iommu :: fsc_t pc_fsc;
134+ rv_iommu :: iohgatp_t pc_iohgatp;
130135
131136 rv_iommu :: nl_entry_t nl;
132137
@@ -137,6 +142,7 @@ module rv_iommu_cdw_pc #(
137142
138143 assign pc_ta = rv_iommu :: pc_ta_t ' (mem_resp_i.r.data);
139144 assign pc_fsc = rv_iommu :: fsc_t ' (mem_resp_i.r.data);
145+ assign pc_iohgatp = rv_iommu :: iohgatp_t ' (mem_resp_i.r.data);
140146
141147 assign nl = rv_iommu :: nl_entry_t ' (mem_resp_i.r.data);
142148
@@ -192,13 +198,17 @@ module rv_iommu_cdw_pc #(
192198 // Signal MSI field config error to main FSM
193199 logic msi_check_error;
194200
201+ // Enable en_stage2
202+ logic en_stage2;
203+ assign en_stage2 = ! gipc_i && en_stage2_i;
204+
195205 // PTW walking
196206 assign cdw_active_o = (state_q != IDLE );
197207 // Last CDW level
198208 assign is_last_cdw_lvl = (cdw_lvl_q == LVL1 );
199209 // Determine whether we have loaded the entire DC/PC
200210 assign dc_fully_loaded = (MSITrans != rv_iommu :: MSI_DISABLED ) ? (entry_cnt_q == 3'b111 ) : (entry_cnt_q == 3'b100 ); // extended format w/out reserved DW (64-8 = 56 bytes)
201- assign pc_fully_loaded = (entry_cnt_q == 3'b010 ); // always 16-bytes
211+ assign pc_fully_loaded = (gipc_i ? entry_cnt_q == 3'b011 : entry_cnt_q == 3' b010 ); // always 16-bytes, but (32-8 = 24) bytes for GIPC
202212 // PTW needs to know walk type to identify pdtp.PPN translations and select correct iohgatp source
203213 assign is_ddt_walk_o = is_ddt_walk_q;
204214
@@ -260,8 +270,8 @@ module rv_iommu_cdw_pc #(
260270 // AR
261271 mem_req_o.ar.id = 4'b0001 ;
262272 mem_req_o.ar.addr = {{ riscv :: XLEN - riscv :: PLEN { 1'b0 }} , cdw_pptr_q} ; // Physical address to access
263- // Number of beats per burst (1 for non-leaf entries, 2 for PC, 7 for DC)
264- mem_req_o.ar.len = (is_last_cdw_lvl) ? ((is_ddt_walk_q) ? (ar_len) : (8'd1 )) : (8'd0 );
273+ // Number of beats per burst (1 for non-leaf entries, 3/ 2 for PC, 7/4 for DC)
274+ mem_req_o.ar.len = (is_last_cdw_lvl) ? ((is_ddt_walk_q) ? (ar_len) : (gipc_i : ( 8'd2 ) : ( 8'd1 ) )) : (8'd0 );
265275 mem_req_o.ar.size = 3'b011 ; // 64 bits (8 bytes) per beat
266276 mem_req_o.ar.burst = axi_pkg :: BURST_INCR ; // Incremental start address
267277 mem_req_o.ar.lock = '0 ;
@@ -300,6 +310,7 @@ module rv_iommu_cdw_pc #(
300310 dc_fsc_n = dc_fsc_q;
301311 pc_ta_n = pc_ta_q;
302312 pc_fsc_n = pc_fsc_q;
313+ pc_iohgatp_n = pc_iohgatp_q;
303314
304315 case (state_q)
305316
@@ -347,13 +358,18 @@ module rv_iommu_cdw_pc #(
347358 // load pptr according to pdtp.MODE
348359 // PD20
349360 if (pdtp_mode_i == 4'b0011 )
350- cdw_pptr_n = { pdtp_ppn_i, 6'b0 , req_pid_i[19 : 17 ], 3'b0 } ; // ... aaaa 0000 00bb b000
361+ cdw_pptr_n = { pdtp_ppn_i,
362+ gipc_i ? 5'b0 : 6'b0 ,
363+ gipc_i ? req_pid_i[19 : 16 ] : req_pid_i[19 : 17 ], 3'b0 } ;
351364 // PD17
352365 else if (pdtp_mode_i == 4'b0010 )
353- cdw_pptr_n = { pdtp_ppn_i, req_pid_i[16 : 8 ], 3'b0 } ; // ... aaaa bbbb bbbb b000
366+ cdw_pptr_n = { pdtp_ppn_i,
367+ gipc_i ? req_pid_i[15 : 7 ] : req_pid_i[16 : 8 ], 3'b0 } ;
354368 // PD8
355369 else if (pdtp_mode_i == 4'b0001 )
356- cdw_pptr_n = { pdtp_ppn_i, req_pid_i[7 : 0 ], 4'b0 } ; // ... aaaa bbbb bbbb 0000
370+ cdw_pptr_n = { pdtp_ppn_i,
371+ gipc_i ? req_pid_i[6 : 0 ] : req_pid_i[7 : 0 ],
372+ gipc_i ? 5'b0 : 4'b0 } ;
357373 end
358374 end
359375
@@ -372,7 +388,7 @@ module rv_iommu_cdw_pc #(
372388 - Is Stage-2 enabled?
373389 - Is the last level of the DDT/PDT?
374390 */
375- case ({ en_stage2_i , is_ddt_walk_q, is_last_cdw_lvl} )
391+ case ({ en_stage2 , is_ddt_walk_q, is_last_cdw_lvl} )
376392 // rdata will hold the PPN of a non-leaf PDT/DDT entry
377393 // Stage-2 is don't care for DC walks since iohgatp always provides a PPN
378394 3'b000 , 3'b010 , 3'b110 : begin
@@ -431,7 +447,7 @@ module rv_iommu_cdw_pc #(
431447 (MSITrans == rv_iommu :: MSI_DISABLED ) ? (device_id_q[15 : 7 ]) : (device_id_q[14 : 6 ]),
432448 3'b0 } ;
433449 else begin
434- if (! en_stage2_i ) cdw_pptr_n = { nl.ppn, process_id_q[16 : 8 ], 3'b0 } ;
450+ if (! en_stage2 ) cdw_pptr_n = { nl.ppn, gipc_i ? process_id_q[ 15 : 7 ] : process_id_q[16 : 8 ], 3'b0 } ;
435451 else cdw_pptr_n = { pdt_ppn_i, process_id_q[16 : 8 ], 3'b0 } ;
436452 end
437453 end
@@ -441,7 +457,7 @@ module rv_iommu_cdw_pc #(
441457 if (is_ddt_walk_q) cdw_pptr_n = { nl.ppn,
442458 (MSITrans == rv_iommu :: MSI_DISABLED ) ? ({ device_id_q[6 : 0 ], 5'b0 } ) : ({ device_id_q[5 : 0 ], 6'b0 } )} ;
443459 else begin
444- if (! en_stage2_i ) cdw_pptr_n = { nl.ppn, process_id_q[7 : 0 ], 4'b0 } ;
460+ if (! en_stage2 ) cdw_pptr_n = { nl.ppn, gipc_i ? process_id_q[6 : 0 ] : process_id_q[ 7 : 0 ], gipc_i ? 5'b0 : 4'b0 } ;
445461 else cdw_pptr_n = { pdt_ppn_i, process_id_q[7 : 0 ], 4'b0 } ;
446462 end
447463 end
@@ -470,7 +486,7 @@ module rv_iommu_cdw_pc #(
470486 end
471487
472488 // Last DW (When stage-2 is enabled we must verify if the DC has been updated with the translated pdtp.PPN)
473- if ((is_ddt_walk_q && dc_fully_loaded && (ptw_done_q || ! en_stage2_i || ! dc_tc_q.pdtv)) ||
489+ if ((is_ddt_walk_q && dc_fully_loaded && (ptw_done_q || ! en_stage2 || ! dc_tc_q.pdtv)) ||
474490 (! is_ddt_walk_q && pc_fully_loaded)) begin
475491
476492 state_n = IDLE ;
@@ -522,6 +538,26 @@ module rv_iommu_cdw_pc #(
522538 (dc_sxl_i && (! caps_sv32_i && pc_fsc.mode == 4'd8 ))) begin
523539 state_n = ERROR ;
524540 cause_n = rv_iommu :: PDT_ENTRY_MISCONFIGURED ;
541+ if (gipc_i) begin
542+ wait_rlast_n = 1'b1 ;
543+ end
544+ end
545+ end
546+
547+ // PC.iohgatp
548+ 4'b0010 : begin
549+ pc_iohgatp_n = pc_iohgatp;
550+
551+ // Config checks
552+ if (! caps_gipc_i ||
553+ (! (pc_iohgatp.mode inside { 4'd0 , 4'd8 , 4'd9 , 4'd10 } )) ||
554+ (! fctl_gxl_i && ((! caps_sv39x4_i && pc_iohgatp.mode == 4'd8 ) ||
555+ (! caps_sv48x4_i && pc_iohgatp.mode == 4'd9 ) ||
556+ (! caps_sv57x4_i && pc_iohgatp.mode == 4'd10 ))) ||
557+ (fctl_gxl_i && (! caps_sv32x4_i && pc_iohgatp.mode == 4'd8 )) ||
558+ (| pc_iohgatp.mode && | pc_iohgatp.ppn[1 : 0 ])) begin
559+ state_n = ERROR ;
560+ cause_n = rv_iommu :: PDT_ENTRY_MISCONFIGURED ;
525561 end
526562 end
527563
@@ -612,7 +648,7 @@ module rv_iommu_cdw_pc #(
612648 else if (MSITrans == rv_iommu :: MSI_DISABLED ) begin
613649 // only if DC have an associated PC and Stage-2 is enabled, pdtp.PPN must be translated before being stored
614650 // otherwise, fsc.PPN holds iosatp field, which must be saved as a GPA
615- if (en_stage2_i && dc_tc_q.pdtv)
651+ if (en_stage2 && dc_tc_q.pdtv)
616652 state_n = GUEST_TR ;
617653 end
618654 end
@@ -806,7 +842,7 @@ module rv_iommu_cdw_pc #(
806842
807843 // only if DC have an associated PC and Stage-2 is enabled, pdtp.PPN must be translated before being stored
808844 // otherwise, fsc.PPN holds iosatp field, which must be saved as a GPA
809- if (en_stage2_i && dc_tc_q.pdtv)
845+ if (en_stage2 && dc_tc_q.pdtv)
810846 translate_pdtp = 1'b1 ;
811847
812848 // Config checks
@@ -871,6 +907,7 @@ module rv_iommu_cdw_pc #(
871907 dc_fsc_q <= '0 ;
872908 pc_ta_q <= '0 ;
873909 pc_fsc_q <= '0 ;
910+ pc_iohgatp_q <= '0 ;
874911 ptw_done_q <= 1'b0 ;
875912 wait_rlast_q <= 1'b0 ;
876913 edge_trigger_q <= 1'b0 ;
@@ -890,6 +927,7 @@ module rv_iommu_cdw_pc #(
890927 dc_fsc_q <= dc_fsc_n;
891928 pc_ta_q <= pc_ta_n;
892929 pc_fsc_q <= pc_fsc_n;
930+ pc_iohgatp_q <= pc_iohgatp_n;
893931 ptw_done_q <= ptw_done_i;
894932 wait_rlast_q <= wait_rlast_n;
895933 edge_trigger_q <= edge_trigger_n;
0 commit comments