feat(hp): replace the OpenC906 clock-gating cells with per-PDK ICGs

Complete the integration manual chapter 3 cell swap (the ICG half; the
SRAM half landed earlier). Three new reviewed overrides, registered in
generate_openc906.py with sha256 pins on the vendored files and added to
the generated-filelist stamp prerequisites:

- gated_clk_cell.v (216 CPU instances) and tdt_gated_clk_cell.v (DTM):
  pass-through upstream by default; with PDK_IHP130/PDK_ICS55/PDK_SKY130/
  PDK_GF180 and without PDK_BEHAV they instantiate the process ICG cell
  (sg13g2_slgcp_1 with SCE, ICGX1H7R with the scan enable ORed into E
  because the ICS55 cell has no TE pin, sky130_fd_sc_hd__sdlclkp_1 with
  SCE, gf180mcu_fd_sc_mcu7t5v0__icgtp_1 with TE and notifier tied off).
- BUFGCE.v (PLIC/CLINT div-2 gate): the upstream behavioral latch model
  stays byte-identical by default; the same four PDK branches substitute
  the process cell with the scan input tied off.

The GF180 branch uses a repo-owned icgtp_1 functional model in
rtl/tech/gf180_seq_sim_cells.v (following the file's dff precedent)
because the vendor functional model references a UDP latch primitive that
the locked gf180mcu-pdk checkout never ships. SKY130 picks up the vendor
sdlclkp model through pdk_sky130.fl, following the existing cell pattern.
ASIC CI profiles with PDK_BEHAV unset now compile real clock gating;
PDK_BEHAV=YES profiles are bit-identical.

Evidence: the manual's MEM_INTF c906_icg_test_tb passes on all four PDK
cell paths (Icarus adaptation); the five-mode boot testbench suite passes
on top of this change.
This commit is contained in:
maksyuki committed 2026-10-15 14:05:46 +08:00
1 parent 65b1794a20
commit 65c19e7005
7 files changed
+480 -2

No files matched your search

+4 -1
View File
@@ -1132,7 +1132,10 @@ $(HP_GENERATED_STAMP): $(ROOT_PATH)/scripts/generate_openc906.py \
$(ROOT_PATH)/rtl/mini/ip_overrides/aq_spsram_128x8.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/aq_spsram_64x58.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/aq_spsram_64x88.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/aq_spsram_64x98.v $(LOCK_FILE)
$(ROOT_PATH)/rtl/mini/ip_overrides/aq_spsram_64x98.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/gated_clk_cell.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/tdt_gated_clk_cell.v \
$(ROOT_PATH)/rtl/mini/ip_overrides/BUFGCE.v $(LOCK_FILE)
python3 $(ROOT_PATH)/scripts/generate_openc906.py \
--root $(ROOT_PATH) --source $(OPENC906_ROOT) --output $(HP_GENERATED_DIR) \
--manifest $(HP_GENERATED_MANIFEST) --lock $(LOCK_FILE)
+2
View File
@@ -5,6 +5,7 @@
+incdir+/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/clkinv
+incdir+/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/mux2
+incdir+/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/xor2
+incdir+/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/sdlclkp
/tech/sky130_io_sim_cells.v
/clusterip/common/rtl/tech/ram.sv
/tech/sky130_sram_sim_cells.sv
@@ -12,3 +13,4 @@
/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/clkinv/sky130_fd_sc_hd__clkinv_1.v
/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/mux2/sky130_fd_sc_hd__mux2_1.v
/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/xor2/sky130_fd_sc_hd__xor2_1.v
/physical/pdk/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/sdlclkp/sky130_fd_sc_hd__sdlclkp_1.v
+114
View File
@@ -0,0 +1,114 @@
// retroSoC controlled override of the vendored OpenC906 BUFGCE.v.
//
// Source: openc906 dependency (dependencies.lock.json "openc906"),
// C906_RTL_FACTORY/gen_rtl/common/rtl/BUFGCE.v
// revision b0c06eb1f8b3bae663bd8b87eac89ff48e68a57f
// License: Apache-2.0 (T-Head Semiconductor)
//
// retroSoC change (OpenC906 integration manual chapter 3 ICG swap): with a
// PDK define and without PDK_BEHAV, the clock buffer-gate feeding the
// PLIC/CLINT divide-by-2 domain (aq_mp_clk_top.v apb_clk_buf) uses the
// process integrated clock-gating cell (same selection as
// gated_clk_cell.v; there is no scan enable on this instance, so SCE/TE are
// tied off). PDK_BEHAV and PDK-less builds keep the upstream behavioral
// latch-based gate byte-identical. Keep in sync when the lock revision
// changes.
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module BUFGCE(
I,
CE,
O
);
input I;
input CE ;
output O;
`ifndef PDK_BEHAV
`ifdef PDK_IHP130
`define _AQ_BUFGCE_IHP130_
`endif
`ifdef PDK_ICS55
`define _AQ_BUFGCE_ICS55_
`endif
`ifdef PDK_SKY130
`define _AQ_BUFGCE_SKY130_
`endif
`ifdef PDK_GF180
`define _AQ_BUFGCE_GF180_
`endif
`endif
`ifdef _AQ_BUFGCE_IHP130_
sg13g2_slgcp_1 u_icg (
.CLK (I),
.GATE (CE),
.SCE (1'b0),
.GCLK (O)
);
`elsif _AQ_BUFGCE_ICS55_
ICGX1H7R u_icg (
.CK (I),
.E (CE),
.ECK (O)
);
`elsif _AQ_BUFGCE_SKY130_
sky130_fd_sc_hd__sdlclkp_1 u_icg (
.CLK (I),
.GATE (CE),
.SCE (1'b0),
.GCLK (O)
);
`elsif _AQ_BUFGCE_GF180_
gf180mcu_fd_sc_mcu7t5v0__icgtp_1 u_icg (
.CLK (I),
.E (CE),
.TE (1'b0),
.Q (O),
.notifier (1'b0)
);
`else
reg clk_en_af_latch;
always @(I or CE)
begin
if(!I)
clk_en_af_latch <= CE;
end
reg clk_en ;
always @ (clk_en_af_latch )
begin
clk_en <= clk_en_af_latch;
end
assign O = I && clk_en ;
`endif
`ifdef _AQ_BUFGCE_IHP130_
`undef _AQ_BUFGCE_IHP130_
`endif
`ifdef _AQ_BUFGCE_ICS55_
`undef _AQ_BUFGCE_ICS55_
`endif
`ifdef _AQ_BUFGCE_SKY130_
`undef _AQ_BUFGCE_SKY130_
`endif
`ifdef _AQ_BUFGCE_GF180_
`undef _AQ_BUFGCE_GF180_
`endif
endmodule
+131
View File
@@ -0,0 +1,131 @@
// retroSoC controlled override of the vendored OpenC906 gated_clk_cell.v.
//
// Source: openc906 dependency (dependencies.lock.json "openc906"),
// C906_RTL_FACTORY/gen_rtl/clk/rtl/gated_clk_cell.v
// revision b0c06eb1f8b3bae663bd8b87eac89ff48e68a57f
// License: Apache-2.0 (T-Head Semiconductor)
//
// retroSoC change (OpenC906 integration manual chapter 3 ICG swap): with a
// PDK define and without PDK_BEHAV, the upstream pass-through clock gate is
// replaced by the process integrated clock-gating cell:
// PDK_IHP130 -> sg13g2_slgcp_1 (GATE=enable, SCE=scan enable)
// PDK_ICS55 -> ICGX1H7R (no test-enable pin; the scan enable is ORed
// into E so scan mode forces the clock on)
// PDK_SKY130 -> sky130_fd_sc_hd__sdlclkp_1 (GATE=enable, SCE=scan enable)
// PDK_GF180 -> gf180mcu_fd_sc_mcu7t5v0__icgtp_1 (E=enable, TE=scan enable)
// PDK_BEHAV and PDK-less builds keep the upstream pass-through
// byte-identical. Keep in sync when the lock revision changes.
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module gated_clk_cell(
clk_in,
global_en,
module_en,
local_en,
external_en,
pad_yy_icg_scan_en,
clk_out
);
input clk_in;
input global_en;
input module_en;
input local_en;
input external_en;
input pad_yy_icg_scan_en;
output clk_out;
wire clk_en_bf_latch;
wire SE;
assign clk_en_bf_latch = (global_en && (module_en || local_en)) || external_en ;
// SE driven from primary input, held constant
assign SE = pad_yy_icg_scan_en;
`ifndef PDK_BEHAV
`ifdef PDK_IHP130
`define _AQ_GATED_CLK_CELL_IHP130_
`endif
`ifdef PDK_ICS55
`define _AQ_GATED_CLK_CELL_ICS55_
`endif
`ifdef PDK_SKY130
`define _AQ_GATED_CLK_CELL_SKY130_
`endif
`ifdef PDK_GF180
`define _AQ_GATED_CLK_CELL_GF180_
`endif
`endif
`ifdef _AQ_GATED_CLK_CELL_IHP130_
sg13g2_slgcp_1 u_icg (
.CLK (clk_in),
.GATE (clk_en_bf_latch),
.SCE (SE),
.GCLK (clk_out)
);
`elsif _AQ_GATED_CLK_CELL_ICS55_
// ICGX1H7R has no test-enable pin; OR the scan enable into the enable input.
wire s_en_se;
assign s_en_se = clk_en_bf_latch | SE;
ICGX1H7R u_icg (
.CK (clk_in),
.E (s_en_se),
.ECK (clk_out)
);
`elsif _AQ_GATED_CLK_CELL_SKY130_
sky130_fd_sc_hd__sdlclkp_1 u_icg (
.CLK (clk_in),
.GATE (clk_en_bf_latch),
.SCE (SE),
.GCLK (clk_out)
);
`elsif _AQ_GATED_CLK_CELL_GF180_
gf180mcu_fd_sc_mcu7t5v0__icgtp_1 u_icg (
.CLK (clk_in),
.E (clk_en_bf_latch),
.TE (SE),
.Q (clk_out),
.notifier (1'b0)
);
`else
// // &Connect( .clk_in (clk_in), @50
// // .SE (SE), @51
// // .external_en (clk_en_bf_latch), @52
// // .clk_out (clk_out) @53
// // ) ; @54
assign clk_out = clk_in;
`endif
`ifdef _AQ_GATED_CLK_CELL_IHP130_
`undef _AQ_GATED_CLK_CELL_IHP130_
`endif
`ifdef _AQ_GATED_CLK_CELL_ICS55_
`undef _AQ_GATED_CLK_CELL_ICS55_
`endif
`ifdef _AQ_GATED_CLK_CELL_SKY130_
`undef _AQ_GATED_CLK_CELL_SKY130_
`endif
`ifdef _AQ_GATED_CLK_CELL_GF180_
`undef _AQ_GATED_CLK_CELL_GF180_
`endif
endmodule
+190
View File
@@ -0,0 +1,190 @@
// retroSoC controlled override of the vendored OpenC906 tdt_gated_clk_cell.v.
//
// Source: openc906 dependency (dependencies.lock.json "openc906"),
// C906_RTL_FACTORY/gen_rtl/tdt/rtl/common/tdt_gated_clk_cell.v
// revision b0c06eb1f8b3bae663bd8b87eac89ff48e68a57f
// License: Apache-2.0 (T-Head Semiconductor)
//
// retroSoC change (OpenC906 integration manual chapter 3 ICG swap): the
// upstream `ifdef TDT_GATED_CELL branch is preserved verbatim; with a PDK
// define and without PDK_BEHAV the debug module clock gate uses the process
// integrated clock-gating cell (same selection as gated_clk_cell.v;
// ICGX1H7R has no test-enable pin, so the scan enable is ORed into E).
// PDK_BEHAV and PDK-less builds keep the upstream pass-through
// byte-identical. Keep in sync when the lock revision changes.
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module tdt_gated_clk_cell(
clk_in,
global_en,
module_en,
local_en,
external_en,
pad_yy_icg_scan_en,
clk_out
);
input clk_in;
input global_en;
input module_en;
input local_en;
input external_en;
input pad_yy_icg_scan_en;
output clk_out;
wire clk_en_bf_latch;
wire SE;
assign clk_en_bf_latch = (global_en && (module_en || local_en)) || external_en ;
// SE driven from primary input, held constant
assign SE = pad_yy_icg_scan_en;
`ifndef PDK_BEHAV
`ifdef PDK_IHP130
`define _TDT_GATED_CLK_CELL_IHP130_
`endif
`ifdef PDK_ICS55
`define _TDT_GATED_CLK_CELL_ICS55_
`endif
`ifdef PDK_SKY130
`define _TDT_GATED_CLK_CELL_SKY130_
`endif
`ifdef PDK_GF180
`define _TDT_GATED_CLK_CELL_GF180_
`endif
`endif
`ifdef TDT_GATED_CELL
tdt_gated_cell x_tdt_gated_cell(
.clk_in (clk_in),
.external_en (clk_en_bf_latch),
.SE (SE),
.clk_out (clk_out)
);
//`ifdef TDT_SMIC
// `ifdef TDT_PROCESS55LL
//HVT_CLKLANQHDV8 x_gated_clk_cell(
//.CK(clk_in),
// `endif
//.TE(SE),
//.E(clk_en_bf_latch),
//.Q(clk_out));
//`endif
//`ifdef TDT_TSMC
// `ifdef TDT_PROCESS40LP
//CKLNQD1BWP x_gated_clk_cell(
//.CP(clk_in),
//.TE(SE),
//.E(clk_en_bf_latch),
//.Q(clk_out));
// `endif
// `ifdef TDT_PROCESS28HPC
// CKLNQD8BWP35P140 x_gated_clk_cell (
// .CP (clk_in),
// .TE (SE),
// .E (clk_en_bf_latch),
// .Q (clk_out)
// );
// `endif
//`endif
//`ifdef TDT_GSMC
// `ifdef TDT_PROCESS130
//CLKGTPHD8X x_gated_clk_cell(
//.CK(clk_in),
// `endif
//.TE(SE),
//.E(clk_en_bf_latch),
//.Z(clk_out));
//`endif
//
//`ifdef TDT_UMC
// `ifdef TDT_PROCESS28HDE
// PREICG_X4B_A9PP140ZTR_C30 x_gated_clk_cell (
// .CK(clk_in),
// .SE(SE),
// .E(clk_en_bf_latch),
// .ECK(clk_out)
// );
// `endif
// `ifdef TDT_PROCESS22HDE
// PREICG_X4B_A9PP140ZTS_C30 x_gated_clk_cell (
// .CK(clk_in),
// .SE(SE),
// .E(clk_en_bf_latch),
// .ECK(clk_out)
// );
//
// `endif
//`endif
`elsif _TDT_GATED_CLK_CELL_IHP130_
sg13g2_slgcp_1 u_icg (
.CLK (clk_in),
.GATE (clk_en_bf_latch),
.SCE (SE),
.GCLK (clk_out)
);
`elsif _TDT_GATED_CLK_CELL_ICS55_
// ICGX1H7R has no test-enable pin; OR the scan enable into the enable input.
wire s_en_se;
assign s_en_se = clk_en_bf_latch | SE;
ICGX1H7R u_icg (
.CK (clk_in),
.E (s_en_se),
.ECK (clk_out)
);
`elsif _TDT_GATED_CLK_CELL_SKY130_
sky130_fd_sc_hd__sdlclkp_1 u_icg (
.CLK (clk_in),
.GATE (clk_en_bf_latch),
.SCE (SE),
.GCLK (clk_out)
);
`elsif _TDT_GATED_CLK_CELL_GF180_
gf180mcu_fd_sc_mcu7t5v0__icgtp_1 u_icg (
.CLK (clk_in),
.E (clk_en_bf_latch),
.TE (SE),
.Q (clk_out),
.notifier (1'b0)
);
`else
//STN_CKGTPLT_V5_1 x_gated_clk_cell (
// .CK (clk_in),
// .SE (SE),
// .EN (clk_en_bf_latch),
// .Q (clk_out)
//);
assign clk_out = clk_in;
`endif
`ifdef _TDT_GATED_CLK_CELL_IHP130_
`undef _TDT_GATED_CLK_CELL_IHP130_
`endif
`ifdef _TDT_GATED_CLK_CELL_ICS55_
`undef _TDT_GATED_CLK_CELL_ICS55_
`endif
`ifdef _TDT_GATED_CLK_CELL_SKY130_
`undef _TDT_GATED_CLK_CELL_SKY130_
`endif
`ifdef _TDT_GATED_CLK_CELL_GF180_
`undef _TDT_GATED_CLK_CELL_GF180_
`endif
endmodule
+18
View File
@@ -53,3 +53,21 @@ module gf180mcu_fd_sc_mcu7t5v0__dffsnq_1 (
else Q <= D;
end
endmodule
// The upstream icgtp functional model references a UDP latch primitive
// (UDP_GF018hv5v_mcu_sc7_TT_1P8V_25C_verilog_nonpg_MGM_N_IQ_LATCH_UDP) that
// is not shipped anywhere in the locked GF180 checkout, so the vendor model
// cannot elaborate; this functional model retains the PDK cell interface.
module gf180mcu_fd_sc_mcu7t5v0__icgtp_1 (
input wire TE,
input wire E,
input wire CLK,
output wire Q,
input wire notifier
);
reg s_en_latch;
always @(CLK or E or TE) begin
if (!CLK) s_en_latch <= E | TE;
end
assign Q = CLK & s_en_latch;
endmodule
+21 -1
View File
@@ -18,8 +18,16 @@ for their vendored counterparts:
integration manual chapter 3 memory swap). Each override keeps the upstream
behavioral ``aq_f_spsram_*`` instance by default and substitutes IHP130
``RM_IHPSG13_1P_*`` macro combinations (depth/width stacking per manual
section 3.1.5) only when the build defines ``PDK_IHP130`` and
section 3.1.5) or exact-geometry ICS55 ``ics55_ecos_sram_*`` macros only
when the build defines ``PDK_IHP130``/``PDK_ICS55`` and
``HAVE_SRAM_MACRO`` without ``PDK_BEHAV``.
- ``gated_clk_cell.v`` / ``tdt_gated_clk_cell.v`` / ``BUFGCE.v``: the
clock-gating cells (manual chapter 3 ICG swap). Each override keeps the
upstream default (pass-through for the two ``*_gated_clk_cell`` wrappers,
behavioral latch gate for ``BUFGCE``) unless a PDK define is set without
``PDK_BEHAV``, in which case the process ICG cell is instantiated
(``sg13g2_slgcp_1`` / ``ICGX1H7R`` / ``sky130_fd_sc_hd__sdlclkp_1`` /
``gf180mcu_fd_sc_mcu7t5v0__icgtp_1``).
All sources are concatenated into a single compilation unit
(``openc906_combined.v``) because gen_rtl relies on header macros being
@@ -88,6 +96,18 @@ OVERRIDES = {
"aq_spsram_64x98.v",
"99680fb11271eee6cfe6ff7aaa95cbdd04ef4f78d7b0e23a18c17ef064a8bedf",
),
"C906_RTL_FACTORY/gen_rtl/clk/rtl/gated_clk_cell.v": (
"gated_clk_cell.v",
"22a4a5f41c7733bd4935adc8a036870a110a8e2f2a70f1f3cf64476b7a49eb9e",
),
"C906_RTL_FACTORY/gen_rtl/tdt/rtl/common/tdt_gated_clk_cell.v": (
"tdt_gated_clk_cell.v",
"9c38f1d71a3aaa64e00d2aa7d5a43f5836080c604f245dd414a85935241d26bd",
),
"C906_RTL_FACTORY/gen_rtl/common/rtl/BUFGCE.v": (
"BUFGCE.v",
"b0907982b81c64494756d7f62a3a35bf961f6cbf7d54241460a476dde36a333a",
),
}