diff --git a/Bender.yml b/Bender.yml index 5acef88..413d051 100644 --- a/Bender.yml +++ b/Bender.yml @@ -5,6 +5,7 @@ package: dependencies: tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git", version: 0.2.2 } + common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.39 } sources: - include_dirs: @@ -17,13 +18,14 @@ sources: - rtl/hwpe_ctrl_package.sv - rtl/hwpe_ctrl_interfaces.sv # Level 1 - - rtl/hwpe_ctrl_regfile_ff.sv - - rtl/hwpe_ctrl_regfile_latch.sv + - rtl/deprecated/hwpe_ctrl_regfile_ff.sv + - rtl/deprecated/hwpe_ctrl_regfile_latch.sv - rtl/hwpe_ctrl_seq_mult.sv - rtl/hwpe_ctrl_uloop.sv + - rtl/hwpe_ctrl_target.sv # Level 2 - - rtl/hwpe_ctrl_regfile_latch_test_wrap.sv + - rtl/deprecated/hwpe_ctrl_regfile_latch_test_wrap.sv # Level 3 - - rtl/hwpe_ctrl_regfile.sv + - rtl/deprecated/hwpe_ctrl_regfile.sv # Level 4 - - rtl/hwpe_ctrl_slave.sv + - rtl/deprecated/hwpe_ctrl_slave.sv diff --git a/rtl/hwpe_ctrl_regfile.sv b/rtl/deprecated/hwpe_ctrl_regfile.sv similarity index 100% rename from rtl/hwpe_ctrl_regfile.sv rename to rtl/deprecated/hwpe_ctrl_regfile.sv diff --git a/rtl/hwpe_ctrl_regfile_ff.sv b/rtl/deprecated/hwpe_ctrl_regfile_ff.sv similarity index 100% rename from rtl/hwpe_ctrl_regfile_ff.sv rename to rtl/deprecated/hwpe_ctrl_regfile_ff.sv diff --git a/rtl/hwpe_ctrl_regfile_latch.sv b/rtl/deprecated/hwpe_ctrl_regfile_latch.sv similarity index 100% rename from rtl/hwpe_ctrl_regfile_latch.sv rename to rtl/deprecated/hwpe_ctrl_regfile_latch.sv diff --git a/rtl/hwpe_ctrl_regfile_latch_test_wrap.sv b/rtl/deprecated/hwpe_ctrl_regfile_latch_test_wrap.sv similarity index 100% rename from rtl/hwpe_ctrl_regfile_latch_test_wrap.sv rename to rtl/deprecated/hwpe_ctrl_regfile_latch_test_wrap.sv diff --git a/rtl/hwpe_ctrl_slave.sv b/rtl/deprecated/hwpe_ctrl_slave.sv similarity index 100% rename from rtl/hwpe_ctrl_slave.sv rename to rtl/deprecated/hwpe_ctrl_slave.sv diff --git a/rtl/hwpe_ctrl_regif_example.rdl b/rtl/hwpe_ctrl_regif_example.rdl new file mode 100644 index 0000000..730117f --- /dev/null +++ b/rtl/hwpe_ctrl_regif_example.rdl @@ -0,0 +1,128 @@ +/* + * hwpe_ctrl_regif_example.rdl + * Francesco Conti + * + * Copyright (C) 2025 ETH Zurich, University of Bologna + * Copyright and related rights are licensed under the Solderpad Hardware + * License, Version 0.51 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law + * or agreed to in writing, software, hardware and materials distributed under + * this 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. + */ + + /* + * This file contains a sample address map for a HWPE with mandatory registers + * (not to be changed) and sample job-independent and job-dependent registers. + */ + +addrmap hwpe_ctrl_regif_example { + name = "HWPE Control port"; + desc = "Control register map for the HWPE, including mandatory control/status registers and example job-independent and job-dependent configuration registers."; + + // Mandatory COMMIT_TRIGGER register. Not to be updated inside HWPEs. + reg hwpe_commit_trigger { + field { + name = "reserved"; + desc = "Reserved."; + hw = r; + sw = r; + } r0[31:2] = 0; + field { + name = "commit_trigger"; + desc = "Write 0 to commit job & start execution, unlock controller; write `0x1` value to commit job & unlock controller without starting execution, which will be started when the next job is committed and triggered; write `0x2` value to trigger the current job queue without committing any new job."; + hw = r; + sw = w; + swacc = true; + } commit_trigger[1:0] = 0; + }; + // Mandatory ACQUIRE register. Not to be updated inside HWPEs. + reg hwpe_acquire { + field { + name = "acquire"; + desc = "On read starts a job offload, locks controller. Returns job ID."; + hw = w; + sw = r; + swacc = true; + } acquire[31:0] = 0; + }; + // Mandatory RESERVED register. Not to be updated inside HWPEs. + reg hwpe_reserved { + field { + name = "reserved"; + desc = "Reserved."; + hw = r; + sw = r; + } reserved[31:0] = 0; + }; + // Mandatory STATUS register. Not to be updated inside HWPEs. + reg hwpe_status { + field { + name = "status"; + desc = "Status of currently running job."; + hw = w; + sw = r; + } status0[31:0] = 0; + }; + // Mandatory RUNNING_JOB register. Not to be updated inside HWPEs. + reg hwpe_running_job { + field { + name = "reserved"; + desc = "Reserved."; + hw = r; + sw = r; + } r0[31:8] = 0; + field { + name = "running_job"; + desc = "Returns ID of currently running job if any job is running; otherwise, of the last job that has been run."; + hw = w; + sw = r; + } running_job[7:0] = 0; + }; + // Mandatory SOFT_CLEAR register. Not to be updated inside HWPEs. + reg hwpe_soft_clear { + field { + name = "reserved"; + desc = "Reserved."; + hw = r; + sw = r; + } r0[31:2] = 0; + field { + name = "soft_clear"; + desc = "Write `0x0` to clear the full status of the accelerator IP, including the register file; write `0x1` to clear the status of the accelerator IP, except for the register file; write `0x2` to clear only the register file."; + hw = r; + sw = w; + swacc = true; + } soft_clear[1:0] = 0; + }; + + // "mandatory" set of HWPE registers (CONTROL regs). Not to be updated inside HWPEs. + regfile hwpe_ctrl_mandatory { + hwpe_commit_trigger commit_trigger @ 0x00; + hwpe_acquire acquire @ 0x04; + hwpe_reserved reserved0 @ 0x08; + hwpe_status status @ 0x0c; + hwpe_running_job running_job @ 0x10; + hwpe_soft_clear soft_clear @ 0x14; + hwpe_reserved reserved1 @ 0x18; + hwpe_reserved reserved2 @ 0x1c; + }; + + // "generic" set of HWPE registers. Update inside HWPEs. + regfile hwpe_ctrl_job_indep { + hwpe_reserved rr; + }; + + // "job-dependent" set of HWPE registers. Update inside HWPEs. + regfile hwpe_ctrl_job_dep { + hwpe_reserved rr; + }; + + // HWPE control address map. Update inside HWPEs + hwpe_ctrl_mandatory hwpe_ctrl @ 0x00; + hwpe_ctrl_job_indep hwpe_generic @ 0x20; + hwpe_ctrl_job_dep hwpe_job_dep @ 0x40; + +}; diff --git a/rtl/hwpe_ctrl_target.sv b/rtl/hwpe_ctrl_target.sv new file mode 100644 index 0000000..913751d --- /dev/null +++ b/rtl/hwpe_ctrl_target.sv @@ -0,0 +1,235 @@ +/* + * hwpe_ctrl_target.sv + * Francesco Conti + * + * Copyright (C) 2014-2025 ETH Zurich, University of Bologna + * Copyright and related rights are licensed under the Solderpad Hardware + * License, Version 0.51 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law + * or agreed to in writing, software, hardware and materials distributed under + * this 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. + */ + + /* + * This module exposes a hwpe_ctrl_intf_periph target (slave) port like the + * deprecated `hwpe_ctrl_slave`. However, it differs from the previous module + * in that it exploits SystemRDL to generate a register file interface. + * This module must be coupled with a register interface generated out of + * a SystemRDL description. This repository contains a reference SystemRDL + * `hwpe_ctrl_regif_example.rdl` and a `rdl.sh` script to generate the register + * interface with PeakRDL. HWPEs must internalize this and modify the content to + * align with their required set of job-independent and job-dependent registers, + * without modifying the mandatory registers. + * Then, the `hwpe_ctrl_target` can be integrated by 1) overriding the parametric + * types; 2) plugging the OBI interface signals; 3) plugging `hwif_in` and + * `hwif_out`. + */ + +module hwpe_ctrl_target + import hwpe_ctrl_package::*; +#( + parameter int unsigned NB_CONTEXT = 2, + parameter int unsigned NB_CLEAR_CYCLES = 3, + parameter int unsigned ID_WIDTH = 2, + parameter int unsigned ADDR_WIDTH = 16, + parameter type hwpe_ctrl_regif_in_t = logic, // must be overridden! + parameter type hwpe_ctrl_regif_out_t = logic, // must be overridden! + parameter type hwpe_ctrl_job_indep_t = logic, // must be overridden! + parameter type hwpe_ctrl_job_dep_t = logic // must be overridden! +) +( + input logic clk_i, + input logic rst_ni, + output logic clear_o, + + // peripheral interconnect side + hwpe_ctrl_intf_periph.slave target, + + // job triggering completion & status + output logic job_trigger_o, + input logic job_done_i, + input logic [31:0] job_status_i, + + // job-independent registers + output hwpe_ctrl_job_indep_t job_indep_regs_o, + + // job-dependent registers + output logic job_dep_regs_valid_o, + output hwpe_ctrl_job_dep_t job_dep_regs_o, + + // OBI interface to target SystemRDL-generated register interface + output logic target_obi_req_o, + input logic target_obi_gnt_i, + output logic [31:0] target_obi_addr_o, + output logic target_obi_we_o, + output logic [3:0] target_obi_be_o, + output logic [31:0] target_obi_wdata_o, + output logic [ID_WIDTH-1:0] target_obi_aid_o, + input logic target_obi_rvalid_i, + output logic target_obi_rready_o, + input logic [31:0] target_obi_rdata_i, + input logic target_obi_err_i, + input logic [ID_WIDTH-1:0] target_obi_rid_i, + + // wrap -> register interface signals + output hwpe_ctrl_regif_in_t hwif_in, + + // register interface -> wrap signals + input hwpe_ctrl_regif_out_t hwif_out +); + + // unroll periph interconnect signals into OBI + assign target_obi_req_o = target.req; + assign target.gnt = target_obi_gnt_i; + assign target_obi_addr_o = {{(32-ADDR_WIDTH){1'b0}} , target.add[ADDR_WIDTH-1:0]}; + assign target_obi_we_o = ~target.wen; + assign target_obi_be_o = target.be; + assign target_obi_wdata_o = target.data; + assign target_obi_aid_o = target.id; + assign target.r_data = target_obi_rdata_i; + assign target.r_valid = target_obi_rvalid_i; + assign target.r_id = target_obi_rid_i; + assign target_obi_rready_o = '1; + + // error codes for job offload + localparam logic [31:0] HWPE_CTRL_JOB_QUEUE_FULL_ERR_CODE = 32'hffff_ffff; + localparam logic [31:0] HWPE_CTRL_JOB_ACQUIRED_ERR_CODE = 32'hffff_fffe; + + // state of job offload procedure + typedef enum logic { IDLE, ACQUIRE } job_offload_state_t; + job_offload_state_t job_offload_state_d, job_offload_state_q; + + // current and next job ID + logic [7:0] job_id_d, job_id_q; + + // job commit signal + logic job_commit; + + // job queue control signals + logic job_fifo_full, job_fifo_empty; + + // internal clear signals + logic soft_clear_regfile_d, soft_clear_state_d; + logic [NB_CLEAR_CYCLES-1:0] soft_clear_regfile_q, soft_clear_state_q; + logic soft_clear_regfile_en, soft_clear_state_en; + + // SOFT_CLEAR register: + // clear regfile if SOFT_CLEAR[0] is 0, clear state if SOFT_CLEAR[1] is 0 + assign soft_clear_regfile_d = hwif_out.hwpe_ctrl.soft_clear.soft_clear.swacc & ~hwif_out.hwpe_ctrl.soft_clear.soft_clear.value[0]; + assign soft_clear_state_d = hwif_out.hwpe_ctrl.soft_clear.soft_clear.swacc & ~hwif_out.hwpe_ctrl.soft_clear.soft_clear.value[1]; + + // generate clear enables + assign soft_clear_regfile_en = soft_clear_regfile_d | (|soft_clear_regfile_q); + assign soft_clear_state_en = soft_clear_state_d | (|soft_clear_state_q); + + // activate clear for NB_CLEAR_CYCLES cycles in case of a SOFT_CLEAR write + always_ff @(posedge clk_i or negedge rst_ni) + begin + if(~rst_ni) begin + soft_clear_regfile_q <= '0; + end + else if(soft_clear_regfile_en) begin + soft_clear_regfile_q[0] <= soft_clear_regfile_d; + for(int i=1; i