Skip to content

Commit 0e7117f

Browse files
msfschaffnertomeroberts
authored andcommitted
[lockstep] Introduce optimization barrier around lockstep Ibex
Certain synthesis tools like DC are very smart at optimizing away redundant logic. Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex. This is achieved by manually buffering each bit using prim_buf. Our Xilinx and DC synthesis flows make sure that these buffers cannot be optimized away using keep attributes (Vivado) and size_only constraints (DC). Signed-off-by: Michael Schaffner <[email protected]>
1 parent 1b59c67 commit 0e7117f

File tree

2 files changed

+285
-53
lines changed

2 files changed

+285
-53
lines changed

ibex_top.core

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ filesets:
1010
depend:
1111
- lowrisc:ibex:ibex_pkg
1212
- lowrisc:ibex:ibex_core
13+
- lowrisc:prim:buf
1314
files:
1415
- rtl/ibex_register_file_ff.sv # generic FF-based
1516
- rtl/ibex_register_file_fpga.sv # FPGA

rtl/ibex_top.sv

+284-53
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,225 @@ module ibex_top #(
416416

417417
// Redundant lockstep core implementation
418418
if (Lockstep) begin : gen_lockstep
419+
// Note: certain synthesis tools like DC are very smart at optimizing away redundant logic.
420+
// Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex.
421+
// This is achieved by manually buffering each bit using prim_buf.
422+
// Our Xilinx and DC synthesis flows make sure that these buffers cannot be optimized away
423+
// using keep attributes (Vivado) and size_only constraints (DC).
424+
425+
localparam int NumBufferBits = $bits({
426+
hart_id_i,
427+
boot_addr_i,
428+
instr_req_o,
429+
instr_gnt_i,
430+
instr_rvalid_i,
431+
instr_addr_o,
432+
instr_rdata_i,
433+
instr_err_i,
434+
data_req_o,
435+
data_gnt_i,
436+
data_rvalid_i,
437+
data_we_o,
438+
data_be_o,
439+
data_addr_o,
440+
data_wdata_o,
441+
data_rdata_i,
442+
data_err_i,
443+
dummy_instr_id,
444+
rf_raddr_a,
445+
rf_raddr_b,
446+
rf_waddr_wb,
447+
rf_we_wb,
448+
rf_wdata_wb_ecc,
449+
rf_rdata_a_ecc,
450+
rf_rdata_b_ecc,
451+
ic_tag_req,
452+
ic_tag_write,
453+
ic_tag_addr,
454+
ic_tag_wdata,
455+
ic_data_req,
456+
ic_data_write,
457+
ic_data_addr,
458+
ic_data_wdata,
459+
irq_software_i,
460+
irq_timer_i,
461+
irq_external_i,
462+
irq_fast_i,
463+
irq_nm_i,
464+
irq_pending,
465+
debug_req_i,
466+
crash_dump_o,
467+
core_busy_d
468+
});
469+
470+
logic [NumBufferBits-1:0] buf_in, buf_out;
471+
472+
logic [31:0] hart_id_local;
473+
logic [31:0] boot_addr_local;
474+
475+
logic instr_req_local;
476+
logic instr_gnt_local;
477+
logic instr_rvalid_local;
478+
logic [31:0] instr_addr_local;
479+
logic [31:0] instr_rdata_local;
480+
logic instr_err_local;
481+
482+
logic data_req_local;
483+
logic data_gnt_local;
484+
logic data_rvalid_local;
485+
logic data_we_local;
486+
logic [3:0] data_be_local;
487+
logic [31:0] data_addr_local;
488+
logic [31:0] data_wdata_local;
489+
logic [31:0] data_rdata_local;
490+
logic data_err_local;
491+
492+
logic dummy_instr_id_local;
493+
logic [4:0] rf_raddr_a_local;
494+
logic [4:0] rf_raddr_b_local;
495+
logic [4:0] rf_waddr_wb_local;
496+
logic rf_we_wb_local;
497+
logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_local;
498+
logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_local;
499+
logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_local;
500+
501+
logic [IC_NUM_WAYS-1:0] ic_tag_req_local;
502+
logic ic_tag_write_local;
503+
logic [IC_INDEX_W-1:0] ic_tag_addr_local;
504+
logic [TagSizeECC-1:0] ic_tag_wdata_local;
505+
logic [IC_NUM_WAYS-1:0] ic_data_req_local;
506+
logic ic_data_write_local;
507+
logic [IC_INDEX_W-1:0] ic_data_addr_local;
508+
logic [LineSizeECC-1:0] ic_data_wdata_local;
509+
510+
logic irq_software_local;
511+
logic irq_timer_local;
512+
logic irq_external_local;
513+
logic [14:0] irq_fast_local;
514+
logic irq_nm_local;
515+
logic irq_pending_local;
516+
517+
logic debug_req_local;
518+
crash_dump_t crash_dump_local;
519+
520+
logic core_busy_local;
521+
522+
assign buf_in = {
523+
hart_id_i,
524+
boot_addr_i,
525+
instr_req_o,
526+
instr_gnt_i,
527+
instr_rvalid_i,
528+
instr_addr_o,
529+
instr_rdata_i,
530+
instr_err_i,
531+
data_req_o,
532+
data_gnt_i,
533+
data_rvalid_i,
534+
data_we_o,
535+
data_be_o,
536+
data_addr_o,
537+
data_wdata_o,
538+
data_rdata_i,
539+
data_err_i,
540+
dummy_instr_id,
541+
rf_raddr_a,
542+
rf_raddr_b,
543+
rf_waddr_wb,
544+
rf_we_wb,
545+
rf_wdata_wb_ecc,
546+
rf_rdata_a_ecc,
547+
rf_rdata_b_ecc,
548+
ic_tag_req,
549+
ic_tag_write,
550+
ic_tag_addr,
551+
ic_tag_wdata,
552+
ic_data_req,
553+
ic_data_write,
554+
ic_data_addr,
555+
ic_data_wdata,
556+
irq_software_i,
557+
irq_timer_i,
558+
irq_external_i,
559+
irq_fast_i,
560+
irq_nm_i,
561+
irq_pending,
562+
debug_req_i,
563+
crash_dump_o,
564+
core_busy_d
565+
};
566+
567+
assign {
568+
hart_id_local,
569+
boot_addr_local,
570+
instr_req_local,
571+
instr_gnt_local,
572+
instr_rvalid_local,
573+
instr_addr_local,
574+
instr_rdata_local,
575+
instr_err_local,
576+
data_req_local,
577+
data_gnt_local,
578+
data_rvalid_local,
579+
data_we_local,
580+
data_be_local,
581+
data_addr_local,
582+
data_wdata_local,
583+
data_rdata_local,
584+
data_err_local,
585+
dummy_instr_id_local,
586+
rf_raddr_a_local,
587+
rf_raddr_b_local,
588+
rf_waddr_wb_local,
589+
rf_we_wb_local,
590+
rf_wdata_wb_ecc_local,
591+
rf_rdata_a_ecc_local,
592+
rf_rdata_b_ecc_local,
593+
ic_tag_req_local,
594+
ic_tag_write_local,
595+
ic_tag_addr_local,
596+
ic_tag_wdata_local,
597+
ic_data_req_local,
598+
ic_data_write_local,
599+
ic_data_addr_local,
600+
ic_data_wdata_local,
601+
irq_software_local,
602+
irq_timer_local,
603+
irq_external_local,
604+
irq_fast_local,
605+
irq_nm_local,
606+
irq_pending_local,
607+
debug_req_local,
608+
crash_dump_local,
609+
core_busy_local
610+
} = buf_out;
611+
612+
// Manually buffer all input signals.
613+
for (genvar k = 0; k < NumBufferBits; k++) begin : gen_buffers
614+
prim_buf u_prim_buf (
615+
.in_i(buf_in[k]),
616+
.out_o(buf_out[k])
617+
);
618+
end
619+
620+
logic [TagSizeECC-1:0] ic_tag_rdata_local [IC_NUM_WAYS];
621+
logic [LineSizeECC-1:0] ic_data_rdata_local [IC_NUM_WAYS];
622+
for (genvar k = 0; k < IC_NUM_WAYS; k++) begin : gen_ways
623+
for (genvar j = 0; j < TagSizeECC; j++) begin : gen_tag_bufs
624+
prim_buf u_prim_buf (
625+
.in_i(ic_tag_rdata[k][j]),
626+
.out_o(ic_tag_rdata_local[k][j])
627+
);
628+
end
629+
for (genvar j = 0; j < TagSizeECC; j++) begin : gen_data_bufs
630+
prim_buf u_prim_buf (
631+
.in_i(ic_data_rdata[k][j]),
632+
.out_o(ic_data_rdata_local[k][j])
633+
);
634+
end
635+
end
636+
637+
logic lockstep_alert_minor_local, lockstep_alert_major_local;
419638
ibex_lockstep #(
420639
.PMPEnable ( PMPEnable ),
421640
.PMPGranularity ( PMPGranularity ),
@@ -445,60 +664,72 @@ module ibex_top #(
445664
.clk_i (clk),
446665
.rst_ni (rst_ni),
447666

448-
.hart_id_i (hart_id_i),
449-
.boot_addr_i (boot_addr_i),
450-
451-
.instr_req_i (instr_req_o),
452-
.instr_gnt_i (instr_gnt_i),
453-
.instr_rvalid_i (instr_rvalid_i),
454-
.instr_addr_i (instr_addr_o),
455-
.instr_rdata_i (instr_rdata_i),
456-
.instr_err_i (instr_err_i),
457-
458-
.data_req_i (data_req_o),
459-
.data_gnt_i (data_gnt_i),
460-
.data_rvalid_i (data_rvalid_i),
461-
.data_we_i (data_we_o),
462-
.data_be_i (data_be_o),
463-
.data_addr_i (data_addr_o),
464-
.data_wdata_i (data_wdata_o),
465-
.data_rdata_i (data_rdata_i),
466-
.data_err_i (data_err_i),
467-
468-
.dummy_instr_id_i (dummy_instr_id),
469-
.rf_raddr_a_i (rf_raddr_a),
470-
.rf_raddr_b_i (rf_raddr_b),
471-
.rf_waddr_wb_i (rf_waddr_wb),
472-
.rf_we_wb_i (rf_we_wb),
473-
.rf_wdata_wb_ecc_i (rf_wdata_wb_ecc),
474-
.rf_rdata_a_ecc_i (rf_rdata_a_ecc),
475-
.rf_rdata_b_ecc_i (rf_rdata_b_ecc),
476-
477-
.ic_tag_req_i (ic_tag_req),
478-
.ic_tag_write_i (ic_tag_write),
479-
.ic_tag_addr_i (ic_tag_addr),
480-
.ic_tag_wdata_i (ic_tag_wdata),
481-
.ic_tag_rdata_i (ic_tag_rdata),
482-
.ic_data_req_i (ic_data_req),
483-
.ic_data_write_i (ic_data_write),
484-
.ic_data_addr_i (ic_data_addr),
485-
.ic_data_wdata_i (ic_data_wdata),
486-
.ic_data_rdata_i (ic_data_rdata),
487-
488-
.irq_software_i (irq_software_i),
489-
.irq_timer_i (irq_timer_i),
490-
.irq_external_i (irq_external_i),
491-
.irq_fast_i (irq_fast_i),
492-
.irq_nm_i (irq_nm_i),
493-
.irq_pending_i (irq_pending),
494-
495-
.debug_req_i (debug_req_i),
496-
.crash_dump_i (crash_dump_o),
497-
498-
.alert_minor_o (lockstep_alert_minor),
499-
.alert_major_o (lockstep_alert_major),
500-
.core_busy_i (core_busy_d)
667+
.hart_id_i (hart_id_local),
668+
.boot_addr_i (boot_addr_local),
669+
670+
.instr_req_i (instr_req_local),
671+
.instr_gnt_i (instr_gnt_local),
672+
.instr_rvalid_i (instr_rvalid_local),
673+
.instr_addr_i (instr_addr_local),
674+
.instr_rdata_i (instr_rdata_local),
675+
.instr_err_i (instr_err_local),
676+
677+
.data_req_i (data_req_local),
678+
.data_gnt_i (data_gnt_local),
679+
.data_rvalid_i (data_rvalid_local),
680+
.data_we_i (data_we_local),
681+
.data_be_i (data_be_local),
682+
.data_addr_i (data_addr_local),
683+
.data_wdata_i (data_wdata_local),
684+
.data_rdata_i (data_rdata_local),
685+
.data_err_i (data_err_local),
686+
687+
.dummy_instr_id_i (dummy_instr_id_local),
688+
.rf_raddr_a_i (rf_raddr_a_local),
689+
.rf_raddr_b_i (rf_raddr_b_local),
690+
.rf_waddr_wb_i (rf_waddr_wb_local),
691+
.rf_we_wb_i (rf_we_wb_local),
692+
.rf_wdata_wb_ecc_i (rf_wdata_wb_ecc_local),
693+
.rf_rdata_a_ecc_i (rf_rdata_a_ecc_local),
694+
.rf_rdata_b_ecc_i (rf_rdata_b_ecc_local),
695+
696+
.ic_tag_req_i (ic_tag_req_local),
697+
.ic_tag_write_i (ic_tag_write_local),
698+
.ic_tag_addr_i (ic_tag_addr_local),
699+
.ic_tag_wdata_i (ic_tag_wdata_local),
700+
.ic_tag_rdata_i (ic_tag_rdata_local),
701+
.ic_data_req_i (ic_data_req_local),
702+
.ic_data_write_i (ic_data_write_local),
703+
.ic_data_addr_i (ic_data_addr_local),
704+
.ic_data_wdata_i (ic_data_wdata_local),
705+
.ic_data_rdata_i (ic_data_rdata_local),
706+
707+
.irq_software_i (irq_software_local),
708+
.irq_timer_i (irq_timer_local),
709+
.irq_external_i (irq_external_local),
710+
.irq_fast_i (irq_fast_local),
711+
.irq_nm_i (irq_nm_local),
712+
.irq_pending_i (irq_pending_local),
713+
714+
.debug_req_i (debug_req_local),
715+
.crash_dump_i (crash_dump_local),
716+
717+
.alert_minor_o (lockstep_alert_minor_local),
718+
.alert_major_o (lockstep_alert_major_local),
719+
.core_busy_i (core_busy_local)
501720
);
721+
722+
// Manually buffer the output signals.
723+
prim_buf u_prim_buf_alert_minor (
724+
.in_i(lockstep_alert_minor_local),
725+
.out_o(lockstep_alert_minor)
726+
);
727+
728+
prim_buf u_prim_buf_alert_major (
729+
.in_i(lockstep_alert_major_local),
730+
.out_o(lockstep_alert_major)
731+
);
732+
502733
end else begin : gen_no_lockstep
503734
assign lockstep_alert_major = 1'b0;
504735
assign lockstep_alert_minor = 1'b0;

0 commit comments

Comments
 (0)