From e230c61b4df5fb26cb53bfb001e7209c14fb90c0 Mon Sep 17 00:00:00 2001 From: Salvatore Date: Tue, 13 Apr 2021 16:19:31 +0200 Subject: [PATCH] initial commit --- examples/aggregate/Makefile | 13 + .../aggregate/handlers/aggregate_global.c | 69 + examples/copy_from_host/Makefile | 13 + .../copy_from_host/handlers/copy_from_host.c | 58 + examples/copy_to_host/Makefile | 13 + examples/copy_to_host/handlers/copy_to_host.c | 56 + examples/empty/Makefile | 11 + examples/empty/handlers/empty.c | 40 + examples/filtering/Makefile | 15 + examples/filtering/handlers/filtering.c | 111 + examples/hashtable_fun/Makefile | 17 + examples/hashtable_fun/driver/htable_driver.c | 94 + .../hashtable_fun/handlers/htable_handlers.c | 48 + examples/histogram/Makefile | 15 + examples/histogram/handlers/histogram_l1.c | 82 + examples/host_direct/Makefile | 11 + examples/host_direct/handlers/hostdirect.c | 26 + examples/ping_pong/Makefile | 13 + examples/ping_pong/handlers/ping_pong.c | 62 + examples/reduce/Makefile | 13 + examples/reduce/handlers/reduce_l1.c | 74 + hw/deps/apb/src/apb_intf.sv | 55 + hw/deps/axi/src/axi_atop_filter.sv | 427 + hw/deps/axi/src/axi_buf.sv | 247 + hw/deps/axi/src/axi_cut.sv | 263 + hw/deps/axi/src/axi_demux.sv | 741 + hw/deps/axi/src/axi_dw_converter.sv | 188 + hw/deps/axi/src/axi_dw_downsizer.sv | 767 + hw/deps/axi/src/axi_dw_upsizer.sv | 645 + hw/deps/axi/src/axi_err_slv.sv | 256 + hw/deps/axi/src/axi_id_prepend.sv | 159 + hw/deps/axi/src/axi_id_remap.sv | 640 + hw/deps/axi/src/axi_intf.sv | 434 + hw/deps/axi/src/axi_mux.sv | 520 + hw/deps/axi/src/axi_pkg.sv | 311 + hw/deps/axi/src/axi_serializer.sv | 294 + hw/deps/axi/src/axi_xbar.sv | 312 + hw/deps/axi/src/dma/axi_dma_backend.sv | 588 + hw/deps/axi/src/dma/axi_dma_burst_reshaper.sv | 357 + hw/deps/axi/src/dma/axi_dma_data_mover.sv | 370 + hw/deps/axi/src/dma/axi_dma_data_path.sv | 393 + .../pspin_soc_frontend/src/pspin_soc_dma.sv | 259 + .../src/pulp_cluster_frontend.sv | 425 + .../src/pulp_cluster_frontend_regs.sv | 205 + .../src/transfer_id_gen.sv | 58 + hw/deps/axi2apb/src/axi2apb_64_32.sv | 756 + hw/deps/axi2apb/src/axi2apb_wrap.sv | 180 + hw/deps/axi2mem/src/axi_to_mem.sv | 782 + hw/deps/axi2mem/src/axi_to_mem_banked_mp.sv | 373 + hw/deps/axi2mem/src/axi_to_mem_interleaved.sv | 209 + hw/deps/axi2per/axi2per.sv | 467 + hw/deps/axi2per/axi2per_req_channel.sv | 215 + hw/deps/axi2per/axi2per_res_channel.sv | 183 + hw/deps/axi_riscv_atomics/src/axi_res_tbl.sv | 89 + .../axi_riscv_atomics/src/axi_riscv_amos.sv | 1075 + .../src/axi_riscv_amos_alu.sv | 78 + .../src/axi_riscv_atomics.sv | 404 + .../src/axi_riscv_atomics_wrap.sv | 154 + .../axi_riscv_atomics/src/axi_riscv_lrsc.sv | 987 + hw/deps/axi_slice/src/axi_ar_buffer.sv | 74 + hw/deps/axi_slice/src/axi_aw_buffer.sv | 78 + hw/deps/axi_slice/src/axi_b_buffer.sv | 54 + hw/deps/axi_slice/src/axi_r_buffer.sv | 60 + hw/deps/axi_slice/src/axi_single_slice.sv | 51 + hw/deps/axi_slice/src/axi_w_buffer.sv | 55 + hw/deps/axi_slice_dc/src/dc_synchronizer.v | 38 + hw/deps/axi_slice_dc/src/dc_token_ring.v | 40 + .../src/dc_token_ring_fifo_dout.v | 77 + .../rtl/interfaces/tcdm_bank_mem_bus.sv | 30 + .../rtl/interfaces/wide_dma_tcdm.sv | 39 + .../rtl/interfaces/xbar_demux_bus.sv | 41 + .../rtl/interfaces/xbar_periph_bus.sv | 40 + .../rtl/interfaces/xbar_tcdm_bus.sv | 36 + .../AddressDecoder_PE_Req.sv | 113 + .../AddressDecoder_Resp_PE.sv | 63 + .../peripheral_interco/ArbitrationTree_PE.sv | 347 + .../FanInPrimitive_PE_Resp.sv | 87 + .../FanInPrimitive_Req_PE.sv | 137 + .../rtl/peripheral_interco/MUX2_REQ_PE.sv | 147 + .../rtl/peripheral_interco/RR_Flag_Req_PE.sv | 87 + .../peripheral_interco/RequestBlock2CH_PE.sv | 637 + .../peripheral_interco/ResponseBlock_PE.sv | 150 + .../rtl/peripheral_interco/ResponseTree_PE.sv | 177 + .../rtl/peripheral_interco/XBAR_PE.sv | 316 + .../tcdm_interconnect/addr_dec_resp_mux.sv | 184 + .../rtl/tcdm_interconnect/amo_shim.sv | 333 + .../superbank_addr_decoder.sv | 114 + .../tcdm_interconnect/tcdm_interconnect.sv | 323 + .../tcdm_interconnect_pkg.sv | 73 + .../tcdm_interconnect/tcdm_superbank_mux.sv | 184 + .../rtl/tcdm_interconnect/xbar.sv | 132 + .../cluster_control_unit.sv | 393 + .../interfaces/mp_pf_icache_ctrl_unit_bus.sv | 55 + .../mp_pf_icache_ctrl_unit.sv | 432 + hw/deps/common_cells/src/addr_decode.sv | 159 + hw/deps/common_cells/src/cf_math_pkg.sv | 85 + hw/deps/common_cells/src/counter.sv | 43 + hw/deps/common_cells/src/delta_counter.sv | 74 + .../common_cells/src/deprecated/fifo_v1.sv | 57 + .../common_cells/src/deprecated/fifo_v2.sv | 79 + .../src/deprecated/generic_LFSR_8bit.sv | 64 + .../src/deprecated/generic_fifo.sv | 274 + .../common_cells/src/edge_propagator_tx.sv | 40 + .../common_cells/src/fall_through_register.sv | 58 + hw/deps/common_cells/src/fifo_v3.sv | 155 + hw/deps/common_cells/src/id_queue.sv | 277 + hw/deps/common_cells/src/lzc.sv | 109 + hw/deps/common_cells/src/onehot_to_bin.sv | 38 + hw/deps/common_cells/src/rr_arb_tree.sv | 341 + hw/deps/common_cells/src/rstgen.sv | 30 + hw/deps/common_cells/src/rstgen_bypass.sv | 57 + hw/deps/common_cells/src/spill_register.sv | 95 + hw/deps/common_cells/src/stream_arbiter.sv | 49 + .../src/stream_arbiter_flushable.sv | 82 + hw/deps/common_cells/src/stream_demux.sv | 36 + hw/deps/common_cells/src/stream_fifo.sv | 66 + hw/deps/common_cells/src/stream_filter.sv | 26 + hw/deps/common_cells/src/stream_fork.sv | 133 + .../common_cells/src/stream_fork_dynamic.sv | 95 + hw/deps/common_cells/src/stream_join.sv | 43 + hw/deps/common_cells/src/stream_mux.sv | 46 + hw/deps/common_cells/src/stream_register.sv | 57 + hw/deps/common_cells/src/stream_to_mem.sv | 134 + hw/deps/event_unit_flex/event_unit_core.sv | 577 + .../event_unit_interface_mux.sv | 330 + hw/deps/event_unit_flex/event_unit_top.sv | 338 + hw/deps/event_unit_flex/hw_barrier_unit.sv | 225 + hw/deps/event_unit_flex/hw_dispatch.sv | 179 + hw/deps/event_unit_flex/hw_mutex_unit.sv | 180 + hw/deps/event_unit_flex/interc_sw_evt_trig.sv | 65 + hw/deps/event_unit_flex/message_bus.sv | 58 + ...butedArbitrationNetwork_Req_icache_intc.sv | 206 + ...utedArbitrationNetwork_Resp_icache_intc.sv | 145 + .../icache-intc/Req_Arb_Node_icache_intc.sv | 78 + .../RoutingBlock_Req_icache_intc.sv | 94 + .../RoutingBlock_Resp_icache_intc.sv | 86 + hw/deps/icache-intc/icache_intc.sv | 170 + .../RTL/cache_controller_to_axi_128_PF.sv | 515 + .../RTL/central_controller_128.sv | 508 + .../RTL/icache_bank_mp_128.sv | 610 + .../icache_mp_128_pf/RTL/icache_bank_mp_PF.sv | 544 + .../RTL/icache_top_mp_128_PF.sv | 879 + .../RTL/merge_refill_cam_128_16.sv | 544 + hw/deps/icache_mp_128_pf/RTL/pf_miss_mux.sv | 95 + hw/deps/icache_mp_128_pf/RTL/prefetcher_if.sv | 204 + hw/deps/per2axi/src/per2axi.sv | 484 + hw/deps/per2axi/src/per2axi_busy_unit.sv | 72 + hw/deps/per2axi/src/per2axi_req_channel.sv | 309 + hw/deps/per2axi/src/per2axi_res_channel.sv | 213 + hw/deps/pulp_cluster/packages/apu_package.sv | 52 + .../packages/pulp_cluster_package.sv | 43 + hw/deps/pulp_cluster/rtl/axi2per_wrap.sv | 120 + hw/deps/pulp_cluster/rtl/cluster_bus_wrap.sv | 121 + hw/deps/pulp_cluster/rtl/cluster_event_map.sv | 58 + .../rtl/cluster_interconnect_wrap.sv | 672 + .../pulp_cluster/rtl/cluster_peripherals.sv | 274 + .../pulp_cluster/rtl/cluster_timer_wrap.sv | 71 + hw/deps/pulp_cluster/rtl/core_demux.sv | 568 + hw/deps/pulp_cluster/rtl/core_region.sv | 573 + hw/deps/pulp_cluster/rtl/cpu_marx_if.sv | 63 + hw/deps/pulp_cluster/rtl/dmac_wrap.sv | 359 + hw/deps/pulp_cluster/rtl/inter_core_fifo.sv | 116 + hw/deps/pulp_cluster/rtl/nhi_port_wrap.sv | 86 + hw/deps/pulp_cluster/rtl/per2axi_wrap.sv | 129 + hw/deps/pulp_cluster/rtl/per_demux_wrap.sv | 75 + hw/deps/pulp_cluster/rtl/periph_FIFO.sv | 86 + hw/deps/pulp_cluster/rtl/periph_demux.sv | 267 + hw/deps/pulp_cluster/rtl/pulp_cluster.sv | 1844 + hw/deps/pulp_cluster/rtl/tryx_ctrl.sv | 140 + .../pulp_cluster/rtl/virtual_stdout_demux.sv | 106 + hw/deps/riscv/include/apu_core_package.sv | 77 + hw/deps/riscv/include/fpnew_pkg.sv | 484 + hw/deps/riscv/include/riscv_defines.sv | 675 + hw/deps/riscv/include/riscv_tracer_defines.sv | 203 + hw/deps/riscv/riscv_L0_buffer.sv | 282 + hw/deps/riscv/riscv_alu.sv | 1155 + hw/deps/riscv/riscv_alu_div.sv | 216 + hw/deps/riscv/riscv_apu_disp.sv | 248 + hw/deps/riscv/riscv_compressed_decoder.sv | 299 + hw/deps/riscv/riscv_controller.sv | 1138 + hw/deps/riscv/riscv_core.sv | 1284 + hw/deps/riscv/riscv_cs_registers.sv | 1646 + hw/deps/riscv/riscv_decoder.sv | 2675 ++ hw/deps/riscv/riscv_ex_stage.sv | 564 + hw/deps/riscv/riscv_ff_one.sv | 98 + hw/deps/riscv/riscv_hwloop_controller.sv | 98 + hw/deps/riscv/riscv_hwloop_regs.sv | 134 + hw/deps/riscv/riscv_id_stage.sv | 1676 + hw/deps/riscv/riscv_if_stage.sv | 428 + hw/deps/riscv/riscv_int_controller.sv | 126 + hw/deps/riscv/riscv_load_store_unit.sv | 337 + hw/deps/riscv/riscv_mult.sv | 365 + hw/deps/riscv/riscv_pmp.sv | 810 + hw/deps/riscv/riscv_popcnt.sv | 63 + hw/deps/riscv/riscv_prefetch_L0_buffer.sv | 579 + hw/deps/riscv/riscv_register_file.sv | 189 + hw/deps/riscv/riscv_store_buffer.sv | 225 + hw/deps/riscv/riscv_tracer.sv | 1192 + .../verilator-model/cluster_clock_gating.sv | 34 + .../register_file_1w_multi_port_read.sv | 173 + hw/deps/tech_cells_generic/src/rtl/tc_sram.sv | 206 + hw/deps/timer_unit/rtl/timer_unit.sv | 579 + hw/deps/timer_unit/rtl/timer_unit_counter.sv | 73 + .../rtl/timer_unit_counter_presc.sv | 73 + hw/src/apb/apb_bus.sv | 128 + hw/src/apb/apb_bus_wrap.sv | 82 + hw/src/apb/apb_ro_regs.sv | 56 + hw/src/apb/apb_rw_regs.sv | 82 + hw/src/apb/apb_stdout.sv | 70 + hw/src/cmds/cluster_cmd.sv | 50 + hw/src/cmds/cmd_unit.sv | 212 + hw/src/host_direct.sv | 258 + hw/src/host_mst_mux.sv | 108 + hw/src/interconnects/cluster_noc.sv | 179 + hw/src/interconnects/dma_noc.sv | 122 + hw/src/interconnects/l2_xbar.sv | 354 + hw/src/interconnects/nhi_xbar.sv | 584 + hw/src/interconnects/pe_noc.sv | 295 + hw/src/memories/l2_mem.sv | 194 + hw/src/memories/prog_mem.sv | 163 + hw/src/memories/sram.sv | 52 + hw/src/pkt_scheduler/cluster_rb.sv | 190 + hw/src/pkt_scheduler/cluster_scheduler.sv | 298 + hw/src/pkt_scheduler/fifo_engine.sv | 221 + hw/src/pkt_scheduler/hpu_driver.sv | 884 + hw/src/pkt_scheduler/mpq_engine.sv | 538 + hw/src/pkt_scheduler/scheduler.sv | 293 + hw/src/pspin.sv | 865 + hw/src/pspin_cfg_pkg.sv | 322 + hw/src/pspin_verilator.sv | 696 + hw/src/pulp_cluster_cfg_pkg.sv | 88 + hw/src/pulp_cluster_ooc.sv | 1213 + hw/src/soc_ctrl_regs.sv | 92 + hw/src/soc_dma_wrap.sv | 336 + hw/src/soc_peripherals.sv | 94 + hw/verilator_model/Makefile | 285 + hw/verilator_model/include/pspinsim.h | 87 + hw/verilator_model/include/spin.h | 72 + hw/verilator_model/include/spin_hw_conf.h | 41 + hw/verilator_model/src/AXIDriver.hpp | 247 + hw/verilator_model/src/AXIMaster.hpp | 492 + hw/verilator_model/src/AXIPort.hpp | 218 + hw/verilator_model/src/AXISlave.hpp | 404 + hw/verilator_model/src/NICInbound.hpp | 549 + hw/verilator_model/src/NICOutbound.hpp | 325 + hw/verilator_model/src/PCIe.hpp | 251 + hw/verilator_model/src/PCIeMaster.hpp | 193 + hw/verilator_model/src/PCIeSlave.hpp | 257 + hw/verilator_model/src/SimControl.hpp | 183 + hw/verilator_model/src/SimModule.hpp | 31 + hw/verilator_model/src/main.cpp | 79 + hw/verilator_model/src/pspin.hpp | 170 + hw/verilator_model/src/pspinsim.cpp | 335 + hw/verilator_model/start_sim.sh | 9 + sourceme-template.sh | 16 + sw/pulp-sdk/archi/.gitignore | 6 + sw/pulp-sdk/archi/LICENSE | 177 + sw/pulp-sdk/archi/Makefile | 69 + sw/pulp-sdk/archi/SConstruct | 207 + sw/pulp-sdk/archi/doc/APB_GPIO_reference.xlsx | 1 + .../archi/doc/CL_EVENT_UNIT_reference.xlsx | Bin 0 -> 35270 bytes .../archi/doc/FC_EVENT_UNIT_reference.xlsx | Bin 0 -> 85411 bytes sw/pulp-sdk/archi/doc/HYPER_V2_reference.xlsx | 1 + .../PULPISSIMO_APB_SOC_CTRL_reference.xlsx | Bin 0 -> 10067 bytes sw/pulp-sdk/archi/doc/RTC_UNIT_reference.xlsx | Bin 0 -> 14802 bytes .../archi/doc/TIMER_UNIT_reference.xlsx | 1 + .../doc/WOLFE_APB_SOC_CTRL_reference.xlsx | Bin 0 -> 18185 bytes .../archi/doc/gap/APB_SOC_CTRL_reference.xlsx | 1 + .../archi/doc/gpio/APB_GPIO_V3_reference.xlsx | 1 + .../archi/doc/hwce/HWCE_v4_reference.xlsx | 1 + .../archi/doc/hwce/HWCE_v5_reference.xlsx | 1 + .../archi/doc/mchan/CL_DMA_v7_reference.xlsx | 1 + sw/pulp-sdk/archi/doc/pwm/pwm_v1.xlsx | 1 + .../archi/doc/udma/CAM_CPI_V1_reference.xlsx | 1 + .../archi/doc/udma/MEMCPY_v1_reference.xlsx | 1 + .../archi/doc/udma/MRAM_reference.xlsx | 1 + .../archi/doc/udma/i2s/I2S_V1_reference.xlsx | 1 + .../archi/doc/udma/i2s/I2S_V2_reference.xlsx | 1 + .../archi/doc/udma/i2s/I2S_V3_reference.xlsx | Bin 0 -> 26482 bytes .../doc/vega/APB_SOC_CTRL_reference.xlsx | 1 + .../include/archi/chips/arnold/apb_soc.h | 121 + .../include/archi/chips/arnold/memory_map.h | 94 + .../include/archi/chips/arnold/properties.h | 191 + .../archi/include/archi/chips/arnold/pulp.h | 38 + .../include/archi/chips/bigpulp/apb_soc.h | 122 + .../include/archi/chips/bigpulp/memory_map.h | 87 + .../include/archi/chips/bigpulp/properties.h | 145 + .../archi/include/archi/chips/bigpulp/pulp.h | 34 + .../include/archi/chips/devchip/apb_soc.h | 121 + .../include/archi/chips/devchip/memory_map.h | 108 + .../include/archi/chips/devchip/properties.h | 223 + .../archi/include/archi/chips/devchip/pulp.h | 31 + .../include/archi/chips/fulmine/apb_soc.h | 33 + .../include/archi/chips/fulmine/memory_map.h | 92 + .../include/archi/chips/fulmine/properties.h | 123 + .../archi/include/archi/chips/fulmine/pulp.h | 27 + .../archi/include/archi/chips/gap/apb_soc.h | 1588 + .../include/archi/chips/gap/memory_map.h | 148 + .../archi/include/archi/chips/gap/padframe.h | 140 + .../include/archi/chips/gap/properties.h | 273 + .../archi/include/archi/chips/gap/pulp.h | 47 + .../archi/include/archi/chips/gap9/apb_soc.h | 110 + .../include/archi/chips/gap9/apb_soc_ctrl.h | 1581 + .../include/archi/chips/gap9/memory_map.h.in | 175 + .../archi/include/archi/chips/gap9/pmu.h | 510 + .../include/archi/chips/gap9/properties.h | 347 + .../archi/include/archi/chips/gap9/pulp.h | 45 + .../archi/include/archi/chips/honey/apb_soc.h | 19 + .../include/archi/chips/honey/memory_map.h | 92 + .../include/archi/chips/honey/padframe.h | 199 + .../include/archi/chips/honey/properties.h | 100 + .../archi/include/archi/chips/honey/pulp.h | 31 + .../include/archi/chips/multino/apb_soc.h | 122 + .../include/archi/chips/multino/memory_map.h | 117 + .../include/archi/chips/multino/properties.h | 114 + .../archi/include/archi/chips/multino/pulp.h | 32 + .../include/archi/chips/neuraghe/memory_map.h | 79 + .../include/archi/chips/neuraghe/properties.h | 54 + .../archi/include/archi/chips/neuraghe/pulp.h | 29 + .../include/archi/chips/oprecompkw/apb_soc.h | 121 + .../archi/chips/oprecompkw/memory_map.h | 90 + .../archi/chips/oprecompkw/properties.h | 102 + .../include/archi/chips/oprecompkw/pulp.h | 31 + .../archi/include/archi/chips/pulp/apb_soc.h | 121 + .../include/archi/chips/pulp/apb_soc_ctrl.h | 116 + .../include/archi/chips/pulp/memory_map.h | 128 + .../include/archi/chips/pulp/properties.h | 275 + .../archi/include/archi/chips/pulp/pulp.h | 41 + .../include/archi/chips/pulp_v1/apb_soc.h | 121 + .../include/archi/chips/pulp_v1/memory_map.h | 128 + .../include/archi/chips/pulp_v1/properties.h | 226 + .../archi/include/archi/chips/pulp_v1/pulp.h | 39 + .../include/archi/chips/pulpissimo/apb_soc.h | 121 + .../archi/chips/pulpissimo/apb_soc_ctrl.h | 116 + .../archi/chips/pulpissimo/memory_map.h | 81 + .../archi/chips/pulpissimo/properties.h | 236 + .../include/archi/chips/pulpissimo/pulp.h | 39 + .../archi/chips/pulpissimo_v1/apb_soc.h | 121 + .../archi/chips/pulpissimo_v1/memory_map.h | 81 + .../archi/chips/pulpissimo_v1/properties.h | 200 + .../include/archi/chips/pulpissimo_v1/pulp.h | 35 + .../include/archi/chips/quentin/apb_soc.h | 121 + .../include/archi/chips/quentin/memory_map.h | 95 + .../include/archi/chips/quentin/properties.h | 197 + .../archi/include/archi/chips/quentin/pulp.h | 32 + .../include/archi/chips/usoc_v1/apb_soc.h | 75 + .../archi/include/archi/chips/usoc_v1/gpio.h | 50 + .../include/archi/chips/usoc_v1/memory_map.h | 123 + .../include/archi/chips/usoc_v1/properties.h | 168 + .../archi/include/archi/chips/usoc_v1/pulp.h | 31 + .../archi/include/archi/chips/vega/apb_soc.h | 110 + .../include/archi/chips/vega/apb_soc_ctrl.h | 1581 + .../include/archi/chips/vega/memory_map.h.in | 175 + .../archi/include/archi/chips/vega/pmu.h | 510 + .../include/archi/chips/vega/properties.h | 347 + .../archi/include/archi/chips/vega/pulp.h | 45 + .../include/archi/chips/vivosoc2/memory_map.h | 94 + .../include/archi/chips/vivosoc2/properties.h | 135 + .../archi/include/archi/chips/vivosoc2/pulp.h | 26 + .../archi/chips/vivosoc2_1/memory_map.h | 94 + .../archi/chips/vivosoc2_1/properties.h | 134 + .../include/archi/chips/vivosoc2_1/pulp.h | 26 + .../include/archi/chips/vivosoc3/apb_soc.h | 121 + .../archi/include/archi/chips/vivosoc3/fll.h | 125 + .../archi/include/archi/chips/vivosoc3/freq.h | 27 + .../include/archi/chips/vivosoc3/memory_map.h | 127 + .../include/archi/chips/vivosoc3/properties.h | 212 + .../archi/include/archi/chips/vivosoc3/pulp.h | 41 + .../include/archi/chips/vivosoc3_1/apb_soc.h | 124 + .../include/archi/chips/vivosoc3_1/fll.h | 125 + .../include/archi/chips/vivosoc3_1/freq.h | 27 + .../archi/chips/vivosoc3_1/memory_map.h | 125 + .../archi/chips/vivosoc3_1/properties.h | 293 + .../include/archi/chips/vivosoc3_1/pulp.h | 40 + .../include/archi/chips/vivosoc3_5/apb_soc.h | 121 + .../include/archi/chips/vivosoc3_5/fll.h | 125 + .../include/archi/chips/vivosoc3_5/freq.h | 27 + .../archi/chips/vivosoc3_5/memory_map.h | 127 + .../archi/chips/vivosoc3_5/properties.h | 212 + .../include/archi/chips/vivosoc3_5/pulp.h | 39 + .../include/archi/chips/vivosoc4/apb_soc.h | 124 + .../archi/include/archi/chips/vivosoc4/fll.h | 125 + .../archi/include/archi/chips/vivosoc4/freq.h | 27 + .../include/archi/chips/vivosoc4/memory_map.h | 125 + .../include/archi/chips/vivosoc4/properties.h | 293 + .../archi/include/archi/chips/vivosoc4/pulp.h | 40 + .../archi/include/archi/chips/wolfe/apb_soc.h | 138 + .../archi/chips/wolfe/apb_soc_ctrl_new.h | 271 + .../include/archi/chips/wolfe/memory_map.h | 133 + .../archi/include/archi/chips/wolfe/pmu.h | 330 + .../include/archi/chips/wolfe/properties.h | 245 + .../archi/include/archi/chips/wolfe/pulp.h | 44 + .../archi/cluster_ctrl/cluster_ctrl_v2.h | 38 + .../archi/include/archi/dma/mchan_v3.h | 63 + .../archi/include/archi/dma/mchan_v5.h | 119 + .../archi/include/archi/dma/mchan_v6.h | 80 + .../archi/include/archi/dma/mchan_v7.h | 486 + .../archi/include/archi/efuse/efuse_v1.h | 28 + sw/pulp-sdk/archi/include/archi/eu/eu_v1.h | 82 + sw/pulp-sdk/archi/include/archi/eu/eu_v3.h | 206 + sw/pulp-sdk/archi/include/archi/fll/fll_v0.h | 25 + sw/pulp-sdk/archi/include/archi/fll/fll_v1.h | 231 + .../archi/include/archi/gpio/gpio_v2.h | 88 + .../archi/include/archi/gpio/gpio_v2_new.h | 1346 + .../archi/include/archi/gpio/gpio_v3.h | 992 + sw/pulp-sdk/archi/include/archi/gvsoc/gvsoc.h | 31 + .../archi/include/archi/hwce/hwce_v4.h | 1806 + .../archi/include/archi/hwce/hwce_v4_old.h | 133 + .../archi/include/archi/hwce/hwce_v5.h | 139 + .../archi/include/archi/hwme/hwme_v1.h | 91 + sw/pulp-sdk/archi/include/archi/itc/itc_v1.h | 268 + .../archi/include/archi/maestro/maestro_v1.h | 20 + .../include/archi/maestro/maestro_v1_new.h | 1472 + .../archi/include/archi/maestro/maestro_v2.h | 32 + .../include/archi/maestro/maestro_v2_new.h | 1472 + .../archi/include/archi/maestro/maestro_v3.h | 1545 + .../archi/include/archi/mailbox/mailbox_v0.h | 51 + .../archi/include/archi/or1k/spr-defs.h | 86 + sw/pulp-sdk/archi/include/archi/pulp.h | 34 + sw/pulp-sdk/archi/include/archi/pulp_defs.h | 90 + sw/pulp-sdk/archi/include/archi/pwm/pwm_v1.h | 84 + .../archi/include/archi/pwm/v1/pwm_v1.h | 41 + .../include/archi/pwm/v1/pwm_v1_accessors.h | 145 + .../include/archi/pwm/v1/pwm_v1_constants.h | 33 + .../include/archi/pwm/v1/pwm_v1_groups.h | 33 + .../archi/include/archi/pwm/v1/pwm_v1_gvsoc.h | 385 + .../include/archi/pwm/v1/pwm_v1_macros.h | 473 + .../include/archi/pwm/v1/pwm_v1_regfields.h | 469 + .../include/archi/pwm/v1/pwm_v1_regmap.h | 80 + .../archi/include/archi/pwm/v1/pwm_v1_regs.h | 141 + .../include/archi/pwm/v1/pwm_v1_structs.h | 337 + sw/pulp-sdk/archi/include/archi/rab/rab_v1.h | 52 + .../archi/include/archi/riscv/builtins_v2.h | 328 + .../include/archi/riscv/builtins_v2_emu.h | 347 + .../archi/include/archi/riscv/pcer_v1.h | 60 + .../archi/include/archi/riscv/pcer_v2.h | 56 + .../archi/include/archi/riscv/priv_1.9.h | 29 + .../archi/include/archi/riscv/priv_1_10.h | 55 + .../archi/include/archi/riscv/priv_1_7.h | 29 + .../archi/include/archi/riscv/priv_1_9.h | 55 + sw/pulp-sdk/archi/include/archi/rtc/rtc_v2.h | 473 + .../archi/include/archi/soc_eu/soc_eu_v1.h | 42 + .../archi/include/archi/soc_eu/soc_eu_v2.h | 61 + .../archi/include/archi/soc_eu/soc_eu_v3.h | 70 + sw/pulp-sdk/archi/include/archi/spim/spi_v1.h | 49 + .../archi/include/archi/stdout/stdout_v2.h | 25 + .../archi/include/archi/stdout/stdout_v3.h | 25 + .../archi/include/archi/timer/timer_v2.h | 617 + .../include/archi/udma/cpi/udma_cpi_v1.h | 614 + .../include/archi/udma/cpi/udma_cpi_v1_old.h | 151 + .../include/archi/udma/csi2/udma_csi2_v1.h | 35 + .../include/archi/udma/hyper/udma_hyper_v1.h | 195 + .../include/archi/udma/hyper/udma_hyper_v2.h | 999 + .../include/archi/udma/i2c/udma_i2c_v1.h | 33 + .../include/archi/udma/i2c/udma_i2c_v2.h | 32 + .../include/archi/udma/i2s/udma_i2s_v1.h | 242 + .../include/archi/udma/i2s/udma_i2s_v1_new.h | 786 + .../include/archi/udma/i2s/udma_i2s_v2.h | 808 + .../include/archi/udma/i2s/v3/udma_i2s_v3.h | 41 + .../archi/udma/i2s/v3/udma_i2s_v3_accessors.h | 79 + .../archi/udma/i2s/v3/udma_i2s_v3_constants.h | 33 + .../archi/udma/i2s/v3/udma_i2s_v3_groups.h | 33 + .../archi/udma/i2s/v3/udma_i2s_v3_gvsoc.h | 169 + .../archi/udma/i2s/v3/udma_i2s_v3_macros.h | 233 + .../archi/udma/i2s/v3/udma_i2s_v3_regfields.h | 229 + .../archi/udma/i2s/v3/udma_i2s_v3_regmap.h | 58 + .../archi/udma/i2s/v3/udma_i2s_v3_regs.h | 75 + .../archi/udma/i2s/v3/udma_i2s_v3_structs.h | 163 + .../archi/udma/memcpy/v1/udma_memcpy_v1.h | 41 + .../udma/memcpy/v1/udma_memcpy_v1_accessors.h | 70 + .../udma/memcpy/v1/udma_memcpy_v1_constants.h | 33 + .../udma/memcpy/v1/udma_memcpy_v1_groups.h | 33 + .../udma/memcpy/v1/udma_memcpy_v1_gvsoc.h | 118 + .../udma/memcpy/v1/udma_memcpy_v1_macros.h | 118 + .../udma/memcpy/v1/udma_memcpy_v1_regfields.h | 114 + .../udma/memcpy/v1/udma_memcpy_v1_regmap.h | 55 + .../udma/memcpy/v1/udma_memcpy_v1_regs.h | 66 + .../udma/memcpy/v1/udma_memcpy_v1_structs.h | 114 + .../include/archi/udma/mram/udma_mram_v1.h | 965 + .../include/archi/udma/spim/udma_spim_v1.h | 69 + .../include/archi/udma/spim/udma_spim_v2.h | 172 + .../include/archi/udma/spim/udma_spim_v3.h | 196 + .../include/archi/udma/tcdm/udma_tcdm_v1.h | 23 + .../include/archi/udma/uart/udma_uart_v1.h | 82 + .../archi/include/archi/udma/udma_v1.h | 125 + .../archi/include/archi/udma/udma_v2.h | 230 + .../archi/include/archi/udma/udma_v3.h | 176 + sw/pulp-sdk/archi/include/archi/utils.h | 74 + .../archi/include/archi/vendors/dolphin/rtc.h | 297 + .../include/archi/vendors/iid/quiddikey_v1.h | 459 + .../archi/include/archi/vendors/lnt/csi2_v1.h | 294 + sw/pulp-sdk/archi/include/archi/xne/xne_v1.h | 82 + sw/pulp-sdk/bin/rename_l2.py | 11 + sw/pulp-sdk/bin/slm_conv | Bin 0 -> 3186640 bytes sw/pulp-sdk/hal/.gitignore | 3 + sw/pulp-sdk/hal/LICENSE | 177 + sw/pulp-sdk/hal/Makefile | 8 + sw/pulp-sdk/hal/SConstruct | 125 + .../hal/include/hal/apb_soc/apb_soc_v1.h | 49 + .../hal/include/hal/apb_soc/apb_soc_v2.h | 92 + .../hal/include/hal/apb_soc/apb_soc_v3.h | 158 + .../hal/include/hal/apb_soc/apb_soc_v4.h | 156 + .../hal/include/hal/chips/arnold/pulp.h | 36 + .../hal/include/hal/chips/bigpulp/pulp.h | 32 + .../hal/include/hal/chips/devchip/pulp.h | 29 + .../hal/include/hal/chips/fulmine/pulp.h | 28 + .../hal/include/hal/chips/gap/apb_soc.h | 120 + sw/pulp-sdk/hal/include/hal/chips/gap/efuse.h | 492 + sw/pulp-sdk/hal/include/hal/chips/gap/pulp.h | 47 + sw/pulp-sdk/hal/include/hal/chips/gap8 | 1 + .../hal/include/hal/chips/gap9/efuse.h | 178 + sw/pulp-sdk/hal/include/hal/chips/gap9/pulp.h | 45 + .../hal/include/hal/chips/gap_rev1/efuse.h | 160 + .../hal/include/hal/chips/gap_rev1/pulp.h | 46 + sw/pulp-sdk/hal/include/hal/chips/honey/fll.h | 45 + .../hal/include/hal/chips/honey/pulp.h | 31 + .../hal/include/hal/chips/multino/pulp.h | 32 + .../hal/include/hal/chips/neuraghe/pulp.h | 25 + .../hal/include/hal/chips/oprecompkw/pulp.h | 29 + sw/pulp-sdk/hal/include/hal/chips/pulp/pulp.h | 39 + .../hal/include/hal/chips/pulp_v1/pulp.h | 40 + .../hal/include/hal/chips/pulpissimo/pulp.h | 36 + .../include/hal/chips/pulpissimo_v1/pulp.h | 37 + .../hal/include/hal/chips/quentin/pulp.h | 31 + .../hal/include/hal/chips/usoc_v1/apb_soc.h | 76 + .../hal/include/hal/chips/usoc_v1/gpio.h | 113 + .../hal/include/hal/chips/usoc_v1/pulp.h | 34 + .../hal/include/hal/chips/vega/efuse.h | 178 + sw/pulp-sdk/hal/include/hal/chips/vega/pulp.h | 45 + .../hal/include/hal/chips/vivosoc2/pulp.h | 28 + .../hal/include/hal/chips/vivosoc2_1/pulp.h | 28 + .../hal/include/hal/chips/vivosoc3/fll.h | 108 + .../hal/include/hal/chips/vivosoc3/freq.h | 69 + .../hal/include/hal/chips/vivosoc3/pulp.h | 40 + .../hal/include/hal/chips/vivosoc3_1/fll.h | 108 + .../hal/include/hal/chips/vivosoc3_1/freq.h | 69 + .../hal/include/hal/chips/vivosoc3_1/pulp.h | 40 + .../hal/include/hal/chips/vivosoc3_5/fll.h | 108 + .../hal/include/hal/chips/vivosoc3_5/freq.h | 69 + .../hal/include/hal/chips/vivosoc3_5/pulp.h | 40 + .../hal/include/hal/chips/vivosoc4/fll.h | 108 + .../hal/include/hal/chips/vivosoc4/freq.h | 69 + .../hal/include/hal/chips/vivosoc4/pulp.h | 40 + .../hal/include/hal/chips/wolfe/pulp.h | 43 + .../hal/cluster_ctrl/cluster_ctrl_v2.h | 66 + .../include/hal/debug_bridge/debug_bridge.h | 176 + sw/pulp-sdk/hal/include/hal/dma/mchan_v4.h | 39 + sw/pulp-sdk/hal/include/hal/dma/mchan_v5.h | 222 + sw/pulp-sdk/hal/include/hal/dma/mchan_v6.h | 438 + sw/pulp-sdk/hal/include/hal/dma/mchan_v7.h | 427 + sw/pulp-sdk/hal/include/hal/efuse/efuse_v1.h | 58 + sw/pulp-sdk/hal/include/hal/eu/eu_v1.h | 262 + sw/pulp-sdk/hal/include/hal/eu/eu_v1_ids.h | 62 + sw/pulp-sdk/hal/include/hal/eu/eu_v3.h | 609 + sw/pulp-sdk/hal/include/hal/fll/fll_v1.h | 166 + sw/pulp-sdk/hal/include/hal/gpio/gpio_v0.h | 77 + sw/pulp-sdk/hal/include/hal/gpio/gpio_v2.h | 161 + sw/pulp-sdk/hal/include/hal/gpio/gpio_v3.h | 192 + sw/pulp-sdk/hal/include/hal/gvsoc/gvsoc.h | 104 + sw/pulp-sdk/hal/include/hal/hwce/hwce_v4.h | 321 + sw/pulp-sdk/hal/include/hal/hwce/hwce_v5.h | 263 + sw/pulp-sdk/hal/include/hal/hwme/hwme_v1.h | 168 + .../hal/include/hal/icache/icache_ctrl_v1.h | 156 + .../hal/include/hal/icache/icache_ctrl_v2.h | 135 + sw/pulp-sdk/hal/include/hal/itc/itc_v1.h | 116 + sw/pulp-sdk/hal/include/hal/maestro/pmu_v1.h | 337 + sw/pulp-sdk/hal/include/hal/maestro/pmu_v2.h | 31 + sw/pulp-sdk/hal/include/hal/maestro/pmu_v3.h | 119 + .../hal/include/hal/mailbox/mailbox_v0.h | 78 + .../hal/include/hal/or1k/or10nv2_builtins.h | 53 + sw/pulp-sdk/hal/include/hal/or1k/or1k_v5.h | 241 + sw/pulp-sdk/hal/include/hal/periph/spi_v1.h | 78 + sw/pulp-sdk/hal/include/hal/pulp.h | 32 + sw/pulp-sdk/hal/include/hal/pulp_io.h | 84 + sw/pulp-sdk/hal/include/hal/pwm/pwm_v1.h | 184 + sw/pulp-sdk/hal/include/hal/rab/rab_v1.h | 381 + .../hal/include/hal/riscv/builtins_v2.h | 324 + .../hal/include/hal/riscv/builtins_v2_emu.h | 347 + sw/pulp-sdk/hal/include/hal/riscv/riscv_v3.h | 208 + sw/pulp-sdk/hal/include/hal/riscv/riscv_v4.h | 648 + sw/pulp-sdk/hal/include/hal/riscv/riscv_v5.h | 669 + sw/pulp-sdk/hal/include/hal/riscv/types.h | 35 + sw/pulp-sdk/hal/include/hal/rom/rom_v2.h | 61 + sw/pulp-sdk/hal/include/hal/rtc/rtc_v2.h | 29 + .../hal/include/hal/soc_eu/soc_eu_v1.h | 90 + .../hal/include/hal/soc_eu/soc_eu_v2.h | 107 + .../hal/include/hal/soc_eu/soc_eu_v3.h | 107 + sw/pulp-sdk/hal/include/hal/tb/tb.h | 104 + sw/pulp-sdk/hal/include/hal/timer/timer_v1.h | 98 + sw/pulp-sdk/hal/include/hal/timer/timer_v2.h | 97 + sw/pulp-sdk/hal/include/hal/tryx/tryx_v1.h | 174 + .../hal/include/hal/udma/cpi/udma_cpi_v1.h | 191 + .../hal/include/hal/udma/csi2/udma_csi2_v1.h | 53 + .../include/hal/udma/hyper/udma_hyper_v1.h | 589 + .../include/hal/udma/hyper/udma_hyper_v2.h | 108 + .../hal/include/hal/udma/i2c/udma_i2c_v1.h | 37 + .../hal/include/hal/udma/i2c/udma_i2c_v2.h | 30 + .../hal/include/hal/udma/i2s/udma_i2s_v1.h | 95 + .../hal/include/hal/udma/spim/udma_spim_v1.h | 78 + .../hal/include/hal/udma/spim/udma_spim_v2.h | 22 + .../hal/include/hal/udma/spim/udma_spim_v3.h | 28 + .../hal/include/hal/udma/tcdm/udma_tcdm_v1.h | 50 + .../hal/include/hal/udma/uart/udma_uart_v1.h | 151 + sw/pulp-sdk/hal/include/hal/udma/udma_v1.h | 57 + sw/pulp-sdk/hal/include/hal/udma/udma_v2.h | 268 + sw/pulp-sdk/hal/include/hal/udma/udma_v3.h | 266 + sw/pulp-sdk/hal/include/hal/utils.h | 123 + .../hal/include/hal/vendors/dolphin/rtc.h | 45 + .../include/hal/vendors/iid/quiddikey_v1.h | 372 + .../hal/include/hal/vendors/lnt/csi2_v1.h | 338 + sw/pulp-sdk/hal/include/hal/xne/xne_v1.h | 230 + sw/pulp-sdk/hal/src/hal/mailbox/mailbox_v0.c | 80 + sw/pulp-sdk/hal/src/hal/rab/rab_v1.c | 68 + sw/pulp-sdk/hal/src/hal/tryx/tryx_v1.c | 40 + sw/pulp-sdk/kernel/riscv/rt/crt0.S | 129 + sw/pulp-sdk/linker/config.ld | 25 + sw/pulp-sdk/linker/link.ld | 170 + sw/pulp-sdk/runtime/libs/io/io.c | 151 + sw/pulp-sdk/runtime/libs/io/tinyprintf.c | 539 + sw/pulp-sdk/runtime/libs/io/tinyprintf.h | 206 + sw/pulp-sdk/scripts/s19toslm.py | 209 + sw/rules/spin-handlers.mk | 92 + sw/rules/spin-rt.mk | 52 + sw/runtime/include/handler.h | 286 + sw/runtime/include/hwsched.h | 39 + sw/runtime/include/libaxidma.h | 155 + sw/runtime/include/packets.h | 49 + sw/runtime/include/pspin.h | 258 + sw/runtime/include/pspin_rt.h | 48 + sw/runtime/include/spin_conf.h | 27 + sw/runtime/include/spin_dma.h | 121 + sw/runtime/include/util.h | 69 + sw/runtime/src/handler.c | 220 + sw/runtime/src/hpu.c | 127 + sw/runtime/src/hpu.h | 8 + sw/runtime/src/main.c | 74 + sw/runtime/src/spin_dma.h | 119 + sw/scripts/benchmark.py | 154 + sw/scripts/extract_info.sh | 11 + sw/scripts/handlers_data.sh | 112 + sw/scripts/handlers_duration.sh | 21 + sw/scripts/inspect_trace.py | 107 + sw/scripts/make_packets.sh | 27 + sw/scripts/telemetry.sh | 73 + sw/scripts/telemetry_instructions_tracevis.sh | 109 + sw/scripts/telemetry_time_tracevis.sh | 39 + sw/scripts/tracevis/README.md | 38 + .../tracevis/example/bin/pulp_api_example | Bin 0 -> 244496 bytes sw/scripts/tracevis/example/chrome.json | 30955 ++++++++++++++++ .../example/traces/trace_core_00_0.log | 4559 +++ .../example/traces/trace_core_00_1.log | 847 + .../example/traces/trace_core_00_2.log | 847 + .../example/traces/trace_core_00_3.log | 847 + .../example/traces/trace_core_00_4.log | 847 + .../example/traces/trace_core_00_5.log | 847 + .../example/traces/trace_core_00_6.log | 847 + .../example/traces/trace_core_00_7.log | 847 + .../example/traces/trace_core_01_0.log | 921 + .../example/traces/trace_core_01_1.log | 846 + .../example/traces/trace_core_01_2.log | 846 + .../example/traces/trace_core_01_3.log | 846 + .../example/traces/trace_core_01_4.log | 846 + .../example/traces/trace_core_01_5.log | 846 + .../example/traces/trace_core_01_6.log | 846 + .../example/traces/trace_core_01_7.log | 846 + .../example/traces/trace_core_02_0.log | 921 + .../example/traces/trace_core_02_1.log | 846 + .../example/traces/trace_core_02_2.log | 846 + .../example/traces/trace_core_02_3.log | 846 + .../example/traces/trace_core_02_4.log | 846 + .../example/traces/trace_core_02_5.log | 846 + .../example/traces/trace_core_02_6.log | 846 + .../example/traces/trace_core_02_7.log | 846 + .../example/traces/trace_core_03_0.log | 921 + .../example/traces/trace_core_03_1.log | 846 + .../example/traces/trace_core_03_2.log | 846 + .../example/traces/trace_core_03_3.log | 846 + .../example/traces/trace_core_03_4.log | 846 + .../example/traces/trace_core_03_5.log | 846 + .../example/traces/trace_core_03_6.log | 846 + .../example/traces/trace_core_03_7.log | 846 + sw/scripts/tracevis/parse.pl | 204 + 682 files changed, 194410 insertions(+) create mode 100644 examples/aggregate/Makefile create mode 100644 examples/aggregate/handlers/aggregate_global.c create mode 100644 examples/copy_from_host/Makefile create mode 100644 examples/copy_from_host/handlers/copy_from_host.c create mode 100644 examples/copy_to_host/Makefile create mode 100644 examples/copy_to_host/handlers/copy_to_host.c create mode 100644 examples/empty/Makefile create mode 100644 examples/empty/handlers/empty.c create mode 100644 examples/filtering/Makefile create mode 100644 examples/filtering/handlers/filtering.c create mode 100644 examples/hashtable_fun/Makefile create mode 100644 examples/hashtable_fun/driver/htable_driver.c create mode 100644 examples/hashtable_fun/handlers/htable_handlers.c create mode 100644 examples/histogram/Makefile create mode 100644 examples/histogram/handlers/histogram_l1.c create mode 100644 examples/host_direct/Makefile create mode 100644 examples/host_direct/handlers/hostdirect.c create mode 100644 examples/ping_pong/Makefile create mode 100644 examples/ping_pong/handlers/ping_pong.c create mode 100644 examples/reduce/Makefile create mode 100644 examples/reduce/handlers/reduce_l1.c create mode 100644 hw/deps/apb/src/apb_intf.sv create mode 100644 hw/deps/axi/src/axi_atop_filter.sv create mode 100644 hw/deps/axi/src/axi_buf.sv create mode 100644 hw/deps/axi/src/axi_cut.sv create mode 100644 hw/deps/axi/src/axi_demux.sv create mode 100644 hw/deps/axi/src/axi_dw_converter.sv create mode 100644 hw/deps/axi/src/axi_dw_downsizer.sv create mode 100644 hw/deps/axi/src/axi_dw_upsizer.sv create mode 100644 hw/deps/axi/src/axi_err_slv.sv create mode 100644 hw/deps/axi/src/axi_id_prepend.sv create mode 100644 hw/deps/axi/src/axi_id_remap.sv create mode 100644 hw/deps/axi/src/axi_intf.sv create mode 100644 hw/deps/axi/src/axi_mux.sv create mode 100644 hw/deps/axi/src/axi_pkg.sv create mode 100644 hw/deps/axi/src/axi_serializer.sv create mode 100644 hw/deps/axi/src/axi_xbar.sv create mode 100644 hw/deps/axi/src/dma/axi_dma_backend.sv create mode 100644 hw/deps/axi/src/dma/axi_dma_burst_reshaper.sv create mode 100644 hw/deps/axi/src/dma/axi_dma_data_mover.sv create mode 100644 hw/deps/axi/src/dma/axi_dma_data_path.sv create mode 100644 hw/deps/axi/src/dma/frontends/pspin_soc_frontend/src/pspin_soc_dma.sv create mode 100644 hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend.sv create mode 100644 hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend_regs.sv create mode 100644 hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/transfer_id_gen.sv create mode 100644 hw/deps/axi2apb/src/axi2apb_64_32.sv create mode 100644 hw/deps/axi2apb/src/axi2apb_wrap.sv create mode 100644 hw/deps/axi2mem/src/axi_to_mem.sv create mode 100644 hw/deps/axi2mem/src/axi_to_mem_banked_mp.sv create mode 100644 hw/deps/axi2mem/src/axi_to_mem_interleaved.sv create mode 100644 hw/deps/axi2per/axi2per.sv create mode 100644 hw/deps/axi2per/axi2per_req_channel.sv create mode 100644 hw/deps/axi2per/axi2per_res_channel.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_res_tbl.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_riscv_amos.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_riscv_amos_alu.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_riscv_atomics.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv create mode 100644 hw/deps/axi_riscv_atomics/src/axi_riscv_lrsc.sv create mode 100644 hw/deps/axi_slice/src/axi_ar_buffer.sv create mode 100644 hw/deps/axi_slice/src/axi_aw_buffer.sv create mode 100644 hw/deps/axi_slice/src/axi_b_buffer.sv create mode 100644 hw/deps/axi_slice/src/axi_r_buffer.sv create mode 100644 hw/deps/axi_slice/src/axi_single_slice.sv create mode 100644 hw/deps/axi_slice/src/axi_w_buffer.sv create mode 100644 hw/deps/axi_slice_dc/src/dc_synchronizer.v create mode 100644 hw/deps/axi_slice_dc/src/dc_token_ring.v create mode 100644 hw/deps/axi_slice_dc/src/dc_token_ring_fifo_dout.v create mode 100644 hw/deps/cluster_interconnect/rtl/interfaces/tcdm_bank_mem_bus.sv create mode 100644 hw/deps/cluster_interconnect/rtl/interfaces/wide_dma_tcdm.sv create mode 100644 hw/deps/cluster_interconnect/rtl/interfaces/xbar_demux_bus.sv create mode 100644 hw/deps/cluster_interconnect/rtl/interfaces/xbar_periph_bus.sv create mode 100644 hw/deps/cluster_interconnect/rtl/interfaces/xbar_tcdm_bus.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_PE_Req.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_Resp_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/ArbitrationTree_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_PE_Resp.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_Req_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/MUX2_REQ_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/RR_Flag_Req_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/RequestBlock2CH_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseBlock_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseTree_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/peripheral_interco/XBAR_PE.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/addr_dec_resp_mux.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/amo_shim.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/superbank_addr_decoder.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect_pkg.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_superbank_mux.sv create mode 100644 hw/deps/cluster_interconnect/rtl/tcdm_interconnect/xbar.sv create mode 100644 hw/deps/cluster_peripherals/cluster_control_unit/cluster_control_unit.sv create mode 100644 hw/deps/cluster_peripherals/icache_ctrl_unit/interfaces/mp_pf_icache_ctrl_unit_bus.sv create mode 100644 hw/deps/cluster_peripherals/icache_ctrl_unit/mp_pf_icache_ctrl_unit.sv create mode 100644 hw/deps/common_cells/src/addr_decode.sv create mode 100644 hw/deps/common_cells/src/cf_math_pkg.sv create mode 100644 hw/deps/common_cells/src/counter.sv create mode 100644 hw/deps/common_cells/src/delta_counter.sv create mode 100644 hw/deps/common_cells/src/deprecated/fifo_v1.sv create mode 100644 hw/deps/common_cells/src/deprecated/fifo_v2.sv create mode 100644 hw/deps/common_cells/src/deprecated/generic_LFSR_8bit.sv create mode 100644 hw/deps/common_cells/src/deprecated/generic_fifo.sv create mode 100644 hw/deps/common_cells/src/edge_propagator_tx.sv create mode 100644 hw/deps/common_cells/src/fall_through_register.sv create mode 100644 hw/deps/common_cells/src/fifo_v3.sv create mode 100644 hw/deps/common_cells/src/id_queue.sv create mode 100644 hw/deps/common_cells/src/lzc.sv create mode 100644 hw/deps/common_cells/src/onehot_to_bin.sv create mode 100644 hw/deps/common_cells/src/rr_arb_tree.sv create mode 100644 hw/deps/common_cells/src/rstgen.sv create mode 100644 hw/deps/common_cells/src/rstgen_bypass.sv create mode 100644 hw/deps/common_cells/src/spill_register.sv create mode 100644 hw/deps/common_cells/src/stream_arbiter.sv create mode 100644 hw/deps/common_cells/src/stream_arbiter_flushable.sv create mode 100644 hw/deps/common_cells/src/stream_demux.sv create mode 100644 hw/deps/common_cells/src/stream_fifo.sv create mode 100644 hw/deps/common_cells/src/stream_filter.sv create mode 100644 hw/deps/common_cells/src/stream_fork.sv create mode 100644 hw/deps/common_cells/src/stream_fork_dynamic.sv create mode 100644 hw/deps/common_cells/src/stream_join.sv create mode 100644 hw/deps/common_cells/src/stream_mux.sv create mode 100644 hw/deps/common_cells/src/stream_register.sv create mode 100644 hw/deps/common_cells/src/stream_to_mem.sv create mode 100644 hw/deps/event_unit_flex/event_unit_core.sv create mode 100644 hw/deps/event_unit_flex/event_unit_interface_mux.sv create mode 100644 hw/deps/event_unit_flex/event_unit_top.sv create mode 100644 hw/deps/event_unit_flex/hw_barrier_unit.sv create mode 100644 hw/deps/event_unit_flex/hw_dispatch.sv create mode 100755 hw/deps/event_unit_flex/hw_mutex_unit.sv create mode 100644 hw/deps/event_unit_flex/interc_sw_evt_trig.sv create mode 100644 hw/deps/event_unit_flex/message_bus.sv create mode 100644 hw/deps/icache-intc/DistributedArbitrationNetwork_Req_icache_intc.sv create mode 100644 hw/deps/icache-intc/DistributedArbitrationNetwork_Resp_icache_intc.sv create mode 100644 hw/deps/icache-intc/Req_Arb_Node_icache_intc.sv create mode 100644 hw/deps/icache-intc/RoutingBlock_Req_icache_intc.sv create mode 100644 hw/deps/icache-intc/RoutingBlock_Resp_icache_intc.sv create mode 100644 hw/deps/icache-intc/icache_intc.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/cache_controller_to_axi_128_PF.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/central_controller_128.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/icache_bank_mp_128.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/icache_bank_mp_PF.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/icache_top_mp_128_PF.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/merge_refill_cam_128_16.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/pf_miss_mux.sv create mode 100644 hw/deps/icache_mp_128_pf/RTL/prefetcher_if.sv create mode 100644 hw/deps/per2axi/src/per2axi.sv create mode 100644 hw/deps/per2axi/src/per2axi_busy_unit.sv create mode 100644 hw/deps/per2axi/src/per2axi_req_channel.sv create mode 100644 hw/deps/per2axi/src/per2axi_res_channel.sv create mode 100644 hw/deps/pulp_cluster/packages/apu_package.sv create mode 100644 hw/deps/pulp_cluster/packages/pulp_cluster_package.sv create mode 100644 hw/deps/pulp_cluster/rtl/axi2per_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/cluster_bus_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/cluster_event_map.sv create mode 100644 hw/deps/pulp_cluster/rtl/cluster_interconnect_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/cluster_peripherals.sv create mode 100644 hw/deps/pulp_cluster/rtl/cluster_timer_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/core_demux.sv create mode 100644 hw/deps/pulp_cluster/rtl/core_region.sv create mode 100644 hw/deps/pulp_cluster/rtl/cpu_marx_if.sv create mode 100644 hw/deps/pulp_cluster/rtl/dmac_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/inter_core_fifo.sv create mode 100644 hw/deps/pulp_cluster/rtl/nhi_port_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/per2axi_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/per_demux_wrap.sv create mode 100644 hw/deps/pulp_cluster/rtl/periph_FIFO.sv create mode 100644 hw/deps/pulp_cluster/rtl/periph_demux.sv create mode 100644 hw/deps/pulp_cluster/rtl/pulp_cluster.sv create mode 100644 hw/deps/pulp_cluster/rtl/tryx_ctrl.sv create mode 100644 hw/deps/pulp_cluster/rtl/virtual_stdout_demux.sv create mode 100644 hw/deps/riscv/include/apu_core_package.sv create mode 100644 hw/deps/riscv/include/fpnew_pkg.sv create mode 100644 hw/deps/riscv/include/riscv_defines.sv create mode 100644 hw/deps/riscv/include/riscv_tracer_defines.sv create mode 100644 hw/deps/riscv/riscv_L0_buffer.sv create mode 100644 hw/deps/riscv/riscv_alu.sv create mode 100644 hw/deps/riscv/riscv_alu_div.sv create mode 100644 hw/deps/riscv/riscv_apu_disp.sv create mode 100644 hw/deps/riscv/riscv_compressed_decoder.sv create mode 100644 hw/deps/riscv/riscv_controller.sv create mode 100644 hw/deps/riscv/riscv_core.sv create mode 100644 hw/deps/riscv/riscv_cs_registers.sv create mode 100644 hw/deps/riscv/riscv_decoder.sv create mode 100644 hw/deps/riscv/riscv_ex_stage.sv create mode 100644 hw/deps/riscv/riscv_ff_one.sv create mode 100644 hw/deps/riscv/riscv_hwloop_controller.sv create mode 100644 hw/deps/riscv/riscv_hwloop_regs.sv create mode 100644 hw/deps/riscv/riscv_id_stage.sv create mode 100644 hw/deps/riscv/riscv_if_stage.sv create mode 100644 hw/deps/riscv/riscv_int_controller.sv create mode 100644 hw/deps/riscv/riscv_load_store_unit.sv create mode 100644 hw/deps/riscv/riscv_mult.sv create mode 100644 hw/deps/riscv/riscv_pmp.sv create mode 100644 hw/deps/riscv/riscv_popcnt.sv create mode 100644 hw/deps/riscv/riscv_prefetch_L0_buffer.sv create mode 100644 hw/deps/riscv/riscv_register_file.sv create mode 100644 hw/deps/riscv/riscv_store_buffer.sv create mode 100644 hw/deps/riscv/riscv_tracer.sv create mode 100644 hw/deps/riscv/verilator-model/cluster_clock_gating.sv create mode 100644 hw/deps/scm/latch_scm/register_file_1w_multi_port_read.sv create mode 100644 hw/deps/tech_cells_generic/src/rtl/tc_sram.sv create mode 100644 hw/deps/timer_unit/rtl/timer_unit.sv create mode 100644 hw/deps/timer_unit/rtl/timer_unit_counter.sv create mode 100644 hw/deps/timer_unit/rtl/timer_unit_counter_presc.sv create mode 100644 hw/src/apb/apb_bus.sv create mode 100644 hw/src/apb/apb_bus_wrap.sv create mode 100644 hw/src/apb/apb_ro_regs.sv create mode 100644 hw/src/apb/apb_rw_regs.sv create mode 100644 hw/src/apb/apb_stdout.sv create mode 100644 hw/src/cmds/cluster_cmd.sv create mode 100644 hw/src/cmds/cmd_unit.sv create mode 100644 hw/src/host_direct.sv create mode 100644 hw/src/host_mst_mux.sv create mode 100644 hw/src/interconnects/cluster_noc.sv create mode 100644 hw/src/interconnects/dma_noc.sv create mode 100644 hw/src/interconnects/l2_xbar.sv create mode 100644 hw/src/interconnects/nhi_xbar.sv create mode 100644 hw/src/interconnects/pe_noc.sv create mode 100644 hw/src/memories/l2_mem.sv create mode 100644 hw/src/memories/prog_mem.sv create mode 100644 hw/src/memories/sram.sv create mode 100644 hw/src/pkt_scheduler/cluster_rb.sv create mode 100644 hw/src/pkt_scheduler/cluster_scheduler.sv create mode 100644 hw/src/pkt_scheduler/fifo_engine.sv create mode 100644 hw/src/pkt_scheduler/hpu_driver.sv create mode 100644 hw/src/pkt_scheduler/mpq_engine.sv create mode 100644 hw/src/pkt_scheduler/scheduler.sv create mode 100644 hw/src/pspin.sv create mode 100644 hw/src/pspin_cfg_pkg.sv create mode 100644 hw/src/pspin_verilator.sv create mode 100644 hw/src/pulp_cluster_cfg_pkg.sv create mode 100644 hw/src/pulp_cluster_ooc.sv create mode 100644 hw/src/soc_ctrl_regs.sv create mode 100644 hw/src/soc_dma_wrap.sv create mode 100644 hw/src/soc_peripherals.sv create mode 100644 hw/verilator_model/Makefile create mode 100644 hw/verilator_model/include/pspinsim.h create mode 100644 hw/verilator_model/include/spin.h create mode 100644 hw/verilator_model/include/spin_hw_conf.h create mode 100644 hw/verilator_model/src/AXIDriver.hpp create mode 100644 hw/verilator_model/src/AXIMaster.hpp create mode 100644 hw/verilator_model/src/AXIPort.hpp create mode 100644 hw/verilator_model/src/AXISlave.hpp create mode 100644 hw/verilator_model/src/NICInbound.hpp create mode 100644 hw/verilator_model/src/NICOutbound.hpp create mode 100644 hw/verilator_model/src/PCIe.hpp create mode 100644 hw/verilator_model/src/PCIeMaster.hpp create mode 100644 hw/verilator_model/src/PCIeSlave.hpp create mode 100644 hw/verilator_model/src/SimControl.hpp create mode 100644 hw/verilator_model/src/SimModule.hpp create mode 100644 hw/verilator_model/src/main.cpp create mode 100644 hw/verilator_model/src/pspin.hpp create mode 100644 hw/verilator_model/src/pspinsim.cpp create mode 100755 hw/verilator_model/start_sim.sh create mode 100644 sourceme-template.sh create mode 100644 sw/pulp-sdk/archi/.gitignore create mode 100644 sw/pulp-sdk/archi/LICENSE create mode 100644 sw/pulp-sdk/archi/Makefile create mode 100644 sw/pulp-sdk/archi/SConstruct create mode 120000 sw/pulp-sdk/archi/doc/APB_GPIO_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/CL_EVENT_UNIT_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/FC_EVENT_UNIT_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/HYPER_V2_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/PULPISSIMO_APB_SOC_CTRL_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/RTC_UNIT_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/TIMER_UNIT_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/WOLFE_APB_SOC_CTRL_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/gap/APB_SOC_CTRL_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/gpio/APB_GPIO_V3_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/hwce/HWCE_v4_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/hwce/HWCE_v5_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/mchan/CL_DMA_v7_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/pwm/pwm_v1.xlsx create mode 120000 sw/pulp-sdk/archi/doc/udma/CAM_CPI_V1_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/udma/MEMCPY_v1_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/udma/MRAM_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/udma/i2s/I2S_V1_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/udma/i2s/I2S_V2_reference.xlsx create mode 100644 sw/pulp-sdk/archi/doc/udma/i2s/I2S_V3_reference.xlsx create mode 120000 sw/pulp-sdk/archi/doc/vega/APB_SOC_CTRL_reference.xlsx create mode 100644 sw/pulp-sdk/archi/include/archi/chips/arnold/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/arnold/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/arnold/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/arnold/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/bigpulp/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/bigpulp/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/bigpulp/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/bigpulp/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/devchip/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/devchip/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/devchip/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/devchip/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/fulmine/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/fulmine/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/fulmine/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/fulmine/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap/padframe.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/apb_soc_ctrl.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/memory_map.h.in create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/pmu.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/gap9/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/honey/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/honey/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/honey/padframe.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/honey/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/honey/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/multino/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/multino/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/multino/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/multino/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/neuraghe/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/neuraghe/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/neuraghe/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/oprecompkw/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/oprecompkw/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/oprecompkw/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/oprecompkw/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp/apb_soc_ctrl.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp_v1/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp_v1/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp_v1/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulp_v1/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo/apb_soc_ctrl.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/quentin/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/quentin/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/quentin/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/quentin/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/usoc_v1/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/usoc_v1/gpio.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/usoc_v1/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/usoc_v1/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/usoc_v1/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/apb_soc_ctrl.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/memory_map.h.in create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/pmu.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vega/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2_1/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2_1/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc2_1/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/fll.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/freq.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/fll.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/freq.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/memory_map.h create mode 100755 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/fll.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/freq.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/fll.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/freq.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/memory_map.h create mode 100755 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/vivosoc4/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/apb_soc.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/apb_soc_ctrl_new.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/memory_map.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/pmu.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/properties.h create mode 100644 sw/pulp-sdk/archi/include/archi/chips/wolfe/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/cluster_ctrl/cluster_ctrl_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/dma/mchan_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/dma/mchan_v5.h create mode 100644 sw/pulp-sdk/archi/include/archi/dma/mchan_v6.h create mode 100644 sw/pulp-sdk/archi/include/archi/dma/mchan_v7.h create mode 100644 sw/pulp-sdk/archi/include/archi/efuse/efuse_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/eu/eu_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/eu/eu_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/fll/fll_v0.h create mode 100644 sw/pulp-sdk/archi/include/archi/fll/fll_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/gpio/gpio_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/gpio/gpio_v2_new.h create mode 100644 sw/pulp-sdk/archi/include/archi/gpio/gpio_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/gvsoc/gvsoc.h create mode 100644 sw/pulp-sdk/archi/include/archi/hwce/hwce_v4.h create mode 100644 sw/pulp-sdk/archi/include/archi/hwce/hwce_v4_old.h create mode 100644 sw/pulp-sdk/archi/include/archi/hwce/hwce_v5.h create mode 100644 sw/pulp-sdk/archi/include/archi/hwme/hwme_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/itc/itc_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/maestro/maestro_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/maestro/maestro_v1_new.h create mode 100644 sw/pulp-sdk/archi/include/archi/maestro/maestro_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/maestro/maestro_v2_new.h create mode 100644 sw/pulp-sdk/archi/include/archi/maestro/maestro_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/mailbox/mailbox_v0.h create mode 100644 sw/pulp-sdk/archi/include/archi/or1k/spr-defs.h create mode 100644 sw/pulp-sdk/archi/include/archi/pulp.h create mode 100644 sw/pulp-sdk/archi/include/archi/pulp_defs.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/pwm_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_accessors.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_constants.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_groups.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_gvsoc.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_macros.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regfields.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regmap.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regs.h create mode 100644 sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_structs.h create mode 100644 sw/pulp-sdk/archi/include/archi/rab/rab_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/builtins_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/builtins_v2_emu.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/pcer_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/pcer_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/priv_1.9.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/priv_1_10.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/priv_1_7.h create mode 100644 sw/pulp-sdk/archi/include/archi/riscv/priv_1_9.h create mode 100644 sw/pulp-sdk/archi/include/archi/rtc/rtc_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/spim/spi_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/stdout/stdout_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/stdout/stdout_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/timer/timer_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1_old.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/csi2/udma_csi2_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1_new.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_accessors.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_constants.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_groups.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_gvsoc.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_macros.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regfields.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regmap.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regs.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_structs.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_accessors.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_constants.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_groups.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_gvsoc.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_macros.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regfields.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regmap.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regs.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_structs.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/mram/udma_mram_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/tcdm/udma_tcdm_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/uart/udma_uart_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/udma_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/udma_v2.h create mode 100644 sw/pulp-sdk/archi/include/archi/udma/udma_v3.h create mode 100644 sw/pulp-sdk/archi/include/archi/utils.h create mode 100644 sw/pulp-sdk/archi/include/archi/vendors/dolphin/rtc.h create mode 100644 sw/pulp-sdk/archi/include/archi/vendors/iid/quiddikey_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/vendors/lnt/csi2_v1.h create mode 100644 sw/pulp-sdk/archi/include/archi/xne/xne_v1.h create mode 100644 sw/pulp-sdk/bin/rename_l2.py create mode 100755 sw/pulp-sdk/bin/slm_conv create mode 100644 sw/pulp-sdk/hal/.gitignore create mode 100644 sw/pulp-sdk/hal/LICENSE create mode 100644 sw/pulp-sdk/hal/Makefile create mode 100644 sw/pulp-sdk/hal/SConstruct create mode 100644 sw/pulp-sdk/hal/include/hal/apb_soc/apb_soc_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/apb_soc/apb_soc_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/apb_soc/apb_soc_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/apb_soc/apb_soc_v4.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/arnold/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/bigpulp/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/devchip/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/fulmine/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap/apb_soc.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap/efuse.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap/pulp.h create mode 120000 sw/pulp-sdk/hal/include/hal/chips/gap8 create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap9/efuse.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap9/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap_rev1/efuse.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/gap_rev1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/honey/fll.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/honey/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/multino/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/neuraghe/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/oprecompkw/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/pulp/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/pulp_v1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/pulpissimo/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/pulpissimo_v1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/quentin/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/usoc_v1/apb_soc.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/usoc_v1/gpio.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/usoc_v1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vega/efuse.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vega/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc2/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc2_1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3/fll.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3/freq.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_1/fll.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_1/freq.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_1/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_5/fll.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_5/freq.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc3_5/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc4/fll.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc4/freq.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/vivosoc4/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/chips/wolfe/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/cluster_ctrl/cluster_ctrl_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/debug_bridge/debug_bridge.h create mode 100644 sw/pulp-sdk/hal/include/hal/dma/mchan_v4.h create mode 100644 sw/pulp-sdk/hal/include/hal/dma/mchan_v5.h create mode 100644 sw/pulp-sdk/hal/include/hal/dma/mchan_v6.h create mode 100644 sw/pulp-sdk/hal/include/hal/dma/mchan_v7.h create mode 100644 sw/pulp-sdk/hal/include/hal/efuse/efuse_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/eu/eu_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/eu/eu_v1_ids.h create mode 100644 sw/pulp-sdk/hal/include/hal/eu/eu_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/fll/fll_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/gpio/gpio_v0.h create mode 100644 sw/pulp-sdk/hal/include/hal/gpio/gpio_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/gpio/gpio_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/gvsoc/gvsoc.h create mode 100644 sw/pulp-sdk/hal/include/hal/hwce/hwce_v4.h create mode 100644 sw/pulp-sdk/hal/include/hal/hwce/hwce_v5.h create mode 100644 sw/pulp-sdk/hal/include/hal/hwme/hwme_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/icache/icache_ctrl_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/icache/icache_ctrl_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/itc/itc_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/maestro/pmu_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/maestro/pmu_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/maestro/pmu_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/mailbox/mailbox_v0.h create mode 100644 sw/pulp-sdk/hal/include/hal/or1k/or10nv2_builtins.h create mode 100644 sw/pulp-sdk/hal/include/hal/or1k/or1k_v5.h create mode 100644 sw/pulp-sdk/hal/include/hal/periph/spi_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/pulp.h create mode 100644 sw/pulp-sdk/hal/include/hal/pulp_io.h create mode 100644 sw/pulp-sdk/hal/include/hal/pwm/pwm_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/rab/rab_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/builtins_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/builtins_v2_emu.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/riscv_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/riscv_v4.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/riscv_v5.h create mode 100644 sw/pulp-sdk/hal/include/hal/riscv/types.h create mode 100644 sw/pulp-sdk/hal/include/hal/rom/rom_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/rtc/rtc_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/soc_eu/soc_eu_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/soc_eu/soc_eu_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/soc_eu/soc_eu_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/tb/tb.h create mode 100644 sw/pulp-sdk/hal/include/hal/timer/timer_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/timer/timer_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/tryx/tryx_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/cpi/udma_cpi_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/csi2/udma_csi2_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/hyper/udma_hyper_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/hyper/udma_hyper_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/i2c/udma_i2c_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/i2c/udma_i2c_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/i2s/udma_i2s_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/spim/udma_spim_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/spim/udma_spim_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/spim/udma_spim_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/tcdm/udma_tcdm_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/uart/udma_uart_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/udma_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/udma_v2.h create mode 100644 sw/pulp-sdk/hal/include/hal/udma/udma_v3.h create mode 100644 sw/pulp-sdk/hal/include/hal/utils.h create mode 100644 sw/pulp-sdk/hal/include/hal/vendors/dolphin/rtc.h create mode 100644 sw/pulp-sdk/hal/include/hal/vendors/iid/quiddikey_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/vendors/lnt/csi2_v1.h create mode 100644 sw/pulp-sdk/hal/include/hal/xne/xne_v1.h create mode 100644 sw/pulp-sdk/hal/src/hal/mailbox/mailbox_v0.c create mode 100644 sw/pulp-sdk/hal/src/hal/rab/rab_v1.c create mode 100644 sw/pulp-sdk/hal/src/hal/tryx/tryx_v1.c create mode 100644 sw/pulp-sdk/kernel/riscv/rt/crt0.S create mode 100644 sw/pulp-sdk/linker/config.ld create mode 100755 sw/pulp-sdk/linker/link.ld create mode 100644 sw/pulp-sdk/runtime/libs/io/io.c create mode 100644 sw/pulp-sdk/runtime/libs/io/tinyprintf.c create mode 100644 sw/pulp-sdk/runtime/libs/io/tinyprintf.h create mode 100755 sw/pulp-sdk/scripts/s19toslm.py create mode 100644 sw/rules/spin-handlers.mk create mode 100644 sw/rules/spin-rt.mk create mode 100644 sw/runtime/include/handler.h create mode 100644 sw/runtime/include/hwsched.h create mode 100644 sw/runtime/include/libaxidma.h create mode 100755 sw/runtime/include/packets.h create mode 100644 sw/runtime/include/pspin.h create mode 100644 sw/runtime/include/pspin_rt.h create mode 100644 sw/runtime/include/spin_conf.h create mode 100644 sw/runtime/include/spin_dma.h create mode 100644 sw/runtime/include/util.h create mode 100644 sw/runtime/src/handler.c create mode 100644 sw/runtime/src/hpu.c create mode 100644 sw/runtime/src/hpu.h create mode 100644 sw/runtime/src/main.c create mode 100644 sw/runtime/src/spin_dma.h create mode 100755 sw/scripts/benchmark.py create mode 100755 sw/scripts/extract_info.sh create mode 100755 sw/scripts/handlers_data.sh create mode 100755 sw/scripts/handlers_duration.sh create mode 100755 sw/scripts/inspect_trace.py create mode 100755 sw/scripts/make_packets.sh create mode 100755 sw/scripts/telemetry.sh create mode 100755 sw/scripts/telemetry_instructions_tracevis.sh create mode 100755 sw/scripts/telemetry_time_tracevis.sh create mode 100644 sw/scripts/tracevis/README.md create mode 100755 sw/scripts/tracevis/example/bin/pulp_api_example create mode 100644 sw/scripts/tracevis/example/chrome.json create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_0.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_1.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_2.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_3.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_4.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_5.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_6.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_00_7.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_0.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_1.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_2.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_3.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_4.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_5.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_6.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_01_7.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_0.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_1.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_2.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_3.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_4.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_5.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_6.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_02_7.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_0.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_1.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_2.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_3.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_4.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_5.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_6.log create mode 100644 sw/scripts/tracevis/example/traces/trace_core_03_7.log create mode 100644 sw/scripts/tracevis/parse.pl diff --git a/examples/aggregate/Makefile b/examples/aggregate/Makefile new file mode 100644 index 0000000..58e3f11 --- /dev/null +++ b/examples/aggregate/Makefile @@ -0,0 +1,13 @@ +SPIN_APP_NAME = aggregate_global +SPIN_APP_SRCS = aggregate_global.c +SPIN_CFLAGS = -O3 -g +SPIN_LDFLAGS = -lm +NUM_PACKETS ?=512 +HAS_HH=0 +HAS_TH=1 +FULL_PKT=1 +PKT_SIZE ?= 1024 +PKT_DELAY=0 + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/aggregate/handlers/aggregate_global.c b/examples/aggregate/handlers/aggregate_global.c new file mode 100644 index 0000000..0324ee1 --- /dev/null +++ b/examples/aggregate/handlers/aggregate_global.c @@ -0,0 +1,69 @@ +#ifndef HOST +#include +#else +#include +#endif + +#include + +#define MAX_CLUSTERS 4 +#define MAX_HPUS 32 +#define STRIDE 1 +#define OFFSET 0 +#define NUM_INT_OP 0 + +//#define USE_AMO + +// Handler that implements data race free aggregation for int32 +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + +__handler__ void aggregate_global_hh(handler_args_t *args) +{ +} +__handler__ void aggregate_global_ph(handler_args_t *args) +{ + + task_t* task = args->task; + uint32_t *scratchpad = (uint32_t *)task->scratchpad; + + uint8_t *pkt_pld_ptr; + uint32_t pkt_pld_len; + GET_IP_UDP_PLD(task->pkt_mem, pkt_pld_ptr, pkt_pld_len); + + uint32_t *nic_pld_addr = (uint32_t*) pkt_pld_ptr; + + uint32_t aggregator=0; + for(uint32_t i=0;icluster_id; + amo_add(&(scratchpad[my_cluster_id]), aggregator); +} + +__handler__ void aggregate_global_th(handler_args_t *args) +{ + task_t* task = args->task; + uint32_t *scratchpad=(uint32_t*) task->scratchpad; + uint32_t result=0; + for(uint8_t i=0;ihost_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + + spin_host_write(host_address, (uint64_t) result, false); +} + + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {aggregate_global_hh, aggregate_global_ph, aggregate_global_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void*) handler_mem; +} diff --git a/examples/copy_from_host/Makefile b/examples/copy_from_host/Makefile new file mode 100644 index 0000000..a2f33c3 --- /dev/null +++ b/examples/copy_from_host/Makefile @@ -0,0 +1,13 @@ +SPIN_APP_NAME = copy_from_host +SPIN_APP_SRCS = copy_from_host.c +SPIN_CFLAGS = -O3 -g -flto +SPIN_LDFLAGS = -lm +NUM_PACKETS ?= 512 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 +HAS_HH ?= 0 +HAS_TH ?= 0 +FULL_PKT ?= 1 + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/copy_from_host/handlers/copy_from_host.c b/examples/copy_from_host/handlers/copy_from_host.c new file mode 100644 index 0000000..82d1668 --- /dev/null +++ b/examples/copy_from_host/handlers/copy_from_host.c @@ -0,0 +1,58 @@ +#ifndef HOST +#include +#include +#include +#else +#include +#endif + +#if !defined(TO_L2) && !defined(TO_L1) +#define TO_L1 +#endif + +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + + +__handler__ void copy_from_host_hh(handler_args_t *args) {;} +__handler__ void copy_from_host_ph(handler_args_t *args) +{ + task_t* task = args->task; + ip_hdr_t *ip_hdr = (ip_hdr_t*) (task->pkt_mem); +#ifndef TO_L1 + uint8_t *nic_pld_addr = ((uint8_t*) (task->l2_pkt_mem)); +#else + uint8_t *nic_pld_addr = ((uint8_t*) (task->pkt_mem)); +#endif + uint16_t pkt_pld_len = ip_hdr->length; + udp_hdr_t *udp_hdr = (udp_hdr_t*) (((uint8_t*) (task->pkt_mem)) + ip_hdr->ihl * 4); + + uint32_t src_id = ip_hdr->source_id; + ip_hdr->source_id = ip_hdr->dest_id; + ip_hdr->dest_id = src_id; + + uint16_t src_port = udp_hdr->src_port; + udp_hdr->src_port = udp_hdr->dst_port; + udp_hdr->dst_port = src_port; + + spin_cmd_t dma; + + uint64_t host_address = task->host_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + spin_dma_from_host(host_address, (uint32_t) nic_pld_addr, pkt_pld_len, 1, &dma); + + spin_cmd_wait(dma); + + spin_cmd_t send; + spin_send_packet(nic_pld_addr, pkt_pld_len, &send); +} +__handler__ void copy_from_host_th(handler_args_t *args){;} + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {copy_from_host_hh, copy_from_host_ph, copy_from_host_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void*) handler_mem; +} diff --git a/examples/copy_to_host/Makefile b/examples/copy_to_host/Makefile new file mode 100644 index 0000000..8a59803 --- /dev/null +++ b/examples/copy_to_host/Makefile @@ -0,0 +1,13 @@ +SPIN_APP_NAME = copy_to_host +SPIN_APP_SRCS = copy_to_host.c +SPIN_CFLAGS = -O3 -g -flto +SPIN_LDFLAGS = -lm +NUM_PACKETS ?= 512 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 +HAS_HH ?= 0 +HAS_TH ?= 0 +FULL_PKT ?= 1 + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/copy_to_host/handlers/copy_to_host.c b/examples/copy_to_host/handlers/copy_to_host.c new file mode 100644 index 0000000..b357e16 --- /dev/null +++ b/examples/copy_to_host/handlers/copy_to_host.c @@ -0,0 +1,56 @@ +#ifndef HOST +#include +#include +#include +#else +#include +#endif + +#if !defined(FROM_L2) && !defined(FROM_L1) +#define FROM_L1 +#endif + +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + + +__handler__ void copy_to_host_hh(handler_args_t *args) {;} +__handler__ void copy_to_host_ph(handler_args_t *args) +{ + task_t* task = args->task; + ip_hdr_t *ip_hdr = (ip_hdr_t*) (task->pkt_mem); +#ifdef FROM_L2 + uint8_t *nic_pld_addr = ((uint8_t*) (task->l2_pkt_mem)); +#else + uint8_t *nic_pld_addr = ((uint8_t*) (task->pkt_mem)); +#endif + uint16_t pkt_pld_len = ip_hdr->length; + + spin_cmd_t dma; + + uint64_t host_address = task->host_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + spin_dma_to_host(host_address, (uint32_t) nic_pld_addr, pkt_pld_len, 1, &dma); + + //It's not strictly necessary to wait. The hw will enforce that the feedback is not + //sent until all commands issued by this handlers are completed. +#ifdef WAIT_POLL + bool completed = false; + do { + spin_cmd_test(dma, &completed); + } while (!completed); +#elif defined(WAIT_SUSPEND) + spin_cmd_wait(dma); +#endif + +} +__handler__ void copy_to_host_th(handler_args_t *args){;} + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {copy_to_host_hh, copy_to_host_ph, copy_to_host_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void*) handler_mem; +} diff --git a/examples/empty/Makefile b/examples/empty/Makefile new file mode 100644 index 0000000..3967fe1 --- /dev/null +++ b/examples/empty/Makefile @@ -0,0 +1,11 @@ +SPIN_APP_NAME = empty +SPIN_APP_SRCS = empty.c +SPIN_CFLAGS = -O3 -g ${DEFINITIONS} +SPIN_LDFLAGS = -lm -flto +NUM_PACKETS ?= 512 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 + + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/empty/handlers/empty.c b/examples/empty/handlers/empty.c new file mode 100644 index 0000000..ecc40f6 --- /dev/null +++ b/examples/empty/handlers/empty.c @@ -0,0 +1,40 @@ + +#ifndef HOST +#include +#include +#include +#else +#include +#endif + +#ifndef NUM_INT_OP +#define NUM_INT_OP 0 +#endif + +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + +__handler__ void empty_hh(handler_args_t *args) {;} +__handler__ void empty_ph(handler_args_t *args) +{ + //printf("Payload handler!\n"); +#if (NUM_INT_OP > 0) + volatile int xx = 0; + int x = xx; + for (int i=0; i +#else +#include +#endif + +#include +#include + +#define MAX_HPUS_IN_CLUSTER 4 +#define STRIDE 1 +#define OFFSET 0 +#define NUM_INT_OP 0 +// Handler that implements reduce in scratchpad for int32 +#include "hash_maker/f_d.h" + +#define KEY_SIZE 8 + +//number of 32-bit words fitting in 1 MiB +#define TOT_WORDS 262144 + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +__handler__ void filtering_hh(handler_args_t *args) +{ + +} +__handler__ void filtering_ph(handler_args_t *args) +{ + task_t* task = args->task; + + ip_hdr_t *ip_hdr = (ip_hdr_t*) (task->pkt_mem); + uint32_t *mem = (uint32_t *) task->handler_mem; + uint8_t *key_byte = (uint8_t*) task->pkt_mem; + + uint32_t hash; + HASH_JEN(key_byte, KEY_SIZE, hash); + hash = FAST_MOD(hash, TOT_WORDS); + + *((uint32_t *) task->l2_pkt_mem) = mem[hash]; + + spin_cmd_t cpy; + uint64_t host_address = task->host_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + spin_dma_to_host(host_address, task->l2_pkt_mem, task->pkt_mem_size, 0, &cpy); + +} +__handler__ void filtering_th(handler_args_t *args) +{ +} + +void init_handlers(handler_fn *hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {filtering_hh, filtering_ph, filtering_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void *)handler_mem; +} diff --git a/examples/hashtable_fun/Makefile b/examples/hashtable_fun/Makefile new file mode 100644 index 0000000..ce237cb --- /dev/null +++ b/examples/hashtable_fun/Makefile @@ -0,0 +1,17 @@ +SPIN_APP_NAME = htable +SPIN_APP_SRCS = htable_handlers.c +SPIN_CFLAGS = -O3 -g ${DEFINITIONS} +SPIN_LDFLAGS = -lm -flto +NUM_PACKETS ?= 4 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 + + +include $(PSPIN_RT)/spin-handlers.mk + +all:: + make deploy + make driver + +driver: htable_driver.c + gcc -std=c99 -I$(PSPIN_RT)/include/ -I$(PSPIN_HW)/verilator_model/include htable_driver.c -L$(PSPIN_HW)/verilator_model/lib/ -lpspin_debug -o htable_driver diff --git a/examples/hashtable_fun/driver/htable_driver.c b/examples/hashtable_fun/driver/htable_driver.c new file mode 100644 index 0000000..6c563ed --- /dev/null +++ b/examples/hashtable_fun/driver/htable_driver.c @@ -0,0 +1,94 @@ +#include "pspinsim.h" +#include "spin.h" + +#include +#include +#include + +#define NUM_FUNCTIONS 3 + +#define CHECK_ERR(S) {int res; if ((res=S)!=SPIN_SUCCESS) return res;} + +#define NUM_PACKETS 32 +#define PKT_SIZE 64 + +/* This is the handler data memory */ +#define NIC_L2_ADDR 0x1c300000 + +#define HANDLERS_FILE "build/htable" + +/*** Test function that injects some (empty) packets ***/ +int send_packets() +{ + uint8_t pkt_buffer[PKT_SIZE]; + + // find address of the payload handler + spin_nic_addr_t ph_addr; + size_t ph_size; + CHECK_ERR(spin_find_handler_by_name(HANDLERS_FILE, "htable_ph", &ph_addr, &ph_size)); + + /* 1st thing to do: prepare execution context */ + spin_ec_t ec; + ec.handler_mem_addr = (uint32_t) NIC_L2_ADDR; + ec.handler_mem_size = 0x100000; + ec.host_mem_addr = (uint64_t) 0xdeadbeefdeadbeef; + ec.host_mem_size = 0; + ec.hh_addr = 0; //hh_addr; + ec.ph_addr = ph_addr; + ec.th_addr = 0; //th_addr; + ec.hh_size = 0; + ec.ph_size = ph_size; + ec.th_size = 0; + + for (int i=0; i + +typedef void(*fun_ptr_t()); + +void fun1() __attribute__((used)); +void fun2() __attribute__((used)); +void fun3() __attribute__((used)); + +void fun1() +{ + printf("fun1!\n"); +} + +void fun2() +{ + printf("fun2!\n"); +} + +void fun3() +{ + printf("fun3!\n"); +} + + +__handler__ void htable_hh(handler_args_t *args) {;} +__handler__ void htable_th(handler_args_t *args){;} + + +__handler__ void htable_ph(handler_args_t *args) +{ + fun_ptr_t **htable = (fun_ptr_t**) args->task->handler_mem; + + //printf("payload handler (htable[1]: %p; fun2: %p)!\n", htable[1], fun2); + + //TODO: compute hash here and access entry accordingly! + (htable[0])(); + (htable[1])(); + (htable[2])(); + +} + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {htable_hh, htable_ph, htable_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; +} diff --git a/examples/histogram/Makefile b/examples/histogram/Makefile new file mode 100644 index 0000000..95cf591 --- /dev/null +++ b/examples/histogram/Makefile @@ -0,0 +1,15 @@ +SPIN_APP_NAME = histogram_l1 +SPIN_APP_SRCS = histogram_l1.c +SPIN_CFLAGS = -O3 -g -flto +SPIN_LDFLAGS = -lm +NUM_PACKETS ?=512 +HAS_HH ?= 0 +HAS_TH ?= 1 +FULL_PKT = 1 +MSG_COUNT ?=1 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 +PKT_SIZE ?= 1024 +PKTGEN_CUSTOM_PARAMS="--fill-mod 1024" +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/histogram/handlers/histogram_l1.c b/examples/histogram/handlers/histogram_l1.c new file mode 100644 index 0000000..a3af871 --- /dev/null +++ b/examples/histogram/handlers/histogram_l1.c @@ -0,0 +1,82 @@ +#ifndef HOST +#include +#else +#include +#endif + +#include +#include + +#define NUM_CLUSTERS 4 +#define STRIDE 1 +#define OFFSET 0 +#define NUM_INT_OP 0 + +#define HISTOGRAM_SIZE 1024 + +#ifndef HOST +typedef uint32_t pspin_mem_ptr_t; +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}; +#else +typedef uint64_t pspin_mem_ptr_t; +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}; +#endif + +__handler__ void histogram_l1_hh(handler_args_t *args) +{ +} + + +__handler__ void histogram_l1_ph(handler_args_t *args) +{ + task_t* task = args->task; + + uint8_t *pkt_pld_ptr; + uint32_t pkt_pld_len; + GET_IP_UDP_PLD(task->pkt_mem, pkt_pld_ptr, pkt_pld_len); + pkt_pld_ptr += sizeof(app_hdr_t); + pkt_pld_len -= sizeof(app_hdr_t); + + int32_t *nic_pld_addr = (int32_t*) pkt_pld_ptr; + + int32_t *local_mem = (int32_t*) (task->scratchpad[args->cluster_id]); + //volatile uint8_t *local_mem = (volatile uint8_t*) (task->scratchpad[args->cluster_id]); + //printf("pktpld: %p; pkt_pld_len: %lu\n", nic_pld_addr, pkt_pld_len); + + volatile int32_t* word_ptr = &(local_mem[nic_pld_addr[0]]); + //int32_t mul = 4; + //we assume the number of msg size divides the pkt payload size + for (uint32_t i = 1; i < pkt_pld_len / 4; i++) + { + //amo_add(&(local_mem[nic_pld_addr[i]]), 1); + + //uint32_t word_idx = nic_pld_addr[i]; //FAST_MOD(nic_pld_addr[i], HISTOGRAM_SIZE); + //word_ptr = (volatile int32_t*) local_mem; + //asm volatile("p.mac %0, %1, %2" : : "r"(word_ptr), "r"(nic_pld_addr[i]), "r"(mul)); + + //word_ptr = (volatile int32_t*) (local_mem + (nic_pld_addr[i] << 2)); + //amo_add(word_ptr, 1); + + amo_add(word_ptr, 1); + word_ptr = &(local_mem[nic_pld_addr[i]]); + } +} +__handler__ void histogram_l1_th(handler_args_t *args) +{ + task_t* task = args->task; + uint64_t host_address = task->host_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + + //signal that we completed so to let the host read the result back + spin_host_write(host_address, (uint64_t) 1, false); +} + +void init_handlers(handler_fn *hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {histogram_l1_hh, histogram_l1_ph, histogram_l1_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void *)handler_mem; +} diff --git a/examples/host_direct/Makefile b/examples/host_direct/Makefile new file mode 100644 index 0000000..9d3ed05 --- /dev/null +++ b/examples/host_direct/Makefile @@ -0,0 +1,11 @@ +SPIN_APP_NAME = hostdirect +SPIN_APP_SRCS = hostdirect.c +SPIN_CFLAGS = -O3 -g ${DEFINITIONS} +SPIN_LDFLAGS = -lm -flto +NUM_PACKETS ?= 512 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 + + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/host_direct/handlers/hostdirect.c b/examples/host_direct/handlers/hostdirect.c new file mode 100644 index 0000000..e25623c --- /dev/null +++ b/examples/host_direct/handlers/hostdirect.c @@ -0,0 +1,26 @@ + +#include +#include +#include + + +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + +__handler__ void hostdirect_hh(handler_args_t *args) {;} +__handler__ void hostdirect_ph(handler_args_t *args) +{ + spin_cmd_t xfer; + spin_host_write(0xdeadbeef, 0xcafebebe, &xfer); +} +__handler__ void hostdirect_th(handler_args_t *args){;} + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {hostdirect_hh, hostdirect_ph, hostdirect_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void*) handler_mem; +} + diff --git a/examples/ping_pong/Makefile b/examples/ping_pong/Makefile new file mode 100644 index 0000000..13453ec --- /dev/null +++ b/examples/ping_pong/Makefile @@ -0,0 +1,13 @@ +SPIN_APP_NAME = pingpong +SPIN_APP_SRCS = ping_pong.c +SPIN_CFLAGS = -O3 -g -flto +SPIN_LDFLAGS = -lm +NUM_PACKETS ?= 512 +PKT_DELAY ?= 0 +MSG_DELAY ?= 0 +FULL_PKT ?= 1 +HAS_HH = 0 +HAS_TH = 0 + +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/ping_pong/handlers/ping_pong.c b/examples/ping_pong/handlers/ping_pong.c new file mode 100644 index 0000000..c1ba5cd --- /dev/null +++ b/examples/ping_pong/handlers/ping_pong.c @@ -0,0 +1,62 @@ +#ifndef HOST +#include +#include +#include +#else +#include +#endif + +#if !defined(FROM_L2) && !defined(FROM_L1) +#define FROM_L1 +#endif + +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0xde, 0xad, 0xbe, 0xef}; + + +__handler__ void pingpong_hh(handler_args_t *args) {;} +__handler__ void pingpong_ph(handler_args_t *args) +{ + task_t* task = args->task; + ip_hdr_t *ip_hdr = (ip_hdr_t*) (task->pkt_mem); +#ifdef FROM_L2 + uint8_t *nic_pld_addr = ((uint8_t*) (task->l2_pkt_mem)); +#else + uint8_t *nic_pld_addr = ((uint8_t*) (task->pkt_mem)); +#endif + uint16_t pkt_pld_len = ip_hdr->length; + udp_hdr_t *udp_hdr = (udp_hdr_t*) (((uint8_t*) (task->pkt_mem)) + ip_hdr->ihl * 4); + + uint32_t src_id = ip_hdr->source_id; + ip_hdr->source_id = ip_hdr->dest_id; + ip_hdr->dest_id = src_id; + + uint16_t src_port = udp_hdr->src_port; + udp_hdr->src_port = udp_hdr->dst_port; + udp_hdr->dst_port = src_port; + + spin_cmd_t put; + spin_send_packet(nic_pld_addr, pkt_pld_len, &put); + + //It's not strictly necessary to wait. The hw will enforce that the feedback is not + //sent until all commands issued by this handlers are completed. +#ifdef WAIT_POLL + bool completed = false; + do { + spin_cmd_test(put, &completed); + } while (!completed); +#elif defined(WAIT_SUSPEND) + spin_cmd_wait(put); +#endif + +} +__handler__ void pingpong_th(handler_args_t *args){;} + +void init_handlers(handler_fn * hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {pingpong_hh, pingpong_ph, pingpong_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void*) handler_mem; +} diff --git a/examples/reduce/Makefile b/examples/reduce/Makefile new file mode 100644 index 0000000..ec09837 --- /dev/null +++ b/examples/reduce/Makefile @@ -0,0 +1,13 @@ +SPIN_APP_NAME = reduce_l1 +SPIN_APP_SRCS = reduce_l1.c +SPIN_CFLAGS = -O3 -g -flto +SPIN_LDFLAGS = -lm +NUM_PACKETS ?=512 +MSG_COUNT ?=1 +PKT_SIZE ?=1024 +HAS_HH?=0 +HAS_TH?=0 +FULL_PKT=1 +PKT_DELAY=0 +include $(PSPIN_RT)/spin-handlers.mk + diff --git a/examples/reduce/handlers/reduce_l1.c b/examples/reduce/handlers/reduce_l1.c new file mode 100644 index 0000000..48144bf --- /dev/null +++ b/examples/reduce/handlers/reduce_l1.c @@ -0,0 +1,74 @@ +#ifndef HOST +#include +#else +#include +#endif + +#include + +#include +#define NUM_CLUSTERS 4 +#define STRIDE 1 +#define OFFSET 0 +#define NUM_INT_OP 0 + +#define ZEROS 2048 +// Handler that implements reduce in scratchpad for int32 + +// 4 uint32_t -> locks +// 4 uint32_t -> L1 addresses +// 1 uint32_t -> msg_count (now 0x0200) + +#ifndef HOST +typedef uint32_t pspin_mem_ptr_t; +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}; +#else +typedef uint64_t pspin_mem_ptr_t; +volatile __attribute__((section(".l2_handler_data"))) uint8_t handler_mem[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0}; +#endif + + +__handler__ void reduce_l1_hh(handler_args_t *args) +{ +} +__handler__ void reduce_l1_ph(handler_args_t *args) +{ + + task_t* task = args->task; + + uint8_t *pkt_pld_ptr; + uint32_t pkt_pld_len; + GET_IP_UDP_PLD(task->pkt_mem, pkt_pld_ptr, pkt_pld_len); + + uint32_t *nic_pld_addr = (uint32_t*) pkt_pld_ptr; + + //reduce_mem_t *mem = (reduce_mem_t *)args->her->match_info.handler_mem; + volatile int32_t *local_mem = (int32_t *)(task->scratchpad[args->cluster_id]); + + //we assume the number of msg size divides the pkt payload size + for (uint32_t i = 0; i < pkt_pld_len / 4; i++) + { + amo_add(&(local_mem[i]), nic_pld_addr[i]); + } + // We do need atomics here, as each handler writes to the same adress as other in the same cluster. +} +__handler__ void reduce_l1_th(handler_args_t *args) +{ + task_t* task = args->task; + uint64_t host_address = task->host_mem_high; + host_address = (host_address << 32) | (task->host_mem_low); + + //signal that we completed so to let the host read the result back + spin_host_write(host_address, (uint64_t) 1, false); +} + + +void init_handlers(handler_fn *hh, handler_fn *ph, handler_fn *th, void **handler_mem_ptr) +{ + volatile handler_fn handlers[] = {reduce_l1_hh, reduce_l1_ph, reduce_l1_th}; + *hh = handlers[0]; + *ph = handlers[1]; + *th = handlers[2]; + + *handler_mem_ptr = (void *)handler_mem; +} diff --git a/hw/deps/apb/src/apb_intf.sv b/hw/deps/apb/src/apb_intf.sv new file mode 100644 index 0000000..70a659c --- /dev/null +++ b/hw/deps/apb/src/apb_intf.sv @@ -0,0 +1,55 @@ +// Copyright 2014-2018 ETH Zurich and 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. +// +// Fabian Schuiki +// +// This file defines the interfaces we support. + +interface APB_BUS #( + parameter int unsigned APB_ADDR_WIDTH = 32, + parameter int unsigned APB_DATA_WIDTH = 32 +); + + logic [APB_ADDR_WIDTH-1:0] paddr; + logic [APB_DATA_WIDTH-1:0] pwdata; + logic pwrite; + logic psel; + logic penable; + logic [APB_DATA_WIDTH-1:0] prdata; + logic pready; + logic pslverr; + + + // Master Side + modport Master ( + output paddr, pwdata, pwrite, psel, penable, + input prdata, pready, pslverr + ); + + // Slave Side + modport Slave ( + input paddr, pwdata, pwrite, psel, penable, + output prdata, pready, pslverr + ); + + /// The interface as an output (issuing requests, initiator, master). + modport out ( + output paddr, pwdata, pwrite, psel, penable, + input prdata, pready, pslverr + ); + + /// The interface as an input (accepting requests, target, slave) + modport in ( + input paddr, pwdata, pwrite, psel, penable, + output prdata, pready, pslverr + ); + + +endinterface diff --git a/hw/deps/axi/src/axi_atop_filter.sv b/hw/deps/axi/src/axi_atop_filter.sv new file mode 100644 index 0000000..9b82f8b --- /dev/null +++ b/hw/deps/axi/src/axi_atop_filter.sv @@ -0,0 +1,427 @@ +// Copyright 2018 ETH Zurich and 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. + +// Author: +// Andreas Kurth + +// AXI ATOP Filter: This module filters atomic operations (ATOPs), i.e., write transactions that +// have a non-zero `aw_atop` value, from its `slv` to its `mst` port. This module guarantees that: +// +// 1) `aw_atop` is always zero on the `mst` port; +// +// 2) write transactions with non-zero `aw_atop` on the `slv` port are handled in conformance with +// the AXI standard by replying to such write transactions with the proper B and R responses. The +// response code on atomic operations that reach this module is always SLVERR +// (implementation-specific, not defined in the AXI standard). +// +// This module is intended to be placed between masters that may issue ATOPs and slaves that do not +// support ATOPs. That way, this module ensures that the AXI protocol remains in a defined state on +// systems with mixed ATOP capabilities. +// +// Interface note: +// The AXI standard specifies that there may be no ordering requirements between different atomic +// bursts (i.e., a burst started by an AW with ATOP other than 0) and none between atomic bursts and +// non-atomic bursts [E2.1.4]. That is, an atomic burst may never have the same ID as any other +// write or read burst that is ongoing at the same time. + +module axi_atop_filter #( + parameter int unsigned AxiIdWidth = 0, // Synopsys DC requires a default value for parameters. + // Maximum number of AXI write bursts outstanding at the same time + parameter int unsigned AxiMaxWriteTxns = 0, + // AXI request & response type + parameter type req_t = logic, + parameter type resp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + // slave port + input req_t slv_req_i, + output resp_t slv_resp_o, + // master port + output req_t mst_req_o, + input resp_t mst_resp_i +); + + // Minimum counter width is 2 to detect underflows. + localparam int unsigned COUNTER_WIDTH = (AxiMaxWriteTxns == 1) ? 2 : $clog2(AxiMaxWriteTxns+1); + typedef struct packed { + logic underflow; + logic [COUNTER_WIDTH-1:0] cnt; + } cnt_t; + cnt_t w_cnt_d, w_cnt_q; + + typedef enum logic [2:0] { + W_FEEDTHROUGH, BLOCK_AW, ABSORB_W, HOLD_B, INJECT_B, WAIT_R + } w_state_e; + w_state_e w_state_d, w_state_q; + + typedef enum logic [1:0] { R_FEEDTHROUGH, INJECT_R, R_HOLD } r_state_e; + r_state_e r_state_d, r_state_q; + + typedef logic [AxiIdWidth-1:0] id_t; + id_t id_d, id_q; + + typedef logic [7:0] len_t; + len_t r_beats_d, r_beats_q; + + typedef struct packed { + len_t len; + } r_resp_cmd_t; + r_resp_cmd_t r_resp_cmd_push, r_resp_cmd_pop; + + logic aw_without_complete_w_downstream, + complete_w_without_aw_downstream, + r_resp_cmd_push_valid, r_resp_cmd_push_ready, + r_resp_cmd_pop_valid, r_resp_cmd_pop_ready; + + // An AW without a complete W burst is in-flight downstream if the W counter is > 0 and not + // underflowed. + assign aw_without_complete_w_downstream = !w_cnt_q.underflow && (w_cnt_q.cnt > 0); + // A complete W burst without AW is in-flight downstream if the W counter is -1. + assign complete_w_without_aw_downstream = w_cnt_q.underflow && &(w_cnt_q.cnt); + + // Manage AW, W, and B channels. + always_comb begin + // Defaults: + // Disable AW and W handshakes. + mst_req_o.aw_valid = 1'b0; + slv_resp_o.aw_ready = 1'b0; + mst_req_o.w_valid = 1'b0; + slv_resp_o.w_ready = 1'b0; + // Feed write responses through. + mst_req_o.b_ready = slv_req_i.b_ready; + slv_resp_o.b_valid = mst_resp_i.b_valid; + slv_resp_o.b = mst_resp_i.b; + // Keep ID stored for B and R response. + id_d = id_q; + // Do not push R response commands. + r_resp_cmd_push_valid = 1'b0; + // Keep the current state. + w_state_d = w_state_q; + + unique case (w_state_q) + W_FEEDTHROUGH: begin + // Feed AW channel through if the maximum number of outstanding bursts is not reached. + if (complete_w_without_aw_downstream || (w_cnt_q.cnt < AxiMaxWriteTxns)) begin + mst_req_o.aw_valid = slv_req_i.aw_valid; + slv_resp_o.aw_ready = mst_resp_i.aw_ready; + end + // Feed W channel through if .. + if (aw_without_complete_w_downstream // .. downstream is missing W bursts .. + // .. or a new non-ATOP AW is being applied and there is not already a complete W burst + // downstream (to prevent underflows of w_cnt). + || ((slv_req_i.aw_valid && slv_req_i.aw.atop[5:4] == axi_pkg::ATOP_NONE) + && !complete_w_without_aw_downstream) + ) begin + mst_req_o.w_valid = slv_req_i.w_valid; + slv_resp_o.w_ready = mst_resp_i.w_ready; + end + // Filter out AWs that are atomic operations. + if (slv_req_i.aw_valid && slv_req_i.aw.atop[5:4] != axi_pkg::ATOP_NONE) begin + mst_req_o.aw_valid = 1'b0; // Do not let AW pass to master port. + slv_resp_o.aw_ready = 1'b1; // Absorb AW on slave port. + id_d = slv_req_i.aw.id; // Store ID for B response. + // All atomic operations except atomic stores require a response on the R channel. + if (slv_req_i.aw.atop[5:4] != axi_pkg::ATOP_ATOMICSTORE) begin + // Push R response command. We do not have to wait for the ready of the register + // because we know it is ready: we are its only master and will wait for the register to + // be emptied before going back to the `W_FEEDTHROUGH` state. + r_resp_cmd_push_valid = 1'b1; + end + // If downstream is missing W beats, block the AW channel and let the W bursts complete. + if (aw_without_complete_w_downstream) begin + w_state_d = BLOCK_AW; + // If downstream is not missing W beats, absorb the W beats for this atomic AW. + end else begin + mst_req_o.w_valid = 1'b0; // Do not let W beats pass to master port. + slv_resp_o.w_ready = 1'b1; // Absorb W beats on slave port. + if (slv_req_i.w_valid && slv_req_i.w.last) begin + // If the W beat is valid and the last, proceed by injecting the B response. + // However, if there is a non-handshaked B on our response port, we must let that + // complete first. + if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin + w_state_d = HOLD_B; + end else begin + w_state_d = INJECT_B; + end + end else begin + // Otherwise continue with absorbing W beats. + w_state_d = ABSORB_W; + end + end + end + end + + BLOCK_AW: begin + // Feed W channel through to let outstanding bursts complete. + if (aw_without_complete_w_downstream) begin + mst_req_o.w_valid = slv_req_i.w_valid; + slv_resp_o.w_ready = mst_resp_i.w_ready; + end else begin + // If there are no more outstanding W bursts, start absorbing the next W burst. + slv_resp_o.w_ready = 1'b1; + if (slv_req_i.w_valid && slv_req_i.w.last) begin + // If the W beat is valid and the last, proceed by injecting the B response. + if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin + w_state_d = HOLD_B; + end else begin + w_state_d = INJECT_B; + end + end else begin + // Otherwise continue with absorbing W beats. + w_state_d = ABSORB_W; + end + end + end + + ABSORB_W: begin + // Absorb all W beats of the current burst. + slv_resp_o.w_ready = 1'b1; + if (slv_req_i.w_valid && slv_req_i.w.last) begin + if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin + w_state_d = HOLD_B; + end else begin + w_state_d = INJECT_B; + end + end + end + + HOLD_B: begin + // Proceed with injection of B response upon handshake. + if (slv_resp_o.b_valid && slv_req_i.b_ready) begin + w_state_d = INJECT_B; + end + end + + INJECT_B: begin + // Pause forwarding of B response. + mst_req_o.b_ready = 1'b0; + // Inject error response instead. Since the B channel has an ID and the atomic burst we are + // replying to is guaranteed to be the only burst with this ID in flight, we do not have to + // observe any ordering and can immediately inject on the B channel. + slv_resp_o.b = '0; + slv_resp_o.b.id = id_q; + slv_resp_o.b.resp = axi_pkg::RESP_SLVERR; + slv_resp_o.b_valid = 1'b1; + if (slv_req_i.b_ready) begin + // If not all beats of the R response have been injected, wait for them. Otherwise, return + // to `W_FEEDTHROUGH`. + if (r_resp_cmd_pop_valid && !r_resp_cmd_pop_ready) begin + w_state_d = WAIT_R; + end else begin + w_state_d = W_FEEDTHROUGH; + end + end + end + + WAIT_R: begin + // Wait with returning to `W_FEEDTHROUGH` until all beats of the R response have been + // injected. + if (!r_resp_cmd_pop_valid) begin + w_state_d = W_FEEDTHROUGH; + end + end + + default: w_state_d = W_FEEDTHROUGH; + endcase + end + // Connect signals on AW and W channel that are not managed by the control FSM from slave port to + // master port. + // Feed-through of the AW and W vectors, make sure that downstream aw.atop is always zero + always_comb begin + // overwrite the atop signal + mst_req_o.aw = slv_req_i.aw; + mst_req_o.aw.atop = '0; + end + assign mst_req_o.w = slv_req_i.w; + + // Manage R channel. + always_comb begin + // Defaults: + // Feed read responses through. + slv_resp_o.r = mst_resp_i.r; + slv_resp_o.r_valid = mst_resp_i.r_valid; + mst_req_o.r_ready = slv_req_i.r_ready; + // Do not pop R response command. + r_resp_cmd_pop_ready = 1'b0; + // Keep the current value of the beats counter. + r_beats_d = r_beats_q; + // Keep the current state. + r_state_d = r_state_q; + + unique case (r_state_q) + R_FEEDTHROUGH: begin + if (mst_resp_i.r_valid && !slv_req_i.r_ready) begin + r_state_d = R_HOLD; + end else if (r_resp_cmd_pop_valid) begin + // Upon a command to inject an R response, immediately proceed with doing so because there + // are no ordering requirements with other bursts that may be ongoing on the R channel at + // this moment. + r_beats_d = r_resp_cmd_pop.len; + r_state_d = INJECT_R; + end + end + + INJECT_R: begin + mst_req_o.r_ready = 1'b0; + slv_resp_o.r = '0; + slv_resp_o.r.id = id_q; + slv_resp_o.r.resp = axi_pkg::RESP_SLVERR; + slv_resp_o.r.last = (r_beats_q == '0); + slv_resp_o.r_valid = 1'b1; + if (slv_req_i.r_ready) begin + if (slv_resp_o.r.last) begin + r_resp_cmd_pop_ready = 1'b1; + r_state_d = R_FEEDTHROUGH; + end else begin + r_beats_d -= 1; + end + end + end + + R_HOLD: begin + if (mst_resp_i.r_valid && slv_req_i.r_ready) begin + r_state_d = R_FEEDTHROUGH; + end + end + + default: r_state_d = R_FEEDTHROUGH; + endcase + end + // Feed all signals on AR through. + assign mst_req_o.ar = slv_req_i.ar; + assign mst_req_o.ar_valid = slv_req_i.ar_valid; + assign slv_resp_o.ar_ready = mst_resp_i.ar_ready; + + // Keep track of outstanding downstream write bursts and responses. + always_comb begin + w_cnt_d = w_cnt_q; + if (mst_req_o.aw_valid && mst_resp_i.aw_ready) begin + w_cnt_d.cnt += 1; + end + if (mst_req_o.w_valid && mst_resp_i.w_ready && mst_req_o.w.last) begin + w_cnt_d.cnt -= 1; + end + if (w_cnt_q.underflow && (w_cnt_d.cnt == '0)) begin + w_cnt_d.underflow = 1'b0; + end else if (w_cnt_q.cnt == '0 && &(w_cnt_d.cnt)) begin + w_cnt_d.underflow = 1'b1; + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + id_q <= '0; + r_beats_q <= '0; + r_state_q <= R_FEEDTHROUGH; + w_cnt_q <= '{default: '0}; + w_state_q <= W_FEEDTHROUGH; + end else begin + id_q <= id_d; + r_beats_q <= r_beats_d; + r_state_q <= r_state_d; + w_cnt_q <= w_cnt_d; + w_state_q <= w_state_d; + end + end + + stream_register #( + .T(r_resp_cmd_t) + ) r_resp_cmd ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clr_i (1'b0), + .testmode_i (1'b0), + .valid_i (r_resp_cmd_push_valid), + .ready_o (r_resp_cmd_push_ready), + .data_i (r_resp_cmd_push), + .valid_o (r_resp_cmd_pop_valid), + .ready_i (r_resp_cmd_pop_ready), + .data_o (r_resp_cmd_pop) + ); + assign r_resp_cmd_push.len = slv_req_i.aw.len; + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (AxiIdWidth >= 1) else $fatal(1, "AXI ID width must be at least 1!"); + assert (AxiMaxWriteTxns >= 1) + else $fatal(1, "Maximum number of outstanding write transactions must be at least 1!"); + end +`endif +// pragma translate_on +endmodule + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +// interface wrapper +module axi_atop_filter_intf #( + parameter int unsigned AXI_ID_WIDTH = 0, // Synopsys DC requires a default value for parameters. + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_DATA_WIDTH = 0, + parameter int unsigned AXI_USER_WIDTH = 0, + // Maximum number of AXI write bursts outstanding at the same time + parameter int unsigned AXI_MAX_WRITE_TXNS = 0 +) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Slave slv, + AXI_BUS.Master mst +); + + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + + req_t slv_req, mst_req; + resp_t slv_resp, mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_atop_filter #( + .AxiIdWidth ( AXI_ID_WIDTH ), + // Maximum number of AXI write bursts outstanding at the same time + .AxiMaxWriteTxns ( AXI_MAX_WRITE_TXNS ), + // AXI request & response type + .req_t ( req_t ), + .resp_t ( resp_t ) + ) i_axi_atop_filter ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (AXI_ADDR_WIDTH >= 1) else $fatal(1, "AXI ADDR width must be at least 1!"); + assert (AXI_DATA_WIDTH >= 1) else $fatal(1, "AXI DATA width must be at least 1!"); + assert (AXI_USER_WIDTH >= 1) else $fatal(1, "AXI USER width must be at least 1!"); + end +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/axi/src/axi_buf.sv b/hw/deps/axi/src/axi_buf.sv new file mode 100644 index 0000000..9a56d78 --- /dev/null +++ b/hw/deps/axi/src/axi_buf.sv @@ -0,0 +1,247 @@ +// Copyright 2020 ETH Zurich and 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. + +`include "axi/typedef.svh" + +module axi_buf #( + parameter int unsigned AwDepth = 32'd0, + parameter bit AwFallthrough = 1'b1, + parameter int unsigned WDepth = 32'd0, + parameter bit WFallthrough = 1'b1, + parameter int unsigned BDepth = 32'd0, + parameter bit BFallthrough = 1'b1, + parameter int unsigned ArDepth = 32'd0, + parameter bit ArFallthrough = 1'b1, + parameter int unsigned RDepth = 32'd0, + parameter bit RFallthrough = 1'b1, + parameter type req_t = logic, + parameter type resp_t = logic, + parameter int unsigned AddrWidth = 32'd0, + parameter int unsigned DataWidth = 32'd0, + parameter int unsigned IdWidth = 32'd0, + parameter int unsigned UserWidth = 32'd0 +) ( + input logic clk_i, + input logic rst_ni, + + input req_t slv_req_i, + output resp_t slv_resp_o, + + output req_t mst_req_o, + input resp_t mst_resp_i +); + + typedef logic [AddrWidth-1:0] addr_t; + typedef logic [DataWidth-1:0] data_t; + typedef logic [DataWidth/8-1:0] strb_t; + typedef logic [IdWidth-1:0] id_t; + typedef logic [UserWidth-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + + if (AwDepth == 0) begin : gen_no_aw_fifo + assign mst_req_o.aw = slv_req_i.aw; + assign mst_req_o.aw_valid = slv_req_i.aw_valid; + assign slv_resp_o.aw_ready = mst_resp_i.aw_ready; + end else begin + stream_fifo #( + .FALL_THROUGH (AwFallthrough), + .DATA_WIDTH ($bits(aw_chan_t)), + .DEPTH (AwDepth) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .usage_o (/* unused */), + .data_i (slv_req_i.aw), + .valid_i (slv_req_i.aw_valid), + .ready_o (slv_resp_o.aw_ready), + .data_o (mst_req_o.aw), + .valid_o (mst_req_o.aw_valid), + .ready_i (mst_resp_i.aw_ready) + ); + end + + if (WDepth == 0) begin : gen_no_w_fifo + assign mst_req_o.w = slv_req_i.w; + assign mst_req_o.w_valid = slv_req_i.w_valid; + assign slv_resp_o.w_ready = mst_resp_i.w_ready; + end else begin + stream_fifo #( + .FALL_THROUGH (WFallthrough), + .DATA_WIDTH ($bits(w_chan_t)), + .DEPTH (WDepth) + ) i_w_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .usage_o (/* unused */), + .data_i (slv_req_i.w), + .valid_i (slv_req_i.w_valid), + .ready_o (slv_resp_o.w_ready), + .data_o (mst_req_o.w), + .valid_o (mst_req_o.w_valid), + .ready_i (mst_resp_i.w_ready) + ); + end + + if (BDepth == 0) begin : gen_no_b_fifo + assign slv_resp_o.b = mst_resp_i.b; + assign slv_resp_o.b_valid = mst_resp_i.b_valid; + assign mst_req_o.b_ready = slv_req_i.b_ready; + end else begin + stream_fifo #( + .FALL_THROUGH (BFallthrough), + .DATA_WIDTH ($bits(b_chan_t)), + .DEPTH (BDepth) + ) i_b_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .usage_o (/* unused */), + .data_i (mst_resp_i.b), + .valid_i (mst_resp_i.b_valid), + .ready_o (mst_req_o.b_ready), + .data_o (slv_resp_o.b), + .valid_o (slv_resp_o.b_valid), + .ready_i (slv_req_i.b_ready) + ); + end + + if (ArDepth == 0) begin : gen_no_ar_fifo + assign mst_req_o.ar = slv_req_i.ar; + assign mst_req_o.ar_valid = slv_req_i.ar_valid; + assign slv_resp_o.ar_ready = mst_resp_i.ar_ready; + end else begin + stream_fifo #( + .FALL_THROUGH (ArFallthrough), + .DATA_WIDTH ($bits(ar_chan_t)), + .DEPTH (ArDepth) + ) i_ar_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .usage_o (/* unused */), + .data_i (slv_req_i.ar), + .valid_i (slv_req_i.ar_valid), + .ready_o (slv_resp_o.ar_ready), + .data_o (mst_req_o.ar), + .valid_o (mst_req_o.ar_valid), + .ready_i (mst_resp_i.ar_ready) + ); + end + + if (RDepth == 0) begin : gen_no_r_fifo + assign slv_resp_o.r = mst_resp_i.r; + assign slv_resp_o.r_valid = mst_resp_i.r_valid; + assign mst_req_o.r_ready = slv_req_i.r_ready; + end else begin + stream_fifo #( + .FALL_THROUGH (RFallthrough), + .DATA_WIDTH ($bits(r_chan_t)), + .DEPTH (RDepth) + ) i_r_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .usage_o (/* unused */), + .data_i (mst_resp_i.r), + .valid_i (mst_resp_i.r_valid), + .ready_o (mst_req_o.r_ready), + .data_o (slv_resp_o.r), + .valid_o (slv_resp_o.r_valid), + .ready_i (slv_req_i.r_ready) + ); + end + +endmodule + +`include "axi/assign.svh" + +module axi_buf_intf #( + parameter int unsigned AW_DEPTH = 32'd0, + parameter bit AW_FALLTHROUGH = 1'b1, + parameter int unsigned W_DEPTH = 32'd0, + parameter bit W_FALLTHROUGH = 1'b1, + parameter int unsigned B_DEPTH = 32'd0, + parameter bit B_FALLTHROUGH = 1'b1, + parameter int unsigned AR_DEPTH = 32'd0, + parameter bit AR_FALLTHROUGH = 1'b1, + parameter int unsigned R_DEPTH = 32'd0, + parameter bit R_FALLTHROUGH = 1'b1, + parameter int unsigned ADDR_WIDTH = 32'd0, + parameter int unsigned DATA_WIDTH = 32'd0, + parameter int unsigned ID_WIDTH = 32'd0, + parameter int unsigned USER_WIDTH = 32'd0 +) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Slave slv, + AXI_BUS.Master mst +); + + typedef logic [ID_WIDTH-1:0] id_t; + typedef logic [ADDR_WIDTH-1:0] addr_t; + typedef logic [DATA_WIDTH-1:0] data_t; + typedef logic [DATA_WIDTH/8-1:0] strb_t; + typedef logic [USER_WIDTH-1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + + req_t slv_req, mst_req; + resp_t slv_resp, mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_buf #( + .AwDepth (AW_DEPTH), + .AwFallthrough (AW_FALLTHROUGH), + .WDepth (W_DEPTH), + .WFallthrough (W_FALLTHROUGH), + .BDepth (B_DEPTH), + .BFallthrough (B_FALLTHROUGH), + .ArDepth (AR_DEPTH), + .ArFallthrough (AR_FALLTHROUGH), + .RDepth (R_DEPTH), + .RFallthrough (R_FALLTHROUGH), + .req_t (req_t), + .resp_t (resp_t), + .AddrWidth (ADDR_WIDTH), + .DataWidth (DATA_WIDTH), + .IdWidth (ID_WIDTH), + .UserWidth (USER_WIDTH) + ) i_axi_buf ( + .clk_i, + .rst_ni, + .slv_req_i (slv_req), + .slv_resp_o (slv_resp), + .mst_req_o (mst_req), + .mst_resp_i (mst_resp) + ); + +endmodule diff --git a/hw/deps/axi/src/axi_cut.sv b/hw/deps/axi/src/axi_cut.sv new file mode 100644 index 0000000..45bfa96 --- /dev/null +++ b/hw/deps/axi/src/axi_cut.sv @@ -0,0 +1,263 @@ +// Copyright (c) 2014-2018 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. +// +// Fabian Schuiki +// Andreas Kurth + +/// An AXI4 cut. +/// +/// Breaks all combinatorial paths between its input and output. +module axi_cut #( + // bypass enable + parameter bit Bypass = 1'b0, + // AXI channel structs + parameter type aw_chan_t = logic, + parameter type w_chan_t = logic, + parameter type b_chan_t = logic, + parameter type ar_chan_t = logic, + parameter type r_chan_t = logic, + // AXI request & response structs + parameter type req_t = logic, + parameter type resp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + // salve port + input req_t slv_req_i, + output resp_t slv_resp_o, + // master port + output req_t mst_req_o, + input resp_t mst_resp_i +); + + // a spill register for each channel + spill_register #( + .T ( aw_chan_t ), + .Bypass ( Bypass ) + ) i_reg_aw ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.aw_valid ), + .ready_o ( slv_resp_o.aw_ready ), + .data_i ( slv_req_i.aw ), + .valid_o ( mst_req_o.aw_valid ), + .ready_i ( mst_resp_i.aw_ready ), + .data_o ( mst_req_o.aw ) + ); + + spill_register #( + .T ( w_chan_t ), + .Bypass ( Bypass ) + ) i_reg_w ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.w_valid ), + .ready_o ( slv_resp_o.w_ready ), + .data_i ( slv_req_i.w ), + .valid_o ( mst_req_o.w_valid ), + .ready_i ( mst_resp_i.w_ready ), + .data_o ( mst_req_o.w ) + ); + + spill_register #( + .T ( b_chan_t ), + .Bypass ( Bypass ) + ) i_reg_b ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_resp_i.b_valid ), + .ready_o ( mst_req_o.b_ready ), + .data_i ( mst_resp_i.b ), + .valid_o ( slv_resp_o.b_valid ), + .ready_i ( slv_req_i.b_ready ), + .data_o ( slv_resp_o.b ) + ); + + spill_register #( + .T ( ar_chan_t ), + .Bypass ( Bypass ) + ) i_reg_ar ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.ar_valid ), + .ready_o ( slv_resp_o.ar_ready ), + .data_i ( slv_req_i.ar ), + .valid_o ( mst_req_o.ar_valid ), + .ready_i ( mst_resp_i.ar_ready ), + .data_o ( mst_req_o.ar ) + ); + + spill_register #( + .T ( r_chan_t ), + .Bypass ( Bypass ) + ) i_reg_r ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_resp_i.r_valid ), + .ready_o ( mst_req_o.r_ready ), + .data_i ( mst_resp_i.r ), + .valid_o ( slv_resp_o.r_valid ), + .ready_i ( slv_req_i.r_ready ), + .data_o ( slv_resp_o.r ) + ); +endmodule + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +// interface wrapper +module axi_cut_intf #( + // Bypass eneable + parameter bit BYPASS = 1'b0, + // The address width. + parameter int unsigned ADDR_WIDTH = 0, + // The data width. + parameter int unsigned DATA_WIDTH = 0, + // The ID width. + parameter int unsigned ID_WIDTH = 0, + // The user data width. + parameter int unsigned USER_WIDTH = 0 +) ( + input logic clk_i , + input logic rst_ni , + AXI_BUS.Slave in , + AXI_BUS.Master out +); + + typedef logic [ID_WIDTH-1:0] id_t; + typedef logic [ADDR_WIDTH-1:0] addr_t; + typedef logic [DATA_WIDTH-1:0] data_t; + typedef logic [DATA_WIDTH/8-1:0] strb_t; + typedef logic [USER_WIDTH-1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + + req_t slv_req, mst_req; + resp_t slv_resp, mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, in) + `AXI_ASSIGN_FROM_RESP(in, slv_resp) + + `AXI_ASSIGN_FROM_REQ(out, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, out) + + axi_cut #( + .Bypass ( BYPASS ), + .aw_chan_t ( aw_chan_t ), + .w_chan_t ( w_chan_t ), + .b_chan_t ( b_chan_t ), + .ar_chan_t ( ar_chan_t ), + .r_chan_t ( r_chan_t ), + .req_t ( req_t ), + .resp_t ( resp_t ) + ) i_axi_cut ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); + + // Check the invariants. + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (ADDR_WIDTH > 0) else $fatal(1, "Wrong addr width parameter"); + assert (DATA_WIDTH > 0) else $fatal(1, "Wrong data width parameter"); + assert (ID_WIDTH > 0) else $fatal(1, "Wrong id width parameter"); + assert (USER_WIDTH > 0) else $fatal(1, "Wrong user width parameter"); + assert (in.AXI_ADDR_WIDTH == ADDR_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (in.AXI_DATA_WIDTH == DATA_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (in.AXI_ID_WIDTH == ID_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (in.AXI_USER_WIDTH == USER_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_ADDR_WIDTH == ADDR_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_DATA_WIDTH == DATA_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_ID_WIDTH == ID_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_USER_WIDTH == USER_WIDTH) else $fatal(1, "Wrong interface definition"); + end + `endif + // pragma translate_on +endmodule + +module axi_lite_cut_intf #( + // bypass enable + parameter bit BYPASS = 1'b0, + /// The address width. + parameter int unsigned ADDR_WIDTH = 0, + /// The data width. + parameter int unsigned DATA_WIDTH = 0 +) ( + input logic clk_i , + input logic rst_ni , + AXI_LITE.Slave in , + AXI_LITE.Master out +); + + typedef logic [ADDR_WIDTH-1:0] addr_t; + typedef logic [DATA_WIDTH-1:0] data_t; + typedef logic [DATA_WIDTH/8-1:0] strb_t; + + `AXI_LITE_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t) + `AXI_LITE_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t) + `AXI_LITE_TYPEDEF_B_CHAN_T(b_chan_t) + `AXI_LITE_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t) + `AXI_LITE_TYPEDEF_R_CHAN_T(r_chan_t, data_t) + `AXI_LITE_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_LITE_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + + req_t slv_req, mst_req; + resp_t slv_resp, mst_resp; + + `AXI_LITE_ASSIGN_TO_REQ(slv_req, in) + `AXI_LITE_ASSIGN_FROM_RESP(in, slv_resp) + + `AXI_LITE_ASSIGN_FROM_REQ(out, mst_req) + `AXI_LITE_ASSIGN_TO_RESP(mst_resp, out) + + axi_cut #( + .Bypass ( BYPASS ), + .aw_chan_t ( aw_chan_t ), + .w_chan_t ( w_chan_t ), + .b_chan_t ( b_chan_t ), + .ar_chan_t ( ar_chan_t ), + .r_chan_t ( r_chan_t ), + .req_t ( req_t ), + .resp_t ( resp_t ) + ) i_axi_cut ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); + + // Check the invariants. + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (ADDR_WIDTH > 0) else $fatal(1, "Wrong addr width parameter"); + assert (DATA_WIDTH > 0) else $fatal(1, "Wrong data width parameter"); + assert (in.AXI_ADDR_WIDTH == ADDR_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (in.AXI_DATA_WIDTH == DATA_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_ADDR_WIDTH == ADDR_WIDTH) else $fatal(1, "Wrong interface definition"); + assert (out.AXI_DATA_WIDTH == DATA_WIDTH) else $fatal(1, "Wrong interface definition"); + end + `endif + // pragma translate_on +endmodule diff --git a/hw/deps/axi/src/axi_demux.sv b/hw/deps/axi/src/axi_demux.sv new file mode 100644 index 0000000..3cc3120 --- /dev/null +++ b/hw/deps/axi/src/axi_demux.sv @@ -0,0 +1,741 @@ +// Copyright (c) 2019 ETH Zurich and 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. + +// Author: Wolfgang Roenninger + +`include "common_cells/registers.svh" + + + +// axi_demux: Demultiplex an AXI bus from one slave port to multiple master ports. +// See `doc/axi_demux.md` for the documentation, including the definition of parameters and ports. +module axi_demux #( + parameter int unsigned AxiIdWidth = 32'd0, + parameter type aw_chan_t = logic, + parameter type w_chan_t = logic, + parameter type b_chan_t = logic, + parameter type ar_chan_t = logic, + parameter type r_chan_t = logic, + parameter type req_t = logic, + parameter type resp_t = logic, + parameter int unsigned NoMstPorts = 32'd0, + parameter int unsigned MaxTrans = 32'd8, + parameter int unsigned AxiLookBits = 32'd3, + parameter bit FallThrough = 1'b0, + parameter bit SpillAw = 1'b1, + parameter bit SpillW = 1'b0, + parameter bit SpillB = 1'b0, + parameter bit SpillAr = 1'b1, + parameter bit SpillR = 1'b0, + // Dependent parameters, DO NOT OVERRIDE! + parameter int unsigned SelectWidth = (NoMstPorts > 32'd1) ? $clog2(NoMstPorts) : 32'd1, + parameter type select_t = logic [SelectWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + input logic test_i, + // Slave Port + input req_t slv_req_i, + input select_t slv_aw_select_i, + input select_t slv_ar_select_i, + output resp_t slv_resp_o, + // Master Ports + /* verilator lint_off UNOPTFLAT */ + output req_t [NoMstPorts-1:0] mst_reqs_o, + /* verilator lint_on UNOPTFLAT */ + input resp_t [NoMstPorts-1:0] mst_resps_i +); + + localparam int unsigned IdCounterWidth = MaxTrans > 1 ? $clog2(MaxTrans) : 1; + + //-------------------------------------- + // Typedefs for the FIFOs / Queues + //-------------------------------------- + typedef logic [AxiIdWidth-1:0] axi_id_t; + typedef struct packed { + aw_chan_t aw_chan; + select_t aw_select; + } aw_chan_select_t; + typedef struct packed { + ar_chan_t ar_chan; + select_t ar_select; + } ar_chan_select_t; + + // pass through if only one master port + if (NoMstPorts == 32'h1) begin : gen_no_demux + assign mst_reqs_o[0] = slv_req_i; + assign slv_resp_o = mst_resps_i; + // other non degenerate cases + end else begin : gen_demux + + //-------------------------------------- + //-------------------------------------- + // Signal Declarations + //-------------------------------------- + //-------------------------------------- + + //-------------------------------------- + // Write Transaction + //-------------------------------------- + // comes from spill register at input + aw_chan_select_t slv_aw_chan_select; + logic slv_aw_valid, slv_aw_ready; + + // AW ID counter + select_t lookup_aw_select; + logic aw_select_occupied, aw_id_cnt_full; + logic aw_push; + // Upon an ATOP load, inject IDs from the AW into the AR channel + logic atop_inject; + + // W FIFO: stores the decision to which master W beats should go + logic w_fifo_pop; + logic w_fifo_full, w_fifo_empty; + select_t w_select; + + // Register which locks the AW valid signal + logic lock_aw_valid_d, lock_aw_valid_q, load_aw_lock; + logic aw_valid, aw_ready; + + // W channel from spill reg + w_chan_t slv_w_chan; + logic slv_w_valid, slv_w_ready; + + // B channles input into the arbitration + b_chan_t [NoMstPorts-1:0] mst_b_chans; + logic [NoMstPorts-1:0] mst_b_valids, mst_b_readies; + + // B channel to spill register + b_chan_t slv_b_chan; + logic slv_b_valid, slv_b_ready; + + //-------------------------------------- + // Read Transaction + //-------------------------------------- + // comes from spill register at input + ar_chan_select_t slv_ar_chan_select; + logic slv_ar_valid, slv_ar_ready; + + // AR ID counter + select_t lookup_ar_select; + logic ar_select_occupied, ar_id_cnt_full; + logic ar_push; + + // Register which locks the AR valid signel + logic lock_ar_valid_d, lock_ar_valid_q, load_ar_lock; + logic ar_valid, ar_ready; + + // R channles input into the arbitration + r_chan_t [NoMstPorts-1:0] mst_r_chans; + logic [NoMstPorts-1:0] mst_r_valids, mst_r_readies; + + // R channel to spill register + r_chan_t slv_r_chan; + logic slv_r_valid, slv_r_ready; + + //-------------------------------------- + //-------------------------------------- + // Channel Control + //-------------------------------------- + //-------------------------------------- + + //-------------------------------------- + // AW Channel + //-------------------------------------- + // spill register at the channel input + aw_chan_select_t slv_aw_chan_select_in; + assign slv_aw_chan_select_in.aw_chan = slv_req_i.aw; + assign slv_aw_chan_select_in.aw_select = slv_aw_select_i; + + spill_register #( + .T ( aw_chan_select_t ), + .Bypass ( ~SpillAw ) // because module param indicates if we want a spill reg + ) i_aw_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.aw_valid ), + .ready_o ( slv_resp_o.aw_ready ), + .data_i ( slv_aw_chan_select_in ), + .valid_o ( slv_aw_valid ), + .ready_i ( slv_aw_ready ), + .data_o ( slv_aw_chan_select ) + ); + + // Control of the AW handshake + always_comb begin + // AXI Handshakes + slv_aw_ready = 1'b0; + aw_valid = 1'b0; + // `lock_aw_valid`, used to be protocol conform as it is not allowed to deassert + // a valid if there was no corresponding ready. As this process has to be able to inject + // an AXI ID into the counter of the AR channel on an ATOP, there could be a case where + // this process waits on `aw_ready` but in the mean time on the AR channel the counter gets + // full. + lock_aw_valid_d = lock_aw_valid_q; + load_aw_lock = 1'b0; + // AW ID counter and W FIFO + aw_push = 1'b0; + // ATOP injection into ar counter + atop_inject = 1'b0; + // we had an arbitration decision, the valid is locked, wait for the transaction + if (lock_aw_valid_q) begin + aw_valid = 1'b1; + // transaction + if (aw_ready) begin + slv_aw_ready = 1'b1; + lock_aw_valid_d = 1'b0; + load_aw_lock = 1'b1; + atop_inject = slv_aw_chan_select.aw_chan.atop[5]; // inject the ATOP if necessary + end + end else begin + // Process can start handling a transaction if its `i_aw_id_counter` and `w_fifo` have + // space in them. Further check if we could inject something on the AR channel. + if (!aw_id_cnt_full && !w_fifo_full && !ar_id_cnt_full) begin + // there is a valid AW vector make the id lookup and go further, if it passes + if (slv_aw_valid && (!aw_select_occupied || + (slv_aw_chan_select.aw_select == lookup_aw_select))) begin + // connect the handshake + aw_valid = 1'b1; + // push arbitration to the W FIFO regardless, do not wait for the AW transaction + aw_push = 1'b1; + // on AW transaction + if (aw_ready) begin + slv_aw_ready = 1'b1; + atop_inject = slv_aw_chan_select.aw_chan.atop[5]; + // no AW transaction this cycle, lock the decision + end else begin + lock_aw_valid_d = 1'b1; + load_aw_lock = 1'b1; + end + end + end + end + end + + // lock the valid signal, as the selection gets pushed into the W FIFO on first assertion, + // prevent further pushing + `FFLARN(lock_aw_valid_q, lock_aw_valid_d, load_aw_lock, '0, clk_i, rst_ni) + + axi_demux_id_counters #( + .AxiIdBits ( AxiLookBits ), + .CounterWidth ( IdCounterWidth ), + .mst_port_select_t ( select_t ) + ) i_aw_id_counter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .lookup_axi_id_i ( slv_aw_chan_select.aw_chan.id[0+:AxiLookBits] ), + .lookup_mst_select_o ( lookup_aw_select ), + .lookup_mst_select_occupied_o ( aw_select_occupied ), + .full_o ( aw_id_cnt_full ), + .inject_axi_id_i ( '0 ), + .inject_i ( 1'b0 ), + .push_axi_id_i ( slv_aw_chan_select.aw_chan.id[0+:AxiLookBits] ), + .push_mst_select_i ( slv_aw_chan_select.aw_select ), + .push_i ( aw_push ), + .pop_axi_id_i ( slv_b_chan.id[0+:AxiLookBits] ), + .pop_i ( slv_b_valid & slv_b_ready ) + ); + // pop from ID counter on outward transaction + + // FIFO to save W selection + fifo_v3 #( + .FALL_THROUGH ( FallThrough ), + .DEPTH ( MaxTrans ), + .dtype ( select_t ) + ) i_w_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( test_i ), + .full_o ( w_fifo_full ), + .empty_o ( w_fifo_empty ), + .usage_o ( ), + .data_i ( slv_aw_chan_select.aw_select ), + .push_i ( aw_push ), // controlled from proc_aw_chan + .data_o ( w_select ), // where the w beat should go + .pop_i ( w_fifo_pop ) // controlled from proc_w_chan + ); + + //-------------------------------------- + // W Channel + //-------------------------------------- + spill_register #( + .T ( w_chan_t ), + .Bypass ( ~SpillW ) + ) i_w_spill_reg( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.w_valid ), + .ready_o ( slv_resp_o.w_ready ), + .data_i ( slv_req_i.w ), + .valid_o ( slv_w_valid ), + .ready_i ( slv_w_ready ), + .data_o ( slv_w_chan ) + ); + + //-------------------------------------- + // B Channel + //-------------------------------------- + // optional spill register + spill_register #( + .T ( b_chan_t ), + .Bypass ( ~SpillB ) + ) i_b_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_b_valid ), + .ready_o ( slv_b_ready ), + .data_i ( slv_b_chan ), + .valid_o ( slv_resp_o.b_valid ), + .ready_i ( slv_req_i.b_ready ), + .data_o ( slv_resp_o.b ) + ); + + // Arbitration of the different B responses + rr_arb_tree #( + .NumIn ( NoMstPorts ), + .DataType ( b_chan_t ), + .AxiVldRdy( 1'b1 ), + .LockIn ( 1'b1 ) + ) i_b_mux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i( 1'b0 ), + .rr_i ( '0 ), + .req_i ( mst_b_valids ), + .gnt_o ( mst_b_readies ), + .data_i ( mst_b_chans ), + .gnt_i ( slv_b_ready ), + .req_o ( slv_b_valid ), + .data_o ( slv_b_chan ), + .idx_o ( ) + ); + + //-------------------------------------- + // AR Channel + //-------------------------------------- + ar_chan_select_t slv_ar_chan_select_in; + assign slv_ar_chan_select_in.ar_chan = slv_req_i.ar; + // assign slv_ar_chan_select_in.ar_chan = slv_ar_chan_i; + assign slv_ar_chan_select_in.ar_select = slv_ar_select_i; + spill_register #( + .T ( ar_chan_select_t ), + .Bypass ( ~SpillAr ) + ) i_ar_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_req_i.ar_valid ), + .ready_o ( slv_resp_o.ar_ready ), + .data_i ( slv_ar_chan_select_in ), + .valid_o ( slv_ar_valid ), + .ready_i ( slv_ar_ready ), + .data_o ( slv_ar_chan_select ) + ); + + // control of the AR handshake + always_comb begin + // AXI Handshakes + slv_ar_ready = 1'b0; + ar_valid = 1'b0; + // `lock_ar_valid`: Used to be protocol conform as it is not allowed to deassert `ar_valid` + // if there was no corresponding `ar_ready`. There is the possibility that an injection + // of a R response from an `atop` from the AW channel can change the occupied flag of the + // `i_ar_id_counter`, even if it was previously empty. This FF prevents the deassertion. + lock_ar_valid_d = lock_ar_valid_q; + load_ar_lock = 1'b0; + // AR id counter + ar_push = 1'b0; + // The process had an arbitration decision in a previous cycle, the valid is locked, + // wait for the AR transaction. + if (lock_ar_valid_q) begin + ar_valid = 1'b1; + // transaction + if (ar_ready) begin + slv_ar_ready = 1'b1; + ar_push = 1'b1; + lock_ar_valid_d = 1'b0; + load_ar_lock = 1'b1; + end + end else begin + // The process can start handling AR transaction if `i_ar_id_counter` has space. + if (!ar_id_cnt_full) begin + // There is a valid AR, so look the ID up. + if (slv_ar_valid && (!ar_select_occupied || + (slv_ar_chan_select.ar_select == lookup_ar_select))) begin + // connect the AR handshake + ar_valid = 1'b1; + // on transaction + if (ar_ready) begin + slv_ar_ready = 1'b1; + ar_push = 1'b1; + // no transaction this cycle, lock the valid decision! + end else begin + lock_ar_valid_d = 1'b1; + load_ar_lock = 1'b1; + end + end + end + end + end + + // this ff is needed so that ar does not get de-asserted if an atop gets injected + `FFLARN(lock_ar_valid_q, lock_ar_valid_d, load_ar_lock, '0, clk_i, rst_ni) + + axi_demux_id_counters #( + .AxiIdBits ( AxiLookBits ), + .CounterWidth ( IdCounterWidth ), + .mst_port_select_t ( select_t ) + ) i_ar_id_counter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .lookup_axi_id_i ( slv_ar_chan_select.ar_chan.id[0+:AxiLookBits] ), + .lookup_mst_select_o ( lookup_ar_select ), + .lookup_mst_select_occupied_o ( ar_select_occupied ), + .full_o ( ar_id_cnt_full ), + .inject_axi_id_i ( slv_aw_chan_select.aw_chan.id[0+:AxiLookBits] ), + .inject_i ( atop_inject ), + .push_axi_id_i ( slv_ar_chan_select.ar_chan.id[0+:AxiLookBits] ), + .push_mst_select_i ( slv_ar_chan_select.ar_select ), + .push_i ( ar_push ), + .pop_axi_id_i ( slv_r_chan.id[0+:AxiLookBits] ), + .pop_i ( slv_r_valid & slv_r_ready & slv_r_chan.last ) + ); + + //-------------------------------------- + // R Channel + //-------------------------------------- + // optional spill register + spill_register #( + .T ( r_chan_t ), + .Bypass ( ~SpillR ) + ) i_r_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( slv_r_valid ), + .ready_o ( slv_r_ready ), + .data_i ( slv_r_chan ), + .valid_o ( slv_resp_o.r_valid ), + .ready_i ( slv_req_i.r_ready ), + .data_o ( slv_resp_o.r ) + ); + + // Arbitration of the different r responses + rr_arb_tree #( + .NumIn ( NoMstPorts ), + .DataType ( r_chan_t ), + .AxiVldRdy( 1'b1 ), + .LockIn ( 1'b1 ) + ) i_r_mux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i( 1'b0 ), + .rr_i ( '0 ), + .req_i ( mst_r_valids ), + .gnt_o ( mst_r_readies ), + .data_i ( mst_r_chans ), + .gnt_i ( slv_r_ready ), + .req_o ( slv_r_valid ), + .data_o ( slv_r_chan ), + .idx_o ( ) + ); + + // process that defines the individual demuxes and assignments for the arbitration + // as mst_reqs_o has to be drivem from the same always comb block! + always_comb begin + // default assignments + mst_reqs_o = '0; + aw_ready = 1'b0; + slv_w_ready = 1'b0; + w_fifo_pop = 1'b0; + ar_ready = 1'b0; + + for (int unsigned i = 0; i < NoMstPorts; i++) begin + // AW channel + mst_reqs_o[i].aw = slv_aw_chan_select.aw_chan; + mst_reqs_o[i].aw_valid = 1'b0; + if (aw_valid && (slv_aw_chan_select.aw_select == i)) begin + mst_reqs_o[i].aw_valid = 1'b1; + aw_ready = mst_resps_i[i].aw_ready; + end + + // W channel + mst_reqs_o[i].w = slv_w_chan; + mst_reqs_o[i].w_valid = 1'b0; + if (!w_fifo_empty && (w_select == i)) begin + mst_reqs_o[i].w_valid = slv_w_valid; + slv_w_ready = mst_resps_i[i].w_ready; + w_fifo_pop = slv_w_valid & mst_resps_i[i].w_ready & slv_w_chan.last; + end + + // B channel + mst_reqs_o[i].b_ready = mst_b_readies[i]; + + // AR channel + mst_reqs_o[i].ar = slv_ar_chan_select.ar_chan; + mst_reqs_o[i].ar_valid = 1'b0; + if (ar_valid && (slv_ar_chan_select.ar_select == i)) begin + mst_reqs_o[i].ar_valid = 1'b1; + ar_ready = mst_resps_i[i].ar_ready; + end + + // R channel + mst_reqs_o[i].r_ready = mst_r_readies[i]; + end + end + // unpack the response B and R channels for the arbitration + for (genvar i = 0; i < NoMstPorts; i++) begin : gen_b_channels + assign mst_b_chans[i] = mst_resps_i[i].b; + assign mst_b_valids[i] = mst_resps_i[i].b_valid; + assign mst_r_chans[i] = mst_resps_i[i].r; + assign mst_r_valids[i] = mst_resps_i[i].r_valid; + end + + +// Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + no_mst_ports: assume (NoMstPorts > 0) else + $fatal(1, "The Number of slaves (NoMstPorts) has to be at least 1"); + AXI_ID_BITS: assume (AxiIdWidth >= AxiLookBits) else + $fatal(1, "AxiIdBits has to be equal or smaller than AxiIdWidth."); + end + default disable iff (!rst_ni); + aw_select: assume property( @(posedge clk_i) (slv_req_i.aw_valid |-> + (slv_aw_select_i < NoMstPorts))) else + $fatal(1, "slv_aw_select_i is %d: AW has selected a slave that is not defined.\ + NoMstPorts: %d", slv_aw_select_i, NoMstPorts); + ar_select: assume property( @(posedge clk_i) (slv_req_i.ar_valid |-> + (slv_ar_select_i < NoMstPorts))) else + $fatal(1, "slv_ar_select_i is %d: AR has selected a slave that is not defined.\ + NoMstPorts: %d", slv_ar_select_i, NoMstPorts); + aw_valid_stable: assert property( @(posedge clk_i) (aw_valid && !aw_ready) |=> aw_valid) else + $fatal(1, "aw_valid was deasserted, when aw_ready = 0 in last cycle."); + ar_valid_stable: assert property( @(posedge clk_i) + (ar_valid && !ar_ready) |=> ar_valid) else + $fatal(1, "ar_valid was deasserted, when ar_ready = 0 in last cycle."); + aw_stable: assert property( @(posedge clk_i) (aw_valid && !aw_ready) + |=> $stable(slv_aw_chan_select)) else + $fatal(1, "slv_aw_chan_select unstable with valid set."); + ar_stable: assert property( @(posedge clk_i) (ar_valid && !ar_ready) + |=> $stable(slv_ar_chan_select)) else + $fatal(1, "slv_aw_chan_select unstable with valid set."); +`endif +// pragma translate_on + end +endmodule + +module axi_demux_id_counters #( + // the lower bits of the AXI ID that should be considered, results in 2**AXI_ID_BITS counters + parameter int unsigned AxiIdBits = 2, + parameter int unsigned CounterWidth = 4, + parameter type mst_port_select_t = logic +) ( + input clk_i, // Clock + input rst_ni, // Asynchronous reset active low + // lookup + input logic [AxiIdBits-1:0] lookup_axi_id_i, + output mst_port_select_t lookup_mst_select_o, + output logic lookup_mst_select_occupied_o, + // push + output logic full_o, + input logic [AxiIdBits-1:0] push_axi_id_i, + input mst_port_select_t push_mst_select_i, + input logic push_i, + // inject ATOPs in AR channel + input logic [AxiIdBits-1:0] inject_axi_id_i, + input logic inject_i, + // pop + input logic [AxiIdBits-1:0] pop_axi_id_i, + input logic pop_i +); + localparam int unsigned NoCounters = 2**AxiIdBits; + typedef logic [CounterWidth-1:0] cnt_t; + + // registers, each gets loaded when push_en[i] + mst_port_select_t [NoCounters-1:0] mst_select_q; + + // counter signals + logic [NoCounters-1:0] push_en, inject_en, pop_en, occupied, cnt_full; + + //----------------------------------- + // Lookup + //----------------------------------- + assign lookup_mst_select_o = mst_select_q[lookup_axi_id_i]; + assign lookup_mst_select_occupied_o = occupied[lookup_axi_id_i]; + //----------------------------------- + // Push and Pop + //----------------------------------- + assign push_en = (push_i) ? (1 << push_axi_id_i) : '0; + assign inject_en = (inject_i) ? (1 << inject_axi_id_i) : '0; + assign pop_en = (pop_i) ? (1 << pop_axi_id_i) : '0; + assign full_o = |cnt_full; + // counters + for (genvar i = 0; i < NoCounters; i++) begin : gen_counters + logic cnt_en, cnt_down, overflow; + cnt_t cnt_delta, in_flight; + always_comb begin + unique case ({push_en[i], inject_en[i], pop_en[i]}) + 3'b001 : begin // pop_i = -1 + cnt_en = 1'b1; + cnt_down = 1'b1; + cnt_delta = cnt_t'(1); + end + 3'b010 : begin // inject_i = +1 + cnt_en = 1'b1; + cnt_down = 1'b0; + cnt_delta = cnt_t'(1); + end + // 3'b011, inject_i & pop_i = 0 --> use default + 3'b100 : begin // push_i = +1 + cnt_en = 1'b1; + cnt_down = 1'b0; + cnt_delta = cnt_t'(1); + end + // 3'b101, push_i & pop_i = 0 --> use default + 3'b110 : begin // push_i & inject_i = +2 + cnt_en = 1'b1; + cnt_down = 1'b0; + cnt_delta = cnt_t'(2); + end + 3'b111 : begin // push_i & inject_i & pop_i = +1 + cnt_en = 1'b1; + cnt_down = 1'b0; + cnt_delta = cnt_t'(1); + end + default : begin // do nothing to the counters + cnt_en = 1'b0; + cnt_down = 1'b0; + cnt_delta = cnt_t'(0); + end + endcase + end + + delta_counter #( + .WIDTH ( CounterWidth ), + .STICKY_OVERFLOW ( 1'b0 ) + ) i_in_flight_cnt ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clear_i ( 1'b0 ), + .en_i ( cnt_en ), + .load_i ( 1'b0 ), + .down_i ( cnt_down ), + .delta_i ( cnt_delta ), + .d_i ( '0 ), + .q_o ( in_flight ), + .overflow_o ( overflow ) + ); + assign occupied[i] = |in_flight; + assign cnt_full[i] = overflow | (&in_flight); + + // holds the selection signal for this id + `FFLARN(mst_select_q[i], push_mst_select_i, push_en[i], '0, clk_i, rst_ni) + +// pragma translate_off +`ifndef VERILATOR + // Validate parameters. + cnt_underflow: assert property( + @(posedge clk_i) disable iff (~rst_ni) (pop_en[i] |=> !overflow)) else + $fatal(1, "axi_demux_id_counters > Counter: %0d underflowed.\ + The reason is probably a faulty AXI response.", i); +`endif +// pragma translate_on + end +endmodule + +// interface wrapper +`include "axi/assign.svh" +`include "axi/typedef.svh" +module axi_demux_intf #( + parameter int unsigned AXI_ID_WIDTH = 32'd0, // Synopsys DC requires default value for params + parameter int unsigned AXI_ADDR_WIDTH = 32'd0, + parameter int unsigned AXI_DATA_WIDTH = 32'd0, + parameter int unsigned AXI_USER_WIDTH = 32'd0, + parameter int unsigned NO_MST_PORTS = 32'd3, + parameter int unsigned MAX_TRANS = 32'd8, + parameter int unsigned AXI_LOOK_BITS = 32'd3, + parameter bit FALL_THROUGH = 1'b0, + parameter bit SPILL_AW = 1'b1, + parameter bit SPILL_W = 1'b0, + parameter bit SPILL_B = 1'b0, + parameter bit SPILL_AR = 1'b1, + parameter bit SPILL_R = 1'b0, + // Dependent parameters, DO NOT OVERRIDE! + parameter int unsigned SELECT_WIDTH = (NO_MST_PORTS > 32'd1) ? $clog2(NO_MST_PORTS) : 32'd1, + parameter type select_t = logic [SELECT_WIDTH-1:0] // MST port select type +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic test_i, // Testmode enable + input select_t slv_aw_select_i, // has to be stable, when aw_valid + input select_t slv_ar_select_i, // has to be stable, when ar_valid + AXI_BUS.Slave slv, // slave port + AXI_BUS.Master mst [NO_MST_PORTS-1:0] // master ports +); + + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + + req_t slv_req; + resp_t slv_resp; + req_t [NO_MST_PORTS-1:0] mst_req; + resp_t [NO_MST_PORTS-1:0] mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + + for (genvar i = 0; i < NO_MST_PORTS; i++) begin : gen_assign_mst_ports + `AXI_ASSIGN_FROM_REQ(mst[i], mst_req[i]) + `AXI_ASSIGN_TO_RESP(mst_resp[i], mst[i]) + end + + axi_demux #( + .AxiIdWidth ( AXI_ID_WIDTH ), // ID Width + .aw_chan_t ( aw_chan_t ), // AW Channel Type + .w_chan_t ( w_chan_t ), // W Channel Type + .b_chan_t ( b_chan_t ), // B Channel Type + .ar_chan_t ( ar_chan_t ), // AR Channel Type + .r_chan_t ( r_chan_t ), // R Channel Type + .req_t ( req_t ), + .resp_t ( resp_t ), + .NoMstPorts ( NO_MST_PORTS ), + .MaxTrans ( MAX_TRANS ), + .AxiLookBits ( AXI_LOOK_BITS ), + .FallThrough ( FALL_THROUGH ), + .SpillAw ( SPILL_AW ), + .SpillW ( SPILL_W ), + .SpillB ( SPILL_B ), + .SpillAr ( SPILL_AR ), + .SpillR ( SPILL_R ) + ) i_axi_demux ( + .clk_i, // Clock + .rst_ni, // Asynchronous reset active low + .test_i, // Testmode enable + // slave port + .slv_req_i ( slv_req ), + .slv_aw_select_i ( slv_aw_select_i ), + .slv_ar_select_i ( slv_ar_select_i ), + .slv_resp_o ( slv_resp ), + // master port + .mst_reqs_o ( mst_req ), + .mst_resps_i ( mst_resp ) + ); +endmodule diff --git a/hw/deps/axi/src/axi_dw_converter.sv b/hw/deps/axi/src/axi_dw_converter.sv new file mode 100644 index 0000000..d708c62 --- /dev/null +++ b/hw/deps/axi/src/axi_dw_converter.sv @@ -0,0 +1,188 @@ +// Copyright 2020 ETH Zurich and 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. + +// Author: Matheus Cavalcante + +// NOTE: The upsizer/downsizer do not support WRAP and FIXED bursts, and +// will answer with SLVERR upon receiving a burst of such types. + +module axi_dw_converter #( + parameter int unsigned AxiMaxReads = 1 , // Number of outstanding reads + parameter int unsigned AxiSlvPortDataWidth = 8 , // Data width of the slv port + parameter int unsigned AxiMstPortDataWidth = 8 , // Data width of the mst port + parameter int unsigned AxiAddrWidth = 1 , // Address width + parameter int unsigned AxiIdWidth = 1 , // ID width + parameter type aw_chan_t = logic, // AW Channel Type + parameter type mst_w_chan_t = logic, // W Channel Type for the mst port + parameter type slv_w_chan_t = logic, // W Channel Type for the slv port + parameter type b_chan_t = logic, // B Channel Type + parameter type ar_chan_t = logic, // AR Channel Type + parameter type mst_r_chan_t = logic, // R Channel Type for the mst port + parameter type slv_r_chan_t = logic, // R Channel Type for the slv port + parameter type axi_mst_req_t = logic, // AXI Request Type for mst ports + parameter type axi_mst_resp_t = logic, // AXI Response Type for mst ports + parameter type axi_slv_req_t = logic, // AXI Request Type for slv ports + parameter type axi_slv_resp_t = logic // AXI Response Type for slv ports + ) ( + input logic clk_i, + input logic rst_ni, + // Slave interface + input axi_slv_req_t slv_req_i, + output axi_slv_resp_t slv_resp_o, + // Master interface + output axi_mst_req_t mst_req_o, + input axi_mst_resp_t mst_resp_i + ); + + if (AxiMstPortDataWidth == AxiSlvPortDataWidth) begin: gen_no_dw_conversion + assign mst_req_o = slv_req_i ; + assign slv_resp_o = mst_resp_i; + end : gen_no_dw_conversion + + if (AxiMstPortDataWidth > AxiSlvPortDataWidth) begin: gen_dw_upsize + axi_dw_upsizer #( + .AxiMaxReads (AxiMaxReads ), + .AxiSlvPortDataWidth(AxiSlvPortDataWidth), + .AxiMstPortDataWidth(AxiMstPortDataWidth), + .AxiAddrWidth (AxiAddrWidth ), + .AxiIdWidth (AxiIdWidth ), + .aw_chan_t (aw_chan_t ), + .mst_w_chan_t (mst_w_chan_t ), + .slv_w_chan_t (slv_w_chan_t ), + .b_chan_t (b_chan_t ), + .ar_chan_t (ar_chan_t ), + .mst_r_chan_t (mst_r_chan_t ), + .slv_r_chan_t (slv_r_chan_t ), + .axi_mst_req_t (axi_mst_req_t ), + .axi_mst_resp_t (axi_mst_resp_t ), + .axi_slv_req_t (axi_slv_req_t ), + .axi_slv_resp_t (axi_slv_resp_t ) + ) i_axi_dw_upsizer ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + // Slave interface + .slv_req_i (slv_req_i ), + .slv_resp_o(slv_resp_o), + // Master interface + .mst_req_o (mst_req_o ), + .mst_resp_i(mst_resp_i) + ); + end : gen_dw_upsize + + if (AxiMstPortDataWidth < AxiSlvPortDataWidth) begin: gen_dw_downsize + axi_dw_downsizer #( + .AxiMaxReads (AxiMaxReads ), + .AxiSlvPortDataWidth(AxiSlvPortDataWidth), + .AxiMstPortDataWidth(AxiMstPortDataWidth), + .AxiAddrWidth (AxiAddrWidth ), + .AxiIdWidth (AxiIdWidth ), + .aw_chan_t (aw_chan_t ), + .mst_w_chan_t (mst_w_chan_t ), + .slv_w_chan_t (slv_w_chan_t ), + .b_chan_t (b_chan_t ), + .ar_chan_t (ar_chan_t ), + .mst_r_chan_t (mst_r_chan_t ), + .slv_r_chan_t (slv_r_chan_t ), + .axi_mst_req_t (axi_mst_req_t ), + .axi_mst_resp_t (axi_mst_resp_t ), + .axi_slv_req_t (axi_slv_req_t ), + .axi_slv_resp_t (axi_slv_resp_t ) + ) i_axi_dw_downsizer ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + // Slave interface + .slv_req_i (slv_req_i ), + .slv_resp_o(slv_resp_o), + // Master interface + .mst_req_o (mst_req_o ), + .mst_resp_i(mst_resp_i) + ); + end : gen_dw_downsize + +endmodule : axi_dw_converter + +// Interface wrapper + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module axi_dw_converter_intf #( + parameter int unsigned AXI_ID_WIDTH = 1, + parameter int unsigned AXI_ADDR_WIDTH = 1, + parameter int unsigned AXI_SLV_PORT_DATA_WIDTH = 8, + parameter int unsigned AXI_MST_PORT_DATA_WIDTH = 8, + parameter int unsigned AXI_USER_WIDTH = 0, + parameter int unsigned AXI_MAX_READS = 8 + ) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Slave slv, + AXI_BUS.Master mst + ); + + typedef logic [AXI_ID_WIDTH-1:0] id_t ; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t ; + typedef logic [AXI_MST_PORT_DATA_WIDTH-1:0] mst_data_t ; + typedef logic [AXI_MST_PORT_DATA_WIDTH/8-1:0] mst_strb_t; + typedef logic [AXI_SLV_PORT_DATA_WIDTH-1:0] slv_data_t ; + typedef logic [AXI_SLV_PORT_DATA_WIDTH/8-1:0] slv_strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t ; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(mst_w_chan_t, mst_data_t, mst_strb_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(slv_w_chan_t, slv_data_t, slv_strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(mst_r_chan_t, mst_data_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(slv_r_chan_t, slv_data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(mst_req_t, aw_chan_t, mst_w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(mst_resp_t, b_chan_t, mst_r_chan_t) + `AXI_TYPEDEF_REQ_T(slv_req_t, aw_chan_t, slv_w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(slv_resp_t, b_chan_t, slv_r_chan_t) + + slv_req_t slv_req; + slv_resp_t slv_resp; + mst_req_t mst_req; + mst_resp_t mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_dw_converter #( + .AxiMaxReads ( AXI_MAX_READS ), + .AxiSlvPortDataWidth( AXI_SLV_PORT_DATA_WIDTH ), + .AxiMstPortDataWidth( AXI_MST_PORT_DATA_WIDTH ), + .AxiAddrWidth ( AXI_ADDR_WIDTH ), + .AxiIdWidth ( AXI_ID_WIDTH ), + .aw_chan_t ( aw_chan_t ), + .mst_w_chan_t ( mst_w_chan_t ), + .slv_w_chan_t ( slv_w_chan_t ), + .b_chan_t ( b_chan_t ), + .ar_chan_t ( ar_chan_t ), + .mst_r_chan_t ( mst_r_chan_t ), + .slv_r_chan_t ( slv_r_chan_t ), + .axi_mst_req_t ( mst_req_t ), + .axi_mst_resp_t ( mst_resp_t ), + .axi_slv_req_t ( slv_req_t ), + .axi_slv_resp_t ( slv_resp_t ) + ) i_axi_dw_converter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + // slave port + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + // master port + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); + +endmodule : axi_dw_converter_intf diff --git a/hw/deps/axi/src/axi_dw_downsizer.sv b/hw/deps/axi/src/axi_dw_downsizer.sv new file mode 100644 index 0000000..dee4ba3 --- /dev/null +++ b/hw/deps/axi/src/axi_dw_downsizer.sv @@ -0,0 +1,767 @@ +// Copyright 2020 ETH Zurich and 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. + +// Author: Matheus Cavalcante + +// Description: +// Data width downsize conversion. +// Connects a wide master to a narrower slave. + +// NOTE: The downsizer does not support WRAP and FIXED bursts, and +// will answer with SLVERR upon receiving a burst of such types. + +module axi_dw_downsizer #( + parameter int unsigned AxiMaxReads = 1 , // Number of outstanding reads + parameter int unsigned AxiSlvPortDataWidth = 8 , // Data width of the slv port + parameter int unsigned AxiMstPortDataWidth = 8 , // Data width of the mst port + parameter int unsigned AxiAddrWidth = 1 , // Address width + parameter int unsigned AxiIdWidth = 1 , // ID width + parameter type aw_chan_t = logic, // AW Channel Type + parameter type mst_w_chan_t = logic, // W Channel Type for mst port + parameter type slv_w_chan_t = logic, // W Channel Type for slv port + parameter type b_chan_t = logic, // B Channel Type + parameter type ar_chan_t = logic, // AR Channel Type + parameter type mst_r_chan_t = logic, // R Channel Type for mst port + parameter type slv_r_chan_t = logic, // R Channel Type for slv port + parameter type axi_mst_req_t = logic, // AXI Request Type for mst ports + parameter type axi_mst_resp_t = logic, // AXI Response Type for mst ports + parameter type axi_slv_req_t = logic, // AXI Request Type for slv ports + parameter type axi_slv_resp_t = logic // AXI Response Type for slv ports + ) ( + input logic clk_i, + input logic rst_ni, + // Slave interface + input axi_slv_req_t slv_req_i, + output axi_slv_resp_t slv_resp_o, + // Master interface + output axi_mst_req_t mst_req_o, + input axi_mst_resp_t mst_resp_i + ); + + /***************** + * DEFINITIONS * + *****************/ + import axi_pkg::aligned_addr; + + // Type used to index which adapter is handling each outstanding transaction. + localparam TranIdWidth = AxiMaxReads > 1 ? $clog2(AxiMaxReads) : 1; + typedef logic [TranIdWidth-1:0] tran_id_t; + + // Data width + localparam AxiSlvPortStrbWidth = AxiSlvPortDataWidth / 8; + localparam AxiMstPortStrbWidth = AxiMstPortDataWidth / 8; + + localparam AxiSlvPortMaxSize = $clog2(AxiSlvPortStrbWidth); + localparam AxiMstPortMaxSize = $clog2(AxiMstPortStrbWidth); + + localparam SlvPortByteMask = AxiSlvPortStrbWidth - 1; + localparam MstPortByteMask = AxiMstPortStrbWidth - 1; + + // Address width + typedef logic [AxiAddrWidth-1:0] addr_t; + + // ID width + typedef logic [AxiIdWidth-1:0] id_t; + + // Length of burst after upsizing + typedef logic [$clog2(AxiSlvPortStrbWidth/AxiMstPortStrbWidth) + 7:0] burst_len_t; + + // Internal AXI bus + axi_mst_req_t mst_req; + axi_mst_resp_t mst_resp; + + /************** + * ARBITERS * + **************/ + + // R + + slv_r_chan_t [AxiMaxReads-1:0] slv_r_tran; + logic [AxiMaxReads-1:0] slv_r_valid_tran; + logic [AxiMaxReads-1:0] slv_r_ready_tran; + + rr_arb_tree #( + .NumIn (AxiMaxReads ), + .DataType (slv_r_chan_t), + .AxiVldRdy(1'b1 ), + .ExtPrio (1'b0 ), + .LockIn (1'b1 ) + ) i_slv_r_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + .rr_i ('0 ), + .req_i (slv_r_valid_tran ), + .gnt_o (slv_r_ready_tran ), + .data_i (slv_r_tran ), + .gnt_i (slv_req_i.r_ready ), + .req_o (slv_resp_o.r_valid), + .data_o (slv_resp_o.r ), + .idx_o (/* Unused */ ) + ); + + logic [AxiMaxReads-1:0] mst_r_ready_tran; + assign mst_req.r_ready = |mst_r_ready_tran; + + // AR + + id_t arb_slv_ar_id; + logic arb_slv_ar_req; + logic arb_slv_ar_gnt; + logic [AxiMaxReads-1:0] arb_slv_ar_gnt_tran; + // Multiplex AR slave between AR and AW for the injection of atomic operations with an R response. + logic inject_aw_into_ar; + logic inject_aw_into_ar_req; + logic inject_aw_into_ar_gnt; + + assign arb_slv_ar_gnt = |arb_slv_ar_gnt_tran; + + rr_arb_tree #( + .NumIn (2 ), + .DataWidth (AxiIdWidth), + .ExtPrio (1'b0 ), + .AxiVldRdy (1'b1 ), + .LockIn (1'b0 ) + ) i_slv_ar_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i (1'b0 ), + .rr_i ('0 ), + .req_i ({inject_aw_into_ar_req, slv_req_i.ar_valid} ), + .gnt_o ({inject_aw_into_ar_gnt, slv_resp_o.ar_ready}), + .data_i ({slv_req_i.aw.id, slv_req_i.ar.id} ), + .req_o (arb_slv_ar_req ), + .gnt_i (arb_slv_ar_gnt ), + .data_o (arb_slv_ar_id ), + .idx_o (inject_aw_into_ar ) + ); + + ar_chan_t [AxiMaxReads-1:0] mst_ar_tran; + id_t [AxiMaxReads-1:0] mst_ar_id; + logic [AxiMaxReads-1:0] mst_ar_valid_tran; + logic [AxiMaxReads-1:0] mst_ar_ready_tran; + tran_id_t mst_req_idx; + + rr_arb_tree #( + .NumIn (AxiMaxReads), + .DataType (ar_chan_t ), + .AxiVldRdy(1'b1 ), + .ExtPrio (1'b0 ), + .LockIn (1'b1 ) + ) i_mst_ar_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + .rr_i ('0 ), + .req_i (mst_ar_valid_tran), + .gnt_o (mst_ar_ready_tran), + .data_i (mst_ar_tran ), + .gnt_i (mst_resp.ar_ready), + .req_o (mst_req.ar_valid ), + .data_o (mst_req.ar ), + .idx_o (mst_req_idx ) + ); + + /***************** + * ERROR SLAVE * + *****************/ + + axi_mst_req_t axi_err_req; + axi_mst_resp_t axi_err_resp; + + axi_err_slv #( + .AxiIdWidth(AxiIdWidth ), + .Resp (axi_pkg::RESP_SLVERR), + .req_t (axi_mst_req_t ), + .resp_t (axi_mst_resp_t ) + ) i_axi_err_slv ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_req_i (axi_err_req ), + .slv_resp_o(axi_err_resp) + ); + + /*********** + * DEMUX * + ***********/ + + // Requests can be sent either to the error slave, + // or to the DWC's master port. + + logic [AxiMaxReads-1:0] mst_req_ar_err; + logic mst_req_aw_err; + + axi_demux #( + .AxiIdWidth (AxiIdWidth ), + .AxiLookBits(AxiIdWidth ), + .aw_chan_t (aw_chan_t ), + .w_chan_t (mst_w_chan_t ), + .b_chan_t (b_chan_t ), + .ar_chan_t (ar_chan_t ), + .r_chan_t (mst_r_chan_t ), + .req_t (axi_mst_req_t ), + .resp_t (axi_mst_resp_t), + .NoMstPorts (2 ), + .MaxTrans (AxiMaxReads ), + .SpillAw (1'b1 ) // Required to break dependency between AW and W channels + ) i_axi_demux ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .mst_reqs_o ({axi_err_req, mst_req_o} ), + .mst_resps_i ({axi_err_resp, mst_resp_i} ), + .slv_ar_select_i(mst_req_ar_err[mst_req_idx]), + .slv_aw_select_i(mst_req_aw_err ), + .slv_req_i (mst_req ), + .slv_resp_o (mst_resp ) + ); + + /********** + * READ * + **********/ + + typedef enum logic [1:0] { + R_IDLE , + R_PASSTHROUGH , + R_INCR_DOWNSIZE, + R_SPLIT_INCR_DOWNSIZE + } r_state_e; + + typedef struct packed { + ar_chan_t ar ; + logic ar_valid ; + logic ar_throw_error ; + slv_r_chan_t r ; + logic r_valid ; + burst_len_t burst_len ; + axi_pkg::size_t orig_ar_size; + } r_req_t; + + // Decide which downsizer will handle the incoming AXI transaction + logic [AxiMaxReads-1:0] idle_read_downsizer; + tran_id_t idx_ar_downsizer; + + // Find an idle downsizer to handle this transaction + tran_id_t idx_idle_downsizer; + lzc #( + .WIDTH(AxiMaxReads) + ) i_idle_lzc ( + .in_i (idle_read_downsizer), + .cnt_o (idx_idle_downsizer ), + .empty_o(/* Unused */ ) + ); + + // Is there already another downsizer handling a transaction with the same id + logic [AxiMaxReads-1:0] id_clash_downsizer; + tran_id_t idx_id_clash_downsizer; + for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_id_clash + assign id_clash_downsizer[t] = arb_slv_ar_id == mst_ar_id[t] && !idle_read_downsizer[t]; + end + + onehot_to_bin #( + .ONEHOT_WIDTH(AxiMaxReads) + ) i_id_clash_onehot_to_bin ( + .onehot(id_clash_downsizer ), + .bin (idx_id_clash_downsizer) + ); + + // Choose an idle downsizer, unless there is an id clash + assign idx_ar_downsizer = (|id_clash_downsizer) ? idx_id_clash_downsizer : idx_idle_downsizer; + + // This ID queue is used to resolve which downsizer is handling + // each outstanding read transaction. + + logic [AxiMaxReads-1:0] idqueue_push; + logic [AxiMaxReads-1:0] idqueue_pop; + tran_id_t idqueue_id; + logic idqueue_valid; + + id_queue #( + .ID_WIDTH(AxiIdWidth ), + .CAPACITY(AxiMaxReads), + .data_t (tran_id_t ) + ) i_read_id_queue ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .inp_id_i (arb_slv_ar_id ), + .inp_data_i (idx_ar_downsizer), + .inp_req_i (|idqueue_push ), + .inp_gnt_o (/* Unused */ ), + .oup_id_i (mst_resp.r.id ), + .oup_pop_i (|idqueue_pop ), + .oup_req_i (1'b1 ), + .oup_data_o (idqueue_id ), + .oup_data_valid_o(idqueue_valid ), + .oup_gnt_o (/* Unused */ ), + .exists_data_i ('0 ), + .exists_mask_i ('0 ), + .exists_req_i ('0 ), + .exists_o (/* Unused */ ), + .exists_gnt_o (/* Unused */ ) + ); + + for (genvar t = 0; unsigned'(t) < AxiMaxReads; t++) begin: gen_read_downsizer + r_state_e r_state_d, r_state_q; + r_req_t r_req_d , r_req_q ; + + // Are we idle? + assign idle_read_downsizer[t] = (r_state_q == R_IDLE); + + always_comb begin + // Maintain state + r_state_d = r_state_q; + r_req_d = r_req_q ; + + // AR Channel + mst_ar_tran[t] = r_req_q.ar ; + mst_ar_id[t] = r_req_q.ar.id ; + mst_ar_valid_tran[t] = r_req_q.ar_valid; + + // Throw an error + mst_req_ar_err[t] = r_req_q.ar_throw_error; + + // R Channel + slv_r_tran[t] = r_req_q.r ; + slv_r_valid_tran[t] = r_req_q.r_valid; + + idqueue_push[t] = '0; + idqueue_pop[t] = '0; + + arb_slv_ar_gnt_tran[t] = 1'b0; + + mst_r_ready_tran[t] = 1'b0; + + // Got a grant on the AR channel + if (mst_ar_valid_tran[t] && mst_ar_ready_tran[t]) begin + r_req_d.ar_valid = 1'b0; + r_req_d.ar_throw_error = 1'b0; + end + + case (r_state_q) + R_IDLE : begin + // Reset channels + r_req_d.ar = '0; + r_req_d.r = '0; + + // New read request + if (arb_slv_ar_req && (idx_ar_downsizer == t)) begin + arb_slv_ar_gnt_tran[t] = 1'b1; + // Push to ID queue + idqueue_push[t] = 1'b1; + + // Default state + r_state_d = R_PASSTHROUGH; + + // Save beat + r_req_d.ar = slv_req_i.ar ; + r_req_d.ar_valid = 1'b1 ; + r_req_d.burst_len = slv_req_i.ar.len ; + r_req_d.orig_ar_size = slv_req_i.ar.size; + if (inject_aw_into_ar) begin + r_req_d.ar.id = slv_req_i.aw.id ; + r_req_d.ar.addr = slv_req_i.aw.addr ; + r_req_d.ar.size = slv_req_i.aw.size ; + r_req_d.ar.burst = slv_req_i.aw.burst ; + r_req_d.ar.len = slv_req_i.aw.len ; + r_req_d.ar.lock = slv_req_i.aw.lock ; + r_req_d.ar.cache = slv_req_i.aw.cache ; + r_req_d.ar.prot = slv_req_i.aw.prot ; + r_req_d.ar.qos = slv_req_i.aw.qos ; + r_req_d.ar.region = slv_req_i.aw.region; + r_req_d.ar.user = slv_req_i.aw.user ; + r_req_d.ar_valid = 1'b0 ; // Injected "AR"s from AW are not valid. + r_req_d.burst_len = slv_req_i.aw.len ; + r_req_d.orig_ar_size = slv_req_i.aw.size ; + end + + case (r_req_d.ar.burst) + axi_pkg::BURST_INCR : begin + // Modifiable transaction + if (|(r_req_d.ar.cache & axi_pkg::CACHE_MODIFIABLE)) begin + // Evaluate downsize ratio + automatic addr_t size_mask = (1 << r_req_d.ar.size) - 1 ; + automatic addr_t conv_ratio = ((1 << r_req_d.ar.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth; + + // Evaluate output burst length + automatic addr_t align_adj = (r_req_d.ar.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth; + r_req_d.burst_len = (r_req_d.ar.len + 1) * conv_ratio - align_adj - 1 ; + + if (conv_ratio != 1) begin + r_req_d.ar.size = AxiMstPortMaxSize; + + if (r_req_d.burst_len <= 255) begin + r_state_d = R_INCR_DOWNSIZE ; + r_req_d.ar.len = r_req_d.burst_len; + end else begin + r_state_d = R_SPLIT_INCR_DOWNSIZE; + r_req_d.ar.len = 255 - align_adj ; + end + end + // Non-modifiable transaction + end else begin + // Incoming transaction is wider than the master bus + if (r_req_d.ar.size > AxiMstPortMaxSize) begin + r_req_d.ar_throw_error = 1'b1 ; + r_state_d = R_PASSTHROUGH; + end + end + end + + axi_pkg::BURST_WRAP: begin + // The DW converter does not support this kind of burst ... + r_state_d = R_PASSTHROUGH; + r_req_d.ar_throw_error = 1'b1 ; + + // ... but might if this is a narrow single-beat transaction + if (r_req_d.ar.len == '0 && r_req_d.ar.size <= AxiMstPortMaxSize) + r_req_d.ar_throw_error = 1'b0; + end + + axi_pkg::BURST_FIXED: begin + // The DW converter does not support this kind of burst ... + r_state_d = R_PASSTHROUGH; + r_req_d.ar_throw_error = 1'b1 ; + + // ... but might if this is a narrow single-beat transaction + if (r_req_d.ar.len == '0 && r_req_d.ar.size <= AxiMstPortMaxSize) + r_req_d.ar_throw_error = 1'b0; + end + endcase + end + end + + R_PASSTHROUGH, R_INCR_DOWNSIZE, R_SPLIT_INCR_DOWNSIZE: begin + // Got a grant on the R channel + if (slv_r_valid_tran[t] && slv_r_ready_tran[t]) begin + r_req_d.r = '0 ; + r_req_d.r_valid = 1'b0; + end + + // Request was accepted + if (!r_req_q.ar_valid) + // Our turn + if ((idqueue_id == t) && idqueue_valid) + // Ready to accept more data + if (!slv_r_valid_tran[t] || (slv_r_valid_tran[t] && slv_r_ready_tran[t])) begin + mst_r_ready_tran[t] = 1'b1; + + if (mst_resp.r_valid) begin + automatic addr_t mst_port_offset = r_req_q.ar.addr[(AxiMstPortStrbWidth == 1 ? 1 : $clog2(AxiMstPortStrbWidth)) - 1:0]; + automatic addr_t slv_port_offset = r_req_q.ar.addr[(AxiSlvPortStrbWidth == 1 ? 1 : $clog2(AxiSlvPortStrbWidth)) - 1:0]; + + // Serialization + for (int b = 0; b < AxiSlvPortStrbWidth; b++) + if ((b >= slv_port_offset) && + (b - slv_port_offset < (1 << r_req_q.orig_ar_size)) && + (b + mst_port_offset - slv_port_offset < AxiMstPortStrbWidth)) begin + r_req_d.r.data[8*b +: 8] = mst_resp.r.data[8*(b + mst_port_offset - slv_port_offset) +: 8]; + end + + r_req_d.burst_len = r_req_q.burst_len - 1 ; + r_req_d.ar.len = r_req_q.ar.len - 1 ; + r_req_d.ar.addr = aligned_addr(r_req_q.ar.addr, r_req_q.ar.size) + (1 << r_req_q.ar.size); + r_req_d.r.last = (r_req_q.burst_len == 0) ; + r_req_d.r.id = mst_resp.r.id ; + r_req_d.r.resp = mst_resp.r.resp ; + r_req_d.r.user = mst_resp.r.user ; + + if (r_req_q.burst_len == 0) + idqueue_pop[t] = 1'b1; + + case (r_state_q) + R_PASSTHROUGH : + // Forward data as soon as we can + r_req_d.r_valid = 1'b1; + + R_INCR_DOWNSIZE, R_SPLIT_INCR_DOWNSIZE: + // Forward when the burst is finished, or after filling up a word + if (r_req_q.burst_len == 0 || (aligned_addr(r_req_d.ar.addr, r_req_q.orig_ar_size) != aligned_addr(r_req_q.ar.addr, r_req_q.orig_ar_size))) + r_req_d.r_valid = 1'b1; + endcase + + // Trigger another burst request, if needed + if (r_state_q == R_SPLIT_INCR_DOWNSIZE) + // Finished current burst, but whole transaction hasn't finished + if (r_req_q.ar.len == '0 && r_req_q.burst_len != '0) begin + r_req_d.ar_valid = 1'b1; + r_req_d.ar.len = (r_req_d.burst_len <= 255) ? r_req_d.burst_len : 255; + end + end + end + + if (slv_r_valid_tran[t] && slv_r_ready_tran[t]) + if (r_req_q.burst_len == '1) + r_state_d = R_IDLE; + end + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + r_state_q <= R_IDLE; + r_req_q <= '0 ; + end else begin + r_state_q <= r_state_d; + r_req_q <= r_req_d ; + end + end + end : gen_read_downsizer + + /*********** + * WRITE * + ***********/ + typedef enum logic [1:0] { + W_IDLE , + W_PASSTHROUGH , + W_INCR_DOWNSIZE, + W_SPLIT_INCR_DOWNSIZE + } w_state_e; + + typedef struct packed { + aw_chan_t aw ; + logic aw_valid ; + logic aw_throw_error ; + burst_len_t burst_len ; + axi_pkg::size_t orig_aw_size; + } w_req_t; + + w_state_e w_state_d, w_state_q; + w_req_t w_req_d, w_req_q; + + // This FIFO holds the number of bursts generated by each write transactions handled by this downsizer. + // This is used to forward only the correct B beats to the slave. + logic forward_b_beat_i; + logic forward_b_beat_o; + logic forward_b_beat_push; + logic forward_b_beat_pop; + logic forward_b_beat_full; + + fifo_v3 #( + .DATA_WIDTH (1 ), + .DEPTH (AxiMaxReads), + .FALL_THROUGH(1'b1 ) + ) i_forward_b_beats_queue ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i (1'b0 ), + .testmode_i(1'b0 ), + .data_i (forward_b_beat_i ), + .push_i (forward_b_beat_push ), + .full_o (forward_b_beat_full ), + .data_o (forward_b_beat_o ), + .pop_i (forward_b_beat_pop ), + .empty_o (/* Unused */ ), + .usage_o (/* Unused */ ) + ); + + always_comb begin + inject_aw_into_ar_req = 1'b0; + + // i_num_b_beats default state + forward_b_beat_i = '0 ; + forward_b_beat_push = 1'b0; + forward_b_beat_pop = 1'b0; + + // Maintain state + w_state_d = w_state_q; + w_req_d = w_req_q ; + + // AW Channel + mst_req.aw = w_req_q.aw ; + mst_req.aw_valid = w_req_q.aw_valid; + slv_resp_o.aw_ready = '0 ; + + // Throw an error. + mst_req_aw_err = w_req_q.aw_throw_error; + + // W Channel + mst_req.w = '0; + mst_req.w_valid = '0; + slv_resp_o.w_ready = '0; + + // B Channel (No latency) + slv_resp_o.b = mst_resp.b; + + // Each write transaction might trigger several B beats on the master (narrow) side. + // Only forward the last B beat of each transaction. + if (forward_b_beat_o) begin + slv_resp_o.b_valid = mst_resp.b_valid ; + mst_req.b_ready = slv_req_i.b_ready; + + // Got an ack on the B channel. Pop transaction. + if (mst_req.b_ready && mst_resp.b_valid) + forward_b_beat_pop = 1'b1; + end else begin + // Otherwise, just acknowlegde the B beats + slv_resp_o.b_valid = 1'b0 ; + mst_req.b_ready = 1'b1 ; + forward_b_beat_pop = mst_resp.b_valid; + end + + // Got a grant on the AW channel + if (mst_req.aw_valid & mst_resp.aw_ready) begin + w_req_d.aw_valid = 1'b0; + w_req_d.aw_throw_error = 1'b0; + end + + case (w_state_q) + W_PASSTHROUGH, W_INCR_DOWNSIZE, W_SPLIT_INCR_DOWNSIZE: begin + // Request was accepted + if (!w_req_q.aw_valid) + if (slv_req_i.w_valid) begin + automatic addr_t mst_port_offset = w_req_q.aw.addr[(AxiMstPortStrbWidth == 1 ? 1 : $clog2(AxiMstPortStrbWidth)) - 1:0]; + automatic addr_t slv_port_offset = w_req_q.aw.addr[(AxiSlvPortStrbWidth == 1 ? 1 : $clog2(AxiSlvPortStrbWidth)) - 1:0]; + + // Valid output + mst_req.w_valid = 1'b1 ; + mst_req.w.last = w_req_q.aw.len == 0; + mst_req.w.user = slv_req_i.w.user ; + + // Lane steering + for (int b = 0; b < AxiSlvPortStrbWidth; b++) + if ((b >= slv_port_offset) && + (b - slv_port_offset < (1 << w_req_q.orig_aw_size)) && + (b + mst_port_offset - slv_port_offset < AxiMstPortStrbWidth)) begin + mst_req.w.data[8*(b + mst_port_offset - slv_port_offset) +: 8] = slv_req_i.w.data[8*b +: 8]; + mst_req.w.strb[b + mst_port_offset - slv_port_offset] = slv_req_i.w.strb[b] ; + end + end + + // Acknowledgment + if (mst_resp.w_ready && mst_req.w_valid) begin + w_req_d.burst_len = w_req_q.burst_len - 1 ; + w_req_d.aw.len = w_req_q.aw.len - 1 ; + w_req_d.aw.addr = aligned_addr(w_req_q.aw.addr, w_req_q.aw.size) + (1 << w_req_q.aw.size); + + case (w_state_q) + W_PASSTHROUGH: + slv_resp_o.w_ready = 1'b1; + + W_INCR_DOWNSIZE, W_SPLIT_INCR_DOWNSIZE: + if (w_req_q.burst_len == 0 || (aligned_addr(w_req_d.aw.addr, w_req_q.orig_aw_size) != aligned_addr(w_req_q.aw.addr, w_req_q.orig_aw_size))) + slv_resp_o.w_ready = 1'b1; + endcase + + // Trigger another burst request, if needed + if (w_state_q == W_SPLIT_INCR_DOWNSIZE) + // Finished current burst, but whole transaction hasn't finished + if (w_req_q.aw.len == '0 && w_req_q.burst_len != '0 && !forward_b_beat_full) begin + w_req_d.aw_valid = 1'b1; + w_req_d.aw.len = (w_req_d.burst_len <= 255) ? w_req_d.burst_len : 255; + + // We will receive an extraneous B beat. Ignore it. + forward_b_beat_i = 1'b0; + forward_b_beat_push = 1'b1; + end + + if (w_req_q.burst_len == 0 && !forward_b_beat_full) begin + w_state_d = W_IDLE; + + forward_b_beat_push = 1'b1; + forward_b_beat_i = 1'b1; + end + end + end + endcase + + // Can start a new request as soon as w_state_d is W_IDLE + if (w_state_d == W_IDLE) begin + // Reset channels + w_req_d.aw = '0 ; + w_req_d.aw_valid = 1'b0; + w_req_d.aw_throw_error = 1'b0; + + if (slv_req_i.aw_valid && slv_req_i.aw.atop[5]) begin // ATOP with an R response + inject_aw_into_ar_req = 1'b1 ; + slv_resp_o.aw_ready = inject_aw_into_ar_gnt; + end else begin // Regular AW + slv_resp_o.aw_ready = 1'b1; + end + + // New write request + if (slv_req_i.aw_valid && slv_resp_o.aw_ready && !forward_b_beat_full) begin + // Default state + w_state_d = W_PASSTHROUGH; + + // Save beat + w_req_d.aw = slv_req_i.aw ; + w_req_d.aw_valid = 1'b1 ; + w_req_d.burst_len = slv_req_i.aw.len ; + w_req_d.orig_aw_size = slv_req_i.aw.size; + + case (slv_req_i.aw.burst) + axi_pkg::BURST_INCR: begin + // Modifiable transaction + if (|(slv_req_i.aw.cache & axi_pkg::CACHE_MODIFIABLE)) begin + // Evaluate downsize ratio + automatic addr_t size_mask = (1 << slv_req_i.aw.size) - 1 ; + automatic addr_t conv_ratio = ((1 << slv_req_i.aw.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth; + + // Evaluate output burst length + automatic addr_t align_adj = (slv_req_i.aw.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth; + w_req_d.burst_len = (slv_req_i.aw.len + 1) * conv_ratio - align_adj - 1 ; + + if (conv_ratio != 1) begin + w_req_d.aw.size = AxiMstPortMaxSize; + + if (w_req_d.burst_len <= 255) begin + w_state_d = W_INCR_DOWNSIZE ; + w_req_d.aw.len = w_req_d.burst_len; + end else begin + w_state_d = W_SPLIT_INCR_DOWNSIZE; + w_req_d.aw.len = 255 - align_adj ; + end + end + // Non-modifiable transaction. + end else begin + // Incoming transaction is wider than the master bus. + if (slv_req_i.aw.size > AxiMstPortMaxSize) begin + w_state_d = W_PASSTHROUGH; + w_req_d.aw_throw_error = 1'b1 ; + end + end + end + + axi_pkg::BURST_WRAP: begin + // The DW converter does not support this kind of burst ... + w_state_d = W_PASSTHROUGH; + w_req_d.aw_throw_error = 1'b1 ; + + // ... but might if this is a narrow single-beat transaction + if (slv_req_i.aw.size <= AxiSlvPortMaxSize && slv_req_i.aw.len == '0) + w_req_d.aw_throw_error = 1'b0; + end + + axi_pkg::BURST_FIXED: begin + // The DW converter does not support this kind of burst ... + w_state_d = W_PASSTHROUGH; + w_req_d.aw_throw_error = 1'b1 ; + + // ... but might if this is a narrow single-beat transaction + if (slv_req_i.aw.size <= AxiSlvPortMaxSize && slv_req_i.aw.len == '0) + w_req_d.aw_throw_error = 1'b0; + end + endcase + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + w_state_q <= W_IDLE; + w_req_q <= '0 ; + end else begin + w_state_q <= w_state_d; + w_req_q <= w_req_d ; + end + end + +endmodule : axi_dw_downsizer diff --git a/hw/deps/axi/src/axi_dw_upsizer.sv b/hw/deps/axi/src/axi_dw_upsizer.sv new file mode 100644 index 0000000..08766cc --- /dev/null +++ b/hw/deps/axi/src/axi_dw_upsizer.sv @@ -0,0 +1,645 @@ +// Copyright 2020 ETH Zurich and 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. + +// Author: Matheus Cavalcante + +// Description: +// Data width upsize conversion. +// Connects a narrow master to a wider slave. + +// NOTE: The upsizer does not support WRAP and FIXED bursts, and +// will answer with SLVERR upon receiving a burst of such types. + +module axi_dw_upsizer #( + parameter int unsigned AxiMaxReads = 1 , // Number of outstanding reads + parameter int unsigned AxiSlvPortDataWidth = 8 , // Data width of the slv port + parameter int unsigned AxiMstPortDataWidth = 8 , // Data width of the mst port + parameter int unsigned AxiAddrWidth = 1 , // Address width + parameter int unsigned AxiIdWidth = 1 , // ID width + parameter type aw_chan_t = logic, // AW Channel Type + parameter type mst_w_chan_t = logic, // W Channel Type for mst port + parameter type slv_w_chan_t = logic, // W Channel Type for slv port + parameter type b_chan_t = logic, // B Channel Type + parameter type ar_chan_t = logic, // AR Channel Type + parameter type mst_r_chan_t = logic, // R Channel Type for mst port + parameter type slv_r_chan_t = logic, // R Channel Type for slv port + parameter type axi_mst_req_t = logic, // AXI Request Type for mst ports + parameter type axi_mst_resp_t = logic, // AXI Response Type for mst ports + parameter type axi_slv_req_t = logic, // AXI Request Type for slv ports + parameter type axi_slv_resp_t = logic // AXI Response Type for slv ports + ) ( + input logic clk_i, + input logic rst_ni, + // Slave interface + input axi_slv_req_t slv_req_i, + output axi_slv_resp_t slv_resp_o, + // Master interface + output axi_mst_req_t mst_req_o, + input axi_mst_resp_t mst_resp_i + ); + + /***************** + * DEFINITIONS * + *****************/ + import axi_pkg::aligned_addr; + import axi_pkg::beat_addr ; + + // Type used to index which adapter is handling each outstanding transaction. + localparam TranIdWidth = AxiMaxReads > 1 ? $clog2(AxiMaxReads) : 1; + typedef logic [TranIdWidth-1:0] tran_id_t; + + // Data width + localparam AxiSlvPortStrbWidth = AxiSlvPortDataWidth / 8; + localparam AxiMstPortStrbWidth = AxiMstPortDataWidth / 8; + + localparam AxiSlvPortMaxSize = $clog2(AxiSlvPortStrbWidth); + localparam AxiMstPortMaxSize = $clog2(AxiMstPortStrbWidth); + + // Address width + typedef logic [AxiAddrWidth-1:0] addr_t; + + // ID width + typedef logic [AxiIdWidth-1:0] id_t; + + // Length of burst after upsizing + typedef logic [$clog2(AxiMstPortStrbWidth/AxiSlvPortStrbWidth) + 7:0] burst_len_t; + + // Internal AXI bus + axi_mst_req_t mst_req; + axi_mst_resp_t mst_resp; + + /************** + * ARBITERS * + **************/ + + // R + + slv_r_chan_t [AxiMaxReads-1:0] slv_r_tran; + logic [AxiMaxReads-1:0] slv_r_valid_tran; + logic [AxiMaxReads-1:0] slv_r_ready_tran; + + rr_arb_tree #( + .NumIn (AxiMaxReads ), + .DataType (slv_r_chan_t), + .AxiVldRdy(1'b1 ), + .ExtPrio (1'b0 ), + .LockIn (1'b1 ) + ) i_slv_r_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + .rr_i ('0 ), + .req_i (slv_r_valid_tran ), + .gnt_o (slv_r_ready_tran ), + .data_i (slv_r_tran ), + .gnt_i (slv_req_i.r_ready ), + .req_o (slv_resp_o.r_valid), + .data_o (slv_resp_o.r ), + .idx_o (/* Unused */ ) + ); + + logic [AxiMaxReads-1:0] mst_r_ready_tran; + assign mst_req.r_ready = |mst_r_ready_tran; + + // AR + + id_t arb_slv_ar_id; + logic arb_slv_ar_req; + logic arb_slv_ar_gnt; + logic [AxiMaxReads-1:0] arb_slv_ar_gnt_tran; + // Multiplex AR slave between AR and AW for the injection of atomic operations with an R response. + logic inject_aw_into_ar; + logic inject_aw_into_ar_req; + logic inject_aw_into_ar_gnt; + + assign arb_slv_ar_gnt = |arb_slv_ar_gnt_tran; + + rr_arb_tree #( + .NumIn (2 ), + .DataWidth (AxiIdWidth), + .ExtPrio (1'b0 ), + .AxiVldRdy (1'b1 ), + .LockIn (1'b0 ) + ) i_slv_ar_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + .rr_i ('0 ), + .req_i ({inject_aw_into_ar_req, slv_req_i.ar_valid} ), + .gnt_o ({inject_aw_into_ar_gnt, slv_resp_o.ar_ready}), + .data_i ({slv_req_i.aw.id, slv_req_i.ar.id} ), + .req_o (arb_slv_ar_req ), + .gnt_i (arb_slv_ar_gnt ), + .data_o (arb_slv_ar_id ), + .idx_o (inject_aw_into_ar ) + ); + + ar_chan_t [AxiMaxReads-1:0] mst_ar_tran; + id_t [AxiMaxReads-1:0] mst_ar_id; + logic [AxiMaxReads-1:0] mst_ar_valid_tran; + logic [AxiMaxReads-1:0] mst_ar_ready_tran; + tran_id_t mst_req_idx; + + rr_arb_tree #( + .NumIn (AxiMaxReads), + .DataType (ar_chan_t ), + .AxiVldRdy(1'b1 ), + .ExtPrio (1'b0 ), + .LockIn (1'b1 ) + ) i_mst_ar_arb ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_i(1'b0 ), + .rr_i ('0 ), + .req_i (mst_ar_valid_tran), + .gnt_o (mst_ar_ready_tran), + .data_i (mst_ar_tran ), + .gnt_i (mst_resp.ar_ready), + .req_o (mst_req.ar_valid ), + .data_o (mst_req.ar ), + .idx_o (mst_req_idx ) + ); + + /***************** + * ERROR SLAVE * + *****************/ + + axi_mst_req_t axi_err_req; + axi_mst_resp_t axi_err_resp; + + axi_err_slv #( + .AxiIdWidth(AxiIdWidth ), + .Resp (axi_pkg::RESP_SLVERR), + .req_t (axi_mst_req_t ), + .resp_t (axi_mst_resp_t ) + ) i_axi_err_slv ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .slv_req_i (axi_err_req ), + .slv_resp_o(axi_err_resp) + ); + + /*********** + * DEMUX * + ***********/ + + // Requests can be sent either to the error slave, + // or to the DWC's master port. + + logic [AxiMaxReads-1:0] mst_req_ar_err; + logic mst_req_aw_err; + + axi_demux #( + .AxiIdWidth (AxiIdWidth ), + .AxiLookBits(AxiIdWidth ), + .aw_chan_t (aw_chan_t ), + .w_chan_t (mst_w_chan_t ), + .b_chan_t (b_chan_t ), + .ar_chan_t (ar_chan_t ), + .r_chan_t (mst_r_chan_t ), + .req_t (axi_mst_req_t ), + .resp_t (axi_mst_resp_t), + .NoMstPorts (2 ), + .MaxTrans (AxiMaxReads ), + .SpillAw (1'b1 ) // Required to break dependency between AW and W channels + ) i_axi_demux ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .test_i (1'b0 ), + .mst_reqs_o ({axi_err_req, mst_req_o} ), + .mst_resps_i ({axi_err_resp, mst_resp_i} ), + .slv_ar_select_i(mst_req_ar_err[mst_req_idx]), + .slv_aw_select_i(mst_req_aw_err ), + .slv_req_i (mst_req ), + .slv_resp_o (mst_resp ) + ); + + /********** + * READ * + **********/ + + typedef enum logic [1:0] { + R_IDLE , + R_PASSTHROUGH, + R_INCR_UPSIZE + } r_state_e; + + // Decide which upsizer will handle the incoming AXI transaction + logic [AxiMaxReads-1:0] idle_read_upsizer; + tran_id_t idx_ar_upsizer ; + + // Find an idle upsizer to handle this transaction + tran_id_t idx_idle_upsizer; + lzc #( + .WIDTH(AxiMaxReads) + ) i_idle_lzc ( + .in_i (idle_read_upsizer), + .cnt_o (idx_idle_upsizer ), + .empty_o(/* Unused */ ) + ); + + // Is there already another upsizer handling a transaction with the same id + logic [AxiMaxReads-1:0] id_clash_upsizer; + tran_id_t idx_id_clash_upsizer ; + for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_id_clash + assign id_clash_upsizer[t] = arb_slv_ar_id == mst_ar_id[t] && !idle_read_upsizer[t]; + end + + onehot_to_bin #( + .ONEHOT_WIDTH(AxiMaxReads) + ) i_id_clash_onehot_to_bin ( + .onehot(id_clash_upsizer ), + .bin (idx_id_clash_upsizer) + ); + + // Choose an idle upsizer, unless there is an id clash + assign idx_ar_upsizer = (|id_clash_upsizer) ? idx_id_clash_upsizer : idx_idle_upsizer; + + // This logic is used to resolve which upsizer is handling + // each outstanding read transaction + + logic r_upsizer_valid; + tran_id_t idx_r_upsizer; + + logic [AxiMaxReads-1:0] rid_upsizer_match; + + // Is there a upsizer handling this transaction? + assign r_upsizer_valid = |rid_upsizer_match; + + for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_rid_match + assign rid_upsizer_match[t] = (mst_resp.r.id == mst_ar_id[t]) && !idle_read_upsizer[t]; + end + + onehot_to_bin #( + .ONEHOT_WIDTH(AxiMaxReads) + ) i_rid_upsizer_lzc ( + .onehot(rid_upsizer_match), + .bin (idx_r_upsizer ) + ); + + typedef struct packed { + ar_chan_t ar ; + logic ar_valid ; + logic ar_throw_error ; + axi_pkg::len_t burst_len ; + axi_pkg::size_t orig_ar_size; + } r_req_t; + + for (genvar t = 0; unsigned'(t) < AxiMaxReads; t++) begin: gen_read_upsizer + r_state_e r_state_d, r_state_q; + r_req_t r_req_d , r_req_q ; + + // Are we idle? + assign idle_read_upsizer[t] = (r_state_q == R_IDLE); + + always_comb begin + // Maintain state + r_state_d = r_state_q; + r_req_d = r_req_q ; + + // AR Channel + mst_ar_tran[t] = r_req_q.ar ; + mst_ar_id[t] = r_req_q.ar.id ; + mst_ar_valid_tran[t] = r_req_q.ar_valid; + + // Throw an error + mst_req_ar_err[t] = r_req_q.ar_throw_error; + + // R Channel + // No latency + slv_r_tran[t] = '0 ; + slv_r_tran[t].id = mst_resp.r.id ; + slv_r_tran[t].resp = mst_resp.r.resp; + slv_r_tran[t].user = mst_resp.r.user; + + arb_slv_ar_gnt_tran[t] = 1'b0; + + mst_r_ready_tran[t] = 1'b0; + slv_r_valid_tran[t] = 1'b0; + + // Got a grant on the AR channel + if (mst_ar_valid_tran[t] && mst_ar_ready_tran[t]) begin + r_req_d.ar_valid = 1'b0; + r_req_d.ar_throw_error = 1'b0; + end + + case (r_state_q) + R_IDLE : begin + // Reset channels + r_req_d.ar = '0; + + // New read request + if (arb_slv_ar_req && (idx_ar_upsizer == t)) begin + arb_slv_ar_gnt_tran[t] = 1'b1; + + // Default state + r_state_d = R_PASSTHROUGH; + + // Save beat + r_req_d.ar = slv_req_i.ar ; + r_req_d.ar_valid = 1'b1 ; + r_req_d.burst_len = slv_req_i.ar.len ; + r_req_d.orig_ar_size = slv_req_i.ar.size; + if (inject_aw_into_ar) begin + r_req_d.ar.id = slv_req_i.aw.id ; + r_req_d.ar.addr = slv_req_i.aw.addr ; + r_req_d.ar.size = slv_req_i.aw.size ; + r_req_d.ar.burst = slv_req_i.aw.burst ; + r_req_d.ar.len = slv_req_i.aw.len ; + r_req_d.ar.lock = slv_req_i.aw.lock ; + r_req_d.ar.cache = slv_req_i.aw.cache ; + r_req_d.ar.prot = slv_req_i.aw.prot ; + r_req_d.ar.qos = slv_req_i.aw.qos ; + r_req_d.ar.region = slv_req_i.aw.region; + r_req_d.ar.user = slv_req_i.aw.user ; + r_req_d.ar_valid = 1'b0 ; // Injected "AR"s from AW are not valid. + r_req_d.burst_len = slv_req_i.aw.len ; + r_req_d.orig_ar_size = slv_req_i.aw.size ; + end + + case (r_req_d.ar.burst) + axi_pkg::BURST_INCR : begin + // Modifiable transaction + if (|(r_req_d.ar.cache & axi_pkg::CACHE_MODIFIABLE)) begin + // No need to upsize single-beat transactions. + if (r_req_d.ar.len != '0) begin + // Evaluate output burst length + automatic addr_t start_addr = aligned_addr(r_req_d.ar.addr, AxiMstPortMaxSize) ; + automatic addr_t end_addr = aligned_addr(beat_addr(r_req_d.ar.addr, r_req_d.orig_ar_size, r_req_d.burst_len), AxiMstPortMaxSize); + + r_req_d.ar.len = (end_addr - start_addr) >> AxiMstPortMaxSize; + r_req_d.ar.size = AxiMstPortMaxSize ; + r_state_d = R_INCR_UPSIZE ; + end + end + end + + axi_pkg::BURST_WRAP: begin + // The DW converter does not support this kind of burst ... + r_state_d = R_PASSTHROUGH; + r_req_d.ar_throw_error = 1'b1 ; + + // ... but might if this is a single-beat transaction + if (r_req_d.ar.len == '0) + r_req_d.ar_throw_error = 1'b0; + end + + axi_pkg::BURST_FIXED: begin + // The DW converter does not support this kind of burst ... + r_state_d = R_PASSTHROUGH; + r_req_d.ar_throw_error = 1'b1 ; + + // ... but might if this is a single-beat transaction + if (r_req_d.ar.len == '0) + r_req_d.ar_throw_error = 1'b0; + end + endcase + end + end + + R_PASSTHROUGH, R_INCR_UPSIZE: begin + // Request was accepted + if (!r_req_q.ar_valid) + if (mst_resp.r_valid && (idx_r_upsizer == t) && r_upsizer_valid) begin + automatic addr_t mst_port_offset = r_req_q.ar.addr[(AxiMstPortStrbWidth == 1 ? 1 : $clog2(AxiMstPortStrbWidth)) - 1:0]; + automatic addr_t slv_port_offset = r_req_q.ar.addr[(AxiSlvPortStrbWidth == 1 ? 1 : $clog2(AxiSlvPortStrbWidth)) - 1:0]; + + // Valid output + slv_r_valid_tran[t] = 1'b1 ; + slv_r_tran[t].last = mst_resp.r.last && (r_req_q.burst_len == 0); + + // Lane steering + for (int b = 0; b < AxiMstPortStrbWidth; b++) begin + if ((b >= mst_port_offset) && + (b - mst_port_offset < (1 << r_req_q.orig_ar_size)) && + (b + slv_port_offset - mst_port_offset < AxiSlvPortStrbWidth)) begin + slv_r_tran[t].data[8*(b + slv_port_offset - mst_port_offset) +: 8] = mst_resp.r.data[8*b +: 8]; + end + end + + // Acknowledgment + if (slv_r_ready_tran[t]) begin + r_req_d.burst_len = r_req_q.burst_len - 1 ; + r_req_d.ar.addr = aligned_addr(r_req_q.ar.addr, r_req_q.orig_ar_size) + (1 << r_req_q.orig_ar_size); + + case (r_state_q) + R_PASSTHROUGH : + mst_r_ready_tran[t] = 1'b1; + + R_INCR_UPSIZE : + if (r_req_q.burst_len == 0 || (aligned_addr(r_req_d.ar.addr, AxiMstPortMaxSize) != aligned_addr(r_req_q.ar.addr, AxiMstPortMaxSize))) + mst_r_ready_tran[t] = 1'b1; + endcase + + if (r_req_q.burst_len == '0) + r_state_d = R_IDLE; + end + end + end + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + r_state_q <= R_IDLE; + r_req_q <= '0 ; + end else begin + r_state_q <= r_state_d; + r_req_q <= r_req_d ; + end + end + end : gen_read_upsizer + + /*********** + * WRITE * + ***********/ + + typedef enum logic [1:0] { + W_IDLE , + W_PASSTHROUGH, + W_INCR_UPSIZE + } w_state_e; + + typedef struct packed { + aw_chan_t aw ; + logic aw_valid ; + logic aw_throw_error ; + mst_w_chan_t w ; + logic w_valid ; + axi_pkg::len_t burst_len ; + axi_pkg::size_t orig_aw_size; + } w_req_t; + + w_state_e w_state_d, w_state_q; + w_req_t w_req_d , w_req_q ; + + always_comb begin + inject_aw_into_ar_req = 1'b0; + + // Maintain state + w_state_d = w_state_q; + w_req_d = w_req_q ; + + // AW Channel + mst_req.aw = w_req_q.aw ; + mst_req.aw_valid = w_req_q.aw_valid; + slv_resp_o.aw_ready = '0 ; + + // Throw an error. + mst_req_aw_err = w_req_q.aw_throw_error; + + // W Channel + mst_req.w = w_req_q.w ; + mst_req.w_valid = w_req_q.w_valid; + slv_resp_o.w_ready = '0 ; + + // B Channel (No latency) + slv_resp_o.b = mst_resp.b ; + slv_resp_o.b_valid = mst_resp.b_valid ; + mst_req.b_ready = slv_req_i.b_ready; + + // Got a grant on the AW channel + if (mst_req.aw_valid && mst_resp.aw_ready) begin + w_req_d.aw_valid = 1'b0; + w_req_d.aw_throw_error = 1'b0; + end + + case (w_state_q) + W_PASSTHROUGH, W_INCR_UPSIZE: begin + // Got a grant on the W channel + if (mst_req.w_valid && mst_resp.w_ready) begin + w_req_d.w = '0 ; + w_req_d.w_valid = 1'b0; + end + + // Request was accepted + if (!w_req_q.aw_valid) begin + // Ready if downstream interface is idle, or if it is ready + slv_resp_o.w_ready = ~mst_req.w_valid || mst_resp.w_ready; + + if (slv_req_i.w_valid && slv_resp_o.w_ready) begin + automatic addr_t mst_port_offset = w_req_q.aw.addr[(AxiMstPortStrbWidth == 1 ? 1 : $clog2(AxiMstPortStrbWidth)) - 1:0]; + automatic addr_t slv_port_offset = w_req_q.aw.addr[(AxiSlvPortStrbWidth == 1 ? 1 : $clog2(AxiSlvPortStrbWidth)) - 1:0]; + + // Serialization + for (int b = 0; b < AxiMstPortStrbWidth; b++) + if ((b >= mst_port_offset) && + (b - mst_port_offset < (1 << w_req_q.orig_aw_size)) && + (b + slv_port_offset - mst_port_offset < AxiSlvPortStrbWidth)) begin + w_req_d.w.data[8*b +: 8] = slv_req_i.w.data[8*(b + slv_port_offset - mst_port_offset) +: 8]; + w_req_d.w.strb[b] = slv_req_i.w.strb[b + slv_port_offset - mst_port_offset] ; + end + + w_req_d.burst_len = w_req_q.burst_len - 1 ; + w_req_d.aw.addr = aligned_addr(w_req_q.aw.addr, w_req_q.orig_aw_size) + (1 << w_req_q.orig_aw_size); + w_req_d.w.last = (w_req_q.burst_len == 0) ; + w_req_d.w.user = slv_req_i.w.user ; + + case (w_state_q) + W_PASSTHROUGH: + // Forward data as soon as we can + w_req_d.w_valid = 1'b1; + + W_INCR_UPSIZE: + // Forward when the burst is finished, or after filling up a word + if (w_req_q.burst_len == 0 || (aligned_addr(w_req_d.aw.addr, AxiMstPortMaxSize) != aligned_addr(w_req_q.aw.addr, AxiMstPortMaxSize))) + w_req_d.w_valid = 1'b1; + endcase + end + end + + if (mst_req.w_valid && mst_resp.w_ready) + if (w_req_q.burst_len == '1) begin + slv_resp_o.w_ready = 1'b0 ; + w_state_d = W_IDLE; + end + end + endcase + + // Can start a new request as soon as w_state_d is W_IDLE + if (w_state_d == W_IDLE) begin + // Reset channels + w_req_d.aw = '0 ; + w_req_d.aw_valid = 1'b0; + w_req_d.aw_throw_error = 1'b0; + w_req_d.w = '0 ; + w_req_d.w_valid = 1'b0; + + if (slv_req_i.aw_valid && slv_req_i.aw.atop[5]) begin // ATOP with an R response + inject_aw_into_ar_req = 1'b1 ; + slv_resp_o.aw_ready = inject_aw_into_ar_gnt; + end else begin // Regular AW + slv_resp_o.aw_ready = 1'b1; + end + + // New write request + if (slv_req_i.aw_valid & slv_resp_o.aw_ready) begin + // Default state + w_state_d = W_PASSTHROUGH; + + // Save beat + w_req_d.aw = slv_req_i.aw; + w_req_d.aw_valid = 1'b1 ; + + w_req_d.burst_len = slv_req_i.aw.len ; + w_req_d.orig_aw_size = slv_req_i.aw.size; + + case (slv_req_i.aw.burst) + axi_pkg::BURST_INCR: begin + // Modifiable transaction + if (|(slv_req_i.aw.cache & axi_pkg::CACHE_MODIFIABLE)) + // No need to upsize single-beat transactions. + if (slv_req_i.aw.len != '0) begin + // Evaluate output burst length + automatic addr_t start_addr = aligned_addr(slv_req_i.aw.addr, AxiMstPortMaxSize) ; + automatic addr_t end_addr = aligned_addr(beat_addr(slv_req_i.aw.addr, slv_req_i.aw.size, slv_req_i.aw.len), AxiMstPortMaxSize); + + w_req_d.aw.len = (end_addr - start_addr) >> AxiMstPortMaxSize; + w_req_d.aw.size = AxiMstPortMaxSize ; + w_state_d = W_INCR_UPSIZE ; + end + end + + axi_pkg::BURST_WRAP: begin + // The DW converter does not support this kind of burst ... + w_state_d = W_PASSTHROUGH; + w_req_d.aw_throw_error = 1'b1 ; + + // ... but might if this is a single-beat transaction + if (slv_req_i.aw.len == '0) + w_req_d.aw_throw_error = 1'b0; + end + + axi_pkg::BURST_FIXED: begin + // The DW converter does not support this kind of burst ... + w_state_d = W_PASSTHROUGH; + w_req_d.aw_throw_error = 1'b1 ; + + // ... but might if this is a single-beat transaction + if (slv_req_i.aw.len == '0) + w_req_d.aw_throw_error = 1'b0; + end + endcase + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + w_state_q <= W_IDLE; + w_req_q <= '0 ; + end else begin + w_state_q <= w_state_d; + w_req_q <= w_req_d ; + end + end + +endmodule : axi_dw_upsizer diff --git a/hw/deps/axi/src/axi_err_slv.sv b/hw/deps/axi/src/axi_err_slv.sv new file mode 100644 index 0000000..b3a8b9c --- /dev/null +++ b/hw/deps/axi/src/axi_err_slv.sv @@ -0,0 +1,256 @@ +// Copyright 2019 ETH Zurich and 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. + +// Author: Wolfgang Roenninger + +// AXI Error Slave: This module always responds with an AXI error for transactions that are sent to +// it. This module optionally supports ATOPs if the `ATOPs` parameter is set. + +module axi_err_slv #( + parameter int unsigned AxiIdWidth = 0, // AXI ID Width + parameter type req_t = logic, // AXI 4 request struct, with atop field + parameter type resp_t = logic, // AXI 4 response struct + parameter axi_pkg::resp_t Resp = axi_pkg::RESP_DECERR, // Error generated by this slave. + parameter int unsigned RespWidth = 32'd64, // Data response width, gets zero extended or truncated to r.data. + parameter logic [RespWidth-1:0] RespData = 64'hCA11AB1EBADCAB1E, // Hexvalue for data return value + parameter bit ATOPs = 1'b1, // Activate support for ATOPs. Set to 1 if this slave could ever get an atomic AXI transaction. + parameter int unsigned MaxTrans = 1 // Maximum # of accepted transactions before stalling +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic test_i, // Testmode enable + // slave port + input req_t slv_req_i, + output resp_t slv_resp_o +); + typedef logic [AxiIdWidth-1:0] id_t; + typedef struct packed { + id_t id; + axi_pkg::len_t len; + } r_data_t; + + req_t err_req; + resp_t err_resp; + + if (ATOPs) begin + axi_atop_filter #( + .AxiIdWidth ( AxiIdWidth ), + .AxiMaxWriteTxns ( MaxTrans ), + .req_t ( req_t ), + .resp_t ( resp_t ) + ) i_atop_filter ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req_i ), + .slv_resp_o ( slv_resp_o ), + .mst_req_o ( err_req ), + .mst_resp_i ( err_resp ) + ); + end else begin + assign err_req = slv_req_i; + assign slv_resp_o = err_resp; + end + + // w fifo + logic w_fifo_full, w_fifo_empty; + logic w_fifo_push, w_fifo_pop; + id_t w_fifo_data; + // b fifo + logic b_fifo_full, b_fifo_empty; + logic b_fifo_push, b_fifo_pop; + id_t b_fifo_data; + // r fifo + r_data_t r_fifo_inp; + logic r_fifo_full, r_fifo_empty; + logic r_fifo_push, r_fifo_pop; + r_data_t r_fifo_data; + // r counter + logic r_cnt_clear, r_cnt_en, r_cnt_load; + axi_pkg::len_t r_current_beat; + // r status + logic r_busy_d, r_busy_q, r_busy_load; + + //-------------------------------------- + // Write Transactions + //-------------------------------------- + // push, when there is room in the fifo + assign w_fifo_push = err_req.aw_valid & ~w_fifo_full; + assign err_resp.aw_ready = ~w_fifo_full; + + fifo_v3 #( + .FALL_THROUGH ( 1'b1 ), + .DEPTH ( MaxTrans ), + .dtype ( id_t ) + ) i_w_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( test_i ), + .full_o ( w_fifo_full ), + .empty_o ( w_fifo_empty ), + .usage_o ( ), + .data_i ( err_req.aw.id ), + .push_i ( w_fifo_push ), + .data_o ( w_fifo_data ), + .pop_i ( w_fifo_pop ) + ); + + always_comb begin : proc_w_channel + err_resp.w_ready = 1'b0; + w_fifo_pop = 1'b0; + b_fifo_push = 1'b0; + if (!w_fifo_empty && !b_fifo_full) begin + // eat the beats + err_resp.w_ready = 1'b1; + // on the last w transaction + if (err_req.w_valid && err_req.w.last) begin + w_fifo_pop = 1'b1; + b_fifo_push = 1'b1; + end + end + end + + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DEPTH ( unsigned'(2) ), // two placed so that w can eat beats if b is not sent + .dtype ( id_t ) + ) i_b_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( test_i ), + .full_o ( b_fifo_full ), + .empty_o ( b_fifo_empty ), + .usage_o ( ), + .data_i ( w_fifo_data ), + .push_i ( b_fifo_push ), + .data_o ( b_fifo_data ), + .pop_i ( b_fifo_pop ) + ); + + always_comb begin : proc_b_channel + b_fifo_pop = 1'b0; + err_resp.b = '0; + err_resp.b.id = b_fifo_data; + err_resp.b.resp = Resp; + err_resp.b_valid = 1'b0; + if (!b_fifo_empty) begin + err_resp.b_valid = 1'b1; + // b transaction + b_fifo_pop = err_req.b_ready; + end + end + + //-------------------------------------- + // Read Transactions + //-------------------------------------- + // push if there is room in the fifo + assign r_fifo_push = err_req.ar_valid & ~r_fifo_full; + assign err_resp.ar_ready = ~r_fifo_full; + + // fifo data assignment + assign r_fifo_inp.id = err_req.ar.id; + assign r_fifo_inp.len = err_req.ar.len; + + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DEPTH ( MaxTrans ), + .dtype ( r_data_t ) + ) i_r_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( test_i ), + .full_o ( r_fifo_full ), + .empty_o ( r_fifo_empty ), + .usage_o ( ), + .data_i ( r_fifo_inp ), + .push_i ( r_fifo_push ), + .data_o ( r_fifo_data ), + .pop_i ( r_fifo_pop ) + ); + + always_comb begin : proc_r_channel + // default assignments + r_busy_d = r_busy_q; + r_busy_load = 1'b0; + // r fifo signals + r_fifo_pop = 1'b0; + // r counter signals + r_cnt_clear = 1'b0; + r_cnt_en = 1'b0; + r_cnt_load = 1'b0; + // r_channel + err_resp.r = '0; + err_resp.r.id = r_fifo_data.id; + err_resp.r.data = RespData; + err_resp.r.resp = Resp; + err_resp.r_valid = 1'b0; + // control + if (r_busy_q) begin + err_resp.r_valid = 1'b1; + err_resp.r.last = (r_current_beat == '0); + // r transaction + if (err_req.r_ready) begin + r_cnt_en = 1'b1; + if (r_current_beat == '0) begin + r_busy_d = 1'b0; + r_busy_load = 1'b1; + r_cnt_clear = 1'b1; + r_fifo_pop = 1'b1; + end + end + end else begin + // when not busy and fifo not empty, start counter err gen + if (!r_fifo_empty) begin + r_busy_d = 1'b1; + r_busy_load = 1'b1; + r_cnt_load = 1'b1; + end + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + r_busy_q <= '0; + end else if (r_busy_load) begin + r_busy_q <= r_busy_d; + end + end + + counter #( + .WIDTH ($bits(axi_pkg::len_t)) + ) i_r_counter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clear_i ( r_cnt_clear ), + .en_i ( r_cnt_en ), + .load_i ( r_cnt_load ), + .down_i ( 1'b1 ), + .d_i ( r_fifo_data.len ), + .q_o ( r_current_beat ), + .overflow_o( ) + ); + + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (Resp == axi_pkg::RESP_DECERR || Resp == axi_pkg::RESP_SLVERR) else + $fatal(1, "This module may only generate RESP_DECERR or RESP_SLVERR responses!"); + end + default disable iff (!rst_ni); + if (!ATOPs) begin : gen_assert_atops_unsupported + assume property( @(posedge clk_i) (slv_req_i.aw_valid |-> slv_req_i.aw.atop == '0)) else + $fatal(1, "Got ATOP but not configured to support ATOPs!"); + end + `endif + // pragma translate_on + +endmodule diff --git a/hw/deps/axi/src/axi_id_prepend.sv b/hw/deps/axi/src/axi_id_prepend.sv new file mode 100644 index 0000000..317ae32 --- /dev/null +++ b/hw/deps/axi/src/axi_id_prepend.sv @@ -0,0 +1,159 @@ +// Copyright 2019 ETH Zurich and 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. + +// Author: Wolfgang Roenninger + +// AXI ID Prepend: This module prepends/strips the MSB from the AXI IDs. +// Constraints enforced through assertions: ID width of slave and master port + +module axi_id_prepend #( + parameter int unsigned NoBus = 1, // Can take multiple axi busses + parameter int unsigned AxiIdWidthSlvPort = 4, // AXI ID Width of the Slave Ports + parameter int unsigned AxiIdWidthMstPort = 6, // AXI ID Width of the Master Ports + parameter type slv_aw_chan_t = logic, // AW Channel Type for slv port + parameter type slv_w_chan_t = logic, // W Channel Type for slv port + parameter type slv_b_chan_t = logic, // B Channel Type for slv port + parameter type slv_ar_chan_t = logic, // AR Channel Type for slv port + parameter type slv_r_chan_t = logic, // R Channel Type for slv port + parameter type mst_aw_chan_t = logic, // AW Channel Type for mst port + parameter type mst_w_chan_t = logic, // W Channel Type for mst port + parameter type mst_b_chan_t = logic, // B Channel Type for mst port + parameter type mst_ar_chan_t = logic, // AR Channel Type for mst port + parameter type mst_r_chan_t = logic, // R Channel Type for mst port + // DEPENDENT PARAMETER DO NOT OVERWRITE! + parameter int unsigned PreIdWidth = AxiIdWidthMstPort - AxiIdWidthSlvPort +) ( + input logic [PreIdWidth-1:0] pre_id_i, // ID to be prepended + // slave port (input), connect master modules here + // AW channel + input slv_aw_chan_t [NoBus-1:0] slv_aw_chans_i, + input logic [NoBus-1:0] slv_aw_valids_i, + output logic [NoBus-1:0] slv_aw_readies_o, + // W channel + input slv_w_chan_t [NoBus-1:0] slv_w_chans_i, + input logic [NoBus-1:0] slv_w_valids_i, + output logic [NoBus-1:0] slv_w_readies_o, + // B channel + output slv_b_chan_t [NoBus-1:0] slv_b_chans_o, + output logic [NoBus-1:0] slv_b_valids_o, + input logic [NoBus-1:0] slv_b_readies_i, + // AR channel + input slv_ar_chan_t [NoBus-1:0] slv_ar_chans_i, + input logic [NoBus-1:0] slv_ar_valids_i, + output logic [NoBus-1:0] slv_ar_readies_o, + // R channel + output slv_r_chan_t [NoBus-1:0] slv_r_chans_o, + output logic [NoBus-1:0] slv_r_valids_o, + input logic [NoBus-1:0] slv_r_readies_i, + // master ports (output), connect slave modules here + // AW channel + output mst_aw_chan_t [NoBus-1:0] mst_aw_chans_o, + output logic [NoBus-1:0] mst_aw_valids_o, + input logic [NoBus-1:0] mst_aw_readies_i, + // W channel + output mst_w_chan_t [NoBus-1:0] mst_w_chans_o, + output logic [NoBus-1:0] mst_w_valids_o, + input logic [NoBus-1:0] mst_w_readies_i, + // B channel + input mst_b_chan_t [NoBus-1:0] mst_b_chans_i, + input logic [NoBus-1:0] mst_b_valids_i, + output logic [NoBus-1:0] mst_b_readies_o, + // AR channel + output mst_ar_chan_t [NoBus-1:0] mst_ar_chans_o, + output logic [NoBus-1:0] mst_ar_valids_o, + input logic [NoBus-1:0] mst_ar_readies_i, + // R channel + input mst_r_chan_t [NoBus-1:0] mst_r_chans_i, + input logic [NoBus-1:0] mst_r_valids_i, + output logic [NoBus-1:0] mst_r_readies_o +); + + // prepend the ID + for (genvar i = 0; i < NoBus; i++) begin : gen_id_prepend + if (PreIdWidth == 0) begin : gen_no_prepend + assign mst_aw_chans_o[i] = slv_aw_chans_i[i]; + assign mst_ar_chans_o[i] = slv_ar_chans_i[i]; + end else begin : gen_prepend + always_comb begin + mst_aw_chans_o[i] = slv_aw_chans_i[i]; + mst_ar_chans_o[i] = slv_ar_chans_i[i]; + mst_aw_chans_o[i].id = {pre_id_i, slv_aw_chans_i[i].id[AxiIdWidthSlvPort-1:0]}; + mst_ar_chans_o[i].id = {pre_id_i, slv_ar_chans_i[i].id[AxiIdWidthSlvPort-1:0]}; + end + end + // The ID is in the highest bits of the struct, so an assignment from a channel with a wide ID + // to a channel with a shorter ID correctly cuts the prepended ID. + assign slv_b_chans_o[i] = mst_b_chans_i[i]; + assign slv_r_chans_o[i] = mst_r_chans_i[i]; + end + + // assign the handshaking's and w channel + assign mst_w_chans_o = slv_w_chans_i; + assign mst_aw_valids_o = slv_aw_valids_i; + assign slv_aw_readies_o = mst_aw_readies_i; + assign mst_w_valids_o = slv_w_valids_i; + assign slv_w_readies_o = mst_w_readies_i; + assign slv_b_valids_o = mst_b_valids_i; + assign mst_b_readies_o = slv_b_readies_i; + assign mst_ar_valids_o = slv_ar_valids_i; + assign slv_ar_readies_o = mst_ar_readies_i; + assign slv_r_valids_o = mst_r_valids_i; + assign mst_r_readies_o = slv_r_readies_i; + +// pragma translate_off +`ifndef VERILATOR + initial begin : p_assert + assert(NoBus > 0) + else $fatal(1, "Input must be at least one element wide."); + assert(PreIdWidth == ($bits(mst_aw_chans_o[0].id) - $bits(slv_aw_chans_i[0].id))) + else $fatal(1, "Prepend ID Width must be: $bits(mst_aw_chans_o.id)-$bits(slv_aw_chans_i.id)"); + assert ($bits(mst_aw_chans_o[0].id) > $bits(slv_aw_chans_i[0].id)) + else $fatal(1, "The master AXI port has to have a wider ID than the slave port."); + end + + aw_id : assert final( + mst_aw_chans_o[0].id[$bits(slv_aw_chans_i[0].id)-1:0] === slv_aw_chans_i[0].id) + else $fatal (1, "Something with the AW channel ID prepending went wrong."); + aw_addr : assert final(mst_aw_chans_o[0].addr === slv_aw_chans_i[0].addr) + else $fatal (1, "Something with the AW channel ID prepending went wrong."); + aw_len : assert final(mst_aw_chans_o[0].len === slv_aw_chans_i[0].len) + else $fatal (1, "Something with the AW channel ID prepending went wrong."); + aw_size : assert final(mst_aw_chans_o[0].size === slv_aw_chans_i[0].size) + else $fatal (1, "Something with the AW channel ID prepending went wrong."); + aw_qos : assert final(mst_aw_chans_o[0].qos === slv_aw_chans_i[0].qos) + else $fatal (1, "Something with the AW channel ID prepending went wrong."); + + b_id : assert final( + mst_b_chans_i[0].id[$bits(slv_b_chans_o[0].id)-1:0] === slv_b_chans_o[0].id) + else $fatal (1, "Something with the B channel ID stripping went wrong."); + b_resp : assert final(mst_b_chans_i[0].resp === slv_b_chans_o[0].resp) + else $fatal (1, "Something with the B channel ID stripping went wrong."); + + ar_id : assert final( + mst_ar_chans_o[0].id[$bits(slv_ar_chans_i[0].id)-1:0] === slv_ar_chans_i[0].id) + else $fatal (1, "Something with the AR channel ID prepending went wrong."); + ar_addr : assert final(mst_ar_chans_o[0].addr === slv_ar_chans_i[0].addr) + else $fatal (1, "Something with the AR channel ID prepending went wrong."); + ar_len : assert final(mst_ar_chans_o[0].len === slv_ar_chans_i[0].len) + else $fatal (1, "Something with the AR channel ID prepending went wrong."); + ar_size : assert final(mst_ar_chans_o[0].size === slv_ar_chans_i[0].size) + else $fatal (1, "Something with the AR channel ID prepending went wrong."); + ar_qos : assert final(mst_ar_chans_o[0].qos === slv_ar_chans_i[0].qos) + else $fatal (1, "Something with the AR channel ID prepending went wrong."); + + r_id : assert final(mst_r_chans_i[0].id[$bits(slv_r_chans_o[0].id)-1:0] === slv_r_chans_o[0].id) + else $fatal (1, "Something with the R channel ID stripping went wrong."); + r_data : assert final(mst_r_chans_i[0].data === slv_r_chans_o[0].data) + else $fatal (1, "Something with the R channel ID stripping went wrong."); + r_resp : assert final(mst_r_chans_i[0].resp === slv_r_chans_o[0].resp) + else $fatal (1, "Something with the R channel ID stripping went wrong."); +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/axi/src/axi_id_remap.sv b/hw/deps/axi/src/axi_id_remap.sv new file mode 100644 index 0000000..78033f2 --- /dev/null +++ b/hw/deps/axi/src/axi_id_remap.sv @@ -0,0 +1,640 @@ +// Copyright (c) 2014-2020 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. +// +// Andreas Kurth +// Florian Zaruba +// Wolfgang Roenninger + +`include "common_cells/registers.svh" + +/// Remap AXI IDs from wide IDs at the slave port to narrower IDs at the master port. +/// +/// This module is designed to remap an overly wide, sparsely used ID space to a narrower, densely +/// used ID space. This scenario occurs, for example, when an AXI master has wide ID ports but +/// effectively only uses a (not necessarily contiguous) subset of IDs. +/// +/// This module retains the independence of IDs. That is, if two transactions have different IDs at +/// the slave port of this module, they are guaranteed to have different IDs at the master port of +/// this module. This implies a lower bound on the [width of IDs on the master +/// port](#parameter.AxiMstPortIdWidth). If you require narrower master port IDs and can forgo ID +/// independence, use [`axi_id_serialize`](module.axi_id_serialize) instead. +/// +/// Internally, a [table is used for remapping IDs](module.axi_id_remap_table). +module axi_id_remap #( + /// ID width of the AXI4+ATOP slave port. + parameter int unsigned AxiSlvPortIdWidth = 32'd0, + /// Maximum number of different IDs that can be in flight at the slave port. Reads and writes are + /// counted separately (except for ATOPs, which count as both read and write). + /// + /// It is legal for upstream to have transactions with more unique IDs than the maximum given by + /// this parameter in flight, but a transaction exceeding the maximum will be stalled until all + /// transactions of another ID complete. + /// + /// The maximum value of this parameter is `2**AxiSlvPortIdWidth`. + parameter int unsigned AxiSlvPortMaxUniqIds = 32'd0, + /// Maximum number of in-flight transactions with the same ID. + /// + /// It is legal for upstream to have more transactions than the maximum given by this parameter in + /// flight for any ID, but a transaction exceeding the maximum will be stalled until another + /// transaction with the same ID completes. + parameter int unsigned AxiMaxTxnsPerId = 32'd0, + /// ID width of the AXI4+ATOP master port. + /// + /// The minimum value of this parameter is the ceiled binary logarithm of `AxiSlvPortMaxUniqIds`, + /// because IDs at the master port must be wide enough to represent IDs up to + /// `AxiSlvPortMaxUniqIds-1`. + /// + /// If master IDs are wider than the minimum, they are extended by prepending zeros. + parameter int unsigned AxiMstPortIdWidth = 32'd0, + /// Request struct type of the AXI4+ATOP slave port. + /// + /// The width of all IDs in this struct must match `AxiSlvPortIdWidth`. + parameter type slv_req_t = logic, + /// Response struct type of the AXI4+ATOP slave port. + /// + /// The width of all IDs in this struct must match `AxiSlvPortIdWidth`. + parameter type slv_resp_t = logic, + /// Request struct type of the AXI4+ATOP master port + /// + /// The width of all IDs in this struct must match `AxiMstPortIdWidth`. + parameter type mst_req_t = logic, + /// Response struct type of the AXI4+ATOP master port + /// + /// The width of all IDs in this struct must match `AxiMstPortIdWidth`. + parameter type mst_resp_t = logic +) ( + /// Rising-edge clock of all ports + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Slave port request + input slv_req_t slv_req_i, + /// Slave port response + output slv_resp_t slv_resp_o, + /// Master port request + output mst_req_t mst_req_o, + /// Master port response + input mst_resp_t mst_resp_i +); + + // Feed all signals that are not ID or flow control of AW and AR through. + assign mst_req_o.aw.addr = slv_req_i.aw.addr; + assign mst_req_o.aw.len = slv_req_i.aw.len; + assign mst_req_o.aw.size = slv_req_i.aw.size; + assign mst_req_o.aw.burst = slv_req_i.aw.burst; + assign mst_req_o.aw.lock = slv_req_i.aw.lock; + assign mst_req_o.aw.cache = slv_req_i.aw.cache; + assign mst_req_o.aw.prot = slv_req_i.aw.prot; + assign mst_req_o.aw.qos = slv_req_i.aw.qos; + assign mst_req_o.aw.region = slv_req_i.aw.region; + assign mst_req_o.aw.atop = slv_req_i.aw.atop; + assign mst_req_o.aw.user = slv_req_i.aw.user; + + assign mst_req_o.w = slv_req_i.w; + assign mst_req_o.w_valid = slv_req_i.w_valid; + assign slv_resp_o.w_ready = mst_resp_i.w_ready; + + assign slv_resp_o.b.resp = mst_resp_i.b.resp; + assign slv_resp_o.b.user = mst_resp_i.b.user; + assign slv_resp_o.b_valid = mst_resp_i.b_valid; + assign mst_req_o.b_ready = slv_req_i.b_ready; + + assign mst_req_o.ar.addr = slv_req_i.ar.addr; + assign mst_req_o.ar.len = slv_req_i.ar.len; + assign mst_req_o.ar.size = slv_req_i.ar.size; + assign mst_req_o.ar.burst = slv_req_i.ar.burst; + assign mst_req_o.ar.lock = slv_req_i.ar.lock; + assign mst_req_o.ar.cache = slv_req_i.ar.cache; + assign mst_req_o.ar.prot = slv_req_i.ar.prot; + assign mst_req_o.ar.qos = slv_req_i.ar.qos; + assign mst_req_o.ar.region = slv_req_i.ar.region; + assign mst_req_o.ar.user = slv_req_i.ar.user; + + assign slv_resp_o.r.data = mst_resp_i.r.data; + assign slv_resp_o.r.resp = mst_resp_i.r.resp; + assign slv_resp_o.r.last = mst_resp_i.r.last; + assign slv_resp_o.r.user = mst_resp_i.r.user; + assign slv_resp_o.r_valid = mst_resp_i.r_valid; + assign mst_req_o.r_ready = slv_req_i.r_ready; + + + // Remap tables keep track of in-flight bursts and their input and output IDs. + localparam int unsigned IdxWidth = cf_math_pkg::idx_width(AxiSlvPortMaxUniqIds); + typedef logic [AxiSlvPortMaxUniqIds-1:0] field_t; + typedef logic [AxiSlvPortIdWidth-1:0] id_inp_t; + typedef logic [IdxWidth-1:0] idx_t; + field_t wr_free, rd_free, both_free; + id_inp_t rd_push_inp_id; + idx_t wr_free_oup_id, rd_free_oup_id, both_free_oup_id, + wr_push_oup_id, rd_push_oup_id, + wr_exists_id, rd_exists_id; + logic wr_exists, rd_exists, + wr_exists_full, rd_exists_full, + wr_full, rd_full, + wr_push, rd_push; + + logic ar_must_pass_q, ar_must_pass_d; + + axi_id_remap_table #( + .InpIdWidth ( AxiSlvPortIdWidth ), + .MaxUniqInpIds ( AxiSlvPortMaxUniqIds ), + .MaxTxnsPerId ( AxiMaxTxnsPerId ) + ) i_wr_table ( + .clk_i, + .rst_ni, + .free_o ( wr_free ), + .free_oup_id_o ( wr_free_oup_id ), + .full_o ( wr_full ), + .push_i ( wr_push ), + .push_inp_id_i ( slv_req_i.aw.id ), + .push_oup_id_i ( wr_push_oup_id ), + .exists_inp_id_i ( slv_req_i.aw.id ), + .exists_o ( wr_exists ), + .exists_oup_id_o ( wr_exists_id ), + .exists_full_o ( wr_exists_full ), + .pop_i ( slv_resp_o.b_valid && slv_req_i.b_ready ), + .pop_oup_id_i ( mst_resp_i.b.id[IdxWidth-1:0] ), + .pop_inp_id_o ( slv_resp_o.b.id ) + ); + axi_id_remap_table #( + .InpIdWidth ( AxiSlvPortIdWidth ), + .MaxUniqInpIds ( AxiSlvPortMaxUniqIds ), + .MaxTxnsPerId ( AxiMaxTxnsPerId ) + ) i_rd_table ( + .clk_i, + .rst_ni, + .free_o ( rd_free ), + .free_oup_id_o ( rd_free_oup_id ), + .full_o ( rd_full ), + .push_i ( rd_push ), + .push_inp_id_i ( rd_push_inp_id ), + .push_oup_id_i ( rd_push_oup_id ), + .exists_inp_id_i ( slv_req_i.ar.id ), + .exists_o ( rd_exists ), + .exists_oup_id_o ( rd_exists_id ), + .exists_full_o ( rd_exists_full ), + .pop_i ( slv_resp_o.r_valid && slv_req_i.r_ready && slv_resp_o.r.last ), + .pop_oup_id_i ( mst_resp_i.r.id[IdxWidth-1:0] ), + .pop_inp_id_o ( slv_resp_o.r.id ) + ); + assign both_free = wr_free & rd_free; + lzc #( + .WIDTH ( AxiSlvPortMaxUniqIds ), + .MODE ( 1'b0 ) + ) i_lzc ( + .in_i ( both_free ), + .cnt_o ( both_free_oup_id ), + .empty_o ( /* unused */ ) + ); + + // Zero-extend output IDs if the output IDs is are wider than the IDs from the tables. + localparam ZeroWidth = AxiMstPortIdWidth - IdxWidth; + assign mst_req_o.ar.id = {{ZeroWidth{1'b0}}, rd_push_oup_id}; + assign mst_req_o.aw.id = {{ZeroWidth{1'b0}}, wr_push_oup_id}; + + // Handle requests. + enum logic [1:0] {Ready, HoldAR, HoldAW, HoldAx} state_d, state_q; + idx_t ar_id_d, ar_id_q, + aw_id_d, aw_id_q; + always_comb begin + mst_req_o.aw_valid = 1'b0; + slv_resp_o.aw_ready = 1'b0; + wr_push = 1'b0; + wr_push_oup_id = '0; + mst_req_o.ar_valid = 1'b0; + slv_resp_o.ar_ready = 1'b0; + rd_push = 1'b0; + rd_push_inp_id = '0; + rd_push_oup_id = '0; + ar_id_d = ar_id_q; + aw_id_d = aw_id_q; + state_d = state_q; + ar_must_pass_d = ar_must_pass_q; + + unique case (state_q) + Ready: begin + // Reads + if (slv_req_i.ar_valid) begin + // If a burst with the same input ID is already in flight or there are free output IDs: + if ((rd_exists && !rd_exists_full) || (!rd_exists && !rd_full)) begin + // Determine the output ID: if another in-flight burst had the same input ID, we must + // reuse its output ID to maintain ordering; else, we assign the next free ID. + rd_push_inp_id = slv_req_i.ar.id; + rd_push_oup_id = rd_exists ? rd_exists_id : rd_free_oup_id; + // Forward the AR and push a new entry to the read table. + mst_req_o.ar_valid = 1'b1; + rd_push = 1'b1; + end + end + + // Writes + if (slv_req_i.aw_valid) begin + // If this is not an ATOP that gives rise to an R response, we can handle it in isolation + // on the write direction. + if (!slv_req_i.aw.atop[5]) begin + // If a burst with the same input ID is already in flight or there are free output IDs: + if ((wr_exists && !wr_exists_full) || (!wr_exists && !wr_full)) begin + // Determine the output ID: if another in-flight burst had the same input ID, we must + // reuse its output ID to maintain ordering; else, we assign the next free ID. + wr_push_oup_id = wr_exists ? wr_exists_id : wr_free_oup_id; + // Forward the AW and push a new entry to the write table. + mst_req_o.aw_valid = 1'b1; + wr_push = 1'b1; + end + // If this is an ATOP that gives rise to an R response, we must remap to an ID that is + // free on both read and write direction and push also to the read table. + end else if (ar_must_pass_q == 1'b0) begin + // Nullify a potential AR at our output. This is legal in this state. + ar_must_pass_d = mst_req_o.ar_valid; + mst_req_o.ar_valid = 1'b0; + slv_resp_o.ar_ready = 1'b0; + rd_push = 1'b0; + if ((|both_free)) begin + // Use an output ID that is free in both directions. + wr_push_oup_id = both_free_oup_id; + rd_push_inp_id = slv_req_i.aw.id; + rd_push_oup_id = both_free_oup_id; + // Forward the AW and push a new entry to both tables. + mst_req_o.aw_valid = 1'b1; + rd_push = 1'b1; + wr_push = 1'b1; + end + end + end + + // Hold AR, AW, or both if they are valid but not yet ready. + if (mst_req_o.ar_valid) begin + ar_must_pass_d = 1'b0; + slv_resp_o.ar_ready = mst_resp_i.ar_ready; + if (!mst_resp_i.ar_ready) begin + ar_id_d = rd_push_oup_id; + end + end + if (mst_req_o.aw_valid) begin + slv_resp_o.aw_ready = mst_resp_i.aw_ready; + if (!mst_resp_i.aw_ready) begin + aw_id_d = wr_push_oup_id; + end + end + priority casez ({mst_req_o.ar_valid, mst_resp_i.ar_ready, + mst_req_o.aw_valid, mst_resp_i.aw_ready}) + 4'b1010: state_d = HoldAx; + 4'b10??: state_d = HoldAR; + 4'b??10: state_d = HoldAW; + default: state_d = Ready; + endcase + end + + HoldAR: begin + // Drive `mst_req_o.ar.id` through `rd_push_oup_id`. + rd_push_oup_id = ar_id_q; + mst_req_o.ar_valid = 1'b1; + slv_resp_o.ar_ready = mst_resp_i.ar_ready; + if (mst_resp_i.ar_ready) begin + state_d = Ready; + end + end + + HoldAW: begin + // Drive mst_req_o.aw.id through `wr_push_oup_id`. + wr_push_oup_id = aw_id_q; + mst_req_o.aw_valid = 1'b1; + slv_resp_o.aw_ready = mst_resp_i.aw_ready; + if (mst_resp_i.aw_ready) begin + state_d = Ready; + end + end + + HoldAx: begin + rd_push_oup_id = ar_id_q; + mst_req_o.ar_valid = 1'b1; + slv_resp_o.ar_ready = mst_resp_i.ar_ready; + wr_push_oup_id = aw_id_q; + mst_req_o.aw_valid = 1'b1; + slv_resp_o.aw_ready = mst_resp_i.aw_ready; + unique case ({mst_resp_i.ar_ready, mst_resp_i.aw_ready}) + 2'b01: state_d = HoldAR; + 2'b10: state_d = HoldAW; + 2'b11: state_d = Ready; + default: /*do nothing / stay in this state*/; + endcase + end + + default: state_d = Ready; + endcase + end + + // Registers + `FFARN(ar_id_q, ar_id_d, '0, clk_i, rst_ni) + `FFARN(aw_id_q, aw_id_d, '0, clk_i, rst_ni) + `FFARN(ar_must_pass_q, ar_must_pass_d, '0, clk_i, rst_ni) + `FFARN(state_q, state_d, Ready, clk_i, rst_ni) + + `ifndef VERILATOR + // pragma translate_off + initial begin : p_assert + assert(AxiSlvPortIdWidth > 32'd0) + else $fatal(1, "Parameter AxiSlvPortIdWidth has to be larger than 0!"); + assert(AxiMstPortIdWidth >= IdxWidth) + else $fatal(1, "Parameter AxiMstPortIdWidth has to be at least IdxWidth!"); + assert (AxiSlvPortMaxUniqIds > 0) + else $fatal(1, "Parameter AxiSlvPortMaxUniqIds has to be larger than 0!"); + assert (AxiSlvPortMaxUniqIds <= 2**AxiSlvPortIdWidth) + else $fatal(1, "Parameter AxiSlvPortMaxUniqIds may be at most 2**AxiSlvPortIdWidth!"); + assert (AxiMaxTxnsPerId > 0) + else $fatal(1, "Parameter AxiMaxTxnsPerId has to be larger than 0!"); + assert($bits(slv_req_i.aw.addr) == $bits(mst_req_o.aw.addr)) + else $fatal(1, "AXI AW address widths are not equal!"); + assert($bits(slv_req_i.w.data) == $bits(mst_req_o.w.data)) + else $fatal(1, "AXI W data widths are not equal!"); + assert($bits(slv_req_i.ar.addr) == $bits(mst_req_o.ar.addr)) + else $fatal(1, "AXI AR address widths are not equal!"); + assert($bits(slv_resp_o.r.data) == $bits(mst_resp_i.r.data)) + else $fatal(1, "AXI R data widths are not equal!"); + assert ($bits(slv_req_i.aw.id) == AxiSlvPortIdWidth); + assert ($bits(slv_resp_o.b.id) == AxiSlvPortIdWidth); + assert ($bits(slv_req_i.ar.id) == AxiSlvPortIdWidth); + assert ($bits(slv_resp_o.r.id) == AxiSlvPortIdWidth); + assert ($bits(mst_req_o.aw.id) == AxiMstPortIdWidth); + assert ($bits(mst_resp_i.b.id) == AxiMstPortIdWidth); + assert ($bits(mst_req_o.ar.id) == AxiMstPortIdWidth); + assert ($bits(mst_resp_i.r.id) == AxiMstPortIdWidth); + end + + default disable iff (!rst_ni); + assert property (@(posedge clk_i) slv_req_i.aw_valid && slv_resp_o.aw_ready + |-> mst_req_o.aw_valid && mst_resp_i.aw_ready); + assert property (@(posedge clk_i) mst_resp_i.b_valid && mst_req_o.b_ready + |-> slv_resp_o.b_valid && slv_req_i.b_ready); + assert property (@(posedge clk_i) slv_req_i.ar_valid && slv_resp_o.ar_ready + |-> mst_req_o.ar_valid && mst_resp_i.ar_ready); + assert property (@(posedge clk_i) mst_resp_i.r_valid && mst_req_o.r_ready + |-> slv_resp_o.r_valid && slv_req_i.r_ready); + assert property (@(posedge clk_i) slv_resp_o.r_valid + |-> slv_resp_o.r.last == mst_resp_i.r.last); + assert property (@(posedge clk_i) mst_req_o.ar_valid && !mst_resp_i.ar_ready + |=> mst_req_o.ar_valid && $stable(mst_req_o.ar.id)); + assert property (@(posedge clk_i) mst_req_o.aw_valid && !mst_resp_i.aw_ready + |=> mst_req_o.aw_valid && $stable(mst_req_o.aw.id)); + // pragma translate_on + `endif +endmodule + +/// Internal module of [`axi_id_remap`](module.axi_id_remap): Table to remap input to output IDs. +/// +/// This module contains a table indexed by the output ID (type `idx_t`). Each table entry has two +/// fields: the input ID and a counter that records how many transactions with the input and output +/// ID of the entry are in-flight. +/// +/// The mapping from input and output IDs is injective. Therefore, when the table contains an entry +/// for an input ID with non-zero counter value, subsequent input IDs must use the same entry and +/// thus the same output ID. +/// +/// ## Relation of types and table layout +/// ![diagram of table](axi_id_remap_table.svg) +/// +/// ## Complexity +/// This module has: +/// - `MaxUniqInpIds * InpIdWidth * clog2(MaxTxnsPerId)` flip flops; +/// - `MaxUniqInpIds` comparators of width `InpIdWidth`; +/// - 2 leading-zero counters of width `MaxUniqInpIds`. +module axi_id_remap_table #( + /// Width of input IDs, therefore width of `id_inp_t`. + parameter int unsigned InpIdWidth = 32'd0, + /// Maximum number of different input IDs that can be in-flight. This defines the number of remap + /// table entries. + /// + /// The maximum value of this parameter is `2**InpIdWidth`. + parameter int unsigned MaxUniqInpIds = 32'd0, + /// Maximum number of in-flight transactions with the same ID. + parameter int unsigned MaxTxnsPerId = 32'd0, + /// Derived (**=do not override**) type of input IDs. + localparam type id_inp_t = logic [InpIdWidth-1:0], + /// Derived (**=do not override**) width of table index (ceiled binary logarithm of + /// `MaxUniqInpIds`). + localparam int unsigned IdxWidth = cf_math_pkg::idx_width(MaxUniqInpIds), + /// Derived (**=do not override**) type of table index (width = `IdxWidth`). + localparam type idx_t = logic [IdxWidth-1:0], + /// Derived (**=do not override**) type with one bit per table entry (thus also output ID). + localparam type field_t = logic [MaxUniqInpIds-1:0] +) ( + /// Rising-edge clock of all ports + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// One bit per table entry / output ID that indicates whether the entry is free. + output field_t free_o, + /// Lowest free output ID. Only valid if the table is not full (i.e., `!full_o`). + output idx_t free_oup_id_o, + /// Indicates whether the table is full. + output logic full_o, + + /// Push an input/output ID pair to the table. + input logic push_i, + /// Input ID to be pushed. If the table already contains this ID, its counter must be smaller than + /// `MaxTxnsPerId`. + input id_inp_t push_inp_id_i, + /// Output ID to be pushed. If the table already contains the input ID to be pushed, the output + /// ID **must** match the output ID of the existing entry with the same input ID. + input idx_t push_oup_id_i, + + /// Input ID to look up in the table. + input id_inp_t exists_inp_id_i, + /// Indicates whether the given input ID exists in the table. + output logic exists_o, + /// The output ID of the given input ID. Only valid if the input ID exists (i.e., `exists_o`). + output idx_t exists_oup_id_o, + /// Indicates whether the maximum number of transactions for the given input ID is reached. Only + /// valid if the input ID exists (i.e., `exists_o`). + output logic exists_full_o, + + /// Pop an output ID from the table. This reduces the counter for the table index given in + /// `pop_oup_id_i` by one. + input logic pop_i, + /// Output ID to be popped. The counter for this ID must be larger than `0`. + input idx_t pop_oup_id_i, + /// Input ID corresponding to the popped output ID. + output id_inp_t pop_inp_id_o +); + + /// Counter width, derived to hold numbers up to `MaxTxnsPerId`. + localparam int unsigned CntWidth = $clog2(MaxTxnsPerId+1); + /// Counter that tracks the number of in-flight transactions with an ID. + typedef logic [CntWidth-1:0] cnt_t; + + /// Type of a table entry. + typedef struct packed { + id_inp_t inp_id; + cnt_t cnt; + } entry_t; + + // Table indexed by output IDs that contains the corresponding input IDs + entry_t [MaxUniqInpIds-1:0] table_d, table_q; + + // Determine lowest free output ID. + for (genvar i = 0; i < MaxUniqInpIds; i++) begin : gen_free_o + assign free_o[i] = table_q[i].cnt == '0; + end + lzc #( + .WIDTH ( MaxUniqInpIds ), + .MODE ( 1'b0 ) + ) i_lzc_free ( + .in_i ( free_o ), + .cnt_o ( free_oup_id_o ), + .empty_o ( full_o ) + ); + + // Determine the input ID for a given output ID. + assign pop_inp_id_o = table_q[pop_oup_id_i].inp_id; + + // Determine if given output ID is already used and, if it is, by which input ID. + field_t match; + for (genvar i = 0; i < MaxUniqInpIds; i++) begin : gen_match + assign match[i] = table_q[i].cnt > 0 && table_q[i].inp_id == exists_inp_id_i; + end + logic no_match; + lzc #( + .WIDTH ( MaxUniqInpIds ), + .MODE ( 1'b0 ) + ) i_lzc_match ( + .in_i ( match ), + .cnt_o ( exists_oup_id_o ), + .empty_o ( no_match ) + ); + assign exists_o = ~no_match; + assign exists_full_o = table_q[exists_oup_id_o].cnt == MaxTxnsPerId; + + // Push and pop table entries. + always_comb begin + table_d = table_q; + if (push_i) begin + table_d[push_oup_id_i].inp_id = push_inp_id_i; + table_d[push_oup_id_i].cnt += 1; + end + if (pop_i) begin + table_d[pop_oup_id_i].cnt -= 1; + end + end + + // Registers + `FFARN(table_q, table_d, '0, clk_i, rst_ni) + + // Assertions + // pragma translate_off + `ifndef VERILATOR + default disable iff (!rst_ni); + assume property (@(posedge clk_i) push_i |-> + table_q[push_oup_id_i].cnt == '0 || table_q[push_oup_id_i].inp_id == push_inp_id_i) + else $error("Push must be to empty output ID or match existing input ID!"); + assume property (@(posedge clk_i) push_i |-> table_q[push_oup_id_i].cnt < MaxTxnsPerId) + else $error("Maximum number of in-flight bursts must not be exceeded!"); + assume property (@(posedge clk_i) pop_i |-> table_q[pop_oup_id_i].cnt > 0) + else $error("Pop must target output ID with non-zero counter!"); + assume property (@(posedge clk_i) $onehot0(match)) + else $error("Input ID in table must be unique!"); + initial begin + assert (InpIdWidth > 0); + assert (MaxUniqInpIds > 0); + assert (MaxUniqInpIds <= (1 << InpIdWidth)); + assert (MaxTxnsPerId > 0); + assert (IdxWidth >= 1); + end + `endif + // pragma translate_on + +endmodule + + +`include "axi/typedef.svh" +`include "axi/assign.svh" +/// Interface variant of [`axi_id_remap`](module.axi_id_remap). +/// +/// See the documentation of the main module for the definition of ports and parameters. +module axi_id_remap_intf #( + parameter int unsigned AXI_SLV_PORT_ID_WIDTH = 32'd0, + parameter int unsigned AXI_SLV_PORT_MAX_UNIQ_IDS = 32'd0, + parameter int unsigned AXI_MAX_TXNS_PER_ID = 32'd0, + parameter int unsigned AXI_MST_PORT_ID_WIDTH = 32'd0, + parameter int unsigned AXI_ADDR_WIDTH = 32'd0, + parameter int unsigned AXI_DATA_WIDTH = 32'd0, + parameter int unsigned AXI_USER_WIDTH = 32'd0 +) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Slave slv, + AXI_BUS.Master mst +); + typedef logic [AXI_SLV_PORT_ID_WIDTH-1:0] slv_id_t; + typedef logic [AXI_MST_PORT_ID_WIDTH-1:0] mst_id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] axi_addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] axi_data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] axi_strb_t; + typedef logic [AXI_USER_WIDTH-1:0] axi_user_t; + + `AXI_TYPEDEF_AW_CHAN_T(slv_aw_chan_t, axi_addr_t, slv_id_t, axi_user_t) + `AXI_TYPEDEF_W_CHAN_T(slv_w_chan_t, axi_data_t, axi_strb_t, axi_user_t) + `AXI_TYPEDEF_B_CHAN_T(slv_b_chan_t, slv_id_t, axi_user_t) + `AXI_TYPEDEF_AR_CHAN_T(slv_ar_chan_t, axi_addr_t, slv_id_t, axi_user_t) + `AXI_TYPEDEF_R_CHAN_T(slv_r_chan_t, axi_data_t, slv_id_t, axi_user_t) + `AXI_TYPEDEF_REQ_T(slv_req_t, slv_aw_chan_t, slv_w_chan_t, slv_ar_chan_t) + `AXI_TYPEDEF_RESP_T(slv_resp_t, slv_b_chan_t, slv_r_chan_t) + + `AXI_TYPEDEF_AW_CHAN_T(mst_aw_chan_t, axi_addr_t, mst_id_t, axi_user_t) + `AXI_TYPEDEF_W_CHAN_T(mst_w_chan_t, axi_data_t, axi_strb_t, axi_user_t) + `AXI_TYPEDEF_B_CHAN_T(mst_b_chan_t, mst_id_t, axi_user_t) + `AXI_TYPEDEF_AR_CHAN_T(mst_ar_chan_t, axi_addr_t, mst_id_t, axi_user_t) + `AXI_TYPEDEF_R_CHAN_T(mst_r_chan_t, axi_data_t, mst_id_t, axi_user_t) + `AXI_TYPEDEF_REQ_T(mst_req_t, mst_aw_chan_t, mst_w_chan_t, mst_ar_chan_t) + `AXI_TYPEDEF_RESP_T(mst_resp_t, mst_b_chan_t, mst_r_chan_t) + + slv_req_t slv_req; + slv_resp_t slv_resp; + mst_req_t mst_req; + mst_resp_t mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_id_remap #( + .AxiSlvPortIdWidth ( AXI_SLV_PORT_ID_WIDTH ), + .AxiSlvPortMaxUniqIds ( AXI_SLV_PORT_MAX_UNIQ_IDS ), + .AxiMaxTxnsPerId ( AXI_MAX_TXNS_PER_ID ), + .AxiMstPortIdWidth ( AXI_MST_PORT_ID_WIDTH ), + .slv_req_t ( slv_req_t ), + .slv_resp_t ( slv_resp_t ), + .mst_req_t ( mst_req_t ), + .mst_resp_t ( mst_resp_t ) + ) i_axi_id_remap ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (slv.AXI_ID_WIDTH == AXI_SLV_PORT_ID_WIDTH); + assert (slv.AXI_ADDR_WIDTH == AXI_ADDR_WIDTH); + assert (slv.AXI_DATA_WIDTH == AXI_DATA_WIDTH); + assert (slv.AXI_USER_WIDTH == AXI_USER_WIDTH); + assert (mst.AXI_ID_WIDTH == AXI_MST_PORT_ID_WIDTH); + assert (mst.AXI_ADDR_WIDTH == AXI_ADDR_WIDTH); + assert (mst.AXI_DATA_WIDTH == AXI_DATA_WIDTH); + assert (mst.AXI_USER_WIDTH == AXI_USER_WIDTH); + end + `endif + // pragma translate_on +endmodule diff --git a/hw/deps/axi/src/axi_intf.sv b/hw/deps/axi/src/axi_intf.sv new file mode 100644 index 0000000..38047fc --- /dev/null +++ b/hw/deps/axi/src/axi_intf.sv @@ -0,0 +1,434 @@ +// Copyright (c) 2014-2018 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. +// +// Fabian Schuiki +// +// This file defines the interfaces we support. + + + +/// An AXI4 interface. +interface AXI_BUS #( + parameter AXI_ADDR_WIDTH = -1, + parameter AXI_DATA_WIDTH = -1, + parameter AXI_ID_WIDTH = -1, + parameter AXI_USER_WIDTH = -1 +); + + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8; + + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_STRB_WIDTH-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + + id_t aw_id; + addr_t aw_addr; + axi_pkg::len_t aw_len; + axi_pkg::size_t aw_size; + axi_pkg::burst_t aw_burst; + logic aw_lock; + axi_pkg::cache_t aw_cache; + axi_pkg::prot_t aw_prot; + axi_pkg::qos_t aw_qos; + axi_pkg::region_t aw_region; + axi_pkg::atop_t aw_atop; + user_t aw_user; + logic aw_valid; + logic aw_ready; + + data_t w_data; + strb_t w_strb; + logic w_last; + user_t w_user; + logic w_valid; + logic w_ready; + + id_t b_id; + axi_pkg::resp_t b_resp; + user_t b_user; + logic b_valid; + logic b_ready; + + id_t ar_id; + addr_t ar_addr; + axi_pkg::len_t ar_len; + axi_pkg::size_t ar_size; + axi_pkg::burst_t ar_burst; + logic ar_lock; + axi_pkg::cache_t ar_cache; + axi_pkg::prot_t ar_prot; + axi_pkg::qos_t ar_qos; + axi_pkg::region_t ar_region; + user_t ar_user; + logic ar_valid; + logic ar_ready; + + id_t r_id; + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_last; + user_t r_user; + logic r_valid; + logic r_ready; + + modport Master ( + output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, input aw_ready, + output w_data, w_strb, w_last, w_user, w_valid, input w_ready, + input b_id, b_resp, b_user, b_valid, output b_ready, + output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready, + input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready + ); + + modport Slave ( + input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, output aw_ready, + input w_data, w_strb, w_last, w_user, w_valid, output w_ready, + output b_id, b_resp, b_user, b_valid, input b_ready, + input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready, + output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready + ); + +endinterface + + +/// A clocked AXI4 interface for use in design verification. +interface AXI_BUS_DV #( + parameter AXI_ADDR_WIDTH = -1, + parameter AXI_DATA_WIDTH = -1, + parameter AXI_ID_WIDTH = -1, + parameter AXI_USER_WIDTH = -1 +)( + input logic clk_i +); + + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8; + + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_STRB_WIDTH-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + + id_t aw_id; + addr_t aw_addr; + axi_pkg::len_t aw_len; + axi_pkg::size_t aw_size; + axi_pkg::burst_t aw_burst; + logic aw_lock; + axi_pkg::cache_t aw_cache; + axi_pkg::prot_t aw_prot; + axi_pkg::qos_t aw_qos; + axi_pkg::region_t aw_region; + axi_pkg::atop_t aw_atop; + user_t aw_user; + logic aw_valid; + logic aw_ready; + + data_t w_data; + strb_t w_strb; + logic w_last; + user_t w_user; + logic w_valid; + logic w_ready; + + id_t b_id; + axi_pkg::resp_t b_resp; + user_t b_user; + logic b_valid; + logic b_ready; + + id_t ar_id; + addr_t ar_addr; + axi_pkg::len_t ar_len; + axi_pkg::size_t ar_size; + axi_pkg::burst_t ar_burst; + logic ar_lock; + axi_pkg::cache_t ar_cache; + axi_pkg::prot_t ar_prot; + axi_pkg::qos_t ar_qos; + axi_pkg::region_t ar_region; + user_t ar_user; + logic ar_valid; + logic ar_ready; + + id_t r_id; + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_last; + user_t r_user; + logic r_valid; + logic r_ready; + + modport Master ( + output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, input aw_ready, + output w_data, w_strb, w_last, w_user, w_valid, input w_ready, + input b_id, b_resp, b_user, b_valid, output b_ready, + output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready, + input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready + ); + + modport Slave ( + input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, output aw_ready, + input w_data, w_strb, w_last, w_user, w_valid, output w_ready, + output b_id, b_resp, b_user, b_valid, input b_ready, + input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready, + output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready + ); + + // pragma translate_off + `ifndef VERILATOR + // Single-Channel Assertions: Signals including valid must not change between valid and handshake. + // AW + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_id))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_addr))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_len))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_size))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_burst))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_lock))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_cache))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_prot))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_qos))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_region))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_atop))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> $stable(aw_user))); + assert property (@(posedge clk_i) (aw_valid && !aw_ready |=> aw_valid)); + // W + assert property (@(posedge clk_i) ( w_valid && ! w_ready |=> $stable(w_data))); + assert property (@(posedge clk_i) ( w_valid && ! w_ready |=> $stable(w_strb))); + assert property (@(posedge clk_i) ( w_valid && ! w_ready |=> $stable(w_last))); + assert property (@(posedge clk_i) ( w_valid && ! w_ready |=> $stable(w_user))); + assert property (@(posedge clk_i) ( w_valid && ! w_ready |=> w_valid)); + // B + assert property (@(posedge clk_i) ( b_valid && ! b_ready |=> $stable(b_id))); + assert property (@(posedge clk_i) ( b_valid && ! b_ready |=> $stable(b_resp))); + assert property (@(posedge clk_i) ( b_valid && ! b_ready |=> $stable(b_user))); + assert property (@(posedge clk_i) ( b_valid && ! b_ready |=> b_valid)); + // AR + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_id))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_addr))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_len))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_size))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_burst))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_lock))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_cache))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_prot))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_qos))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_region))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> $stable(ar_user))); + assert property (@(posedge clk_i) (ar_valid && !ar_ready |=> ar_valid)); + // R + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> $stable(r_id))); + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> $stable(r_data))); + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> $stable(r_resp))); + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> $stable(r_last))); + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> $stable(r_user))); + assert property (@(posedge clk_i) ( r_valid && ! r_ready |=> r_valid)); + `endif + // pragma translate_on + +endinterface + +/// An asynchronous AXI4 interface. +interface AXI_BUS_ASYNC +#( + parameter AXI_ADDR_WIDTH = -1, + parameter AXI_DATA_WIDTH = -1, + parameter AXI_ID_WIDTH = -1, + parameter AXI_USER_WIDTH = -1, + parameter BUFFER_WIDTH = -1 +); + + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8; + + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_STRB_WIDTH-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + typedef logic [BUFFER_WIDTH-1:0] buffer_t; + + id_t aw_id; + addr_t aw_addr; + axi_pkg::len_t aw_len; + axi_pkg::size_t aw_size; + axi_pkg::burst_t aw_burst; + logic aw_lock; + axi_pkg::cache_t aw_cache; + axi_pkg::prot_t aw_prot; + axi_pkg::qos_t aw_qos; + axi_pkg::region_t aw_region; + axi_pkg::atop_t aw_atop; + user_t aw_user; + buffer_t aw_writetoken; + buffer_t aw_readpointer; + + data_t w_data; + strb_t w_strb; + logic w_last; + user_t w_user; + buffer_t w_writetoken; + buffer_t w_readpointer; + + id_t b_id; + axi_pkg::resp_t b_resp; + user_t b_user; + buffer_t b_writetoken; + buffer_t b_readpointer; + + id_t ar_id; + addr_t ar_addr; + axi_pkg::len_t ar_len; + axi_pkg::size_t ar_size; + axi_pkg::burst_t ar_burst; + logic ar_lock; + axi_pkg::cache_t ar_cache; + axi_pkg::prot_t ar_prot; + axi_pkg::qos_t ar_qos; + axi_pkg::region_t ar_region; + user_t ar_user; + buffer_t ar_writetoken; + buffer_t ar_readpointer; + + id_t r_id; + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_last; + user_t r_user; + buffer_t r_writetoken; + buffer_t r_readpointer; + + modport Master ( + output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_writetoken, input aw_readpointer, + output w_data, w_strb, w_last, w_user, w_writetoken, input w_readpointer, + input b_id, b_resp, b_user, b_writetoken, output b_readpointer, + output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, input ar_readpointer, + input r_id, r_data, r_resp, r_last, r_user, r_writetoken, output r_readpointer + ); + + modport Slave ( + input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_writetoken, output aw_readpointer, + input w_data, w_strb, w_last, w_user, w_writetoken, output w_readpointer, + output b_id, b_resp, b_user, b_writetoken, input b_readpointer, + input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, output ar_readpointer, + output r_id, r_data, r_resp, r_last, r_user, r_writetoken, input r_readpointer + ); + +endinterface + + +/// An AXI4-Lite interface. +interface AXI_LITE #( + parameter AXI_ADDR_WIDTH = -1, + parameter AXI_DATA_WIDTH = -1 +); + + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8; + + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_STRB_WIDTH-1:0] strb_t; + + // AW channel + addr_t aw_addr; + logic aw_valid; + logic aw_ready; + + data_t w_data; + strb_t w_strb; + logic w_valid; + logic w_ready; + + axi_pkg::resp_t b_resp; + logic b_valid; + logic b_ready; + + addr_t ar_addr; + logic ar_valid; + logic ar_ready; + + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_valid; + logic r_ready; + + modport Master ( + output aw_addr, aw_valid, input aw_ready, + output w_data, w_strb, w_valid, input w_ready, + input b_resp, b_valid, output b_ready, + output ar_addr, ar_valid, input ar_ready, + input r_data, r_resp, r_valid, output r_ready + ); + + modport Slave ( + input aw_addr, aw_valid, output aw_ready, + input w_data, w_strb, w_valid, output w_ready, + output b_resp, b_valid, input b_ready, + input ar_addr, ar_valid, output ar_ready, + output r_data, r_resp, r_valid, input r_ready + ); + +endinterface + +/// A clocked AXI4-Lite interface for use in design verification. +interface AXI_LITE_DV #( + parameter AXI_ADDR_WIDTH = -1, + parameter AXI_DATA_WIDTH = -1 +)( + input logic clk_i +); + + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8; + + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_STRB_WIDTH-1:0] strb_t; + + // AW channel + addr_t aw_addr; + logic aw_valid; + logic aw_ready; + + data_t w_data; + strb_t w_strb; + logic w_valid; + logic w_ready; + + axi_pkg::resp_t b_resp; + logic b_valid; + logic b_ready; + + addr_t ar_addr; + logic ar_valid; + logic ar_ready; + + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_valid; + logic r_ready; + + modport Master ( + output aw_addr, aw_valid, input aw_ready, + output w_data, w_strb, w_valid, input w_ready, + input b_resp, b_valid, output b_ready, + output ar_addr, ar_valid, input ar_ready, + input r_data, r_resp, r_valid, output r_ready + ); + + modport Slave ( + input aw_addr, aw_valid, output aw_ready, + input w_data, w_strb, w_valid, output w_ready, + output b_resp, b_valid, input b_ready, + input ar_addr, ar_valid, output ar_ready, + output r_data, r_resp, r_valid, input r_ready + ); + +endinterface diff --git a/hw/deps/axi/src/axi_mux.sv b/hw/deps/axi/src/axi_mux.sv new file mode 100644 index 0000000..f6644ff --- /dev/null +++ b/hw/deps/axi/src/axi_mux.sv @@ -0,0 +1,520 @@ +// Copyright (c) 2019 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. + +// Author: Wolfgang Roenninger + +// AXI Multiplexer: This module multiplexes the AXI4 slave ports down to one master port. +// The AXI IDs from the slave ports get extended with the respective slave port index. +// The extension width can be calculated with `$clog2(NoSlvPorts)`. This means the AXI +// ID for the master port has to be this `$clog2(NoSlvPorts)` wider than the ID for the +// slave ports. +// Responses are switched based on these bits. For example, with 4 slave ports +// a response with ID `6'b100110` will be forwarded to slave port 2 (`2'b10`). + +// register macros +`include "common_cells/registers.svh" + +module axi_mux #( + // AXI parameter and channel types + parameter int unsigned SlvAxiIDWidth = 32'd0, // AXI ID width, slave ports + parameter type slv_aw_chan_t = logic, // AW Channel Type, slave ports + parameter type mst_aw_chan_t = logic, // AW Channel Type, master port + parameter type w_chan_t = logic, // W Channel Type, all ports + parameter type slv_b_chan_t = logic, // B Channel Type, slave ports + parameter type mst_b_chan_t = logic, // B Channel Type, master port + parameter type slv_ar_chan_t = logic, // AR Channel Type, slave ports + parameter type mst_ar_chan_t = logic, // AR Channel Type, master port + parameter type slv_r_chan_t = logic, // R Channel Type, slave ports + parameter type mst_r_chan_t = logic, // R Channel Type, master port + parameter type slv_req_t = logic, // Slave port request type + parameter type slv_resp_t = logic, // Slave port response type + parameter type mst_req_t = logic, // Master ports request type + parameter type mst_resp_t = logic, // Master ports response type + parameter int unsigned NoSlvPorts = 32'd0, // Number of slave ports + // Maximum number of outstanding transactions per write + parameter int unsigned MaxWTrans = 32'd8, + // If enabled, this multiplexer is purely combinatorial + parameter bit FallThrough = 1'b0, + // add spill register on write master ports, adds a cycle latency on write channels + parameter bit SpillAw = 1'b1, + parameter bit SpillW = 1'b0, + parameter bit SpillB = 1'b0, + // add spill register on read master ports, adds a cycle latency on read channels + parameter bit SpillAr = 1'b1, + parameter bit SpillR = 1'b0 +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic test_i, // Test Mode enable + // slave ports (AXI inputs), connect master modules here + input slv_req_t [NoSlvPorts-1:0] slv_reqs_i, + output slv_resp_t [NoSlvPorts-1:0] slv_resps_o, + // master port (AXI outputs), connect slave modules here + output mst_req_t mst_req_o, + input mst_resp_t mst_resp_i +); + + localparam int unsigned MstIdxBits = $clog2(NoSlvPorts); + localparam int unsigned MstAxiIDWidth = SlvAxiIDWidth + MstIdxBits; + + // pass through if only one slave port + if (NoSlvPorts == 32'h1) begin : gen_no_mux + assign mst_req_o = slv_reqs_i[0]; + assign slv_resps_o[0] = mst_resp_i; + // other non degenerate cases + end else begin : gen_mux + + typedef logic [MstIdxBits-1:0] switch_id_t; + + // AXI channels between the ID prepend unit and the rest of the multiplexer + mst_aw_chan_t [NoSlvPorts-1:0] slv_aw_chans; + logic [NoSlvPorts-1:0] slv_aw_valids, slv_aw_readies; + w_chan_t [NoSlvPorts-1:0] slv_w_chans; + logic [NoSlvPorts-1:0] slv_w_valids, slv_w_readies; + mst_b_chan_t [NoSlvPorts-1:0] slv_b_chans; + logic [NoSlvPorts-1:0] slv_b_valids, slv_b_readies; + mst_ar_chan_t [NoSlvPorts-1:0] slv_ar_chans; + logic [NoSlvPorts-1:0] slv_ar_valids, slv_ar_readies; + mst_r_chan_t [NoSlvPorts-1:0] slv_r_chans; + logic [NoSlvPorts-1:0] slv_r_valids, slv_r_readies; + + // These signals are all ID prepended + // AW channel + mst_aw_chan_t mst_aw_chan; + logic mst_aw_valid, mst_aw_ready; + + // AW master handshake internal, so that we are able to stall, if w_fifo is full + logic aw_valid, aw_ready; + + // FF to lock the AW valid signal, when a new arbitration decision is made the decision + // gets pushed into the W FIFO, when it now stalls prevent subsequent pushing + // This FF removes AW to W dependency + logic lock_aw_valid_d, lock_aw_valid_q; + logic load_aw_lock; + + // signals for the FIFO that holds the last switching decision of the AW channel + logic w_fifo_full, w_fifo_empty; + logic w_fifo_push, w_fifo_pop; + switch_id_t w_fifo_data; + + // W channel spill reg + w_chan_t mst_w_chan; + logic mst_w_valid, mst_w_ready; + + // master ID in the b_id + switch_id_t switch_b_id; + + // B channel spill reg + mst_b_chan_t mst_b_chan; + logic mst_b_valid; + + // AR channel for when spill is enabled + mst_ar_chan_t mst_ar_chan; + logic ar_valid, ar_ready; + + // master ID in the r_id + switch_id_t switch_r_id; + + // R channel spill reg + mst_r_chan_t mst_r_chan; + logic mst_r_valid; + + //-------------------------------------- + // ID prepend for all slave ports + //-------------------------------------- + for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_id_prepend + axi_id_prepend #( + .NoBus ( 32'd1 ), // one AXI bus per slave port + .AxiIdWidthSlvPort( SlvAxiIDWidth ), + .AxiIdWidthMstPort( MstAxiIDWidth ), + .slv_aw_chan_t ( slv_aw_chan_t ), + .slv_w_chan_t ( w_chan_t ), + .slv_b_chan_t ( slv_b_chan_t ), + .slv_ar_chan_t ( slv_ar_chan_t ), + .slv_r_chan_t ( slv_r_chan_t ), + .mst_aw_chan_t ( mst_aw_chan_t ), + .mst_w_chan_t ( w_chan_t ), + .mst_b_chan_t ( mst_b_chan_t ), + .mst_ar_chan_t ( mst_ar_chan_t ), + .mst_r_chan_t ( mst_r_chan_t ) + ) i_id_prepend ( + .pre_id_i ( switch_id_t'(i) ), + .slv_aw_chans_i ( slv_reqs_i[i].aw ), + .slv_aw_valids_i ( slv_reqs_i[i].aw_valid ), + .slv_aw_readies_o ( slv_resps_o[i].aw_ready ), + .slv_w_chans_i ( slv_reqs_i[i].w ), + .slv_w_valids_i ( slv_reqs_i[i].w_valid ), + .slv_w_readies_o ( slv_resps_o[i].w_ready ), + .slv_b_chans_o ( slv_resps_o[i].b ), + .slv_b_valids_o ( slv_resps_o[i].b_valid ), + .slv_b_readies_i ( slv_reqs_i[i].b_ready ), + .slv_ar_chans_i ( slv_reqs_i[i].ar ), + .slv_ar_valids_i ( slv_reqs_i[i].ar_valid ), + .slv_ar_readies_o ( slv_resps_o[i].ar_ready ), + .slv_r_chans_o ( slv_resps_o[i].r ), + .slv_r_valids_o ( slv_resps_o[i].r_valid ), + .slv_r_readies_i ( slv_reqs_i[i].r_ready ), + .mst_aw_chans_o ( slv_aw_chans[i] ), + .mst_aw_valids_o ( slv_aw_valids[i] ), + .mst_aw_readies_i ( slv_aw_readies[i] ), + .mst_w_chans_o ( slv_w_chans[i] ), + .mst_w_valids_o ( slv_w_valids[i] ), + .mst_w_readies_i ( slv_w_readies[i] ), + .mst_b_chans_i ( slv_b_chans[i] ), + .mst_b_valids_i ( slv_b_valids[i] ), + .mst_b_readies_o ( slv_b_readies[i] ), + .mst_ar_chans_o ( slv_ar_chans[i] ), + .mst_ar_valids_o ( slv_ar_valids[i] ), + .mst_ar_readies_i ( slv_ar_readies[i] ), + .mst_r_chans_i ( slv_r_chans[i] ), + .mst_r_valids_i ( slv_r_valids[i] ), + .mst_r_readies_o ( slv_r_readies[i] ) + ); + end + + //-------------------------------------- + // AW Channel + //-------------------------------------- + rr_arb_tree #( + .NumIn ( NoSlvPorts ), + .DataType ( mst_aw_chan_t ), + .AxiVldRdy( 1'b1 ), + .LockIn ( 1'b1 ) + ) i_aw_arbiter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i( 1'b0 ), + .rr_i ( '0 ), + .req_i ( slv_aw_valids ), + .gnt_o ( slv_aw_readies ), + .data_i ( slv_aw_chans ), + .gnt_i ( aw_ready ), + .req_o ( aw_valid ), + .data_o ( mst_aw_chan ), + .idx_o ( ) + ); + + // control of the AW channel + always_comb begin + // default assignments + lock_aw_valid_d = lock_aw_valid_q; + load_aw_lock = 1'b0; + w_fifo_push = 1'b0; + mst_aw_valid = 1'b0; + aw_ready = 1'b0; + // had a downstream stall, be valid and send the AW along + if (lock_aw_valid_q) begin + mst_aw_valid = 1'b1; + // transaction + if (mst_aw_ready) begin + aw_ready = 1'b1; + lock_aw_valid_d = 1'b0; + load_aw_lock = 1'b1; + end + end else begin + if (!w_fifo_full && aw_valid) begin + mst_aw_valid = 1'b1; + w_fifo_push = 1'b1; + if (mst_aw_ready) begin + aw_ready = 1'b1; + end else begin + // go to lock if transaction not in this cycle + lock_aw_valid_d = 1'b1; + load_aw_lock = 1'b1; + end + end + end + end + + `FFLARN(lock_aw_valid_q, lock_aw_valid_d, load_aw_lock, '0, clk_i, rst_ni) + + fifo_v3 #( + .FALL_THROUGH ( FallThrough ), + .DEPTH ( MaxWTrans ), + .dtype ( switch_id_t ) + ) i_w_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( test_i ), + .full_o ( w_fifo_full ), + .empty_o ( w_fifo_empty ), + .usage_o ( ), + .data_i ( mst_aw_chan.id[SlvAxiIDWidth+:MstIdxBits] ), + .push_i ( w_fifo_push ), + .data_o ( w_fifo_data ), + .pop_i ( w_fifo_pop ) + ); + + spill_register #( + .T ( mst_aw_chan_t ), + .Bypass ( ~SpillAw ) // Param indicated that we want a spill reg + ) i_aw_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_aw_valid ), + .ready_o ( mst_aw_ready ), + .data_i ( mst_aw_chan ), + .valid_o ( mst_req_o.aw_valid ), + .ready_i ( mst_resp_i.aw_ready ), + .data_o ( mst_req_o.aw ) + ); + + //-------------------------------------- + // W Channel + //-------------------------------------- + // multiplexer + assign mst_w_chan = slv_w_chans[w_fifo_data]; + always_comb begin + // default assignments + mst_w_valid = 1'b0; + slv_w_readies = '0; + w_fifo_pop = 1'b0; + // control + if (!w_fifo_empty) begin + // connect the handshake + mst_w_valid = slv_w_valids[w_fifo_data]; + slv_w_readies[w_fifo_data] = mst_w_ready; + // pop FIFO on a last transaction + w_fifo_pop = slv_w_valids[w_fifo_data] & mst_w_ready & mst_w_chan.last; + end + end + + spill_register #( + .T ( w_chan_t ), + .Bypass ( ~SpillW ) + ) i_w_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_w_valid ), + .ready_o ( mst_w_ready ), + .data_i ( mst_w_chan ), + .valid_o ( mst_req_o.w_valid ), + .ready_i ( mst_resp_i.w_ready ), + .data_o ( mst_req_o.w ) + ); + + //-------------------------------------- + // B Channel + //-------------------------------------- + // replicate B channels + assign slv_b_chans = {NoSlvPorts{mst_b_chan}}; + // control B channel handshake + assign switch_b_id = mst_b_chan.id[SlvAxiIDWidth+:MstIdxBits]; + assign slv_b_valids = (mst_b_valid) ? (1 << switch_b_id) : '0; + + spill_register #( + .T ( mst_b_chan_t ), + .Bypass ( ~SpillB ) + ) i_b_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_resp_i.b_valid ), + .ready_o ( mst_req_o.b_ready ), + .data_i ( mst_resp_i.b ), + .valid_o ( mst_b_valid ), + .ready_i ( slv_b_readies[switch_b_id] ), + .data_o ( mst_b_chan ) + ); + + //-------------------------------------- + // AR Channel + //-------------------------------------- + rr_arb_tree #( + .NumIn ( NoSlvPorts ), + .DataType ( mst_ar_chan_t ), + .AxiVldRdy( 1'b1 ), + .LockIn ( 1'b1 ) + ) i_ar_arbiter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i( 1'b0 ), + .rr_i ( '0 ), + .req_i ( slv_ar_valids ), + .gnt_o ( slv_ar_readies ), + .data_i ( slv_ar_chans ), + .gnt_i ( ar_ready ), + .req_o ( ar_valid ), + .data_o ( mst_ar_chan ), + .idx_o ( ) + ); + + spill_register #( + .T ( mst_ar_chan_t ), + .Bypass ( ~SpillAr ) + ) i_ar_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( ar_valid ), + .ready_o ( ar_ready ), + .data_i ( mst_ar_chan ), + .valid_o ( mst_req_o.ar_valid ), + .ready_i ( mst_resp_i.ar_ready ), + .data_o ( mst_req_o.ar ) + ); + + //-------------------------------------- + // R Channel + //-------------------------------------- + // replicate R channels + assign slv_r_chans = {NoSlvPorts{mst_r_chan}}; + // R channel handshake control + assign switch_r_id = mst_r_chan.id[SlvAxiIDWidth+:MstIdxBits]; + assign slv_r_valids = (mst_r_valid) ? (1 << switch_r_id) : '0; + + spill_register #( + .T ( mst_r_chan_t ), + .Bypass ( ~SpillR ) + ) i_r_spill_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( mst_resp_i.r_valid ), + .ready_o ( mst_req_o.r_ready ), + .data_i ( mst_resp_i.r ), + .valid_o ( mst_r_valid ), + .ready_i ( slv_r_readies[switch_r_id] ), + .data_o ( mst_r_chan ) + ); + end + +// pragma translate_off +`ifndef VERILATOR + initial begin + assert (SlvAxiIDWidth > 0) else $fatal(1, "AXI ID width of slave ports must be non-zero!"); + assert (NoSlvPorts > 0) else $fatal(1, "Number of slave ports must be non-zero!"); + assert (MaxWTrans > 0) + else $fatal(1, "Maximum number of outstanding writes must be non-zero!"); + assert (MstAxiIDWidth >= SlvAxiIDWidth + $clog2(NoSlvPorts)) + else $fatal(1, "AXI ID width of master ports must be wide enough to identify slave ports!"); + // Assert ID widths (one slave is sufficient since they all have the same type). + assert ($unsigned($bits(slv_reqs_i[0].aw.id)) == SlvAxiIDWidth) + else $fatal(1, "ID width of AW channel of slave ports does not match parameter!"); + assert ($unsigned($bits(slv_reqs_i[0].ar.id)) == SlvAxiIDWidth) + else $fatal(1, "ID width of AR channel of slave ports does not match parameter!"); + assert ($unsigned($bits(slv_resps_o[0].b.id)) == SlvAxiIDWidth) + else $fatal(1, "ID width of B channel of slave ports does not match parameter!"); + assert ($unsigned($bits(slv_resps_o[0].r.id)) == SlvAxiIDWidth) + else $fatal(1, "ID width of R channel of slave ports does not match parameter!"); + assert ($unsigned($bits(mst_req_o.aw.id)) == MstAxiIDWidth) + else $fatal(1, "ID width of AW channel of master port is wrong!"); + assert ($unsigned($bits(mst_req_o.ar.id)) == MstAxiIDWidth) + else $fatal(1, "ID width of AR channel of master port is wrong!"); + assert ($unsigned($bits(mst_resp_i.b.id)) == MstAxiIDWidth) + else $fatal(1, "ID width of B channel of master port is wrong!"); + assert ($unsigned($bits(mst_resp_i.r.id)) == MstAxiIDWidth) + else $fatal(1, "ID width of R channel of master port is wrong!"); + end +`endif +// pragma translate_on +endmodule + +// interface wrap +`include "axi/assign.svh" +`include "axi/typedef.svh" +module axi_mux_intf #( + parameter int unsigned SLV_AXI_ID_WIDTH = 32'd0, // Synopsys DC requires default value for params + parameter int unsigned MST_AXI_ID_WIDTH = 32'd0, + parameter int unsigned AXI_ADDR_WIDTH = 32'd0, + parameter int unsigned AXI_DATA_WIDTH = 32'd0, + parameter int unsigned AXI_USER_WIDTH = 32'd0, + parameter int unsigned NO_SLV_PORTS = 32'd0, // Number of slave ports + // Maximum number of outstanding transactions per write + parameter int unsigned MAX_W_TRANS = 32'd8, + // if enabled, this multiplexer is purely combinatorial + parameter bit FALL_THROUGH = 1'b0, + // add spill register on write master ports, adds a cycle latency on write channels + parameter bit SPILL_AW = 1'b1, + parameter bit SPILL_W = 1'b0, + parameter bit SPILL_B = 1'b0, + // add spill register on read master ports, adds a cycle latency on read channels + parameter bit SPILL_AR = 1'b1, + parameter bit SPILL_R = 1'b0 +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic test_i, // Testmode enable + AXI_BUS.Slave slv [NO_SLV_PORTS-1:0], // slave ports + AXI_BUS.Master mst // master port +); + + typedef logic [SLV_AXI_ID_WIDTH-1:0] slv_id_t; + typedef logic [MST_AXI_ID_WIDTH-1:0] mst_id_t; + typedef logic [AXI_ADDR_WIDTH -1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + // channels typedef + `AXI_TYPEDEF_AW_CHAN_T(slv_aw_chan_t, addr_t, slv_id_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(mst_aw_chan_t, addr_t, mst_id_t, user_t) + + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + + `AXI_TYPEDEF_B_CHAN_T(slv_b_chan_t, slv_id_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(mst_b_chan_t, mst_id_t, user_t) + + `AXI_TYPEDEF_AR_CHAN_T(slv_ar_chan_t, addr_t, slv_id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(mst_ar_chan_t, addr_t, mst_id_t, user_t) + + `AXI_TYPEDEF_R_CHAN_T(slv_r_chan_t, data_t, slv_id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(mst_r_chan_t, data_t, mst_id_t, user_t) + + `AXI_TYPEDEF_REQ_T(slv_req_t, slv_aw_chan_t, w_chan_t, slv_ar_chan_t) + `AXI_TYPEDEF_RESP_T(slv_resp_t, slv_b_chan_t, slv_r_chan_t) + + `AXI_TYPEDEF_REQ_T(mst_req_t, mst_aw_chan_t, w_chan_t, mst_ar_chan_t) + `AXI_TYPEDEF_RESP_T(mst_resp_t, mst_b_chan_t, mst_r_chan_t) + + slv_req_t [NO_SLV_PORTS-1:0] slv_reqs; + slv_resp_t [NO_SLV_PORTS-1:0] slv_resps; + mst_req_t mst_req; + mst_resp_t mst_resp; + + for (genvar i = 0; i < NO_SLV_PORTS; i++) begin : gen_assign_slv_ports + `AXI_ASSIGN_TO_REQ(slv_reqs[i], slv[i]) + `AXI_ASSIGN_FROM_RESP(slv[i], slv_resps[i]) + end + + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_mux #( + .SlvAxiIDWidth ( SLV_AXI_ID_WIDTH ), + .slv_aw_chan_t ( slv_aw_chan_t ), // AW Channel Type, slave ports + .mst_aw_chan_t ( mst_aw_chan_t ), // AW Channel Type, master port + .w_chan_t ( w_chan_t ), // W Channel Type, all ports + .slv_b_chan_t ( slv_b_chan_t ), // B Channel Type, slave ports + .mst_b_chan_t ( mst_b_chan_t ), // B Channel Type, master port + .slv_ar_chan_t ( slv_ar_chan_t ), // AR Channel Type, slave ports + .mst_ar_chan_t ( mst_ar_chan_t ), // AR Channel Type, master port + .slv_r_chan_t ( slv_r_chan_t ), // R Channel Type, slave ports + .mst_r_chan_t ( mst_r_chan_t ), // R Channel Type, master port + .slv_req_t ( slv_req_t ), + .slv_resp_t ( slv_resp_t ), + .mst_req_t ( mst_req_t ), + .mst_resp_t ( mst_resp_t ), + .NoSlvPorts ( NO_SLV_PORTS ), // Number of slave ports + .MaxWTrans ( MAX_W_TRANS ), + .FallThrough ( FALL_THROUGH ), + .SpillAw ( SPILL_AW ), + .SpillW ( SPILL_W ), + .SpillB ( SPILL_B ), + .SpillAr ( SPILL_AR ), + .SpillR ( SPILL_R ) + ) i_axi_mux ( + .clk_i ( clk_i ), // Clock + .rst_ni ( rst_ni ), // Asynchronous reset active low + .test_i ( test_i ), // Test Mode enable + .slv_reqs_i ( slv_reqs ), + .slv_resps_o ( slv_resps ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); +endmodule diff --git a/hw/deps/axi/src/axi_pkg.sv b/hw/deps/axi/src/axi_pkg.sv new file mode 100644 index 0000000..74e879d --- /dev/null +++ b/hw/deps/axi/src/axi_pkg.sv @@ -0,0 +1,311 @@ +// Copyright (c) 2014-2020 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. +// +// Fabian Schuiki +// Andreas Kurth + +//! AXI Package +/// Contains all necessary type definitions, constants, and generally useful functions. +package axi_pkg; + /// AXI Transaction Burst Type. + typedef logic [1:0] burst_t; + /// AXI Transaction Response Type. + typedef logic [1:0] resp_t; + /// AXI Transaction Cacheability Type. + typedef logic [3:0] cache_t; + /// AXI Transaction Protection Type. + typedef logic [2:0] prot_t; + /// AXI Transaction Quality of Service Type. + typedef logic [3:0] qos_t; + /// AXI Transaction Region Type. + typedef logic [3:0] region_t; + /// AXI Transaction Length Type. + typedef logic [7:0] len_t; + /// AXI Transaction Size Type. + typedef logic [2:0] size_t; + /// AXI5 Atomic Operation Type. + typedef logic [5:0] atop_t; // atomic operations + /// AXI5 Non-Secure Address Identifier. + typedef logic [3:0] nsaid_t; + + /// In a fixed burst: + /// - The address is the same for every transfer in the burst. + /// - The byte lanes that are valid are constant for all beats in the burst. However, within + /// those byte lanes, the actual bytes that have `wstrb` asserted can differ for each beat in + /// the burst. + /// This burst type is used for repeated accesses to the same location such as when loading or + /// emptying a FIFO. + localparam BURST_FIXED = 2'b00; + /// In an incrementing burst, the address for each transfer in the burst is an increment of the + /// address for the previous transfer. The increment value depends on the size of the transfer. + /// For example, the address for each transfer in a burst with a size of 4 bytes is the previous + /// address plus four. + /// This burst type is used for accesses to normal sequential memory. + localparam BURST_INCR = 2'b01; + /// A wrapping burst is similar to an incrementing burst, except that the address wraps around to + /// a lower address if an upper address limit is reached. + /// The following restrictions apply to wrapping bursts: + /// - The start address must be aligned to the size of each transfer. + /// - The length of the burst must be 2, 4, 8, or 16 transfers. + localparam BURST_WRAP = 2'b10; + + /// Normal access success. Indicates that a normal access has been successful. Can also indicate + /// that an exclusive access has failed. + localparam RESP_OKAY = 2'b00; + /// Exclusive access okay. Indicates that either the read or write portion of an exclusive access + /// has been successful. + localparam RESP_EXOKAY = 2'b01; + /// Slave error. Used when the access has reached the slave successfully, but the slave wishes to + /// return an error condition to the originating master. + localparam RESP_SLVERR = 2'b10; + /// Decode error. Generated, typically by an interconnect component, to indicate that there is no + /// slave at the transaction address. + localparam RESP_DECERR = 2'b11; + + /// When this bit is asserted, the interconnect, or any component, can delay the transaction + /// reaching its final destination for any number of cycles. + localparam CACHE_BUFFERABLE = 4'b0001; + /// When HIGH, Modifiable indicates that the characteristics of the transaction can be modified. + /// When Modifiable is LOW, the transaction is Non-modifiable. + localparam CACHE_MODIFIABLE = 4'b0010; + /// When this bit is asserted, read allocation of the transaction is recommended but is not + /// mandatory. + localparam CACHE_RD_ALLOC = 4'b0100; + /// When this bit is asserted, write allocation of the transaction is recommended but is not + /// mandatory. + localparam CACHE_WR_ALLOC = 4'b1000; + + /// Maximum number of bytes per burst, as specified by `size` (see Table A3-2). + function automatic shortint unsigned num_bytes(size_t size); + return 1 << size; + endfunction + + /// An overly long address type. + /// It lets us define functions that work generically for shorter addresses. We rely on the + /// synthesizer to optimize the unused bits away. + typedef logic [127:0] largest_addr_t; + + /// Aligned address of burst (see A3-51). + function automatic largest_addr_t aligned_addr(largest_addr_t addr, size_t size); + return (addr >> size) << size; + endfunction + + /// Address of beat (see A3-51). + function automatic largest_addr_t + beat_addr(largest_addr_t addr, size_t size, shortint unsigned i_beat); + if (i_beat == 0) begin + return addr; + end else begin + return aligned_addr(addr, size) + i_beat * num_bytes(size); + end + endfunction + + /// Index of lowest beat in byte (see A3-51). + function automatic shortint unsigned + beat_lower_byte(largest_addr_t addr, size_t size, shortint unsigned strobe_width, + shortint unsigned i_beat); + largest_addr_t _addr = beat_addr(addr, size, i_beat); + return _addr - (_addr / strobe_width) * strobe_width; + endfunction + + /// Index of highest beat in byte (see A3-51). + function automatic shortint unsigned + beat_upper_byte(largest_addr_t addr, size_t size, shortint unsigned strobe_width, + shortint unsigned i_beat); + if (i_beat == 0) begin + return aligned_addr(addr, size) + (num_bytes(size) - 1) - (addr / strobe_width) * strobe_width; + end else begin + return beat_lower_byte(addr, size, strobe_width, i_beat) + num_bytes(size) - 1; + end + endfunction + + /// Memory Type. + typedef enum logic [3:0] { + DEVICE_NONBUFFERABLE, + DEVICE_BUFFERABLE, + NORMAL_NONCACHEABLE_NONBUFFERABLE, + NORMAL_NONCACHEABLE_BUFFERABLE, + WTHRU_NOALLOCATE, + WTHRU_RALLOCATE, + WTHRU_WALLOCATE, + WTHRU_RWALLOCATE, + WBACK_NOALLOCATE, + WBACK_RALLOCATE, + WBACK_WALLOCATE, + WBACK_RWALLOCATE + } mem_type_t; + + /// Create an `AR_CACHE` field from a `mem_type_t` type. + function automatic logic [3:0] get_arcache(mem_type_t mtype); + unique case (mtype) + DEVICE_NONBUFFERABLE : return 4'b0000; + DEVICE_BUFFERABLE : return 4'b0001; + NORMAL_NONCACHEABLE_NONBUFFERABLE : return 4'b0010; + NORMAL_NONCACHEABLE_BUFFERABLE : return 4'b0011; + WTHRU_NOALLOCATE : return 4'b1010; + WTHRU_RALLOCATE : return 4'b1110; + WTHRU_WALLOCATE : return 4'b1010; + WTHRU_RWALLOCATE : return 4'b1110; + WBACK_NOALLOCATE : return 4'b1011; + WBACK_RALLOCATE : return 4'b1111; + WBACK_WALLOCATE : return 4'b1011; + WBACK_RWALLOCATE : return 4'b1111; + endcase // mtype + endfunction + + /// Create an `AW_CACHE` field from a `mem_type_t` type. + function automatic logic [3:0] get_awcache(mem_type_t mtype); + unique case (mtype) + DEVICE_NONBUFFERABLE : return 4'b0000; + DEVICE_BUFFERABLE : return 4'b0001; + NORMAL_NONCACHEABLE_NONBUFFERABLE : return 4'b0010; + NORMAL_NONCACHEABLE_BUFFERABLE : return 4'b0011; + WTHRU_NOALLOCATE : return 4'b0110; + WTHRU_RALLOCATE : return 4'b0110; + WTHRU_WALLOCATE : return 4'b1110; + WTHRU_RWALLOCATE : return 4'b1110; + WBACK_NOALLOCATE : return 4'b0111; + WBACK_RALLOCATE : return 4'b0111; + WBACK_WALLOCATE : return 4'b1111; + WBACK_RWALLOCATE : return 4'b1111; + endcase // mtype + endfunction + + // ATOP[5:0] + /// - Sends a single data value with an address. + /// - The target swaps the value at the addressed location with the data value that is supplied in + /// the transaction. + /// - The original data value at the addressed location is returned. + /// - Outbound data size is 1, 2, 4, or 8 bytes. + /// - Inbound data size is the same as the outbound data size. + localparam ATOP_ATOMICSWAP = 6'b110000; + /// - Sends two data values, the compare value and the swap value, to the addressed location. + /// The compare and swap values are of equal size. + /// - The data value at the addressed location is checked against the compare value: + /// - If the values match, the swap value is written to the addressed location. + /// - If the values do not match, the swap value is not written to the addressed location. + /// - The original data value at the addressed location is returned. + /// - Outbound data size is 2, 4, 8, 16, or 32 bytes. + /// - Inbound data size is half of the outbound data size because the outbound data contains both + /// compare and swap values, whereas the inbound data has only the original data value. + localparam ATOP_ATOMICCMP = 6'b110001; + // ATOP[5:4] + /// Perform no atomic operation. + localparam ATOP_NONE = 2'b00; + /// - Sends a single data value with an address and the atomic operation to be performed. + /// - The target performs the operation using the sent data and value at the addressed location as + /// operands. + /// - The result is stored in the address location. + /// - A single response is given without data. + /// - Outbound data size is 1, 2, 4, or 8 bytes. + localparam ATOP_ATOMICSTORE = 2'b01; + /// Sends a single data value with an address and the atomic operation to be performed. + /// - The original data value at the addressed location is returned. + /// - The target performs the operation using the sent data and value at the addressed location as + /// operands. + /// - The result is stored in the address location. + /// - Outbound data size is 1, 2, 4, or 8 bytes. + /// - Inbound data size is the same as the outbound data size. + localparam ATOP_ATOMICLOAD = 2'b10; + // ATOP[3] + /// For AtomicStore and AtomicLoad transactions `AWATOP[3]` indicates the endianness that is + /// required for the atomic operation. The value of `AWATOP[3]` applies to arithmetic operations + /// only and is ignored for bitwise logical operations. + /// When deasserted, this bit indicates that the operation is little-endian. + localparam ATOP_LITTLE_END = 1'b0; + /// When asserted, this bit indicates that the operation is big-endian. + localparam ATOP_BIG_END = 1'b1; + // ATOP[2:0] + /// The value in memory is added to the sent data and the result stored in memory. + localparam ATOP_ADD = 3'b000; + /// Every set bit in the sent data clears the corresponding bit of the data in memory. + localparam ATOP_CLR = 3'b001; + /// Bitwise exclusive OR of the sent data and value in memory. + localparam ATOP_EOR = 3'b010; + /// Every set bit in the sent data sets the corresponding bit of the data in memory. + localparam ATOP_SET = 3'b011; + /// The value stored in memory is the maximum of the existing value and sent data. This operation + /// assumes signed data. + localparam ATOP_SMAX = 3'b100; + /// The value stored in memory is the minimum of the existing value and sent data. This operation + /// assumes signed data. + localparam ATOP_SMIN = 3'b101; + /// The value stored in memory is the maximum of the existing value and sent data. This operation + /// assumes unsigned data. + localparam ATOP_UMAX = 3'b110; + /// The value stored in memory is the minimum of the existing value and sent data. This operation + /// assumes unsigned data. + localparam ATOP_UMIN = 3'b111; + // ATOP[5] == 1'b1 indicated that an atomic transaction has a read response + // Ussage eg: if (req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin + localparam ATOP_R_RESP = 32'd5; + + // `xbar_latency_e` and `xbar_cfg_t` are documented in `doc/axi_xbar.md`. + /// Slice on Demux AW channel. + localparam logic [9:0] DemuxAw = (1 << 9); + /// Slice on Demux W channel. + localparam logic [9:0] DemuxW = (1 << 8); + /// Slice on Demux B channel. + localparam logic [9:0] DemuxB = (1 << 7); + /// Slice on Demux AR channel. + localparam logic [9:0] DemuxAr = (1 << 6); + /// Slice on Demux R channel. + localparam logic [9:0] DemuxR = (1 << 5); + /// Slice on Mux AW channel. + localparam logic [9:0] MuxAw = (1 << 4); + /// Slice on Mux W channel. + localparam logic [9:0] MuxW = (1 << 3); + /// Slice on Mux B channel. + localparam logic [9:0] MuxB = (1 << 2); + /// Slice on Mux AR channel. + localparam logic [9:0] MuxAr = (1 << 1); + /// Slice on Mux R channel. + localparam logic [9:0] MuxR = (1 << 0); + /// Latency configuration for `axi_xbar`. + typedef enum logic [9:0] { + NO_LATENCY = 10'b000_00_000_00, + CUT_SLV_AX = DemuxAw | DemuxAr, + CUT_MST_AX = MuxAw | MuxAr, + CUT_ALL_AX = DemuxAw | DemuxAr | MuxAw | MuxAr, + CUT_SLV_PORTS = DemuxAw | DemuxW | DemuxB | DemuxAr | DemuxR, + CUT_MST_PORTS = MuxAw | MuxW | MuxB | MuxAr | MuxR, + CUT_ALL_PORTS = 10'b111_11_111_11 + } xbar_latency_e; + + /// Configuration for `axi_xbar`. + typedef struct packed { + int unsigned NoSlvPorts; + int unsigned NoMstPorts; + int unsigned MaxMstTrans; + int unsigned MaxSlvTrans; + bit FallThrough; + xbar_latency_e LatencyMode; + int unsigned AxiIdWidthSlvPorts; + int unsigned AxiIdUsedSlvPorts; + int unsigned AxiAddrWidth; + int unsigned AxiDataWidth; + int unsigned NoAddrRules; + } xbar_cfg_t; + + /// Commonly used rule types for `axi_xbar` (64-bit addresses). + typedef struct packed { + int unsigned idx; + logic [63:0] start_addr; + logic [63:0] end_addr; + } xbar_rule_64_t; + + /// Commonly used rule types for `axi_xbar` (32-bit addresses). + typedef struct packed { + int unsigned idx; + logic [31:0] start_addr; + logic [31:0] end_addr; + } xbar_rule_32_t; +endpackage diff --git a/hw/deps/axi/src/axi_serializer.sv b/hw/deps/axi/src/axi_serializer.sv new file mode 100644 index 0000000..5ff0d91 --- /dev/null +++ b/hw/deps/axi/src/axi_serializer.sv @@ -0,0 +1,294 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Author: Andreas Kurth +// Wolfgang Roenninger + +`include "common_cells/registers.svh" + +/// Serialize all AXI transactions to a single ID (zero). +/// +/// This module contains one queue with slave port IDs for the read direction and one for the write +/// direction. These queues are used to reconstruct the ID of responses at the slave port. The +/// depth of each queue is defined by `MaxReadTxns` and `MaxWriteTxns`, respectively. +module axi_serializer #( + /// Maximum number of in flight read transactions. + parameter int unsigned MaxReadTxns = 32'd0, + /// Maximum number of in flight write transactions. + parameter int unsigned MaxWriteTxns = 32'd0, + /// AXI4+ATOP ID width. + parameter int unsigned AxiIdWidth = 32'd0, + /// AXI4+ATOP request struct definition. + parameter type req_t = logic, + /// AXI4+ATOP response struct definition. + parameter type resp_t = logic +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Slave port request + input req_t slv_req_i, + /// Slave port response + output resp_t slv_resp_o, + /// Master port request + output req_t mst_req_o, + /// Master port response + input resp_t mst_resp_i +); + + typedef logic [AxiIdWidth-1:0] id_t; + typedef enum logic [1:0] { + AtopIdle = 2'b00, + AtopDrain = 2'b01, + AtopExecute = 2'b10 + } state_e; + + logic rd_fifo_full, rd_fifo_empty, rd_fifo_push, rd_fifo_pop, + wr_fifo_full, wr_fifo_empty, wr_fifo_push, wr_fifo_pop; + id_t b_id, + r_id, ar_id; + state_e state_q, state_d; + + always_comb begin + // Default assignments + state_d = state_q; + rd_fifo_push = 1'b0; + wr_fifo_push = 1'b0; + + // Default, connect the channels + mst_req_o = slv_req_i; + slv_resp_o = mst_resp_i; + + // Serialize transactions -> tie downstream IDs to zero. + mst_req_o.aw.id = '0; + mst_req_o.ar.id = '0; + + // Reflect upstream ID in response. + ar_id = slv_req_i.ar.id; + slv_resp_o.b.id = b_id; + slv_resp_o.r.id = r_id; + + // Default, cut the AW/AR handshaking + mst_req_o.ar_valid = 1'b0; + slv_resp_o.ar_ready = 1'b0; + mst_req_o.aw_valid = 1'b0; + slv_resp_o.aw_ready = 1'b0; + + unique case (state_q) + AtopIdle, AtopExecute: begin + + // Wait until the ATOP response(s) have been sent back upstream. + if (state_q == AtopExecute) begin + if ((wr_fifo_empty && rd_fifo_empty) || (wr_fifo_pop && rd_fifo_pop) || + (wr_fifo_empty && rd_fifo_pop) || (wr_fifo_pop && rd_fifo_empty)) begin + state_d = AtopIdle; + end + end + + // This part lets new Transactions through, if no ATOP is underway or the last ATOP + // response has been transmitted. + if ((state_q == AtopIdle) || (state_d == AtopIdle)) begin + // Gate AR handshake with ready output of Read FIFO. + mst_req_o.ar_valid = slv_req_i.ar_valid & ~rd_fifo_full; + slv_resp_o.ar_ready = mst_resp_i.ar_ready & ~rd_fifo_full; + rd_fifo_push = mst_req_o.ar_valid & mst_resp_i.ar_ready; + if (slv_req_i.aw_valid) begin + if (slv_req_i.aw.atop[5:4] == axi_pkg::ATOP_NONE) begin + // Normal operation + // Gate AW handshake with ready output of Write FIFO. + mst_req_o.aw_valid = ~wr_fifo_full; + slv_resp_o.aw_ready = mst_resp_i.aw_ready & ~wr_fifo_full; + wr_fifo_push = mst_req_o.aw_valid & mst_resp_i.aw_ready; + end else begin + // Atomic Operation received, go to drain state, when both channels are ready + // Wait for finished or no AR beat + if (!mst_req_o.ar_valid || (mst_req_o.ar_valid && mst_resp_i.ar_ready)) begin + state_d = AtopDrain; + end + end + end + end + end + AtopDrain: begin + // Send the ATOP AW when the last open transaction terminates + if (wr_fifo_empty && rd_fifo_empty) begin + mst_req_o.aw_valid = 1'b1; + slv_resp_o.aw_ready = mst_resp_i.aw_ready; + wr_fifo_push = mst_resp_i.aw_ready; + if (slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin + // Overwrite the read ID with the one from AW + ar_id = slv_req_i.aw.id; + rd_fifo_push = mst_resp_i.aw_ready; + end + if (mst_resp_i.aw_ready) begin + state_d = AtopExecute; + end + end + end + default : /* do nothing */; + endcase + + // Gate B handshake with empty flag output of Write FIFO. + slv_resp_o.b_valid = mst_resp_i.b_valid & ~wr_fifo_empty; + mst_req_o.b_ready = slv_req_i.b_ready & ~wr_fifo_empty; + + // Gate R handshake with empty flag output of Read FIFO. + slv_resp_o.r_valid = mst_resp_i.r_valid & ~rd_fifo_empty; + mst_req_o.r_ready = slv_req_i.r_ready & ~rd_fifo_empty; + end + + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), // No fall-through as response has to come a cycle later anyway + .DEPTH ( MaxReadTxns ), + .dtype ( id_t ) + ) i_rd_id_fifo ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .data_i ( ar_id ), + .push_i ( rd_fifo_push ), + .full_o ( rd_fifo_full ), + .data_o ( r_id ), + .empty_o ( rd_fifo_empty ), + .pop_i ( rd_fifo_pop ), + .usage_o ( /*not used*/ ) + ); + // Assign as this condition is needed in FSM + assign rd_fifo_pop = slv_resp_o.r_valid & slv_req_i.r_ready & slv_resp_o.r.last; + + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DEPTH ( MaxWriteTxns ), + .dtype ( id_t ) + ) i_wr_id_fifo ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .data_i ( slv_req_i.aw.id ), + .push_i ( wr_fifo_push ), + .full_o ( wr_fifo_full ), + .data_o ( b_id ), + .empty_o ( wr_fifo_empty ), + .pop_i ( wr_fifo_pop ), + .usage_o ( /*not used*/ ) + ); + // Assign as this condition is needed in FSM + assign wr_fifo_pop = slv_resp_o.b_valid & slv_req_i.b_ready; + + `FFARN(state_q, state_d, AtopIdle, clk_i, rst_ni) + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (AxiIdWidth >= 1) else $fatal(1, "AXI ID width must be at least 1!"); + assert (MaxReadTxns >= 1) + else $fatal(1, "Maximum number of read transactions must be >= 1!"); + assert (MaxWriteTxns >= 1) + else $fatal(1, "Maximum number of write transactions must be >= 1!"); + end + default disable iff (~rst_ni); + aw_lost : assert property( @(posedge clk_i) + (slv_req_i.aw_valid & slv_resp_o.aw_ready |-> mst_req_o.aw_valid & mst_resp_i.aw_ready)) + else $error("AW beat lost."); + w_lost : assert property( @(posedge clk_i) + (slv_req_i.w_valid & slv_resp_o.w_ready |-> mst_req_o.w_valid & mst_resp_i.w_ready)) + else $error("W beat lost."); + b_lost : assert property( @(posedge clk_i) + (mst_resp_i.b_valid & mst_req_o.b_ready |-> slv_resp_o.b_valid & slv_req_i.b_ready)) + else $error("B beat lost."); + ar_lost : assert property( @(posedge clk_i) + (slv_req_i.ar_valid & slv_resp_o.ar_ready |-> mst_req_o.ar_valid & mst_resp_i.ar_ready)) + else $error("AR beat lost."); + r_lost : assert property( @(posedge clk_i) + (mst_resp_i.r_valid & mst_req_o.r_ready |-> slv_resp_o.r_valid & slv_req_i.r_ready)) + else $error("R beat lost."); +`endif +// pragma translate_on +endmodule + +`include "axi/typedef.svh" +`include "axi/assign.svh" +/// Serialize all AXI transactions to a single ID (zero), interface version. +module axi_serializer_intf #( + /// AXI4+ATOP ID width. + parameter int unsigned AXI_ID_WIDTH = 32'd0, + /// AXI4+ATOP address width. + parameter int unsigned AXI_ADDR_WIDTH = 32'd0, + /// AXI4+ATOP data width. + parameter int unsigned AXI_DATA_WIDTH = 32'd0, + /// AXI4+ATOP user width. + parameter int unsigned AXI_USER_WIDTH = 32'd0, + /// Maximum number of in flight read transactions. + parameter int unsigned MAX_READ_TXNS = 32'd0, + /// Maximum number of in flight write transactions. + parameter int unsigned MAX_WRITE_TXNS = 32'd0 +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// AXI4+ATOP Slave modport + AXI_BUS.Slave slv, + /// AXI4+ATOP Master modport + AXI_BUS.Master mst +); + + typedef logic [AXI_ID_WIDTH -1:0] id_t; + typedef logic [AXI_ADDR_WIDTH -1:0] addr_t; + typedef logic [AXI_DATA_WIDTH -1:0] data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH -1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + req_t slv_req, mst_req; + resp_t slv_resp, mst_resp; + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_serializer #( + .MaxReadTxns ( MAX_READ_TXNS ), + .MaxWriteTxns ( MAX_WRITE_TXNS ), + .AxiIdWidth ( AXI_ID_WIDTH ), + .req_t ( req_t ), + .resp_t ( resp_t ) + ) i_axi_serializer ( + .clk_i, + .rst_ni, + .slv_req_i ( slv_req ), + .slv_resp_o ( slv_resp ), + .mst_req_o ( mst_req ), + .mst_resp_i ( mst_resp ) + ); + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (AXI_ADDR_WIDTH >= 1) else $fatal(1, "AXI address width must be at least 1!"); + assert (AXI_DATA_WIDTH >= 1) else $fatal(1, "AXI data width must be at least 1!"); + assert (AXI_ID_WIDTH >= 1) else $fatal(1, "AXI ID width must be at least 1!"); + assert (AXI_USER_WIDTH >= 1) else $fatal(1, "AXI user width must be at least 1!"); + assert (MAX_READ_TXNS >= 1) + else $fatal(1, "Maximum number of read transactions must be >= 1!"); + assert (MAX_WRITE_TXNS >= 1) + else $fatal(1, "Maximum number of write transactions must be >= 1!"); + end +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/axi/src/axi_xbar.sv b/hw/deps/axi/src/axi_xbar.sv new file mode 100644 index 0000000..5d0b79c --- /dev/null +++ b/hw/deps/axi/src/axi_xbar.sv @@ -0,0 +1,312 @@ +// Copyright (c) 2019 ETH Zurich and 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. + +// Author: Wolfgang Roenninger + +// axi_xbar: Fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports. +// See `doc/axi_xbar.md` for the documentation, including the definition of parameters and ports. +module axi_xbar #( + parameter axi_pkg::xbar_cfg_t Cfg = '0, + parameter type slv_aw_chan_t = logic, + parameter type mst_aw_chan_t = logic, + parameter type w_chan_t = logic, + parameter type slv_b_chan_t = logic, + parameter type mst_b_chan_t = logic, + parameter type slv_ar_chan_t = logic, + parameter type mst_ar_chan_t = logic, + parameter type slv_r_chan_t = logic, + parameter type mst_r_chan_t = logic, + parameter type slv_req_t = logic, + parameter type slv_resp_t = logic, + parameter type mst_req_t = logic, + parameter type mst_resp_t = logic, + parameter type rule_t = axi_pkg::xbar_rule_64_t +) ( + input logic clk_i, + input logic rst_ni, + input logic test_i, + input slv_req_t [Cfg.NoSlvPorts-1:0] slv_ports_req_i, + output slv_resp_t [Cfg.NoSlvPorts-1:0] slv_ports_resp_o, + output mst_req_t [Cfg.NoMstPorts-1:0] mst_ports_req_o, + input mst_resp_t [Cfg.NoMstPorts-1:0] mst_ports_resp_i, + input rule_t [Cfg.NoAddrRules-1:0] addr_map_i, + input logic [Cfg.NoSlvPorts-1:0] en_default_mst_port_i, + input logic [Cfg.NoSlvPorts-1:0][$clog2(Cfg.NoMstPorts)-1:0] default_mst_port_i +); + + typedef logic [Cfg.AxiAddrWidth-1:0] addr_t; + // to account for the decoding error slave + typedef logic [$clog2(Cfg.NoMstPorts + 1)-1:0] mst_port_idx_t; + + // signals from the axi_demuxes, one index more for decode error + slv_req_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_reqs; + slv_resp_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_resps; + + // signals into the axi_muxes, are of type slave as the multiplexer extends the ID + slv_req_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_reqs; + slv_resp_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_resps; + + for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_slv_port_demux + logic [$clog2(Cfg.NoMstPorts)-1:0] dec_aw, dec_ar; + mst_port_idx_t slv_aw_select, slv_ar_select; + logic dec_aw_valid, dec_aw_error; + logic dec_ar_valid, dec_ar_error; + + addr_decode #( + .NoIndices ( Cfg.NoMstPorts ), + .NoRules ( Cfg.NoAddrRules ), + .addr_t ( addr_t ), + .rule_t ( rule_t ) + ) i_axi_aw_decode ( + .addr_i ( slv_ports_req_i[i].aw.addr ), + .addr_map_i ( addr_map_i ), + .idx_o ( dec_aw ), + .dec_valid_o ( dec_aw_valid ), + .dec_error_o ( dec_aw_error ), + .en_default_idx_i ( en_default_mst_port_i[i] ), + .default_idx_i ( default_mst_port_i[i] ) + ); + + addr_decode #( + .NoIndices ( Cfg.NoMstPorts ), + .addr_t ( addr_t ), + .NoRules ( Cfg.NoAddrRules ), + .rule_t ( rule_t ) + ) i_axi_ar_decode ( + .addr_i ( slv_ports_req_i[i].ar.addr ), + .addr_map_i ( addr_map_i ), + .idx_o ( dec_ar ), + .dec_valid_o ( dec_ar_valid ), + .dec_error_o ( dec_ar_error ), + .en_default_idx_i ( en_default_mst_port_i[i] ), + .default_idx_i ( default_mst_port_i[i] ) + ); + + assign slv_aw_select = (dec_aw_error) ? + mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_aw); + assign slv_ar_select = (dec_ar_error) ? + mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_ar); + + // make sure that the default slave does not get changed, if there is an unserved Ax + // pragma translate_off + `ifndef VERILATOR + default disable iff (~rst_ni); + default_aw_mst_port_en: assert property( + @(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready) + |=> $stable(en_default_mst_port_i[i])) + else $fatal (1, $sformatf("It is not allowed to change the default mst port\ + enable, when there is an unserved Aw beat. Slave Port: %0d", i)); + default_aw_mst_port: assert property( + @(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready) + |=> $stable(default_mst_port_i[i])) + else $fatal (1, $sformatf("It is not allowed to change the default mst port\ + when there is an unserved Aw beat. Slave Port: %0d", i)); + default_ar_mst_port_en: assert property( + @(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready) + |=> $stable(en_default_mst_port_i[i])) + else $fatal (1, $sformatf("It is not allowed to change the enable, when\ + there is an unserved Ar beat. Slave Port: %0d", i)); + default_ar_mst_port: assert property( + @(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready) + |=> $stable(default_mst_port_i[i])) + else $fatal (1, $sformatf("It is not allowed to change the default mst port\ + when there is an unserved Ar beat. Slave Port: %0d", i)); + `endif + // pragma translate_on + axi_demux #( + .AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), // ID Width + .aw_chan_t ( slv_aw_chan_t ), // AW Channel Type + .w_chan_t ( w_chan_t ), // W Channel Type + .b_chan_t ( slv_b_chan_t ), // B Channel Type + .ar_chan_t ( slv_ar_chan_t ), // AR Channel Type + .r_chan_t ( slv_r_chan_t ), // R Channel Type + .req_t ( slv_req_t ), + .resp_t ( slv_resp_t ), + .NoMstPorts ( Cfg.NoMstPorts + 1 ), + .MaxTrans ( Cfg.MaxMstTrans ), + .AxiLookBits ( Cfg.AxiIdUsedSlvPorts ), + .FallThrough ( Cfg.FallThrough ), + .SpillAw ( Cfg.LatencyMode[9] ), + .SpillW ( Cfg.LatencyMode[8] ), + .SpillB ( Cfg.LatencyMode[7] ), + .SpillAr ( Cfg.LatencyMode[6] ), + .SpillR ( Cfg.LatencyMode[5] ) + ) i_axi_demux ( + .clk_i, // Clock + .rst_ni, // Asynchronous reset active low + .test_i, // Testmode enable + .slv_req_i ( slv_ports_req_i[i] ), + .slv_aw_select_i ( slv_aw_select ), + .slv_ar_select_i ( slv_ar_select ), + .slv_resp_o ( slv_ports_resp_o[i] ), + .mst_reqs_o ( slv_reqs[i] ), + .mst_resps_i ( slv_resps[i] ) + ); + + axi_err_slv #( + .AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), + .req_t ( slv_req_t ), + .resp_t ( slv_resp_t ), + .Resp ( axi_pkg::RESP_DECERR ), + .ATOPs ( 1'b1 ), + .MaxTrans ( 4 ) // Transactions terminate at this slave, so minimize + // resource consumption by accepting only a few + // transactions at a time. + ) i_axi_err_slv ( + .clk_i, // Clock + .rst_ni, // Asynchronous reset active low + .test_i, // Testmode enable + // slave port + .slv_req_i ( slv_reqs[i][Cfg.NoMstPorts] ), + .slv_resp_o ( slv_resps[i][Cfg.NoMstPorts] ) + ); + end + + // cross all channels + for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_xbar_slv_cross + for (genvar j = 0; j < Cfg.NoMstPorts; j++) begin : gen_xbar_mst_cross + assign mst_reqs[j][i] = slv_reqs[i][j]; + assign slv_resps[i][j] = mst_resps[j][i]; + end + end + + for (genvar i = 0; i < Cfg.NoMstPorts; i++) begin : gen_mst_port_mux + axi_mux #( + .SlvAxiIDWidth ( Cfg.AxiIdWidthSlvPorts ), // ID width of the slave ports + .slv_aw_chan_t ( slv_aw_chan_t ), // AW Channel Type, slave ports + .mst_aw_chan_t ( mst_aw_chan_t ), // AW Channel Type, master port + .w_chan_t ( w_chan_t ), // W Channel Type, all ports + .slv_b_chan_t ( slv_b_chan_t ), // B Channel Type, slave ports + .mst_b_chan_t ( mst_b_chan_t ), // B Channel Type, master port + .slv_ar_chan_t ( slv_ar_chan_t ), // AR Channel Type, slave ports + .mst_ar_chan_t ( mst_ar_chan_t ), // AR Channel Type, master port + .slv_r_chan_t ( slv_r_chan_t ), // R Channel Type, slave ports + .mst_r_chan_t ( mst_r_chan_t ), // R Channel Type, master port + .slv_req_t ( slv_req_t ), + .slv_resp_t ( slv_resp_t ), + .mst_req_t ( mst_req_t ), + .mst_resp_t ( mst_resp_t ), + .NoSlvPorts ( Cfg.NoSlvPorts ), // Number of Masters for the module + .MaxWTrans ( Cfg.MaxSlvTrans ), + .FallThrough ( Cfg.FallThrough ), + .SpillAw ( Cfg.LatencyMode[4] ), + .SpillW ( Cfg.LatencyMode[3] ), + .SpillB ( Cfg.LatencyMode[2] ), + .SpillAr ( Cfg.LatencyMode[1] ), + .SpillR ( Cfg.LatencyMode[0] ) + ) i_axi_mux ( + .clk_i, // Clock + .rst_ni, // Asynchronous reset active low + .test_i, // Test Mode enable + .slv_reqs_i ( mst_reqs[i] ), + .slv_resps_o ( mst_resps[i] ), + .mst_req_o ( mst_ports_req_o[i] ), + .mst_resp_i ( mst_ports_resp_i[i] ) + ); + end + + // pragma translate_off + `ifndef VERILATOR + initial begin : check_params + id_slv_req_ports: assert ($bits(slv_ports_req_i[0].aw.id ) == Cfg.AxiIdWidthSlvPorts) else + $fatal(1, $sformatf("Slv_req and aw_chan id width not equal.")); + id_slv_resp_ports: assert ($bits(slv_ports_resp_o[0].r.id) == Cfg.AxiIdWidthSlvPorts) else + $fatal(1, $sformatf("Slv_req and aw_chan id width not equal.")); + end + `endif + // pragma translate_on +endmodule + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module axi_xbar_intf #( + parameter int unsigned AXI_USER_WIDTH = 0, + parameter axi_pkg::xbar_cfg_t Cfg = '0, + parameter type rule_t = axi_pkg::xbar_rule_64_t +) ( + input logic clk_i, + input logic rst_ni, + input logic test_i, + AXI_BUS.Slave slv_ports [Cfg.NoSlvPorts-1:0], + AXI_BUS.Master mst_ports [Cfg.NoMstPorts-1:0], + input rule_t [Cfg.NoAddrRules-1:0] addr_map_i, + input logic [Cfg.NoSlvPorts-1:0] en_default_mst_port_i, + input logic [Cfg.NoSlvPorts-1:0][$clog2(Cfg.NoMstPorts)-1:0] default_mst_port_i +); + + localparam int unsigned AxiIdWidthMstPorts = Cfg.AxiIdWidthSlvPorts + $clog2(Cfg.NoSlvPorts); + + typedef logic [AxiIdWidthMstPorts -1:0] id_mst_t; + typedef logic [Cfg.AxiIdWidthSlvPorts -1:0] id_slv_t; + typedef logic [Cfg.AxiAddrWidth -1:0] addr_t; + typedef logic [Cfg.AxiDataWidth -1:0] data_t; + typedef logic [Cfg.AxiDataWidth/8 -1:0] strb_t; + typedef logic [AXI_USER_WIDTH -1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(mst_aw_chan_t, addr_t, id_mst_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(slv_aw_chan_t, addr_t, id_slv_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(mst_b_chan_t, id_mst_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(slv_b_chan_t, id_slv_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(mst_ar_chan_t, addr_t, id_mst_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(slv_ar_chan_t, addr_t, id_slv_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(mst_r_chan_t, data_t, id_mst_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(slv_r_chan_t, data_t, id_slv_t, user_t) + `AXI_TYPEDEF_REQ_T(mst_req_t, mst_aw_chan_t, w_chan_t, mst_ar_chan_t) + `AXI_TYPEDEF_REQ_T(slv_req_t, slv_aw_chan_t, w_chan_t, slv_ar_chan_t) + `AXI_TYPEDEF_RESP_T(mst_resp_t, mst_b_chan_t, mst_r_chan_t) + `AXI_TYPEDEF_RESP_T(slv_resp_t, slv_b_chan_t, slv_r_chan_t) + + mst_req_t [Cfg.NoMstPorts-1:0] mst_reqs; + mst_resp_t [Cfg.NoMstPorts-1:0] mst_resps; + slv_req_t [Cfg.NoSlvPorts-1:0] slv_reqs; + slv_resp_t [Cfg.NoSlvPorts-1:0] slv_resps; + + for (genvar i = 0; i < Cfg.NoMstPorts; i++) begin : gen_assign_mst + `AXI_ASSIGN_FROM_REQ(mst_ports[i], mst_reqs[i]) + `AXI_ASSIGN_TO_RESP(mst_resps[i], mst_ports[i]) + end + + for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_assign_slv + `AXI_ASSIGN_TO_REQ(slv_reqs[i], slv_ports[i]) + `AXI_ASSIGN_FROM_RESP(slv_ports[i], slv_resps[i]) + end + + axi_xbar #( + .Cfg (Cfg), + .slv_aw_chan_t ( slv_aw_chan_t ), + .mst_aw_chan_t ( mst_aw_chan_t ), + .w_chan_t ( w_chan_t ), + .slv_b_chan_t ( slv_b_chan_t ), + .mst_b_chan_t ( mst_b_chan_t ), + .slv_ar_chan_t ( slv_ar_chan_t ), + .mst_ar_chan_t ( mst_ar_chan_t ), + .slv_r_chan_t ( slv_r_chan_t ), + .mst_r_chan_t ( mst_r_chan_t ), + .slv_req_t ( slv_req_t ), + .slv_resp_t ( slv_resp_t ), + .mst_req_t ( mst_req_t ), + .mst_resp_t ( mst_resp_t ), + .rule_t ( rule_t ) + ) i_xbar ( + .clk_i, + .rst_ni, + .test_i, + .slv_ports_req_i (slv_reqs ), + .slv_ports_resp_o (slv_resps), + .mst_ports_req_o (mst_reqs ), + .mst_ports_resp_i (mst_resps), + .addr_map_i, + .en_default_mst_port_i, + .default_mst_port_i + ); + +endmodule diff --git a/hw/deps/axi/src/dma/axi_dma_backend.sv b/hw/deps/axi/src/dma/axi_dma_backend.sv new file mode 100644 index 0000000..1c072d9 --- /dev/null +++ b/hw/deps/axi/src/dma/axi_dma_backend.sv @@ -0,0 +1,588 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// The backend implements the generic 1D data transfer on an AXI BUS +module axi_dma_backend #( + /// Data width of the AXI bus + parameter int unsigned DataWidth = -1, + /// Address width of the AXI bus + parameter int unsigned AddrWidth = -1, + /// ID width of the AXI bus + parameter int unsigned IdWidth = -1, + /// Number of AX beats that can be in-flight + parameter int unsigned AxReqFifoDepth = -1, + /// Number of generic 1D requests that can be buffered + parameter int unsigned TransFifoDepth = -1, + /// Number of elements the realignment buffer can hold. To achieve + /// full performance a depth of 3 is minimally required. + parameter int unsigned BufferDepth = -1, + /// AXI4+ATOP request struct definition. + parameter type axi_req_t = logic, + /// AXI4+ATOP response struct definition. + parameter type axi_res_t = logic, + /// Arbitrary 1D burst request definition: + /// - `id`: the AXI id used - this id should be constant, as the DMA does not support reordering + /// - `src`, `dst`: source and destination address, same width as the AXI 4 channels + /// - `num_bytes`: the length of the contiguous 1D transfer requested, can be up to 32/64 bit long + /// num_bytes will be interpreted as an unsigned number + /// A value of 0 will cause the backend to discard the transfer prematurely + /// - `src_cache`, `dst_cache`: the configuration of the cache fields in the AX beats + /// - `src_burst`, `dst_burst`: currently only incremental bursts are supported (`2'b01`) + /// - `decouple_rw`: if set to true, there is no longer exactly one AXI write_request issued for + /// every read request. This mode can improve performance of unaligned transfers when crossing + /// the AXI page boundaries. + /// - `deburst`: if set, the DMA will split all bursts in single transfers + /// - `serialize`: if set, the DMA will only send AX belonging to a given Arbitrary 1D burst request + /// at a time. This is default behavior to prevent deadlocks. + parameter type burst_req_t = logic, + /// Give each DMA backend a unique id + parameter int unsigned DmaIdWidth = -1, + /// Enable or disable tracing + parameter bit DmaTracing = 0 + +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// AXI4+ATOP master request + output axi_req_t axi_dma_req_o, + /// AXI4+ATOP master response + input axi_res_t axi_dma_res_i, + /// Arbitrary 1D burst request + input burst_req_t burst_req_i, + /// Handshake: 1D burst request is valid + input logic valid_i, + /// Handshake: 1D burst can be accepted + output logic ready_o, + /// High if the backend is idle + output logic backend_idle_o, + /// Event: a 1D burst request has completed + output logic trans_complete_o, + /// unique DMA id + input logic [DmaIdWidth-1:0] dma_id_i +); + + /// Number of bytes per word + localparam int unsigned StrobeWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrobeWidth); + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Address Type + typedef logic [ AddrWidth-1:0] addr_t; + /// AXI ID Type + typedef logic [ IdWidth-1:0] axi_id_t; + + /// id: AXI id + /// last: last transaction in burst + /// address: address of burst + /// length: burst length + /// size: bytes in each burst + /// burst: burst type; only INC supported + /// cache: cache type + typedef struct packed { + axi_id_t id; + logic last; + addr_t addr; + axi_pkg::len_t len; + axi_pkg::size_t size; + axi_pkg::burst_t burst; + axi_pkg::cache_t cache; + } desc_ax_t; + + /// offset: initial misalignment + /// tailer: final misalignment + /// shift: amount the data needs to be shifted to realign it + typedef struct packed { + offset_t offset; + offset_t tailer; + offset_t shift; + } desc_r_t; + + /// offset: initial misalignment + /// tailer: final misalignment + /// num_beats: number of beats in the burst + /// is_single: burst length is 0 + typedef struct packed { + offset_t offset; + offset_t tailer; + axi_pkg::len_t num_beats; + logic is_single; + } desc_w_t; + + /// Write request definition + typedef struct packed { + desc_ax_t aw; + desc_w_t w; + } write_req_t; + + /// Read request definition + typedef struct packed { + desc_ax_t ar; + desc_r_t r; + } read_req_t; + + //-------------------------------------- + // Assertions + //-------------------------------------- + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (DataWidth inside {16, 32, 64, 128, 256, 512, 1024}) + else $fatal(1, "16 <= DataWidth <= 1024"); + assert (AddrWidth >= 32 & AddrWidth <= 128) /* this is outside AXI4 specs -> be careful! */ + else $fatal(1, " 32 <= AddrWidth <= 128"); + end + `endif + // pragma translate_on + + //-------------------------------------- + // Request Fifo + //-------------------------------------- + burst_req_t burst_req; + logic burst_req_empty; + logic burst_req_pop; + logic burst_req_full; + + // buffer the input requests in a fifo + fifo_v3 #( + .dtype ( burst_req_t ), + .DEPTH ( TransFifoDepth ) + ) i_burst_request_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( 1'b0 ), + .full_o ( burst_req_full ), + .empty_o ( burst_req_empty ), + .usage_o ( ), + .data_i ( burst_req_i ), + .push_i ( valid_i && ready_o ), + .data_o ( burst_req ), + .pop_i ( burst_req_pop ) + ); + + assign ready_o = !burst_req_full; + + //-------------------------------------- + // Burst reshaper + //-------------------------------------- + write_req_t write_req; + read_req_t read_req; + + logic read_req_valid; + logic read_req_ready; + logic write_req_valid; + logic write_req_ready; + + // send the next burst either immediately or once the last burst + // has been completed. The former mode is not AXI4+ATOP spec + // conform and may result in deadlocks! + logic in_flight_d, in_flight_q; + logic burst_valid; + always_comb begin : proc_select_burst_valid + if (burst_req.serialize) begin + // AXI4-conform behavior. As both the buffer and the memory system + // assume in-order operation. + burst_valid = ~burst_req_empty & (~in_flight_q | trans_complete_o); + end else begin + // legacy, non-AXI4-conform behavior. Send as many AX as possible + // This can lead to deadlocks due to in-memory reordering + burst_valid = ~burst_req_empty; + end + end + + // transforms arbitrary burst into AXI conform bursts + axi_dma_burst_reshaper #( + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .IdWidth ( IdWidth ), + .burst_req_t ( burst_req_t ), + .read_req_t ( read_req_t ), + .write_req_t ( write_req_t ) + ) i_axi_dma_burst_reshaper ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .burst_req_i ( burst_req ), + .valid_i ( burst_valid ), + .ready_o ( burst_req_pop ), + .write_req_o ( write_req ), + .read_req_o ( read_req ), + .r_valid_o ( read_req_valid ), + .r_ready_i ( read_req_ready ), + .w_valid_o ( write_req_valid ), + .w_ready_i ( write_req_ready ) + ); + + //-------------------------------------- + // Data mover + //-------------------------------------- + axi_dma_data_mover #( + .DataWidth ( DataWidth ), + .ReqFifoDepth ( AxReqFifoDepth ), + .BufferDepth ( BufferDepth ), + .read_req_t ( read_req_t ), + .write_req_t ( write_req_t ), + .axi_req_t ( axi_req_t ), + .axi_res_t ( axi_res_t ), + .desc_ax_t ( desc_ax_t ), + .desc_r_t ( desc_r_t ), + .desc_w_t ( desc_w_t ) + ) i_axi_dma_data_mover ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .axi_dma_req_o ( axi_dma_req_o ), + .axi_dma_res_i ( axi_dma_res_i ), + .read_req_i ( read_req ), + .write_req_i ( write_req ), + .r_valid_i ( read_req_valid ), + .r_ready_o ( read_req_ready ), + .w_valid_i ( write_req_valid ), + .w_ready_o ( write_req_ready ), + .data_mover_idle_o ( backend_idle_o ), + .trans_complete_o ( trans_complete_o ) + ); + + //-------------------------------------- + // In-flight check + //-------------------------------------- + // to conform to the AXI4+ATOP spec: only send a burst + // once the last one has been completed . This check can be overridden + always_comb begin : proc_in_flight_check + + // default: last state + in_flight_d = in_flight_q; + + // new transfer: set in-flight to one + if (burst_req_pop & ~burst_req_empty) begin + in_flight_d = 1; + end else begin + // no new transfer and the old retires -> idle + if (trans_complete_o) begin + in_flight_d = 0; + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_in_flight_check_state + if(~rst_ni) begin + in_flight_q <= 0; + end else begin + in_flight_q <= in_flight_d; + end + end + + //-------------------------------------- + // Tracer + //-------------------------------------- + //pragma translate_off + `ifndef SYNTHESYS + `ifndef VERILATOR + generate if (DmaTracing) begin : gen_dma_tracer + string fn; + integer f; + + logic [DataWidth/8-1:0][BufferDepth-1:0][7:0] buffer_mem; + + // open file + initial begin + #1; + $sformat(fn, "dma_trace_%05x.log", dma_id_i); + f = $fopen(fn, "w"); + $display("[Tracer] Logging DMA %d to %s", dma_id_i, fn); + end + + // access buffer memory storage + for(genvar d = 0; d < BufferDepth; d++) begin + for(genvar i = 0; i < DataWidth/8-1; i++) begin + assign buffer_mem[i][d] = + i_axi_dma_data_mover.i_axi_dma_data_path.fifo_buffer[i].i_fifo_buffer.mem_q[d]; + end + end + + // do the tracing + always_ff @(posedge clk_i) begin : proc_tracer + // dict + automatic longint dma_meta [string]; + automatic longint dma_backend [string]; + automatic longint dma_burst_res [string]; + automatic longint dma_data_mover [string]; + automatic logic [DataWidth-1:0] dma_data_path [string]; + automatic string dma_string; + + // start of python dict + dma_string = "{"; + + // we do not dump while reset + if (rst_ni) begin + + // commented signals are currently not used by the python golden model :) + + //-------------------------------------- + // Metadata + //-------------------------------------- + dma_meta = '{ + // time + "time" : $time(), + "DataWidth" : DataWidth, + "AddrWidth" : AddrWidth, + "IdWidth" : IdWidth, + "AxReqFifoDepth" : AxReqFifoDepth, + "TransFifoDepth" : TransFifoDepth, + "BufferDepth" : BufferDepth + }; + + //-------------------------------------- + // Backend + //-------------------------------------- + dma_backend = '{ + // dma backend interface + "backend_burst_req_id" : burst_req_i.id, + "backend_burst_req_src" : burst_req_i.src, + "backend_burst_req_dst" : burst_req_i.dst, + "backend_burst_req_num_bytes" : burst_req_i.num_bytes, + // "backend_burst_req_cache_src" : burst_req_i.cache_src, + // "backend_burst_req_cache_dst" : burst_req_i.cache_dst, + // "backend_burst_req_burst_src" : burst_req_i.burst_src, + // "backend_burst_req_burst_dst" : burst_req_i.burst_dst, + "backend_burst_req_burst_decouple_rw" : burst_req_i.decouple_rw, + "backend_burst_req_burst_deburst" : burst_req_i.deburst, + "backend_burst_req_valid" : valid_i, + "backend_burst_req_ready" : ready_o, + "backend_idle" : backend_idle_o, + "transfer_completed" : trans_complete_o + }; + + //-------------------------------------- + // Burst Reshaper + //-------------------------------------- + dma_burst_res = '{ + // burst request + "burst_reshaper_burst_req_id" : i_axi_dma_burst_reshaper.burst_req_i.id, + "burst_reshaper_burst_req_src" : i_axi_dma_burst_reshaper.burst_req_i.src, + "burst_reshaper_burst_req_dst" : i_axi_dma_burst_reshaper.burst_req_i.dst, + "burst_reshaper_burst_req_num_bytes" : i_axi_dma_burst_reshaper.burst_req_i.num_bytes, + // "burst_reshaper_burst_req_cache_src" : i_axi_dma_burst_reshaper.burst_req_i.cache_src, + // "burst_reshaper_burst_req_cache_dst" : i_axi_dma_burst_reshaper.burst_req_i.cache_dst, + // "burst_reshaper_burst_req_burst_src" : i_axi_dma_burst_reshaper.burst_req_i.burst_src, + // "burst_reshaper_burst_req_burst_dst" : i_axi_dma_burst_reshaper.burst_req_i.burst_dst, + "burst_reshaper_burst_req_decouple_rw" : i_axi_dma_burst_reshaper.burst_req_i.decouple_rw, + "burst_reshaper_burst_req_deburst" : i_axi_dma_burst_reshaper.burst_req_i.deburst, + "burst_reshaper_burst_req_valid" : i_axi_dma_burst_reshaper.valid_i, + "burst_reshaper_burst_req_ready" : i_axi_dma_burst_reshaper.ready_o, + // write request + "burst_reshaper_write_req_aw_id" : i_axi_dma_burst_reshaper.write_req_o.aw.id, + "burst_reshaper_write_req_aw_last" : i_axi_dma_burst_reshaper.write_req_o.aw.last, + "burst_reshaper_write_req_aw_addr" : i_axi_dma_burst_reshaper.write_req_o.aw.addr, + "burst_reshaper_write_req_aw_len" : i_axi_dma_burst_reshaper.write_req_o.aw.len, + "burst_reshaper_write_req_aw_size" : i_axi_dma_burst_reshaper.write_req_o.aw.size, + "burst_reshaper_write_req_aw_burst" : i_axi_dma_burst_reshaper.write_req_o.aw.burst, + "burst_reshaper_write_req_aw_cache" : i_axi_dma_burst_reshaper.write_req_o.aw.cache, + "burst_reshaper_write_req_w_offset" : i_axi_dma_burst_reshaper.write_req_o.w.offset, + "burst_reshaper_write_req_w_tailer" : i_axi_dma_burst_reshaper.write_req_o.w.tailer, + "burst_reshaper_write_req_w_num_beats" : i_axi_dma_burst_reshaper.write_req_o.w.num_beats, + // "burst_reshaper_write_req_w_is_single" : i_axi_dma_burst_reshaper.write_req_o.w.is_single, + "burst_reshaper_write_req_valid" : i_axi_dma_burst_reshaper.w_valid_o, + "burst_reshaper_write_req_ready" : i_axi_dma_burst_reshaper.w_ready_i, + // read request + "burst_reshaper_read_req_ar_id" : i_axi_dma_burst_reshaper.read_req_o.ar.id, + "burst_reshaper_read_req_ar_last" : i_axi_dma_burst_reshaper.read_req_o.ar.last, + "burst_reshaper_read_req_ar_addr" : i_axi_dma_burst_reshaper.read_req_o.ar.addr, + "burst_reshaper_read_req_ar_len" : i_axi_dma_burst_reshaper.read_req_o.ar.len, + "burst_reshaper_read_req_ar_size" : i_axi_dma_burst_reshaper.read_req_o.ar.size, + "burst_reshaper_read_req_ar_burst" : i_axi_dma_burst_reshaper.read_req_o.ar.burst, + "burst_reshaper_read_req_ar_cache" : i_axi_dma_burst_reshaper.read_req_o.ar.cache, + "burst_reshaper_read_req_r_offset" : i_axi_dma_burst_reshaper.read_req_o.r.offset, + "burst_reshaper_read_req_r_tailer" : i_axi_dma_burst_reshaper.read_req_o.r.tailer, + "burst_reshaper_read_req_r_shift" : i_axi_dma_burst_reshaper.read_req_o.r.shift, + "burst_reshaper_read_req_valid" : i_axi_dma_burst_reshaper.r_valid_o, + "burst_reshaper_read_req_ready" : i_axi_dma_burst_reshaper.r_ready_i// , + // current burst + // "burst_reshaper_burst_src_id" : i_axi_dma_burst_reshaper.burst_q.src.id, + // "burst_reshaper_burst_src_addr" : i_axi_dma_burst_reshaper.burst_q.src.addr, + // "burst_reshaper_burst_src_num_bytes" : i_axi_dma_burst_reshaper.burst_q.src.num_bytes, + // "burst_reshaper_burst_src_cache" : i_axi_dma_burst_reshaper.burst_q.src.cache, + // "burst_reshaper_burst_src_burst" : i_axi_dma_burst_reshaper.burst_q.src.burst, + // "burst_reshaper_burst_src_valid" : i_axi_dma_burst_reshaper.burst_q.src.valid, + // "burst_reshaper_burst_dst_id" : i_axi_dma_burst_reshaper.burst_q.dst.id, + // "burst_reshaper_burst_dst_addr" : i_axi_dma_burst_reshaper.burst_q.dst.addr, + // "burst_reshaper_burst_dst_num_bytes" : i_axi_dma_burst_reshaper.burst_q.dst.num_bytes, + // "burst_reshaper_burst_dst_cache" : i_axi_dma_burst_reshaper.burst_q.dst.cache, + // "burst_reshaper_burst_dst_burst" : i_axi_dma_burst_reshaper.burst_q.dst.burst, + // "burst_reshaper_burst_dst_valid" : i_axi_dma_burst_reshaper.burst_q.dst.valid, + // "burst_reshaper_burst_shift" : i_axi_dma_burst_reshaper.burst_q.shift, + // "burst_reshaper_burst_decouple_rw" : i_axi_dma_burst_reshaper.burst_q.decouple_rw, + // "burst_reshaper_burst_deburst" : i_axi_dma_burst_reshaper.burst_q.deburst, + // page + // "burst_reshaper_r_page_offset" : i_axi_dma_burst_reshaper.r_page_offset, + // "burst_reshaper_r_num_bytes_to_pb" : i_axi_dma_burst_reshaper.r_num_bytes_to_pb, + // "burst_reshaper_w_page_offset" : i_axi_dma_burst_reshaper.w_page_offset, + // "burst_reshaper_w_num_bytes_to_pb" : i_axi_dma_burst_reshaper.w_num_bytes_to_pb, + // "burst_reshaper_c_num_bytes_to_pb" : i_axi_dma_burst_reshaper.c_num_bytes_to_pb, + // issue process + // "burst_reshaper_r_num_bytes_possible" : i_axi_dma_burst_reshaper.r_num_bytes_possible, + // "burst_reshaper_r_num_bytes" : i_axi_dma_burst_reshaper.r_num_bytes, + // "burst_reshaper_r_finish" : i_axi_dma_burst_reshaper.r_finish, + // "burst_reshaper_r_addr_offset" : i_axi_dma_burst_reshaper.r_addr_offset, + // "burst_reshaper_w_num_bytes_possible" : i_axi_dma_burst_reshaper.w_num_bytes_possible, + // "burst_reshaper_w_num_bytes" : i_axi_dma_burst_reshaper.w_num_bytes, + // "burst_reshaper_w_finish" : i_axi_dma_burst_reshaper.w_finish, + // "burst_reshaper_w_addr_offset" : i_axi_dma_burst_reshaper.w_addr_offset + }; + + //-------------------------------------- + // Data Mover + //-------------------------------------- + dma_data_mover = '{ + // AR emitter + // "data_mover_ar_emitter_full" : i_axi_dma_data_mover.ar_emitter_full, + // "data_mover_ar_emitter_empty" : i_axi_dma_data_mover.ar_emitter_empty, + // "data_mover_ar_emitter_push" : i_axi_dma_data_mover.ar_emitter_push, + // "data_mover_ar_emitter_pop" : i_axi_dma_data_mover.ar_emitter_pop, + // AW emitter + // "data_mover_aw_emitter_full" : i_axi_dma_data_mover.aw_emitter_full, + // "data_mover_aw_emitter_empty" : i_axi_dma_data_mover.aw_emitter_empty, + // "data_mover_aw_emitter_push" : i_axi_dma_data_mover.aw_emitter_push, + // "data_mover_aw_emitter_pop" : i_axi_dma_data_mover.aw_emitter_pop, + // "data_mover_is_last_aw" : i_axi_dma_data_mover.is_last_aw, + // R emitter + // "data_mover_r_emitter_full" : i_axi_dma_data_mover.r_emitter_full, + // "data_mover_r_emitter_empty" : i_axi_dma_data_mover.r_emitter_empty, + // "data_mover_r_emitter_push" : i_axi_dma_data_mover.r_emitter_push, + // "data_mover_r_emitter_pop" : i_axi_dma_data_mover.r_emitter_pop, + // W emitter + // "data_mover_w_emitter_full" : i_axi_dma_data_mover.w_emitter_full, + // "data_mover_w_emitter_empty" : i_axi_dma_data_mover.w_emitter_empty, + // "data_mover_w_emitter_push" : i_axi_dma_data_mover.w_emitter_push, + // "data_mover_w_emitter_pop" : i_axi_dma_data_mover.w_emitter_pop, + // AW AXI signals + // "axi_dma_bus_aw_id" : i_axi_dma_data_mover.axi_dma_req_o.aw.id, + // "axi_dma_bus_aw_addr" : i_axi_dma_data_mover.axi_dma_req_o.aw.addr, + "axi_dma_bus_aw_len" : i_axi_dma_data_mover.axi_dma_req_o.aw.len, + "axi_dma_bus_aw_size" : i_axi_dma_data_mover.axi_dma_req_o.aw.size, + // "axi_dma_bus_aw_burst" : i_axi_dma_data_mover.axi_dma_req_o.aw.burst, + // "axi_dma_bus_aw_cache" : i_axi_dma_data_mover.axi_dma_req_o.aw.cache, + "axi_dma_bus_aw_valid" : i_axi_dma_data_mover.axi_dma_req_o.aw_valid, + "axi_dma_bus_aw_ready" : i_axi_dma_data_mover.axi_dma_res_i.aw_ready, + // B AXI signals + "axi_dma_bus_b_ready" : i_axi_dma_data_mover.axi_dma_req_o.b_ready, + "axi_dma_bus_b_valid" : i_axi_dma_data_mover.axi_dma_res_i.b_valid, + // AR AXI signals + // "axi_dma_bus_ar_id" : i_axi_dma_data_mover.axi_dma_req_o.ar.id, + // "axi_dma_bus_ar_addr" : i_axi_dma_data_mover.axi_dma_req_o.ar.addr, + "axi_dma_bus_ar_len" : i_axi_dma_data_mover.axi_dma_req_o.ar.len, + "axi_dma_bus_ar_size" : i_axi_dma_data_mover.axi_dma_req_o.ar.size, + // "axi_dma_bus_ar_burst" : i_axi_dma_data_mover.axi_dma_req_o.ar.burst, + // "axi_dma_bus_ar_cache" : i_axi_dma_data_mover.axi_dma_req_o.ar.cache, + "axi_dma_bus_ar_valid" : i_axi_dma_data_mover.axi_dma_req_o.ar_valid, + "axi_dma_bus_ar_ready" : i_axi_dma_data_mover.axi_dma_res_i.ar_ready + }; + + //-------------------------------------- + // Data Path + //-------------------------------------- + dma_data_path = '{ + // r channel + "data_path_r_dp_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.r_dp_valid_i, + "data_path_r_dp_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.r_dp_ready_o, + "data_path_r_tailer_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_tailer_i, + "data_path_r_offset_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_offset_i, + "data_path_r_shift_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_shift_i, + "axi_dma_bus_r_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.r_valid_i, + // "axi_dma_bus_r_data" : i_axi_dma_data_mover.i_axi_dma_data_path.r_data_i, + // "axi_dma_bus_r_last" : i_axi_dma_data_mover.i_axi_dma_data_path.r_last_i, + // "axi_dma_bus_r_resp" : i_axi_dma_data_mover.i_axi_dma_data_path.r_resp_i, + "axi_dma_bus_r_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.r_ready_o, + // w channel + "data_path_w_dp_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_dp_valid_i, + "data_path_w_dp_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.w_dp_ready_o, + "data_path_w_tailer_i" : i_axi_dma_data_mover.i_axi_dma_data_path.w_tailer_i, + "data_path_w_offset_i" : i_axi_dma_data_mover.i_axi_dma_data_path.w_offset_i, + "data_path_w_num_beats" : i_axi_dma_data_mover.i_axi_dma_data_path.w_num_beats_i, + "data_path_w_is_single" : i_axi_dma_data_mover.i_axi_dma_data_path.w_is_single_i, + "axi_dma_bus_w_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_valid_o, + // "axi_dma_bus_w_data" : i_axi_dma_data_mover.i_axi_dma_data_path.w_data_o, + "axi_dma_bus_w_strb" : i_axi_dma_data_mover.i_axi_dma_data_path.w_strb_o, + // "axi_dma_bus_w_last" : i_axi_dma_data_mover.i_axi_dma_data_path.w_last_o, + "axi_dma_bus_w_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.w_ready_i, + // mask pre-calculation + "data_path_r_first_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.r_first_mask, + "data_path_r_last_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.r_last_mask, + "data_path_w_first_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.w_first_mask, + "data_path_w_last_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.w_last_mask, + // barrel shifter + // "data_path_buffer_in" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_in, + "data_path_read_aligned_in_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.read_aligned_in_mask, + "data_path_write_aligned_in_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.in_mask, + // in mask generation + // "data_path_is_first_r" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r, + // "data_path_is_first_r_d" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r_d, + // "data_path_is_first_r_d" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r_d, + // read control + // "data_path_buffer_full" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_full, + // "data_path_buffer_push" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_push, + // "data_path_full" : i_axi_dma_data_mover.i_axi_dma_data_path.full, + "data_path_push" : i_axi_dma_data_mover.i_axi_dma_data_path.push, + // out mask generation + "data_path_out_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.out_mask, + // "data_path_is_first_w" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_w, + // "data_path_is_last_w" : i_axi_dma_data_mover.i_axi_dma_data_path.is_last_w, + // write control + // "data_path_buffer_out" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_out, + // "data_path_buffer_empty" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_empty, + // "data_path_buffer_pop" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_pop, + // "data_path_w_num_beats" : i_axi_dma_data_mover.i_axi_dma_data_path.w_num_beats_q, + // "data_path_w_cnt_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_cnt_valid_q, + "data_path_pop" : i_axi_dma_data_mover.i_axi_dma_data_path.pop// , + // "data_path_write_happening" : i_axi_dma_data_mover.i_axi_dma_data_path.write_happening, + // "data_path_ready_to_write" : i_axi_dma_data_mover.i_axi_dma_data_path.ready_to_write, + // "data_path_first_possible" : i_axi_dma_data_mover.i_axi_dma_data_path.first_possible, + // "data_path_buffer_clean" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_clean + }; + + // write dicts to string + foreach(dma_meta[key]) dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_meta[key]); + // only write bulk of data if dma is actually active :) + if (!backend_idle_o | valid_i & ready_o | i_axi_dma_burst_reshaper.valid_i & i_axi_dma_burst_reshaper.ready_o | + i_axi_dma_burst_reshaper.burst_q.src.valid | i_axi_dma_burst_reshaper.burst_q.dst.valid | trans_complete_o) begin + foreach(dma_backend[key]) dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_backend[key]); + foreach(dma_burst_res[key]) dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_burst_res[key]); + foreach(dma_data_mover[key]) dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_data_mover[key]); + foreach(dma_data_path[key]) dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_data_path[key]); + + //-------------------------------------- + // Realign Buffer Data Store + //-------------------------------------- + // for(int d = 0; d < BUFFER_DEPTH; d++) begin + // for(int i = 0; i < DATA_WIDTH/8; i++) begin + // dma_string = $sformatf("%s'buffer_mem_%0d_level_%0d': 0x%0x, ", + // dma_string, i, d, buffer_mem[i][d] + // ); + // end + // end + end + dma_string = $sformatf("%s}", dma_string); + $fwrite(f, dma_string); + $fwrite(f, "\n"); + end + end + // close the file + final begin + $fclose(f); + end + end + endgenerate + `endif + `endif + //pragma translate_on +endmodule : axi_dma_backend diff --git a/hw/deps/axi/src/dma/axi_dma_burst_reshaper.sv b/hw/deps/axi/src/dma/axi_dma_burst_reshaper.sv new file mode 100644 index 0000000..c456984 --- /dev/null +++ b/hw/deps/axi/src/dma/axi_dma_burst_reshaper.sv @@ -0,0 +1,357 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// Splits a generic 1D transfer in AXI-conform transfers +module axi_dma_burst_reshaper #( + /// Data width of the AXI bus + parameter int unsigned DataWidth = -1, + /// Address width of the AXI bus + parameter int unsigned AddrWidth = -1, + /// ID width of the AXI bus + parameter int unsigned IdWidth = -1, + /// Arbitrary 1D burst request definition: + /// - id: the AXI id used - this id should be constant, as the DMA does not support reordering + /// - src, dst: source and destination address, same width as the AXI 4 interface + /// - num_bytes: the length of the contiguous 1D transfer requested, can be up to 32/64 bit long + /// num_bytes will be interpreted as an unsigned number + /// A value of 0 will cause the backend to discard the transfer prematurely + /// - src_cache, dst_cache: the configuration of the cache fields in the AX beats + /// - src_burst, dst_burst: currently only incremental bursts are supported (2'b01) + /// - decouple_rw: if set to true, there is no longer exactly one AXI write_request issued for + /// every read request. This mode can improve performance of unaligned transfers when crossing + /// the AXI page boundaries. + /// - deburst: if set, the DMA will split all bursts in single transfers + parameter type burst_req_t = logic, + /// Read request definition. Includes: + /// - ax descriptor + /// - id: AXI id + /// - last: last transaction in burst + /// - address: address of burst + /// - length: burst length + /// - size: bytes in each burst + /// - burst: burst type; only INC supported + /// - cache: cache type + /// - r descriptor + /// - offset: initial misalignment + /// - tailer: final misalignment + /// - shift: amount the data needs to be shifted to realign it + parameter type read_req_t = logic, + /// Write request definition. Includes: + /// - ax descriptor + /// - id: AXI id + /// - last: last transaction in burst + /// - address: address of burst + /// - length: burst length + /// - size: bytes in each burst + /// - burst: burst type; only INC supported + /// - cache: cache type + /// - w descriptor + /// - offset: initial misalignment + /// - tailer: final misalignment + /// - num_beats: number of beats in the burst + /// - is_single: burst length is 0 + parameter type write_req_t = logic + +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Arbitrary 1D burst request + input burst_req_t burst_req_i, + + /// Handshake: burst request is valid + input logic valid_i, + /// Handshake: burst request can be accepted + output logic ready_o, + + /// Write transfer request + output write_req_t write_req_o, + /// Read transfer request + output read_req_t read_req_o, + + /// Handshake: read transfer request valid + output logic r_valid_o, + /// Handshake: read transfer request ready + input logic r_ready_i, + /// Handshake: write transfer request valid + output logic w_valid_o, + /// Handshake: write transfer request ready + input logic w_ready_i +); + + localparam int unsigned StrbWidth = DataWidth / 8; + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + localparam int unsigned PageSize = (256 * StrbWidth > 4096) ? 4096 : 256 * StrbWidth; + localparam int unsigned PageAddrWidth = $clog2(PageSize); + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address Type + typedef logic [ AddrWidth-1:0] addr_t; + /// AXI ID Type + typedef logic [ IdWidth-1:0] axi_id_t; + + /// Type containing burst description for each channel independently + typedef struct packed { + axi_id_t id; + addr_t addr; + addr_t num_bytes; + axi_pkg::cache_t cache; + axi_pkg::burst_t burst; + logic valid; + } burst_chan_t; + + /// Type containing burst description + typedef struct packed { + burst_chan_t src; + burst_chan_t dst; + offset_t shift; + logic decouple_rw; + logic deburst; + } burst_decoupled_t; + + //-------------------------------------- + // state; internally hold one transfer + //-------------------------------------- + burst_decoupled_t burst_d, burst_q; + + //-------------------------------------- + // page boundary check + //-------------------------------------- + logic [PageAddrWidth-1:0] r_page_offset; + logic [PageAddrWidth :0] r_num_bytes_to_pb; + logic [PageAddrWidth-1:0] w_page_offset; + logic [PageAddrWidth :0] w_num_bytes_to_pb; + logic [PageAddrWidth :0] c_num_bytes_to_pb; + + always_comb begin : proc_write_page_boundry_check + // implement deburst operation + if (burst_q.deburst) begin + // deburst + // read pages + r_page_offset = burst_q.src.addr[OffsetWidth-1:0]; + // how many transfers are remaining until the end of the bus? + r_num_bytes_to_pb = (StrbWidth - r_page_offset) % (2 * StrbWidth); + + // write pages + w_page_offset = burst_q.dst.addr[OffsetWidth-1:0]; + // how many transfers are remaining until the end of the bus? + w_num_bytes_to_pb = (StrbWidth - w_page_offset) % (2 * StrbWidth); + end else begin + // bursts allowed + // read pages + r_page_offset = burst_q.src.addr[PageAddrWidth-1:0]; + // how many transfers are remaining in current page? + r_num_bytes_to_pb = PageSize - r_page_offset; + + // write pages + w_page_offset = burst_q.dst.addr[PageAddrWidth-1:0]; + // how many transfers are remaining in current page? + w_num_bytes_to_pb = PageSize - w_page_offset; + end + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + end + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + logic [PageAddrWidth:0] r_num_bytes_possible; + logic [PageAddrWidth:0] r_num_bytes; + logic r_finish; + logic [OffsetWidth-1:0] r_addr_offset; + + logic [PageAddrWidth:0] w_num_bytes_possible; + logic [PageAddrWidth:0] w_num_bytes; + logic w_finish; + logic [OffsetWidth-1:0] w_addr_offset; + + always_comb begin : proc_read_write_transaction + + // default: keep last state + burst_d = burst_q; + + //-------------------------------------- + // Specify read transaction + //-------------------------------------- + // max num bytes according to page(s) + r_num_bytes_possible = (burst_q.decouple_rw == 1'b1) ? + r_num_bytes_to_pb : c_num_bytes_to_pb; + + // more bytes remaining than we can send + if (burst_q.src.num_bytes > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + burst_d.src.num_bytes = burst_q.src.num_bytes - r_num_bytes_possible; + // not finished + r_finish = 1'b0; + // next address, depends on burst type. only type 01 is supported yet + burst_d.src.addr = (burst_q.src.burst == axi_pkg::BURST_INCR) ? + burst_q.src.addr + r_num_bytes : burst_q.src.addr; + + // remaining bytes fit in one burst + // reset storage for the read channel to stop this channel + end else begin + r_num_bytes = burst_q.src.num_bytes[PageAddrWidth:0]; + // default: when a transfer is finished, set it to 0 + burst_d.src = '0; + // finished + r_finish = 1'b1; + end + + // calculate the address offset aligned to transfer sizes. + r_addr_offset = burst_q.src.addr[OffsetWidth-1:0]; + + // create the AR request + read_req_o.ar.addr = { burst_q.src.addr[AddrWidth-1:OffsetWidth], + {{OffsetWidth}{1'b0}} }; + read_req_o.ar.len = ((r_num_bytes + r_addr_offset - 1) >> OffsetWidth); + read_req_o.ar.size = axi_pkg::size_t'(OffsetWidth); + read_req_o.ar.id = burst_q.src.id; + read_req_o.ar.last = r_finish; + read_req_o.ar.burst = burst_q.src.burst; + read_req_o.ar.cache = burst_q.src.cache; + r_valid_o = burst_q.decouple_rw ? + burst_q.src.valid : burst_q.src.valid & w_ready_i; + + // create the R request + read_req_o.r.offset = r_addr_offset; + read_req_o.r.tailer = OffsetWidth'(r_num_bytes + r_addr_offset); + // shift is determined on a per 1D request base + read_req_o.r.shift = burst_q.shift; + + //-------------------------------------- + // Specify write transaction + //-------------------------------------- + // max num bytes according to page(s) + w_num_bytes_possible = (burst_q.decouple_rw == 1'b1) ? + w_num_bytes_to_pb : c_num_bytes_to_pb; + + // more bytes remaining than we can send + if (burst_q.dst.num_bytes > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + burst_d.dst.num_bytes = burst_q.dst.num_bytes - w_num_bytes_possible; + // not finished + w_finish = 1'b0; + // next address, depends on burst type. only type 01 is supported yet + burst_d.dst.addr = (burst_q.dst.burst == axi_pkg::BURST_INCR) ? + burst_q.dst.addr + w_num_bytes : burst_q.dst.addr; + + // remaining bytes fit in one burst + // reset storage for the write channel to stop this channel + end else begin + w_num_bytes = burst_q.dst.num_bytes[PageAddrWidth:0]; + // default: when a transfer is finished, set it to 0 + burst_d.dst = '0; + // finished + w_finish = 1'b1; + end + + // calculate the address offset aligned to transfer sizes. + w_addr_offset = burst_q.dst.addr[OffsetWidth-1:0]; + + // create the AW request + write_req_o.aw.addr = { burst_q.dst.addr[AddrWidth-1:OffsetWidth], + {{OffsetWidth}{1'b0}} }; + write_req_o.aw.len = ((w_num_bytes + w_addr_offset - 1) >> OffsetWidth); + write_req_o.aw.size = axi_pkg::size_t'(OffsetWidth); + write_req_o.aw.id = burst_q.dst.id; + // hand over internal transaction id + write_req_o.aw.last = w_finish; + write_req_o.aw.burst = burst_q.dst.burst; + write_req_o.aw.cache = burst_q.dst.cache; + w_valid_o = burst_q.decouple_rw ? + burst_q.dst.valid : burst_q.dst.valid & r_ready_i; + + // create the W request + write_req_o.w.offset = w_addr_offset; + write_req_o.w.tailer = OffsetWidth'(w_num_bytes + w_addr_offset); + write_req_o.w.num_beats = write_req_o.aw.len; + // is the transfer be only one beat in length? Counters don't have to be initialized then. + write_req_o.w.is_single = (write_req_o.aw.len == '0); + + //-------------------------------------- + // Module control + //-------------------------------------- + ready_o = r_finish & w_finish & valid_i & r_ready_i & w_ready_i; + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o) begin + // unfortunately this is unpacked + burst_d.src.id = burst_req_i.id; + burst_d.src.addr = burst_req_i.src; + burst_d.src.num_bytes = burst_req_i.num_bytes; + burst_d.src.cache = burst_req_i.cache_src; + burst_d.src.burst = burst_req_i.burst_src; + // check if transfer is possible -> num_bytes has to be larger than 0 + burst_d.src.valid = (burst_req_i.num_bytes == '0) ? 1'b0 : valid_i; + + burst_d.dst.id = burst_req_i.id; + burst_d.dst.addr = burst_req_i.dst; + burst_d.dst.num_bytes = burst_req_i.num_bytes; + burst_d.dst.cache = burst_req_i.cache_dst; + burst_d.dst.burst = burst_req_i.burst_dst; + // check if transfer is possible -> num_bytes has to be larger than 0 + burst_d.dst.valid = (burst_req_i.num_bytes == '0) ? 1'b0 : valid_i; + + burst_d.decouple_rw = burst_req_i.decouple_rw; + burst_d.deburst = burst_req_i.deburst; + // shift is calculated for each 1D transfer + burst_d.shift = burst_req_i.src[OffsetWidth-1:0] - + burst_req_i.dst[OffsetWidth-1:0]; + + // assertions + // pragma translate_off + `ifndef VERILATOR + assert property (@(posedge clk_i) disable iff (~rst_ni) + (valid_i |-> burst_req_i.burst_src inside {axi_pkg::BURST_INCR})) else + $fatal(1, "Unsupported DMA src_burst request.."); + assert property (@(posedge clk_i) disable iff (~rst_ni) + (valid_i |-> burst_req_i.burst_dst inside {axi_pkg::BURST_INCR})) else + $fatal(1, "Unsupported DMA dst_burst request."); + `endif + // pragma translate_on + end + end + + //-------------------------------------- + // State + //-------------------------------------- + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + burst_q.decouple_rw <= '0; + burst_q.deburst <= '0; + burst_q.shift <= '0; + burst_q.src <= '0; + burst_q.dst <= '0; + end else begin + burst_q.decouple_rw <= burst_d.decouple_rw; + burst_q.deburst <= burst_d.deburst; + burst_q.shift <= burst_d.shift; + // couple read and write machines in the coupled test + if (burst_d.decouple_rw) begin + if (r_ready_i) burst_q.src <= burst_d.src; + if (w_ready_i) burst_q.dst <= burst_d.dst; + end else begin + if (r_ready_i & w_ready_i) burst_q.src <= burst_d.src; + if (w_ready_i & r_ready_i) burst_q.dst <= burst_d.dst; + end + end + end +endmodule : axi_dma_burst_reshaper diff --git a/hw/deps/axi/src/dma/axi_dma_data_mover.sv b/hw/deps/axi/src/dma/axi_dma_data_mover.sv new file mode 100644 index 0000000..433fed0 --- /dev/null +++ b/hw/deps/axi/src/dma/axi_dma_data_mover.sv @@ -0,0 +1,370 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// Module, that controls the AXI bus. Takes two configuration structs (R/W) as an +/// input. Implements the DMA functionality on the AXI bus. +/// R and W config structs need to appear at the input simultaneously; sending a +/// R config w/o the corresponding W could lead to wrong AXI transfers. +module axi_dma_data_mover #( + /// Data width of the AXI bus + parameter int unsigned DataWidth = -1, + /// Number of AX beats that can be in-flight + parameter int unsigned ReqFifoDepth = -1, + /// Number of elements the realignment buffer can hold. To achieve + /// full performance a depth of 3 is minimally required. + parameter int unsigned BufferDepth = -1, + /// AXI4+ATOP request struct definition. + parameter type axi_req_t = logic, + /// AXI4+ATOP response struct definition. + parameter type axi_res_t = logic, + /// ax descriptor + /// - `id`: AXI id + /// - `last`: last transaction in burst + /// - `address`: address of burst + /// - `length`: burst length + /// - `size`: bytes in each burst + /// - `burst`: burst type; only INC supported + /// - `cache`: cache type + parameter type desc_ax_t = logic, + /// r descriptor + /// - `offset`: initial misalignment + /// - `tailer`: final misalignment + /// - `shift`: amount the data needs to be shifted to realign it + parameter type desc_r_t = logic, + /// w descriptor + /// - `offset`: initial misalignment + /// - `tailer`: final misalignment + /// - `num_beats`: number of beats in the burst + /// - `is_single`: burst length is 0 + parameter type desc_w_t = logic, + /// Read request definition. Includes: + /// - ax descriptor + /// - `id`: AXI id + /// - `last`: last transaction in burst + /// - `address`: address of burst + /// - `length`: burst length + /// - `size`: bytes in each burst + /// - `burst`: burst type; only INC supported + /// - `cache`: cache type + /// - r descriptor + /// - `offset`: initial misalignment + /// - `tailer`: final misalignment + /// - `shift`: amount the data needs to be shifted to realign it + parameter type read_req_t = logic, + /// Write request definition. Includes: + /// - ax descriptor + /// - `id`: AXI id + /// - `last`: last transaction in burst + /// - `address`: address of burst + /// - `length`: burst length + /// - `size`: bytes in each burst + /// - `burst`: burst type; only INC supported + /// - `cache`: cache type + /// - w descriptor + /// - `offset`: initial misalignment + /// - `tailer`: final misalignment + /// - `num_beats`: number of beats in the burst + /// - `is_single`: burst length is 0 + parameter type write_req_t = logic +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// AXI4+ATOP master request + output axi_req_t axi_dma_req_o, + /// AXI4+ATOP master response + input axi_res_t axi_dma_res_i, + /// Read transfer request + input read_req_t read_req_i, + /// Write transfer request + input write_req_t write_req_i, + /// Handshake: read transfer request valid + input logic r_valid_i, + /// Handshake: read transfer request ready + output logic r_ready_o, + /// Handshake: write transfer request valid + input logic w_valid_i, + /// Handshake: write transfer request ready + output logic w_ready_o, + /// High if the data mover is idle + output logic data_mover_idle_o, + /// Event: a transaction has completed + output logic trans_complete_o +); + + localparam int unsigned StrbWidth = DataWidth / 8; + // local types + typedef logic [DataWidth-1:0] data_t; + typedef logic [StrbWidth-1:0] strb_t; + + //-------------------------------------- + // AR emitter + //-------------------------------------- + // object currently at the tail of the fifo + desc_ax_t current_ar_req; + // control signals + logic ar_emitter_full; + logic ar_emitter_empty; + logic ar_emitter_push; + logic ar_emitter_pop; + + // instanciate a fifo to buffer the address read requests + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DEPTH ( ReqFifoDepth ), + .dtype ( desc_ax_t ) + ) i_fifo_ar_emitter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( ar_emitter_full ), + .empty_o ( ar_emitter_empty ), + .usage_o ( ), + .data_i ( read_req_i.ar ), + .push_i ( ar_emitter_push ), + .data_o ( current_ar_req ), + .pop_i ( ar_emitter_pop ) + ); + + //-------------------------------------- + // AW emitter + //-------------------------------------- + // object currently at the tail of the fifo + desc_ax_t current_aw_req; + // control signals + logic aw_emitter_full; + logic aw_emitter_empty; + logic aw_emitter_push; + logic aw_emitter_pop; + + // instantiate a fifo to buffer the address write requests + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .dtype ( desc_ax_t ), + .DEPTH ( ReqFifoDepth ) + ) i_fifo_aw_emitter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( aw_emitter_full ), + .empty_o ( aw_emitter_empty ), + .usage_o ( ), + .data_i ( write_req_i.aw ), + .push_i ( aw_emitter_push ), + .data_o ( current_aw_req ), + .pop_i ( aw_emitter_pop ) + ); + + //-------------------------------------- + // R emitter + //-------------------------------------- + // object currently at the tail of the fifo + desc_r_t current_r_req; + // control signals + logic r_emitter_full; + logic r_emitter_empty; + logic r_emitter_push; + logic r_emitter_pop; + + // instantiate a fifo to buffer the read requests + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .dtype ( desc_r_t ), + .DEPTH ( ReqFifoDepth ) + ) i_fifo_r_emitter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( r_emitter_full ), + .empty_o ( r_emitter_empty ), + .usage_o ( ), + .data_i ( read_req_i.r ), + .push_i ( r_emitter_push ), + .data_o ( current_r_req ), + .pop_i ( r_emitter_pop ) + ); + + //-------------------------------------- + // W emitter + //-------------------------------------- + // object currently at the tail of the fifo + desc_w_t current_w_req; + // control signals + logic w_emitter_full; + logic w_emitter_empty; + logic w_emitter_push; + logic w_emitter_pop; + + // instanciate a fifo to buffer the read requests + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .dtype ( desc_w_t ), + .DEPTH ( ReqFifoDepth ) + ) i_fifo_w_emitter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( w_emitter_full ), + .empty_o ( w_emitter_empty ), + .usage_o ( ), + .data_i ( write_req_i.w ), + .push_i ( w_emitter_push ), + .data_o ( current_w_req ), + .pop_i ( w_emitter_pop ) + ); + + //-------------------------------------- + // instantiate of the data path + //-------------------------------------- + // AXI bus signals from and to the datapath + data_t r_data; + axi_pkg::resp_t r_resp; + logic r_last; + logic r_valid; + logic r_ready; + data_t w_data; + strb_t w_strb; + logic w_valid; + logic w_last; + logic w_ready; + + logic w_next; + + axi_dma_data_path #( + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ) + ) i_axi_dma_data_path ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_valid_i ( ~r_emitter_empty ), + .r_dp_ready_o ( r_emitter_pop ), + .w_dp_valid_i ( ~w_emitter_empty ), + .w_dp_ready_o ( w_emitter_pop ), + .data_path_idle_o ( data_mover_idle_o ), + // AXI R signals + .r_data_i ( r_data ), + .r_valid_i ( r_valid ), + .r_last_i ( r_last ), + .r_resp_i ( r_resp ), + .r_ready_o ( r_ready ), + // R control + .r_tailer_i ( current_r_req.tailer ), + .r_offset_i ( current_r_req.offset ), + .r_shift_i ( current_r_req.shift ), + // AXI W signals + .w_data_o ( w_data ), + .w_strb_o ( w_strb ), + .w_valid_o ( w_valid ), + .w_last_o ( w_last ), + .w_ready_i ( w_ready ), + // W control + .w_offset_i ( current_w_req.offset ), + .w_tailer_i ( current_w_req.tailer ), + .w_num_beats_i ( current_w_req.num_beats ), + .w_is_single_i ( current_w_req.is_single ) + ); + + //-------------------------------------- + // Refill control + //-------------------------------------- + // the ax and x fifos of both channels are filled + // together, as request come bundled. + always_comb begin : proc_refill + // Read related channels + r_ready_o = ~ar_emitter_full & ~r_emitter_full; + r_emitter_push = r_valid_i & r_ready_o; + ar_emitter_push = r_valid_i & r_ready_o; + + // Write related channels + w_ready_o = ~aw_emitter_full & ~w_emitter_full; + w_emitter_push = w_valid_i & w_ready_o; + aw_emitter_push = w_valid_i & w_ready_o; + end + + //-------------------------------------- + // Bus control + //-------------------------------------- + // here the AXI bus is unpacked/packed. + always_comb begin : proc_bus_packer + // defaults: not used signals -> 0 + axi_dma_req_o = '0; + + // assign R signals + r_data = axi_dma_res_i.r.data; + r_resp = axi_dma_res_i.r.resp; + r_last = axi_dma_res_i.r.last; + r_valid = axi_dma_res_i.r_valid; + axi_dma_req_o.r_ready = r_ready; + + // assign W signals + axi_dma_req_o.w.data = w_data; + axi_dma_req_o.w.strb = w_strb; + axi_dma_req_o.w.last = w_last; + axi_dma_req_o.w_valid = w_valid; + w_ready = axi_dma_res_i.w_ready; + + // AW signals + axi_dma_req_o.aw.id = current_aw_req.id; + axi_dma_req_o.aw.addr = current_aw_req.addr; + axi_dma_req_o.aw.len = current_aw_req.len; + axi_dma_req_o.aw.size = current_aw_req.size; + axi_dma_req_o.aw.burst = current_aw_req.burst; + axi_dma_req_o.aw.cache = current_aw_req.cache; + // flow control + axi_dma_req_o.aw_valid = ~aw_emitter_empty; + aw_emitter_pop = axi_dma_res_i.aw_ready & axi_dma_req_o.aw_valid; + + // B signals + // we are always ready to accept b signals, as we do not need them + // inside the DMA (we don't care if write failed) + axi_dma_req_o.b_ready = 1'b1; + + // AR signals + axi_dma_req_o.ar.id = current_ar_req.id; + axi_dma_req_o.ar.addr = current_ar_req.addr; + axi_dma_req_o.ar.len = current_ar_req.len; + axi_dma_req_o.ar.size = current_ar_req.size; + axi_dma_req_o.ar.burst = current_ar_req.burst; + axi_dma_req_o.ar.cache = current_ar_req.cache; + // flow control + axi_dma_req_o.ar_valid = ~ar_emitter_empty; + ar_emitter_pop = axi_dma_res_i.ar_ready & axi_dma_req_o.ar_valid; + end + + //-------------------------------------- + // ID control + //-------------------------------------- + logic is_last_aw; + fifo_v3 #( + .DEPTH ( ReqFifoDepth + BufferDepth + 1 ), + .dtype ( logic ) + ) i_last_transaction_queue ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( ), + .empty_o ( ), + .usage_o ( ), + .data_i ( current_aw_req.last ), + .push_i ( aw_emitter_pop ), + .data_o ( is_last_aw ), + .pop_i ( axi_dma_res_i.b_valid ) + ); + assign trans_complete_o = is_last_aw & axi_dma_res_i.b_valid; + +endmodule : axi_dma_data_mover diff --git a/hw/deps/axi/src/dma/axi_dma_data_path.sv b/hw/deps/axi/src/dma/axi_dma_data_path.sv new file mode 100644 index 0000000..73a197e --- /dev/null +++ b/hw/deps/axi/src/dma/axi_dma_data_path.sv @@ -0,0 +1,393 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// Data path for the AXI DMA. This modules handles the R/W channel of the +/// AXI protocol. +/// Module gets read stream, realigns data and emits a write stream. +/// AXI-like valid/ready handshaking is used to communicate with the rest +/// of the backend. +module axi_dma_data_path #( + /// Data width of the AXI bus + parameter int DataWidth = -1, + /// Number of elements the realignment buffer can hold. To achieve + /// full performance a depth of 3 is minimally required. + parameter int BufferDepth = -1, + // DO NOT OVERWRITE THIS PARAMETER + parameter int StrbWidth = DataWidth / 8, + parameter int OffsetWidth = $clog2(StrbWidth) +) ( + // status signals + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + // handshaking signals + /// Handshake: read side of data path is presented with a valid request + input logic r_dp_valid_i, + /// Handshake: read side of data path is ready to accept new requests + output logic r_dp_ready_o, + /// Handshake: write side of data path is presented with a valid request + input logic w_dp_valid_i, + /// Handshake: write side of data path is ready to accept new requests + output logic w_dp_ready_o, + + // status signal + /// High if the data path is idle + output logic data_path_idle_o, + + // r-channel + /// Read data from the AXI bus + input logic [DataWidth-1:0] r_data_i, + /// Valid signal of the AXI r channel + input logic r_valid_i, + /// Last signal of the AXI r channel + input logic r_last_i, + /// Response signal of the AXI r channel + input logic [ 1:0] r_resp_i, + /// Ready signal of the AXI r channel + output logic r_ready_o, + + /// number of bytes the end of the read transfer is short to reach a + /// Bus-aligned boundary + input logic [OffsetWidth-1:0] r_tailer_i, + /// number of bytes the read transfers starts after a + /// Bus-aligned boundary + input logic [OffsetWidth-1:0] r_offset_i, + /// The amount the read data has to be shifted to write-align it + input logic [OffsetWidth-1:0] r_shift_i, + + // w-channel + /// Write data of the AXI bus + output logic [DataWidth-1:0] w_data_o, + /// Write strobe of the AXI bus + output logic [StrbWidth-1:0] w_strb_o, + /// Valid signal of the AXI w channel + output logic w_valid_o, + /// Last signal of the AXI w channel + output logic w_last_o, + /// Ready signal of the AXI w channel + input logic w_ready_i, + + /// number of bytes the write transfers starts after a + /// Bus-aligned boundary + input logic [OffsetWidth-1:0] w_offset_i, + /// number of bytes the end of the write transfer is short to reach a + /// Bus-aligned boundary + input logic [OffsetWidth-1:0] w_tailer_i, + /// Number of beats requested by this transfer + input logic [ 7:0] w_num_beats_i, + /// True if the transfer only consists of a single beat + input logic w_is_single_i +); + + // buffer contains 8 data bits per FIFO + // buffer is at least 3 deep to prevent stalls + + // 64 bit DATA Width example: + // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD <- head + // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD + // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD <- tail + // -byte7--|-byte6--|-byte5--|-byte4--|-byte3--|-byte2--|-byte1--|-byte0--| + + + //-------------------------------------- + // Mask pre-calculation + //-------------------------------------- + // in contiguous transfers that are unaligned, there will be some + // invalid bytes at the beginning and the end of the stream + // example: 25B in 64 bit system + // iiiivvvv|vvvvvvvv|vvvvvvvv|vvvvviii + // last msk|----full mask----|first msk + + // offsets needed for masks to fill/empty buffer + logic [StrbWidth-1:0] r_first_mask; + logic [StrbWidth-1:0] r_last_mask; + logic [StrbWidth-1:0] w_first_mask; + logic [StrbWidth-1:0] w_last_mask; + + // read align masks + assign r_first_mask = '1 << r_offset_i; + assign r_last_mask = '1 >> (StrbWidth - r_tailer_i); + + // write align masks + assign w_first_mask = '1 << w_offset_i; + assign w_last_mask = '1 >> (StrbWidth - w_tailer_i); + + + //-------------------------------------- + // Barrel shifter + //-------------------------------------- + // data arrives in chuncks of length DATA_WDITH, the buffer will be filled with + // the realigned data. StrbWidth bytes will be inserted starting from the + // provided address, overflows will naturally wrap + + // signals connected to the buffer + logic [StrbWidth-1:0][7:0] buffer_in; + + // read aligned in mask. needs to be rotated together with the data before + // it can be used to fill in valid data into the buffer + logic [StrbWidth-1:0] read_aligned_in_mask; + + // in mask is write aligned, so it is the result of the read aligned in mask + // that is rotated together with the data in the barrel shifter + logic [StrbWidth-1:0] in_mask; + + // a barrel shifter is a concatenation of the same array with itself and a normal + // shift. + assign buffer_in = {r_data_i, r_data_i} >> (r_shift_i * 8); + assign in_mask = {read_aligned_in_mask, read_aligned_in_mask} >> r_shift_i; + + //-------------------------------------- + // In mask generation + //-------------------------------------- + // in the case of unaligned reads -> not all data is valid + logic is_first_r, is_first_r_d; + + always_comb begin : proc_in_mask_generator + // default case: all ones + read_aligned_in_mask = '1; + // is first word: some bytes at the beginning may be invalid + read_aligned_in_mask = is_first_r ? + read_aligned_in_mask & r_first_mask : read_aligned_in_mask; + // is last word in write burst: some bytes at the end may be invalid + if (r_tailer_i != '0) begin + read_aligned_in_mask = r_last_i ? + read_aligned_in_mask & r_last_mask : read_aligned_in_mask; + end + end + + //-------------------------------------- + // Read control + //-------------------------------------- + logic [StrbWidth-1:0] buffer_full; + logic [StrbWidth-1:0] buffer_push; + logic full; + // this signal is used for pushing data to the control fifo + logic push; + + always_comb begin : proc_read_control + // sticky is first bit for read + if (r_valid_i & !r_last_i) begin + // new transfer has started + is_first_r_d = 1'b0; + end else if (r_last_i & r_valid_i) begin + // finish read burst + is_first_r_d = 1'b1; + end else begin + // no change + is_first_r_d = is_first_r; + end + + // the buffer can be pushed to if all the masked fifo buffers (in_mask) are not full. + full = |(buffer_full & in_mask); + // the read can accept data if the buffer is not full + r_ready_o = ~full; + + // once valid data is applied, it can be pushed in all the selected (in_mask) buffers + push = r_valid_i && ~full; + buffer_push = push ? in_mask : '0; + + // r_dp_ready_o is triggered by the last element arriving from the read + r_dp_ready_o = r_dp_valid_i && r_last_i && r_valid_i && ~full;; + end + + //-------------------------------------- + // Out mask generation -> wstrb mask + //-------------------------------------- + // only pop the data actually needed for write from the buffer, + // determine valid data to pop by calculation the wstrb + logic [StrbWidth-1:0] out_mask; + logic is_first_w; + logic is_last_w; + + always_comb begin : proc_out_mask_generator + // default case: all ones + out_mask = '1; + // is first word: some bytes at the beginning may be invalid + out_mask = is_first_w ? (out_mask & w_first_mask) : out_mask; + // is last word in write burst: some bytes at the end may be invalid + if (w_tailer_i != '0) begin + out_mask = is_last_w ? out_mask & w_last_mask : out_mask; + end + end + + //-------------------------------------- + // Write control + //-------------------------------------- + // once buffer contains a full line -> all fifos are non-empty + // push it out. + // signals connected to the buffer + logic [StrbWidth-1:0][7:0] buffer_out; + logic [StrbWidth-1:0] buffer_empty; + logic [StrbWidth-1:0] buffer_pop; + + // write is decoupled from read, due to misalignments in the read/write + // addresses, page crossing can be encountered at any time. + // To handle this efficiently, a 2-to-1 or 1-to-2 mapping of r/w beats + // is required. The write unit needs to keep track of progress through + // a counter and cannot use `r_last` for that. + logic [7:0] w_num_beats_d, w_num_beats_q; + logic w_cnt_valid_d, w_cnt_valid_q; + + // data from buffer is popped + logic pop; + // write happens + logic write_happening; + // buffer is ready to write the requested data + logic ready_to_write; + // first transfer is possible - this signal is used to detect + // the first write transfer in a burst + logic first_possible; + // buffer is completely empty + logic buffer_clean; + + always_comb begin : proc_write_control + // counter + w_num_beats_d = w_num_beats_q; + w_cnt_valid_d = w_cnt_valid_q; + // buffer ctrl + pop = 1'b0; + buffer_pop = 'b0; + write_happening = 1'b0; + ready_to_write = 1'b0; + first_possible = 1'b0; + // bus signals + w_valid_o = 1'b0; + w_data_o = '0; + w_strb_o = '0; + w_last_o = 1'b0; + // mask control + is_first_w = 1'b0; + is_last_w = 1'b0; + // data flow + w_dp_ready_o = 1'b0; + + + // all elements needed (defined by the mask) are in the buffer and the buffer is non-empty + ready_to_write = ((~buffer_empty & out_mask) == out_mask) && (buffer_empty != '1); + + // data needed by the first mask is available in the buffer -> r_first happened for sure + // this signal can be high during a transfer as well, it needs to be masked + first_possible = ((~buffer_empty & w_first_mask) == w_first_mask) && (buffer_empty != '1); + + // the buffer is completely empty (debug only signal) + buffer_clean = &(buffer_empty); + + // write happening: both the bus (w_ready) and the buffer (ready_to_write) is high + write_happening = ready_to_write & w_ready_i; + + // signal the control fifo it could be popped + pop = write_happening; + + // the main buffer is conditionally to the write mask popped + buffer_pop = write_happening ? out_mask : '0; + + // signal the bus that we are ready + w_valid_o = ready_to_write; + + // control the write to the bus apply data to the bus only if data should be written + if (ready_to_write == 1'b1) begin + // assign data from buffers, mask out non valid entries + for (int i = 0; i < StrbWidth; i++) begin + w_data_o[i*8 +: 8] = out_mask[i] ? buffer_out[i] : 8'b0; + end + // assign the out mask to the strobe + w_strb_o = out_mask; + end + + // differentiate between the burst and non-burst case. If a transfer + // consists just of one beat the counters are disabled + if (w_is_single_i) begin + // in the single case the transfer is both first and last. + is_first_w = 1'b1; + is_last_w = 1'b1; + + // in the bursted case the counters are needed to keep track of the progress of sending + // beats. The w_last_o depends on the state of the counter + end else begin + // first transfer happens as soon as a) the buffer is ready for a first transfer and b) + // the counter is currently invalid + is_first_w = first_possible & ~w_cnt_valid_q; + + // last happens as soon as a) the counter is valid and b) the counter is now down to 1 + is_last_w = w_cnt_valid_q & (w_num_beats_q == 8'h01); + + // load the counter with data in a first cycle, only modifying state if bus is ready + if (is_first_w && write_happening) begin + w_num_beats_d = w_num_beats_i; + w_cnt_valid_d = 1'b1; + end + + // if we hit the last element, invalidate the counter, only modifying state + // if bus is ready + if (is_last_w && write_happening) begin + w_cnt_valid_d = 1'b0; + end + + // count down the beats if the counter is valid and valid data is written to the bus + if (w_cnt_valid_q && write_happening) w_num_beats_d = w_num_beats_q - 8'h01; + end + + // the w_last_o signal should only be applied to the bus if an actual transfer happens + w_last_o = is_last_w & ready_to_write; + + // we are ready for the next transfer internally, once the w_last_o signal is applied + w_dp_ready_o = is_last_w & write_happening; + end + + + //-------------------------------------- + // Buffer - implemented as fifo + //-------------------------------------- + logic control_empty; + + for (genvar i = 0; i < StrbWidth; i++) begin : fifo_buffer + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DATA_WIDTH ( 8 ), + .DEPTH ( BufferDepth ) + ) i_fifo_buffer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( buffer_full [i] ), + .empty_o ( buffer_empty[i] ), + .usage_o ( ), + .data_i ( buffer_in [i] ), + .push_i ( buffer_push [i] ), + .data_o ( buffer_out [i] ), + .pop_i ( buffer_pop [i] ) + ); + end + + //-------------------------------------- + // Module Control + //------------------------------------- + assign data_path_idle_o = !(r_dp_valid_i | r_dp_ready_o | + w_dp_valid_i | w_dp_ready_o | !buffer_clean); + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ff + if (!rst_ni) begin + is_first_r <= 1'b1; + w_cnt_valid_q <= 1'b0; + w_num_beats_q <= 8'h0; + end else begin + // running_q <= running_d; + if (r_valid_i & r_ready_o) is_first_r <= is_first_r_d; + w_cnt_valid_q <= w_cnt_valid_d; + w_num_beats_q <= w_num_beats_d; + end + end + +endmodule : axi_dma_data_path diff --git a/hw/deps/axi/src/dma/frontends/pspin_soc_frontend/src/pspin_soc_dma.sv b/hw/deps/axi/src/dma/frontends/pspin_soc_frontend/src/pspin_soc_dma.sv new file mode 100644 index 0000000..b7be8c6 --- /dev/null +++ b/hw/deps/axi/src/dma/frontends/pspin_soc_frontend/src/pspin_soc_dma.sv @@ -0,0 +1,259 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// soc-level dma + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module pspin_soc_dma #( + /// id width of the DMA AXI Master port + parameter int unsigned DmaAxiIdWidth = -1, + /// data width of the DMA AXI Master port + parameter int unsigned DmaDataWidth = -1, + /// address width of the DMA AXI Master port + parameter int unsigned DmaAddrWidth = -1, + /// user width + parameter int unsigned DmaUserWidth = -1, + /// number of AX requests in-flight + parameter int unsigned AxiAxReqDepth = -1, + /// number of 1D transfers buffered in backend + parameter int unsigned TfReqFifoDepth = -1, + /// data request type + parameter type axi_req_t = logic, + /// data response type + parameter type axi_res_t = logic, + /// transfer descriptor for hw access to DMA + parameter type transf_descr_t = logic, + parameter logic[DmaAddrWidth-1:0] PCIeStartAddr = '0, + parameter logic[DmaAddrWidth-1:0] PCIeEndAddr = '0, + parameter logic[DmaAddrWidth-1:0] NHIStartAddr = '0, + parameter logic[DmaAddrWidth-1:0] NHIEndAddr = '0 +) ( + input logic clk_i, + input logic rst_ni, + /// direct hw port + input logic rx_req_valid_i, + output logic rx_req_ready_o, + input transf_descr_t rx_req_i, + output logic rx_rsp_valid_o, + /// direct hw port + input logic tx_req_valid_i, + output logic tx_req_ready_o, + input transf_descr_t tx_req_i, + output logic tx_rsp_valid_o, + /// wide AXI pcie ports + output axi_req_t pcie_dma_req_o, + input axi_res_t pcie_dma_res_i, + /// wide AXI nhi ports + output axi_req_t nhi_dma_req_o, + input axi_res_t nhi_dma_res_i, + /// status signal + output logic [1:0] idle_o +); + + localparam int unsigned BaseDMAId = 'h10; + + // 1D burst request + typedef logic [DmaAddrWidth-1 :0] addr_t; + typedef logic [DmaAxiIdWidth-1:0] axi_id_t; + typedef struct packed { + axi_id_t id; + addr_t src, dst, num_bytes; + axi_pkg::cache_t cache_src, cache_dst; + axi_pkg::burst_t burst_src, burst_dst; + logic decouple_rw; + logic deburst; + logic serialize; + } burst_req_t; + + // axi definition + localparam int unsigned DmaAxiIdWidthMst = DmaAxiIdWidth - 1; + + typedef logic [DmaDataWidth-1 :0] data_t; + typedef logic [DmaAxiIdWidthMst-1:0] id_mst_t; + typedef logic [DmaAxiIdWidth-1 :0] id_slv_t; + typedef logic [DmaDataWidth/8-1 :0] strb_t; + typedef logic [DmaUserWidth-1 :0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_mst_t, addr_t, id_mst_t, user_t); + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_slv_t, addr_t, id_slv_t, user_t); + `AXI_TYPEDEF_W_CHAN_T (w_chan_t, data_t, strb_t, user_t); + `AXI_TYPEDEF_B_CHAN_T (b_chan_mst_t, id_mst_t, user_t); + `AXI_TYPEDEF_B_CHAN_T (b_chan_slv_t, id_slv_t, user_t); + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_mst_t, addr_t, id_mst_t, user_t); + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_slv_t, addr_t, id_slv_t, user_t); + `AXI_TYPEDEF_R_CHAN_T (r_chan_mst_t, data_t, id_mst_t, user_t); + `AXI_TYPEDEF_R_CHAN_T (r_chan_slv_t, data_t, id_slv_t, user_t); + `AXI_TYPEDEF_REQ_T (axi_dma_req_mst_t, aw_chan_mst_t, w_chan_t, ar_chan_mst_t); + `AXI_TYPEDEF_REQ_T (axi_dma_req_slv_t, aw_chan_slv_t, w_chan_t, ar_chan_slv_t); + `AXI_TYPEDEF_RESP_T (axi_dma_resp_mst_t, b_chan_mst_t, r_chan_mst_t); + `AXI_TYPEDEF_RESP_T (axi_dma_resp_slv_t, b_chan_slv_t, r_chan_slv_t); + + axi_dma_req_mst_t axi_dma_tx_req, axi_dma_rx_req; + axi_dma_resp_mst_t axi_dma_tx_resp, axi_dma_rx_resp; + + burst_req_t rx_burst_req, tx_burst_req; + + always_comb begin : proc_map_rx_to_1D_burst + rx_burst_req.id = BaseDMAId; + rx_burst_req.src = rx_req_i.src_addr; + rx_burst_req.dst = rx_req_i.dst_addr; + rx_burst_req.num_bytes = rx_req_i.num_bytes; + rx_burst_req.burst_src = axi_pkg::BURST_INCR; + rx_burst_req.burst_dst = axi_pkg::BURST_INCR; + rx_burst_req.cache_src = 4'h0; + rx_burst_req.cache_dst = 4'h0; + rx_burst_req.deburst = rx_req_i.deburst; + rx_burst_req.decouple_rw = rx_req_i.decouple; + rx_burst_req.serialize = rx_req_i.serialize; + end + + always_comb begin : proc_map_tx_to_1D_burst + tx_burst_req.id = BaseDMAId; + tx_burst_req.src = tx_req_i.src_addr; + tx_burst_req.dst = tx_req_i.dst_addr; + tx_burst_req.num_bytes = tx_req_i.num_bytes; + tx_burst_req.burst_src = axi_pkg::BURST_INCR; + tx_burst_req.burst_dst = axi_pkg::BURST_INCR; + tx_burst_req.cache_src = 4'h0; + tx_burst_req.cache_dst = 4'h0; + tx_burst_req.deburst = tx_req_i.deburst; + tx_burst_req.decouple_rw = tx_req_i.decouple; + tx_burst_req.serialize = tx_req_i.serialize; + end + axi_dma_backend #( + .DataWidth ( DmaDataWidth ), + .AddrWidth ( DmaAddrWidth ), + .IdWidth ( DmaAxiIdWidthMst ), + .AxReqFifoDepth ( AxiAxReqDepth ), + .TransFifoDepth ( TfReqFifoDepth ), + .BufferDepth ( 3 ), // minimal number giving full performance + .axi_req_t ( axi_dma_req_mst_t ), + .axi_res_t ( axi_dma_resp_mst_t ), + .burst_req_t ( burst_req_t ), + .DmaIdWidth ( 32 ), // the width of the internal id of the dma engine (debug only) + .DmaTracing ( 0 ) + ) i_rx_dma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .dma_id_i ( BaseDMAId + 0 ), + .axi_dma_req_o ( axi_dma_rx_req ), + .axi_dma_res_i ( axi_dma_rx_resp ), + .burst_req_i ( rx_burst_req ), + .valid_i ( rx_req_valid_i ), + .ready_o ( rx_req_ready_o ), + .backend_idle_o ( idle_o [0] ), + .trans_complete_o ( rx_rsp_valid_o ) + ); + + axi_dma_backend #( + .DataWidth ( DmaDataWidth ), + .AddrWidth ( DmaAddrWidth ), + .IdWidth ( DmaAxiIdWidthMst ), + .AxReqFifoDepth ( AxiAxReqDepth ), + .TransFifoDepth ( TfReqFifoDepth ), + .BufferDepth ( 3 ), // minimal number giving full performance + .axi_req_t ( axi_dma_req_mst_t ), + .axi_res_t ( axi_dma_resp_mst_t ), + .burst_req_t ( burst_req_t ), + .DmaIdWidth ( 32 ), // the width of the internal id of the dma engine (debug only) + .DmaTracing ( 0 ) + ) i_tx_dma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .dma_id_i ( BaseDMAId + 1 ), + .axi_dma_req_o ( axi_dma_tx_req ), + .axi_dma_res_i ( axi_dma_tx_resp ), + .burst_req_i ( tx_burst_req ), + .valid_i ( tx_req_valid_i ), + .ready_o ( tx_req_ready_o ), + .backend_idle_o ( idle_o [1] ), + .trans_complete_o ( tx_rsp_valid_o ) + ); + + // include a x-bar to allow full-duplex copy + localparam int unsigned NumRules = 2; + localparam int unsigned IdxPcie = 0; + localparam int unsigned IdxNhi = 1; + + typedef struct packed { + int unsigned idx; + logic [64:0] start_addr; + logic [64:0] end_addr; + } xbar_rule_65_t; + + xbar_rule_65_t [NumRules-1:0] addr_map; + + assign addr_map[IdxPcie] = '{ + start_addr: PCIeStartAddr, + end_addr: PCIeEndAddr, + idx: IdxPcie + }; + + //I'm not being more detailed here because a detailed + //address map is already in the NHI interconnect + assign addr_map[IdxNhi] = '{ + start_addr: NHIStartAddr, + end_addr: NHIEndAddr, + idx: IdxNhi + }; + + localparam NumMstPorts = 2; + localparam NumSlvPorts = 2; + + /* verilator lint_off WIDTHCONCAT */ + localparam axi_pkg::xbar_cfg_t XbarCfg = '{ + NoSlvPorts: NumSlvPorts, + NoMstPorts: NumMstPorts, + MaxMstTrans: 16, + MaxSlvTrans: 32, + FallThrough: 1'b0, + LatencyMode: axi_pkg::CUT_ALL_PORTS, + AxiIdWidthSlvPorts: DmaAxiIdWidthMst, + AxiIdUsedSlvPorts: DmaAxiIdWidthMst, + AxiAddrWidth: DmaAddrWidth, + AxiDataWidth: DmaDataWidth, + NoAddrRules: NumRules + }; + /* verilator lint_on WIDTHCONCAT */ + + axi_xbar #( + .Cfg ( XbarCfg ), + .slv_aw_chan_t ( aw_chan_mst_t ), + .mst_aw_chan_t ( aw_chan_slv_t ), + .w_chan_t ( w_chan_t ), + .slv_b_chan_t ( b_chan_mst_t ), + .mst_b_chan_t ( b_chan_slv_t ), + .slv_ar_chan_t ( ar_chan_mst_t ), + .mst_ar_chan_t ( ar_chan_slv_t ), + .slv_r_chan_t ( r_chan_mst_t ), + .mst_r_chan_t ( r_chan_slv_t ), + .slv_req_t ( axi_dma_req_mst_t ), + .slv_resp_t ( axi_dma_resp_mst_t ), + .mst_req_t ( axi_dma_req_slv_t ), + .mst_resp_t ( axi_dma_resp_slv_t ), + .rule_t ( xbar_rule_65_t ) + ) i_soc_dma_xbar ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_i ( 1'b0 ), + .slv_ports_req_i ( '{ axi_dma_rx_req, axi_dma_tx_req } ), + .slv_ports_resp_o ( '{ axi_dma_rx_resp, axi_dma_tx_resp } ), + .mst_ports_req_o ( '{ nhi_dma_req_o, pcie_dma_req_o } ), + .mst_ports_resp_i ( '{ nhi_dma_res_i, pcie_dma_res_i } ), + .addr_map_i ( addr_map ), + .en_default_mst_port_i ( '0 ), + .default_mst_port_i ( '0 ) + ); + +endmodule : pspin_soc_dma diff --git a/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend.sv b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend.sv new file mode 100644 index 0000000..e40a9d2 --- /dev/null +++ b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend.sv @@ -0,0 +1,425 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +/// replaces the mchan in the pulp cluster if the new AXI DMA should be used +/// strictly 32 bit on the TCDM side. +module pulp_cluster_frontend #( + /// number of cores in the cluster + parameter int unsigned NumCores = -1, + /// id width of peripherals + parameter int unsigned PerifIdWidth = -1, + /// id width of the DMA AXI Master port + parameter int unsigned DmaAxiIdWidth = -1, + /// data width of the DMA AXI Master port + parameter int unsigned DmaDataWidth = -1, + /// address width of the DMA AXI Master port + parameter int unsigned DmaAddrWidth = -1, + /// number of AX requests in-flight + parameter int unsigned AxiAxReqDepth = -1, + /// number of 1D transfers buffered in backend + parameter int unsigned TfReqFifoDepth = -1, + /// data request type + parameter type axi_req_t = logic, + /// data response type + parameter type axi_res_t = logic, + /// transfer descriptor for hw access to DMA + parameter type transf_descr_t = logic +)( + input logic clk_i, + input logic rst_ni, + input logic [5:0] cluster_id_i, + /// x-bar + input logic ctrl_pe_targ_req_i, + input logic ctrl_pe_targ_type_i, + input logic [3:0] ctrl_pe_targ_be_i, + input logic [31:0] ctrl_pe_targ_add_i, + input logic [31:0] ctrl_pe_targ_data_i, + input logic [PerifIdWidth-1:0] ctrl_pe_targ_id_i, + output logic ctrl_pe_targ_gnt_o, + output logic ctrl_pe_targ_r_valid_o, + output logic [31:0] ctrl_pe_targ_r_data_o, + output logic ctrl_pe_targ_r_opc_o, + output logic [PerifIdWidth-1:0] ctrl_pe_targ_r_id_o, + /// from cores + input logic [NumCores-1:0] ctrl_targ_req_i, + input logic [NumCores-1:0] ctrl_targ_type_i, + input logic [NumCores-1:0][3:0] ctrl_targ_be_i, + input logic [NumCores-1:0][31:0] ctrl_targ_add_i, + input logic [NumCores-1:0][31:0] ctrl_targ_data_i, + output logic [NumCores-1:0] ctrl_targ_gnt_o, + output logic [NumCores-1:0] ctrl_targ_r_valid_o, + output logic [NumCores-1:0][31:0] ctrl_targ_r_data_o, + /// direct hw port + input logic dma_req_valid_i, + output logic dma_req_ready_o, + input transf_descr_t dma_req_i, + output logic dma_rsp_valid_o, + /// wide AXI port + output axi_req_t axi_dma_req_o, + input axi_res_t axi_dma_res_i, + /// status signal + output logic busy_o, + /// events and interrupts (cores) + output logic [NumCores-1:0] term_event_o, + output logic [NumCores-1:0] term_irq_o, + /// events and interrupts (peripherals) + output logic term_event_pe_o, + output logic term_irq_pe_o, + /// events and interrupts (cores) + output logic [NumCores-1:0] no_req_pending_o +); + + // number of register sets in fe + localparam int unsigned NumRegs = NumCores + 1; + + // arbitration index width + localparam int unsigned IdxWidth = (NumRegs + 1 > 32'd1) ? unsigned'($clog2(NumRegs + 1)) : 32'd1; + + // buffer depth + localparam int unsigned BufferDepth = 3; // + 64; + + localparam int unsigned TfFifoDepth = TfReqFifoDepth + AxiAxReqDepth + BufferDepth + 1; + + // 1D burst request + typedef logic [DmaAddrWidth-1 :0] addr_t; + typedef logic [DmaAxiIdWidth-1:0] axi_id_t; + typedef struct packed { + axi_id_t id; + addr_t src, dst, num_bytes; + axi_pkg::cache_t cache_src, cache_dst; + axi_pkg::burst_t burst_src, burst_dst; + logic decouple_rw; + logic deburst; + logic serialize; + } burst_req_t; + + // debug only: logfile + integer log_file; + string log_file_name; + + // rr input + transf_descr_t [NumRegs-1:0] transf_descr; + logic [NumRegs-1:0] be_ready; + logic [NumRegs-1:0] be_valid; + // rr output + transf_descr_t transf_descr_arb; + logic be_ready_arb; + logic be_valid_arb; + // the index ob the chosen pe + logic [IdxWidth-1:0] pe_idx_arb; + + // burst request definition + burst_req_t burst_req; + + // transaction id + logic [31:0] next_id, done_id; + + // keep track of peripherals + logic [PerifIdWidth-1:0] peripherals_id_q; + + // backend idle signal + logic be_idle; + logic trans_complete; + + // information about most recent transfer + logic [IdxWidth-1:0] tf_head; + logic tf_empty; + + // define a counter to keep track of the cores individual requests + localparam int unsigned MaxNumRequests = TfReqFifoDepth + BufferDepth + 1; + localparam int unsigned MaxReqWidth = $clog2(MaxNumRequests); + logic [NumCores-1:0][MaxReqWidth-1:0] core_tf_num_d, core_tf_num_q; + + // generate registers for cores + for (genvar i = 0; i < NumCores; i++) begin : gen_core_regs + + pulp_cluster_frontend_regs #( + .transf_descr_t ( transf_descr_t ) + ) i_dma_conf_regs_cores ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .ctrl_req_i ( ctrl_targ_req_i [i] ), + .ctrl_type_i ( ctrl_targ_type_i [i] ), + .ctrl_be_i ( ctrl_targ_be_i [i] ), + .ctrl_add_i ( ctrl_targ_add_i [i] ), + .ctrl_data_i ( ctrl_targ_data_i [i] ), + .ctrl_gnt_o ( ctrl_targ_gnt_o [i] ), + .ctrl_valid_o ( ctrl_targ_r_valid_o [i] ), + .ctrl_data_o ( ctrl_targ_r_data_o [i] ), + .next_id_i ( next_id ), + .done_id_i ( done_id ), + .be_ready_i ( be_ready [i] ), + .be_valid_o ( be_valid [i] ), + .be_busy_i ( busy_o ), + .transf_descr_o ( transf_descr [i] ) + ); + end // gen_core_regs + + // generate registers for cores + for (genvar i = 0; i < NumCores; i++) begin : gen_req_counters + //increase counter if tf is started + always_comb begin : proc_counter + // default + core_tf_num_d[i] = core_tf_num_q[i]; + // increase + if (be_ready[i] & be_valid[i] & transf_descr[i].num_bytes != 0) begin + core_tf_num_d[i] = core_tf_num_d[i] + 1; + end + // decrement + if ((tf_head == i) & !tf_empty & trans_complete) begin + core_tf_num_d[i] = core_tf_num_d[i] - 1; + end + end + // assign output + assign no_req_pending_o[i] = core_tf_num_d[i] == 0; + end // gen_req_counters + + // generate registers for peripherals + pulp_cluster_frontend_regs #( + .transf_descr_t ( transf_descr_t ) + ) i_dma_conf_regs_periphs ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .ctrl_req_i ( ctrl_pe_targ_req_i ), + .ctrl_type_i ( ctrl_pe_targ_type_i ), + .ctrl_be_i ( ctrl_pe_targ_be_i ), + .ctrl_add_i ( ctrl_pe_targ_add_i ), + .ctrl_data_i ( ctrl_pe_targ_data_i ), + .ctrl_gnt_o ( ctrl_pe_targ_gnt_o ), + .ctrl_valid_o ( ctrl_pe_targ_r_valid_o ), + .ctrl_data_o ( ctrl_pe_targ_r_data_o ), + .next_id_i ( next_id ), + .done_id_i ( done_id ), + .be_ready_i ( be_ready [NumCores] ), + .be_valid_o ( be_valid [NumCores] ), + .be_busy_i ( busy_o ), + .transf_descr_o ( transf_descr [NumCores] ) + ); + + // set this to zero as it is done mchan + assign ctrl_pe_targ_r_opc_o = 1'b0; + + // round robin to arbitrate + rr_arb_tree #( + .NumIn ( NumRegs + 1 ), // +1 is the external unit + .DataWidth ( -1 ), + .DataType ( transf_descr_t ), + .ExtPrio ( 0 ), + .AxiVldRdy ( 1 ), + .LockIn ( 1 ) + ) i_rr_arb_tree ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .rr_i ( '0 ), + .req_i ( { dma_req_valid_i, be_valid } ), + .gnt_o ( { dma_req_ready_o, be_ready } ), + .data_i ( { dma_req_i, transf_descr } ), + .gnt_i ( be_ready_arb ), + .req_o ( be_valid_arb ), + .data_o ( transf_descr_arb ), + .idx_o ( pe_idx_arb ) + ); + + // global transfer id + transfer_id_gen #( + // keep this fixed at 32 bit as two 32 bit counters are + // relatively cheap + .ID_WIDTH ( 32 ) + ) i_transfer_id_gen ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .issue_i ( be_ready_arb & be_valid_arb & transf_descr_arb.num_bytes != 0 ), + .retire_i ( trans_complete ), + .next_o ( next_id ), + .completed_o ( done_id ) + ); + + // hold a bit for each launched transfer where it came from + fifo_v3 #( + .dtype ( logic [IdxWidth-1:0] ), + .DEPTH ( TfFifoDepth ) + ) i_tf_id_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( 1'b0 ), + .full_o ( ), + .empty_o ( tf_empty ), + .usage_o ( ), + .data_i ( pe_idx_arb ), // we are external tf + .push_i ( be_ready_arb & be_valid_arb & transf_descr_arb.num_bytes != 0 ), + .data_o ( tf_head ), + .pop_i ( trans_complete ) + ); + + assign dma_rsp_valid_o = (tf_head == NumRegs) & !tf_empty & trans_complete; + // ack external tf tf came from ext valid we are done :) + + //---------NON SYNTHESIZABLE --------------- + `ifndef VERILATOR + //pragma translate_off + // log dma transfers to disk + initial begin + @(posedge rst_ni); + $sformat(log_file_name, "DMA_TRANSFERS_%2h.log", cluster_id_i); + log_file = $fopen(log_file_name, "w"); + $fwrite(log_file, "queue_time pe_id tf_id src dst num_bytes launch_time completion_time\n"); + $fclose(log_file); + end + // datatype to store arbitrated tf + typedef struct packed { + longint queue_time; + longint pe_id; + longint next_id; + longint src; + longint dst; + longint len; + } queued_tf_t; + // launch tf + typedef struct packed { + queued_tf_t queued_tf; + longint launch_time; + } launched_tf_t; + // create queued tf + queued_tf_t queued_tf, queued_tf_head; + // pack queued tf + always_comb begin + queued_tf.queue_time = $time(); + queued_tf.pe_id = pe_idx_arb; + queued_tf.next_id = next_id; + queued_tf.src = transf_descr_arb.src_addr; + queued_tf.dst = transf_descr_arb.dst_addr; + queued_tf.len = transf_descr_arb.num_bytes; + end + // use a fifo to model queuing + fifo_v3 #( + .dtype ( queued_tf_t ), + .DEPTH ( TfReqFifoDepth ) + ) i_queue_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( 1'b0 ), + .full_o ( ), + .empty_o ( ), + .usage_o ( ), + .data_i ( queued_tf ), + .push_i ( be_valid_arb && be_ready_arb ), + .data_o ( queued_tf_head ), + .pop_i ( i_axi_dma_backend.burst_req_pop ) + ); + // launched tf + launched_tf_t launched_tf, launched_tf_head; + // pack launched tf + always_comb begin + launched_tf.queued_tf = queued_tf_head; + launched_tf.launch_time = $time(); + end + // use a fifo to hold tf info while it goes through the backend + fifo_v3 #( + .dtype ( launched_tf_t ), + .DEPTH ( AxiAxReqDepth + BufferDepth + 1 ) + ) i_launch_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i( 1'b0 ), + .full_o ( ), + .empty_o ( ), + .usage_o ( ), + .data_i ( launched_tf ), + .push_i ( i_axi_dma_backend.burst_req_pop ), + .data_o ( launched_tf_head ), + .pop_i ( trans_complete ) + ); + // write info to file + always @(posedge clk_i) begin + #0; + if(trans_complete) begin + log_file = $fopen(log_file_name, "a"); + $fwrite(log_file, "%0d %0d %0d 0x%0x 0x%0x %0d %0d %0d\n", + launched_tf_head.queued_tf.queue_time, launched_tf_head.queued_tf.pe_id, + launched_tf_head.queued_tf.next_id, launched_tf_head.queued_tf.src, + launched_tf_head.queued_tf.dst, launched_tf_head.queued_tf.len, + launched_tf_head.launch_time, $time() + ); + $fclose(log_file); + end + end + //pragma translate_on + `endif + //---------NON SYNTHESIZABLE --------------- + + // map arbitrated transfer descriptor onto generic burst request + always_comb begin : proc_map_to_1D_burst + burst_req = '0; + burst_req.src = transf_descr_arb.src_addr; + burst_req.dst = transf_descr_arb.dst_addr; + burst_req.num_bytes = transf_descr_arb.num_bytes; + burst_req.burst_src = axi_pkg::BURST_INCR; + burst_req.burst_dst = axi_pkg::BURST_INCR; + burst_req.decouple_rw = transf_descr_arb.decouple; + burst_req.deburst = transf_descr_arb.deburst; + burst_req.serialize = transf_descr_arb.serialize; + end + + // instantiate backend :) + axi_dma_backend #( + .DataWidth ( DmaDataWidth ), + .AddrWidth ( DmaAddrWidth ), + .IdWidth ( DmaAxiIdWidth ), + .AxReqFifoDepth ( AxiAxReqDepth ), + .TransFifoDepth ( TfReqFifoDepth ), + .BufferDepth ( BufferDepth ), // minimal 3 for giving full performance + .axi_req_t ( axi_req_t ), + .axi_res_t ( axi_res_t ), + .burst_req_t ( burst_req_t ), + .DmaIdWidth ( 6 ), + .DmaTracing ( 0 ) + ) i_axi_dma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .dma_id_i ( cluster_id_i ), + .axi_dma_req_o ( axi_dma_req_o ), + .axi_dma_res_i ( axi_dma_res_i ), + .burst_req_i ( burst_req ), + .valid_i ( be_valid_arb ), + .ready_o ( be_ready_arb ), + .backend_idle_o ( be_idle ), + .trans_complete_o ( trans_complete ) + ); + + // busy if not idle + assign busy_o = ~be_idle; + + // interrupts and events (unconditionally) + assign term_event_o = trans_complete ? '1 : '0; + assign term_irq_o = trans_complete ? '1 : '0; + assign term_event_pe_o = trans_complete ? '1 : '0; + assign term_irq_pe_o = trans_complete ? '1 : '0; + + // keep id for peripherals + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_id_peripherals + if(~rst_ni) begin + peripherals_id_q <= 0; + core_tf_num_q <= 0; + end else begin + peripherals_id_q <= ctrl_pe_targ_id_i; + core_tf_num_q <= core_tf_num_d; + end + end + + // id is returned + assign ctrl_pe_targ_r_id_o = peripherals_id_q; + +endmodule : pulp_cluster_frontend diff --git a/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend_regs.sv b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend_regs.sv new file mode 100644 index 0000000..bd3de44 --- /dev/null +++ b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend_regs.sv @@ -0,0 +1,205 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +// register file for one pe in the pulp_cluster_frontend +// strictly 32 bit on TCDM side. + +module pulp_cluster_frontend_regs #( + parameter type transf_descr_t = logic +)( + input logic clk_i, + input logic rst_ni, + // tcdm forwards channel + input logic ctrl_req_i, + input logic ctrl_type_i, + input logic [3:0] ctrl_be_i, + input logic [31:0] ctrl_add_i, + input logic [31:0] ctrl_data_i, + output logic ctrl_gnt_o, + // return channel + output logic ctrl_valid_o, + output logic [31:0] ctrl_data_o, + // transfer ids + input logic [31:0] next_id_i, + input logic [31:0] done_id_i, + // backend handshake + input logic be_ready_i, + output logic be_valid_o, + input logic be_busy_i, + output transf_descr_t transf_descr_o +); + + // DMA transfer descriptor + typedef struct packed { + logic [31:0] num_bytes; + logic [31:0] dst_addr; + logic [31:0] src_addr; + } transf_descr_regular_t; + + // data stored + typedef union packed { + logic [2:0][31:0] words; + logic [2:0][ 3:0][7:0] bytes; + transf_descr_regular_t transfer; + } dma_data_store_t; + + // have 8 registers per PE + logic [5:0] reg_addr; + // 6 registers are r/w so we need to keep a state + dma_data_store_t data_store_d, data_store_q; + logic [2:0] conf_store_d, conf_store_q; + // data is delayed one cycle + logic [31:0] rdata_d, rdata_q; + logic valid_d, valid_q; + + // assign address to register address + assign reg_addr = ctrl_add_i[5:0]; + + // address decode + always_comb begin : proc_address_decode + + // defaults + ctrl_gnt_o = 1'b0; + rdata_d = '0; + valid_d = 1'b0; + be_valid_o = 1'b0; + data_store_d = data_store_q; + conf_store_d = conf_store_q; + + // if we have access + if (ctrl_req_i) begin + + // only grant if a request is here + ctrl_gnt_o = 1'b1; + + // address decoding + case(reg_addr) + // source address (low) + 6'h00 : begin + valid_d = 1'b1; + if (ctrl_type_i) begin // read + rdata_d = data_store_q.words[0]; + end else begin // write + for (int i = 0; i < 4; i++) begin + if (ctrl_be_i[i]) + data_store_d.bytes[0][i] = ctrl_data_i[8 * i +: 8]; + end + end + end + //// source address (high) + //6'h04 : begin + // valid_d = 1'b1; + // if (ctrl_type_i) begin // read + // rdata_d = data_store_q.words[1]; + // end else begin // write + // for (int i = 0; i < 4; i++) begin + // if (ctrl_be_i[i]) + // data_store_d.bytes[1][i] = ctrl_data_i[8 * i +: 8]; + // end + // end + //end + // destination address (low) + 6'h08 : begin + valid_d = 1'b1; + if (ctrl_type_i) begin // read + rdata_d = data_store_q.words[1]; + end else begin // write + for (int i = 0; i < 4; i++) begin + if (ctrl_be_i[i]) + data_store_d.bytes[1][i] = ctrl_data_i[8 * i +: 8]; + end + end + end + //// destination address (high) + //6'h0c : begin + // valid_d = 1'b1; + // if (ctrl_type_i) begin // read + // rdata_d = data_store_q.words[3]; + // end else begin // write + // for (int i = 0; i < 4; i++) begin + // if (ctrl_be_i[i]) + // data_store_d.bytes[3][i] = ctrl_data_i[8 * i +: 8]; + // end + // end + //end + // num bytes + 6'h10 : begin + valid_d = 1'b1; + if (ctrl_type_i) begin // read + rdata_d = data_store_q.words[2]; + end else begin // write + for (int i = 0; i < 4; i++) begin + if (ctrl_be_i[i]) + data_store_d.bytes[2][i] = ctrl_data_i[8 * i +: 8]; + end + end + end + // next_id + 6'h18 : begin + valid_d = be_ready_i; + if (ctrl_type_i) begin // read + ctrl_gnt_o = be_ready_i; + rdata_d = next_id_i; + be_valid_o = 1'b1; + end + end + // completed id + 6'h20 : begin + valid_d = 1'b1; + if (ctrl_type_i) begin // read + rdata_d = done_id_i; + end + end + // status / conf + 6'h28 : begin + valid_d = 1'b1; + if (ctrl_type_i) begin // read + rdata_d = {15'h0000, be_busy_i, 13'h0000, conf_store_q}; + end else begin // write + conf_store_d = ctrl_data_i[2:0]; + end + end + // default case + default : begin + rdata_d = '0; + valid_d = 1'b1; + end + endcase + end + end + + // data store + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_data_store + if(~rst_ni) begin + data_store_q <= '0; + conf_store_q <= 3'b001; + rdata_q <= '0; + valid_q <= '0; + end else begin + data_store_q <= data_store_d; + conf_store_q <= conf_store_d; + rdata_q <= rdata_d; + valid_q <= valid_d; + end + end + + assign ctrl_valid_o = valid_q; + assign ctrl_data_o = rdata_q; + + assign transf_descr_o.num_bytes = data_store_q.transfer.num_bytes; + assign transf_descr_o.dst_addr = data_store_q.transfer.dst_addr; + assign transf_descr_o.src_addr = data_store_q.transfer.src_addr; + assign transf_descr_o.decouple = conf_store_q[0]; + assign transf_descr_o.deburst = conf_store_q[1]; + assign transf_descr_o.serialize = conf_store_q[2]; + +endmodule : pulp_cluster_frontend_regs diff --git a/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/transfer_id_gen.sv b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/transfer_id_gen.sv new file mode 100644 index 0000000..2fa6008 --- /dev/null +++ b/hw/deps/axi/src/dma/frontends/pulp_cluster_frontend/src/transfer_id_gen.sv @@ -0,0 +1,58 @@ +// Copyright (c) 2020 ETH Zurich and 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. +// +// Thomas Benz + +// transaction id generator. just increase the transaction id on every request + +module transfer_id_gen #( + parameter int unsigned ID_WIDTH = -1 +) ( + input logic clk_i, + input logic rst_ni, + // new request is pushed + input logic issue_i, + // request is popped + input logic retire_i, + // next id is + output logic [ID_WIDTH-1:0] next_o, + // last id completed is + output logic [ID_WIDTH-1:0] completed_o +); + + //-------------------------------------- + // counters + //-------------------------------------- + logic [ID_WIDTH-1:0] next_d, next_q; + logic [ID_WIDTH-1:0] completed_d, completed_q; + + // count up on events + assign next_d = (issue_i == 1'b1) ? next_q + 'h1 : next_q; + assign completed_d = (retire_i == 1'b1) ? completed_q + 'h1 : completed_q; + + // assign outputs + assign next_o = next_q; + assign completed_o = completed_q; + + //-------------------------------------- + // state + //-------------------------------------- + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_id_gen + if(~rst_ni) begin + next_q <= 1; + completed_q <= 0; + end else begin + next_q <= next_d; + completed_q <= completed_d; + end + end + +endmodule : transfer_id_gen + diff --git a/hw/deps/axi2apb/src/axi2apb_64_32.sv b/hw/deps/axi2apb/src/axi2apb_64_32.sv new file mode 100644 index 0000000..7c7343b --- /dev/null +++ b/hw/deps/axi2apb/src/axi2apb_64_32.sv @@ -0,0 +1,756 @@ +// Copyright 2014-2018 ETH Zurich and 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. +// +// Igor Loi +// Davide Rossi +// Florian Zaruba + +`define OKAY 2'b00 +`define EXOKAY 2'b01 +`define SLVERR 2'b10 +`define DECERR 2'b11 + +module axi2apb_64_32 #( + parameter int unsigned AXI4_ADDRESS_WIDTH = 32, + parameter int unsigned AXI4_RDATA_WIDTH = 64, + parameter int unsigned AXI4_WDATA_WIDTH = 64, + parameter int unsigned AXI4_ID_WIDTH = 16, + parameter int unsigned AXI4_USER_WIDTH = 10, + parameter int unsigned AXI_NUMBYTES = AXI4_WDATA_WIDTH/8, + + parameter int unsigned BUFF_DEPTH_SLAVE = 4, + parameter int unsigned APB_NUM_SLAVES = 8, + parameter int unsigned APB_ADDR_WIDTH = 12 +) +( + input logic ACLK, + input logic ARESETn, + input logic test_en_i, + // --------------------------------------------------------- + // AXI TARG Port Declarations ------------------------------ + // --------------------------------------------------------- + //AXI write address bus -------------- // USED// ----------- + input logic [AXI4_ID_WIDTH-1:0] AWID_i , + input logic [AXI4_ADDRESS_WIDTH-1:0] AWADDR_i , + input logic [ 7:0] AWLEN_i , + input logic [ 2:0] AWSIZE_i , + input logic [ 1:0] AWBURST_i , + input logic AWLOCK_i , + input logic [ 3:0] AWCACHE_i , + input logic [ 2:0] AWPROT_i , + input logic [ 3:0] AWREGION_i , + input logic [ 5:0] AWATOP_i , + input logic [ AXI4_USER_WIDTH-1:0] AWUSER_i , + input logic [ 3:0] AWQOS_i , + input logic AWVALID_i , + output logic AWREADY_o , + // --------------------------------------------------------- + + //AXI write data bus -------------- // USED// -------------- + input logic [AXI_NUMBYTES-1:0][7:0] WDATA_i , + input logic [AXI_NUMBYTES-1:0] WSTRB_i , + input logic WLAST_i , + input logic [AXI4_USER_WIDTH-1:0] WUSER_i , + input logic WVALID_i , + output logic WREADY_o , + // --------------------------------------------------------- + + //AXI write response bus -------------- // USED// ---------- + output logic [AXI4_ID_WIDTH-1:0] BID_o , + output logic [ 1:0] BRESP_o , + output logic BVALID_o , + output logic [AXI4_USER_WIDTH-1:0] BUSER_o , + input logic BREADY_i , + // --------------------------------------------------------- + + //AXI read address bus ------------------------------------- + input logic [AXI4_ID_WIDTH-1:0] ARID_i , + input logic [AXI4_ADDRESS_WIDTH-1:0] ARADDR_i , + input logic [ 7:0] ARLEN_i , + input logic [ 2:0] ARSIZE_i , + input logic [ 1:0] ARBURST_i , + input logic ARLOCK_i , + input logic [ 3:0] ARCACHE_i , + input logic [ 2:0] ARPROT_i , + input logic [ 3:0] ARREGION_i , + input logic [ AXI4_USER_WIDTH-1:0] ARUSER_i , + input logic [ 3:0] ARQOS_i , + input logic ARVALID_i , + output logic ARREADY_o , + // --------------------------------------------------------- + + //AXI read data bus ---------------------------------------- + output logic [AXI4_ID_WIDTH-1:0] RID_o , + output logic [AXI4_RDATA_WIDTH-1:0] RDATA_o , + output logic [ 1:0] RRESP_o , + output logic RLAST_o , + output logic [AXI4_USER_WIDTH-1:0] RUSER_o , + output logic RVALID_o , + input logic RREADY_i , + // --------------------------------------------------------- + + output logic PENABLE , + output logic PWRITE , + output logic [APB_ADDR_WIDTH-1:0] PADDR , + output logic PSEL , + output logic [31:0] PWDATA , + input logic [31:0] PRDATA , + input logic PREADY , + input logic PSLVERR +); + + // -------------------- + // AXI write address bus + // -------------------- + logic [AXI4_ID_WIDTH-1:0] AWID; + logic [AXI4_ADDRESS_WIDTH-1:0] AWADDR; + logic [ 7:0] AWLEN; + logic [ 2:0] AWSIZE; + logic [ 1:0] AWBURST; + logic AWLOCK; + logic [ 3:0] AWCACHE; + logic [ 2:0] AWPROT; + logic [ 3:0] AWREGION; + logic [ AXI4_USER_WIDTH-1:0] AWUSER; + logic [ 3:0] AWQOS; + logic AWVALID; + logic AWREADY; + // -------------------- + // AXI write data bus + // -------------------- + logic [1:0][31:0] WDATA; // from FIFO + logic [AXI_NUMBYTES-1:0] WSTRB; // from FIFO + logic WLAST; // from FIFO + logic [AXI4_USER_WIDTH-1:0] WUSER; // from FIFO + logic WVALID; // from FIFO + logic WREADY; // TO FIFO + // -------------------- + // AXI write response bus + // -------------------- + logic [AXI4_ID_WIDTH-1:0] BID; + logic [ 1:0] BRESP; + logic BVALID; + logic [AXI4_USER_WIDTH-1:0] BUSER; + logic BREADY; + // -------------------- + // AXI read address bus + // -------------------- + logic [AXI4_ID_WIDTH-1:0] ARID; + logic [AXI4_ADDRESS_WIDTH-1:0] ARADDR; + logic [ 7:0] ARLEN; + logic [ 2:0] ARSIZE; + logic [ 1:0] ARBURST; + logic ARLOCK; + logic [ 3:0] ARCACHE; + logic [ 2:0] ARPROT; + logic [ 3:0] ARREGION; + logic [ AXI4_USER_WIDTH-1:0] ARUSER; + logic [ 3:0] ARQOS; + logic ARVALID; + logic ARREADY; + // -------------------- + // AXI read data bus + // -------------------- + logic [AXI4_ID_WIDTH-1:0] RID; + logic [1:0][31:0] RDATA; + logic [ 1:0] RRESP; + logic RLAST; + logic [AXI4_USER_WIDTH-1:0] RUSER; + logic RVALID; + logic RREADY; + + enum logic [3:0] { IDLE, + SINGLE_RD, SINGLE_RD_64, + BURST_RD_1, BURST_RD, BURST_RD_64, + BURST_WR, BURST_WR_64, + SINGLE_WR,SINGLE_WR_64, + WAIT_R_PREADY, WAIT_W_PREADY + } CS, NS; + + logic W_word_sel; + + logic [APB_ADDR_WIDTH-1:0] address; + + logic read_req; + logic write_req; + + logic sample_AR; + logic [8:0] ARLEN_Q; + logic decr_ARLEN; + + logic sample_AW; + logic [8:0] AWLEN_Q; + logic decr_AWLEN; + + logic [AXI4_ADDRESS_WIDTH-1:0] ARADDR_Q; + logic incr_ARADDR; + + logic [AXI4_ADDRESS_WIDTH-1:0] AWADDR_Q; + logic incr_AWADDR; + + logic sample_RDATA_0; // sample the first 32 bit chunk to be aggregated in 64 bit rdata + logic sample_RDATA_1; // sample the second 32 bit chunk to be aggregated in 64 bit rdata + logic [31:0] RDATA_Q_0; + logic [31:0] RDATA_Q_1; + + assign PENABLE = write_req | read_req; + assign PWRITE = write_req; + assign PADDR = address[APB_ADDR_WIDTH-1:0]; + + assign PWDATA = WDATA[W_word_sel]; + assign PSEL = 1'b1; + + // AXI WRITE ADDRESS CHANNEL BUFFER + axi_aw_buffer #( + .ID_WIDTH ( AXI4_ID_WIDTH ), + .ADDR_WIDTH ( AXI4_ADDRESS_WIDTH ), + .USER_WIDTH ( AXI4_USER_WIDTH ), + .BUFFER_DEPTH ( BUFF_DEPTH_SLAVE ) + ) slave_aw_buffer_i ( + .clk_i ( ACLK ), + .rst_ni ( ARESETn ), + .test_en_i ( test_en_i ), + .slave_valid_i ( AWVALID_i ), + .slave_addr_i ( AWADDR_i ), + .slave_prot_i ( AWPROT_i ), + .slave_region_i ( AWREGION_i ), + .slave_atop_i ( '0 ), + .slave_len_i ( AWLEN_i ), + .slave_size_i ( AWSIZE_i ), + .slave_burst_i ( AWBURST_i ), + .slave_lock_i ( AWLOCK_i ), + .slave_cache_i ( AWCACHE_i ), + .slave_qos_i ( AWQOS_i ), + .slave_id_i ( AWID_i ), + .slave_user_i ( AWUSER_i ), + .slave_ready_o ( AWREADY_o ), + .master_valid_o ( AWVALID ), + .master_addr_o ( AWADDR ), + .master_prot_o ( AWPROT ), + .master_region_o ( AWREGION ), + .master_atop_o ( ), + .master_len_o ( AWLEN ), + .master_size_o ( AWSIZE ), + .master_burst_o ( AWBURST ), + .master_lock_o ( AWLOCK ), + .master_cache_o ( AWCACHE ), + .master_qos_o ( AWQOS ), + .master_id_o ( AWID ), + .master_user_o ( AWUSER ), + .master_ready_i ( AWREADY ) + ); + // AXI WRITE ADDRESS CHANNEL BUFFER + axi_ar_buffer #( + .ID_WIDTH ( AXI4_ID_WIDTH ), + .ADDR_WIDTH ( AXI4_ADDRESS_WIDTH ), + .USER_WIDTH ( AXI4_USER_WIDTH ), + .BUFFER_DEPTH ( BUFF_DEPTH_SLAVE ) + ) slave_ar_buffer_i ( + .clk_i ( ACLK ), + .rst_ni ( ARESETn ), + .test_en_i ( test_en_i ), + .slave_valid_i ( ARVALID_i ), + .slave_addr_i ( ARADDR_i ), + .slave_prot_i ( ARPROT_i ), + .slave_region_i ( ARREGION_i ), + .slave_len_i ( ARLEN_i ), + .slave_size_i ( ARSIZE_i ), + .slave_burst_i ( ARBURST_i ), + .slave_lock_i ( ARLOCK_i ), + .slave_cache_i ( ARCACHE_i ), + .slave_qos_i ( ARQOS_i ), + .slave_id_i ( ARID_i ), + .slave_user_i ( ARUSER_i ), + .slave_ready_o ( ARREADY_o ), + .master_valid_o ( ARVALID ), + .master_addr_o ( ARADDR ), + .master_prot_o ( ARPROT ), + .master_region_o ( ARREGION ), + .master_len_o ( ARLEN ), + .master_size_o ( ARSIZE ), + .master_burst_o ( ARBURST ), + .master_lock_o ( ARLOCK ), + .master_cache_o ( ARCACHE ), + .master_qos_o ( ARQOS ), + .master_id_o ( ARID ), + .master_user_o ( ARUSER ), + .master_ready_i ( ARREADY ) + ); + axi_w_buffer #( + .DATA_WIDTH ( AXI4_WDATA_WIDTH ), + .USER_WIDTH ( AXI4_USER_WIDTH ), + .BUFFER_DEPTH ( BUFF_DEPTH_SLAVE ) + ) slave_w_buffer_i ( + .clk_i ( ACLK ), + .rst_ni ( ARESETn ), + .test_en_i ( test_en_i ), + .slave_valid_i ( WVALID_i ), + .slave_data_i ( WDATA_i ), + .slave_strb_i ( WSTRB_i ), + .slave_user_i ( WUSER_i ), + .slave_last_i ( WLAST_i ), + .slave_ready_o ( WREADY_o ), + .master_valid_o ( WVALID ), + .master_data_o ( WDATA ), + .master_strb_o ( WSTRB ), + .master_user_o ( WUSER ), + .master_last_o ( WLAST ), + .master_ready_i ( WREADY ) + ); + axi_r_buffer #( + .ID_WIDTH ( AXI4_ID_WIDTH ), + .DATA_WIDTH ( AXI4_RDATA_WIDTH ), + .USER_WIDTH ( AXI4_USER_WIDTH ), + .BUFFER_DEPTH ( BUFF_DEPTH_SLAVE ) + ) slave_r_buffer_i ( + .clk_i ( ACLK ), + .rst_ni ( ARESETn ), + .test_en_i ( test_en_i ), + .slave_valid_i ( RVALID ), + .slave_data_i ( RDATA ), + .slave_resp_i ( RRESP ), + .slave_user_i ( RUSER ), + .slave_id_i ( RID ), + .slave_last_i ( RLAST ), + .slave_ready_o ( RREADY ), + .master_valid_o ( RVALID_o ), + .master_data_o ( RDATA_o ), + .master_resp_o ( RRESP_o ), + .master_user_o ( RUSER_o ), + .master_id_o ( RID_o ), + .master_last_o ( RLAST_o ), + .master_ready_i ( RREADY_i ) + ); + + axi_b_buffer #( + .ID_WIDTH ( AXI4_ID_WIDTH ), + .USER_WIDTH ( AXI4_USER_WIDTH ), + .BUFFER_DEPTH ( BUFF_DEPTH_SLAVE ) + ) slave_b_buffer_i ( + .clk_i ( ACLK ), + .rst_ni ( ARESETn ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( BVALID ), + .slave_resp_i ( BRESP ), + .slave_id_i ( BID ), + .slave_user_i ( BUSER ), + .slave_ready_o ( BREADY ), + + .master_valid_o ( BVALID_o ), + .master_resp_o ( BRESP_o ), + .master_id_o ( BID_o ), + .master_user_o ( BUSER_o ), + .master_ready_i ( BREADY_i ) + ); + + always_comb begin + read_req = 1'b0; + write_req = 1'b0; + W_word_sel = 1'b0; // Write Word Selector + + sample_AW = 1'b0; + decr_AWLEN = 1'b0; + sample_AR = 1'b0; + decr_ARLEN = 1'b0; + + incr_AWADDR = 1'b0; + incr_ARADDR = 1'b0; + + sample_RDATA_0 = 1'b0; + sample_RDATA_1 = 1'b0; + + ARREADY = 1'b0; + AWREADY = 1'b0; + WREADY = 1'b0; + RDATA = '0; + + BVALID = 1'b0; + BRESP = `OKAY; + BID = AWID; + BUSER = AWUSER; + + RVALID = 1'b0; + RLAST = 1'b0; + RID = ARID; + RUSER = ARUSER; + RRESP = `OKAY; + + case(CS) + + WAIT_R_PREADY: begin + sample_AR = 1'b0; + read_req = 1'b1; + address = ARADDR; + + if (PREADY == 1'b1) begin// APB is READY --> RDATA is AVAILABLE + if (ARLEN == 0) begin + case (ARSIZE) + 3'h3: begin + NS = SINGLE_RD_64; + if (ARADDR[2:0] == 3'h4) + sample_RDATA_1 = 1'b1; + else sample_RDATA_0 = 1'b1; + end + + default: begin + NS = SINGLE_RD; + if (ARADDR[2:0] == 3'h4) + sample_RDATA_1 = 1'b1; + else + sample_RDATA_0 = 1'b1; + end + endcase + end else begin // ARLEN > 0 --> BURST + NS = BURST_RD_64; + sample_RDATA_0 = 1'b1; + decr_ARLEN = 1'b1; + incr_ARADDR = 1'b1; + end + end else begin // APB not ready + NS = WAIT_R_PREADY; + end + end + + WAIT_W_PREADY: begin + address = AWADDR; + write_req = 1'b1; + + if (AWADDR[2:0] == 3'h4) + W_word_sel = 1'b1; + else + W_word_sel = 1'b0; + + // There is a Pending WRITE!! + if (PREADY == 1'b1) begin // APB is READY --> WDATA is LAtched + if (AWLEN == 0) begin // single write + case (AWSIZE) + 3'h3: NS = SINGLE_WR_64; + default: NS = SINGLE_WR; + endcase + end else begin // BURST WRITE + sample_AW = 1'b1; + NS = BURST_WR_64; + end + end else begin // APB not READY + NS = WAIT_W_PREADY; + end + end + + IDLE: begin + if (ARVALID == 1'b1) begin + sample_AR = 1'b1; + read_req = 1'b1; + address = ARADDR; + + if (PREADY == 1'b1) begin // APB is READY --> RDATA is AVAILABLE + if (ARLEN == 0) begin + case (ARSIZE) + 3'h3: begin + NS = SINGLE_RD_64; + if (ARADDR[2:0] == 4) + sample_RDATA_1 = 1'b1; + else + sample_RDATA_0 = 1'b1; + end + default: begin + NS = SINGLE_RD; + if (ARADDR[2:0] == 4) + sample_RDATA_1 = 1'b1; + else + sample_RDATA_0 = 1'b1; + end + endcase end else begin //ARLEN > 0 --> BURST + NS = BURST_RD_64; + sample_RDATA_0 = 1'b1; + end + end else begin // APB not ready + NS = WAIT_R_PREADY; + end + end else begin + + if (AWVALID) begin //: _VALID_AW_REQ_ + if (WVALID) begin // : _VALID_W_REQ_ + write_req = 1'b1; + address = AWADDR; + + if (AWADDR[2:0] == 3'h4) + W_word_sel = 1'b1; + else + W_word_sel = 1'b0; + + // There is a Pending WRITE!! + if (PREADY == 1'b1) begin// APB is READY --> WDATA is LAtched _APB_SLAVE_READY_ + if(AWLEN == 0) begin //: _SINGLE_WRITE_ + case(AWSIZE) + 3'h3: NS = SINGLE_WR_64; + default: NS = SINGLE_WR; + endcase + end else begin // BURST WRITE + sample_AW = 1'b1; + if ((AWADDR[2:0] == 3'h4) && (WSTRB[7:4] == 0)) + incr_AWADDR = 1'b0; + else + incr_AWADDR = 1'b1; + NS = BURST_WR_64; + end + end else begin// APB not READY + NS = WAIT_W_PREADY; + end + end else begin // GOT ADDRESS WRITE, not DATA + write_req = 1'b0; + address = '0; + NS = IDLE; + end + end else begin// No requests + NS = IDLE; + address = '0; + end + end + end + + SINGLE_WR_64: begin + address = AWADDR + 4; + W_word_sel = 1'b1; // write the Second data chunk + write_req = WVALID; + if (WVALID) begin + if (PREADY == 1'b1) + NS = SINGLE_WR; + else + NS = SINGLE_WR_64; + end else begin + NS = SINGLE_WR_64; + end + end + + SINGLE_WR: begin + BVALID = 1'b1; + address = '0; + if (BREADY) begin + NS = IDLE; + AWREADY = 1'b1; + WREADY = 1'b1; + end else begin + NS = SINGLE_WR; + end + end + + BURST_WR_64: begin + W_word_sel = 1'b1; // write the Second data chunk first + write_req = WVALID & (|WSTRB[7:4]); + address = AWADDR_Q; // second Chunk, Fixzed Burst + + if (WVALID) begin + if (&WSTRB[7:4]) begin + if(PREADY == 1'b1) begin + NS = BURST_WR; + WREADY = 1'b1; // pop onother data from the WDATA fifo + decr_AWLEN = 1'b1; // decrement the remaining BURST beat + incr_AWADDR = 1'b1; // increment address + end else begin + NS = BURST_WR_64; + end + end else begin + NS = BURST_WR; + WREADY = 1'b1; // pop onother data from the WDATA fifo + decr_AWLEN = 1'b1; // decrement the remaining BURST beat + incr_AWADDR = 1'b1; // increment address + end + end else begin + NS = BURST_WR_64; + end + end + + BURST_WR: begin + address = AWADDR_Q; // second Chunk, Fixzed Burst + if (AWLEN_Q == 0) begin // last : _BURST_COMPLETED_ + BVALID = 1'b1; + if (BREADY) begin + NS = IDLE; + AWREADY = 1'b1; + end else + NS = BURST_WR; + end else begin //: _BUSRST_NOT_COMPLETED_ + W_word_sel = 1'b0; // write the Second data chunk first + write_req = WVALID & (&WSTRB[3:0]); + if (WVALID) begin + if (PREADY == 1'b1) begin + NS = BURST_WR_64; + incr_AWADDR = 1'b1; + decr_AWLEN = 1'b1; //decrement the remaining BURST beat + end else + NS = BURST_WR; + end else begin + NS = BURST_WR_64; + end + end + end + + BURST_RD_64: begin + read_req = 1'b1; + address = ARADDR_Q; + + if (ARLEN_Q == 0) begin // burst completed + NS = IDLE; + ARREADY = 1'b1; + end else begin + if (PREADY == 1'b1) begin // APB is READY --> RDATA is AVAILABLE + decr_ARLEN = 1'b1; + sample_RDATA_1 = 1'b1; + NS = BURST_RD; + + if (ARADDR_Q[2:0] == 3'h4) + incr_ARADDR = 1'b1; + else + incr_ARADDR = 1'b0; + end + else begin + NS = BURST_RD_64; + end + end + end + + BURST_RD: begin + RVALID = 1'b1; + RDATA[0] = RDATA_Q_0; + RDATA[1] = RDATA_Q_1; + RLAST = (ARLEN_Q == 0) ? 1'b1 : 1'b0; + address = ARADDR_Q; + + if (RREADY) begin // ready to send back the rdata + if (ARLEN_Q == 0) begin // burst completed + NS = IDLE; + ARREADY = 1'b1; + end else begin //: _READ_BUSRST_NOT_COMPLETED_ + read_req = 1'b1; + if (PREADY == 1'b1) begin // APB is READY --> RDATA is AVAILABLE + sample_RDATA_0 = 1'b1; + NS = BURST_RD_64; + incr_ARADDR = 1'b1; + decr_ARLEN = 1'b1; + end else begin + NS = BURST_RD_1; + end + end + end else begin // NOT ready to send back the rdata + NS = BURST_RD; + end + end + + BURST_RD_1: begin + read_req = 1'b1; + address = ARADDR_Q; + + if (PREADY == 1'b1) begin // APB is READY --> RDATA is AVAILABLE + sample_RDATA_0 = 1'b1; + NS = BURST_RD_64; + incr_ARADDR = 1'b1; + decr_ARLEN = 1'b1; + end else begin + NS = BURST_RD_1; + end + end + + SINGLE_RD: begin + RVALID = 1'b1; + RDATA[0] = RDATA_Q_0; + RDATA[1] = RDATA_Q_1; + RLAST = 1; + address = '0; + + if (RREADY) begin // ready to send back the rdata + NS = IDLE; + ARREADY = 1'b1; + end else begin // NOT ready to send back the rdata + NS = SINGLE_RD; + end + end + + SINGLE_RD_64: begin + read_req = 1'b1; + address = ARADDR + 4; + if (PREADY == 1'b1) begin // APB is READY --> RDATA is AVAILABLE + NS = SINGLE_RD; + if(ARADDR[2:0] == 3'h4) + sample_RDATA_0 = 1'b1; + else + sample_RDATA_1 = 1'b1; + end else begin + NS = SINGLE_RD_64; + end + end + + default: begin + NS = IDLE; + address = '0; + end + endcase + end + + // ----------- + // Registers + // ----------- + always_ff @(posedge ACLK, negedge ARESETn) begin + if (ARESETn == 1'b0) begin + CS <= IDLE; + //Read Channel + ARLEN_Q <= '0; + AWADDR_Q <= '0; + //Write Channel + AWLEN_Q <= '0; + RDATA_Q_0 <= '0; + RDATA_Q_1 <= '0; + ARADDR_Q <= '0; + end else begin + CS <= NS; + + if (sample_AR) begin + ARLEN_Q <= {ARLEN,1'b0} + 2; + end else if (decr_ARLEN) begin + ARLEN_Q <= ARLEN_Q - 1; + end + + if (sample_RDATA_0) + RDATA_Q_0 <= PRDATA; + + if (sample_RDATA_1) + RDATA_Q_1 <= PRDATA; + + case ({sample_AW, decr_AWLEN}) + 2'b00: AWLEN_Q <= AWLEN_Q; + 2'b01: AWLEN_Q <= AWLEN_Q - 1; + 2'b10: AWLEN_Q <= {AWLEN, 1'b0} + 1; + 2'b11: AWLEN_Q <= {AWLEN, 1'b0}; + endcase + + case ({sample_AW, incr_AWADDR}) + 2'b00: AWADDR_Q <= AWADDR_Q; + 2'b01: AWADDR_Q <= AWADDR_Q + 4; + 2'b10: AWADDR_Q <= {AWADDR[AXI4_ADDRESS_WIDTH-1:3], 3'b000}; + 2'b11: AWADDR_Q <= {AWADDR[AXI4_ADDRESS_WIDTH-1:3], 3'b000} + 4; + endcase + + case({sample_AR, incr_ARADDR}) + 2'b00: ARADDR_Q <= ARADDR_Q; + 2'b01: ARADDR_Q <= ARADDR_Q + 4; + 2'b10: ARADDR_Q <= {ARADDR[AXI4_ADDRESS_WIDTH-1:3], 3'b000}; + 2'b11: ARADDR_Q <= {ARADDR[AXI4_ADDRESS_WIDTH-1:3], 3'b000} + 4; + endcase + end + end + + `ifndef VERILATOR + //pragma translate_off + assert property (@(posedge ACLK) (ARESETn && AWVALID_i |-> AWATOP_i == '0)) + else $error("This module does not support atomic operations!"); + //pragma translate_on + `endif + +endmodule diff --git a/hw/deps/axi2apb/src/axi2apb_wrap.sv b/hw/deps/axi2apb/src/axi2apb_wrap.sv new file mode 100644 index 0000000..8ccde3a --- /dev/null +++ b/hw/deps/axi2apb/src/axi2apb_wrap.sv @@ -0,0 +1,180 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +module axi2apb_wrap #( + parameter int unsigned AXI_ADDR_WIDTH = 32, + parameter int unsigned AXI_DATA_WIDTH = 32, + parameter int unsigned AXI_USER_WIDTH = 6, + parameter int unsigned AXI_ID_WIDTH = 6, + parameter int unsigned APB_ADDR_WIDTH = 32, + parameter int unsigned APB_DATA_WIDTH = 32 +)( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + AXI_BUS.Slave axi_slave, + APB_BUS.Master apb_master +); + + // ---------------- + // AXI2APB WRAPER + // ---------------- + generate if (AXI_DATA_WIDTH == APB_DATA_WIDTH) begin + axi2apb #( + .AXI4_ADDRESS_WIDTH ( AXI_ADDR_WIDTH ), + .AXI4_RDATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI4_WDATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI4_ID_WIDTH ( AXI_ID_WIDTH ), + .AXI4_USER_WIDTH ( AXI_USER_WIDTH ), + + .BUFF_DEPTH_SLAVE ( 2 ), + .APB_ADDR_WIDTH ( APB_ADDR_WIDTH ) + ) axi2apb_i ( + .ACLK ( clk_i ), + .ARESETn ( rst_ni ), + .test_en_i ( test_en_i ), + + .AWID_i ( axi_slave.aw_id ), + .AWADDR_i ( axi_slave.aw_addr ), + .AWLEN_i ( axi_slave.aw_len ), + .AWSIZE_i ( axi_slave.aw_size ), + .AWBURST_i ( axi_slave.aw_burst ), + .AWLOCK_i ( axi_slave.aw_lock ), + .AWCACHE_i ( axi_slave.aw_cache ), + .AWPROT_i ( axi_slave.aw_prot ), + .AWREGION_i ( axi_slave.aw_region ), + .AWATOP_i ( axi_slave.aw_atop ), + .AWUSER_i ( axi_slave.aw_user ), + .AWQOS_i ( axi_slave.aw_qos ), + .AWVALID_i ( axi_slave.aw_valid ), + .AWREADY_o ( axi_slave.aw_ready ), + + .WDATA_i ( axi_slave.w_data ), + .WSTRB_i ( axi_slave.w_strb ), + .WLAST_i ( axi_slave.w_last ), + .WUSER_i ( axi_slave.w_user ), + .WVALID_i ( axi_slave.w_valid ), + .WREADY_o ( axi_slave.w_ready ), + + .BID_o ( axi_slave.b_id ), + .BRESP_o ( axi_slave.b_resp ), + .BVALID_o ( axi_slave.b_valid ), + .BUSER_o ( axi_slave.b_user ), + .BREADY_i ( axi_slave.b_ready ), + + .ARID_i ( axi_slave.ar_id ), + .ARADDR_i ( axi_slave.ar_addr ), + .ARLEN_i ( axi_slave.ar_len ), + .ARSIZE_i ( axi_slave.ar_size ), + .ARBURST_i ( axi_slave.ar_burst ), + .ARLOCK_i ( axi_slave.ar_lock ), + .ARCACHE_i ( axi_slave.ar_cache ), + .ARPROT_i ( axi_slave.ar_prot ), + .ARREGION_i ( axi_slave.ar_region ), + .ARUSER_i ( axi_slave.ar_user ), + .ARQOS_i ( axi_slave.ar_qos ), + .ARVALID_i ( axi_slave.ar_valid ), + .ARREADY_o ( axi_slave.ar_ready ), + + .RID_o ( axi_slave.r_id ), + .RDATA_o ( axi_slave.r_data ), + .RRESP_o ( axi_slave.r_resp ), + .RLAST_o ( axi_slave.r_last ), + .RUSER_o ( axi_slave.r_user ), + .RVALID_o ( axi_slave.r_valid ), + .RREADY_i ( axi_slave.r_ready ), + + .PENABLE ( apb_master.penable ), + .PWRITE ( apb_master.pwrite ), + .PADDR ( apb_master.paddr ), + .PSEL ( apb_master.psel ), + .PWDATA ( apb_master.pwdata ), + .PRDATA ( apb_master.prdata ), + .PREADY ( apb_master.pready ), + .PSLVERR ( apb_master.pslverr ) + ); + end else if (AXI_DATA_WIDTH == 64 && APB_DATA_WIDTH == 32) begin + axi2apb_64_32 #( + .AXI4_ADDRESS_WIDTH ( AXI_ADDR_WIDTH ), + .AXI4_RDATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI4_WDATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI4_ID_WIDTH ( AXI_ID_WIDTH ), + .AXI4_USER_WIDTH ( AXI_USER_WIDTH ), + + .BUFF_DEPTH_SLAVE ( 2 ), + .APB_ADDR_WIDTH ( APB_ADDR_WIDTH ) + ) axi2apb_i ( + .ACLK ( clk_i ), + .ARESETn ( rst_ni ), + .test_en_i ( test_en_i ), + + .AWID_i ( axi_slave.aw_id ), + .AWADDR_i ( axi_slave.aw_addr ), + .AWLEN_i ( axi_slave.aw_len ), + .AWSIZE_i ( axi_slave.aw_size ), + .AWBURST_i ( axi_slave.aw_burst ), + .AWLOCK_i ( axi_slave.aw_lock ), + .AWCACHE_i ( axi_slave.aw_cache ), + .AWPROT_i ( axi_slave.aw_prot ), + .AWREGION_i ( axi_slave.aw_region ), + .AWATOP_i ( axi_slave.aw_atop ), + .AWUSER_i ( axi_slave.aw_user ), + .AWQOS_i ( axi_slave.aw_qos ), + .AWVALID_i ( axi_slave.aw_valid ), + .AWREADY_o ( axi_slave.aw_ready ), + + .WDATA_i ( axi_slave.w_data ), + .WSTRB_i ( axi_slave.w_strb ), + .WLAST_i ( axi_slave.w_last ), + .WUSER_i ( axi_slave.w_user ), + .WVALID_i ( axi_slave.w_valid ), + .WREADY_o ( axi_slave.w_ready ), + + .BID_o ( axi_slave.b_id ), + .BRESP_o ( axi_slave.b_resp ), + .BVALID_o ( axi_slave.b_valid ), + .BUSER_o ( axi_slave.b_user ), + .BREADY_i ( axi_slave.b_ready ), + + .ARID_i ( axi_slave.ar_id ), + .ARADDR_i ( axi_slave.ar_addr ), + .ARLEN_i ( axi_slave.ar_len ), + .ARSIZE_i ( axi_slave.ar_size ), + .ARBURST_i ( axi_slave.ar_burst ), + .ARLOCK_i ( axi_slave.ar_lock ), + .ARCACHE_i ( axi_slave.ar_cache ), + .ARPROT_i ( axi_slave.ar_prot ), + .ARREGION_i ( axi_slave.ar_region ), + .ARUSER_i ( axi_slave.ar_user ), + .ARQOS_i ( axi_slave.ar_qos ), + .ARVALID_i ( axi_slave.ar_valid ), + .ARREADY_o ( axi_slave.ar_ready ), + + .RID_o ( axi_slave.r_id ), + .RDATA_o ( axi_slave.r_data ), + .RRESP_o ( axi_slave.r_resp ), + .RLAST_o ( axi_slave.r_last ), + .RUSER_o ( axi_slave.r_user ), + .RVALID_o ( axi_slave.r_valid ), + .RREADY_i ( axi_slave.r_ready ), + + .PENABLE ( apb_master.penable ), + .PWRITE ( apb_master.pwrite ), + .PADDR ( apb_master.paddr ), + .PSEL ( apb_master.psel ), + .PWDATA ( apb_master.pwdata ), + .PRDATA ( apb_master.prdata ), + .PREADY ( apb_master.pready ), + .PSLVERR ( apb_master.pslverr ) + ); + end + endgenerate +endmodule diff --git a/hw/deps/axi2mem/src/axi_to_mem.sv b/hw/deps/axi2mem/src/axi_to_mem.sv new file mode 100644 index 0000000..bc93220 --- /dev/null +++ b/hw/deps/axi2mem/src/axi_to_mem.sv @@ -0,0 +1,782 @@ +// Copyright 2020 ETH Zurich and 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. + +// Andreas Kurth + +module axi_to_mem #( + parameter type axi_req_t = logic, // AXI request type + parameter type axi_resp_t = logic, // AXI response type + parameter int unsigned AddrWidth = 0, // address width + parameter int unsigned DataWidth = 0, // AXI data width + parameter int unsigned IdWidth = 0, // AXI ID width + parameter int unsigned NumBanks = 0, // number of banks at output + parameter int unsigned BufDepth = 1, // depth of memory response buffer + // Dependent parameters, do not override. + localparam type addr_t = logic [AddrWidth-1:0], + localparam type mem_atop_t = logic [5:0], + localparam type mem_data_t = logic [DataWidth/NumBanks-1:0], + localparam type mem_strb_t = logic [DataWidth/NumBanks/8-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + output logic busy_o, + + input axi_req_t axi_req_i, + output axi_resp_t axi_resp_o, + + output logic [NumBanks-1:0] mem_req_o, + input logic [NumBanks-1:0] mem_gnt_i, + output addr_t [NumBanks-1:0] mem_addr_o, // byte address + output mem_data_t [NumBanks-1:0] mem_wdata_o, // write data + output mem_strb_t [NumBanks-1:0] mem_strb_o, // byte-wise strobe + output mem_atop_t [NumBanks-1:0] mem_atop_o, // atomic operation + output logic [NumBanks-1:0] mem_we_o, // write enable + input logic [NumBanks-1:0] mem_rvalid_i, // response valid + input mem_data_t [NumBanks-1:0] mem_rdata_i // read data +); + + typedef logic [DataWidth-1:0] axi_data_t; + typedef logic [DataWidth/8-1:0] axi_strb_t; + typedef logic [IdWidth-1:0] axi_id_t; + + typedef struct packed { + addr_t addr; + mem_atop_t atop; + axi_strb_t strb; + axi_data_t wdata; + logic we; + } mem_req_t; + + typedef struct packed { + addr_t addr; + axi_pkg::len_t len; + axi_pkg::atop_t atop; + axi_id_t id; + logic last; + axi_pkg::qos_t qos; + axi_pkg::size_t size; + logic write; + } meta_t; + + axi_data_t mem_rdata, + m2s_resp; + axi_pkg::len_t r_cnt_d, r_cnt_q, + w_cnt_d, w_cnt_q; + logic arb_valid, arb_ready, + rd_valid, rd_ready, + rd_buf_valid, rd_buf_ready, + wr_valid, wr_ready, + rd_mux_valid, rd_mux_ready, + rd_prio_demux, + rd_prio_inp_valid, rd_prio_inp_ready, + rd_regu_inp_valid, rd_regu_inp_ready, + rd_prio_mux, + rd_prio_valid, rd_prio_ready, + rd_regu_valid, rd_regu_ready, + sel_b, sel_buf_b, + sel_r, sel_buf_r, + sel_valid, sel_ready, + sel_buf_valid, sel_buf_ready, + sel_lock_d, sel_lock_q, + meta_valid, meta_ready, + meta_buf_valid, meta_buf_ready, + meta_sel_d, meta_sel_q, + m2s_req_valid, m2s_req_ready, + m2s_resp_valid, m2s_resp_ready, + mem_req_valid, mem_req_ready, + mem_rvalid; + mem_req_t m2s_req, + mem_req; + meta_t rd_meta, + rd_meta_d, rd_meta_q, + rd_buf_meta, + rd_mux_meta, + rd_prio_meta, + rd_regu_meta, + wr_meta, + wr_meta_d, wr_meta_q, + meta, meta_buf; + + assign busy_o = axi_req_i.aw_valid | axi_req_i.ar_valid | axi_req_i.w_valid | + axi_resp_o.b_valid | axi_resp_o.r_valid | + (r_cnt_q > 0) | (w_cnt_q > 0); + + // This is not ready for upstreaming; for that, we would have to compare the incoming ID against + // all IDs in both queues to ensure ordering. + stream_demux #( + .N_OUP (2) + ) i_rd_prio_demux ( + .inp_valid_i (axi_req_i.ar_valid), + .inp_ready_o (axi_resp_o.ar_ready), + .oup_sel_i (rd_prio_demux), + .oup_valid_o ({rd_prio_inp_valid, rd_regu_inp_valid}), + .oup_ready_i ({rd_prio_inp_ready, rd_regu_inp_ready}) + ); + assign rd_prio_demux = axi_req_i.ar_valid & axi_req_i.ar.len == '0 & axi_req_i.ar.qos != '0; + stream_fifo #( + .FALL_THROUGH (1'b1), + .DEPTH (16), + .T (meta_t) + ) i_rd_regu_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .data_i ('{ + addr: axi_req_i.ar.addr, + len: axi_req_i.ar.len, + atop: '0, + id: axi_req_i.ar.id, + last: (axi_req_i.ar.len == '0), + qos: axi_req_i.ar.qos, + size: axi_req_i.ar.size, + write: 1'b0 + }), + .valid_i (rd_regu_inp_valid), + .ready_o (rd_regu_inp_ready), + .data_o (rd_regu_meta), + .valid_o (rd_regu_valid), + .ready_i (rd_regu_ready), + .usage_o (/* unused */) + ); + stream_fifo #( + .FALL_THROUGH (1'b1), + .DEPTH (4), + .T (meta_t) + ) i_rd_prio_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .data_i ('{ + addr: axi_req_i.ar.addr, + len: axi_req_i.ar.len, + atop: '0, + id: axi_req_i.ar.id, + last: (axi_req_i.ar.len == '0), + qos: axi_req_i.ar.qos, + size: axi_req_i.ar.size, + write: 1'b0 + }), + .valid_i (rd_prio_inp_valid), + .ready_o (rd_prio_inp_ready), + .data_o (rd_prio_meta), + .valid_o (rd_prio_valid), + .ready_i (rd_prio_ready), + .usage_o (/* unused */) + ); + stream_mux #( + .DATA_T (meta_t), + .N_INP (2) + ) i_rd_prio_mux ( + .inp_data_i ({rd_prio_meta, rd_regu_meta}), + .inp_valid_i ({rd_prio_valid, rd_regu_valid}), + .inp_ready_o ({rd_prio_ready, rd_regu_ready}), + .inp_sel_i (rd_prio_mux), + .oup_data_o (rd_mux_meta), + .oup_valid_o (rd_mux_valid), + .oup_ready_i (rd_mux_ready) + ); + assign rd_prio_mux = rd_prio_valid; + + // Handle reads. + always_comb begin + // Default assignments + rd_mux_ready = 1'b0; + rd_meta_d = rd_meta_q; + r_cnt_d = r_cnt_q; + rd_meta = '{ default: 'x }; + rd_valid = 1'b0; + // Prioritize single-beat read with QoS > 0 over in-progress bursts. + if (rd_mux_valid && rd_mux_meta.len == '0 && rd_mux_meta.qos != '0 && + // Additionally, we may only handle this request if we are not currently handling a burst + // with the same ID. + (r_cnt_q == '0 || rd_meta_q.id != rd_mux_meta.id)) begin + rd_meta = rd_mux_meta; + rd_valid = 1'b1; + rd_mux_ready = rd_ready; + // Handle R burst in progress. + end else if (r_cnt_q > '0) begin + rd_meta_d.last = (r_cnt_q == 8'd1); + rd_meta = rd_meta_d; + rd_meta.addr = rd_meta_q.addr + axi_pkg::num_bytes(rd_meta_q.size); + rd_valid = 1'b1; + if (rd_ready) begin + r_cnt_d--; + rd_meta_d.addr = rd_meta.addr; + end + // Handle new AR if there is one. + end else if (rd_mux_valid) begin + rd_meta_d = rd_mux_meta; + rd_meta_d.addr = axi_pkg::aligned_addr(rd_mux_meta.addr, rd_mux_meta.size); + rd_meta = rd_meta_d; + rd_meta.addr = rd_mux_meta.addr; + rd_valid = 1'b1; + if (rd_ready) begin + r_cnt_d = rd_mux_meta.len; + rd_mux_ready = 1'b1; + end + end + end + + // FT register required to absorb changes to `rd_meta` while `rd_valid` but not yet `rd_ready`. + fall_through_register #( + .T (meta_t) + ) i_rd_ft_reg ( + .clk_i, + .rst_ni, + .clr_i (1'b0), + .testmode_i (1'b0), + .valid_i (rd_valid), + .ready_o (rd_ready), + .data_i (rd_meta), + .valid_o (rd_buf_valid), + .ready_i (rd_buf_ready), + .data_o (rd_buf_meta) + ); + + // Handle writes. + always_comb begin + // Default assignments + axi_resp_o.aw_ready = 1'b0; + axi_resp_o.w_ready = 1'b0; + wr_meta_d = wr_meta_q; + wr_meta = 'x; + wr_valid = 1'b0; + w_cnt_d = w_cnt_q; + // Handle W bursts in progress. + if (w_cnt_q > '0) begin + wr_meta_d.last = (w_cnt_q == 8'd1); + wr_meta = wr_meta_d; + wr_meta.addr = wr_meta_q.addr + axi_pkg::num_bytes(wr_meta_q.size); + if (axi_req_i.w_valid) begin + wr_valid = 1'b1; + if (wr_ready) begin + axi_resp_o.w_ready = 1'b1; + w_cnt_d--; + wr_meta_d.addr = wr_meta.addr; + end + end + // Handle new AW if there is one. + end else if (axi_req_i.aw_valid && axi_req_i.w_valid) begin + wr_meta_d = '{ + addr: axi_pkg::aligned_addr(axi_req_i.aw.addr, axi_req_i.aw.size), + len: axi_req_i.aw.len, + atop: axi_req_i.aw.atop, + id: axi_req_i.aw.id, + last: (axi_req_i.aw.len == '0), + qos: axi_req_i.aw.qos, + size: axi_req_i.aw.size, + write: 1'b1 + }; + wr_meta = wr_meta_d; + wr_meta.addr = axi_req_i.aw.addr; + wr_valid = 1'b1; + if (wr_ready) begin + w_cnt_d = axi_req_i.aw.len; + axi_resp_o.aw_ready = 1'b1; + axi_resp_o.w_ready = 1'b1; + end + end + end + + // Arbitrate between reads and writes. + + /* verilator lint_off UNOPTFLAT */ + logic [1:0] ax_mux_inp_ready; + /* verilator lint_on UNOPTFLAT */ + + assign rd_buf_ready = ax_mux_inp_ready[0]; + assign wr_ready = ax_mux_inp_ready[1]; + + stream_mux #( + .DATA_T (meta_t), + .N_INP (2) + ) i_ax_mux ( + .inp_data_i ({wr_meta, rd_buf_meta}), + .inp_valid_i ({wr_valid, rd_buf_valid}), + .inp_ready_o (ax_mux_inp_ready), + .inp_sel_i (meta_sel_d), + .oup_data_o (meta), + .oup_valid_o (arb_valid), + .oup_ready_i (arb_ready) + ); + always_comb begin + meta_sel_d = meta_sel_q; + sel_lock_d = sel_lock_q; + if (sel_lock_q) begin + meta_sel_d = meta_sel_q; + if (arb_valid && arb_ready) begin + sel_lock_d = 1'b0; + end + end else begin + if (wr_valid ^ rd_buf_valid) begin + // If either write or read is valid but not both, select the valid one. + meta_sel_d = wr_valid; + end else if (wr_valid && rd_buf_valid) begin + // If both write and read are valid, decide according to QoS then burst properties. + // Priorize higher QoS. + if (wr_meta.qos > rd_buf_meta.qos) begin + meta_sel_d = 1'b1; + end else if (rd_buf_meta.qos > wr_meta.qos) begin + meta_sel_d = 1'b0; + // Decide requests with identical QoS. + end else if (wr_meta.qos == rd_buf_meta.qos) begin + // 1. Priorize individual writes over read bursts. + // Rationale: Read bursts can be interleaved on AXI but write bursts cannot. However, + // progress of read bursts must still be guaranteed, so this condition only applies if the + // last beat granted was a read. + if (wr_meta.last && !rd_buf_meta.last && !meta_sel_q) begin + meta_sel_d = 1'b1; + // 2. Prioritize ongoing burst. + // Rationale: Stalled bursts create backpressure or require costly buffers. + end else if (w_cnt_q > '0) begin + meta_sel_d = 1'b1; + end else if (r_cnt_q > '0) begin + meta_sel_d = 1'b0; + // 3. Otherwise arbitrate round robin to prevent starvation. + end else begin + meta_sel_d = ~meta_sel_q; + end + end + end + // Lock arbitration if valid but not yet ready. + if (arb_valid && !arb_ready) begin + sel_lock_d = 1'b1; + end + end + end + + // Fork arbitrated stream to meta data, memory requests, and R/B channel selection. + stream_fork #( + .N_OUP (3) + ) i_fork ( + .clk_i, + .rst_ni, + .valid_i (arb_valid), + .ready_o (arb_ready), + .valid_o ({sel_valid, meta_valid, m2s_req_valid}), + .ready_i ({sel_ready, meta_ready, m2s_req_ready}) + ); + + assign sel_b = meta.write & meta.last; + assign sel_r = ~meta.write | meta.atop[5]; + + stream_fifo #( + .FALL_THROUGH (1'b0), + .DEPTH (1 + BufDepth), + .T (logic[1:0]) + ) i_sel_buf ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .data_i ({sel_b, sel_r}), + .valid_i (sel_valid), + .ready_o (sel_ready), + .data_o ({sel_buf_b, sel_buf_r}), + .valid_o (sel_buf_valid), + .ready_i (sel_buf_ready), + .usage_o (/* unused */) + ); + + stream_fifo #( + .FALL_THROUGH (1'b0), + .DEPTH (1 + BufDepth), + .T (meta_t) + ) i_meta_buf ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .data_i (meta), + .valid_i (meta_valid), + .ready_o (meta_ready), + .data_o (meta_buf), + .valid_o (meta_buf_valid), + .ready_i (meta_buf_ready), + .usage_o (/* unused */) + ); + + // Map AXI ATOPs to RI5CY AMOs. + always_comb begin + m2s_req.atop = '0; + m2s_req.wdata = axi_req_i.w.data; + if (arb_valid && meta.atop[5:4] != axi_pkg::ATOP_NONE) begin + m2s_req.atop[5] = 1'b1; + if (meta.atop == axi_pkg::ATOP_ATOMICSWAP) begin + m2s_req.atop[4:0] = riscv_defines::AMO_SWAP; + end else begin + case (meta.atop[2:0]) + axi_pkg::ATOP_ADD: m2s_req.atop[4:0] = riscv_defines::AMO_ADD; + axi_pkg::ATOP_CLR: begin + m2s_req.atop[4:0] = riscv_defines::AMO_AND; + m2s_req.wdata = ~axi_req_i.w.data; + end + axi_pkg::ATOP_EOR: m2s_req.atop[4:0] = riscv_defines::AMO_XOR; + axi_pkg::ATOP_SET: m2s_req.atop[4:0] = riscv_defines::AMO_OR; + axi_pkg::ATOP_SMAX: m2s_req.atop[4:0] = riscv_defines::AMO_MAX; + axi_pkg::ATOP_SMIN: m2s_req.atop[4:0] = riscv_defines::AMO_MIN; + axi_pkg::ATOP_UMAX: m2s_req.atop[4:0] = riscv_defines::AMO_MAXU; + axi_pkg::ATOP_UMIN: m2s_req.atop[4:0] = riscv_defines::AMO_MINU; + endcase + end + end + end + assign m2s_req.addr = meta.addr; + assign m2s_req.strb = axi_req_i.w.strb; + assign m2s_req.we = meta.write; + + // Interface memory as stream. + stream_to_mem #( + .mem_req_t (mem_req_t), + .mem_resp_t (axi_data_t), + .BufDepth (BufDepth) + ) i_stream_to_mem ( + .clk_i, + .rst_ni, + .req_i (m2s_req), + .req_valid_i (m2s_req_valid), + .req_ready_o (m2s_req_ready), + .resp_o (m2s_resp), + .resp_valid_o (m2s_resp_valid), + .resp_ready_i (m2s_resp_ready), + .mem_req_o (mem_req), + .mem_req_valid_o (mem_req_valid), + .mem_req_ready_i (mem_req_ready), + .mem_resp_i (mem_rdata), + .mem_resp_valid_i (mem_rvalid) + ); + + // Split single memory request to desired number of banks. + mem_to_banks #( + .AddrWidth (AddrWidth), + .DataWidth (DataWidth), + .NumBanks (NumBanks) + ) i_mem_to_banks ( + .clk_i, + .rst_ni, + .req_i (mem_req_valid), + .gnt_o (mem_req_ready), + .addr_i (mem_req.addr), + .wdata_i (mem_req.wdata), + .strb_i (mem_req.strb), + .atop_i (mem_req.atop), + .we_i (mem_req.we), + .rvalid_o (mem_rvalid), + .rdata_o (mem_rdata), + .bank_req_o (mem_req_o), + .bank_gnt_i (mem_gnt_i), + .bank_addr_o (mem_addr_o), + .bank_wdata_o (mem_wdata_o), + .bank_strb_o (mem_strb_o), + .bank_atop_o (mem_atop_o), + .bank_we_o (mem_we_o), + .bank_rvalid_i (mem_rvalid_i), + .bank_rdata_i (mem_rdata_i) + ); + + // Join memory read data and meta data stream. + logic mem_join_valid, mem_join_ready; + stream_join #( + .N_INP (2) + ) i_join ( + .inp_valid_i ({m2s_resp_valid, meta_buf_valid}), + .inp_ready_o ({m2s_resp_ready, meta_buf_ready}), + .oup_valid_o (mem_join_valid), + .oup_ready_i (mem_join_ready) + ); + + // Dynamically fork the joined stream to B and R channels. + stream_fork_dynamic #( + .N_OUP (2) + ) i_fork_dynamic ( + .clk_i, + .rst_ni, + .valid_i (mem_join_valid), + .ready_o (mem_join_ready), + .sel_i ({sel_buf_b, sel_buf_r}), + .sel_valid_i (sel_buf_valid), + .sel_ready_o (sel_buf_ready), + .valid_o ({axi_resp_o.b_valid, axi_resp_o.r_valid}), + .ready_i ({axi_req_i.b_ready, axi_req_i.r_ready}) + ); + + // Compose B responses. + assign axi_resp_o.b = '{ + id: meta_buf.id, + resp: axi_pkg::RESP_OKAY, + user: '0 + }; + + // Compose R responses. + assign axi_resp_o.r = '{ + data: m2s_resp, + id: meta_buf.id, + last: meta_buf.last, + resp: axi_pkg::RESP_OKAY, + user: '0 + }; + + // Registers + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + meta_sel_q <= 1'b0; + sel_lock_q <= 1'b0; + rd_meta_q <= '{default: '0}; + wr_meta_q <= '{default: '0}; + r_cnt_q <= '0; + w_cnt_q <= '0; + end else begin + meta_sel_q <= meta_sel_d; + sel_lock_q <= sel_lock_d; + rd_meta_q <= rd_meta_d; + wr_meta_q <= wr_meta_d; + r_cnt_q <= r_cnt_d; + w_cnt_q <= w_cnt_d; + end + end + + // Assertions + `ifndef VERILATOR + `ifndef TARGET_SYNTHESIS + default disable iff (!rst_ni); + assume property (@(posedge clk_i) + axi_req_i.ar_valid && !axi_resp_o.ar_ready |=> $stable(axi_req_i.ar)) + else $error("AR must remain stable until handshake has happened!"); + assert property (@(posedge clk_i) + axi_resp_o.r_valid && !axi_req_i.r_ready |=> $stable(axi_resp_o.r)) + else $error("R must remain stable until handshake has happened!"); + assume property (@(posedge clk_i) + axi_req_i.aw_valid && !axi_resp_o.aw_ready |=> $stable(axi_req_i.aw)) + else $error("AW must remain stable until handshake has happened!"); + assume property (@(posedge clk_i) + axi_req_i.w_valid && !axi_resp_o.w_ready |=> $stable(axi_req_i.w)) + else $error("W must remain stable until handshake has happened!"); + assert property (@(posedge clk_i) + axi_resp_o.b_valid && !axi_req_i.b_ready |=> $stable(axi_resp_o.b)) + else $error("B must remain stable until handshake has happened!"); + assert property (@(posedge clk_i) axi_req_i.ar_valid && axi_req_i.ar.len > 0 |-> + axi_req_i.ar.burst == axi_pkg::BURST_INCR) + else $error("Non-incrementing bursts are not supported!"); + assert property (@(posedge clk_i) axi_req_i.aw_valid && axi_req_i.aw.len > 0 |-> + axi_req_i.aw.burst == axi_pkg::BURST_INCR) + else $error("Non-incrementing bursts are not supported!"); + assert property (@(posedge clk_i) meta_valid && meta.atop != '0 |-> meta.write) + else $warning("Unexpected atomic operation on read."); + `endif + `endif + +endmodule + + +`include "axi/assign.svh" +`include "axi/typedef.svh" +// Interface wrapper for axi_to_mem +module axi_to_mem_intf #( + parameter int unsigned AddrWidth = 0, + parameter int unsigned DataWidth = 0, + parameter int unsigned IdWidth = 0, + parameter int unsigned UserWidth = 0, + parameter int unsigned NumBanks = 0, + parameter int unsigned BufDepth = 1, // depth of memory response buffer + // Dependent parameters, do not override. + localparam type addr_t = logic [AddrWidth-1:0], + localparam type mem_atop_t = logic [5:0], + localparam type mem_data_t = logic [DataWidth/NumBanks-1:0], + localparam type mem_strb_t = logic [DataWidth/NumBanks/8-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + output logic busy_o, + + AXI_BUS.Slave slv, + + output logic [NumBanks-1:0] mem_req_o, + input logic [NumBanks-1:0] mem_gnt_i, + output addr_t [NumBanks-1:0] mem_addr_o, // byte address + output mem_data_t [NumBanks-1:0] mem_wdata_o, // write data + output mem_strb_t [NumBanks-1:0] mem_strb_o, // byte-wise strobe + output mem_atop_t [NumBanks-1:0] mem_atop_o, // atomic operation + output logic [NumBanks-1:0] mem_we_o, // write enable + input logic [NumBanks-1:0] mem_rvalid_i, // response valid + input mem_data_t [NumBanks-1:0] mem_rdata_i // read data +); + typedef logic [IdWidth-1:0] id_t; + typedef logic [DataWidth-1:0] data_t; + typedef logic [DataWidth/8-1:0] strb_t; + typedef logic [UserWidth-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t) + req_t req; + resp_t resp; + `AXI_ASSIGN_TO_REQ(req, slv) + `AXI_ASSIGN_FROM_RESP(slv, resp) + axi_to_mem #( + .axi_req_t (req_t), + .axi_resp_t (resp_t), + .AddrWidth (AddrWidth), + .DataWidth (DataWidth), + .IdWidth (IdWidth), + .NumBanks (NumBanks), + .BufDepth (BufDepth) + ) i_axi_to_mem ( + .clk_i, + .rst_ni, + .busy_o, + .axi_req_i (req), + .axi_resp_o (resp), + .mem_req_o, + .mem_gnt_i, + .mem_addr_o, + .mem_wdata_o, + .mem_strb_o, + .mem_atop_o, + .mem_we_o, + .mem_rvalid_i, + .mem_rdata_i + ); +endmodule + + +// Split memory access over multiple parallel banks, where each bank has its own req/gnt request and +// valid response direction. +module mem_to_banks #( + parameter int unsigned AddrWidth = 0, // input address width + parameter int unsigned DataWidth = 0, // input data width, must be a power of two + parameter int unsigned NumBanks = 0, // number of banks at output, must evenly divide the data + // width + // Dependent parameters, do not override. + localparam type addr_t = logic [AddrWidth-1:0], + localparam type atop_t = logic [5:0], + localparam type inp_data_t = logic [DataWidth-1:0], + localparam type inp_strb_t = logic [DataWidth/8-1:0], + localparam type oup_data_t = logic [DataWidth/NumBanks-1:0], + localparam type oup_strb_t = logic [DataWidth/NumBanks/8-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + input logic req_i, + output logic gnt_o, + input addr_t addr_i, + input inp_data_t wdata_i, + input inp_strb_t strb_i, + input atop_t atop_i, + input logic we_i, + output logic rvalid_o, + output inp_data_t rdata_o, + + output logic [NumBanks-1:0] bank_req_o, + input logic [NumBanks-1:0] bank_gnt_i, + output addr_t [NumBanks-1:0] bank_addr_o, + output oup_data_t [NumBanks-1:0] bank_wdata_o, + output oup_strb_t [NumBanks-1:0] bank_strb_o, + output atop_t [NumBanks-1:0] bank_atop_o, + output logic [NumBanks-1:0] bank_we_o, + input logic [NumBanks-1:0] bank_rvalid_i, + input oup_data_t [NumBanks-1:0] bank_rdata_i +); + + localparam DataBytes = $bits(inp_strb_t); + localparam BitsPerBank = $bits(oup_data_t); + localparam BytesPerBank = $bits(oup_strb_t); + + typedef struct packed { + addr_t addr; + oup_data_t wdata; + oup_strb_t strb; + atop_t atop; + logic we; + } req_t; + + logic req_valid; + logic [NumBanks-1:0] req_ready, + resp_valid, resp_ready; + req_t [NumBanks-1:0] bank_req, + bank_oup; + + function automatic addr_t align_addr(input addr_t addr); + return (addr >> $clog2(DataBytes)) << $clog2(DataBytes); + endfunction + + // Handle requests. + assign req_valid = req_i & gnt_o; + for (genvar i = 0; i < NumBanks; i++) begin : gen_reqs + assign bank_req[i].addr = align_addr(addr_i) + i * BytesPerBank; + assign bank_req[i].wdata = wdata_i[i*BitsPerBank+:BitsPerBank]; + assign bank_req[i].strb = strb_i[i*BytesPerBank+:BytesPerBank]; + assign bank_req[i].atop = atop_i; + assign bank_req[i].we = we_i; + fall_through_register #( + .T (req_t) + ) i_ft_reg ( + .clk_i, + .rst_ni, + .clr_i (1'b0), + .testmode_i (1'b0), + .valid_i (req_valid), + .ready_o (req_ready[i]), + .data_i (bank_req[i]), + .valid_o (bank_req_o[i]), + .ready_i (bank_gnt_i[i]), + .data_o (bank_oup[i]) + ); + assign bank_addr_o[i] = bank_oup[i].addr; + assign bank_wdata_o[i] = bank_oup[i].wdata; + assign bank_strb_o[i] = bank_oup[i].strb; + assign bank_atop_o[i] = bank_oup[i].atop; + assign bank_we_o[i] = bank_oup[i].we; + end + + // Grant output if all our requests have been granted. + assign gnt_o = (&req_ready) & (&resp_ready); + + // Handle responses. + for (genvar i = 0; i < NumBanks; i++) begin : gen_resp_regs + fall_through_register #( + .T (oup_data_t) + ) i_ft_reg ( + .clk_i, + .rst_ni, + .clr_i (1'b0), + .testmode_i (1'b0), + .valid_i (bank_rvalid_i[i]), + .ready_o (resp_ready[i]), + .data_i (bank_rdata_i[i]), + .data_o (rdata_o[i*BitsPerBank+:BitsPerBank]), + .ready_i (rvalid_o), + .valid_o (resp_valid[i]) + ); + end + assign rvalid_o = &resp_valid; + + // Assertions + `ifndef VERILATOR + `ifndef TARGET_SYNTHESIS + initial begin + assume (DataWidth != 0 && (DataWidth & (DataWidth - 1)) == 0) + else $fatal(1, "Data width must be a power of two!"); + assume (DataWidth % NumBanks == 0) + else $fatal(1, "Data width must be evenly divisible over banks!"); + assume ((DataWidth / NumBanks) % 8 == 0) + else $fatal(1, "Data width of each bank must be divisible into 8-bit bytes!"); + end + `endif + `endif + +endmodule diff --git a/hw/deps/axi2mem/src/axi_to_mem_banked_mp.sv b/hw/deps/axi2mem/src/axi_to_mem_banked_mp.sv new file mode 100644 index 0000000..573d9da --- /dev/null +++ b/hw/deps/axi2mem/src/axi_to_mem_banked_mp.sv @@ -0,0 +1,373 @@ +// Copyright 2020 ETH Zurich and 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. + +// Wolfgang Rönninger + +/// AXI4+ATOP to banked SRAM memory slave. Allows for parallel read and write transactions. Multi-port extension. +module axi_to_mem_banked_mp #( + /// AXI4+ATOP ID width + parameter int unsigned AxiIdWidth = 32'd0, + /// AXI4+ATOP address width + parameter int unsigned AxiAddrWidth = 32'd0, + /// AXI4+ATOP data width + parameter int unsigned AxiDataWidth = 32'd0, + /// AXI4+ATOP AW channel struct + parameter type axi_aw_chan_t = logic, + /// AXI4+ATOP W channel struct + parameter type axi_w_chan_t = logic, + /// AXI4+ATOP B channel struct + parameter type axi_b_chan_t = logic, + /// AXI4+ATOP AR channel struct + parameter type axi_ar_chan_t = logic, + /// AXI4+ATOP R channel struct + parameter type axi_r_chan_t = logic, + /// AXI4+ATOP request struct + parameter type axi_req_t = logic, + /// AXI4+ATOP response struct + parameter type axi_resp_t = logic, + // Number of slave ports + parameter int unsigned NumSlvPorts = 1, + /// Number of memory banks / macros + /// Has to satisfy: + /// - MemNumBanks >= 2 * AxiDataWidth / MemDataWidth + /// - MemNumBanks is a power of 2. + parameter int unsigned MemNumBanks = 32'd4, + /// Address width of an individual memory bank. + parameter int unsigned MemAddrWidth = 32'd11, + /// Data width of the memory macros. + /// Has to satisfy: + /// - AxiDataWidth % MemDataWidth = 0 + parameter int unsigned MemDataWidth = 32'd32, + /// Read latency of the connected memory in cycles + parameter int unsigned MemLatency = 32'd1, + /// TCDM topology can be: LIC, BFLY2, BFLY4, CLOS + parameter tcdm_interconnect_pkg::topo_e Topology = tcdm_interconnect_pkg::LIC, + /// DEPENDENT PARAMETERS, DO NOT OVERWRITE! + parameter type mem_addr_t = logic [MemAddrWidth-1:0], + parameter type mem_atop_t = logic [5:0], + parameter type mem_data_t = logic [MemDataWidth-1:0], + parameter type mem_strb_t = logic [MemDataWidth/8-1:0] +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode enable + input logic test_i, + /// AXI4+ATOP slave port, request struct + input axi_req_t [NumSlvPorts-1:0] axi_req_i, + /// AXI4+ATOP slave port, response struct + output axi_resp_t [NumSlvPorts-1:0] axi_resp_o, + /// Memory bank request + output logic [MemNumBanks-1:0] mem_req_o, + /// Memory request grant + input logic [MemNumBanks-1:0] mem_gnt_i, + /// Request address + output mem_addr_t [MemNumBanks-1:0] mem_add_o, + /// Write request enable, active high + output logic [MemNumBanks-1:0] mem_wen_o, + /// Write data + output mem_data_t [MemNumBanks-1:0] mem_wdata_o, + /// Write data byte enable, active high + output mem_strb_t [MemNumBanks-1:0] mem_be_o, + /// Atomic operation + output mem_atop_t [MemNumBanks-1:0] mem_atop_o, + /// Read data response + input mem_data_t [MemNumBanks-1:0] mem_rdata_i, + /// Status output, busy flag of `axi_to_mem` + output logic [NumSlvPorts-1:0][1:0] axi_to_mem_busy_o +); + localparam int unsigned BanksPerAxiChannel = AxiDataWidth / MemDataWidth; + // atop signal is piggybacked on tcdm_data + localparam int unsigned TcdmDataWidth = MemDataWidth + 6; + + // Typedef for defining the channels + typedef enum logic { + ReadAccess = 1'b0, + WriteAccess = 1'b1 + } access_type_e; + typedef logic [AxiAddrWidth-1:0] axi_addr_t; + typedef logic [TcdmDataWidth-1:0] tcdm_data_t; + + axi_req_t [NumSlvPorts-1:0][1:0] mem_axi_reqs; + axi_resp_t [NumSlvPorts-1:0][1:0] mem_axi_resps; + + for (genvar i=0; i= 1) else $fatal(1, "AxiIdWidth must be at least 1!"); + assert (AxiAddrWidth >= 1) else $fatal(1, "AxiAddrWidth must be at least 1!"); + assert (AxiDataWidth >= 1) else $fatal(1, "AxiDataWidth must be at least 1!"); + assert (MemNumBanks >= 2 * AxiDataWidth / MemDataWidth) else + $fatal(1, "MemNumBanks has to be >= 2 * AxiDataWidth / MemDataWidth"); + assert ($onehot(MemNumBanks)) else $fatal(1, "MemNumBanks has to be a power of 2."); + assert (MemAddrWidth >= 1) else $fatal(1, "MemAddrWidth must be at least 1!"); + assert (MemDataWidth >= 1) else $fatal(1, "MemDataWidth must be at least 1!"); + assert (AxiDataWidth % MemDataWidth == 0) else + $fatal(1, "MemDataWidth has to be a divisor of AxiDataWidth."); + end +`endif +// pragma translate_on +endmodule + +`include "axi/typedef.svh" +`include "axi/assign.svh" +/// AXI4+ATOP interface wrapper for `axi_to_mem` +module axi_to_mem_banked_2p_intf #( + /// AXI4+ATOP ID width + parameter int unsigned AXI_ID_WIDTH = 32'd0, + /// AXI4+ATOP address width + parameter int unsigned AXI_ADDR_WIDTH = 32'd0, + /// AXI4+ATOP data width + parameter int unsigned AXI_DATA_WIDTH = 32'd0, + /// AXI4+ATOP user width + parameter int unsigned AXI_USER_WIDTH = 32'd0, + /// Number of memory banks / macros + /// Has to satisfy: + /// - MemNumBanks >= 2 * AxiDataWidth / MemDataWidth + /// - MemNumBanks is a power of 2. + parameter int unsigned MEM_NUM_BANKS = 32'd4, + /// Address width of an individual memory bank. + parameter int unsigned MEM_ADDR_WIDTH = 32'd11, + /// Data width of the memory macros. + /// Has to satisfy: + /// - AxiDataWidth % MemDataWidth = 0 + parameter int unsigned MEM_DATA_WIDTH = 32'd32, + /// Read latency of the connected memory in cycles + parameter int unsigned MEM_LATENCY = 32'd1, + /// TCDM topology can be: LIC, BFLY2, BFLY4, CLOS + parameter tcdm_interconnect_pkg::topo_e TOPOLOGY = tcdm_interconnect_pkg::LIC, + // DEPENDENT PARAMETERS, DO NOT OVERWRITE! + parameter type mem_addr_t = logic [MEM_ADDR_WIDTH-1:0], + parameter type mem_atop_t = logic [5:0], + parameter type mem_data_t = logic [MEM_DATA_WIDTH-1:0], + parameter type mem_strb_t = logic [MEM_DATA_WIDTH/8-1:0] +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode enable + input logic test_i, + /// AXI4+ATOP slave ports + // seems that array of interfaces are not supported? + AXI_BUS.Slave slv_a, + AXI_BUS.Slave slv_b, + /// Memory bank request + output logic [MEM_NUM_BANKS-1:0] mem_req_o, + /// Memory request grant + input logic [MEM_NUM_BANKS-1:0] mem_gnt_i, + /// Request address + output mem_addr_t [MEM_NUM_BANKS-1:0] mem_add_o, + /// Write request enable, active high + output logic [MEM_NUM_BANKS-1:0] mem_wen_o, + /// Write data + output mem_data_t [MEM_NUM_BANKS-1:0] mem_wdata_o, + /// Write data byte enable, active high + output mem_strb_t [MEM_NUM_BANKS-1:0] mem_be_o, + /// Atomic operation + output mem_atop_t [MEM_NUM_BANKS-1:0] mem_atop_o, + /// Read data response + input mem_data_t [MEM_NUM_BANKS-1:0] mem_rdata_i, + /// Status output, busy flag of `axi_to_mem` + output logic [1:0] axi_to_mem_busy_a_o, + output logic [1:0] axi_to_mem_busy_b_o +); + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(axi_req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(axi_resp_t, b_chan_t, r_chan_t) + + axi_req_t [1:0] mem_axi_req; + axi_resp_t [1:0] mem_axi_resp; + + `AXI_ASSIGN_TO_REQ(mem_axi_req[0], slv_a) + `AXI_ASSIGN_FROM_RESP(slv_a, mem_axi_resp[0]) + + `AXI_ASSIGN_TO_REQ(mem_axi_req[1], slv_b) + `AXI_ASSIGN_FROM_RESP(slv_b, mem_axi_resp[1]) + + axi_to_mem_banked_mp #( + .AxiIdWidth ( AXI_ID_WIDTH ), + .AxiAddrWidth ( AXI_ADDR_WIDTH ), + .AxiDataWidth ( AXI_DATA_WIDTH ), + .axi_aw_chan_t ( aw_chan_t ), + .axi_w_chan_t ( w_chan_t ), + .axi_b_chan_t ( b_chan_t ), + .axi_ar_chan_t ( ar_chan_t ), + .axi_r_chan_t ( r_chan_t ), + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_resp_t ), + .NumSlvPorts ( 2 ), + .MemNumBanks ( MEM_NUM_BANKS ), + .MemAddrWidth ( MEM_ADDR_WIDTH ), + .MemDataWidth ( MEM_DATA_WIDTH ), + .MemLatency ( MEM_LATENCY ), + .Topology ( tcdm_interconnect_pkg::LIC ) + ) i_axi_to_mem_banked ( + .clk_i, + .rst_ni, + .test_i, + .axi_to_mem_busy_o ( {axi_to_mem_busy_a_o, axi_to_mem_busy_b_o}), + .axi_req_i ( mem_axi_req ), + .axi_resp_o ( mem_axi_resp ), + .mem_req_o, + .mem_gnt_i, + .mem_add_o, + .mem_wdata_o, + .mem_be_o, + .mem_atop_o, + .mem_wen_o, + .mem_rdata_i + ); + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (AXI_ADDR_WIDTH >= 1) else $fatal(1, "AXI address width must be at least 1!"); + assert (AXI_DATA_WIDTH >= 1) else $fatal(1, "AXI data width must be at least 1!"); + assert (AXI_ID_WIDTH >= 1) else $fatal(1, "AXI ID width must be at least 1!"); + assert (AXI_USER_WIDTH >= 1) else $fatal(1, "AXI user width must be at least 1!"); + end +`endif +// pragma translate_on +endmodule + diff --git a/hw/deps/axi2mem/src/axi_to_mem_interleaved.sv b/hw/deps/axi2mem/src/axi_to_mem_interleaved.sv new file mode 100644 index 0000000..9e87787 --- /dev/null +++ b/hw/deps/axi2mem/src/axi_to_mem_interleaved.sv @@ -0,0 +1,209 @@ +// Copyright 2020 ETH Zurich and 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. + +module axi_to_mem_interleaved #( + parameter type axi_req_t = logic, // AXI request type + parameter type axi_resp_t = logic, // AXI response type + parameter int unsigned AddrWidth = 0, // address width + parameter int unsigned DataWidth = 0, // AXI data width + parameter int unsigned IdWidth = 0, // AXI ID width + parameter int unsigned NumBanks = 0, // number of banks at output + parameter int unsigned BufDepth = 1, // depth of memory response buffer + // Dependent parameters, do not override. + localparam type addr_t = logic [AddrWidth-1:0], + localparam type mem_atop_t = logic [5:0], + localparam type mem_data_t = logic [DataWidth/NumBanks-1:0], + localparam type mem_strb_t = logic [DataWidth/NumBanks/8-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + output logic busy_o, + + input axi_req_t axi_req_i, + output axi_resp_t axi_resp_o, + + output logic [NumBanks-1:0] mem_req_o, + input logic [NumBanks-1:0] mem_gnt_i, + output addr_t [NumBanks-1:0] mem_addr_o, // byte address + output mem_data_t [NumBanks-1:0] mem_wdata_o, // write data + output mem_strb_t [NumBanks-1:0] mem_strb_o, // byte-wise strobe + output mem_atop_t [NumBanks-1:0] mem_atop_o, // atomic operation + output logic [NumBanks-1:0] mem_we_o, // write enable + input logic [NumBanks-1:0] mem_rvalid_i, // response valid + input mem_data_t [NumBanks-1:0] mem_rdata_i // read data +); + + // internal signals + logic w_busy, r_busy; + logic arb_outcome, arb_outcome_head; + + // internal AXI buses + axi_req_t r_axi_req, w_axi_req; + axi_resp_t r_axi_resp, w_axi_resp; + + // internal TCDM buses + logic [NumBanks-1:0] r_mem_req, w_mem_req; + logic [NumBanks-1:0] r_mem_gnt, w_mem_gnt; + addr_t [NumBanks-1:0] r_mem_addr, w_mem_addr; + mem_data_t [NumBanks-1:0] r_mem_wdata, w_mem_wdata; + mem_strb_t [NumBanks-1:0] r_mem_strb, w_mem_strb; + mem_atop_t [NumBanks-1:0] r_mem_atop, w_mem_atop; + logic [NumBanks-1:0] r_mem_we, w_mem_we; + logic [NumBanks-1:0] r_mem_rvalid, w_mem_rvalid; + mem_data_t [NumBanks-1:0] r_mem_rdata, w_mem_rdata; + + // split AXI bus in read and write + always_comb begin : proc_axi_rw_split + axi_resp_o.r = r_axi_resp.r; + axi_resp_o.r_valid = r_axi_resp.r_valid; + axi_resp_o.ar_ready = r_axi_resp.ar_ready; + axi_resp_o.b = w_axi_resp.b; + axi_resp_o.b_valid = w_axi_resp.b_valid; + axi_resp_o.w_ready = w_axi_resp.w_ready; + axi_resp_o.aw_ready = w_axi_resp.aw_ready; + + w_axi_req = '0; + w_axi_req.aw = axi_req_i.aw; + w_axi_req.aw_valid = axi_req_i.aw_valid; + w_axi_req.w = axi_req_i.w; + w_axi_req.w_valid = axi_req_i.w_valid; + w_axi_req.b_ready = axi_req_i.b_ready; + + r_axi_req = '0; + r_axi_req.ar = axi_req_i.ar; + r_axi_req.ar_valid = axi_req_i.ar_valid; + r_axi_req.r_ready = axi_req_i.r_ready; + end + + axi_to_mem #( + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_resp_t ), + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( IdWidth ), + .NumBanks ( NumBanks ), + .BufDepth ( BufDepth ) + ) i_axi_to_mem_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .busy_o ( w_busy ), + .axi_req_i ( w_axi_req ), + .axi_resp_o ( w_axi_resp ), + .mem_req_o ( w_mem_req ), + .mem_gnt_i ( w_mem_gnt ), + .mem_addr_o ( w_mem_addr ), + .mem_wdata_o ( w_mem_wdata ), + .mem_strb_o ( w_mem_strb ), + .mem_atop_o ( w_mem_atop ), + .mem_we_o ( w_mem_we ), + .mem_rvalid_i ( w_mem_rvalid ), + .mem_rdata_i ( w_mem_rdata ) + ); + + axi_to_mem #( + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_resp_t ), + .AddrWidth ( AddrWidth ), + .DataWidth ( DataWidth ), + .IdWidth ( IdWidth ), + .NumBanks ( NumBanks ), + .BufDepth ( BufDepth ) + ) i_axi_to_mem_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .busy_o ( r_busy ), + .axi_req_i ( r_axi_req ), + .axi_resp_o ( r_axi_resp ), + .mem_req_o ( r_mem_req ), + .mem_gnt_i ( r_mem_gnt ), + .mem_addr_o ( r_mem_addr ), + .mem_wdata_o ( r_mem_wdata ), + .mem_strb_o ( r_mem_strb ), + .mem_atop_o ( r_mem_atop ), + .mem_we_o ( r_mem_we ), + .mem_rvalid_i ( r_mem_rvalid ), + .mem_rdata_i ( r_mem_rdata ) + ); + + // create a struct for the rr-arb-tree + typedef struct packed { + addr_t addr; + mem_data_t wdata; + mem_strb_t strb; + logic we; + mem_atop_t atop; + } mem_req_payload_t; + + mem_req_payload_t r_payload, w_payload, payload; + + // pack the mem + assign r_payload.addr = r_mem_addr; + assign r_payload.wdata = r_mem_wdata; + assign r_payload.strb = r_mem_strb; + assign r_payload.we = r_mem_we; + assign r_payload.atop = r_mem_atop; + + assign w_payload.addr = w_mem_addr; + assign w_payload.wdata = w_mem_wdata; + assign w_payload.strb = w_mem_strb; + assign w_payload.we = w_mem_we; + assign w_payload.atop = w_mem_atop; + + assign mem_addr_o = payload.addr; + assign mem_wdata_o = payload.wdata; + assign mem_strb_o = payload.strb; + assign mem_we_o = payload.we; + assign mem_atop_o = payload.atop; + + // route data back to both channels + assign w_mem_rdata = mem_rdata_i; + assign r_mem_rdata = mem_rdata_i; + + assign w_mem_rvalid = mem_rvalid_i & !arb_outcome_head; + assign r_mem_rvalid = mem_rvalid_i & arb_outcome_head; + + // fine-grain arbitration + rr_arb_tree #( + .NumIn ( 2 ), + .DataType ( mem_req_payload_t ) + ) i_rr_arb_tree ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .rr_i ( '0 ), + .req_i ( { r_mem_req, w_mem_req } ), + .gnt_o ( { r_mem_gnt, w_mem_gnt } ), + .data_i ( { r_payload, w_payload } ), + .req_o ( mem_req_o ), + .gnt_i ( mem_gnt_i ), + .data_o ( payload ), + .idx_o ( arb_outcome ) + ); + + // back-routing store + fifo_v3 #( + .DATA_WIDTH ( 1 ), + .DEPTH ( BufDepth + 1 ) + ) i_fifo_v3_response_trgt_store ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( ), + .empty_o ( ), + .usage_o ( ), + .data_i ( arb_outcome ), + .push_i ( mem_req_o & mem_gnt_i ), + .data_o ( arb_outcome_head ), + .pop_i ( mem_rvalid_i ) + ); + +endmodule : axi_to_mem_interleaved diff --git a/hw/deps/axi2per/axi2per.sv b/hw/deps/axi2per/axi2per.sv new file mode 100644 index 0000000..a8d0656 --- /dev/null +++ b/hw/deps/axi2per/axi2per.sv @@ -0,0 +1,467 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi2per +#( + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + parameter BUFFER_DEPTH = 2, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic [5:0] cluster_id_i, + + // AXI4 SLAVE + //*************************************** + // WRITE ADDRESS CHANNEL + input logic axi_slave_aw_valid_i, + input logic [AXI_ADDR_WIDTH-1:0] axi_slave_aw_addr_i, + input logic [2:0] axi_slave_aw_prot_i, + input logic [3:0] axi_slave_aw_region_i, + input logic [7:0] axi_slave_aw_len_i, + input logic [2:0] axi_slave_aw_size_i, + input logic [1:0] axi_slave_aw_burst_i, + input logic axi_slave_aw_lock_i, + input logic [5:0] axi_slave_aw_atop_i, + input logic [3:0] axi_slave_aw_cache_i, + input logic [3:0] axi_slave_aw_qos_i, + input logic [AXI_ID_WIDTH-1:0] axi_slave_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_aw_user_i, + output logic axi_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input logic axi_slave_ar_valid_i, + input logic [AXI_ADDR_WIDTH-1:0] axi_slave_ar_addr_i, + input logic [2:0] axi_slave_ar_prot_i, + input logic [3:0] axi_slave_ar_region_i, + input logic [7:0] axi_slave_ar_len_i, + input logic [2:0] axi_slave_ar_size_i, + input logic [1:0] axi_slave_ar_burst_i, + input logic axi_slave_ar_lock_i, + input logic [3:0] axi_slave_ar_cache_i, + input logic [3:0] axi_slave_ar_qos_i, + input logic [AXI_ID_WIDTH-1:0] axi_slave_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_ar_user_i, + output logic axi_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input logic axi_slave_w_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_slave_w_data_i, + input logic [AXI_STRB_WIDTH-1:0] axi_slave_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_w_user_i, + input logic axi_slave_w_last_i, + output logic axi_slave_w_ready_o, + + // READ DATA CHANNEL + output logic axi_slave_r_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_slave_r_data_o, + output logic [1:0] axi_slave_r_resp_o, + output logic axi_slave_r_last_o, + output logic [AXI_ID_WIDTH-1:0] axi_slave_r_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_slave_r_user_o, + input logic axi_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output logic axi_slave_b_valid_o, + output logic [1:0] axi_slave_b_resp_o, + output logic [AXI_ID_WIDTH-1:0] axi_slave_b_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_slave_b_user_o, + input logic axi_slave_b_ready_i, + + // PERIPHERAL INTERCONNECT MASTER + //*************************************** + //REQUEST CHANNEL + output logic per_master_req_o, + output logic [PER_ADDR_WIDTH-1:0] per_master_add_o, + output logic per_master_we_no, + output logic [5:0] per_master_atop_o, + output logic [31:0] per_master_wdata_o, + output logic [3:0] per_master_be_o, + input logic per_master_gnt_i, + + //RESPONSE CHANNEL + input logic per_master_r_valid_i, + input logic per_master_r_opc_i, + input logic [31:0] per_master_r_rdata_i, + + // BUSY SIGNAL + output logic busy_o +); + + // SIGNAL DECLARATION + logic s_aw_valid; + logic [AXI_ADDR_WIDTH-1:0] s_aw_addr; + logic [2:0] s_aw_prot; + logic [3:0] s_aw_region; + logic [7:0] s_aw_len; + logic [2:0] s_aw_size; + logic [1:0] s_aw_burst; + logic s_aw_lock; + logic [5:0] s_aw_atop; + logic [3:0] s_aw_cache; + logic [3:0] s_aw_qos; + logic [AXI_ID_WIDTH-1:0] s_aw_id; + logic [AXI_USER_WIDTH-1:0] s_aw_user; + logic s_aw_ready; + + logic s_ar_valid; + logic [AXI_ADDR_WIDTH-1:0] s_ar_addr; + logic [2:0] s_ar_prot; + logic [3:0] s_ar_region; + logic [7:0] s_ar_len; + logic [2:0] s_ar_size; + logic [1:0] s_ar_burst; + logic s_ar_lock; + logic [3:0] s_ar_cache; + logic [3:0] s_ar_qos; + logic [AXI_ID_WIDTH-1:0] s_ar_id; + logic [AXI_USER_WIDTH-1:0] s_ar_user; + logic s_ar_ready; + + logic s_w_valid; + logic [AXI_DATA_WIDTH-1:0] s_w_data; + logic [AXI_STRB_WIDTH-1:0] s_w_strb; + logic [AXI_USER_WIDTH-1:0] s_w_user; + logic s_w_last; + logic s_w_ready; + + logic s_r_valid; + logic [AXI_DATA_WIDTH-1:0] s_r_data; + logic [1:0] s_r_resp; + logic s_r_last; + logic [AXI_ID_WIDTH-1:0] s_r_id; + logic [AXI_USER_WIDTH-1:0] s_r_user; + logic s_r_ready; + + logic s_b_valid; + logic [1:0] s_b_resp; + logic [AXI_ID_WIDTH-1:0] s_b_id; + logic [AXI_USER_WIDTH-1:0] s_b_user; + logic s_b_ready; + + logic s_trans_req; + logic s_trans_we, + s_trans_atop_r; + logic [AXI_ID_WIDTH-1:0] s_trans_id; + logic [AXI_ADDR_WIDTH-1:0] s_trans_add; + logic s_trans_r_valid; + + // AXI2PER REQUEST CHANNEL + axi2per_req_channel + #( + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ) + ) + req_channel_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .cluster_id_i ( cluster_id_i ), + + .axi_slave_aw_valid_i ( s_aw_valid ), + .axi_slave_aw_addr_i ( s_aw_addr ), + .axi_slave_aw_prot_i ( s_aw_prot ), + .axi_slave_aw_region_i ( s_aw_region ), + .axi_slave_aw_len_i ( s_aw_len ), + .axi_slave_aw_size_i ( s_aw_size ), + .axi_slave_aw_burst_i ( s_aw_burst ), + .axi_slave_aw_lock_i ( s_aw_lock ), + .axi_slave_aw_atop_i ( s_aw_atop ), + .axi_slave_aw_cache_i ( s_aw_cache ), + .axi_slave_aw_qos_i ( s_aw_qos ), + .axi_slave_aw_id_i ( s_aw_id ), + .axi_slave_aw_user_i ( s_aw_user ), + .axi_slave_aw_ready_o ( s_aw_ready ), + + .axi_slave_ar_valid_i ( s_ar_valid ), + .axi_slave_ar_addr_i ( s_ar_addr ), + .axi_slave_ar_prot_i ( s_ar_prot ), + .axi_slave_ar_region_i ( s_ar_region ), + .axi_slave_ar_len_i ( s_ar_len ), + .axi_slave_ar_size_i ( s_ar_size ), + .axi_slave_ar_burst_i ( s_ar_burst ), + .axi_slave_ar_lock_i ( s_ar_lock ), + .axi_slave_ar_cache_i ( s_ar_cache ), + .axi_slave_ar_qos_i ( s_ar_qos ), + .axi_slave_ar_id_i ( s_ar_id ), + .axi_slave_ar_user_i ( s_ar_user ), + .axi_slave_ar_ready_o ( s_ar_ready ), + + .axi_slave_w_valid_i ( s_w_valid ), + .axi_slave_w_data_i ( s_w_data ), + .axi_slave_w_strb_i ( s_w_strb ), + .axi_slave_w_user_i ( s_w_user ), + .axi_slave_w_last_i ( s_w_last ), + .axi_slave_w_ready_o ( s_w_ready ), + + .per_master_req_o ( per_master_req_o ), + .per_master_add_o ( per_master_add_o ), + .per_master_we_o ( per_master_we_no ), + .per_master_atop_o ( per_master_atop_o ), + .per_master_wdata_o ( per_master_wdata_o ), + .per_master_be_o ( per_master_be_o ), + .per_master_gnt_i ( per_master_gnt_i ), + + .trans_req_o ( s_trans_req ), + .trans_we_o ( s_trans_we ), + .trans_atop_r_o ( s_trans_atop_r ), + .trans_id_o ( s_trans_id ), + .trans_add_o ( s_trans_add ), + .trans_r_valid_i ( s_trans_r_valid ), + + .busy_o ( busy_o ) + ); + + // AXI2PER RESPONSE CHANNEL + axi2per_res_channel + #( + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ) + ) + res_channel_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .axi_slave_r_valid_o ( s_r_valid ), + .axi_slave_r_data_o ( s_r_data ), + .axi_slave_r_resp_o ( s_r_resp ), + .axi_slave_r_last_o ( s_r_last ), + .axi_slave_r_id_o ( s_r_id ), + .axi_slave_r_user_o ( s_r_user ), + .axi_slave_r_ready_i ( s_r_ready ), + + .axi_slave_b_valid_o ( s_b_valid ), + .axi_slave_b_resp_o ( s_b_resp ), + .axi_slave_b_id_o ( s_b_id ), + .axi_slave_b_user_o ( s_b_user ), + .axi_slave_b_ready_i ( s_b_ready ), + + .per_master_r_valid_i ( per_master_r_valid_i ), + .per_master_r_opc_i ( per_master_r_opc_i ), + .per_master_r_rdata_i ( per_master_r_rdata_i ), + + .trans_req_i ( s_trans_req ), + .trans_we_i ( s_trans_we ), + .trans_atop_r_i ( s_trans_atop_r ), + .trans_id_i ( s_trans_id ), + .trans_add_i ( s_trans_add ), + .trans_r_valid_o ( s_trans_r_valid ) + ); + + + + + // AXI WRITE ADDRESS CHANNEL BUFFER + axi_aw_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) + aw_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_slave_aw_valid_i ), + .slave_addr_i ( axi_slave_aw_addr_i ), + .slave_prot_i ( axi_slave_aw_prot_i ), + .slave_region_i ( axi_slave_aw_region_i ), + .slave_len_i ( axi_slave_aw_len_i ), + .slave_size_i ( axi_slave_aw_size_i ), + .slave_burst_i ( axi_slave_aw_burst_i ), + .slave_lock_i ( axi_slave_aw_lock_i ), + .slave_atop_i ( axi_slave_aw_atop_i ), + .slave_cache_i ( axi_slave_aw_cache_i ), + .slave_qos_i ( axi_slave_aw_qos_i ), + .slave_id_i ( axi_slave_aw_id_i ), + .slave_user_i ( axi_slave_aw_user_i ), + .slave_ready_o ( axi_slave_aw_ready_o ), + + .master_valid_o ( s_aw_valid ), + .master_addr_o ( s_aw_addr ), + .master_prot_o ( s_aw_prot ), + .master_region_o ( s_aw_region ), + .master_len_o ( s_aw_len ), + .master_size_o ( s_aw_size ), + .master_burst_o ( s_aw_burst ), + .master_lock_o ( s_aw_lock ), + .master_atop_o ( s_aw_atop ), + .master_cache_o ( s_aw_cache ), + .master_qos_o ( s_aw_qos ), + .master_id_o ( s_aw_id ), + .master_user_o ( s_aw_user ), + .master_ready_i ( s_aw_ready ) + ); + + // AXI READ ADDRESS CHANNEL BUFFER + axi_ar_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) + ar_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_slave_ar_valid_i ), + .slave_addr_i ( axi_slave_ar_addr_i ), + .slave_prot_i ( axi_slave_ar_prot_i ), + .slave_region_i ( axi_slave_ar_region_i ), + .slave_len_i ( axi_slave_ar_len_i ), + .slave_size_i ( axi_slave_ar_size_i ), + .slave_burst_i ( axi_slave_ar_burst_i ), + .slave_lock_i ( axi_slave_ar_lock_i ), + .slave_cache_i ( axi_slave_ar_cache_i ), + .slave_qos_i ( axi_slave_ar_qos_i ), + .slave_id_i ( axi_slave_ar_id_i ), + .slave_user_i ( axi_slave_ar_user_i ), + .slave_ready_o ( axi_slave_ar_ready_o ), + + .master_valid_o ( s_ar_valid ), + .master_addr_o ( s_ar_addr ), + .master_prot_o ( s_ar_prot ), + .master_region_o ( s_ar_region ), + .master_len_o ( s_ar_len ), + .master_size_o ( s_ar_size ), + .master_burst_o ( s_ar_burst ), + .master_lock_o ( s_ar_lock ), + .master_cache_o ( s_ar_cache ), + .master_qos_o ( s_ar_qos ), + .master_id_o ( s_ar_id ), + .master_user_o ( s_ar_user ), + .master_ready_i ( s_ar_ready ) + ); + + // WRITE DATA CHANNEL BUFFER + axi_w_buffer + #( + .DATA_WIDTH ( AXI_DATA_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) + w_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_slave_w_valid_i ), + .slave_data_i ( axi_slave_w_data_i ), + .slave_strb_i ( axi_slave_w_strb_i ), + .slave_user_i ( axi_slave_w_user_i ), + .slave_last_i ( axi_slave_w_last_i ), + .slave_ready_o ( axi_slave_w_ready_o ), + + .master_valid_o ( s_w_valid ), + .master_data_o ( s_w_data ), + .master_strb_o ( s_w_strb ), + .master_user_o ( s_w_user ), + .master_last_o ( s_w_last ), + .master_ready_i ( s_w_ready ) + ); + + // READ DATA CHANNEL BUFFER + axi_r_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .DATA_WIDTH ( AXI_DATA_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) + r_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( s_r_valid ), + .slave_data_i ( s_r_data ), + .slave_resp_i ( s_r_resp ), + .slave_user_i ( s_r_user ), + .slave_id_i ( s_r_id ), + .slave_last_i ( s_r_last ), + .slave_ready_o ( s_r_ready ), + + .master_valid_o ( axi_slave_r_valid_o ), + .master_data_o ( axi_slave_r_data_o ), + .master_resp_o ( axi_slave_r_resp_o ), + .master_user_o ( axi_slave_r_user_o ), + .master_id_o ( axi_slave_r_id_o ), + .master_last_o ( axi_slave_r_last_o ), + .master_ready_i ( axi_slave_r_ready_i ) + ); + + // WRITE RESPONSE CHANNEL BUFFER + axi_b_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) + b_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( s_b_valid ), + .slave_resp_i ( s_b_resp ), + .slave_id_i ( s_b_id ), + .slave_user_i ( s_b_user ), + .slave_ready_o ( s_b_ready ), + + .master_valid_o ( axi_slave_b_valid_o ), + .master_resp_o ( axi_slave_b_resp_o ), + .master_id_o ( axi_slave_b_id_o ), + .master_user_o ( axi_slave_b_user_o ), + .master_ready_i ( axi_slave_b_ready_i ) + ); + + `ifndef TARGET_SYNTHESIS + assert property (@(posedge clk_i) disable iff (!rst_ni) + axi_slave_aw_valid_i |-> axi_slave_aw_len_i == '0) + else $error("This module does not support bursts!"); + assert property (@(posedge clk_i) disable iff (!rst_ni) + axi_slave_ar_valid_i |-> axi_slave_ar_len_i == '0) + else $error("This module does not support bursts!"); + assert property (@(posedge clk_i) disable iff (!rst_ni) + axi_slave_aw_valid_i |-> axi_slave_aw_size_i <= 3'd2) + else $error("This module does not support beats wider than 32 bit!"); + assert property (@(posedge clk_i) disable iff (!rst_ni) + axi_slave_ar_valid_i |-> axi_slave_ar_size_i <= 3'd2) + else $error("This module does not support beats wider than 32 bit!"); + `endif + +endmodule diff --git a/hw/deps/axi2per/axi2per_req_channel.sv b/hw/deps/axi2per/axi2per_req_channel.sv new file mode 100644 index 0000000..0437673 --- /dev/null +++ b/hw/deps/axi2per/axi2per_req_channel.sv @@ -0,0 +1,215 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi2per_req_channel #( + // PARAMETERS + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + // LOCAL PARAMETERS --> DO NOT OVERRIDE + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 // DO NOT OVERRIDE +) ( + input logic clk_i, + input logic rst_ni, + + input logic [5:0] cluster_id_i, + + input logic axi_slave_aw_valid_i, + input logic [AXI_ADDR_WIDTH-1:0] axi_slave_aw_addr_i, + input logic [2:0] axi_slave_aw_prot_i, + input logic [3:0] axi_slave_aw_region_i, + input logic [7:0] axi_slave_aw_len_i, + input logic [2:0] axi_slave_aw_size_i, + input logic [1:0] axi_slave_aw_burst_i, + input logic axi_slave_aw_lock_i, + input logic [5:0] axi_slave_aw_atop_i, + input logic [3:0] axi_slave_aw_cache_i, + input logic [3:0] axi_slave_aw_qos_i, + input logic [AXI_ID_WIDTH-1:0] axi_slave_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_aw_user_i, + output logic axi_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input logic axi_slave_ar_valid_i, + input logic [AXI_ADDR_WIDTH-1:0] axi_slave_ar_addr_i, + input logic [2:0] axi_slave_ar_prot_i, + input logic [3:0] axi_slave_ar_region_i, + input logic [7:0] axi_slave_ar_len_i, + input logic [2:0] axi_slave_ar_size_i, + input logic [1:0] axi_slave_ar_burst_i, + input logic axi_slave_ar_lock_i, + input logic [3:0] axi_slave_ar_cache_i, + input logic [3:0] axi_slave_ar_qos_i, + input logic [AXI_ID_WIDTH-1:0] axi_slave_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_ar_user_i, + output logic axi_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input logic axi_slave_w_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_slave_w_data_i, + input logic [AXI_STRB_WIDTH-1:0] axi_slave_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] axi_slave_w_user_i, + input logic axi_slave_w_last_i, + output logic axi_slave_w_ready_o, + + // PERIPHERAL REQUEST CHANNEL + output logic per_master_req_o, + output logic [PER_ADDR_WIDTH-1:0] per_master_add_o, + output logic per_master_we_o, + output logic [5:0] per_master_atop_o, + output logic [31:0] per_master_wdata_o, + output logic [3:0] per_master_be_o, + input logic per_master_gnt_i, + + // CONTROL SIGNALS + output logic trans_req_o, + output logic trans_we_o, + output logic trans_atop_r_o, + output logic [AXI_ID_WIDTH-1:0] trans_id_o, + output logic [AXI_ADDR_WIDTH-1:0] trans_add_o, + input logic trans_r_valid_i, + + // BUSY SIGNAL + output logic busy_o +); + + enum logic {TransIdle, TransPending} state_d, state_q; + + logic inv_wdata; + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + state_q <= TransIdle; + end else begin + state_q <= state_d; + end + end + + // COMPUTE NEXT STATE + always_comb begin + axi_slave_aw_ready_o = 1'b0; + axi_slave_ar_ready_o = 1'b0; + axi_slave_w_ready_o = 1'b0; + + per_master_req_o = 1'b0; + per_master_add_o = '0; + per_master_we_o = 1'b0; + per_master_wdata_o = '0; + per_master_be_o = '0; + + trans_req_o = 1'b0; + trans_id_o = '0; + trans_add_o = '0; + + busy_o = 1'b0; + + state_d = state_q; + + case (state_q) + TransIdle: begin + // Handle request on AR + if (axi_slave_ar_valid_i) begin + per_master_req_o = 1'b1; + per_master_we_o = 1'b1; // write enable is active low + per_master_add_o = axi_slave_ar_addr_i; + + if (per_master_gnt_i) begin + axi_slave_ar_ready_o = 1'b1; + + trans_req_o = 1'b1; + trans_id_o = axi_slave_ar_id_i; + trans_add_o = axi_slave_ar_addr_i; + + state_d = TransPending; + end + // Handle request on AW and W + end else if (axi_slave_aw_valid_i && axi_slave_w_valid_i) begin + per_master_req_o = 1'b1; + per_master_we_o = 1'b0; // write enable is active low + per_master_add_o = axi_slave_aw_addr_i; + + // Multiplex 64-bit W channel to 32-bit peripheral data channel based on the address. + if (axi_slave_aw_addr_i[2]) begin + per_master_be_o = axi_slave_w_strb_i[7:4]; + per_master_wdata_o = axi_slave_w_data_i[63:32]; + end else begin + per_master_be_o = axi_slave_w_strb_i[3:0]; + per_master_wdata_o = axi_slave_w_data_i[31:0]; + end + + if (inv_wdata) begin + per_master_wdata_o = ~per_master_wdata_o; + end + + if (per_master_gnt_i) begin + axi_slave_aw_ready_o = 1'b1; + axi_slave_w_ready_o = 1'b1; + + trans_req_o = 1'b1; + trans_id_o = axi_slave_aw_id_i; + trans_add_o = axi_slave_aw_addr_i; + + state_d = TransPending; + end + end + per_master_add_o = per_master_add_o - (32'h0040_0000 * cluster_id_i); + end + + TransPending: begin + busy_o = 1'b1; + if (trans_r_valid_i) begin + // Received notification from response channel -> transaction completed. + state_d = TransIdle; + end + end + endcase + end + assign trans_we_o = per_master_we_o; + + always_comb begin + inv_wdata = 1'b0; + per_master_atop_o = '0; + trans_atop_r_o = 1'b0; + if (!per_master_we_o && axi_slave_aw_atop_i[5:4] != axi_pkg::ATOP_NONE) begin + if (axi_slave_aw_atop_i == axi_pkg::ATOP_ATOMICSWAP) begin + per_master_atop_o = riscv_defines::AMO_SWAP; + end else begin + case (axi_slave_aw_atop_i[2:0]) + axi_pkg::ATOP_ADD: per_master_atop_o = riscv_defines::AMO_ADD; + axi_pkg::ATOP_CLR: begin + inv_wdata = 1'b1; + per_master_atop_o = riscv_defines::AMO_AND; + end + axi_pkg::ATOP_EOR: per_master_atop_o = riscv_defines::AMO_XOR; + axi_pkg::ATOP_SET: per_master_atop_o = riscv_defines::AMO_OR; + axi_pkg::ATOP_SMAX: per_master_atop_o = riscv_defines::AMO_MAX; + axi_pkg::ATOP_SMIN: per_master_atop_o = riscv_defines::AMO_MIN; + axi_pkg::ATOP_UMAX: per_master_atop_o = riscv_defines::AMO_MAXU; + axi_pkg::ATOP_UMIN: per_master_atop_o = riscv_defines::AMO_MINU; + endcase + if (axi_slave_aw_atop_i[5:4] == axi_pkg::ATOP_ATOMICLOAD) begin + trans_atop_r_o = 1'b1; + end + end + end + end + + `ifndef TARGET_SYNTHESIS + assert property (@(posedge clk_i) disable iff (!rst_ni) + axi_slave_aw_atop_i != axi_pkg::ATOP_ATOMICCMP) + else $error("Atomic compare-and-swap not supported!"); + `endif + +endmodule diff --git a/hw/deps/axi2per/axi2per_res_channel.sv b/hw/deps/axi2per/axi2per_res_channel.sv new file mode 100644 index 0000000..4c7700e --- /dev/null +++ b/hw/deps/axi2per/axi2per_res_channel.sv @@ -0,0 +1,183 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi2per_res_channel #( + // PARAMETERS + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3 +) ( + input logic clk_i, + input logic rst_ni, + + // PERIPHERAL INTERCONNECT MASTER + //*************************************** + //RESPONSE CHANNEL + input logic per_master_r_valid_i, + input logic per_master_r_opc_i, + input logic [31:0] per_master_r_rdata_i, + + // AXI4 MASTER + //*************************************** + // READ DATA CHANNEL + output logic axi_slave_r_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_slave_r_data_o, + output logic [1:0] axi_slave_r_resp_o, + output logic axi_slave_r_last_o, + output logic [AXI_ID_WIDTH-1:0] axi_slave_r_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_slave_r_user_o, + input logic axi_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output logic axi_slave_b_valid_o, + output logic [1:0] axi_slave_b_resp_o, + output logic [AXI_ID_WIDTH-1:0] axi_slave_b_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_slave_b_user_o, + input logic axi_slave_b_ready_i, + + // CONTROL SIGNALS + input logic trans_req_i, + input logic trans_we_i, + input logic trans_atop_r_i, + input logic [AXI_ID_WIDTH-1:0] trans_id_i, + input logic [AXI_ADDR_WIDTH-1:0] trans_add_i, + output logic trans_r_valid_o +); + + logic [AXI_DATA_WIDTH-1:0] s_axi_slave_r_data; + + logic [31:0] s_per_master_r_data; + + logic s_trans_add_alignment, //0 --> aligned to 64bit, 1--> not aligned to 64bit + s_trans_atop_r_buf, + s_trans_we_buf; + logic [AXI_ID_WIDTH-1:0] s_trans_id_buf; + + enum logic [1:0] {Idle, Pending, HoldB, HoldR} state_d, state_q; + + always_comb begin + axi_slave_r_valid_o = 1'b0; + axi_slave_r_data_o = '0; + axi_slave_r_last_o = 1'b0; + + axi_slave_b_valid_o = 1'b0; + + state_d = state_q; + + unique case (state_q) + Idle: begin + if (per_master_r_valid_i) begin + state_d = Pending; + end + end + + Pending: begin + if (s_trans_we_buf) begin // read + axi_slave_r_data_o = s_axi_slave_r_data; + axi_slave_r_last_o = 1'b1; + axi_slave_r_valid_o = 1'b1; + if (axi_slave_r_ready_i) begin + state_d = Idle; + end + end else begin // write + axi_slave_b_valid_o = 1'b1; + if (axi_slave_b_ready_i) begin + state_d = Idle; + end + if (s_trans_atop_r_buf) begin // ATOP with R response + axi_slave_r_data_o = s_axi_slave_r_data; + axi_slave_r_last_o = 1'b1; + axi_slave_r_valid_o = 1'b1; + case ({axi_slave_b_ready_i, axi_slave_r_ready_i}) + 2'b01: state_d = HoldB; + 2'b10: state_d = HoldR; + 2'b11: state_d = Idle; + endcase + end + end + end + + HoldB: begin + axi_slave_b_valid_o = 1'b1; + if (axi_slave_b_ready_i) begin + state_d = Idle; + end + end + + HoldR: begin + axi_slave_r_data_o = s_axi_slave_r_data; + axi_slave_r_last_o = 1'b1; + axi_slave_r_valid_o = 1'b1; + if (axi_slave_r_ready_i) begin + state_d = Idle; + end + end + + default: state_d = Idle; + endcase + end + + assign trans_r_valid_o = axi_slave_b_valid_o | axi_slave_r_valid_o; + assign axi_slave_b_id_o = s_trans_id_buf; + assign axi_slave_r_id_o = s_trans_id_buf; + + // Demultiplex the 32-bit data of the peripheral bus to the 64-bit AXI R channel. + always_comb begin + if (!s_trans_add_alignment) begin + s_axi_slave_r_data = {32'b0, s_per_master_r_data}; + end else begin + s_axi_slave_r_data = {s_per_master_r_data, 32'b0}; + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + s_per_master_r_data <= '0; + s_trans_add_alignment <= 1'b0; + s_trans_atop_r_buf <= 1'b0; + s_trans_id_buf <= '0; + s_trans_we_buf <= 1'b0; + state_q <= Idle; + end else begin + if (per_master_r_valid_i) begin + s_per_master_r_data <= per_master_r_rdata_i; + end + if (trans_req_i) begin + s_trans_add_alignment <= trans_add_i[2]; + s_trans_atop_r_buf <= trans_atop_r_i; + s_trans_id_buf <= trans_id_i; + s_trans_we_buf <= trans_we_i; + end + state_q <= state_d; + end + end + + // UNUSED SIGNALS + assign axi_slave_r_resp_o = '0; + assign axi_slave_r_user_o = '0; + assign axi_slave_b_resp_o = '0; + assign axi_slave_b_user_o = '0; + + `ifndef VERILATOR + `ifndef TARGET_SYNTHESIS + default disable iff (!rst_ni); + assert property (@(posedge clk_i) per_master_r_valid_i |-> state_q == Idle) + else $error("Lost response on peripheral bus!"); + assert property (@(posedge clk_i) trans_req_i |-> state_q == Idle) + else $error("Lost transfer request!"); + `endif + `endif + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_res_tbl.sv b/hw/deps/axi_riscv_atomics/src/axi_res_tbl.sv new file mode 100644 index 0000000..657e6f5 --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_res_tbl.sv @@ -0,0 +1,89 @@ +// Copyright (c) 2018 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. + +// AXI Reservation Table +module axi_res_tbl #( + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_ID_WIDTH = 0 +) ( + input logic clk_i, + input logic rst_ni, + input logic [AXI_ADDR_WIDTH-1:0] check_clr_addr_i, + input logic [AXI_ID_WIDTH-1:0] check_id_i, + input logic check_clr_excl_i, + output logic check_res_o, + input logic check_clr_req_i, + output logic check_clr_gnt_o, + input logic [AXI_ADDR_WIDTH-1:0] set_addr_i, + input logic [AXI_ID_WIDTH-1:0] set_id_i, + input logic set_req_i, + output logic set_gnt_o +); + + localparam integer N_IDS = 2**AXI_ID_WIDTH; + + // Declarations of Signals and Types + logic [N_IDS-1:0][AXI_ADDR_WIDTH-1:0] tbl_d, tbl_q; + logic clr, + set; + + generate for (genvar i = 0; i < N_IDS; ++i) begin: gen_tbl + always_comb begin + tbl_d[i] = tbl_q[i]; + if (set && i == set_id_i) begin + tbl_d[i] = set_addr_i; + end else if (clr && tbl_q[i] == check_clr_addr_i) begin + tbl_d[i] = '0; + end + end + end endgenerate + + // Table-Managing Logic + always_comb begin + clr = 1'b0; + set = 1'b0; + set_gnt_o = 1'b0; + check_res_o = 1'b0; + check_clr_gnt_o = 1'b0; + + if (check_clr_req_i) begin + automatic logic match = (tbl_q[check_id_i] == check_clr_addr_i); + check_clr_gnt_o = 1'b1; + check_res_o = match; + clr = !(check_clr_excl_i && !match); + end else if (set_req_i) begin + set = 1'b1; + set_gnt_o = 1'b1; + end + end + + // Registers + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + tbl_q <= '0; + end else begin + tbl_q <= tbl_d; + end + end + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (AXI_ADDR_WIDTH > 0) + else $fatal(1, "AXI_ADDR_WIDTH must be greater than 0!"); + assert (AXI_ID_WIDTH > 0) + else $fatal(1, "AXI_ID_WIDTH must be greater than 0!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_riscv_amos.sv b/hw/deps/axi_riscv_atomics/src/axi_riscv_amos.sv new file mode 100644 index 0000000..98b3a73 --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_riscv_amos.sv @@ -0,0 +1,1075 @@ +// Copyright (c) 2018 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. + +// AXI RISC-V Atomic Operations (AMOs) Adapter +// +// This adapter implements atomic memory operations in accordance with the RVWMO memory consistency +// model. +// +// Interface notes: +// - This module has combinational paths between AXI inputs and outputs for minimum latency. Add +// slices upstream or downstream or in both directions if combinatorial paths become too long. +// The module adheres to the AXI ready/valid dependency specification to prevent combinatorial +// loops. + +module axi_riscv_amos #( + // AXI Parameters + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_DATA_WIDTH = 0, + parameter int unsigned AXI_ID_WIDTH = 0, + parameter int unsigned AXI_USER_WIDTH = 0, + // Maximum number of AXI write transactions outstanding at the same time + parameter int unsigned AXI_MAX_WRITE_TXNS = 0, + // Word width of the widest RISC-V processor that can issue requests to this module. + // 32 for RV32; 64 for RV64, where both 32-bit (.W suffix) and 64-bit (.D suffix) AMOs are + // supported if `aw_strb` is set correctly. + parameter int unsigned RISCV_WORD_WIDTH = 0, + /// Derived Parameters (do NOT change manually!) + localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + + /// Slave Interface + input logic [AXI_ADDR_WIDTH-1:0] slv_aw_addr_i, + input logic [2:0] slv_aw_prot_i, + input logic [3:0] slv_aw_region_i, + input logic [5:0] slv_aw_atop_i, + input logic [7:0] slv_aw_len_i, + input logic [2:0] slv_aw_size_i, + input logic [1:0] slv_aw_burst_i, + input logic slv_aw_lock_i, + input logic [3:0] slv_aw_cache_i, + input logic [3:0] slv_aw_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_aw_user_i, + output logic slv_aw_ready_o, + input logic slv_aw_valid_i, + + input logic [AXI_ADDR_WIDTH-1:0] slv_ar_addr_i, + input logic [2:0] slv_ar_prot_i, + input logic [3:0] slv_ar_region_i, + input logic [7:0] slv_ar_len_i, + input logic [2:0] slv_ar_size_i, + input logic [1:0] slv_ar_burst_i, + input logic slv_ar_lock_i, + input logic [3:0] slv_ar_cache_i, + input logic [3:0] slv_ar_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_ar_user_i, + output logic slv_ar_ready_o, + input logic slv_ar_valid_i, + + input logic [AXI_DATA_WIDTH-1:0] slv_w_data_i, + input logic [AXI_STRB_WIDTH-1:0] slv_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] slv_w_user_i, + input logic slv_w_last_i, + output logic slv_w_ready_o, + input logic slv_w_valid_i, + + output logic [AXI_DATA_WIDTH-1:0] slv_r_data_o, + output logic [1:0] slv_r_resp_o, + output logic slv_r_last_o, + output logic [AXI_ID_WIDTH-1:0] slv_r_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_r_user_o, + input logic slv_r_ready_i, + output logic slv_r_valid_o, + + output logic [1:0] slv_b_resp_o, + output logic [AXI_ID_WIDTH-1:0] slv_b_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_b_user_o, + input logic slv_b_ready_i, + output logic slv_b_valid_o, + + /// Master Interface + output logic [AXI_ADDR_WIDTH-1:0] mst_aw_addr_o, + output logic [2:0] mst_aw_prot_o, + output logic [3:0] mst_aw_region_o, + output logic [5:0] mst_aw_atop_o, + output logic [7:0] mst_aw_len_o, + output logic [2:0] mst_aw_size_o, + output logic [1:0] mst_aw_burst_o, + output logic mst_aw_lock_o, + output logic [3:0] mst_aw_cache_o, + output logic [3:0] mst_aw_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_aw_user_o, + input logic mst_aw_ready_i, + output logic mst_aw_valid_o, + + output logic [AXI_ADDR_WIDTH-1:0] mst_ar_addr_o, + output logic [2:0] mst_ar_prot_o, + output logic [3:0] mst_ar_region_o, + output logic [7:0] mst_ar_len_o, + output logic [2:0] mst_ar_size_o, + output logic [1:0] mst_ar_burst_o, + output logic mst_ar_lock_o, + output logic [3:0] mst_ar_cache_o, + output logic [3:0] mst_ar_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_ar_user_o, + input logic mst_ar_ready_i, + output logic mst_ar_valid_o, + + output logic [AXI_DATA_WIDTH-1:0] mst_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] mst_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] mst_w_user_o, + output logic mst_w_last_o, + input logic mst_w_ready_i, + output logic mst_w_valid_o, + + input logic [AXI_DATA_WIDTH-1:0] mst_r_data_i, + input logic [1:0] mst_r_resp_i, + input logic mst_r_last_i, + input logic [AXI_ID_WIDTH-1:0] mst_r_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_r_user_i, + output logic mst_r_ready_o, + input logic mst_r_valid_i, + + input logic [1:0] mst_b_resp_i, + input logic [AXI_ID_WIDTH-1:0] mst_b_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_b_user_i, + output logic mst_b_ready_o, + input logic mst_b_valid_i +); + + localparam int unsigned OUTSTND_BURSTS_WIDTH = $clog2(AXI_MAX_WRITE_TXNS+1); + localparam int unsigned AXI_ALU_RATIO = AXI_DATA_WIDTH/RISCV_WORD_WIDTH; + + // State types + typedef enum logic [1:0] { FEEDTHROUGH_AW, WAIT_RESULT_AW, SEND_AW } aw_state_t; + aw_state_t aw_state_d, aw_state_q; + + typedef enum logic [2:0] { FEEDTHROUGH_W, WAIT_DATA_W, WAIT_RESULT_W, WAIT_CHANNEL_W, SEND_W } w_state_t; + w_state_t w_state_d, w_state_q; + + typedef enum logic [1:0] { FEEDTHROUGH_B, WAIT_COMPLETE_B, WAIT_CHANNEL_B, SEND_B } b_state_t; + b_state_t b_state_d, b_state_q; + + typedef enum logic [1:0] { FEEDTHROUGH_AR, WAIT_CHANNEL_AR, SEND_AR } ar_state_t; + ar_state_t ar_state_d, ar_state_q; + + typedef enum logic [1:0] { FEEDTHROUGH_R, WAIT_DATA_R, WAIT_CHANNEL_R, SEND_R } r_state_t; + r_state_t r_state_d, r_state_q; + + typedef enum logic [1:0] { NONE, INVALID, LOAD, STORE } atop_req_t; + atop_req_t atop_valid_d, atop_valid_q; + + // Signal declarations + // Transaction FF + logic [AXI_ADDR_WIDTH-1:0] addr_d, addr_q; + logic [AXI_ID_WIDTH-1:0] id_d, id_q; + logic [AXI_STRB_WIDTH-1:0] strb_d, strb_q; + logic [2:0] size_d, size_q; + logic [5:0] atop_d, atop_q; + logic [3:0] cache_d, cache_q; + logic [2:0] prot_d, prot_q; + logic [3:0] qos_d, qos_q; + logic [3:0] region_d, region_q; + logic [1:0] r_resp_d, r_resp_q; + logic [AXI_USER_WIDTH-1:0] aw_user_d, aw_user_q, + w_user_d, w_user_q, + r_user_d, r_user_q; + // Data FF + logic [AXI_DATA_WIDTH-1:0] w_data_d, w_data_q; // AMO operand + logic [AXI_DATA_WIDTH-1:0] r_data_d, r_data_q; // Data from memory + logic [AXI_DATA_WIDTH-1:0] result_d, result_q; // Result of AMO operation + logic w_d_valid_d, w_d_valid_q, // AMO operand valid + r_d_valid_d, r_d_valid_q; // Data from memory valid + // Counters + logic [OUTSTND_BURSTS_WIDTH-1:0] aw_trans_d, aw_trans_q; // AW transaction in flight downstream + logic [OUTSTND_BURSTS_WIDTH-1:0] w_cnt_d, w_cnt_q; // Outstanding W beats + logic [OUTSTND_BURSTS_WIDTH-1:0] w_cnt_req_d, w_cnt_req_q; // W beats until AMO can read W + logic [OUTSTND_BURSTS_WIDTH-1:0] w_cnt_inj_d, w_cnt_inj_q; // W beats until AMO can insert its W + // States + logic adapter_ready; + logic transaction_collision; + logic force_wf_d, force_wf_q; + logic start_wf_d, start_wf_q; + logic b_resp_valid; + logic aw_valid, aw_ready, aw_free, + w_valid, w_ready, w_free, + b_valid, b_ready, b_free, + ar_valid, ar_ready, ar_free, + r_valid, r_ready, r_free; + // ALU Signals + logic [RISCV_WORD_WIDTH-1:0] alu_operand_a; + logic [RISCV_WORD_WIDTH-1:0] alu_operand_b; + logic [RISCV_WORD_WIDTH-1:0] alu_result; + logic [AXI_DATA_WIDTH-1:0] alu_result_ext; + logic [AXI_ALU_RATIO-1:0][RISCV_WORD_WIDTH-1:0] op_a; + logic [AXI_ALU_RATIO-1:0][RISCV_WORD_WIDTH-1:0] op_b; + logic [AXI_ALU_RATIO-1:0][RISCV_WORD_WIDTH-1:0] op_a_sign_ext; + logic [AXI_ALU_RATIO-1:0][RISCV_WORD_WIDTH-1:0] op_b_sign_ext; + logic [AXI_ALU_RATIO-1:0][RISCV_WORD_WIDTH-1:0] res; + logic [AXI_STRB_WIDTH-1:0][7:0] strb_ext; + logic sign_a; + logic sign_b; + + /** + * Calculate ready signals and channel states + */ + + // Check if all state machines are ready for the next atomic request + assign adapter_ready = (aw_state_q == FEEDTHROUGH_AW) && + ( w_state_q == FEEDTHROUGH_W ) && + ( b_state_q == FEEDTHROUGH_B ) && + (ar_state_q == FEEDTHROUGH_AR) && + ( r_state_q == FEEDTHROUGH_R ); + + // Calculate if the channels are free + assign aw_free = ~aw_valid | aw_ready; + assign w_free = ~ w_valid | w_ready; + assign b_free = ~ b_valid | b_ready; + assign ar_free = ~ar_valid | ar_ready; + assign r_free = ~ r_valid | r_ready; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + aw_valid <= 0; + aw_ready <= 0; + w_valid <= 0; + w_ready <= 0; + b_valid <= 0; + b_ready <= 0; + ar_valid <= 0; + ar_ready <= 0; + r_valid <= 0; + r_ready <= 0; + end else begin + aw_valid <= mst_aw_valid_o; + aw_ready <= mst_aw_ready_i; + w_valid <= mst_w_valid_o; + w_ready <= mst_w_ready_i; + b_valid <= slv_b_valid_o; + b_ready <= slv_b_ready_i; + ar_valid <= mst_ar_valid_o; + ar_ready <= mst_ar_ready_i; + r_valid <= slv_r_valid_o; + r_ready <= slv_r_ready_i; + end + end + + // Calculate if the request interferes with the ongoing atomic transaction + // The protected bytes go from addr_q up to addr_q + (1 << size_q) - 1 + // TODO Bursts need special treatment + assign transaction_collision = (slv_aw_addr_i < ( addr_q + (8'h01 << size_q))) & + ( addr_q < (slv_aw_addr_i + (8'h01 << slv_aw_size_i))); + + always_comb begin : calc_atop_valid + atop_valid_d = atop_valid_q; + if (adapter_ready) begin + atop_valid_d = NONE; + if (slv_aw_valid_i && slv_aw_atop_i) begin + // Default is invalid request + atop_valid_d = INVALID; + // Valid load operation + if ((slv_aw_atop_i == axi_pkg::ATOP_ATOMICSWAP) || + (slv_aw_atop_i[5:3] == {axi_pkg::ATOP_ATOMICLOAD , axi_pkg::ATOP_LITTLE_END})) begin + atop_valid_d = LOAD; + end + // Valid store operation + if (slv_aw_atop_i[5:3] == {axi_pkg::ATOP_ATOMICSTORE, axi_pkg::ATOP_LITTLE_END}) begin + atop_valid_d = STORE; + end + // Invalidate valid request if control signals do not match + // Burst or exclusive access + if (slv_aw_len_i | slv_aw_lock_i) begin + atop_valid_d = INVALID; + end + // Unsupported size + if (slv_aw_size_i > $clog2(RISCV_WORD_WIDTH/8)) begin + atop_valid_d = INVALID; + end + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_atop_valid + if(~rst_ni) begin + atop_valid_q <= NONE; + end else begin + atop_valid_q <= atop_valid_d; + end + end + + /** + * Write Channel: AW, W, B + */ + + /*==================================================================== + = AW = + ====================================================================*/ + always_comb begin : axi_aw_channel + // Defaults AXI Bus + mst_aw_id_o = slv_aw_id_i; + mst_aw_addr_o = slv_aw_addr_i; + mst_aw_len_o = slv_aw_len_i; + mst_aw_size_o = slv_aw_size_i; + mst_aw_burst_o = slv_aw_burst_i; + mst_aw_lock_o = slv_aw_lock_i; + mst_aw_cache_o = slv_aw_cache_i; + mst_aw_prot_o = slv_aw_prot_i; + mst_aw_qos_o = slv_aw_qos_i; + mst_aw_region_o = slv_aw_region_i; + mst_aw_atop_o = 6'b0; + mst_aw_user_o = slv_aw_user_i; + // Defaults FF + addr_d = addr_q; + id_d = id_q; + size_d = size_q; + atop_d = atop_q; + cache_d = cache_q; + prot_d = prot_q; + qos_d = qos_q; + region_d = region_q; + aw_user_d = aw_user_q; + w_cnt_inj_d = w_cnt_inj_q; + // State Machine + aw_state_d = aw_state_q; + + // Default control: Block AW channel if... + if (slv_aw_valid_i && slv_aw_atop_i) begin + // Block if atomic request + mst_aw_valid_o = 1'b0; + slv_aw_ready_o = 1'b0; + end else if (w_cnt_q == AXI_MAX_WRITE_TXNS || aw_trans_q == AXI_MAX_WRITE_TXNS) begin + // Block if counter is overflowing + mst_aw_valid_o = 1'b0; + slv_aw_ready_o = 1'b0; + end else if (force_wf_q && aw_free) begin // TODO: no not instantly block the channel but only if its free + // Block if the adapter is in force wait-free mode + mst_aw_valid_o = 1'b0; + slv_aw_ready_o = 1'b0; + end else if (slv_aw_valid_i && transaction_collision && !adapter_ready) begin + // Block requests to the same address as current atomic transaction + mst_aw_valid_o = 1'b0; + slv_aw_ready_o = 1'b0; + end else begin + // Forward + mst_aw_valid_o = slv_aw_valid_i; + slv_aw_ready_o = mst_aw_ready_i; + end + + // Count W burst to know when to inject the W data + if (w_cnt_inj_q && mst_w_valid_o && mst_w_ready_i && mst_w_last_o) begin + w_cnt_inj_d = w_cnt_inj_q - 1; + end + + unique case (aw_state_q) + + FEEDTHROUGH_AW: begin + // Feedthrough slave to master until atomic operation is detected + if (slv_aw_valid_i && slv_aw_atop_i && adapter_ready) begin + // Acknowledge atomic transaction + slv_aw_ready_o = 1'b1; + // Remember request + atop_d = slv_aw_atop_i; + addr_d = slv_aw_addr_i; + id_d = slv_aw_id_i; + size_d = slv_aw_size_i; + cache_d = slv_aw_cache_i; + prot_d = slv_aw_prot_i; + qos_d = slv_aw_qos_i; + region_d = slv_aw_region_i; + aw_user_d = slv_aw_user_i; + // If valid AMO --> wait for result + if (atop_valid_d != INVALID) begin + aw_state_d = WAIT_RESULT_AW; + end + end + + if (start_wf_q) begin + // Forced wait-free state --> wait for ALU once more + aw_state_d = WAIT_RESULT_AW; + end + + + end // FEEDTHROUGH_AW + + WAIT_RESULT_AW, SEND_AW: begin + // If the result is ready and the channel is free --> inject AW request + if ((r_d_valid_q && w_d_valid_q && aw_free) || (aw_state_q == SEND_AW)) begin + // Block + slv_aw_ready_o = 1'b0; + // Make write request + mst_aw_valid_o = 1'b1; + mst_aw_addr_o = addr_q; + mst_aw_len_o = 8'h00; + mst_aw_id_o = id_q; + mst_aw_size_o = size_q; + mst_aw_burst_o = 2'b00; + mst_aw_lock_o = ~force_wf_q; + mst_aw_cache_o = cache_q; + mst_aw_prot_o = prot_q; + mst_aw_qos_o = qos_q; + mst_aw_region_o = region_q; + mst_aw_user_o = aw_user_q; + // Check if request is acknowledged + if (mst_aw_ready_i) begin + aw_state_d = FEEDTHROUGH_AW; + end else begin + aw_state_d = SEND_AW; + end + // Remember outstanding W beats before injected request + if (aw_state_q == WAIT_RESULT_AW) begin + if (w_cnt_q && mst_w_valid_o && mst_w_ready_i && mst_w_last_o) begin + w_cnt_inj_d = w_cnt_q - 1; + end else begin + w_cnt_inj_d = w_cnt_q; + end + end + end + end // WAIT_RESULT_AW, SEND_AW + + default: aw_state_d = FEEDTHROUGH_AW; + + endcase + end // axi_aw_channel + + /*==================================================================== + = W = + ====================================================================*/ + always_comb begin : axi_w_channel + // Defaults AXI Bus + mst_w_data_o = slv_w_data_i; + mst_w_strb_o = slv_w_strb_i; + mst_w_last_o = slv_w_last_i; + mst_w_user_o = slv_w_user_i; + // Defaults FF + strb_d = strb_q; + w_user_d = w_user_q; + w_data_d = w_data_q; + result_d = result_q; + w_d_valid_d = w_d_valid_q; + w_cnt_req_d = w_cnt_req_q; + // State Machine + w_state_d = w_state_q; + + // Default control + // Make sure no data is sent without knowing if it's atomic + if (w_cnt_q == 0) begin + // Stall W as it precedes the AW request + slv_w_ready_o = 1'b0; + mst_w_valid_o = 1'b0; + end else begin + mst_w_valid_o = slv_w_valid_i; + slv_w_ready_o = mst_w_ready_i; + end + + unique case (w_state_q) + + FEEDTHROUGH_W: begin + if (adapter_ready) begin + // Reset read flag + w_d_valid_d = 1'b0; + result_d = '0; + + if (atop_valid_d != NONE) begin + // Check if data is also available and does not belong to previous request + if (w_cnt_q == 0) begin + // Block downstream + mst_w_valid_o = 1'b0; + // Fetch data and wait for all data + slv_w_ready_o = 1'b1; + if (slv_w_valid_i) begin + if (atop_valid_d != INVALID) begin + w_data_d = slv_w_data_i; + strb_d = slv_w_strb_i; + w_user_d = slv_w_user_i; + w_d_valid_d = 1'b1; + w_state_d = WAIT_RESULT_W; + end + end else begin + w_cnt_req_d = '0; + w_state_d = WAIT_DATA_W; + end + end else begin + // Remember the amount of outstanding bursts and count down + if (mst_w_valid_o && mst_w_ready_i && mst_w_last_o) begin + w_cnt_req_d = w_cnt_q - 1; + end else begin + w_cnt_req_d = w_cnt_q; + end + w_state_d = WAIT_DATA_W; + end + end + end + + if (start_wf_q) begin + // Forced wait-free state --> wait for ALU once more + w_state_d = WAIT_RESULT_W; + end + + end // FEEDTHROUGH_W + + WAIT_DATA_W: begin + // Count W beats until data arrives that belongs to the AMO request + if (w_cnt_req_q == 0) begin + // Block downstream + mst_w_valid_o = 1'b0; + // Ready upstream + slv_w_ready_o = 1'b1; + + if (slv_w_valid_i) begin + if (atop_valid_q == INVALID) begin + w_state_d = FEEDTHROUGH_W; + end else begin + w_data_d = slv_w_data_i; + strb_d = slv_w_strb_i; + w_user_d = slv_w_user_i; + w_d_valid_d = 1'b1; + w_state_d = WAIT_RESULT_W; + end + end + end else if (mst_w_valid_o && mst_w_ready_i && mst_w_last_o) begin + w_cnt_req_d = w_cnt_req_q - 1; + end + end // WAIT_DATA_W + + WAIT_RESULT_W: begin + // If the result is ready, try to write it + if (r_d_valid_q && w_d_valid_q && aw_free) begin + // Check if W channel is free and make sure data is not interleaved + result_d = alu_result_ext; + if (w_free && w_cnt_q == 0) begin + // Block + slv_w_ready_o = 1'b0; + // Send write data + mst_w_valid_o = 1'b1; + mst_w_data_o = alu_result_ext; + mst_w_last_o = 1'b1; + mst_w_strb_o = strb_q; + mst_w_user_o = w_user_q; + if (mst_w_ready_i) begin + w_state_d = FEEDTHROUGH_W; + end else begin + w_state_d = SEND_W; + end + end else begin + w_state_d = WAIT_CHANNEL_W; + end + end + end // WAIT_RESULT_W + + WAIT_CHANNEL_W, SEND_W: begin + // Wait to not interleave the data + if ((w_free && w_cnt_inj_q == 0) || (w_state_q == SEND_W)) begin + // Block + slv_w_ready_o = 1'b0; + // Send write data + mst_w_valid_o = 1'b1; + mst_w_data_o = result_q; + mst_w_last_o = 1'b1; + mst_w_strb_o = strb_q; + mst_w_user_o = w_user_q; + if (mst_w_ready_i) begin + w_state_d = FEEDTHROUGH_W; + end else begin + w_state_d = SEND_W; + end + end + end // WAIT_CHANNEL_W, SEND_W + + default: w_state_d = FEEDTHROUGH_W; + + endcase + end // axi_w_channel + + /*==================================================================== + = B = + ====================================================================*/ + always_comb begin : axi_b_channel + // Defaults AXI Bus + mst_b_ready_o = slv_b_ready_i; + slv_b_id_o = mst_b_id_i; + slv_b_resp_o = mst_b_resp_i; + slv_b_user_o = mst_b_user_i; + slv_b_valid_o = mst_b_valid_i; + // Defaults FF + force_wf_d = force_wf_q; + start_wf_d = 1'b0; + b_resp_valid = 1'b0; + // State Machine + b_state_d = b_state_q; + + unique case (b_state_q) + + FEEDTHROUGH_B: begin + if (adapter_ready) begin + if (atop_valid_d == LOAD || atop_valid_d == STORE) begin + // Wait until write is complete + b_state_d = WAIT_COMPLETE_B; + end else if (atop_valid_d == INVALID) begin + // Inject B error resp once the channel is free + if (b_free) begin + // Block downstream + mst_b_ready_o = 1'b0; + // Write B response + slv_b_valid_o = 1'b1; + slv_b_id_o = slv_aw_id_i; + slv_b_resp_o = axi_pkg::RESP_SLVERR; + slv_b_user_o = '0; + if (!slv_b_ready_i) begin + b_state_d = SEND_B; + end + end else begin + b_state_d = WAIT_CHANNEL_B; + end + end + end + end // FEEDTHROUGH_B + + WAIT_CHANNEL_B, SEND_B: begin + if (b_free || (b_state_q == SEND_B)) begin + // Block downstream + mst_b_ready_o = 1'b0; + // Write B response + slv_b_valid_o = 1'b1; + slv_b_id_o = id_q; + slv_b_resp_o = axi_pkg::RESP_SLVERR; + slv_b_user_o = '0; + if (slv_b_ready_i) begin + b_state_d = FEEDTHROUGH_B; + end else begin + b_state_d = SEND_B; + end + end + end // WAIT_CHANNEL_B, SEND_B + + WAIT_COMPLETE_B: begin + if (mst_b_valid_i && (mst_b_id_i == id_q)) begin + // Check if store-conditional was successful + if (mst_b_resp_i == axi_pkg::RESP_OKAY) begin + if (force_wf_q) begin + // We were in wf mode so now we are done + force_wf_d = 1'b0; + b_resp_valid = 1'b1; + b_state_d = FEEDTHROUGH_B; + end else begin + // We were not in wf mode --> catch response + mst_b_ready_o = 1'b1; + slv_b_valid_o = 1'b0; + // Go into wf mode + start_wf_d = 1'b1; + force_wf_d = 1'b1; + end + end else if (mst_b_resp_i == axi_pkg::RESP_EXOKAY) begin + // Modify the B response to regular OK. + b_resp_valid = 1'b1; + slv_b_resp_o = axi_pkg::RESP_OKAY; + if (slv_b_ready_i) begin + b_state_d = FEEDTHROUGH_B; + end + end else begin + b_resp_valid = 1'b1; + b_state_d = FEEDTHROUGH_B; + end + end + end // WAIT_COMPLETE_B + + default: b_state_d = FEEDTHROUGH_B; + + endcase + end // axi_b_channel + + // Keep track of AW requests missing a W and of downstream transactions + always_comb begin + w_cnt_d = w_cnt_q; + aw_trans_d = aw_trans_q; + if (mst_aw_valid_o && mst_aw_ready_i) begin + w_cnt_d += 1; + aw_trans_d += 1; + end + if (mst_w_valid_o && mst_w_ready_i && mst_w_last_o) begin + w_cnt_d -= 1; + end + if (mst_b_valid_i && mst_b_ready_o) begin + aw_trans_d -= 1; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : axi_write_channel_ff + if(~rst_ni) begin + aw_state_q <= FEEDTHROUGH_AW; + w_state_q <= FEEDTHROUGH_W; + b_state_q <= FEEDTHROUGH_B; + aw_trans_q <= '0; + w_cnt_q <= '0; + w_cnt_req_q <= '0; + w_cnt_inj_q <= '0; + force_wf_q <= 1'b0; + start_wf_q <= 1'b0; + addr_q <= '0; + id_q <= '0; + size_q <= '0; + strb_q <= '0; + cache_q <= '0; + prot_q <= '0; + qos_q <= '0; + region_q <= '0; + aw_user_q <= '0; + w_user_q <= '0; + w_data_q <= '0; + result_q <= '0; + w_d_valid_q <= '0; + atop_q <= 6'b0; + end else begin + aw_state_q <= aw_state_d; + w_state_q <= w_state_d; + b_state_q <= b_state_d; + aw_trans_q <= aw_trans_d; + w_cnt_q <= w_cnt_d; + w_cnt_req_q <= w_cnt_req_d; + w_cnt_inj_q <= w_cnt_inj_d; + force_wf_q <= force_wf_d; + start_wf_q <= start_wf_d; + addr_q <= addr_d; + id_q <= id_d; + size_q <= size_d; + strb_q <= strb_d; + cache_q <= cache_d; + prot_q <= prot_d; + qos_q <= qos_d; + region_q <= region_d; + aw_user_q <= aw_user_d; + w_user_q <= w_user_d; + w_data_q <= w_data_d; + result_q <= result_d; + w_d_valid_q <= w_d_valid_d; + atop_q <= atop_d; + end + end + + /** + * Read Channel: AR, R + */ + + /*==================================================================== + = AR = + ====================================================================*/ + always_comb begin : axi_ar_channel + // Defaults AXI Bus + mst_ar_id_o = slv_ar_id_i; + mst_ar_addr_o = slv_ar_addr_i; + mst_ar_len_o = slv_ar_len_i; + mst_ar_size_o = slv_ar_size_i; + mst_ar_burst_o = slv_ar_burst_i; + mst_ar_lock_o = slv_ar_lock_i; + mst_ar_cache_o = slv_ar_cache_i; + mst_ar_prot_o = slv_ar_prot_i; + mst_ar_qos_o = slv_ar_qos_i; + mst_ar_region_o = slv_ar_region_i; + mst_ar_user_o = slv_ar_user_i; + mst_ar_valid_o = 1'b0; + slv_ar_ready_o = 1'b0; + // State Machine + ar_state_d = ar_state_q; + + unique case (ar_state_q) + + FEEDTHROUGH_AR: begin + // Feed through + mst_ar_valid_o = slv_ar_valid_i; + slv_ar_ready_o = mst_ar_ready_i; + + if (adapter_ready && (atop_valid_d == LOAD || atop_valid_d == STORE)) begin + if (ar_free) begin + // Acquire channel + slv_ar_ready_o = 1'b0; + // Immediately start read request + mst_ar_valid_o = 1'b1; + mst_ar_addr_o = slv_aw_addr_i; + mst_ar_id_o = slv_aw_id_i; + mst_ar_len_o = 8'h00; + mst_ar_size_o = slv_aw_size_i; + mst_ar_burst_o = 2'b00; + mst_ar_lock_o = ~force_wf_q; + mst_ar_cache_o = slv_aw_cache_i; + mst_ar_prot_o = slv_aw_prot_i; + mst_ar_qos_o = slv_aw_qos_i; + mst_ar_region_o = slv_aw_region_i; + mst_ar_user_o = slv_aw_user_i; + if (!mst_ar_ready_i) begin + // Hold read request but do not depend on AW + ar_state_d = SEND_AR; + end + end else begin + // Wait until AR is free + ar_state_d = WAIT_CHANNEL_AR; + end + end + + if (start_wf_q) begin + ar_state_d = WAIT_CHANNEL_AR; + end + end // FEEDTHROUGH_AR + + WAIT_CHANNEL_AR, SEND_AR: begin + // Issue read request + if ((ar_free && (aw_trans_q == 0 || force_wf_q == 0)) || (ar_state_q == SEND_AR)) begin + // Inject read request + mst_ar_valid_o = 1'b1; + mst_ar_addr_o = addr_q; + mst_ar_id_o = id_q; + mst_ar_len_o = 8'h00; + mst_ar_size_o = size_q; + mst_ar_burst_o = 2'b00; + mst_ar_lock_o = ~force_wf_q; + mst_ar_cache_o = cache_q; + mst_ar_prot_o = prot_q; + mst_ar_qos_o = qos_q; + mst_ar_region_o = region_q; + mst_ar_user_o = aw_user_q; + if (mst_ar_ready_i) begin + // Request acknowledged + ar_state_d = FEEDTHROUGH_AR; + end else begin + // Hold read request + ar_state_d = SEND_AR; + end + end else begin + // Wait until AR is free + mst_ar_valid_o = slv_ar_valid_i; + slv_ar_ready_o = mst_ar_ready_i; + end + end // WAIT_CHANNEL_AR, SEND_AR + + default: ar_state_d = FEEDTHROUGH_AR; + + endcase + end // axi_ar_channel + + /*==================================================================== + = R = + ====================================================================*/ + always_comb begin : axi_r_channel + // Defaults AXI Bus + mst_r_ready_o = slv_r_ready_i; + slv_r_id_o = mst_r_id_i; + slv_r_data_o = mst_r_data_i; + slv_r_resp_o = mst_r_resp_i; + slv_r_last_o = mst_r_last_i; + slv_r_user_o = mst_r_user_i; + slv_r_valid_o = mst_r_valid_i; + // Defaults FF + r_data_d = r_data_q; + r_resp_d = r_resp_q; + r_user_d = r_user_q; + r_d_valid_d = r_d_valid_q; + // State Machine + r_state_d = r_state_q; + + unique case (r_state_q) + + FEEDTHROUGH_R: begin + if (adapter_ready) begin + // Reset read flag + r_d_valid_d = 1'b0; + + if (atop_valid_d == LOAD || atop_valid_d == STORE) begin + // Wait for R response to read data + r_state_d = WAIT_DATA_R; + end else if (atop_valid_d == INVALID) begin + // Send R response once channel is free + if (r_free) begin + // Acquire the R channel + // Block downstream + mst_r_ready_o = 1'b0; + // Send R error response + slv_r_valid_o = 1'b1; + slv_r_data_o = '0; + slv_r_id_o = slv_aw_id_i; + slv_r_last_o = 1'b1; + slv_r_resp_o = axi_pkg::RESP_SLVERR; + slv_r_user_o = '0; + if (!slv_r_ready_i) begin + // Hold R response + r_state_d = SEND_R; + end + end else begin + r_state_d = WAIT_CHANNEL_R; + end + end + end + + if (start_wf_q) begin + r_d_valid_d = 1'b0; + r_state_d = WAIT_DATA_R; + end + end // FEEDTHROUGH_R + + WAIT_DATA_R: begin + // Read data + if (mst_r_valid_i && (mst_r_id_i == id_q)) begin + // Acknowledge downstream and block upstream + mst_r_ready_o = 1'b1; + slv_r_valid_o = 1'b0; + // Store data + r_data_d = mst_r_data_i; + r_resp_d = mst_r_resp_i; + r_user_d = mst_r_user_i; + r_d_valid_d = 1'b1; + if (atop_valid_q == STORE) begin + r_state_d = FEEDTHROUGH_R; + end else begin + // Wait for B resp before injecting R + r_state_d = WAIT_CHANNEL_R; + end + end + end // WAIT_DATA_R + + WAIT_CHANNEL_R, SEND_R: begin + // Wait for the R channel to become free and B response to be valid + if ((r_free && (b_resp_valid || b_state_q != WAIT_COMPLETE_B)) || (r_state_q == SEND_R)) begin + // Block downstream + mst_r_ready_o = 1'b0; + // Send R response + slv_r_valid_o = 1'b1; + slv_r_data_o = r_data_q; + slv_r_id_o = id_q; + slv_r_last_o = 1'b1; + slv_r_resp_o = r_resp_q; + slv_r_user_o = r_user_q; + if (atop_valid_q == INVALID) begin + slv_r_data_o = '0; + slv_r_resp_o = axi_pkg::RESP_SLVERR; + slv_r_user_o = '0; + end + if (slv_r_ready_i) begin + r_state_d = FEEDTHROUGH_R; + end else begin + r_state_d = SEND_R; + end + end + + if (start_wf_q) begin + r_d_valid_d = 1'b0; + r_state_d = WAIT_DATA_R; + end + end // WAIT_CHANNEL_R, SEND_R + + default: r_state_d = FEEDTHROUGH_R; + + endcase + end // axi_r_channel + + always_ff @(posedge clk_i or negedge rst_ni) begin : axi_read_channel_ff + if(~rst_ni) begin + ar_state_q <= FEEDTHROUGH_AR; + r_state_q <= FEEDTHROUGH_R; + r_data_q <= '0; + r_resp_q <= '0; + r_user_q <= '0; + r_d_valid_q <= 1'b0; + end else begin + ar_state_q <= ar_state_d; + r_state_q <= r_state_d; + r_data_q <= r_data_d; + r_resp_q <= r_resp_d; + r_user_q <= r_user_d; + r_d_valid_q <= r_d_valid_d; + end + end + + /** + * ALU + */ + + assign op_a = r_data_q & strb_ext; + assign op_b = w_data_q & strb_ext; + assign sign_a = |(op_a & ~(strb_ext >> 1)); + assign sign_b = |(op_b & ~(strb_ext >> 1)); + assign alu_result_ext = res; + + generate + if (AXI_ALU_RATIO == 1 && RISCV_WORD_WIDTH == 32) begin + assign alu_operand_a = op_a; + assign alu_operand_b = op_b; + assign res = alu_result; + end else if (AXI_ALU_RATIO == 1 && RISCV_WORD_WIDTH == 64) begin + assign res = alu_result; + always_comb begin + op_a_sign_ext = op_a | ({AXI_ALU_RATIO*RISCV_WORD_WIDTH{sign_a}} & ~strb_ext); + op_b_sign_ext = op_b | ({AXI_ALU_RATIO*RISCV_WORD_WIDTH{sign_b}} & ~strb_ext); + + if (atop_q[2:0] == axi_pkg::ATOP_SMAX || atop_q[2:0] == axi_pkg::ATOP_SMIN) begin + // Sign extend + alu_operand_a = op_a_sign_ext; + alu_operand_b = op_b_sign_ext; + end else begin + // No sign extension necessary + alu_operand_a = op_a; + alu_operand_b = op_b; + end + end + end else begin + always_comb begin + op_a_sign_ext = op_a | ({AXI_ALU_RATIO*RISCV_WORD_WIDTH{sign_a}} & ~strb_ext); + op_b_sign_ext = op_b | ({AXI_ALU_RATIO*RISCV_WORD_WIDTH{sign_b}} & ~strb_ext); + + if (atop_q[2:0] == axi_pkg::ATOP_SMAX || atop_q[2:0] == axi_pkg::ATOP_SMIN) begin + // Sign extend + alu_operand_a = op_a_sign_ext[addr_q[$clog2(AXI_DATA_WIDTH/8)-1:$clog2(RISCV_WORD_WIDTH/8)]]; + alu_operand_b = op_b_sign_ext[addr_q[$clog2(AXI_DATA_WIDTH/8)-1:$clog2(RISCV_WORD_WIDTH/8)]]; + end else begin + // No sign extension necessary + alu_operand_a = op_a[addr_q[$clog2(AXI_DATA_WIDTH/8)-1:$clog2(RISCV_WORD_WIDTH/8)]]; + alu_operand_b = op_b[addr_q[$clog2(AXI_DATA_WIDTH/8)-1:$clog2(RISCV_WORD_WIDTH/8)]]; + end + res = '0; + res[addr_q[$clog2(AXI_DATA_WIDTH/8)-1:$clog2(RISCV_WORD_WIDTH/8)]] = alu_result; + end + end + endgenerate + + generate + for (genvar i = 0; i < AXI_STRB_WIDTH; i++) begin + always_comb begin + if (strb_q[i]) begin + strb_ext[i] = 8'hFF; + end else begin + strb_ext[i] = 8'h00; + end + end + end + endgenerate + + axi_riscv_amos_alu #( + .DATA_WIDTH ( RISCV_WORD_WIDTH ) + ) i_amo_alu ( + .amo_op_i ( atop_q ), + .amo_operand_a_i ( alu_operand_a ), + .amo_operand_b_i ( alu_operand_b ), + .amo_result_o ( alu_result ) + ); + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (AXI_ADDR_WIDTH > 0) + else $fatal(1, "AXI_ADDR_WIDTH must be greater than 0!"); + assert (AXI_DATA_WIDTH > 0) + else $fatal(1, "AXI_DATA_WIDTH must be greater than 0!"); + assert (AXI_ID_WIDTH > 0) + else $fatal(1, "AXI_ID_WIDTH must be greater than 0!"); + assert (AXI_MAX_WRITE_TXNS > 0) + else $fatal(1, "AXI_MAX_WRITE_TXNS must be greater than 0!"); + assert (RISCV_WORD_WIDTH == 32 || RISCV_WORD_WIDTH == 64) + else $fatal(1, "RISCV_WORD_WIDTH must be 32 or 64!"); + assert (RISCV_WORD_WIDTH <= AXI_DATA_WIDTH) + else $fatal(1, "RISCV_WORD_WIDTH must not be greater than AXI_DATA_WIDTH!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_riscv_amos_alu.sv b/hw/deps/axi_riscv_atomics/src/axi_riscv_amos_alu.sv new file mode 100644 index 0000000..40a52b0 --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_riscv_amos_alu.sv @@ -0,0 +1,78 @@ +// Copyright (c) 2018 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. + +// AXI RISC-V Atomic Operations (AMOs) ALU +module axi_riscv_amos_alu # ( + parameter int unsigned DATA_WIDTH = 0 +) ( + input logic [5:0] amo_op_i, + input logic [DATA_WIDTH-1:0] amo_operand_a_i, + input logic [DATA_WIDTH-1:0] amo_operand_b_i, + output logic [DATA_WIDTH-1:0] amo_result_o +); + + logic [DATA_WIDTH:0] adder_sum; + logic [DATA_WIDTH:0] adder_operand_a, adder_operand_b; + + assign adder_sum = adder_operand_a + adder_operand_b; + + always_comb begin + + adder_operand_a = $signed(amo_operand_a_i); + adder_operand_b = $signed(amo_operand_b_i); + + amo_result_o = amo_operand_a_i; + + if (amo_op_i == axi_pkg::ATOP_ATOMICSWAP) begin + // Swap operation + amo_result_o = amo_operand_b_i; + end else if ((amo_op_i[5:4] == axi_pkg::ATOP_ATOMICLOAD) | (amo_op_i[5:4] == axi_pkg::ATOP_ATOMICSTORE)) begin + // Load operation + unique case (amo_op_i[2:0]) + // the default is to output operand_a + axi_pkg::ATOP_ADD: amo_result_o = adder_sum[DATA_WIDTH-1:0]; + axi_pkg::ATOP_CLR: amo_result_o = amo_operand_a_i & (~amo_operand_b_i); + axi_pkg::ATOP_SET: amo_result_o = amo_operand_a_i | amo_operand_b_i; + axi_pkg::ATOP_EOR: amo_result_o = amo_operand_a_i ^ amo_operand_b_i; + axi_pkg::ATOP_SMAX: begin + adder_operand_b = -$signed(amo_operand_b_i); + amo_result_o = adder_sum[DATA_WIDTH] ? amo_operand_b_i : amo_operand_a_i; + end + axi_pkg::ATOP_SMIN: begin + adder_operand_b = -$signed(amo_operand_b_i); + amo_result_o = adder_sum[DATA_WIDTH] ? amo_operand_a_i : amo_operand_b_i; + end + axi_pkg::ATOP_UMAX: begin + adder_operand_a = $unsigned(amo_operand_a_i); + adder_operand_b = -$unsigned(amo_operand_b_i); + amo_result_o = adder_sum[DATA_WIDTH] ? amo_operand_b_i : amo_operand_a_i; + end + axi_pkg::ATOP_UMIN: begin + adder_operand_a = $unsigned(amo_operand_a_i); + adder_operand_b = -$unsigned(amo_operand_b_i); + amo_result_o = adder_sum[DATA_WIDTH] ? amo_operand_a_i : amo_operand_b_i; + end + default: amo_result_o = '0; + endcase + end + end + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (DATA_WIDTH > 0) + else $fatal(1, "DATA_WIDTH must be greater than 0!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics.sv b/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics.sv new file mode 100644 index 0000000..464f3a0 --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics.sv @@ -0,0 +1,404 @@ +// Copyright (c) 2018 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. + +// AXI RISC-V Atomics ("A" Extension) Adapter +// +// This AXI adapter implements the RISC-V "A" extension and adheres to the RVWMO memory consistency +// model. +// +// Maintainer: Andreas Kurth + +module axi_riscv_atomics #( + /// AXI Parameters + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_DATA_WIDTH = 0, + parameter int unsigned AXI_ID_WIDTH = 0, + parameter int unsigned AXI_USER_WIDTH = 0, + // Maximum number of AXI read bursts outstanding at the same time + parameter int unsigned AXI_MAX_READ_TXNS = 0, + // Maximum number of AXI write bursts outstanding at the same time + parameter int unsigned AXI_MAX_WRITE_TXNS = 0, + // Word width of the widest RISC-V processor that can issue requests to this module. + // 32 for RV32; 64 for RV64, where both 32-bit (.W suffix) and 64-bit (.D suffix) AMOs are + // supported if `aw_strb` is set correctly. + parameter int unsigned RISCV_WORD_WIDTH = 0, + /// Derived Parameters (do NOT change manually!) + localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + + /// Slave Interface + input logic [AXI_ADDR_WIDTH-1:0] slv_aw_addr_i, + input logic [2:0] slv_aw_prot_i, + input logic [3:0] slv_aw_region_i, + input logic [5:0] slv_aw_atop_i, + input logic [7:0] slv_aw_len_i, + input logic [2:0] slv_aw_size_i, + input logic [1:0] slv_aw_burst_i, + input logic slv_aw_lock_i, + input logic [3:0] slv_aw_cache_i, + input logic [3:0] slv_aw_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_aw_user_i, + output logic slv_aw_ready_o, + input logic slv_aw_valid_i, + + input logic [AXI_ADDR_WIDTH-1:0] slv_ar_addr_i, + input logic [2:0] slv_ar_prot_i, + input logic [3:0] slv_ar_region_i, + input logic [7:0] slv_ar_len_i, + input logic [2:0] slv_ar_size_i, + input logic [1:0] slv_ar_burst_i, + input logic slv_ar_lock_i, + input logic [3:0] slv_ar_cache_i, + input logic [3:0] slv_ar_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_ar_user_i, + output logic slv_ar_ready_o, + input logic slv_ar_valid_i, + + input logic [AXI_DATA_WIDTH-1:0] slv_w_data_i, + input logic [AXI_STRB_WIDTH-1:0] slv_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] slv_w_user_i, + input logic slv_w_last_i, + output logic slv_w_ready_o, + input logic slv_w_valid_i, + + output logic [AXI_DATA_WIDTH-1:0] slv_r_data_o, + output logic [1:0] slv_r_resp_o, + output logic slv_r_last_o, + output logic [AXI_ID_WIDTH-1:0] slv_r_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_r_user_o, + input logic slv_r_ready_i, + output logic slv_r_valid_o, + + output logic [1:0] slv_b_resp_o, + output logic [AXI_ID_WIDTH-1:0] slv_b_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_b_user_o, + input logic slv_b_ready_i, + output logic slv_b_valid_o, + + /// Master Interface + output logic [AXI_ADDR_WIDTH-1:0] mst_aw_addr_o, + output logic [2:0] mst_aw_prot_o, + output logic [3:0] mst_aw_region_o, + output logic [5:0] mst_aw_atop_o, + output logic [7:0] mst_aw_len_o, + output logic [2:0] mst_aw_size_o, + output logic [1:0] mst_aw_burst_o, + output logic mst_aw_lock_o, + output logic [3:0] mst_aw_cache_o, + output logic [3:0] mst_aw_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_aw_user_o, + input logic mst_aw_ready_i, + output logic mst_aw_valid_o, + + output logic [AXI_ADDR_WIDTH-1:0] mst_ar_addr_o, + output logic [2:0] mst_ar_prot_o, + output logic [3:0] mst_ar_region_o, + output logic [7:0] mst_ar_len_o, + output logic [2:0] mst_ar_size_o, + output logic [1:0] mst_ar_burst_o, + output logic mst_ar_lock_o, + output logic [3:0] mst_ar_cache_o, + output logic [3:0] mst_ar_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_ar_user_o, + input logic mst_ar_ready_i, + output logic mst_ar_valid_o, + + output logic [AXI_DATA_WIDTH-1:0] mst_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] mst_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] mst_w_user_o, + output logic mst_w_last_o, + input logic mst_w_ready_i, + output logic mst_w_valid_o, + + input logic [AXI_DATA_WIDTH-1:0] mst_r_data_i, + input logic [1:0] mst_r_resp_i, + input logic mst_r_last_i, + input logic [AXI_ID_WIDTH-1:0] mst_r_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_r_user_i, + output logic mst_r_ready_o, + input logic mst_r_valid_i, + + input logic [1:0] mst_b_resp_i, + input logic [AXI_ID_WIDTH-1:0] mst_b_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_b_user_i, + output logic mst_b_ready_o, + input logic mst_b_valid_i +); + + // Make the entire address range exclusively accessible. Since the AMO adapter does not support + // address ranges, it would not make sense to expose the address range as a parameter of this + // module. + localparam longint unsigned ADDR_BEGIN = '0; + localparam longint unsigned ADDR_END = {AXI_ADDR_WIDTH{1'b1}}; + + logic [AXI_ADDR_WIDTH-1:0] int_axi_aw_addr; + logic [2:0] int_axi_aw_prot; + logic [3:0] int_axi_aw_region; + logic [5:0] int_axi_aw_atop; + logic [7:0] int_axi_aw_len; + logic [2:0] int_axi_aw_size; + logic [1:0] int_axi_aw_burst; + logic int_axi_aw_lock; + logic [3:0] int_axi_aw_cache; + logic [3:0] int_axi_aw_qos; + logic [AXI_ID_WIDTH-1:0] int_axi_aw_id; + logic [AXI_USER_WIDTH-1:0] int_axi_aw_user; + logic int_axi_aw_ready; + logic int_axi_aw_valid; + + logic [AXI_ADDR_WIDTH-1:0] int_axi_ar_addr; + logic [2:0] int_axi_ar_prot; + logic [3:0] int_axi_ar_region; + logic [7:0] int_axi_ar_len; + logic [2:0] int_axi_ar_size; + logic [1:0] int_axi_ar_burst; + logic int_axi_ar_lock; + logic [3:0] int_axi_ar_cache; + logic [3:0] int_axi_ar_qos; + logic [AXI_ID_WIDTH-1:0] int_axi_ar_id; + logic [AXI_USER_WIDTH-1:0] int_axi_ar_user; + logic int_axi_ar_ready; + logic int_axi_ar_valid; + + logic [AXI_DATA_WIDTH-1:0] int_axi_w_data; + logic [AXI_STRB_WIDTH-1:0] int_axi_w_strb; + logic [AXI_USER_WIDTH-1:0] int_axi_w_user; + logic int_axi_w_last; + logic int_axi_w_ready; + logic int_axi_w_valid; + + logic [AXI_DATA_WIDTH-1:0] int_axi_r_data; + logic [1:0] int_axi_r_resp; + logic int_axi_r_last; + logic [AXI_ID_WIDTH-1:0] int_axi_r_id; + logic [AXI_USER_WIDTH-1:0] int_axi_r_user; + logic int_axi_r_ready; + logic int_axi_r_valid; + + logic [1:0] int_axi_b_resp; + logic [AXI_ID_WIDTH-1:0] int_axi_b_id; + logic [AXI_USER_WIDTH-1:0] int_axi_b_user; + logic int_axi_b_ready; + logic int_axi_b_valid; + + axi_riscv_amos #( + .AXI_ADDR_WIDTH (AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH (AXI_DATA_WIDTH), + .AXI_ID_WIDTH (AXI_ID_WIDTH), + .AXI_USER_WIDTH (AXI_USER_WIDTH), + .AXI_MAX_WRITE_TXNS (AXI_MAX_WRITE_TXNS), + .RISCV_WORD_WIDTH (RISCV_WORD_WIDTH) + ) i_amos ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_aw_addr_i ( slv_aw_addr_i ), + .slv_aw_prot_i ( slv_aw_prot_i ), + .slv_aw_region_i ( slv_aw_region_i ), + .slv_aw_atop_i ( slv_aw_atop_i ), + .slv_aw_len_i ( slv_aw_len_i ), + .slv_aw_size_i ( slv_aw_size_i ), + .slv_aw_burst_i ( slv_aw_burst_i ), + .slv_aw_lock_i ( slv_aw_lock_i ), + .slv_aw_cache_i ( slv_aw_cache_i ), + .slv_aw_qos_i ( slv_aw_qos_i ), + .slv_aw_id_i ( slv_aw_id_i ), + .slv_aw_user_i ( slv_aw_user_i ), + .slv_aw_ready_o ( slv_aw_ready_o ), + .slv_aw_valid_i ( slv_aw_valid_i ), + .slv_ar_addr_i ( slv_ar_addr_i ), + .slv_ar_prot_i ( slv_ar_prot_i ), + .slv_ar_region_i ( slv_ar_region_i ), + .slv_ar_len_i ( slv_ar_len_i ), + .slv_ar_size_i ( slv_ar_size_i ), + .slv_ar_burst_i ( slv_ar_burst_i ), + .slv_ar_lock_i ( slv_ar_lock_i ), + .slv_ar_cache_i ( slv_ar_cache_i ), + .slv_ar_qos_i ( slv_ar_qos_i ), + .slv_ar_id_i ( slv_ar_id_i ), + .slv_ar_user_i ( slv_ar_user_i ), + .slv_ar_ready_o ( slv_ar_ready_o ), + .slv_ar_valid_i ( slv_ar_valid_i ), + .slv_w_data_i ( slv_w_data_i ), + .slv_w_strb_i ( slv_w_strb_i ), + .slv_w_user_i ( slv_w_user_i ), + .slv_w_last_i ( slv_w_last_i ), + .slv_w_ready_o ( slv_w_ready_o ), + .slv_w_valid_i ( slv_w_valid_i ), + .slv_r_data_o ( slv_r_data_o ), + .slv_r_resp_o ( slv_r_resp_o ), + .slv_r_last_o ( slv_r_last_o ), + .slv_r_id_o ( slv_r_id_o ), + .slv_r_user_o ( slv_r_user_o ), + .slv_r_ready_i ( slv_r_ready_i ), + .slv_r_valid_o ( slv_r_valid_o ), + .slv_b_resp_o ( slv_b_resp_o ), + .slv_b_id_o ( slv_b_id_o ), + .slv_b_user_o ( slv_b_user_o ), + .slv_b_ready_i ( slv_b_ready_i ), + .slv_b_valid_o ( slv_b_valid_o ), + .mst_aw_addr_o ( int_axi_aw_addr ), + .mst_aw_prot_o ( int_axi_aw_prot ), + .mst_aw_region_o ( int_axi_aw_region ), + .mst_aw_atop_o ( int_axi_aw_atop ), + .mst_aw_len_o ( int_axi_aw_len ), + .mst_aw_size_o ( int_axi_aw_size ), + .mst_aw_burst_o ( int_axi_aw_burst ), + .mst_aw_lock_o ( int_axi_aw_lock ), + .mst_aw_cache_o ( int_axi_aw_cache ), + .mst_aw_qos_o ( int_axi_aw_qos ), + .mst_aw_id_o ( int_axi_aw_id ), + .mst_aw_user_o ( int_axi_aw_user ), + .mst_aw_ready_i ( int_axi_aw_ready ), + .mst_aw_valid_o ( int_axi_aw_valid ), + .mst_ar_addr_o ( int_axi_ar_addr ), + .mst_ar_prot_o ( int_axi_ar_prot ), + .mst_ar_region_o ( int_axi_ar_region ), + .mst_ar_len_o ( int_axi_ar_len ), + .mst_ar_size_o ( int_axi_ar_size ), + .mst_ar_burst_o ( int_axi_ar_burst ), + .mst_ar_lock_o ( int_axi_ar_lock ), + .mst_ar_cache_o ( int_axi_ar_cache ), + .mst_ar_qos_o ( int_axi_ar_qos ), + .mst_ar_id_o ( int_axi_ar_id ), + .mst_ar_user_o ( int_axi_ar_user ), + .mst_ar_ready_i ( int_axi_ar_ready ), + .mst_ar_valid_o ( int_axi_ar_valid ), + .mst_w_data_o ( int_axi_w_data ), + .mst_w_strb_o ( int_axi_w_strb ), + .mst_w_user_o ( int_axi_w_user ), + .mst_w_last_o ( int_axi_w_last ), + .mst_w_ready_i ( int_axi_w_ready ), + .mst_w_valid_o ( int_axi_w_valid ), + .mst_r_data_i ( int_axi_r_data ), + .mst_r_resp_i ( int_axi_r_resp ), + .mst_r_last_i ( int_axi_r_last ), + .mst_r_id_i ( int_axi_r_id ), + .mst_r_user_i ( int_axi_r_user ), + .mst_r_ready_o ( int_axi_r_ready ), + .mst_r_valid_i ( int_axi_r_valid ), + .mst_b_resp_i ( int_axi_b_resp ), + .mst_b_id_i ( int_axi_b_id ), + .mst_b_user_i ( int_axi_b_user ), + .mst_b_ready_o ( int_axi_b_ready ), + .mst_b_valid_i ( int_axi_b_valid ) + ); + + axi_riscv_lrsc #( + .ADDR_BEGIN (ADDR_BEGIN), + .ADDR_END (ADDR_END), + .AXI_ADDR_WIDTH (AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH (AXI_DATA_WIDTH), + .AXI_ID_WIDTH (AXI_ID_WIDTH), + .AXI_USER_WIDTH (AXI_USER_WIDTH), + .AXI_MAX_READ_TXNS (AXI_MAX_READ_TXNS), + .AXI_MAX_WRITE_TXNS (AXI_MAX_WRITE_TXNS) + ) i_lrsc ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_aw_addr_i ( int_axi_aw_addr ), + .slv_aw_prot_i ( int_axi_aw_prot ), + .slv_aw_region_i ( int_axi_aw_region ), + .slv_aw_atop_i ( int_axi_aw_atop ), + .slv_aw_len_i ( int_axi_aw_len ), + .slv_aw_size_i ( int_axi_aw_size ), + .slv_aw_burst_i ( int_axi_aw_burst ), + .slv_aw_lock_i ( int_axi_aw_lock ), + .slv_aw_cache_i ( int_axi_aw_cache ), + .slv_aw_qos_i ( int_axi_aw_qos ), + .slv_aw_id_i ( int_axi_aw_id ), + .slv_aw_user_i ( int_axi_aw_user ), + .slv_aw_ready_o ( int_axi_aw_ready ), + .slv_aw_valid_i ( int_axi_aw_valid ), + .slv_ar_addr_i ( int_axi_ar_addr ), + .slv_ar_prot_i ( int_axi_ar_prot ), + .slv_ar_region_i ( int_axi_ar_region ), + .slv_ar_len_i ( int_axi_ar_len ), + .slv_ar_size_i ( int_axi_ar_size ), + .slv_ar_burst_i ( int_axi_ar_burst ), + .slv_ar_lock_i ( int_axi_ar_lock ), + .slv_ar_cache_i ( int_axi_ar_cache ), + .slv_ar_qos_i ( int_axi_ar_qos ), + .slv_ar_id_i ( int_axi_ar_id ), + .slv_ar_user_i ( int_axi_ar_user ), + .slv_ar_ready_o ( int_axi_ar_ready ), + .slv_ar_valid_i ( int_axi_ar_valid ), + .slv_w_data_i ( int_axi_w_data ), + .slv_w_strb_i ( int_axi_w_strb ), + .slv_w_user_i ( int_axi_w_user ), + .slv_w_last_i ( int_axi_w_last ), + .slv_w_ready_o ( int_axi_w_ready ), + .slv_w_valid_i ( int_axi_w_valid ), + .slv_r_data_o ( int_axi_r_data ), + .slv_r_resp_o ( int_axi_r_resp ), + .slv_r_last_o ( int_axi_r_last ), + .slv_r_id_o ( int_axi_r_id ), + .slv_r_user_o ( int_axi_r_user ), + .slv_r_ready_i ( int_axi_r_ready ), + .slv_r_valid_o ( int_axi_r_valid ), + .slv_b_resp_o ( int_axi_b_resp ), + .slv_b_id_o ( int_axi_b_id ), + .slv_b_user_o ( int_axi_b_user ), + .slv_b_ready_i ( int_axi_b_ready ), + .slv_b_valid_o ( int_axi_b_valid ), + .mst_aw_addr_o ( mst_aw_addr_o ), + .mst_aw_prot_o ( mst_aw_prot_o ), + .mst_aw_region_o ( mst_aw_region_o ), + .mst_aw_atop_o ( mst_aw_atop_o ), + .mst_aw_len_o ( mst_aw_len_o ), + .mst_aw_size_o ( mst_aw_size_o ), + .mst_aw_burst_o ( mst_aw_burst_o ), + .mst_aw_lock_o ( mst_aw_lock_o ), + .mst_aw_cache_o ( mst_aw_cache_o ), + .mst_aw_qos_o ( mst_aw_qos_o ), + .mst_aw_id_o ( mst_aw_id_o ), + .mst_aw_user_o ( mst_aw_user_o ), + .mst_aw_ready_i ( mst_aw_ready_i ), + .mst_aw_valid_o ( mst_aw_valid_o ), + .mst_ar_addr_o ( mst_ar_addr_o ), + .mst_ar_prot_o ( mst_ar_prot_o ), + .mst_ar_region_o ( mst_ar_region_o ), + .mst_ar_len_o ( mst_ar_len_o ), + .mst_ar_size_o ( mst_ar_size_o ), + .mst_ar_burst_o ( mst_ar_burst_o ), + .mst_ar_lock_o ( mst_ar_lock_o ), + .mst_ar_cache_o ( mst_ar_cache_o ), + .mst_ar_qos_o ( mst_ar_qos_o ), + .mst_ar_id_o ( mst_ar_id_o ), + .mst_ar_user_o ( mst_ar_user_o ), + .mst_ar_ready_i ( mst_ar_ready_i ), + .mst_ar_valid_o ( mst_ar_valid_o ), + .mst_w_data_o ( mst_w_data_o ), + .mst_w_strb_o ( mst_w_strb_o ), + .mst_w_user_o ( mst_w_user_o ), + .mst_w_last_o ( mst_w_last_o ), + .mst_w_ready_i ( mst_w_ready_i ), + .mst_w_valid_o ( mst_w_valid_o ), + .mst_r_data_i ( mst_r_data_i ), + .mst_r_resp_i ( mst_r_resp_i ), + .mst_r_last_i ( mst_r_last_i ), + .mst_r_id_i ( mst_r_id_i ), + .mst_r_user_i ( mst_r_user_i ), + .mst_r_ready_o ( mst_r_ready_o ), + .mst_r_valid_i ( mst_r_valid_i ), + .mst_b_resp_i ( mst_b_resp_i ), + .mst_b_id_i ( mst_b_id_i ), + .mst_b_user_i ( mst_b_user_i ), + .mst_b_ready_o ( mst_b_ready_o ), + .mst_b_valid_i ( mst_b_valid_i ) + ); + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv b/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv new file mode 100644 index 0000000..024f5d5 --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv @@ -0,0 +1,154 @@ +// Copyright (c) 2018 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. + +// Wrapper for the AXI RISC-V Atomics Adapter that exposes AXI SystemVerilog interfaces. +// +// See the header of `axi_riscv_atomics` for a description. +// +// Maintainer: Andreas Kurth + +module axi_riscv_atomics_wrap #( + /// AXI Parameters + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_DATA_WIDTH = 0, + parameter int unsigned AXI_ID_WIDTH = 0, + parameter int unsigned AXI_USER_WIDTH = 0, + // Maximum number of AXI read bursts outstanding at the same time + parameter int unsigned AXI_MAX_READ_TXNS = 0, + // Maximum number of AXI write bursts outstanding at the same time + parameter int unsigned AXI_MAX_WRITE_TXNS = 0, + // Word width of the widest RISC-V processor that can issue requests to this module. + // 32 for RV32; 64 for RV64, where both 32-bit (.W suffix) and 64-bit (.D suffix) AMOs are + // supported if `aw_strb` is set correctly. + parameter int unsigned RISCV_WORD_WIDTH = 0, + /// Derived Parameters (do NOT change manually!) + localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Master mst, + AXI_BUS.Slave slv +); + + axi_riscv_atomics #( + .AXI_ADDR_WIDTH (AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH (AXI_DATA_WIDTH), + .AXI_ID_WIDTH (AXI_ID_WIDTH), + .AXI_USER_WIDTH (AXI_USER_WIDTH), + .AXI_MAX_READ_TXNS (AXI_MAX_READ_TXNS), + .AXI_MAX_WRITE_TXNS (AXI_MAX_WRITE_TXNS), + .RISCV_WORD_WIDTH (RISCV_WORD_WIDTH) + ) i_atomics ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_aw_addr_i ( slv.aw_addr ), + .slv_aw_prot_i ( slv.aw_prot ), + .slv_aw_region_i ( slv.aw_region ), + .slv_aw_atop_i ( slv.aw_atop ), + .slv_aw_len_i ( slv.aw_len ), + .slv_aw_size_i ( slv.aw_size ), + .slv_aw_burst_i ( slv.aw_burst ), + .slv_aw_lock_i ( slv.aw_lock ), + .slv_aw_cache_i ( slv.aw_cache ), + .slv_aw_qos_i ( slv.aw_qos ), + .slv_aw_id_i ( slv.aw_id ), + .slv_aw_user_i ( slv.aw_user ), + .slv_aw_ready_o ( slv.aw_ready ), + .slv_aw_valid_i ( slv.aw_valid ), + .slv_ar_addr_i ( slv.ar_addr ), + .slv_ar_prot_i ( slv.ar_prot ), + .slv_ar_region_i ( slv.ar_region ), + .slv_ar_len_i ( slv.ar_len ), + .slv_ar_size_i ( slv.ar_size ), + .slv_ar_burst_i ( slv.ar_burst ), + .slv_ar_lock_i ( slv.ar_lock ), + .slv_ar_cache_i ( slv.ar_cache ), + .slv_ar_qos_i ( slv.ar_qos ), + .slv_ar_id_i ( slv.ar_id ), + .slv_ar_user_i ( slv.ar_user ), + .slv_ar_ready_o ( slv.ar_ready ), + .slv_ar_valid_i ( slv.ar_valid ), + .slv_w_data_i ( slv.w_data ), + .slv_w_strb_i ( slv.w_strb ), + .slv_w_user_i ( slv.w_user ), + .slv_w_last_i ( slv.w_last ), + .slv_w_ready_o ( slv.w_ready ), + .slv_w_valid_i ( slv.w_valid ), + .slv_r_data_o ( slv.r_data ), + .slv_r_resp_o ( slv.r_resp ), + .slv_r_last_o ( slv.r_last ), + .slv_r_id_o ( slv.r_id ), + .slv_r_user_o ( slv.r_user ), + .slv_r_ready_i ( slv.r_ready ), + .slv_r_valid_o ( slv.r_valid ), + .slv_b_resp_o ( slv.b_resp ), + .slv_b_id_o ( slv.b_id ), + .slv_b_user_o ( slv.b_user ), + .slv_b_ready_i ( slv.b_ready ), + .slv_b_valid_o ( slv.b_valid ), + .mst_aw_addr_o ( mst.aw_addr ), + .mst_aw_prot_o ( mst.aw_prot ), + .mst_aw_region_o ( mst.aw_region ), + .mst_aw_atop_o ( mst.aw_atop ), + .mst_aw_len_o ( mst.aw_len ), + .mst_aw_size_o ( mst.aw_size ), + .mst_aw_burst_o ( mst.aw_burst ), + .mst_aw_lock_o ( mst.aw_lock ), + .mst_aw_cache_o ( mst.aw_cache ), + .mst_aw_qos_o ( mst.aw_qos ), + .mst_aw_id_o ( mst.aw_id ), + .mst_aw_user_o ( mst.aw_user ), + .mst_aw_ready_i ( mst.aw_ready ), + .mst_aw_valid_o ( mst.aw_valid ), + .mst_ar_addr_o ( mst.ar_addr ), + .mst_ar_prot_o ( mst.ar_prot ), + .mst_ar_region_o ( mst.ar_region ), + .mst_ar_len_o ( mst.ar_len ), + .mst_ar_size_o ( mst.ar_size ), + .mst_ar_burst_o ( mst.ar_burst ), + .mst_ar_lock_o ( mst.ar_lock ), + .mst_ar_cache_o ( mst.ar_cache ), + .mst_ar_qos_o ( mst.ar_qos ), + .mst_ar_id_o ( mst.ar_id ), + .mst_ar_user_o ( mst.ar_user ), + .mst_ar_ready_i ( mst.ar_ready ), + .mst_ar_valid_o ( mst.ar_valid ), + .mst_w_data_o ( mst.w_data ), + .mst_w_strb_o ( mst.w_strb ), + .mst_w_user_o ( mst.w_user ), + .mst_w_last_o ( mst.w_last ), + .mst_w_ready_i ( mst.w_ready ), + .mst_w_valid_o ( mst.w_valid ), + .mst_r_data_i ( mst.r_data ), + .mst_r_resp_i ( mst.r_resp ), + .mst_r_last_i ( mst.r_last ), + .mst_r_id_i ( mst.r_id ), + .mst_r_user_i ( mst.r_user ), + .mst_r_ready_o ( mst.r_ready ), + .mst_r_valid_i ( mst.r_valid ), + .mst_b_resp_i ( mst.b_resp ), + .mst_b_id_i ( mst.b_id ), + .mst_b_user_i ( mst.b_user ), + .mst_b_ready_o ( mst.b_ready ), + .mst_b_valid_i ( mst.b_valid ) + ); + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (AXI_STRB_WIDTH == AXI_DATA_WIDTH/8) + else $fatal(1, "AXI_STRB_WIDTH must equal AXI_DATA_WIDTH/8!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/axi_riscv_atomics/src/axi_riscv_lrsc.sv b/hw/deps/axi_riscv_atomics/src/axi_riscv_lrsc.sv new file mode 100644 index 0000000..2c5df0e --- /dev/null +++ b/hw/deps/axi_riscv_atomics/src/axi_riscv_lrsc.sv @@ -0,0 +1,987 @@ +// Copyright (c) 2018 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. + +// AXI RISC-V LR/SC Adapter +// +// This adapter adds support for AXI4 exclusive accesses to a slave that natively does not support +// exclusive accesses. It is to be placed between that slave and the upstream master port, so that +// the `mst` port of this module drives the slave and the `slv` port of this module is driven by +// the upstream master. +// +// Exclusive accesses are only enabled for a range of addresses specified through parameters. All +// addresses within that range are guaranteed to fulfill the constraints described in A7.2 of the +// AXI4 standard, both for normal and exclusive memory accesses. Addresses outside that range +// behave like a slave that does not support exclusive memory accesses (see AXI4, A7.2.5). +// +// Limitations: +// - The adapter does not support bursts in exclusive accessing. Only single words can be +// reserved. +// +// Maintainer: Andreas Kurth + +module axi_riscv_lrsc #( + /// Exclusively-accessible address range (closed interval from ADDR_BEGIN to ADDR_END) + parameter longint unsigned ADDR_BEGIN = 0, + parameter longint unsigned ADDR_END = 0, + /// AXI Parameters + parameter int unsigned AXI_ADDR_WIDTH = 0, + parameter int unsigned AXI_DATA_WIDTH = 0, + parameter int unsigned AXI_ID_WIDTH = 0, + parameter int unsigned AXI_USER_WIDTH = 0, + parameter int unsigned AXI_MAX_READ_TXNS = 0, // Maximum number of in-flight read transactions + parameter int unsigned AXI_MAX_WRITE_TXNS = 0, // Maximum number of in-flight write transactions + /// Enable debug prints (not synthesizable). + parameter bit DEBUG = 1'b0, + /// Derived Parameters (do NOT change manually!) + localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8 +) ( + input logic clk_i, + input logic rst_ni, + + /// Slave Interface + input logic [AXI_ADDR_WIDTH-1:0] slv_aw_addr_i, + input logic [2:0] slv_aw_prot_i, + input logic [3:0] slv_aw_region_i, + input logic [5:0] slv_aw_atop_i, + input logic [7:0] slv_aw_len_i, + input logic [2:0] slv_aw_size_i, + input logic [1:0] slv_aw_burst_i, + input logic slv_aw_lock_i, + input logic [3:0] slv_aw_cache_i, + input logic [3:0] slv_aw_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_aw_user_i, + output logic slv_aw_ready_o, + input logic slv_aw_valid_i, + + input logic [AXI_ADDR_WIDTH-1:0] slv_ar_addr_i, + input logic [2:0] slv_ar_prot_i, + input logic [3:0] slv_ar_region_i, + input logic [7:0] slv_ar_len_i, + input logic [2:0] slv_ar_size_i, + input logic [1:0] slv_ar_burst_i, + input logic slv_ar_lock_i, + input logic [3:0] slv_ar_cache_i, + input logic [3:0] slv_ar_qos_i, + input logic [AXI_ID_WIDTH-1:0] slv_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] slv_ar_user_i, + output logic slv_ar_ready_o, + input logic slv_ar_valid_i, + + input logic [AXI_DATA_WIDTH-1:0] slv_w_data_i, + input logic [AXI_STRB_WIDTH-1:0] slv_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] slv_w_user_i, + input logic slv_w_last_i, + output logic slv_w_ready_o, + input logic slv_w_valid_i, + + output logic [AXI_DATA_WIDTH-1:0] slv_r_data_o, + output logic [1:0] slv_r_resp_o, + output logic slv_r_last_o, + output logic [AXI_ID_WIDTH-1:0] slv_r_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_r_user_o, + input logic slv_r_ready_i, + output logic slv_r_valid_o, + + output logic [1:0] slv_b_resp_o, + output logic [AXI_ID_WIDTH-1:0] slv_b_id_o, + output logic [AXI_USER_WIDTH-1:0] slv_b_user_o, + input logic slv_b_ready_i, + output logic slv_b_valid_o, + + /// Master Interface + output logic [AXI_ADDR_WIDTH-1:0] mst_aw_addr_o, + output logic [2:0] mst_aw_prot_o, + output logic [3:0] mst_aw_region_o, + output logic [5:0] mst_aw_atop_o, + output logic [7:0] mst_aw_len_o, + output logic [2:0] mst_aw_size_o, + output logic [1:0] mst_aw_burst_o, + output logic mst_aw_lock_o, + output logic [3:0] mst_aw_cache_o, + output logic [3:0] mst_aw_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_aw_user_o, + input logic mst_aw_ready_i, + output logic mst_aw_valid_o, + + output logic [AXI_ADDR_WIDTH-1:0] mst_ar_addr_o, + output logic [2:0] mst_ar_prot_o, + output logic [3:0] mst_ar_region_o, + output logic [7:0] mst_ar_len_o, + output logic [2:0] mst_ar_size_o, + output logic [1:0] mst_ar_burst_o, + output logic mst_ar_lock_o, + output logic [3:0] mst_ar_cache_o, + output logic [3:0] mst_ar_qos_o, + output logic [AXI_ID_WIDTH-1:0] mst_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] mst_ar_user_o, + input logic mst_ar_ready_i, + output logic mst_ar_valid_o, + + output logic [AXI_DATA_WIDTH-1:0] mst_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] mst_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] mst_w_user_o, + output logic mst_w_last_o, + input logic mst_w_ready_i, + output logic mst_w_valid_o, + + input logic [AXI_DATA_WIDTH-1:0] mst_r_data_i, + input logic [1:0] mst_r_resp_i, + input logic mst_r_last_i, + input logic [AXI_ID_WIDTH-1:0] mst_r_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_r_user_i, + output logic mst_r_ready_o, + input logic mst_r_valid_i, + + input logic [1:0] mst_b_resp_i, + input logic [AXI_ID_WIDTH-1:0] mst_b_id_i, + input logic [AXI_USER_WIDTH-1:0] mst_b_user_i, + output logic mst_b_ready_o, + input logic mst_b_valid_i +); + + // Declarations of Signals and Types + + typedef logic [AXI_ADDR_WIDTH-1:0] axi_addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] axi_data_t; + typedef logic [AXI_ID_WIDTH-1:0] axi_id_t; + typedef logic [1:0] axi_resp_t; + typedef logic [AXI_USER_WIDTH-1:0] axi_user_t; + typedef logic [AXI_ADDR_WIDTH-3:0] res_addr_t; // Track reservations word wise. + + typedef enum logic [1:0] { + B_U='x, B_REGULAR='0, B_EXCLUSIVE, B_INJECT + } b_cmd_t; + + typedef struct packed { + axi_id_t id; + axi_user_t user; + } b_inj_t; + + typedef struct packed { + axi_id_t id; + axi_user_t user; + axi_resp_t resp; + } b_chan_t; + + typedef struct packed { + axi_id_t id; + axi_data_t data; + axi_resp_t resp; + axi_user_t user; + logic last; + } r_chan_t; + + typedef struct packed { + logic excl; + } r_flight_t; + + typedef struct packed { + logic forward; + axi_id_t id; + axi_user_t user; + } w_cmd_t; + + typedef struct packed { + res_addr_t addr; + logic excl; + } w_flight_t; + + typedef struct packed { + w_flight_t data; + logic [$bits(w_flight_t)-1:0] mask; + } wifq_exists_t; + + typedef enum logic { + AR_IDLE, AR_WAIT + } ar_state_t; + + typedef enum logic { + AW_IDLE, AW_WAIT + } aw_state_t; + + typedef struct packed { + axi_addr_t addr; + logic [2:0] prot; + logic [3:0] region; + logic [5:0] atop; + logic [7:0] len; + logic [2:0] size; + logic [1:0] burst; + logic [3:0] cache; + logic [3:0] qos; + axi_id_t id; + axi_user_t user; + } aw_chan_t; + + typedef enum logic { + B_NORMAL, B_FORWARD + } b_state_t; + + axi_id_t ar_push_id, + art_check_id, + b_status_inp_id, + b_status_oup_id, + rifq_oup_id; + + res_addr_t ar_push_addr, + art_check_clr_addr; + + logic ar_push_excl, + ar_push_res; + + logic art_check_clr_excl; + + logic ar_push_valid, ar_push_ready, + art_check_clr_req, art_check_clr_gnt, + art_filter_valid, art_filter_ready, + art_set_req, art_set_gnt; + + logic rifq_inp_req, rifq_inp_gnt, + rifq_oup_req, rifq_oup_gnt, + rifq_oup_pop, + rifq_oup_data_valid; + + r_flight_t rifq_inp_data, + rifq_oup_data; + + logic wifq_exists, + ar_wifq_exists_req, ar_wifq_exists_gnt, + aw_wifq_exists_req, aw_wifq_exists_gnt, + wifq_exists_req, wifq_exists_gnt, + wifq_inp_gnt, + wifq_oup_req, wifq_oup_gnt, + wifq_oup_data_valid; + + wifq_exists_t ar_wifq_exists_inp, + aw_wifq_exists_inp, + wifq_exists_inp; + + b_chan_t slv_b; + + logic slv_b_valid, slv_b_ready; + + r_chan_t slv_r; + + logic slv_r_valid, slv_r_ready; + + logic mst_b_valid, mst_b_ready; + + w_cmd_t w_cmd_inp, w_cmd_oup; + + logic w_cmd_push, w_cmd_pop, + w_cmd_full, w_cmd_empty; + + b_inj_t b_inj_inp, b_inj_oup; + + logic b_inj_push, b_inj_pop, + b_inj_full, b_inj_empty; + + b_cmd_t b_status_inp_cmd, b_status_oup_cmd; + + logic b_status_inp_req, b_status_oup_req, + b_status_inp_gnt, b_status_oup_gnt, + b_status_oup_pop, + b_status_oup_valid; + + logic art_check_res; + + ar_state_t ar_state_d, ar_state_q; + + aw_state_t aw_state_d, aw_state_q; + + b_state_t b_state_d, b_state_q; + + aw_chan_t slv_aw, mst_aw; + + logic mst_aw_valid, mst_aw_ready; + + // AR and R Channel + + // IQ Queue to track in-flight reads + id_queue #( + .ID_WIDTH (AXI_ID_WIDTH), + .CAPACITY (AXI_MAX_READ_TXNS), + .data_t (r_flight_t) + ) i_read_in_flight_queue ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .inp_id_i (ar_push_id), + .inp_data_i (rifq_inp_data), + .inp_req_i (rifq_inp_req), + .inp_gnt_o (rifq_inp_gnt), + .exists_data_i (), + .exists_mask_i (), + .exists_req_i (1'b0), + .exists_o (), + .exists_gnt_o (), + .oup_id_i (rifq_oup_id), + .oup_pop_i (rifq_oup_pop), + .oup_req_i (rifq_oup_req), + .oup_data_o (rifq_oup_data), + .oup_data_valid_o (rifq_oup_data_valid), + .oup_gnt_o (rifq_oup_gnt) + ); + assign rifq_inp_data.excl = ar_push_excl; + + // Fork requests from AR into reservation table and queue of in-flight reads. + stream_fork #( + .N_OUP (2) + ) i_ar_push_fork ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .valid_i (ar_push_valid), + .ready_o (ar_push_ready), + .valid_o ({art_filter_valid, rifq_inp_req}), + .ready_i ({art_filter_ready, rifq_inp_gnt}) + ); + + stream_filter i_art_filter ( + .valid_i (art_filter_valid), + .ready_o (art_filter_ready), + .drop_i (!ar_push_res), + .valid_o (art_set_req), + .ready_i (art_set_gnt) + ); + + // Time-Invariant Signal Assignments + assign mst_ar_addr_o = slv_ar_addr_i; + assign mst_ar_prot_o = slv_ar_prot_i; + assign mst_ar_region_o = slv_ar_region_i; + assign mst_ar_len_o = slv_ar_len_i; + assign mst_ar_size_o = slv_ar_size_i; + assign mst_ar_burst_o = slv_ar_burst_i; + assign mst_ar_lock_o = 1'b0; + assign mst_ar_cache_o = slv_ar_cache_i; + assign mst_ar_qos_o = slv_ar_qos_i; + assign mst_ar_id_o = slv_ar_id_i; + assign mst_ar_user_o = slv_ar_user_i; + assign slv_r.data = mst_r_data_i; + assign slv_r.last = mst_r_last_i; + assign slv_r.id = mst_r_id_i; + assign slv_r.user = mst_r_user_i; + + // Control R Channel + always_comb begin + mst_r_ready_o = 1'b0; + slv_r.resp = 'x; + slv_r_valid = 1'b0; + rifq_oup_id = 'x; + rifq_oup_pop = 1'b0; + rifq_oup_req = 1'b0; + if (mst_r_valid_i && slv_r_ready) begin + rifq_oup_id = mst_r_id_i; + rifq_oup_pop = mst_r_last_i; + rifq_oup_req = 1'b1; + if (rifq_oup_gnt) begin + mst_r_ready_o = 1'b1; + if (mst_r_resp_i[1] == 1'b0) begin + slv_r.resp = {1'b0, rifq_oup_data.excl}; + end else begin + slv_r.resp = mst_r_resp_i; + end + slv_r_valid = 1'b1; + end + end + end + +// pragma translate_off + always @(posedge clk_i) begin + if (~rst_ni) begin + if (rifq_oup_req && rifq_oup_gnt) begin + assert (rifq_oup_data_valid) else $error("Unexpected R with ID %0x!", mst_r_id_i); + end + end + end +// pragma translate_on + + // Control AR Channel + always_comb begin + mst_ar_valid_o = 1'b0; + slv_ar_ready_o = 1'b0; + ar_push_addr = 'x; + ar_push_excl = 'x; + ar_push_id = 'x; + ar_push_res = 'x; + ar_push_valid = 1'b0; + ar_wifq_exists_inp.data.addr = 'x; + ar_wifq_exists_inp.data.excl = 1'b0; + ar_wifq_exists_inp.mask = '1; + ar_wifq_exists_inp.mask[0] = 1'b0; // Don't care on `excl` bit. + ar_wifq_exists_req = 1'b0; + ar_state_d = ar_state_q; + + case (ar_state_q) + + AR_IDLE: begin + if (slv_ar_valid_i) begin + ar_push_addr = slv_ar_addr_i[AXI_ADDR_WIDTH-1:2]; + ar_push_id = slv_ar_id_i; + ar_push_excl = (slv_ar_addr_i >= ADDR_BEGIN && slv_ar_addr_i <= ADDR_END && + slv_ar_lock_i && slv_ar_len_i == 8'h00); + if (ar_push_excl) begin + ar_wifq_exists_inp.data.addr = slv_ar_addr_i[AXI_ADDR_WIDTH-1:2]; + ar_wifq_exists_req = 1'b1; + if (ar_wifq_exists_gnt) begin + ar_push_res = !wifq_exists; + ar_push_valid = 1'b1; + end + end else begin + ar_push_res = 1'b0; + ar_push_valid = 1'b1; + end + if (ar_push_ready) begin + mst_ar_valid_o = 1'b1; + if (mst_ar_ready_i) begin + slv_ar_ready_o = 1'b1; + end else begin + ar_state_d = AR_WAIT; + end + end + end + end + + AR_WAIT: begin + mst_ar_valid_o = slv_ar_valid_i; + slv_ar_ready_o = mst_ar_ready_i; + if (mst_ar_ready_i && mst_ar_valid_o) begin + ar_state_d = AR_IDLE; + end + end + + default: begin + ar_state_d = AR_IDLE; + end + endcase + end + + // AW, W and B Channel + + // FIFO to track commands for W bursts. + fifo_v3 #( + .FALL_THROUGH (1'b0), // TODO: Why is there a combinatorial loop if this is fall-through? + .dtype (w_cmd_t), + .DEPTH (AXI_MAX_WRITE_TXNS) + ) i_w_cmd_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (w_cmd_full), + .empty_o (w_cmd_empty), + .usage_o (), + .data_i (w_cmd_inp), + .push_i (w_cmd_push), + .data_o (w_cmd_oup), + .pop_i (w_cmd_pop) + ); + + // ID Queue to track downstream W bursts and their pending B responses. + id_queue #( + .ID_WIDTH (AXI_ID_WIDTH), + .CAPACITY (AXI_MAX_WRITE_TXNS), + .data_t (b_cmd_t) + ) i_b_status_queue ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .inp_id_i (b_status_inp_id), + .inp_data_i (b_status_inp_cmd), + .inp_req_i (b_status_inp_req), + .inp_gnt_o (b_status_inp_gnt), + .exists_data_i (), + .exists_mask_i (), + .exists_req_i (1'b0), + .exists_o (), + .exists_gnt_o (), + .oup_id_i (b_status_oup_id), + .oup_pop_i (b_status_oup_pop), + .oup_req_i (b_status_oup_req), + .oup_data_o (b_status_oup_cmd), + .oup_data_valid_o (b_status_oup_valid), + .oup_gnt_o (b_status_oup_gnt) + ); + + // ID Queue to track in-flight writes. + id_queue #( + .ID_WIDTH (AXI_ID_WIDTH), + .CAPACITY (AXI_MAX_WRITE_TXNS), + .data_t (w_flight_t) + ) i_write_in_flight_queue ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .inp_id_i (mst_aw_id_o), + .inp_data_i ({mst_aw_addr_o[AXI_ADDR_WIDTH-1:2], slv_aw_lock_i}), + .inp_req_i (mst_aw_valid && mst_aw_ready), + .inp_gnt_o (wifq_inp_gnt), + .exists_data_i (wifq_exists_inp.data), + .exists_mask_i (wifq_exists_inp.mask), + .exists_req_i (wifq_exists_req), + .exists_o (wifq_exists), + .exists_gnt_o (wifq_exists_gnt), + .oup_id_i (mst_b_id_i), + .oup_pop_i (1'b1), + .oup_req_i (wifq_oup_req), + .oup_data_o (), + .oup_data_valid_o (wifq_oup_data_valid), + .oup_gnt_o (wifq_oup_gnt) + ); + +// pragma translate_off + always @(posedge clk_i) begin + if (~rst_ni) begin + if (mst_aw_valid && mst_aw_ready) begin + assert (wifq_inp_gnt) else $error("Missed enqueuing of in-flight write!"); + end + if (wifq_oup_req && wifq_oup_gnt) begin + assert (wifq_oup_data_valid) else $error("Unexpected B!"); + end + end + end +// pragma translate_on + + stream_arbiter #( + .DATA_T (wifq_exists_t), + .N_INP (2) + ) i_wifq_exists_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .inp_data_i ({ar_wifq_exists_inp, aw_wifq_exists_inp}), + .inp_valid_i ({ar_wifq_exists_req, aw_wifq_exists_req}), + .inp_ready_o ({ar_wifq_exists_gnt, aw_wifq_exists_gnt}), + .oup_data_o (wifq_exists_inp), + .oup_valid_o (wifq_exists_req), + .oup_ready_i (wifq_exists_gnt) + ); + + stream_fork #( + .N_OUP (2) + ) i_mst_b_fork ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .valid_i (mst_b_valid_i), + .ready_o (mst_b_ready_o), + .valid_o ({mst_b_valid, wifq_oup_req}), + .ready_i ({mst_b_ready, wifq_oup_gnt}) + ); + + // FIFO to track B responses that are to be injected. + fifo_v3 #( + .FALL_THROUGH (1'b0), + .dtype (b_inj_t), + .DEPTH (AXI_MAX_WRITE_TXNS) + ) i_b_inj_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (b_inj_full), + .empty_o (b_inj_empty), + .usage_o (), + .data_i (b_inj_inp), + .push_i (b_inj_push), + .data_o (b_inj_oup), + .pop_i (b_inj_pop) + ); + + // Fall-through register to hold AW transactin that passed + assign slv_aw = {slv_aw_addr_i, + slv_aw_prot_i, + slv_aw_region_i, + slv_aw_atop_i, + slv_aw_len_i, + slv_aw_size_i, + slv_aw_burst_i, + slv_aw_cache_i, + slv_aw_qos_i, + slv_aw_id_i, + slv_aw_user_i}; + assign {mst_aw_addr_o, + mst_aw_prot_o, + mst_aw_region_o, + mst_aw_atop_o, + mst_aw_len_o, + mst_aw_size_o, + mst_aw_burst_o, + mst_aw_cache_o, + mst_aw_qos_o, + mst_aw_id_o, + mst_aw_user_o} = mst_aw; + + + fall_through_register #( + .T (aw_chan_t) + ) i_aw_trans_reg ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clr_i (1'b0), + .testmode_i (1'b0), + // Input + .valid_i (mst_aw_valid), + .ready_o (mst_aw_ready), + .data_i (slv_aw), + // Output + .valid_o (mst_aw_valid_o), + .ready_i (mst_aw_ready_i), + .data_o (mst_aw) + ); + + // Time-Invariant Signal Assignments + assign mst_aw_lock_o = 1'b0; + assign mst_w_data_o = slv_w_data_i; + assign mst_w_strb_o = slv_w_strb_i; + assign mst_w_user_o = slv_w_user_i; + assign mst_w_last_o = slv_w_last_i; + + // Control AW Channel + always_comb begin + mst_aw_valid = 1'b0; + slv_aw_ready_o = 1'b0; + art_check_clr_addr = 'x; + art_check_id = 'x; + art_check_clr_excl = 'x; + art_check_clr_req = 1'b0; + aw_wifq_exists_inp.data = 'x; + aw_wifq_exists_inp.mask = '1; + aw_wifq_exists_req = 1'b0; + b_status_inp_id = '0; + b_status_inp_cmd = B_U; + b_status_inp_req = 1'b0; + w_cmd_inp = 'x; + w_cmd_push = 1'b0; + aw_state_d = aw_state_q; + + case (aw_state_q) + AW_IDLE: begin + if (slv_aw_valid_i && !w_cmd_full && b_status_inp_gnt && wifq_inp_gnt) begin + // New AW and we are ready to handle it. + if (slv_aw_addr_i >= ADDR_BEGIN && slv_aw_addr_i <= ADDR_END) begin + // Inside exclusively-accessible range. + // Make sure no exclusive AR to the same address is currently waiting. + if (!(slv_ar_valid_i && slv_ar_lock_i && + slv_ar_addr_i[AXI_ADDR_WIDTH-1:2] == slv_aw_addr_i[AXI_ADDR_WIDTH-1:2])) begin + // Make sure no exclusive write to the same address is currently in + // flight. + aw_wifq_exists_inp.data.addr = slv_aw_addr_i[AXI_ADDR_WIDTH-1:2]; + aw_wifq_exists_inp.data.excl = 1'b1; + aw_wifq_exists_req = 1'b1; + if (aw_wifq_exists_gnt && !wifq_exists) begin + // Check reservation and clear identical addresses. + art_check_clr_addr = slv_aw_addr_i[AXI_ADDR_WIDTH-1:2]; + art_check_id = slv_aw_id_i; + art_check_clr_excl = slv_aw_lock_i; + if (mst_aw_ready) begin + art_check_clr_req = 1'b1; + end + if (art_check_clr_gnt) begin + if (slv_aw_lock_i && slv_aw_len_i == 8'h00) begin + // Exclusive access and no burst, so check reservation. + if (art_check_res) begin + // Reservation exists, so forward downstream. + mst_aw_valid = 1'b1; + slv_aw_ready_o = mst_aw_ready; + if (!mst_aw_ready) begin + aw_state_d = AW_WAIT; + end + end else begin + // No reservation exists, so drop AW. + slv_aw_ready_o = 1'b1; + end + // Store command to forward or drop W burst. + w_cmd_inp = '{forward: art_check_res, id: slv_aw_id_i, + user: slv_aw_user_i}; + w_cmd_push = 1'b1; + // Add B status for this ID (exclusive if there is a + // reservation, inject otherwise). + b_status_inp_cmd = art_check_res ? B_EXCLUSIVE : B_INJECT; + end else begin + // Non-exclusive access or burst, so forward downstream. + mst_aw_valid = 1'b1; + slv_aw_ready_o = mst_aw_ready; + // Store command to forward W burst. + w_cmd_inp = '{forward: 1'b1, id: 'x, user: 'x}; + w_cmd_push = 1'b1; + // Track B response as regular-okay. + b_status_inp_cmd = B_REGULAR; + if (!mst_aw_ready) begin + aw_state_d = AW_WAIT; + end + end + b_status_inp_id = slv_aw_id_i; + b_status_inp_req = 1'b1; + end + end + end + end else begin + // Outside exclusively-accessible address range, so bypass any + // modifications. + mst_aw_valid = 1'b1; + slv_aw_ready_o = mst_aw_ready; + if (mst_aw_ready) begin + // Store command to forward W burst. + w_cmd_inp = '{forward: 1'b1, id: 'x, user: 'x}; + w_cmd_push = 1'b1; + // Track B response as regular-okay. + b_status_inp_id = slv_aw_id_i; + b_status_inp_cmd = B_REGULAR; + b_status_inp_req = 1'b1; + end + end + end + end + + AW_WAIT: begin + mst_aw_valid = 1'b1; + slv_aw_ready_o = mst_aw_ready; + if (mst_aw_ready) begin + aw_state_d = AW_IDLE; + end + end + + default: + aw_state_d = AW_IDLE; + endcase + end + +// pragma translate_off + if (DEBUG) begin + always @(posedge clk_i) begin + if (b_status_inp_req && b_status_inp_gnt) begin + $display("%0t: AW added %0x as %0d", $time, b_status_inp_id, b_status_inp_cmd); + end + end + end +// pragma translate_on + + // Control W Channel + always_comb begin + mst_w_valid_o = 1'b0; + slv_w_ready_o = 1'b0; + b_inj_inp = 'x; + b_inj_push = 1'b0; + w_cmd_pop = 1'b0; + if (slv_w_valid_i && !w_cmd_empty && !b_inj_full) begin + if (w_cmd_oup.forward) begin + // Forward + mst_w_valid_o = 1'b1; + slv_w_ready_o = mst_w_ready_i; + end else begin + // Drop + slv_w_ready_o = 1'b1; + end + if (slv_w_ready_o && slv_w_last_i) begin + w_cmd_pop = 1'b1; + if (!w_cmd_oup.forward) begin + // Add command to inject B response. + b_inj_inp = '{id: w_cmd_oup.id, user: w_cmd_oup.user}; + b_inj_push = 1'b1; + end + end + end + end + +// pragma translate_off + if (DEBUG) begin + always @(posedge clk_i) begin + if (b_inj_push) begin + $display("%0t: W added inject for %0x", $time, b_inj_inp.id); + end + end + end +// pragma translate_on + + // Control B Channel + always_comb begin + slv_b.id = mst_b_id_i; + slv_b.resp = mst_b_resp_i; + slv_b.user = mst_b_user_i; + slv_b_valid = 1'b0; + mst_b_ready = 1'b0; + b_inj_pop = 1'b0; + b_status_oup_id = 'x; + b_status_oup_req = 1'b0; + b_state_d = b_state_q; + + case (b_state_q) + B_NORMAL: begin + if (!b_inj_empty) begin + // There is a response to be injected .. + b_status_oup_id = b_inj_oup.id; + b_status_oup_req = 1'b1; + if (b_status_oup_gnt && b_status_oup_valid) begin + if (b_status_oup_cmd == B_INJECT) begin + // .. and the next B for that ID is indeed an injection, so go ahead and + // inject it. + slv_b.id = b_inj_oup.id; + slv_b.resp = axi_pkg::RESP_OKAY; + slv_b.user = b_inj_oup.user; + slv_b_valid = 1'b1; + b_inj_pop = slv_b_ready; + end else begin + // .. but the next B for that ID is *not* an injection, so try to + // forward a B. + b_state_d = B_FORWARD; + end + end + end else if (mst_b_valid) begin + // There is currently no response to be injected, so try to forward a B. + b_status_oup_id = mst_b_id_i; + b_status_oup_req = 1'b1; + if (b_status_oup_gnt && b_status_oup_valid) begin + if (mst_b_resp_i[1] == 1'b0) begin + slv_b.resp = {1'b0, (b_status_oup_cmd == B_EXCLUSIVE)}; + end else begin + slv_b.resp = mst_b_resp_i; + end + slv_b_valid = 1'b1; + mst_b_ready = slv_b_ready; + end + end + end + + B_FORWARD: begin + if (mst_b_valid) begin + b_status_oup_id = mst_b_id_i; + b_status_oup_req = 1'b1; + if (b_status_oup_gnt && b_status_oup_valid) begin + if (mst_b_resp_i[1] == 1'b0) begin + slv_b.resp = {1'b0, (b_status_oup_cmd == B_EXCLUSIVE)}; + end else begin + slv_b.resp = mst_b_resp_i; + end + slv_b_valid = 1'b1; + mst_b_ready = slv_b_ready; + if (slv_b_ready) begin + b_state_d = B_NORMAL; + end + end + end + end + + default: + b_state_d = B_NORMAL; + endcase + end + +// pragma translate_off + always @(posedge clk_i) begin + if (b_status_oup_req && b_status_oup_gnt) begin + assert (b_status_oup_valid); + if ((b_state_q == B_NORMAL && b_inj_empty) || b_state_q == B_FORWARD) begin + assert (b_status_oup_cmd != B_INJECT); + end + end + end +// pragma translate_on + +// pragma translate_off + if (DEBUG) begin + always @(posedge clk_i) begin + if (slv_b_valid && slv_b_ready) begin + if (mst_b_ready) begin + $display("%0t: B forwarded %0x", $time, slv_b.id); + end else begin + $display("%0t: B injected %0x", $time, slv_b.id); + end + end + end + end +// pragma translate_on + + assign b_status_oup_pop = slv_b_valid && slv_b_ready; + + // Register in front of slv_b to prevent changes by FSM while valid and not yet ready. + fall_through_register #( + .T (b_chan_t) + ) slv_b_reg ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clr_i (1'b0), + .testmode_i (1'b0), + + .valid_i (slv_b_valid), + .ready_o (slv_b_ready), + .data_i (slv_b), + + .valid_o (slv_b_valid_o), + .ready_i (slv_b_ready_i), + .data_o ({slv_b_id_o, slv_b_user_o, slv_b_resp_o}) + ); + + // Fall-through register in front of slv_r to remove mutual dependency. + spill_register #( // TODO: Why is there a combinatorial loop if this is a `fall_through_register`? + .T (r_chan_t) + ) slv_r_reg ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .valid_i (slv_r_valid), + .ready_o (slv_r_ready), + .data_i (slv_r), + + .valid_o (slv_r_valid_o), + .ready_i (slv_r_ready_i), + .data_o ({slv_r_id_o, slv_r_data_o, slv_r_resp_o, slv_r_user_o, slv_r_last_o}) + ); + + // AXI Reservation Table + axi_res_tbl #( + .AXI_ADDR_WIDTH (AXI_ADDR_WIDTH-2), // Track reservations word-wise. + .AXI_ID_WIDTH (AXI_ID_WIDTH) + ) i_art ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .check_clr_addr_i (art_check_clr_addr), + .check_id_i (art_check_id), + .check_clr_excl_i (art_check_clr_excl), + .check_res_o (art_check_res), + .check_clr_req_i (art_check_clr_req), + .check_clr_gnt_o (art_check_clr_gnt), + .set_addr_i (ar_push_addr), + .set_id_i (ar_push_id), + .set_req_i (art_set_req), + .set_gnt_o (art_set_gnt) + ); + + // Registers + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + ar_state_q = AR_IDLE; + aw_state_q = AW_IDLE; + b_state_q = B_NORMAL; + end else begin + ar_state_q = ar_state_d; + aw_state_q = aw_state_d; + b_state_q = b_state_d; + end + end + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (ADDR_END > ADDR_BEGIN) + else $fatal(1, "ADDR_END must be greater than ADDR_BEGIN!"); + assert (AXI_ADDR_WIDTH > 0) + else $fatal(1, "AXI_ADDR_WIDTH must be greater than 0!"); + assert (AXI_DATA_WIDTH > 0) + else $fatal(1, "AXI_DATA_WIDTH must be greater than 0!"); + assert (AXI_ID_WIDTH > 0) + else $fatal(1, "AXI_ID_WIDTH must be greater than 0!"); + assert (AXI_MAX_READ_TXNS > 0) + else $fatal(1, "AXI_MAX_READ_TXNS must be greater than 0!"); + assert (AXI_MAX_WRITE_TXNS > 0) + else $fatal(1, "AXI_MAX_WRITE_TXNS must be greater than 0!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/axi_slice/src/axi_ar_buffer.sv b/hw/deps/axi_slice/src/axi_ar_buffer.sv new file mode 100644 index 0000000..e133693 --- /dev/null +++ b/hw/deps/axi_slice/src/axi_ar_buffer.sv @@ -0,0 +1,74 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi_ar_buffer #( + parameter int ID_WIDTH = -1, + parameter int ADDR_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +)( + + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic slave_valid_i, + input logic [ADDR_WIDTH-1:0] slave_addr_i, + input logic [2:0] slave_prot_i, + input logic [3:0] slave_region_i, + input logic [7:0] slave_len_i, + input logic [2:0] slave_size_i, + input logic [1:0] slave_burst_i, + input logic slave_lock_i, + input logic [3:0] slave_cache_i, + input logic [3:0] slave_qos_i, + input logic [ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + + output logic master_valid_o, + output logic [ADDR_WIDTH-1:0] master_addr_o, + output logic [2:0] master_prot_o, + output logic [3:0] master_region_o, + output logic [7:0] master_len_o, + output logic [2:0] master_size_o, + output logic [1:0] master_burst_o, + output logic master_lock_o, + output logic [3:0] master_cache_o, + output logic [3:0] master_qos_o, + output logic [ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in; + logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out; + + assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i} ; + assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; + + + + axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH)) i_axi_single_slice ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_en_i ), + .valid_i ( slave_valid_i ), + .ready_o ( slave_ready_o ), + .data_i ( s_data_in ), + .ready_i ( master_ready_i ), + .valid_o ( master_valid_o ), + .data_o ( s_data_out ) + ); + + +endmodule diff --git a/hw/deps/axi_slice/src/axi_aw_buffer.sv b/hw/deps/axi_slice/src/axi_aw_buffer.sv new file mode 100644 index 0000000..da8ab41 --- /dev/null +++ b/hw/deps/axi_slice/src/axi_aw_buffer.sv @@ -0,0 +1,78 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi_aw_buffer #( + parameter int ID_WIDTH = -1, + parameter int ADDR_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +)( + + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic slave_valid_i, + input logic [ADDR_WIDTH-1:0] slave_addr_i, + input logic [2:0] slave_prot_i, + input logic [3:0] slave_region_i, + input logic [7:0] slave_len_i, + input logic [2:0] slave_size_i, + input logic [1:0] slave_burst_i, + input logic slave_lock_i, + input logic [5:0] slave_atop_i, + input logic [3:0] slave_cache_i, + input logic [3:0] slave_qos_i, + input logic [ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + + output logic master_valid_o, + output logic [ADDR_WIDTH-1:0] master_addr_o, + output logic [2:0] master_prot_o, + output logic [3:0] master_region_o, + output logic [7:0] master_len_o, + output logic [2:0] master_size_o, + output logic [1:0] master_burst_o, + output logic master_lock_o, + output logic [5:0] master_atop_o, + output logic [3:0] master_cache_o, + output logic [3:0] master_qos_o, + output logic [ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + + localparam int unsigned DATA_WIDTH = 29+6+ADDR_WIDTH+USER_WIDTH+ID_WIDTH; + + logic [DATA_WIDTH-1:0] s_data_in; + logic [DATA_WIDTH-1:0] s_data_out; + + + + assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_atop_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i}; + assign {master_cache_o, master_prot_o, master_lock_o, master_atop_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out; + + + axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(DATA_WIDTH)) i_axi_single_slice ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_en_i ), + .valid_i ( slave_valid_i ), + .ready_o ( slave_ready_o ), + .data_i ( s_data_in ), + .ready_i ( master_ready_i ), + .valid_o ( master_valid_o ), + .data_o ( s_data_out ) + ); + +endmodule diff --git a/hw/deps/axi_slice/src/axi_b_buffer.sv b/hw/deps/axi_slice/src/axi_b_buffer.sv new file mode 100644 index 0000000..d2576bb --- /dev/null +++ b/hw/deps/axi_slice/src/axi_b_buffer.sv @@ -0,0 +1,54 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi_b_buffer #( + parameter int ID_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1 +)( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic slave_valid_i, + input logic [1:0] slave_resp_i, + input logic [ID_WIDTH-1:0] slave_id_i, + input logic [USER_WIDTH-1:0] slave_user_i, + output logic slave_ready_o, + + output logic master_valid_o, + output logic [1:0] master_resp_o, + output logic [ID_WIDTH-1:0] master_id_o, + output logic [USER_WIDTH-1:0] master_user_o, + input logic master_ready_i +); + + logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_in; + logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_out; + + assign s_data_in = {slave_id_i, slave_user_i, slave_resp_i}; + assign {master_id_o, master_user_o, master_resp_o} = s_data_out; + + + axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(2+USER_WIDTH+ID_WIDTH)) i_axi_single_slice ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_en_i ), + .valid_i ( slave_valid_i ), + .ready_o ( slave_ready_o ), + .data_i ( s_data_in ), + .ready_i ( master_ready_i ), + .valid_o ( master_valid_o ), + .data_o ( s_data_out ) + ); + +endmodule diff --git a/hw/deps/axi_slice/src/axi_r_buffer.sv b/hw/deps/axi_slice/src/axi_r_buffer.sv new file mode 100644 index 0000000..3c92b25 --- /dev/null +++ b/hw/deps/axi_slice/src/axi_r_buffer.sv @@ -0,0 +1,60 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi_r_buffer #( + parameter ID_WIDTH = 4, + parameter DATA_WIDTH = 64, + parameter USER_WIDTH = 6, + parameter BUFFER_DEPTH = 8, + parameter STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE +)( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic slave_valid_i, + input logic [DATA_WIDTH-1:0] slave_data_i, + input logic [1:0] slave_resp_i, + input logic [USER_WIDTH-1:0] slave_user_i, + input logic [ID_WIDTH-1:0] slave_id_i, + input logic slave_last_i, + output logic slave_ready_o, + + output logic master_valid_o, + output logic [DATA_WIDTH-1:0] master_data_o, + output logic [1:0] master_resp_o, + output logic [USER_WIDTH-1:0] master_user_o, + output logic [ID_WIDTH-1:0] master_id_o, + output logic master_last_o, + input logic master_ready_i +); + + logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_in; + logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_out; + + + assign s_data_in = {slave_id_i, slave_user_i, slave_data_i, slave_resp_i, slave_last_i}; + assign {master_id_o, master_user_o, master_data_o, master_resp_o, master_last_o} = s_data_out; + + axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(3+DATA_WIDTH+USER_WIDTH+ID_WIDTH)) i_axi_single_slice ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_en_i ), + .valid_i ( slave_valid_i ), + .ready_o ( slave_ready_o ), + .data_i ( s_data_in ), + .ready_i ( master_ready_i ), + .valid_o ( master_valid_o ), + .data_o ( s_data_out ) + ); + +endmodule diff --git a/hw/deps/axi_slice/src/axi_single_slice.sv b/hw/deps/axi_slice/src/axi_single_slice.sv new file mode 100644 index 0000000..fe7fbbc --- /dev/null +++ b/hw/deps/axi_slice/src/axi_single_slice.sv @@ -0,0 +1,51 @@ +// Copyright 2018 ETH Zurich and 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. + +/// Wrapper for a generic fifo +module axi_single_slice #( + parameter int BUFFER_DEPTH = -1, + parameter int DATA_WIDTH = -1 +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic testmode_i, + input logic valid_i, + output logic ready_o, + input logic [DATA_WIDTH-1:0] data_i, + + input logic ready_i, + output logic valid_o, + output logic [DATA_WIDTH-1:0] data_o +); + + logic full, empty; + + assign ready_o = ~full; + assign valid_o = ~empty; + + fifo #( + .FALL_THROUGH ( 1'b0 ), + .DATA_WIDTH ( DATA_WIDTH ), + .DEPTH ( BUFFER_DEPTH ) + ) i_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .threshold_o (), // NC + .testmode_i ( testmode_i ), + .full_o ( full ), + .empty_o ( empty ), + .data_i ( data_i ), + .push_i ( valid_i & ready_o ), + .data_o ( data_o ), + .pop_i ( ready_i & valid_o ) + ); + +endmodule diff --git a/hw/deps/axi_slice/src/axi_w_buffer.sv b/hw/deps/axi_slice/src/axi_w_buffer.sv new file mode 100644 index 0000000..0e89a47 --- /dev/null +++ b/hw/deps/axi_slice/src/axi_w_buffer.sv @@ -0,0 +1,55 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module axi_w_buffer #( + parameter int DATA_WIDTH = -1, + parameter int USER_WIDTH = -1, + parameter int BUFFER_DEPTH = -1, + parameter int STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE +)( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + input logic slave_valid_i, + input logic [DATA_WIDTH-1:0] slave_data_i, + input logic [STRB_WIDTH-1:0] slave_strb_i, + input logic [USER_WIDTH-1:0] slave_user_i, + input logic slave_last_i, + output logic slave_ready_o, + + output logic master_valid_o, + output logic [DATA_WIDTH-1:0] master_data_o, + output logic [STRB_WIDTH-1:0] master_strb_o, + output logic [USER_WIDTH-1:0] master_user_o, + output logic master_last_o, + input logic master_ready_i +); + + logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_in; + logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_out; + + assign s_data_in = { slave_user_i, slave_strb_i, slave_data_i, slave_last_i }; + assign { master_user_o, master_strb_o, master_data_o, master_last_o } = s_data_out; + + axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(1+DATA_WIDTH+STRB_WIDTH+USER_WIDTH)) i_axi_single_slice ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_en_i ), + .valid_i ( slave_valid_i ), + .ready_o ( slave_ready_o ), + .data_i ( s_data_in ), + .ready_i ( master_ready_i ), + .valid_o ( master_valid_o ), + .data_o ( s_data_out ) + ); +endmodule diff --git a/hw/deps/axi_slice_dc/src/dc_synchronizer.v b/hw/deps/axi_slice_dc/src/dc_synchronizer.v new file mode 100644 index 0000000..8be6034 --- /dev/null +++ b/hw/deps/axi_slice_dc/src/dc_synchronizer.v @@ -0,0 +1,38 @@ +// Copyright 2015-2018 ETH Zurich and 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. + +module dc_synchronizer (clk, rstn, d_in, d_out); + + parameter WIDTH = 1; + parameter RESET_VALUE = 'h0; + + input clk; + input rstn; + input [WIDTH - 1 : 0] d_in; + output [WIDTH - 1 : 0] d_out; + + reg [WIDTH - 1 : 0] d_middle; + reg [WIDTH - 1 : 0] d_out; + + always @(posedge clk or negedge rstn) + begin: update_state + if (rstn == 1'b0) + begin + d_middle <= RESET_VALUE; + d_out <= RESET_VALUE; + end + else + begin + d_middle <= d_in; + d_out <= d_middle; + end + end + +endmodule diff --git a/hw/deps/axi_slice_dc/src/dc_token_ring.v b/hw/deps/axi_slice_dc/src/dc_token_ring.v new file mode 100644 index 0000000..4c35237 --- /dev/null +++ b/hw/deps/axi_slice_dc/src/dc_token_ring.v @@ -0,0 +1,40 @@ +// Copyright 2015-2018 ETH Zurich and 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. + +module dc_token_ring(clk, rstn, enable, state); + + parameter BUFFER_DEPTH = 8; + parameter RESET_VALUE = 'h3; + + input clk; + input rstn; + input enable; + output [BUFFER_DEPTH - 1 : 0] state; + + reg [BUFFER_DEPTH - 1 : 0] state; + reg [BUFFER_DEPTH - 1 : 0] next_state; + + always @(posedge clk or negedge rstn) + begin: update_state + if (rstn == 1'b0) + state <= RESET_VALUE; + else + state <= next_state; + end + + always @(enable, state) + begin + if (enable) + next_state = {state[BUFFER_DEPTH - 2 : 0], state[BUFFER_DEPTH - 1]}; + else + next_state = state; + end + +endmodule diff --git a/hw/deps/axi_slice_dc/src/dc_token_ring_fifo_dout.v b/hw/deps/axi_slice_dc/src/dc_token_ring_fifo_dout.v new file mode 100644 index 0000000..66deeb2 --- /dev/null +++ b/hw/deps/axi_slice_dc/src/dc_token_ring_fifo_dout.v @@ -0,0 +1,77 @@ +// Copyright 2015-2018 ETH Zurich and 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. + +module dc_token_ring_fifo_dout(clk, rstn, data_async, write_token, read_pointer, data, valid, ready); + + parameter DATA_WIDTH = 10; + parameter BUFFER_DEPTH = 8; + + input [DATA_WIDTH - 1 : 0] data_async; + + input clk; + input rstn; + output [DATA_WIDTH - 1 : 0] data; + output valid; + input ready; + + input [BUFFER_DEPTH - 1 : 0] write_token; + output [BUFFER_DEPTH - 1 : 0] read_pointer; + + wire read_enable; + wire stall; + // Pointers to the write, read addresses (two-hot encoding) + wire [BUFFER_DEPTH - 1 : 0] read_token; + + wire [BUFFER_DEPTH - 1 : 0] write_token_dn; + wire [BUFFER_DEPTH - 1 : 0] empty; + + assign data = data_async; + + assign stall = ~ready; + + // FIFO read/write enable + assign read_enable = (valid & ~stall); + + // Logic to compute the read, write pointers + dc_token_ring + #( + .BUFFER_DEPTH ( BUFFER_DEPTH ), + .RESET_VALUE ( 'h3 ) + ) + read_tr + ( + .clk ( clk ), + .rstn ( rstn ), + .enable ( read_enable ), + .state ( read_token ) + ); + + // Pointers to the write, read addresses (semi-accurate, leveraging the two-hot encoding for extra robustness) + assign read_pointer = {read_token[BUFFER_DEPTH - 3 : 0], read_token[BUFFER_DEPTH - 1 : BUFFER_DEPTH - 2]} & + {read_token[BUFFER_DEPTH - 4 : 0], read_token[BUFFER_DEPTH - 1 : BUFFER_DEPTH - 3]}; + + // Empty detector; if any of the bits is 1, the synchronizer is empty + dc_synchronizer + #( + .WIDTH ( BUFFER_DEPTH ), + .RESET_VALUE ( 'hc ) + ) + empty_synch + ( + .clk ( clk ), + .rstn ( rstn ), + .d_in ( write_token ), + .d_out ( write_token_dn ) + ); + + assign empty = ~write_token_dn & {write_token_dn[0], write_token_dn[BUFFER_DEPTH - 1 : 1]} & {read_pointer[1 : 0], read_pointer[BUFFER_DEPTH - 1 : 2]}; + assign valid = ~(|empty); + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/interfaces/tcdm_bank_mem_bus.sv b/hw/deps/cluster_interconnect/rtl/interfaces/tcdm_bank_mem_bus.sv new file mode 100644 index 0000000..ed9dfe5 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/interfaces/tcdm_bank_mem_bus.sv @@ -0,0 +1,30 @@ +// Copyright 2018 ETH Zurich and 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. + +interface TCDM_BANK_MEM_BUS; + + logic [31:0] wdata; + logic [31:0] add; + logic req; + logic wen; + logic [3:0] be; + logic [31:0] rdata; + + modport Master ( + output wdata, add, req, wen, be, + input rdata + ); + + modport Slave ( + input wdata, add, req, wen, be, + output rdata + ); + +endinterface diff --git a/hw/deps/cluster_interconnect/rtl/interfaces/wide_dma_tcdm.sv b/hw/deps/cluster_interconnect/rtl/interfaces/wide_dma_tcdm.sv new file mode 100644 index 0000000..fd122c1 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/interfaces/wide_dma_tcdm.sv @@ -0,0 +1,39 @@ +// Copyright 2018 ETH Zurich and 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. + +interface WIDE_DMA_TCDM_BUS #( + parameter int unsigned ADDR_WIDTH = -1, + parameter int unsigned DATA_WIDTH = -1 +); + + // Request Channel + logic req; + logic [ADDR_WIDTH-1:0] add; + logic wen; + logic [DATA_WIDTH-1:0] wdata; + logic [DATA_WIDTH/8-1:0] be; + logic gnt; + + // Response Channel + logic r_opc; + logic [DATA_WIDTH-1:0] r_rdata; + logic r_valid; + + modport Master ( + output req,add, wen, wdata, be, + input gnt, r_rdata, r_opc, r_valid + ); + + modport Slave ( + input req,add, wen, wdata, be, + output gnt, r_rdata, r_opc, r_valid + ); + +endinterface diff --git a/hw/deps/cluster_interconnect/rtl/interfaces/xbar_demux_bus.sv b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_demux_bus.sv new file mode 100644 index 0000000..ad6e529 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_demux_bus.sv @@ -0,0 +1,41 @@ +// Copyright 2018 ETH Zurich and 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. + +interface XBAR_DEMUX_BUS; + + // Request Channel + logic barrier; + logic busy; + logic exec_cancel; + logic exec_stall; + logic req; + logic [31:0] add; + logic we; + logic [5:0] atop; + logic [31:0] wdata; + logic [3:0] be; + logic gnt; + + // Response Channel + logic r_gnt; + logic r_valid; + logic [31:0] r_rdata; + + modport Master ( + output barrier, exec_cancel, exec_stall, req, add, we, atop, wdata, be, r_gnt, + input busy, gnt, r_rdata, r_valid + ); + + modport Slave ( + input barrier, exec_cancel, exec_stall, req, add, we, atop, wdata, be, r_gnt, + output busy, gnt, r_rdata, r_valid + ); + +endinterface diff --git a/hw/deps/cluster_interconnect/rtl/interfaces/xbar_periph_bus.sv b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_periph_bus.sv new file mode 100644 index 0000000..446b141 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_periph_bus.sv @@ -0,0 +1,40 @@ +// Copyright 2018 ETH Zurich and 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. + +interface XBAR_PERIPH_BUS #( + parameter int ID_WIDTH = 9 // typically number of cores plus one +); + + // Request Channel + logic req; + logic [31:0] add; + logic wen; + logic [31:0] wdata; + logic [3:0] be; + logic gnt; + logic [ID_WIDTH-1:0] id; + + // Response Channel + logic r_valid; + logic r_opc; + logic [ID_WIDTH-1:0] r_id; + logic [31:0] r_rdata; + + modport Master ( + output req, add, wen, wdata, be, id, + input gnt, r_rdata, r_opc, r_id, r_valid + ); + + modport Slave ( + input req, add, wen, wdata, be, id, + output gnt, r_rdata, r_opc, r_id, r_valid + ); + +endinterface diff --git a/hw/deps/cluster_interconnect/rtl/interfaces/xbar_tcdm_bus.sv b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_tcdm_bus.sv new file mode 100644 index 0000000..06f0b5b --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/interfaces/xbar_tcdm_bus.sv @@ -0,0 +1,36 @@ +// Copyright 2018 ETH Zurich and 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. + +interface XBAR_TCDM_BUS; + + // Request Channel + logic req; + logic [31:0] add; + logic wen; + logic [31:0] wdata; + logic [3:0] be; + logic gnt; + + // Response Channel + logic r_opc; + logic [31:0] r_rdata; + logic r_valid; + + modport Master ( + output req,add, wen, wdata, be, + input gnt, r_rdata, r_opc, r_valid + ); + + modport Slave ( + input req,add, wen, wdata, be, + output gnt, r_rdata, r_opc, r_valid + ); + +endinterface diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_PE_Req.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_PE_Req.sv new file mode 100644 index 0000000..c424ed0 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_PE_Req.sv @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 29/06/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: AddressDecoder_PE_Req // +// Language: SystemVerilog // +// // +// Description: Address Decoder used to generate the individual requests // +// for all the available memory cuts. It backroutes the // +// grants from the Arbitration tree to the processor // +// // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Code Restyling (19/02/2015) // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + +module AddressDecoder_PE_Req +#( + parameter int ID_WIDTH = 17, // ID WIDTH (number of bits) --> see ID comment + parameter int ID = 1, // ID routed with REQUEST used to backroute response + parameter int N_SLAVE = 16, // Number of Memory cuts + parameter int LOG_CLUSTER = 5, + parameter int ADDR_WIDTH = 32, + parameter int PE_ROUTING_LSB = 16, + parameter int PE_ROUTING_MSB = 19, + parameter bit CLUSTER_ALIAS = 1'b0, + parameter int CLUSTER_ALIAS_BASE = 12'h000 +) +( + input logic [LOG_CLUSTER-1:0] CLUSTER_ID, + // MASTER SIDE + input logic data_req_i, // Request from Master + input logic [ADDR_WIDTH-1:0] data_add_i, // Address from Master +`ifdef GNT_BASED_FC + output logic data_gnt_o, // Grant delivered to Master + input logic [N_SLAVE-1:0] data_gnt_i, // Grant Array: one for each memory on ARB TREE SIDE +`else + output logic data_stall_o, // Stall delivered to Master + input logic [N_SLAVE-1:0] data_stall_i, // Stall Array: one for each memory on ARB TREE SIDE +`endif + // ARB TREE SIDE + output logic [N_SLAVE-1:0] data_req_o, // Request Array: one for each memory + output logic [ID_WIDTH-1:0] data_ID_o // data_ID_o is sent whit the request (like a PID) +); + + localparam LOG_SLAVE = `log2(N_SLAVE-1); + + logic [LOG_SLAVE-1:0] ROUTING_ADDR; // M = Number of memory cuts + + logic [11:0] PE_END; + logic [11:0] PE_START; + + assign data_ID_o = ID; // ID is simply attached to the ID_OUT + + assign PE_START = 12'h100 + (CLUSTER_ID << 2) + 2; + assign PE_END = 12'h100 + (CLUSTER_ID << 2) + 3; + + always_comb begin + if (data_add_i[31:20] >= PE_START && data_add_i[31:20] < PE_END + || (CLUSTER_ALIAS + && data_add_i[31:20] >= CLUSTER_ALIAS_BASE+2 + && data_add_i[31:20] < (CLUSTER_ALIAS_BASE+3) + ) + ) begin + ROUTING_ADDR = data_add_i[PE_ROUTING_MSB:PE_ROUTING_LSB]; + end else begin + ROUTING_ADDR = '1; + end + end + + always_comb + begin : Combinational_ADDR_DEC_REQ + //DEFAULT VALUES + data_req_o = '0; + // Apply the rigth value + data_req_o[ROUTING_ADDR] = data_req_i; + `ifdef GNT_BASED_FC + data_gnt_o = data_gnt_i[ROUTING_ADDR]; + `else + data_stall_o = data_stall_i[ROUTING_ADDR]; + `endif + end + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_Resp_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_Resp_PE.sv new file mode 100644 index 0000000..5e94d3d --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_Resp_PE.sv @@ -0,0 +1,63 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 06/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: AddressDecoder_Resp // +// Project Name: MegaLEON // +// Language: SystemVerilog // +// // +// Description: Address Decoder used to generate the individual requests // +// for all the available masters . It routes the read data // +// from the memory to the processor // +// // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Code Restyling (19/02/2015) // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + +module AddressDecoder_Resp_PE +#( + parameter ID_WIDTH = 20, // ID WIDTH (number of bits) --> see ID comment + parameter N_MASTER = 20 // Number of Master +) +( + // FROM Test And Set Interface + input logic data_r_valid_i, + input logic [ID_WIDTH-1:0] data_ID_i, + + // To Response Network + output logic [N_MASTER-1:0] data_r_valid_o +); + + assign data_r_valid_o = {ID_WIDTH{data_r_valid_i}} & data_ID_i; + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/ArbitrationTree_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ArbitrationTree_PE.sv new file mode 100644 index 0000000..b9d7cfe --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ArbitrationTree_PE.sv @@ -0,0 +1,347 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 06/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: ArbitrationTree // +// Project Name: MegaLEON // +// Language: SystemVerilog // +// // +// Description: Arbitration tree: This block performs the arbitration // +// between the N_MASTER requests. The arbitration is // +// distributed in the several arbitration primitives that // +// compose this routing block. The arbistrtion is round robin // +// and the round robin flag generator is embedded inside this // +// block. Flag updating happens only when requests are grant // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Code Restyling (19/02/2015) // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + + +module ArbitrationTree_PE +#( + parameter ADDR_WIDTH = 32, + parameter ID_WIDTH = 20, + parameter N_MASTER = 16, + parameter DATA_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8, + parameter MAX_COUNT = N_MASTER +) +( + input logic clk, + input logic rst_n, + + // ---------------- REQ_SIDE -------------------------- + input logic [N_MASTER-1:0] data_req_i, + input logic [N_MASTER-1:0][ADDR_WIDTH-1:0] data_add_i, + input logic [N_MASTER-1:0] data_wen_i, + input logic [N_MASTER-1:0][5:0] data_atop_i, + input logic [N_MASTER-1:0][DATA_WIDTH-1:0] data_wdata_i, + input logic [N_MASTER-1:0][BE_WIDTH-1:0] data_be_i, + input logic [N_MASTER-1:0][ID_WIDTH-1:0] data_ID_i, +`ifdef GNT_BASED_FC + output logic [N_MASTER-1:0] data_gnt_o, +`else + output logic [N_MASTER-1:0] data_stall_o, +`endif + // Outputs + output logic data_req_o, + output logic [ADDR_WIDTH-1:0] data_add_o, + output logic data_wen_o, + output logic [5:0] data_atop_o, + output logic [DATA_WIDTH-1:0] data_wdata_o, + output logic [BE_WIDTH-1:0] data_be_o, + output logic [ID_WIDTH-1:0] data_ID_o, +`ifdef GNT_BASED_FC + input logic data_gnt_i +`else + input logic data_stall_i +`endif +); + + localparam LOG_MASTER = `log2(N_MASTER-1); + localparam N_WIRE = N_MASTER - 2; + + logic [LOG_MASTER-1:0] RR_FLAG; + + genvar j,k; + + generate + if(N_MASTER == 2) + begin : INCR // START of MASTER == 2 + // ---------------- FAN IN PRIMITIVE ------------------------- + FanInPrimitive_Req_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ) + ) + i_FanInPrimitive_Req_PE + ( + .RR_FLAG(RR_FLAG), + // LEFT SIDE" + .data_wdata0_i(data_wdata_i[0]), + .data_wdata1_i(data_wdata_i[1]), + .data_add0_i(data_add_i[0]), + .data_add1_i(data_add_i[1]), + .data_req0_i(data_req_i[0]), + .data_req1_i(data_req_i[1]), + .data_wen0_i(data_wen_i[0]), + .data_wen1_i(data_wen_i[1]), + .data_atop0_i(data_atop_i[0]), + .data_atop1_i(data_atop_i[1]), + .data_ID0_i(data_ID_i[0]), + .data_ID1_i(data_ID_i[1]), + .data_be0_i(data_be_i[0]), + .data_be1_i(data_be_i[1]), + `ifdef GNT_BASED_FC + .data_gnt0_o(data_gnt_o[0]), + .data_gnt1_o(data_gnt_o[1]), + `else + .data_stall0_o(data_stall_o[0]), + .data_stall1_o(data_stall_o[1]), + `endif + // RIGTH SIDE" + .data_wdata_o(data_wdata_o), + .data_add_o(data_add_o), + .data_req_o(data_req_o), + .data_wen_o(data_wen_o), + .data_atop_o(data_atop_o), + .data_ID_o(data_ID_o), + .data_be_o(data_be_o), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_i) + `else + .data_stall_i(data_stall_i) + `endif + ); + end // END OF MASTER == 2 + else // More than two master + begin : BINARY_TREE + //// ---------------------------------------------------------------------- //// + //// ------- REQ ARBITRATION TREE WIRES ----------- //// + //// ---------------------------------------------------------------------- //// + logic [DATA_WIDTH-1:0] data_wdata_LEVEL[N_WIRE-1:0]; + logic [ADDR_WIDTH-1:0] data_add_LEVEL[N_WIRE-1:0]; + logic data_req_LEVEL[N_WIRE-1:0]; + logic data_wen_LEVEL[N_WIRE-1:0]; + logic [5:0] data_atop_LEVEL[N_WIRE-1:0]; + logic [ID_WIDTH-1:0] data_ID_LEVEL[N_WIRE-1:0]; + logic [BE_WIDTH-1:0] data_be_LEVEL[N_WIRE-1:0]; + `ifdef GNT_BASED_FC + logic data_gnt_LEVEL[N_WIRE-1:0]; + `else + logic data_stall_LEVEL[N_WIRE-1:0]; + `endif + + for(j=0; j < LOG_MASTER; j++) // Iteration for the number of the stages minus one + begin : STAGE + for(k=0; k<2**j; k=k+1) // Iteration needed to create the binary tree + begin : INCR_VERT + if (j == 0 ) // LAST NODE, drives the module outputs + begin : LAST_NODE + FanInPrimitive_Req_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ) + ) + i_FanInPrimitive_Req_PE + ( + .RR_FLAG(RR_FLAG[LOG_MASTER-j-1]), + // LEFT SIDE + .data_wdata0_i(data_wdata_LEVEL[2*k]), + .data_wdata1_i(data_wdata_LEVEL[2*k+1]), + .data_add0_i(data_add_LEVEL[2*k]), + .data_add1_i(data_add_LEVEL[2*k+1]), + .data_req0_i(data_req_LEVEL[2*k]), + .data_req1_i(data_req_LEVEL[2*k+1]), + .data_wen0_i(data_wen_LEVEL[2*k]), + .data_wen1_i(data_wen_LEVEL[2*k+1]), + .data_atop0_i(data_atop_LEVEL[2*k]), + .data_atop1_i(data_atop_LEVEL[2*k+1]), + .data_ID0_i(data_ID_LEVEL[2*k]), + .data_ID1_i(data_ID_LEVEL[2*k+1]), + .data_be0_i(data_be_LEVEL[2*k]), + .data_be1_i(data_be_LEVEL[2*k+1]), + `ifdef GNT_BASED_FC + .data_gnt0_o(data_gnt_LEVEL[2*k]), + .data_gnt1_o(data_gnt_LEVEL[2*k+1]), + `else + .data_stall0_o(data_stall_LEVEL[2*k]), + .data_stall1_o(data_stall_LEVEL[2*k+1]), + `endif + // RIGTH SIDE + .data_wdata_o(data_wdata_o), + .data_add_o(data_add_o), + .data_req_o(data_req_o), + .data_wen_o(data_wen_o), + .data_atop_o(data_atop_o), + .data_ID_o(data_ID_o), + .data_be_o(data_be_o), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_i) + `else + .data_stall_i(data_stall_i) + `endif + ); + end + else if ( j < LOG_MASTER - 1) // Middle Nodes + begin : MIDDLE_NODES // START of MIDDLE LEVELS Nodes + FanInPrimitive_Req_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ) + ) + i_FanInPrimitive_Req_PE + ( + .RR_FLAG(RR_FLAG[LOG_MASTER-j-1]), + // LEFT SIDE + .data_wdata0_i (data_wdata_LEVEL[((2**j)*2-2) + 2*k]), + .data_wdata1_i (data_wdata_LEVEL[((2**j)*2-2) + 2*k +1]), + .data_add0_i (data_add_LEVEL[((2**j)*2-2) + 2*k]), + .data_add1_i (data_add_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_req0_i (data_req_LEVEL[((2**j)*2-2) + 2*k]), + .data_req1_i (data_req_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_wen0_i (data_wen_LEVEL[((2**j)*2-2) + 2*k]), + .data_wen1_i (data_wen_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_atop0_i (data_atop_LEVEL[((2**j)*2-2) + 2*k]), + .data_atop1_i (data_atop_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_ID0_i (data_ID_LEVEL[((2**j)*2-2) + 2*k]), + .data_ID1_i (data_ID_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_be0_i (data_be_LEVEL[((2**j)*2-2) + 2*k]), + .data_be1_i (data_be_LEVEL[((2**j)*2-2) + 2*k+1]), + `ifdef GNT_BASED_FC + .data_gnt0_o (data_gnt_LEVEL[((2**j)*2-2) + 2*k]), + .data_gnt1_o (data_gnt_LEVEL[((2**j)*2-2) + 2*k+1]), + `else + .data_stall0_o (data_stall_LEVEL[((2**j)*2-2) + 2*k]), + .data_stall1_o (data_stall_LEVEL[((2**j)*2-2) + 2*k+1]), + `endif + + // RIGTH SIDE + .data_wdata_o(data_wdata_LEVEL[((2**(j-1))*2-2) + k]), + .data_add_o(data_add_LEVEL[((2**(j-1))*2-2) + k]), + .data_req_o(data_req_LEVEL[((2**(j-1))*2-2) + k]), + .data_wen_o(data_wen_LEVEL[((2**(j-1))*2-2) + k]), + .data_atop_o(data_atop_LEVEL[((2**(j-1))*2-2) + k]), + .data_ID_o(data_ID_LEVEL[((2**(j-1))*2-2) + k]), + .data_be_o(data_be_LEVEL[((2**(j-1))*2-2) + k]), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_LEVEL[((2**(j-1))*2-2) + k]) + `else + .data_stall_i(data_stall_LEVEL[((2**(j-1))*2-2) + k]) + `endif + ); + end // END of MIDDLE LEVELS Nodes + else // First stage (connected with the Main inputs ) --> ( j == N_MASTER - 1 ) + begin : LEAF_NODES // START of FIRST LEVEL Nodes (LEAF) + FanInPrimitive_Req_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ) + ) + i_FanInPrimitive_Req_PE + ( + .RR_FLAG(RR_FLAG[LOG_MASTER-j-1]), + // LEFT SIDE + .data_wdata0_i(data_wdata_i[2*k]), + .data_wdata1_i(data_wdata_i[2*k+1]), + .data_add0_i(data_add_i[2*k]), + .data_add1_i(data_add_i[2*k+1]), + .data_req0_i(data_req_i[2*k]), + .data_req1_i(data_req_i[2*k+1]), + .data_wen0_i(data_wen_i[2*k]), + .data_wen1_i(data_wen_i[2*k+1]), + .data_atop0_i(data_atop_i[2*k]), + .data_atop1_i(data_atop_i[2*k+1]), + .data_ID0_i(data_ID_i[2*k]), + .data_ID1_i(data_ID_i[2*k+1]), + .data_be0_i(data_be_i[2*k]), + .data_be1_i(data_be_i[2*k+1]), + `ifdef GNT_BASED_FC + .data_gnt0_o(data_gnt_o[2*k]), + .data_gnt1_o(data_gnt_o[2*k+1]), + `else + .data_stall0_o(data_stall_o[2*k]), + .data_stall1_o(data_stall_o[2*k+1]), + `endif + + // RIGTH SIDE + .data_wdata_o(data_wdata_LEVEL[((2**(j-1))*2-2) + k]), + .data_add_o(data_add_LEVEL[((2**(j-1))*2-2) + k]), + .data_req_o(data_req_LEVEL[((2**(j-1))*2-2) + k]), + .data_wen_o(data_wen_LEVEL[((2**(j-1))*2-2) + k]), + .data_atop_o(data_atop_LEVEL[((2**(j-1))*2-2) + k]), + .data_ID_o(data_ID_LEVEL[((2**(j-1))*2-2) + k]), + .data_be_o(data_be_LEVEL[((2**(j-1))*2-2) + k]), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_LEVEL[((2**(j-1))*2-2) + k]) + `else + .data_stall_i(data_stall_LEVEL[((2**(j-1))*2-2) + k]) + `endif + ); + end // End of FIRST LEVEL Nodes (LEAF) + end + + end + + end + endgenerate + + //COUNTER USED TO SWITCH PERIODICALLY THE PRIORITY FLAG" + RR_Flag_Req_PE + #( + .WIDTH(LOG_MASTER), + .MAX_COUNT(MAX_COUNT) + ) + RR_REQ + ( + .clk(clk), + .rst_n(rst_n), + .RR_FLAG_o(RR_FLAG), + .data_req_i(data_req_o), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_i) + `else + .data_stall_i(data_stall_i) + `endif + ); + + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_PE_Resp.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_PE_Resp.sv new file mode 100644 index 0000000..9959c99 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_PE_Resp.sv @@ -0,0 +1,87 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 29/06/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: FanInPrimitive_Resp // +// Language: SystemVerilog // +// // +// Description: Routing primitives used to build the Routing trees. // +// They are part of the response network // +// // +// // +// Revision: // +// Revision v0.1 02/07/2011 - File Created // +// v0.2 15/08/2012 - Improved the Interface Structure, // +// Changed the routing mechanism // +// Revision v0.3 19/02/2015 - Code Restyling // +// // +// // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + +`include "parameters.v" + +module FanInPrimitive_PE_Resp +#( + parameter DATA_WIDTH = 32 +) +( + // UPSTREAM SIDE + input logic [DATA_WIDTH-1:0] data_r_rdata0_i, + input logic [DATA_WIDTH-1:0] data_r_rdata1_i, + input logic data_r_valid0_i, + input logic data_r_valid1_i, + input logic data_r_opc0_i, + input logic data_r_opc1_i, + + // DOWNSTREAM SIDE + output logic [DATA_WIDTH-1:0] data_r_rdata_o, + output logic data_r_valid_o, + output logic data_r_opc_o +); + + // Selector for the FanOut multiplexer + logic SEL; + + // VAlid is simply the or of the two requests + assign data_r_valid_o = data_r_valid1_i | data_r_valid0_i; + + // FIXME: (req0 & req1) must be always 0 + assign SEL = data_r_valid1_i; + + + // SEL CONTROLLER + always_comb + begin : FanOut_MUX2 + case(SEL) + 1'b0: begin data_r_rdata_o = data_r_rdata0_i; data_r_opc_o = data_r_opc0_i; end + 1'b1: begin data_r_rdata_o = data_r_rdata1_i; data_r_opc_o = data_r_opc1_i; end + endcase + end +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_Req_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_Req_PE.sv new file mode 100644 index 0000000..5f51062 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_Req_PE.sv @@ -0,0 +1,137 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 29/06/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: FanInPrimitive_Req // +// Project Name: MegaLEON // +// Language: SystemVerilog // +// // +// Description: Arbitration primitives used to build the arbitration trees.// +// They are part of the request network with a distributed // +// arbiter. The arbitration Algorithm is ROUND ROBIN // +// // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Code Restyling (19/02/2015) // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + + +module FanInPrimitive_Req_PE +#( + parameter ADDR_WIDTH = 32, + parameter ID_WIDTH = 16, + parameter DATA_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8 +) +( + input logic RR_FLAG, + + // LEFT SIDE + input logic [DATA_WIDTH-1:0] data_wdata0_i, + input logic [DATA_WIDTH-1:0] data_wdata1_i, + input logic [ADDR_WIDTH-1:0] data_add0_i, + input logic [ADDR_WIDTH-1:0] data_add1_i, + input logic data_req0_i, + input logic data_req1_i, + input logic data_wen0_i, + input logic data_wen1_i, + input logic [5:0] data_atop0_i, + input logic [5:0] data_atop1_i, + input logic [BE_WIDTH-1:0] data_be0_i, + input logic [BE_WIDTH-1:0] data_be1_i, + input logic [ID_WIDTH-1:0] data_ID0_i, + input logic [ID_WIDTH-1:0] data_ID1_i, +`ifdef GNT_BASED_FC + output logic data_gnt0_o, + output logic data_gnt1_o, +`else + output logic data_stall0_o, + output logic data_stall1_o, +`endif + // RIGTH SIDE + output logic [DATA_WIDTH-1:0] data_wdata_o, + output logic [ADDR_WIDTH-1:0] data_add_o, + output logic data_req_o, + output logic [ID_WIDTH-1:0] data_ID_o, + output logic data_wen_o, + output logic [5:0] data_atop_o, + output logic [BE_WIDTH-1:0] data_be_o, +`ifdef GNT_BASED_FC + input logic data_gnt_i +`else + input logic data_stall_i +`endif +); + + logic SEL; + + assign data_req_o = data_req0_i | data_req1_i; + assign SEL = ~data_req0_i | ( RR_FLAG & data_req1_i); // SEL FOR ROUND ROBIN MUX + + `ifdef GNT_BASED_FC + // Grant gnt0 and gnt1 + assign data_gnt0_o = (( data_req0_i & ~data_req1_i) | ( data_req0_i & ~RR_FLAG)) & data_gnt_i; + assign data_gnt1_o = ((~data_req0_i & data_req1_i) | ( data_req1_i & RR_FLAG)) & data_gnt_i; + `else + // Data stall0 and stall1 + assign data_stall0_o = (data_req0_i & data_req1_i & RR_FLAG) | ((( data_req0_i & ~data_req1_i) | ( data_req0_i & ~RR_FLAG)) & data_stall_i); + assign data_stall1_o = (data_req0_i & data_req1_i & ~RR_FLAG) | (((~data_req0_i & data_req1_i) | ( data_req1_i & RR_FLAG)) & data_stall_i); + `endif + + //MUXES AND DEMUXES + always_comb + begin : FanIn_MUX2 + case(SEL) //synopsys full_case + 1'b0: + begin //PRIORITY ON CH_0 + data_wdata_o = data_wdata0_i; + data_add_o = data_add0_i; + data_wen_o = data_wen0_i; + data_atop_o = data_atop0_i; + data_ID_o = data_ID0_i; + data_be_o = data_be0_i; + end + + 1'b1: + begin //PRIORITY ON CH_1 + data_wdata_o = data_wdata1_i; + data_add_o = data_add1_i; + data_wen_o = data_wen1_i; + data_atop_o = data_atop1_i; + data_ID_o = data_ID1_i; + data_be_o = data_be1_i; + end + + endcase + end + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/MUX2_REQ_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/MUX2_REQ_PE.sv new file mode 100644 index 0000000..0cfd973 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/MUX2_REQ_PE.sv @@ -0,0 +1,147 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 29/06/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: MUX2_REQ // +// Language: SystemVerilog // +// // +// Description: two input multiplxer whith custom ports used to multiplex // +// the datapath request data. It includes an embeddedd // +// Fixed Priory arbiter with max priority to Channel 0 (CH0) // +// // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Code Restyling (19/02/2015) // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + +`include "parameters.v" + +module MUX2_REQ_PE +#( + parameter ID_WIDTH = 20, + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8 +) +( + input logic data_req_CH0_i, + input logic [ADDR_WIDTH-1:0] data_add_CH0_i, + input logic data_wen_CH0_i, + input logic [5:0] data_atop_CH0_i, + input logic [DATA_WIDTH-1:0] data_wdata_CH0_i, + input logic [BE_WIDTH-1:0] data_be_CH0_i, + input logic [ID_WIDTH-1:0] data_ID_CH0_i, +`ifdef GNT_BASED_FC + output logic data_gnt_CH0_o, +`else + output logic data_stall_CH0_o, +`endif + + + input logic data_req_CH1_i, + input logic [ADDR_WIDTH-1:0] data_add_CH1_i, + input logic data_wen_CH1_i, + input logic [5:0] data_atop_CH1_i, + input logic [DATA_WIDTH-1:0] data_wdata_CH1_i, + input logic [BE_WIDTH-1:0] data_be_CH1_i, + input logic [ID_WIDTH-1:0] data_ID_CH1_i, +`ifdef GNT_BASED_FC + output logic data_gnt_CH1_o, +`else + output logic data_stall_CH1_o, +`endif + + output logic data_req_o, + output logic [ADDR_WIDTH-1:0] data_add_o, + output logic data_wen_o, + output logic [5:0] data_atop_o, + output logic [DATA_WIDTH-1:0] data_wdata_o, + output logic [BE_WIDTH-1:0] data_be_o, + output logic [ID_WIDTH-1:0] data_ID_o, +`ifdef GNT_BASED_FC + input logic data_gnt_i, +`else + input logic data_stall_i, +`endif + + input logic clk, + input logic rst_n +); + + logic SEL; // Mux Selector + logic RR_FLAG; + + // Request is simply an or between indoming request + assign data_req_o = data_req_CH0_i | data_req_CH1_i; + + // FIXED PRIORITY ENCODER + assign SEL = ~data_req_CH0_i | ( RR_FLAG & data_req_CH1_i); // SEL FOR ROUND ROBIN MUX +`ifdef GNT_BASED_FC + assign data_gnt_CH0_o = (( data_req_CH0_i & ~data_req_CH1_i) | ( data_req_CH0_i & ~RR_FLAG)) & data_gnt_i; + assign data_gnt_CH1_o = ((~data_req_CH0_i & data_req_CH1_i) | ( data_req_CH1_i & RR_FLAG)) & data_gnt_i; +`else + assign data_stall_CH0_o = (data_req_CH0_i & data_req_CH1_i & RR_FLAG) | ((( data_req_CH0_i & ~data_req_CH1_i) | ( data_req_CH0_i & ~RR_FLAG)) & data_stall_i); + assign data_stall_CH1_o = (data_req_CH0_i & data_req_CH1_i & ~RR_FLAG) | (((~data_req_CH0_i & data_req_CH1_i) | ( data_req_CH1_i & RR_FLAG)) & data_stall_i); +`endif + + always_ff @(posedge clk, negedge rst_n) + begin + if(rst_n == 1'b0) + RR_FLAG <= 1'b0; + else if((data_req_o == 1'b1) && `ifdef GNT_BASED_FC (data_gnt_i == 1'b1) `else (data_stall_i == 1'b0) `endif) + RR_FLAG <= ~RR_FLAG; + end + + always_comb + begin : MUX2_REQ_COMB + case(SEL) // synopsys full_case + 1'b0: + begin + data_add_o = data_add_CH0_i; + data_wen_o = data_wen_CH0_i; + data_atop_o = data_atop_CH0_i; + data_wdata_o = data_wdata_CH0_i; + data_be_o = data_be_CH0_i; + data_ID_o = data_ID_CH0_i; + end + + 1'b1: + begin + data_add_o = data_add_CH1_i; + data_wen_o = data_wen_CH1_i; + data_atop_o = data_atop_CH1_i; + data_wdata_o = data_wdata_CH1_i; + data_be_o = data_be_CH1_i; + data_ID_o = data_ID_CH1_i; + end + endcase + end +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/RR_Flag_Req_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/RR_Flag_Req_PE.sv new file mode 100644 index 0000000..b2c03be --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/RR_Flag_Req_PE.sv @@ -0,0 +1,87 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 29/06/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: RR_Flag_Req // +// Project Name: MegaLEON // +// Language: SystemVerilog // +// // +// Description: Round Robing FLAG generator for the arbitration trees. // +// The values ( RR_FLAG_REQ ) is update only when request and // +// grant are high. This allow to avoid high sw activity when // +// there is no valid traffic. Allows for clock gating // +// insertion // +// // +// Revision: // +// Revision v0.1 - File Created // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + + +module RR_Flag_Req_PE +#( + parameter WIDTH = 3, + parameter MAX_COUNT = 2**WIDTH-1 +) +( + input logic clk, + input logic rst_n, + output logic [WIDTH-1:0] RR_FLAG_o, + input logic data_req_i, +`ifdef GNT_BASED_FC + input logic data_gnt_i +`else + input logic data_stall_i +`endif +); + + + + + always_ff @(posedge clk, negedge rst_n) + begin : RR_Flag_Req_SEQ + if(rst_n == 1'b0) + RR_FLAG_o <= '0; + else + `ifdef GNT_BASED_FC + if( data_req_i & data_gnt_i ) + `else + if( data_req_i & ~data_stall_i ) + `endif + begin + if(RR_FLAG_o < MAX_COUNT) + RR_FLAG_o <= RR_FLAG_o + 1'b1; + else + RR_FLAG_o <= '0; + end + end + + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/RequestBlock2CH_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/RequestBlock2CH_PE.sv new file mode 100644 index 0000000..f4783fc --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/RequestBlock2CH_PE.sv @@ -0,0 +1,637 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 02/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: RequestBlock2CH_PE // +// Language: SystemVerilog // +// // +// Description: Request Block: it embed inside the routing trees and the // +// Multiplexer to mix the request from two channels (one // +// distributed in the several arbitration primitives that // +// compose this routing block. The arbistrtion is round robin // +// and the round robin flag generator is embedded inside this // +// block. Flag updating happens only when requests are grant // +// // +// Revision: // +// Revision v0.1 02/07/2011 - File Created // +// v0.2 14/08/2012 - Improved the Interface Structure, // +// Changed the routing mechanism // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + +// FOR TWO INPUTS +module RequestBlock2CH_PE +#( + parameter ADDR_WIDTH = 32, + parameter N_CH0 = 16, // Example Number of cores + parameter N_CH1 = 1, // Example Number of DMAs + parameter ID_WIDTH = N_CH0+N_CH1, + parameter DATA_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8 +) +( + // CHANNEL CH0 --> (example: Used for cores) + input logic [N_CH0-1:0] data_req_CH0_i, + input logic [N_CH0-1:0][ADDR_WIDTH-1:0] data_add_CH0_i, + input logic [N_CH0-1:0] data_wen_CH0_i, + input logic [N_CH0-1:0][5:0] data_atop_CH0_i, + input logic [N_CH0-1:0][DATA_WIDTH-1:0] data_wdata_CH0_i, + input logic [N_CH0-1:0][BE_WIDTH-1:0] data_be_CH0_i, + input logic [N_CH0-1:0][ID_WIDTH-1:0] data_ID_CH0_i, +`ifdef GNT_BASED_FC + output logic [N_CH0-1:0] data_gnt_CH0_o, +`else + output logic [N_CH0-1:0] data_stall_CH0_o, +`endif + + // CHANNEL CH1 --> (example: Used for DMAs) + input logic [N_CH1-1:0] data_req_CH1_i, + input logic [N_CH1-1:0][ADDR_WIDTH-1:0] data_add_CH1_i, + input logic [N_CH1-1:0] data_wen_CH1_i, + input logic [N_CH1-1:0][5:0] data_atop_CH1_i, + input logic [N_CH1-1:0][DATA_WIDTH-1:0] data_wdata_CH1_i, + input logic [N_CH1-1:0][BE_WIDTH-1:0] data_be_CH1_i, + input logic [N_CH1-1:0][ID_WIDTH-1:0] data_ID_CH1_i, +`ifdef GNT_BASED_FC + output logic [N_CH1-1:0] data_gnt_CH1_o, +`else + output logic [N_CH1-1:0] data_stall_CH1_o, +`endif + + // ----------------- MEMORY ------------------- + // ---------------- RequestBlock OUTPUT (Connected to MEMORY) ---------------- + output logic data_req_o, + output logic [ADDR_WIDTH-1:0] data_add_o, + output logic data_wen_o, + output logic [5:0] data_atop_o, + output logic [DATA_WIDTH-1:0] data_wdata_o, + output logic [BE_WIDTH-1:0] data_be_o, + output logic [ID_WIDTH-1:0] data_ID_o, +`ifdef GNT_BASED_FC + input logic data_gnt_i, +`else + input logic data_stall_i, +`endif + input logic data_r_valid_i, + input logic [ID_WIDTH-1:0] data_r_ID_i, + + + + // GEN VALID_SIGNALS in the response path + output logic [N_CH0-1:0] data_r_valid_CH0_o, + output logic [N_CH1-1:0] data_r_valid_CH1_o, + + input logic clk, + input logic rst_n + + ); + + // OUT CHANNEL CH0 --> (example: Used for cores) + logic data_req_CH0; + logic [ADDR_WIDTH-1:0] data_add_CH0; + logic data_wen_CH0; + logic [5:0] data_atop_CH0; + logic [DATA_WIDTH-1:0] data_wdata_CH0; + logic [BE_WIDTH-1:0] data_be_CH0; + logic [ID_WIDTH-1:0] data_ID_CH0; + `ifdef GNT_BASED_FC + logic data_gnt_CH0; + `else + logic data_stall_CH0; + `endif + + // OUT CHANNEL CH1 --> (example: Used for DMAs) + logic data_req_CH1; + logic [ADDR_WIDTH-1:0] data_add_CH1; + logic data_wen_CH1; + logic [5:0] data_atop_CH1; + logic [DATA_WIDTH-1:0] data_wdata_CH1; + logic [BE_WIDTH-1:0] data_be_CH1; + logic [ID_WIDTH-1:0] data_ID_CH1; + `ifdef GNT_BASED_FC + logic data_gnt_CH1; + `else + logic data_stall_CH1; + `endif + + + // CHANNEL CH0 --> (example: Used for Processing Elements / CORES) + logic [2**$clog2(N_CH0)-1:0] data_req_CH0_int; + logic [2**$clog2(N_CH0)-1:0][ADDR_WIDTH-1:0] data_add_CH0_int; + logic [2**$clog2(N_CH0)-1:0] data_wen_CH0_int; + logic [2**$clog2(N_CH0)-1:0][5:0] data_atop_CH0_int; + logic [2**$clog2(N_CH0)-1:0][DATA_WIDTH-1:0] data_wdata_CH0_int; + logic [2**$clog2(N_CH0)-1:0][BE_WIDTH-1:0] data_be_CH0_int; + logic [2**$clog2(N_CH0)-1:0][ID_WIDTH-1:0] data_ID_CH0_int; +`ifdef GNT_BASED_FC + logic [2**$clog2(N_CH0)-1:0] data_gnt_CH0_int; +`else + logic [2**$clog2(N_CH0)-1:0] data_stall_CH0_int; +`endif + + + + // CHANNEL CH0 --> (example: Used for Processing Elements / CORES) + logic [2**$clog2(N_CH1)-1:0] data_req_CH1_int; + logic [2**$clog2(N_CH1)-1:0][ADDR_WIDTH-1:0] data_add_CH1_int; + logic [2**$clog2(N_CH1)-1:0] data_wen_CH1_int; + logic [2**$clog2(N_CH1)-1:0][5:0] data_atop_CH1_int; + logic [2**$clog2(N_CH1)-1:0][DATA_WIDTH-1:0] data_wdata_CH1_int; + logic [2**$clog2(N_CH1)-1:0][BE_WIDTH-1:0] data_be_CH1_int; + logic [2**$clog2(N_CH1)-1:0][ID_WIDTH-1:0] data_ID_CH1_int; +`ifdef GNT_BASED_FC + logic [2**$clog2(N_CH1)-1:0] data_gnt_CH1_int; +`else + logic [2**$clog2(N_CH1)-1:0] data_stall_CH1_int; +`endif + + + + + generate + + + if(2**$clog2(N_CH0) != N_CH0) // if N_CH0 is not power of 2 --> then use power 2 ports + begin : _DUMMY_CH0_PORTS_ + + logic [2**$clog2(N_CH0)-N_CH0 -1 :0] data_req_CH0_dummy; + logic [2**$clog2(N_CH0)-N_CH0 -1 :0][ADDR_WIDTH-1:0] data_add_CH0_dummy; // Memory address + T&S bit + logic [2**$clog2(N_CH0)-N_CH0 -1 :0] data_wen_CH0_dummy; + logic [2**$clog2(N_CH0)-N_CH0 -1 :0][5:0] data_atop_CH0_dummy; + logic [2**$clog2(N_CH0)-N_CH0 -1 :0][DATA_WIDTH-1:0] data_wdata_CH0_dummy; + logic [2**$clog2(N_CH0)-N_CH0 -1 :0][BE_WIDTH-1:0] data_be_CH0_dummy; + logic [2**$clog2(N_CH0)-N_CH0 -1 :0][ID_WIDTH-1:0] data_ID_CH0_dummy; + `ifdef GNT_BASED_FC + logic [2**$clog2(N_CH0)-N_CH0 -1 :0] data_gnt_CH0_dummy; + `else + logic [2**$clog2(N_CH0)-N_CH0 -1 :0] data_stall_CH0_dummy; + `endif + + assign data_req_CH0_dummy = '0 ; + assign data_add_CH0_dummy = '0 ; + assign data_wen_CH0_dummy = '0 ; + assign data_atop_CH0_dummy = '0 ; + assign data_wdata_CH0_dummy = '0 ; + assign data_be_CH0_dummy = '0 ; + assign data_ID_CH0_dummy = '0 ; + + assign data_req_CH0_int = { data_req_CH0_dummy , data_req_CH0_i }; + assign data_add_CH0_int = { data_add_CH0_dummy , data_add_CH0_i }; + assign data_wen_CH0_int = { data_wen_CH0_dummy , data_wen_CH0_i }; + assign data_atop_CH0_int = { data_atop_CH0_dummy , data_atop_CH0_i }; + assign data_wdata_CH0_int = { data_wdata_CH0_dummy , data_wdata_CH0_i }; + assign data_be_CH0_int = { data_be_CH0_dummy , data_be_CH0_i }; + assign data_ID_CH0_int = { data_ID_CH0_dummy , data_ID_CH0_i }; + + + for(genvar j=0; j then use power 2 ports + begin : _DUMMY_CH1_PORTS_ + + logic [2**$clog2(N_CH1)-N_CH1 -1 :0] data_req_CH1_dummy; + logic [2**$clog2(N_CH1)-N_CH1 -1 :0][ADDR_WIDTH-1:0] data_add_CH1_dummy; // Memory address + T&S bit + logic [2**$clog2(N_CH1)-N_CH1 -1 :0] data_wen_CH1_dummy; + logic [2**$clog2(N_CH1)-N_CH1 -1 :0][5:0] data_atop_CH1_dummy; + logic [2**$clog2(N_CH1)-N_CH1 -1 :0][DATA_WIDTH-1:0] data_wdata_CH1_dummy; + logic [2**$clog2(N_CH1)-N_CH1 -1 :0][BE_WIDTH-1:0] data_be_CH1_dummy; + logic [2**$clog2(N_CH1)-N_CH1 -1 :0][ID_WIDTH-1:0] data_ID_CH1_dummy; + `ifdef GNT_BASED_FC + logic [2**$clog2(N_CH1)-N_CH1 -1 :0] data_gnt_CH1_dummy; + `else + logic [2**$clog2(N_CH1)-N_CH1 -1 :0] data_stall_CH1_dummy; + `endif + + assign data_req_CH1_dummy = '0 ; + assign data_add_CH1_dummy = '0 ; + assign data_wen_CH1_dummy = '0 ; + assign data_atop_CH1_dummy = '0 ; + assign data_wdata_CH1_dummy = '0 ; + assign data_be_CH1_dummy = '0 ; + assign data_ID_CH1_dummy = '0 ; + + assign data_req_CH1_int = { data_req_CH1_dummy , data_req_CH1_i }; + assign data_add_CH1_int = { data_add_CH1_dummy , data_add_CH1_i }; + assign data_wen_CH1_int = { data_wen_CH1_dummy , data_wen_CH1_i }; + assign data_atop_CH1_int = { data_atop_CH1_dummy , data_atop_CH1_i }; + assign data_wdata_CH1_int = { data_wdata_CH1_dummy , data_wdata_CH1_i }; + assign data_be_CH1_int = { data_be_CH1_dummy , data_be_CH1_i }; + assign data_ID_CH1_int = { data_ID_CH1_dummy , data_ID_CH1_i }; + + + for(genvar j=0; j 1) + begin : CH0_ARB_TREE + ArbitrationTree_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .N_MASTER ( N_CH0 ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ), + .MAX_COUNT ( N_CH0 - 1 ) + ) + i_ArbitrationTree_PE + ( + .clk ( clk ), + .rst_n ( rst_n ), + // INPUTS + .data_req_i ( data_req_CH0_int ), + .data_add_i ( data_add_CH0_int ), + .data_wen_i ( data_wen_CH0_int ), + .data_atop_i ( data_atop_CH0_int ), + .data_wdata_i ( data_wdata_CH0_int ), + .data_be_i ( data_be_CH0_int ), + .data_ID_i ( data_ID_CH0_int ), + `ifdef GNT_BASED_FC + .data_gnt_o ( data_gnt_CH0_int ), + `else + .data_stall_o ( data_stall_CH0_int ), + `endif + // OUTPUTS + .data_req_o ( data_req_CH0 ), + .data_add_o ( data_add_CH0 ), + .data_wen_o ( data_wen_CH0 ), + .data_atop_o ( data_atop_CH0 ), + .data_wdata_o ( data_wdata_CH0 ), + .data_be_o ( data_be_CH0 ), + .data_ID_o ( data_ID_CH0 ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_CH0 ) + `else + .data_stall_i ( data_stall_CH0 ) + `endif + ); + end + + if(N_CH1 > 1) + begin : CH1_ARB_TREE + ArbitrationTree_PE + #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .ID_WIDTH ( ID_WIDTH ), + .N_MASTER ( N_CH1 ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ), + .MAX_COUNT ( N_CH1 - 1 ) + ) + i_ArbitrationTree_PE + ( + .clk ( clk ), + .rst_n ( rst_n ), + // INPUTS + .data_req_i ( data_req_CH1_int ), + .data_add_i ( data_add_CH1_int ), + .data_wen_i ( data_wen_CH1_int ), + .data_atop_i ( data_atop_CH1_int ), + .data_wdata_i ( data_wdata_CH1_int ), + .data_be_i ( data_be_CH1_int ), + .data_ID_i ( data_ID_CH1_int ), + `ifdef GNT_BASED_FC + .data_gnt_o ( data_gnt_CH1_int ), + `else + .data_stall_o ( data_stall_CH1_int ), + `endif + // OUTPUTS + .data_req_o ( data_req_CH1 ), + .data_add_o ( data_add_CH1 ), + .data_wen_o ( data_wen_CH1 ), + .data_atop_o ( data_atop_CH1 ), + .data_wdata_o ( data_wdata_CH1 ), + .data_be_o ( data_be_CH1 ), + .data_ID_o ( data_ID_CH1 ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_CH1 ) + `else + .data_stall_i ( data_stall_CH1 ) + `endif + ); + end + + if(N_CH1 == 1) + begin : MONO_CH1 + if(N_CH0 == 1) + begin : MONO_CH0 + MUX2_REQ_PE + #( + .ID_WIDTH ( ID_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( DATA_WIDTH/8 ) + ) + i_MUX2_REQ_PE + ( + // CH0 input + .data_req_CH0_i ( data_req_CH0_int ), + .data_add_CH0_i ( data_add_CH0_int ), + .data_wen_CH0_i ( data_wen_CH0_int ), + .data_atop_CH0_i ( data_atop_CH0_int ), + .data_wdata_CH0_i ( data_wdata_CH0_int ), + .data_be_CH0_i ( data_be_CH0_int ), + .data_ID_CH0_i ( data_ID_CH0_int ), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o ( data_gnt_CH0_int ), + `else + .data_stall_CH0_o ( data_stall_CH0_int ), + `endif + // CH1 input + .data_req_CH1_i ( data_req_CH1_int ), + .data_add_CH1_i ( data_add_CH1_int ), + .data_wen_CH1_i ( data_wen_CH1_int ), + .data_atop_CH1_i ( data_atop_CH1_int ), + .data_wdata_CH1_i ( data_wdata_CH1_int ), + .data_be_CH1_i ( data_be_CH1_int ), + .data_ID_CH1_i ( data_ID_CH1_int ), + `ifdef GNT_BASED_FC + .data_gnt_CH1_o ( data_gnt_CH1_int ), + `else + .data_stall_CH1_o ( data_stall_CH1_int ), + `endif + // MUX output + .data_req_o ( data_req_o ), + .data_add_o ( data_add_o ), + .data_wen_o ( data_wen_o ), + .data_atop_o ( data_atop_o ), + .data_wdata_o ( data_wdata_o ), + .data_be_o ( data_be_o ), + .data_ID_o ( data_ID_o ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_i ), + `else + .data_stall_i ( data_stall_i ), + `endif + .clk ( clk ), + .rst_n ( rst_n ) + ); + end // END MONO_CH0 + else + begin : POLY_CH0 + MUX2_REQ_PE + #( + .ID_WIDTH ( ID_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( DATA_WIDTH/8 ) + ) + i_MUX2_REQ_PE + ( + // CH0 input + .data_req_CH0_i ( data_req_CH0 ), + .data_add_CH0_i ( data_add_CH0 ), + .data_wen_CH0_i ( data_wen_CH0 ), + .data_atop_CH0_i ( data_atop_CH0 ), + .data_wdata_CH0_i ( data_wdata_CH0 ), + .data_be_CH0_i ( data_be_CH0 ), + .data_ID_CH0_i ( data_ID_CH0 ), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o ( data_gnt_CH0 ), + `else + .data_stall_CH0_o ( data_stall_CH0 ), + `endif + // CH1 input + .data_req_CH1_i ( data_req_CH1_int ), + .data_add_CH1_i ( data_add_CH1_int ), + .data_wen_CH1_i ( data_wen_CH1_int ), + .data_atop_CH1_i ( data_atop_CH1_int ), + .data_wdata_CH1_i ( data_wdata_CH1_int ), + .data_be_CH1_i ( data_be_CH1_int ), + .data_ID_CH1_i ( data_ID_CH1_int ), + `ifdef GNT_BASED_FC + .data_gnt_CH1_o ( data_gnt_CH1_int ), + `else + .data_stall_CH1_o ( data_stall_CH1_int ), + `endif + // MUX output + .data_req_o ( data_req_o ), + .data_add_o ( data_add_o ), + .data_wen_o ( data_wen_o ), + .data_atop_o ( data_atop_o ), + .data_wdata_o ( data_wdata_o ), + .data_be_o ( data_be_o ), + .data_ID_o ( data_ID_o ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_i ), + `else + .data_stall_i ( data_stall_i ), + `endif + .clk ( clk ), + .rst_n ( rst_n ) + ); + end // END POLY_CH0 + end + else + begin : POLY_CH1 + if(N_CH0 == 1) + begin : MONO_CH0 + MUX2_REQ_PE + #( + .ID_WIDTH ( ID_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( DATA_WIDTH/8 ) + ) + i_MUX2_REQ_PE + ( + // CH0 input + .data_req_CH0_i ( data_req_CH0_int ), + .data_add_CH0_i ( data_add_CH0_int ), + .data_wen_CH0_i ( data_wen_CH0_int ), + .data_atop_CH0_i ( data_atop_CH0_int ), + .data_wdata_CH0_i ( data_wdata_CH0_int ), + .data_be_CH0_i ( data_be_CH0_int ), + .data_ID_CH0_i ( data_ID_CH0_int ), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o ( data_gnt_CH0_int ), + `else + .data_stall_CH0_o ( data_stall_CH0_int ), + `endif + // CH1 input + .data_req_CH1_i ( data_req_CH1 ), + .data_add_CH1_i ( data_add_CH1 ), + .data_wen_CH1_i ( data_wen_CH1 ), + .data_atop_CH1_i ( data_atop_CH1 ), + .data_wdata_CH1_i ( data_wdata_CH1 ), + .data_be_CH1_i ( data_be_CH1 ), + .data_ID_CH1_i ( data_ID_CH1 ), + `ifdef GNT_BASED_FC + .data_gnt_CH1_o ( data_gnt_CH1 ), + `else + .data_stall_CH1_o ( data_stall_CH1 ), + `endif + // MUX output + .data_req_o ( data_req_o ), + .data_add_o ( data_add_o ), + .data_wen_o ( data_wen_o ), + .data_atop_o ( data_atop_o ), + .data_wdata_o ( data_wdata_o ), + .data_be_o ( data_be_o ), + .data_ID_o ( data_ID_o ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_i ), + `else + .data_stall_i ( data_stall_i ), + `endif + .clk ( clk ), + .rst_n ( rst_n ) + ); + end + else + begin : POLY_CH0 + MUX2_REQ_PE + #( + .ID_WIDTH ( ID_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( DATA_WIDTH/8 ) + ) + i_MUX2_REQ_PE + ( + // CH0 input + .data_req_CH0_i ( data_req_CH0 ), + .data_add_CH0_i ( data_add_CH0 ), + .data_wen_CH0_i ( data_wen_CH0 ), + .data_atop_CH0_i ( data_atop_CH0 ), + .data_wdata_CH0_i ( data_wdata_CH0 ), + .data_be_CH0_i ( data_be_CH0 ), + .data_ID_CH0_i ( data_ID_CH0 ), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o ( data_gnt_CH0 ), + `else + .data_stall_CH0_o ( data_stall_CH0 ), + `endif + // CH1 input + .data_req_CH1_i ( data_req_CH1 ), + .data_add_CH1_i ( data_add_CH1 ), + .data_wen_CH1_i ( data_wen_CH1 ), + .data_atop_CH1_i ( data_atop_CH1 ), + .data_wdata_CH1_i ( data_wdata_CH1 ), + .data_be_CH1_i ( data_be_CH1 ), + .data_ID_CH1_i ( data_ID_CH1 ), + `ifdef GNT_BASED_FC + .data_gnt_CH1_o ( data_gnt_CH1 ), + `else + .data_stall_CH1_o ( data_stall_CH1 ), + `endif + // MUX output + .data_req_o ( data_req_o ), + .data_add_o ( data_add_o ), + .data_wen_o ( data_wen_o ), + .data_atop_o ( data_atop_o ), + .data_wdata_o ( data_wdata_o ), + .data_be_o ( data_be_o ), + .data_ID_o ( data_ID_o ), + `ifdef GNT_BASED_FC + .data_gnt_i ( data_gnt_i ), + `else + .data_stall_i ( data_stall_i ), + `endif + .clk ( clk ), + .rst_n ( rst_n ) + ); + end + end + endgenerate + + + + + AddressDecoder_Resp_PE + #( + .ID_WIDTH(ID_WIDTH), + .N_MASTER(N_CH0+N_CH1) + ) + i_AddressDecoder_Resp_PE + ( + // FROM Test And Set Interface + .data_r_valid_i(data_r_valid_i), + .data_ID_i(data_r_ID_i), + // To Response Network + .data_r_valid_o({data_r_valid_CH1_o,data_r_valid_CH0_o}) + ); + + + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseBlock_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseBlock_PE.sv new file mode 100644 index 0000000..b45141e --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseBlock_PE.sv @@ -0,0 +1,150 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 02/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: ResponseBlock_PE // +// Language: SystemVerilog // +// // +// Description: Response block that embeds address request address decoder // +// and Response tree. // +// // +// Revision: // +// Revision v0.1 02/07/2011 - File Created // +// v0.2 15/08/2012 - Improved the Interface Structure, // +// Changed the routing mechanism // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + + +`include "parameters.v" + +module ResponseBlock_PE +#( + parameter int ID = 1, + parameter int ID_WIDTH = 17, + parameter int N_SLAVE = 16, + + parameter int DATA_WIDTH = 32, + + parameter int LOG_CLUSTER = 5, + parameter int ADDR_WIDTH = 32, + parameter int PE_ROUTING_LSB = 16, + parameter int PE_ROUTING_MSB = 19, + parameter bit CLUSTER_ALIAS = 1'b0, + parameter int CLUSTER_ALIAS_BASE = 12'h000 +) +( + input logic [LOG_CLUSTER-1:0] CLUSTER_ID, + // -----------------------------------------------------------// + // Response HANDLING + // -----------------------------------------------------------// + // Signals from Memory cuts + input logic [N_SLAVE-1:0] data_r_valid_i, + input logic [N_SLAVE-1:0][DATA_WIDTH-1:0] data_r_rdata_i, + input logic [N_SLAVE-1:0] data_r_opc_i, + + // Output of the ResponseTree Block + output logic data_r_valid_o, + output logic [DATA_WIDTH-1:0] data_r_rdata_o, + output logic data_r_opc_o, + + // -----------------------------------------------------------// + // Request HANDLING + // -----------------------------------------------------------// + input logic data_req_i, + input logic [ADDR_WIDTH-1:0] data_add_i, + `ifdef GNT_BASED_FC + output logic data_gnt_o, + `else + output logic data_stall_o, + `endif + + + output logic [N_SLAVE-1:0] data_req_o, + `ifdef GNT_BASED_FC + input logic [N_SLAVE-1:0] data_gnt_i, + `else + input logic [N_SLAVE-1:0] data_stall_i, + `endif + output logic [ID_WIDTH-1:0] data_ID_o +); + + + + // Response Tree + ResponseTree_PE + #( + .N_SLAVE(N_SLAVE), + .DATA_WIDTH(DATA_WIDTH) + ) + i_ResponseTree_PE + ( + // Response Input Channel + .data_r_valid_i(data_r_valid_i), + .data_r_rdata_i(data_r_rdata_i), + .data_r_opc_i(data_r_opc_i), + // Response Output Channel + .data_r_valid_o(data_r_valid_o), + .data_r_rdata_o(data_r_rdata_o), + .data_r_opc_o(data_r_opc_o) + ); + + + AddressDecoder_PE_Req + #( + .ID_WIDTH ( ID_WIDTH ), + .ID ( ID ), + .N_SLAVE ( N_SLAVE ), + .LOG_CLUSTER ( LOG_CLUSTER ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .PE_ROUTING_LSB ( PE_ROUTING_LSB ), + .PE_ROUTING_MSB ( PE_ROUTING_MSB ), + .CLUSTER_ALIAS ( CLUSTER_ALIAS ), + .CLUSTER_ALIAS_BASE (CLUSTER_ALIAS_BASE) + ) + i_AddressDecoder_PE_Req + ( + .CLUSTER_ID(CLUSTER_ID), // CLUSTER_ID is an input!! no Longer a parameter!!! + // MASTER SIDE + .data_req_i(data_req_i), // Request from MASTER + .data_add_i(data_add_i), // Address from MASTER + `ifdef GNT_BASED_FC + .data_gnt_o(data_gnt_o), // Grant delivered to MASTER + .data_gnt_i(data_gnt_i), // Grant Array: one for each memory on ARB TREE SIDE + `else + .data_stall_o(data_stall_o), // Stall delivered to MASTER + .data_stall_i(data_stall_i), // Stall Array: one for each memory on ARB TREE SIDE + `endif + // ARB TREE SIDE + .data_req_o(data_req_o), // Request Array: one for each memory + .data_ID_o(data_ID_o) // ID is sent whit the request (like a PID) + ); + + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseTree_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseTree_PE.sv new file mode 100644 index 0000000..d737bd7 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/ResponseTree_PE.sv @@ -0,0 +1,177 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 02/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: ResponseTree_PE // +// Language: SystemVerilog // +// // +// Description: Peripheral Response tree: This block performs the Routing // +// between N_SLAVE requests. There is no arbitration in this // +// block. Since there is no chanche of request collision on // +// same master. Response latencies are deterministic therefore// +// the response arrive always in the same order they are sent.// +// // +// Revision: // +// Revision v0.1 02/07/2011 - File Created // +// v0.2 15/08/2012 - Improved the Interface Structure, // +// Changed the routing mechanism // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + + +module ResponseTree_PE +#( + parameter N_SLAVE = 16, + parameter DATA_WIDTH = 32 +) +( + // Response Input Channel 0 + input logic [N_SLAVE-1:0] data_r_valid_i, + input logic [N_SLAVE-1:0][DATA_WIDTH-1:0] data_r_rdata_i, + input logic [N_SLAVE-1:0] data_r_opc_i, + // Response Output Channel + output logic data_r_valid_o, + output logic [DATA_WIDTH-1:0] data_r_rdata_o, + output logic data_r_opc_o +); + + localparam LOG_SLAVE = `log2(N_SLAVE-1); + localparam N_WIRE = N_SLAVE - 2; + + genvar j,k; + + generate + + if(N_SLAVE == 2) + begin : INCR // START of N_SLAVE == 2 + // ---------------- FAN IN PRIMITIVE RESP ------------------------- + FanInPrimitive_PE_Resp + #( + .DATA_WIDTH(DATA_WIDTH) + ) + i_FanInPrimitive_PE_Resp + ( + // RIGTH SIDE + .data_r_rdata0_i ( data_r_rdata_i[0] ), + .data_r_rdata1_i ( data_r_rdata_i[1] ), + .data_r_valid0_i ( data_r_valid_i[0] ), + .data_r_valid1_i ( data_r_valid_i[1] ), + .data_r_opc0_i ( data_r_opc_i[0] ), + .data_r_opc1_i ( data_r_opc_i[1] ), + // LEFT SIDE + .data_r_rdata_o ( data_r_rdata_o ), + .data_r_valid_o ( data_r_valid_o ), + .data_r_opc_o ( data_r_opc_o ) + ); + end // END OF N_SLAVE == 2 + else // More than two master + begin : BINARY_TREE + //// ---------------------------------------------------------------------- //// + //// ------- REQ ARBITRATION TREE WIRES ----------- //// + //// ---------------------------------------------------------------------- //// + logic [DATA_WIDTH-1:0] data_r_rdata_LEVEL[N_WIRE-1:0]; + logic data_r_valid_LEVEL[N_WIRE-1:0]; + logic data_r_opc_LEVEL[N_WIRE-1:0]; + + for(j=0; j < LOG_SLAVE; j++) // Iteration for the number of the stages minus one + begin : STAGE + for(k=0; k<2**j; k=k+1) // Iteration needed to create the binary tree + begin : INCR_VERT + + if (j == 0 ) // LAST NODE, drives the module outputs + begin : LAST_NODE + FanInPrimitive_PE_Resp + #( + .DATA_WIDTH(DATA_WIDTH) + ) + i_FanInPrimitive_PE_Resp + ( + // RIGTH SIDE + .data_r_rdata0_i(data_r_rdata_LEVEL[2*k]), + .data_r_rdata1_i(data_r_rdata_LEVEL[2*k+1]), + .data_r_valid0_i(data_r_valid_LEVEL[2*k]), + .data_r_valid1_i(data_r_valid_LEVEL[2*k+1]), + .data_r_opc0_i(data_r_opc_LEVEL[2*k]), + .data_r_opc1_i(data_r_opc_LEVEL[2*k+1]), + // RIGTH SIDE + .data_r_rdata_o(data_r_rdata_o), + .data_r_valid_o(data_r_valid_o), + .data_r_opc_o(data_r_opc_o) + ); + end + else if ( j < LOG_SLAVE - 1) // Middle Nodes + begin : MIDDLE_NODES // START of MIDDLE LEVELS Nodes + FanInPrimitive_PE_Resp + #( + .DATA_WIDTH(DATA_WIDTH) + ) + i_FanInPrimitive_PE_Resp + ( + // RIGTH SIDE + .data_r_rdata0_i(data_r_rdata_LEVEL[((2**j)*2-2) + 2*k]), + .data_r_rdata1_i(data_r_rdata_LEVEL[((2**j)*2-2) + 2*k +1]), + .data_r_valid0_i(data_r_valid_LEVEL[((2**j)*2-2) + 2*k]), + .data_r_valid1_i(data_r_valid_LEVEL[((2**j)*2-2) + 2*k+1]), + .data_r_opc0_i(data_r_opc_LEVEL[((2**j)*2-2) + 2*k]), + .data_r_opc1_i(data_r_opc_LEVEL[((2**j)*2-2) + 2*k+1]), + // LEFT SIDE + .data_r_rdata_o(data_r_rdata_LEVEL[((2**(j-1))*2-2) + k]), + .data_r_valid_o(data_r_valid_LEVEL[((2**(j-1))*2-2) + k]), + .data_r_opc_o(data_r_opc_LEVEL[((2**(j-1))*2-2) + k]) + ); + end // END of MIDDLE LEVELS Nodes + else // First stage (connected with the Main inputs ) --> ( j == N_SLAVE - 1 ) + begin : LEAF_NODES // START of FIRST LEVEL Nodes (LEAF) + FanInPrimitive_PE_Resp + #( + .DATA_WIDTH(DATA_WIDTH) + ) + i_FanInPrimitive_PE_Resp + ( + // RIGTH SIDE + .data_r_rdata0_i(data_r_rdata_i[2*k]), + .data_r_rdata1_i(data_r_rdata_i[2*k+1]), + .data_r_valid0_i(data_r_valid_i[2*k]), + .data_r_valid1_i(data_r_valid_i[2*k+1]), + .data_r_opc0_i(data_r_opc_i[2*k]), + .data_r_opc1_i(data_r_opc_i[2*k+1]), + // LEFT SIDE + .data_r_rdata_o(data_r_rdata_LEVEL[((2**(j-1))*2-2) + k]), + .data_r_valid_o(data_r_valid_LEVEL[((2**(j-1))*2-2) + k]), + .data_r_opc_o(data_r_opc_LEVEL[((2**(j-1))*2-2) + k]) + ); + end // End of FIRST LEVEL Nodes (LEAF) + end + + end + end + endgenerate + + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/peripheral_interco/XBAR_PE.sv b/hw/deps/cluster_interconnect/rtl/peripheral_interco/XBAR_PE.sv new file mode 100644 index 0000000..5cc119d --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/peripheral_interco/XBAR_PE.sv @@ -0,0 +1,316 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 03/07/2011 // +// Design Name: LOG_INTERCONNECT // +// Module Name: XBAR_PE // +// Language: SystemVerilog // +// // +// Description: Top level for the PERIPH Crossbar. It includes both the // +// Request and response Blocks. // +// // +// Revision: // +// Revision v0.1 02/07/2011 - File Created // +// v0.2 15/08/2012 - Improved the Interface Structure, // +// Changed the routing mechanism // +// v0.3 09/03/2015 - Improved identation // +// // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "parameters.v" + +module XBAR_PE +#( + parameter int N_CH0 = 16, //--> CH0 + parameter int N_CH1 = 0, //--> CH1 + parameter int N_SLAVE = 16, + parameter int ID_WIDTH = N_CH0+N_CH1, + + parameter int PE_LSB = 2, + parameter int PE_MSB = 31, + + parameter int LOG_CLUSTER = 5, + parameter int ADDR_WIDTH = 32, + parameter int DATA_WIDTH = 32, + parameter int BE_WIDTH = DATA_WIDTH/8, + + parameter int PE_ROUTING_LSB = 16, + parameter int PE_ROUTING_MSB = 19, + + parameter bit CLUSTER_ALIAS = 1'b0, + parameter int CLUSTER_ALIAS_BASE = 12'h000, + + parameter int ADDR_PE_WIDTH = PE_MSB - PE_LSB + 1 +) +( + input [LOG_CLUSTER-1:0] CLUSTER_ID, + // ---------------- MASTER CH0+CH1 SIDE -------------------------- + // Req + input logic [N_CH0+N_CH1-1:0] data_req_i, // Data request + input logic [N_CH0+N_CH1-1:0][ADDR_WIDTH-1:0] data_add_i, // Data request Address + input logic [N_CH0+N_CH1-1:0] data_wen_i, // Data request type : 0--> Store, 1 --> Load + input logic [N_CH0+N_CH1-1:0][5:0] data_atop_i, // Data request atomic operation + input logic [N_CH0+N_CH1-1:0][DATA_WIDTH-1:0] data_wdata_i, // Data request Write data + input logic [N_CH0+N_CH1-1:0][BE_WIDTH-1:0] data_be_i, // Data request Byte enable +`ifdef GNT_BASED_FC + output logic [N_CH0+N_CH1-1:0] data_gnt_o, // Data request Grant +`else + output logic [N_CH0+N_CH1-1:0] data_stall_o, // Data request stall +`endif + // Resp + output logic [N_CH0+N_CH1-1:0] data_r_valid_o, // Data Response Valid (For LOAD/STORE commands) + output logic [N_CH0+N_CH1-1:0][DATA_WIDTH-1:0] data_r_rdata_o, // Data Response DATA (For LOAD commands) + output logic [N_CH0+N_CH1-1:0] data_r_opc_o, // Response Error + + + // ---------------- MM_SIDE (Interleaved) -------------------------- + // Req --> to Mem + output logic [N_SLAVE-1:0] data_req_o, // Data request + output logic [N_SLAVE-1:0][ADDR_PE_WIDTH-1:0] data_add_o, // Data request Address + output logic [N_SLAVE-1:0] data_wen_o, // Data request type : 0--> Store, 1 --> Load + output logic [N_SLAVE-1:0][5:0] data_atop_o, // Data request atomic operation + output logic [N_SLAVE-1:0][DATA_WIDTH-1:0] data_wdata_o, // Data request Wrire data + output logic [N_SLAVE-1:0][BE_WIDTH-1:0] data_be_o, // Data request Byte enable + output logic [N_SLAVE-1:0][ID_WIDTH-1:0] data_ID_o, +`ifdef GNT_BASED_FC + input logic [N_SLAVE-1:0] data_gnt_i, // Data request : input on slave side +`else + input logic [N_SLAVE-1:0] data_stall_i, // Data request stall : input on slave side +`endif + // Resp --> From Mem + input logic [N_SLAVE-1:0][DATA_WIDTH-1:0] data_r_rdata_i, // Data Response DATA (For LOAD commands) + input logic [N_SLAVE-1:0] data_r_valid_i, // Data Response: Command is Committed + input logic [N_SLAVE-1:0][ID_WIDTH-1:0] data_r_ID_i, // Data Response ID: To backroute Response + input logic [N_SLAVE-1:0] data_r_opc_i, // Data Response: Error + + input logic clk, // Clock + input logic rst_n // Active Low Reset +); + + // DATA ID array FORM address decoders to Request tree. + logic [N_CH0+N_CH1-1:0][ID_WIDTH-1:0] data_ID; + +`ifdef GNT_BASED_FC + logic [N_CH0+N_CH1-1:0] data_gnt_from_MEM[N_SLAVE-1:0]; +`else + logic [N_CH0+N_CH1-1:0] data_stall_from_MEM[N_SLAVE-1:0]; +`endif + logic [N_SLAVE-1:0] data_req_from_MASTER[N_CH0+N_CH1-1:0]; + logic [N_CH0+N_CH1-1:0] data_r_valid_from_MEM[N_SLAVE-1:0]; + + logic [N_SLAVE-1:0] data_r_valid_to_MASTER[N_CH0+N_CH1-1:0]; + logic [N_CH0+N_CH1-1:0] data_req_to_MEM[N_SLAVE-1:0]; +`ifdef GNT_BASED_FC + logic [N_SLAVE-1:0] data_gnt_to_MASTER[N_CH0+N_CH1-1:0]; +`else + logic [N_SLAVE-1:0] data_stall_to_MASTER[N_CH0+N_CH1-1:0]; +`endif + + logic [N_CH0+N_CH1-1:0][ADDR_PE_WIDTH-1:0] data_add; + + + genvar j,k; + + generate + + for (k=0; k (example: Used for cores) + .data_req_CH0_i(data_req_to_MEM[j][N_CH0-1:0]), + .data_add_CH0_i(data_add[N_CH0-1:0]), + .data_wen_CH0_i(data_wen_i[N_CH0-1:0]), + .data_atop_CH0_i(data_atop_i[N_CH0-1:0]), + .data_wdata_CH0_i(data_wdata_i[N_CH0-1:0]), + .data_be_CH0_i(data_be_i[N_CH0-1:0]), + .data_ID_CH0_i(data_ID[N_CH0-1:0]), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o(data_gnt_from_MEM[j][N_CH0-1:0]), + `else + .data_stall_CH0_o(data_stall_from_MEM[j][N_CH0-1:0]), + `endif + // CHANNEL CH1 --> (example: Used for DMAs) + .data_req_CH1_i(data_req_to_MEM[j][N_CH1+N_CH0-1:N_CH0]), + .data_add_CH1_i(data_add[N_CH1+N_CH0-1:N_CH0]), + .data_wen_CH1_i(data_wen_i[N_CH1+N_CH0-1:N_CH0]), + .data_atop_CH1_i(data_atop_i[N_CH1+N_CH0-1:N_CH0]), + .data_wdata_CH1_i(data_wdata_i[N_CH1+N_CH0-1:N_CH0]), + .data_be_CH1_i(data_be_i[N_CH1+N_CH0-1:N_CH0]), + .data_ID_CH1_i(data_ID[N_CH1+N_CH0-1:N_CH0]), + `ifdef GNT_BASED_FC + .data_gnt_CH1_o(data_gnt_from_MEM[j][N_CH1+N_CH0-1:N_CH0]), + `else + .data_stall_CH1_o(data_stall_from_MEM[j][N_CH1+N_CH0-1:N_CH0]), + `endif + // ----------------- MEMORY ------------------- + // ---------------- RequestBlock OUTPUT (Connected to MEMORY) ---------------- + .data_req_o(data_req_o[j]), + .data_add_o(data_add_o[j]), + .data_wen_o(data_wen_o[j]), + .data_atop_o(data_atop_o[j]), + .data_wdata_o(data_wdata_o[j]), + .data_be_o(data_be_o[j]), + .data_ID_o(data_ID_o[j]), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_i[j]), + `else + .data_stall_i(data_stall_i[j]), + `endif + .data_r_valid_i(data_r_valid_i[j]), + .data_r_ID_i(data_r_ID_i[j]), + + // GEN VALID_SIGNALS in the response path + .data_r_valid_CH0_o(data_r_valid_from_MEM[j][N_CH0-1:0]), // N_CH0 Bit + .data_r_valid_CH1_o(data_r_valid_from_MEM[j][N_CH0+N_CH1-1:N_CH0]), // N_CH1 Bit + .clk(clk), + .rst_n(rst_n) + ); + end + else + begin : CH0_ONLY + RequestBlock1CH_PE + #( + .ADDR_WIDTH(ADDR_PE_WIDTH), + .N_CH0(N_CH0), + .ID_WIDTH(ID_WIDTH), + .DATA_WIDTH(DATA_WIDTH), + .BE_WIDTH(DATA_WIDTH/8) + ) + i_RequestBlock1CH_PE + ( + // CHANNEL CH0 --> (example: Used for cores) + .data_req_CH0_i(data_req_to_MEM[j]), + .data_add_CH0_i(data_add), + .data_wen_CH0_i(data_wen_i), + .data_atop_CH0_i(data_atop_i), + .data_wdata_CH0_i(data_wdata_i), + .data_be_CH0_i(data_be_i), + .data_ID_CH0_i(data_ID), + `ifdef GNT_BASED_FC + .data_gnt_CH0_o(data_gnt_from_MEM[j]), + `else + .data_stall_CH0_o(data_stall_from_MEM[j]), + `endif + // ----------------- MEMORY ------------------- + // ---------------- RequestBlock OUTPUT (Connected to MEMORY) ---------------- + .data_req_o(data_req_o[j]), + .data_add_o(data_add_o[j]), + .data_wen_o(data_wen_o[j]), + .data_atop_o(data_atop_o[j]), + .data_wdata_o(data_wdata_o[j]), + .data_be_o(data_be_o[j]), + .data_ID_o(data_ID_o[j]), + `ifdef GNT_BASED_FC + .data_gnt_i(data_gnt_i[j]), + `else + .data_stall_i(data_stall_i[j]), + `endif + .data_r_valid_i(data_r_valid_i[j]), + .data_r_ID_i(data_r_ID_i[j]), + // GEN VALID_SIGNALS in the response path + .data_r_valid_CH0_o(data_r_valid_from_MEM[j]), // N_CH0 Bit + .clk(clk), + .rst_n(rst_n) + ); + end + end + + for (j=0; j< N_CH0+N_CH1; j++) + begin : ResponseBlock_PE_Block + ResponseBlock_PE + #( + .ID ( 2**j ), + .ID_WIDTH ( ID_WIDTH ), + .N_SLAVE ( N_SLAVE ), + .DATA_WIDTH ( DATA_WIDTH ), + .LOG_CLUSTER ( LOG_CLUSTER ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .PE_ROUTING_LSB ( PE_ROUTING_LSB ), + .PE_ROUTING_MSB ( PE_ROUTING_MSB ), + .CLUSTER_ALIAS ( CLUSTER_ALIAS ), + .CLUSTER_ALIAS_BASE (CLUSTER_ALIAS_BASE) + ) + i_ResponseBlock_PE + ( + .CLUSTER_ID(CLUSTER_ID), + // Signals from Memory cuts + .data_r_valid_i(data_r_valid_to_MASTER[j]), + .data_r_rdata_i(data_r_rdata_i), + .data_r_opc_i(data_r_opc_i), + // Output of the ResponseTree Block + .data_r_valid_o(data_r_valid_o[j]), + .data_r_rdata_o(data_r_rdata_o[j]), + .data_r_opc_o(data_r_opc_o[j]), + // Inputs form MAsters + .data_req_i(data_req_i[j]), + .data_add_i(data_add_i[j]), + `ifdef GNT_BASED_FC + .data_gnt_o(data_gnt_o[j]), // grant to master port + .data_gnt_i(data_gnt_to_MASTER[j]), // Signal from Request Block + `else + .data_stall_o(data_stall_o[j]), // stall to master port + .data_stall_i(data_stall_to_MASTER[j]), // Signal from Request Block + `endif + // Signal to/from Request Block + .data_req_o(data_req_from_MASTER[j]), + // Generated ID + .data_ID_o(data_ID[j]) + ); + end + + endgenerate + +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/addr_dec_resp_mux.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/addr_dec_resp_mux.sv new file mode 100644 index 0000000..1bbc5f7 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/addr_dec_resp_mux.sv @@ -0,0 +1,184 @@ +// Copyright 2019 ETH Zurich and 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. +// +// Author: Michael Schaffner , ETH Zurich +// Date: 06.03.2019 +// Description: address decoder and response mux for full crossbar. + +module addr_dec_resp_mux #( + parameter int unsigned NumOut = 32, + parameter int unsigned ReqDataWidth = 32, + parameter int unsigned RespDataWidth = 32, + parameter int unsigned RespLat = 1, // response latency of slaves + parameter bit WriteRespOn = 1'b1, // determines whether writes should return a response or not + parameter bit BroadCastOn = 1'b0 // perform broadcast +) ( + input logic clk_i, + input logic rst_ni, + // master side + input logic req_i, // request from this master + input logic [$clog2(NumOut)-1:0] add_i, // bank selection index to be decoded + input logic wen_i, // write enable + input logic [ReqDataWidth-1:0] data_i, // data to be transported to slaves + output logic gnt_o, // grant to master + output logic vld_o, // read/write response + output logic [RespDataWidth-1:0] rdata_o, // read response + // slave side + /* verilator lint_off UNOPTFLAT */ + output logic [NumOut-1:0] req_o, // request signals after decoding + /* verilator lint_on UNOPTFLAT */ + input logic [NumOut-1:0] gnt_i, // grants from slaves + output logic [NumOut-1:0][ReqDataWidth-1:0] data_o, // data to be transported to slaves + input logic [NumOut-1:0][RespDataWidth-1:0] rdata_i // read responses from slaves +); + +logic [RespLat-1:0] vld_d, vld_q; + +//////////////////////////////////////////////////////////////////////// +// degenerate case +//////////////////////////////////////////////////////////////////////// +if (NumOut == unsigned'(1)) begin : gen_one_output + + assign data_o[0] = data_i; + assign gnt_o = gnt_i[0]; + assign req_o[0] = req_i; + assign rdata_o = rdata_i[0]; + assign vld_o = vld_q[$high(vld_q)]; + + if (RespLat > unsigned'(1)) begin : gen_lat_gt1 + assign vld_d = {vld_q[$high(vld_q)-1:0], gnt_o & (~wen_i | WriteRespOn)}; + end else begin : gen_lat_le1 + assign vld_d = gnt_o & (~wen_i | WriteRespOn); + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg + if (!rst_ni) begin + vld_q <= '0; + end else begin + vld_q <= vld_d; + end + end + +//////////////////////////////////////////////////////////////////////// +// normal case +//////////////////////////////////////////////////////////////////////// +end else begin : gen_several_outputs + + // address decoder + always_comb begin : p_addr_dec + req_o = '0; + if (BroadCastOn) begin + if (req_i) begin + req_o = '1; + end + end else begin + req_o[add_i] = req_i; + end + end + + // connect data outputs + assign data_o = {NumOut{data_i}}; + + // aggregate grant signals + assign gnt_o = |gnt_i; + assign vld_o = vld_q[$high(vld_q)]; + + // response path in case of broadcasts + if (BroadCastOn) begin : gen_bcast + logic [NumOut-1:0] gnt_d, gnt_q; + logic [$clog2(NumOut)-1:0] bank_sel; + + assign gnt_d = gnt_i; + + // determine index from + // one-hot grant vector + lzc #( + .WIDTH(NumOut) + ) lzc_i ( + .in_i(gnt_q), + .cnt_o(bank_sel), + .empty_o() + ); + + if (RespLat > unsigned'(1)) begin : gen_lat_gt1 + logic [RespLat-2:0][$clog2(NumOut)-1:0] bank_sel_d, bank_sel_q; + + assign rdata_o = rdata_i[bank_sel_q[$high(bank_sel_q)]]; + assign vld_d = {vld_q[$high(vld_q)-1:0], gnt_o & (~wen_i | WriteRespOn)}; + + if (RespLat == unsigned'(2)) begin : gen_lat_eq2 + assign bank_sel_d = {bank_sel_q[$high(bank_sel_q)-2:0], bank_sel, bank_sel}; + end else begin : gen_lat_le2 + assign bank_sel_d = bank_sel; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg + if (!rst_ni) begin + bank_sel_q <= '0; + end else begin + bank_sel_q <= bank_sel_d; + end + end + + end else begin : gen_lat_eq1 + assign rdata_o = rdata_i[bank_sel]; + assign vld_d = gnt_o & (~wen_i | WriteRespOn); + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg + if (!rst_ni) begin + gnt_q <= '0; + vld_q <= '0; + end else begin + gnt_q <= gnt_d; + vld_q <= vld_d; + end + end + + // non-broadcast case + end else begin : gen_no_broadcast + logic [RespLat-1:0][$clog2(NumOut)-1:0] bank_sel_d, bank_sel_q; + + assign rdata_o = rdata_i[bank_sel_q[$high(bank_sel_q)]]; + + if (RespLat > unsigned'(1)) begin : gen_lat_gt1 + assign bank_sel_d = {bank_sel_q[$high(bank_sel_q)-1:0], add_i}; + assign vld_d = {vld_q[$high(vld_q)-1:0], gnt_o & (~wen_i | WriteRespOn)}; + end else begin : gen_lat_le1 + assign bank_sel_d = add_i; + assign vld_d = gnt_o & (~wen_i | WriteRespOn); + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg + if (!rst_ni) begin + bank_sel_q <= '0; + vld_q <= '0; + end else begin + bank_sel_q <= bank_sel_d; + vld_q <= vld_d; + end + end + end +end + +//////////////////////////////////////////////////////////////////////// +// assertions +//////////////////////////////////////////////////////////////////////// + +// pragma translate_off +initial begin + assert (RespLat > 0) else + $fatal(1,"RespLat must be greater than 0"); + assert (NumOut > 0) else + $fatal(1,"NumOut must be greater than 0"); +end +// pragma translate_on + +endmodule // addr_dec_resp_mux diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/amo_shim.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/amo_shim.sv new file mode 100644 index 0000000..cdd439c --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/amo_shim.sv @@ -0,0 +1,333 @@ +// Copyright 2020 ETH Zurich and 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. + +/// Description: Governs atomic memory oeprations. This module needs to be instantiated +/// in front of an SRAM. It needs to have exclusive access over it. + +/// Author: Florian Zaruba +/// Superbank Patches: Thomas Benz +module amo_shim #( + parameter int unsigned AddrMemWidth = -1, + parameter int unsigned DataWidth = -1 +) ( + input logic clk_i, + input logic rst_ni, + // master side + input logic in_req_i, // Bank request + output logic in_gnt_o, // Bank grant + input logic [AddrMemWidth-1:0] in_add_i, // Address + input logic [3:0] in_amo_i, // Atomic Memory Operation + input logic in_wen_i, // 1: Store, 0: Load + input logic [DataWidth-1:0] in_wdata_i, // Write data + input logic [DataWidth/8-1:0] in_be_i, // Byte enable + output logic [DataWidth-1:0] in_rdata_o, // Read data + // slave side + output logic out_req_o, // Bank request + output logic [AddrMemWidth-1:0] out_add_o, // Address + output logic out_wen_o, // 1: Store, 0: Load + output logic [DataWidth-1:0] out_wdata_o, // Write data + output logic [DataWidth/8-1:0] out_be_o, // Byte enable + input logic [DataWidth-1:0] out_rdata_i, // Read data + // dma ports + input logic dma_access_i, // Current Access is a DMA access -> bypass amo, abort current op + output logic amo_conflict_o // Throw an error if DMA access occured on amo mem location +); + + typedef enum logic [3:0] { + AMONone = 4'h0, + AMOSwap = 4'h1, + AMOAdd = 4'h2, + AMOAnd = 4'h3, + AMOOr = 4'h4, + AMOXor = 4'h5, + AMOMax = 4'h6, + AMOMaxu = 4'h7, + AMOMin = 4'h8, + AMOMinu = 4'h9, + AMOCAS = 4'hA + } amo_op_t; + + enum logic [1:0] { + Idle, DoAMO, ProlongAMO + } state_q, state_d, state_qq; + + amo_op_t amo_op_q, amo_op_qq; + + logic load_amo; + + logic [AddrMemWidth-1:0] addr_q; + + logic [31:0] amo_operand_a; + logic [31:0] amo_operand_a_d, amo_operand_a_q; + logic [31:0] amo_operand_b_q; + // requested amo should be performed on upper 32 bit + logic upper_word_q; + logic [DataWidth/8-1:0] be_q; + logic [31:0] swap_value_q; + logic [31:0] amo_result; + + logic out_req_d, out_req_q; + logic [AddrMemWidth-1:0] out_add_d, out_add_q; + logic out_wen_d, out_wen_q; + logic [DataWidth/8-1:0] out_be_d, out_be_q; + logic [DataWidth-1:0] out_wdata_d, out_wdata_q; + logic [DataWidth-1:0] in_rdata_d, in_rdata_q; + + always_comb begin + // feed-through + out_req_o = in_req_i; + in_gnt_o = in_req_i; + out_add_o = in_add_i; + out_wen_o = in_wen_i; + out_wdata_o = in_wdata_i; + out_be_o = in_be_i; + in_rdata_o = out_rdata_i; + + // default + out_req_d = out_req_q; + out_add_d = out_add_q; + out_wen_d = out_wen_q; + out_be_d = out_be_q; + out_wdata_d = out_wdata_q; + in_rdata_d = in_rdata_q; + + // assume no error happened + if (DataWidth == 64) begin : gen_op_a_64 + /* verilator lint_off SELRANGE */ + amo_operand_a = upper_word_q ? out_rdata_i[63:32] : out_rdata_i[31:0]; + /* verilator lint_on SELRANGE */ + end else begin : gen_op_a_32 + amo_operand_a = out_rdata_i[31:0]; + end + amo_conflict_o = 1'b0; + state_d = state_q; + load_amo = 1'b0; + amo_operand_a_d = amo_operand_a; + + unique case (state_q) + Idle: begin + if (in_req_i && amo_op_t'(in_amo_i) != AMONone) begin + load_amo = 1'b1; + state_d = DoAMO; + out_wen_o = 1'b0; + end + end + // Claim the memory interface + DoAMO: begin + + // check if amo op was prolonged, if so use previous results + if(state_qq == ProlongAMO) begin + amo_operand_a = amo_operand_a_q; + end + + in_gnt_o = 1'b0; + state_d = Idle; + // Commit AMO + out_req_o = 1'b1; + out_be_o = be_q; + out_wen_o = |be_q; + out_add_o = addr_q; + // shift up if the address was pointing to the upper 32 bits + if (DataWidth == 64) begin + if (upper_word_q) begin + out_wdata_o = {amo_result, 32'b0}; + in_rdata_o = {amo_operand_a, 32'b0}; + end else begin + out_wdata_o = {32'b0, amo_result}; + in_rdata_o = {32'b0, amo_operand_a}; + end + end else begin + out_wdata_o = amo_result; + in_rdata_o = amo_operand_a; + end + + // overrule amo shim if dma is active + if (dma_access_i) begin + // store output of shim + out_req_d = out_req_o; + out_add_d = out_add_o; + out_wen_d = out_wen_o; + out_be_d = out_be_o; + out_wdata_d = out_wdata_o; + in_rdata_d = in_rdata_o; + + // dma data + out_req_o = in_req_i; + in_gnt_o = in_req_i; + out_add_o = in_add_i; + out_wen_o = in_wen_i; + out_wdata_o = in_wdata_i; + out_be_o = in_be_i; + in_rdata_o = out_rdata_i; + // something dangerous happend, inform programmer + amo_conflict_o = (addr_q == in_add_i); + // prolong the amo state + state_d = ProlongAMO; + end + end + // AMO was interrupted by DMA transfer and therefore prolonged + ProlongAMO: begin + state_d = dma_access_i ? ProlongAMO : Idle; + in_gnt_o = dma_access_i; + amo_operand_a_d = amo_operand_a_q; + // prolong + out_req_d = out_req_q; + out_add_d = out_add_q; + out_wen_d = out_wen_q; + out_be_d = out_be_q; + out_wdata_d = out_wdata_q; + in_rdata_d = in_rdata_q; + + if (~dma_access_i) begin + // replay + out_req_o = out_req_q; + out_add_o = out_add_q; + out_wen_o = out_wen_q; + out_be_o = out_be_q; + out_wdata_o = out_wdata_q; + in_rdata_o = in_rdata_q; + end + + end + + default:; + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + state_q <= Idle; + amo_op_q <= amo_op_t'('0); + addr_q <= '0; + amo_operand_b_q <= '0; + amo_operand_a_q <= '0; + be_q <= '0; + swap_value_q <= '0; + upper_word_q <= '0; + amo_op_qq <= amo_op_t'('0); + + out_req_q <= '0; + out_add_q <= '0; + out_wen_q <= '0; + out_be_q <= '0; + out_wdata_q <= '0; + in_rdata_q <= '0; + end else begin + + out_req_q <= out_req_d; + out_add_q <= out_add_d; + out_wen_q <= out_wen_d; + out_be_q <= out_be_d; + out_wdata_q <= out_wdata_d; + in_rdata_q <= in_rdata_d; + + state_q <= state_d; + state_qq <= state_q; + amo_op_qq <= amo_op_q; + amo_operand_a_q <= amo_operand_a_d; + if (load_amo) begin + amo_op_q <= amo_op_t'(in_amo_i); + addr_q <= in_add_i; + be_q <= in_be_i; + if (DataWidth == 64) begin + if (!in_be_i[0]) begin + /* verilator lint_off SELRANGE */ + amo_operand_b_q <= in_wdata_i[63:32]; + /* verilator lint_on SELRANGE */ + end + /* verilator lint_off SELRANGE */ + upper_word_q <= in_be_i[4]; + /* verilator lint_on SELRANGE */ + // swap value is located in the upper word + /* verilator lint_off SELRANGE */ + swap_value_q <= in_wdata_i[63:32]; + /* verilator lint_on SELRANGE */ + end else begin + amo_operand_b_q <= in_wdata_i[31:0]; + end + // on DMA access, keep last op in memory + end else if(dma_access_i) begin + amo_op_q <= amo_op_q; + end else begin + amo_op_q <= AMONone; + end + end + end + + // ---------------- + // AMO ALU + // ---------------- + logic [33:0] adder_sum; + logic [32:0] adder_operand_a, adder_operand_b; + + assign adder_sum = adder_operand_a + adder_operand_b; + /* verilator lint_off WIDTH */ + always_comb begin : amo_alu + + adder_operand_a = 33'($signed(amo_operand_a)); + adder_operand_b = 33'($signed(amo_operand_b_q)); + + amo_result = amo_operand_b_q; + + unique case (state_qq == ProlongAMO ? amo_op_qq : amo_op_q) + // the default is to output operand_b + AMOSwap:; + AMOAdd: amo_result = adder_sum[31:0]; + AMOAnd: amo_result = amo_operand_a & amo_operand_b_q; + AMOOr: amo_result = amo_operand_a | amo_operand_b_q; + AMOXor: amo_result = amo_operand_a ^ amo_operand_b_q; + AMOMax: begin + adder_operand_b = -$signed(amo_operand_b_q); + amo_result = adder_sum[32] ? amo_operand_b_q : amo_operand_a; + end + AMOMin: begin + adder_operand_b = -$signed(amo_operand_b_q); + amo_result = adder_sum[32] ? amo_operand_a : amo_operand_b_q; + end + AMOMaxu: begin + adder_operand_a = 33'($unsigned(amo_operand_a)); + adder_operand_b = -$unsigned(amo_operand_b_q); + amo_result = adder_sum[32] ? amo_operand_b_q : amo_operand_a; + end + AMOMinu: begin + adder_operand_a = 33'($unsigned(amo_operand_a)); + adder_operand_b = -$unsigned(amo_operand_b_q); + amo_result = adder_sum[32] ? amo_operand_a : amo_operand_b_q; + end + AMOCAS: begin + if (DataWidth == 64) begin + adder_operand_b = -$signed(amo_operand_b_q); + // values are equal -> update + if (adder_sum == '0) begin + amo_result = swap_value_q; + // values are not euqal -> don't update + end else begin + /* verilator lint_off SELRANGE */ + amo_result = upper_word_q ? out_rdata_i[63:32] : out_rdata_i[31:0]; + /* verilator lint_on SELRANGE */ + end + end else begin + $error("AMOCAS not supported for DataWidth = 32 bit"); + end + end + default: amo_result = '0; + endcase + end + /* verilator lint_on WIDTH */ + + `ifndef VERILATOR + // pragma translate_off + initial begin + assert (DataWidth == 32 || DataWidth == 64) + else $fatal(1, "Unsupported data width!"); + end + // pragma translate_on + `endif +endmodule diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/superbank_addr_decoder.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/superbank_addr_decoder.sv new file mode 100644 index 0000000..d1d35e5 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/superbank_addr_decoder.sv @@ -0,0 +1,114 @@ +/// Copyright (c) 2020 ETH Zurich, University of Bologna +/// All rights reserved. +/// +/// This code is under development and not yet released to the public. +/// Until it is released, the code is under the copyright of ETH Zurich and +/// the University of Bologna, and may contain confidential and/or unpublished +/// work. Any reuse/redistribution is strictly forbidden without written +/// permission from ETH Zurich. +/// +/// Superbank address decoder +/// groups a number of banks in the TCDM to superbanks. One superbank can be served by the DMA +/// in one cycle. + +/// Author: Thomas Benz + +module superbank_addr_decoder #( + parameter int unsigned TCDMAddrWidth = -1, + parameter int unsigned DMAAddrWidth = -1, + parameter int unsigned BanksPerSuperbank = -1, + parameter int unsigned NrSuperBanks = -1, + parameter int unsigned DMADataWidth = -1, + parameter int unsigned AmoWidth = -1, + parameter int unsigned MemoryLatency = -1 +) ( + + input logic clk_i, + input logic rst_i, + + // single port towards dma + input logic dma_req_i, // Bank request + output logic dma_gnt_o, // Bank grant + input logic [DMAAddrWidth-1:0 ] dma_add_i, // Address + input logic [AmoWidth-1:0 ] dma_amo_i, // Atomic Memory Operation + input logic dma_wen_i, // 1: Store, 0: Load + input logic [DMADataWidth-1:0 ] dma_wdata_i, // Write data + input logic [DMADataWidth/8-1:0 ] dma_be_i, // Byte enable + output logic [DMADataWidth-1:0 ] dma_rdata_o, // Read data + + // dma side + output logic [NrSuperBanks-1:0] super_bank_req_o, // Bank request + input logic [NrSuperBanks-1:0] super_bank_gnt_i, // Bank grant + output logic [NrSuperBanks-1:0][TCDMAddrWidth-1:0 ] super_bank_add_o, // Address + output logic [NrSuperBanks-1:0][AmoWidth-1:0 ] super_bank_amo_o, // Atomic Memory Operation + output logic [NrSuperBanks-1:0] super_bank_wen_o, // 1: Store, 0: Load + output logic [NrSuperBanks-1:0][DMADataWidth-1:0 ] super_bank_wdata_o, // Write data + output logic [NrSuperBanks-1:0][DMADataWidth/8-1:0 ] super_bank_be_o, // Byte enable + input logic [NrSuperBanks-1:0][DMADataWidth-1:0 ] super_bank_rdata_i // Read data +); + + localparam SBWidth = $clog2(NrSuperBanks); + localparam DMADataWidthBytes = DMADataWidth / 8; + localparam NumBitsDMATrans = $clog2(DMADataWidthBytes); // example case: 6 + + // case for 512 bits, 32 banks, 4 superbanks, 1024 words per bank, 256kiB, 64bit system + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + // 00000000000000000000000000000000000000000|-----------------------------|-----|--------|--------| + // zero or ignored tcdm line address superbank byte in bank + // subbank + + localparam TCDMUpper = SBWidth + NumBitsDMATrans + TCDMAddrWidth; + + // super bank address + logic [SBWidth-1:0] super_bank; + logic [TCDMAddrWidth-1:0] tcdm_line_address; + // have to keep the last choosen bank to correctly route response (rdata back) + // the memory can have a parametrizable amount of delay. + logic [MemoryLatency-1:0][SBWidth-1:0] super_bank_q; + + // divide the address + assign super_bank = dma_add_i[SBWidth+NumBitsDMATrans-1:NumBitsDMATrans]; + assign tcdm_line_address = dma_add_i[TCDMUpper-1:TCDMUpper-TCDMAddrWidth]; + + + // create the mux inthe forward and backwords direction + always_comb begin : proc_dma_addr_decoder + + // unused ports are set to 0 + super_bank_req_o = '0; + super_bank_add_o = '0; + super_bank_amo_o = '0; + super_bank_wen_o = '0; + super_bank_wdata_o = '0; + super_bank_be_o = '0; + + // mux + super_bank_req_o [super_bank] = dma_req_i; + super_bank_add_o [super_bank] = tcdm_line_address; + super_bank_amo_o [super_bank] = dma_amo_i; + super_bank_wen_o [super_bank] = dma_wen_i; + super_bank_wdata_o [super_bank] = dma_wdata_i; + super_bank_be_o [super_bank] = dma_be_i; + + dma_gnt_o = super_bank_gnt_i [super_bank]; + + // backwards path has be delayed by one, as memory has one cycle latency + dma_rdata_o = super_bank_rdata_i [super_bank_q[MemoryLatency-1]]; + + end + + always_ff @(posedge clk_i) begin : proc_delay_bank_choice + if (rst_i) begin + super_bank_q<= 0; + end else begin + super_bank_q[0] <= super_bank; + // implement the shift for the delay + if (MemoryLatency > 1) begin + for (int i = 1; i < MemoryLatency; i++) begin + super_bank_q[i] <= super_bank_q[i-1]; + end + end + end + end + +endmodule : superbank_addr_decoder diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect.sv new file mode 100644 index 0000000..0b4025f --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect.sv @@ -0,0 +1,323 @@ +// Copyright 2019 ETH Zurich and 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. +// +// Author: Michael Schaffner , ETH Zurich +// Date: 06.03.2019 +// Description: TCDM interconnect with different network topologies. Currently +// supported are: full crossbar, radix-2/4 butterflies and clos networks. +// Note that only the full crossbar allows NumIn/NumOut configurations that are not +// aligned to a power of 2. + +module tcdm_interconnect #( + /////////////////////////// + // global parameters + parameter int unsigned NumIn = 32, // number of initiator ports (must be aligned with power of 2 for bfly and clos) + parameter int unsigned NumOut = 64, // number of TCDM banks (must be aligned with power of 2 for bfly and clos) + parameter int unsigned AddrWidth = 32, // address width on initiator side + parameter int unsigned DataWidth = 32, // word width of data + parameter int unsigned BeWidth = DataWidth/8, // width of corresponding byte enables + parameter int unsigned AddrMemWidth = 12, // number of address bits per TCDM bank + parameter bit WriteRespOn = 1, // defines whether the interconnect returns a write response + parameter int unsigned RespLat = 1, // TCDM read latency, usually 1 cycle + // determines the width of the byte offset in a memory word. normally this can be left at the default vaule, + // but sometimes it needs to be overridden (e.g. when meta-data is supplied to the memory via the wdata signal). + parameter int unsigned ByteOffWidth = $clog2(DataWidth-1)-3, + + // topology can be: LIC, BFLY2, BFLY4, CLOS + parameter tcdm_interconnect_pkg::topo_e Topology = tcdm_interconnect_pkg::LIC, + // number of parallel butterfly's to use, only relevant for BFLY topologies + parameter int unsigned NumPar = 1, + // this detemines which Clos config to use, only relevant for CLOS topologies + // 1: m=0.50*n, 2: m=1.00*n, 3: m=2.00*n + parameter int unsigned ClosConfig = 2 + /////////////////////////// +) ( + input logic clk_i, + input logic rst_ni, + // master side + input logic [NumIn-1:0] req_i, // request signal + input logic [NumIn-1:0][AddrWidth-1:0] add_i, // tcdm address + input logic [NumIn-1:0] wen_i, // 1: store, 0: load + input logic [NumIn-1:0][DataWidth-1:0] wdata_i, // write data + input logic [NumIn-1:0][BeWidth-1:0] be_i, // byte enable + output logic [NumIn-1:0] gnt_o, // grant (combinationally dependent on req_i and add_i + output logic [NumIn-1:0] vld_o, // response valid, also asserted if write responses ar + output logic [NumIn-1:0][DataWidth-1:0] rdata_o, // data response (for load commands) + // slave side + output logic [NumOut-1:0] req_o, // request out + input logic [NumOut-1:0] gnt_i, // grant input + output logic [NumOut-1:0][AddrMemWidth-1:0] add_o, // address within bank + output logic [NumOut-1:0] wen_o, // write enable + output logic [NumOut-1:0][DataWidth-1:0] wdata_o, // write data + output logic [NumOut-1:0][BeWidth-1:0] be_o, // byte enable + input logic [NumOut-1:0][DataWidth-1:0] rdata_i // data response (for load commands) +); + +//////////////////////////////////////////////////////////////////////// +// localparams and stacking of address, wen and payload data +//////////////////////////////////////////////////////////////////////// + +localparam int unsigned NumOutLog2 = $clog2(NumOut); +localparam int unsigned AggDataWidth = 1+BeWidth+AddrMemWidth+DataWidth; +logic [NumIn-1:0][AggDataWidth-1:0] data_agg_in; +logic [NumOut-1:0][AggDataWidth-1:0] data_agg_out; +logic [NumIn-1:0][NumOutLog2-1:0] bank_sel; + +for (genvar j = 0; unsigned'(j) < NumIn; j++) begin : gen_inputs + // extract bank index + assign bank_sel[j] = add_i[j][ByteOffWidth+NumOutLog2-1:ByteOffWidth]; + // aggregate data to be routed to slaves + assign data_agg_in[j] = {wen_i[j], be_i[j], add_i[j][ByteOffWidth+NumOutLog2+AddrMemWidth-1:ByteOffWidth+NumOutLog2], wdata_i[j]}; +end + +// disaggregate data +for (genvar k = 0; unsigned'(k) < NumOut; k++) begin : gen_outputs + assign {wen_o[k], be_o[k], add_o[k], wdata_o[k]} = data_agg_out[k]; +end + +//////////////////////////////////////////////////////////////////////// +// tuned logarithmic interconnect architecture, based on rr_arb_tree primitives +//////////////////////////////////////////////////////////////////////// +if (Topology == tcdm_interconnect_pkg::LIC) begin : gen_lic + xbar #( + .NumIn ( NumIn ), + .NumOut ( NumOut ), + .ReqDataWidth ( AggDataWidth ), + .RespDataWidth ( DataWidth ), + .RespLat ( RespLat ), + .WriteRespOn ( WriteRespOn ) + ) i_xbar ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( req_i ), + .add_i ( bank_sel ), + .wen_i ( wen_i ), + .wdata_i ( data_agg_in ), + .gnt_o ( gnt_o ), + .rdata_o ( rdata_o ), + .rr_i ( '0 ), + .vld_o ( vld_o ), + .gnt_i ( gnt_i ), + .req_o ( req_o ), + .wdata_o ( data_agg_out ), + .rdata_i ( rdata_i ) + ); +//////////////////////////////////////////////////////////////////////// +// butterfly network (radix 2 or 4) with parallelization option +// (NumPar>1 results in a hybrid between lic and bfly) +//////////////////////////////////////////////////////////////////////// +end else if (Topology == tcdm_interconnect_pkg::BFLY2 || Topology == tcdm_interconnect_pkg::BFLY4) begin : gen_bfly + localparam int unsigned NumPerSlice = NumIn/NumPar; + localparam int unsigned Radix = 2**Topology; + logic [NumOut-1:0][NumPar-1:0][AggDataWidth-1:0] data1; + logic [NumOut-1:0][NumPar-1:0][DataWidth-1:0] rdata1; + logic [NumOut-1:0][NumPar-1:0] gnt1, req1; + + logic [NumPar-1:0][NumOut-1:0][AggDataWidth-1:0] data1_trsp; + logic [NumPar-1:0][NumOut-1:0][DataWidth-1:0] rdata1_trsp; + logic [NumPar-1:0][NumOut-1:0] gnt1_trsp, req1_trsp; + + logic [$clog2(NumIn)-1:0] rr; + logic [NumOutLog2-1:0] rr1; + + // Although round robin arbitration works in some cases, it + // it is quite likely that it interferes with linear access patterns + // hence we use a relatively long LFSR + block cipher here to create a + // pseudo random sequence with good randomness. the block cipher layers + // are used to break shift register linearity. + lfsr #( + .LfsrWidth(64), + .OutWidth($clog2(NumIn)), + .CipherLayers(3), + .CipherReg(1'b1) + ) lfsr_i ( + .clk_i, + .rst_ni, + .en_i(|(gnt_i & req_o)), + .out_o(rr) + ); + + // // this performs a density estimation of the lfsr output + // // in order to assess the quality of the pseudo random sequence + // // ideally this should be flat + // // pragma translate_off + // int unsigned cnt [0:NumOut-1]; + // int unsigned cycle; + // always_ff @(posedge clk_i or negedge rst_ni) begin : p_stats + // if(!rst_ni) begin + // cnt <= '{default:0}; + // cycle <= 0; + // end else begin + // if (|(gnt_i & req_o)) begin + // cnt[rr] <= cnt[rr]+1; + // cycle <= cycle + 1; + // if ((cycle % 9500) == 0 && (cycle>0)) begin + // $display("------------------------"); + // $display("--- LFSR Binning: ---"); + // $display("------------------------"); + // for (int unsigned k=0; k unsigned'(1)) begin : gen_rr_arb + + logic [$clog2(NumPar)-1:0] rr2; + assign rr2 = $clog2(NumPar)'(rr[$clog2(NumPar)-1:0]); + + for (genvar k = 0; unsigned'(k) < NumOut; k++) begin : gen_par + rr_arb_tree #( + .NumIn ( NumPar ), + .DataWidth ( AggDataWidth ), + .ExtPrio ( 1'b1 ) + ) i_rr_arb_tree ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .rr_i ( rr2 ), + .req_i ( req1[k] ), + .gnt_o ( gnt1[k] ), + .data_i ( data1[k] ), + .gnt_i ( gnt_i[k] ), + .req_o ( req_o[k] ), + .data_o ( data_agg_out[k] ), + .idx_o ( )// disabled + ); + end + end else begin : gen_no_rr_arb + // just connect through in this case + assign data_agg_out = data1; + assign req_o = req1; + assign gnt1 = gnt_i; + end + // pragma translate_off + initial begin + assert(NumPar >= unsigned'(1)) else + $fatal(1,"NumPar must be greater or equal 1."); + end + // pragma translate_on +//////////////////////////////////////////////////////////////////////// +// clos network +//////////////////////////////////////////////////////////////////////// +end else if (Topology == tcdm_interconnect_pkg::CLOS) begin : gen_clos + clos_net #( + .NumIn ( NumIn ), + .NumOut ( NumOut ), + .ReqDataWidth ( AggDataWidth ), + .RespDataWidth ( DataWidth ), + .RespLat ( RespLat ), + .WriteRespOn ( WriteRespOn ), + .ClosConfig ( ClosConfig ) + ) i_clos_net ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( req_i ), + .gnt_o ( gnt_o ), + .add_i ( bank_sel ), + .wen_i ( wen_i ), + .wdata_i ( data_agg_in ), + .rdata_o ( rdata_o ), + .vld_o ( vld_o ), + .req_o ( req_o ), + .gnt_i ( gnt_i ), + .wdata_o ( data_agg_out ), + .rdata_i ( rdata_i ) + ); +//////////////////////////////////////////////////////////////////////// +end else begin : gen_unknown + // pragma translate_off + initial begin + $fatal(1,"Unknown TCDM configuration %d.", Topology); + end + // pragma translate_on +end +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// assertions +//////////////////////////////////////////////////////////////////////// + +// pragma translate_off +initial begin + assert(AddrMemWidth+NumOutLog2 <= AddrWidth) else + $fatal(1,"Address not wide enough to accomodate the requested TCDM configuration."); + assert(NumOut >= NumIn) else + $fatal(1,"NumOut < NumIn is not supported."); +end +// pragma translate_on + +endmodule // tcdm_interconnect diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect_pkg.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect_pkg.sv new file mode 100644 index 0000000..7bdd0ed --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect_pkg.sv @@ -0,0 +1,73 @@ +// Copyright 2019 ETH Zurich and 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. +// +// Author: Michael Schaffner , ETH Zurich +// Date: 28.05.2019 +// Description: Package with important constants and lookup tables for TCDM +// interconnect. + +package tcdm_interconnect_pkg; + +typedef enum logic [1:0] { LIC, BFLY2, BFLY4, CLOS } topo_e; + +//////////////////////////////////////////////////////////////////////// +// LUT params for Clos net with configs: 1: m=0.50*n, 2: m=1.00*n, 3: m=2.00*n, +// to be indexed with [config_idx][$clog2(BankingFact)][$clog2(NumBanks)] +// generated with MATLAB script gen_clos_params.m +//////////////////////////////////////////////////////////////////////// +localparam logic [3:1][4:0][12:2][15:0] ClosNLut = {16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2}; +localparam logic [3:1][4:0][12:2][15:0] ClosMLut = {16'd128,16'd128,16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4, + 16'd128,16'd128,16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4, + 16'd128,16'd128,16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4, + 16'd128,16'd128,16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4, + 16'd128,16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2,16'd1, + 16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2,16'd1, + 16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2,16'd1, + 16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2,16'd1, + 16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2,16'd1,16'd1}; +localparam logic [3:1][4:0][12:2][15:0] ClosRLut = {16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2,16'd2, + 16'd64,16'd64,16'd32,16'd32,16'd16,16'd16,16'd8,16'd8,16'd4,16'd4,16'd2}; + + + +endpackage : tcdm_interconnect_pkg diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_superbank_mux.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_superbank_mux.sv new file mode 100644 index 0000000..418e183 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_superbank_mux.sv @@ -0,0 +1,184 @@ +/// Copyright (c) 2020 ETH Zurich, University of Bologna +/// All rights reserved. +/// +/// This code is under development and not yet released to the public. +/// Until it is released, the code is under the copyright of ETH Zurich and +/// the University of Bologna, and may contain confidential and/or unpublished +/// work. Any reuse/redistribution is strictly forbidden without written +/// permission from ETH Zurich. +/// +/// Description: Mux between the DMA and the interconnect. 1 DMA access +/// occupies N banks. + +/// Author: Thomas Benz + +module tcdm_superbank_mux #( + + parameter int unsigned AddrMemWidth = -1, + parameter int unsigned BanksPerSuperbank = -1, + parameter int unsigned DMADataWidth = -1, + parameter int unsigned DataWidth = -1, + parameter int unsigned AmoWidth = -1 +) ( + + input logic clk_i, + input logic rst_i, + + // interconnect side + input logic [BanksPerSuperbank-1:0] ic_req_i, // Bank request + output logic [BanksPerSuperbank-1:0] ic_gnt_o, // Bank grant + input logic [BanksPerSuperbank-1:0][AddrMemWidth-1:0 ] ic_add_i, // Address + input logic [BanksPerSuperbank-1:0][AmoWidth-1:0 ] ic_amo_i, // Atomic Memory Operation + input logic [BanksPerSuperbank-1:0] ic_wen_i, // 1: Store, 0: Load + input logic [BanksPerSuperbank-1:0][DataWidth-1:0 ] ic_wdata_i, // Write data + input logic [BanksPerSuperbank-1:0][DataWidth/8-1:0 ] ic_be_i, // Byte enable + output logic [BanksPerSuperbank-1:0][DataWidth-1:0 ] ic_rdata_o, // Read data + + // dma a side + input logic dma_a_req_i, // Bank request + output logic dma_a_gnt_o, // Bank grant + input logic [AddrMemWidth-1:0 ] dma_a_add_i, // Address + input logic [AmoWidth-1:0 ] dma_a_amo_i, // Atomic Memory Operation + input logic dma_a_wen_i, // 1: Store, 0: Load + input logic [DMADataWidth-1:0 ] dma_a_wdata_i, // Write data + input logic [DMADataWidth/8-1:0 ] dma_a_be_i, // Byte enable + output logic [DMADataWidth-1:0 ] dma_a_rdata_o, // Read data + + // dma b side + input logic dma_b_req_i, // Bank request + output logic dma_b_gnt_o, // Bank grant + input logic [AddrMemWidth-1:0 ] dma_b_add_i, // Address + input logic [AmoWidth-1:0 ] dma_b_amo_i, // Atomic Memory Operation + input logic dma_b_wen_i, // 1: Store, 0: Load + input logic [DMADataWidth-1:0 ] dma_b_wdata_i, // Write data + input logic [DMADataWidth/8-1:0 ] dma_b_be_i, // Byte enable + output logic [DMADataWidth-1:0 ] dma_b_rdata_o, // Read data + + // to memory/amo ports + output logic [BanksPerSuperbank-1:0] amo_req_o, // Bank request + input logic [BanksPerSuperbank-1:0] amo_gnt_i, // Bank grant + output logic [BanksPerSuperbank-1:0][AddrMemWidth-1:0] amo_add_o, // Address + output logic [BanksPerSuperbank-1:0][AmoWidth-1:0 ] amo_amo_o, // Atomic Memory Operation + output logic [BanksPerSuperbank-1:0] amo_wen_o, // 1: Store, 0: Load + output logic [BanksPerSuperbank-1:0][DataWidth-1:0 ] amo_wdata_o, // Write data + output logic [BanksPerSuperbank-1:0][DataWidth/8-1:0 ] amo_be_o, // Byte enable + input logic [BanksPerSuperbank-1:0][DataWidth-1:0 ] amo_rdata_i, // Read data + + // general inputs + input logic sel_dma_a_i, // 0: use ic port, 1: use dma port + input logic sel_dma_b_i // 0: use ic port, 1: use dma port +); + + typedef struct packed { + logic [AddrMemWidth-1:0 ] add; + logic [AmoWidth-1:0 ] amo; + logic wen; + logic [DMADataWidth-1:0 ] wdata; + logic [DMADataWidth/8-1:0 ] be; + } payload_t; + + // arbitrated signals + logic dma_rr_req, dma_rr_gnt; + payload_t dma_payload_a, dma_payload_b, dma_payload_rr; + logic dma_port_used; + + // dma active signal + logic sel_dma; + + // response is always delayed: + logic sel_dma_q; + + // arbitrate the two DMA ports + rr_arb_tree #( + .NumIn ( 2 ), + .DataType ( payload_t ) + ) i_rr_arb_tree ( + .clk_i ( clk_i ), + .rst_ni ( ~rst_i ), + .flush_i ( '0 ), + .rr_i ( '0 ), + .req_i ( { dma_a_req_i, dma_b_req_i } ), + .gnt_o ( { dma_a_gnt_o, dma_b_gnt_o } ), + .data_i ( { dma_payload_a, dma_payload_b } ), + .req_o ( dma_rr_req ), + .gnt_i ( dma_rr_gnt ), + .data_o ( dma_payload_rr ), + .idx_o ( ) + ); + + // one of the two DMA ports is active + assign sel_dma = sel_dma_a_i | sel_dma_b_i; + + // pack a and b ports + assign dma_payload_a.add = dma_a_add_i; + assign dma_payload_a.amo = dma_a_amo_i; + assign dma_payload_a.wen = dma_a_wen_i; + assign dma_payload_a.wdata = dma_a_wdata_i; + assign dma_payload_a.be = dma_a_be_i; + + assign dma_payload_b.add = dma_b_add_i; + assign dma_payload_b.amo = dma_b_amo_i; + assign dma_payload_b.wen = dma_b_wen_i; + assign dma_payload_b.wdata = dma_b_wdata_i; + assign dma_payload_b.be = dma_b_be_i; + + // forwards channel DMA to memory. + always_comb begin : proc_tcdm_mux + + // default -> feed trough ic requests + ic_gnt_o = amo_gnt_i; + amo_req_o = ic_req_i; + amo_add_o = ic_add_i; + amo_amo_o = ic_amo_i; + amo_wen_o = ic_wen_i; + amo_wdata_o = ic_wdata_i; + amo_be_o = ic_be_i; + + // tie dma gnt port to 0 + dma_rr_gnt = 'b0; + + + if(sel_dma) begin + // block access from tcdm + ic_gnt_o = 'b0; + amo_req_o = {{BanksPerSuperbank}{dma_rr_req}}; + amo_add_o = {{BanksPerSuperbank}{dma_payload_rr.add}}; + amo_amo_o = {{BanksPerSuperbank}{dma_payload_rr.amo}}; + amo_wen_o = {{BanksPerSuperbank}{dma_payload_rr.wen}}; + amo_wdata_o = dma_payload_rr.wdata; + amo_be_o = dma_payload_rr.be; + + // we need permission from all banks + dma_rr_gnt = 1'b1; + for(int i = 0; i < BanksPerSuperbank; i++) begin + dma_rr_gnt = dma_rr_gnt & amo_gnt_i; + end + end + end + + // backwards channel memory to DMA, this will be one cycle delayed. + always_comb begin : proc_tcdm_mux_backwards_channel + + // default: get response from DMA + ic_rdata_o = amo_rdata_i; + dma_a_rdata_o = 'b0; + dma_b_rdata_o = 'b0; + + // dma did last request -> get now the response + if(sel_dma_q) begin + ic_rdata_o = 'b0; + dma_a_rdata_o = amo_rdata_i; + dma_b_rdata_o = amo_rdata_i; + end + end + + // delay dma accesses by one for the response channel + always_ff @(posedge clk_i) begin : proc_delay_dma_sel + if(rst_i) begin + sel_dma_q <= 1'b0; + end else begin + sel_dma_q <= sel_dma; + end + end + +endmodule : tcdm_superbank_mux diff --git a/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/xbar.sv b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/xbar.sv new file mode 100644 index 0000000..428f1c6 --- /dev/null +++ b/hw/deps/cluster_interconnect/rtl/tcdm_interconnect/xbar.sv @@ -0,0 +1,132 @@ +// Copyright 2019 ETH Zurich and 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. +// +// Author: Michael Schaffner , ETH Zurich +// Date: 07.03.2019 +// Description: Full crossbar, implemented as logarithmic interconnect. + +module xbar #( + parameter int unsigned NumIn = 4, // number of requestors + parameter int unsigned NumOut = 4, // number of targets + parameter int unsigned ReqDataWidth = 32, // word width of data + parameter int unsigned RespDataWidth = 32, // word width of data + parameter int unsigned RespLat = 1, // response latency of slaves + parameter bit WriteRespOn = 1'b1, // defines whether the interconnect returns a write response + parameter bit BroadCastOn = 1'b0, // perform broadcast + parameter bit ExtPrio = 1'b0 // use external arbiter priority flags +) ( + input logic clk_i, + input logic rst_ni, + // external prio flag input + input logic [NumOut-1:0][$clog2(NumIn)-1:0] rr_i, // external prio input + // master side + input logic [NumIn-1:0] req_i, // request signal + input logic [NumIn-1:0][$clog2(NumOut)-1:0] add_i, // bank Address + input logic [NumIn-1:0] wen_i, // 1: store, 0: load + input logic [NumIn-1:0][ReqDataWidth-1:0] wdata_i, // write data + output logic [NumIn-1:0] gnt_o, // grant (combinationally dependent on req_i and add_i) + output logic [NumIn-1:0] vld_o, // response valid, also asserted if write responses are enabled + output logic [NumIn-1:0][RespDataWidth-1:0] rdata_o, // data response (for load commands) + // slave side + input logic [NumOut-1:0] gnt_i, // request out + output logic [NumOut-1:0] req_o, // grant input + /* verilator lint_off UNOPTFLAT */ + output logic [NumOut-1:0][ReqDataWidth-1:0] wdata_o, // write data + /* verilator lint_on UNOPTFLAT */ + input logic [NumOut-1:0][RespDataWidth-1:0] rdata_i // data response (for load commands) +); + +//////////////////////////////////////////////////////////////////////// +// inter-level wires +//////////////////////////////////////////////////////////////////////// + +logic [NumOut-1:0][NumIn-1:0][ReqDataWidth-1:0] sl_data; +logic [NumIn-1:0][NumOut-1:0][ReqDataWidth-1:0] ma_data; +logic [NumOut-1:0][NumIn-1:0] sl_gnt, sl_req; +logic [NumIn-1:0][NumOut-1:0] ma_gnt, ma_req; + +//////////////////////////////////////////////////////////////////////// +// instantiate bank address decoder/resp mux for each master +//////////////////////////////////////////////////////////////////////// +for (genvar j = 0; unsigned'(j) < NumIn; j++) begin : gen_inputs + addr_dec_resp_mux #( + .NumOut ( NumOut ), + .ReqDataWidth ( ReqDataWidth ), + .RespDataWidth ( RespDataWidth ), + .RespLat ( RespLat ), + .BroadCastOn ( BroadCastOn ), + .WriteRespOn ( WriteRespOn ) + ) i_addr_dec_resp_mux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( req_i[j] ), + .add_i ( add_i[j] ), + .wen_i ( wen_i[j] ), + .data_i ( wdata_i[j] ), + .gnt_o ( gnt_o[j] ), + .vld_o ( vld_o[j] ), + .rdata_o ( rdata_o[j] ), + .req_o ( ma_req[j] ), + .gnt_i ( ma_gnt[j] ), + .data_o ( ma_data[j] ), + .rdata_i ( rdata_i ) + ); + + // reshape connections between M/S + for (genvar k = 0; unsigned'(k) < NumOut; k++) begin : gen_reshape + assign sl_req[k][j] = ma_req[j][k]; + assign ma_gnt[j][k] = sl_gnt[k][j]; + assign sl_data[k][j] = ma_data[j][k]; + end +end + +//////////////////////////////////////////////////////////////////////// +// instantiate an RR arbiter for each endpoint +//////////////////////////////////////////////////////////////////////// +for (genvar k = 0; unsigned'(k) < NumOut; k++) begin : gen_outputs + if (NumIn == unsigned'(1)) begin + assign req_o[k] = sl_req[k][0]; + assign sl_gnt[k][0] = gnt_i[k]; + assign wdata_o[k] = sl_data[k][0]; + end else begin : gen_rr_arb_tree + rr_arb_tree #( + .NumIn ( NumIn ), + .DataWidth ( ReqDataWidth ), + .ExtPrio ( ExtPrio ) + ) i_rr_arb_tree ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( 1'b0 ), + .rr_i ( rr_i[k] ), + .req_i ( sl_req[k] ), + .gnt_o ( sl_gnt[k] ), + .data_i ( sl_data[k] ), + .gnt_i ( gnt_i[k] ), + .req_o ( req_o[k] ), + .data_o ( wdata_o[k] ), + .idx_o ( )// disabled + ); + end +end + +//////////////////////////////////////////////////////////////////////// +// assertion +//////////////////////////////////////////////////////////////////////// + +// pragma translate_off +initial begin + assert(NumIn > 0) else + $fatal(1,"NumIn needs to be larger than 0."); + assert(NumOut > 0) else + $fatal(1,"NumOut needs to be larger than 0."); +end +// pragma translate_on + +endmodule // xbar diff --git a/hw/deps/cluster_peripherals/cluster_control_unit/cluster_control_unit.sv b/hw/deps/cluster_peripherals/cluster_control_unit/cluster_control_unit.sv new file mode 100644 index 0000000..f046e68 --- /dev/null +++ b/hw/deps/cluster_peripherals/cluster_control_unit/cluster_control_unit.sv @@ -0,0 +1,393 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Company: Multitherman Laboratory @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Davide Rossi - davide.rossi@unibo.it // +// // +// Additional contributions by: // +// Andreas Traber - atraber@iis.ee.ethz.ch // +// Stefan Mach - smach@iis.ee.ethz.ch // +// // +// Create Date: 13/02/2013 // +// Design Name: ULPSoC // +// Module Name: ulpcluster_top // +// Project Name: ULPSoC // +// Language: SystemVerilog // +// // +// Description: ULPSoC cluster // +// // +// Revision: // +// Revision v0.1 - File Created // +// Revision v0.2 - Added DVS-DVSE support for memories // +// Revision v0.3 - Cleand Code, added non-blocking assign in the always_ff // +// Revision v0.4 - Updated the address range from [4:3] to[3:2] // +// Revision v0.5 - Restored Back Addr range [4:3], because of TB issues // +// Revision v0.6 - 29/05/15 : removed DVS-DVSE, added HS,LS,RM,WM // +// LS is default 1, other are '0 by default // +// Revision v? - Added fregfile_disable to the cluster control register // +// // +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// Memory Map +// +// 0x000: EoC. Write to bit 0 sets the eoc signal +// 0x008: Fetch Enable. Each core has its own bit, starts from LSB +// 0x010: Event. Bit 0 triggers an event. Usually not connected +// 0x018: Cluster Config. RM, WM, HS, LS, HWPE_SEL, FREGFILE_DIS +// 0x020: Cluster Clock Gate. Bit 0 enables it +// 0x028: Debug Status/Resume. Each core has its own bit, starts from LSB +// On read: Bit is set when core is halted +// On write: Resume core x when bit x is set +// 0x038: Debug Halt Mask. Each core has its own bit, starts from LSB +// When bit is set, core will be part of mask group and stopped +// when one of the members of the group stops +// 0x040-0x07F: Boot Addresses. Each core has its own 32-bit boot address +// 0x80: TCDM arbitration configuration CH0 (CORE) +// 0x88: TCDM arbitration configuration CH1 (DMA HWCE) +//////////////////////////////////////////////////////////////////////////////// + +module cluster_control_unit +#( + parameter NB_CORES = 4, + parameter PER_ID_WIDTH = 5, + parameter ROM_BOOT_ADDR = 32'h1A000000, + parameter BOOT_ADDR = 32'h1C000000 +) +( + input logic clk_i, + input logic rst_ni, + input logic en_sa_boot_i, + input logic fetch_en_i, + XBAR_PERIPH_BUS.Slave speriph_slave, + + output logic event_o, + output logic eoc_o, + + output logic cluster_cg_en_o, + + output logic hwpe_sel_o, + output logic hwpe_en_o, + + output logic fregfile_disable_o, + + input logic [NB_CORES-1:0] core_halted_i, // cores are in halted mode (which means debugging) + output logic [NB_CORES-1:0] core_halt_o, // halt the core + output logic [NB_CORES-1:0] core_resume_o, // resume the core + + output logic [NB_CORES-1:0] fetch_enable_o, + output logic [NB_CORES-1:0][31:0] boot_addr_o, + output logic [1:0] TCDM_arb_policy_o +); + + localparam OFFSET_1 = 4; // It was RM + localparam OFFSET_2 = 4; // It was WM + + logic rvalid_q, rvalid_n; + logic [PER_ID_WIDTH-1:0] id_q, id_n; + logic [31:0] rdata_q, rdata_n; + logic [NB_CORES-1:0] fetch_en_q, fetch_en_n; + + logic [NB_CORES-1:0] dbg_halt_mask_q, dbg_halt_mask_n; + logic core_halted_any_q, core_halted_any_n; + + logic eoc_n; + logic event_n; + + logic hwpe_sel_n; + logic hwpe_en_n; + + logic fregfile_disable_n; + + logic [NB_CORES-1:0][31:0] boot_addr_n; + + logic [1:0] fetch_en_sync; + logic start_fetch; + logic start_boot; + logic cluster_cg_en_n; + + logic [1:0] TCDM_arb_policy_n; + + logic core_halt_rising_edge; + + enum logic [1:0] { RESET, BOOT, WAIT_FETCH, LIMBO } boot_cs, boot_ns; + + assign fetch_enable_o = fetch_en_q; + + always_comb + begin + boot_ns = boot_cs; + start_boot = 1'b0; + start_fetch = 1'b0; + + case (boot_cs) + RESET: begin + boot_ns = BOOT; + end + + BOOT: begin + boot_ns = WAIT_FETCH; + if (en_sa_boot_i) + start_boot = 1'b1; + end + + WAIT_FETCH: begin + if (fetch_en_sync[1]) begin + start_fetch = 1'b1; + boot_ns = LIMBO; + end + end + + LIMBO: begin + boot_ns = LIMBO; + end + endcase + end + + ////////ASYNCH SIGNAL SYNCHRONIZER + EDGE DETECTOR\\\\\\\\ + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + begin + fetch_en_sync <= 2'b0; + boot_cs <= RESET; + end + else + begin + fetch_en_sync <= {fetch_en_sync[0],fetch_en_i}; + boot_cs <= boot_ns; + end + end + + // read logic + always_comb + begin + rdata_n = '0; + + if (speriph_slave.req && speriph_slave.wen) + begin + + case (speriph_slave.add[7:6]) + 2'b00: begin + case (speriph_slave.add[5:3]) + 3'b000: + begin + rdata_n[0] = eoc_o; + end + + 3'b001: + begin + rdata_n[NB_CORES-1:0] = fetch_en_q; + end + + 3'b011: + // +---------------------------------------------------------+ + // ADDR | unused | fregfile_dis | hwpe_en | hwpe_sel | unused | + // 0x18 | 31..13 | 12 | 11 | 10 | 9..0 | + // +---------------------------------------------------------+ + begin + rdata_n[OFFSET_2+OFFSET_1+1] = 0; + rdata_n[OFFSET_2+OFFSET_1 ] = 0; + rdata_n[OFFSET_2+OFFSET_1-1:OFFSET_1] = 0; + rdata_n[OFFSET_1-1:0] = 0; + rdata_n[OFFSET_2+OFFSET_1+2] = hwpe_sel_o; + rdata_n[OFFSET_2+OFFSET_1+3] = hwpe_en_o; + rdata_n[OFFSET_2+OFFSET_1+4] = fregfile_disable_o; + end + + 3'b100: rdata_n[0] = cluster_cg_en_o; + 3'b101: rdata_n[NB_CORES-1:0] = core_halted_i[NB_CORES-1:0]; + 3'b111: rdata_n[NB_CORES-1:0] = dbg_halt_mask_q[NB_CORES-1:0]; + + default:; + endcase + end + + 2'b01: + begin + rdata_n = boot_addr_n[speriph_slave.add[5:2]]; + end + + 2'b10, 2'b11: + begin + case(speriph_slave.add[3]) + 1'b0: + begin + rdata_n[0] = TCDM_arb_policy_o[0]; + end + + 1'b1: + begin + rdata_n[0] = TCDM_arb_policy_o[1]; + end + endcase // speriph_slave.add[3] + end + + endcase // speriph_slave.add[7:6] + end + end + + // write logic + always_comb + begin + hwpe_sel_n = hwpe_sel_o; + hwpe_en_n = hwpe_en_o; + + fregfile_disable_n = fregfile_disable_o; + + fetch_en_n = fetch_en_q; + eoc_n = eoc_o; + event_n = event_o; + + boot_addr_n = boot_addr_o; + cluster_cg_en_n = cluster_cg_en_o; + + TCDM_arb_policy_n = TCDM_arb_policy_o; + + core_resume_o = '0; + dbg_halt_mask_n = dbg_halt_mask_q; + + if (speriph_slave.req && (~speriph_slave.wen)) + begin + + case (speriph_slave.add[7:6]) + 2'b00: + begin + case (speriph_slave.add[5:3]) + 3'b000: begin + eoc_n = speriph_slave.wdata[0]; + end + + 3'b001: begin + fetch_en_n[NB_CORES-1:0] = speriph_slave.wdata[NB_CORES-1:0]; + end + + 3'b010: begin + event_n = speriph_slave.wdata[0]; + end + + 3'b011: begin + hwpe_sel_n = speriph_slave.wdata[OFFSET_2+OFFSET_1+2]; + hwpe_en_n = speriph_slave.wdata[OFFSET_2+OFFSET_1+3]; + fregfile_disable_n = speriph_slave.wdata[OFFSET_2+OFFSET_1+4]; + end + 3'b100: begin + cluster_cg_en_n = speriph_slave.wdata[0]; + end + 3'b101: begin // Debug Status/Resume + core_resume_o = speriph_slave.wdata[NB_CORES-1:0]; + end + 3'b111: begin // Debug Halt Mask + dbg_halt_mask_n = speriph_slave.wdata[NB_CORES-1:0]; + end + endcase + end + 2'b01: + begin + boot_addr_n[speriph_slave.add[5:2]] = speriph_slave.wdata; + end + + 2'b11,2'b10: + begin + case (speriph_slave.add[5:3]) + 3'b000: TCDM_arb_policy_n[0] = speriph_slave.wdata[0]; + 3'b001: TCDM_arb_policy_n[1] = speriph_slave.wdata[0]; + endcase + end + endcase // speriph_slave.add[7:6] + end + end + + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + begin + rdata_q <= '0; + id_q <= '0; + rvalid_q <= 1'b0; + + hwpe_sel_o <= 1'b1; + hwpe_en_o <= 1'b0; + + fregfile_disable_o<= 1'b0; + + fetch_en_q <= '0; + eoc_o <= 1'b0; + event_o <= 1'b0; + + dbg_halt_mask_q <= '0; + core_halted_any_q <= 1'b0; + + cluster_cg_en_o <= 1'b0; + TCDM_arb_policy_o <= 2'b00; + + boot_addr_o <= '{default: BOOT_ADDR}; + end + else + begin + rvalid_q <= rvalid_n; + + if (rvalid_n) + begin + rdata_q <= rdata_n; + id_q <= id_n; + end + + hwpe_sel_o <= hwpe_sel_n; + hwpe_en_o <= hwpe_en_n; + + fregfile_disable_o<= fregfile_disable_n; + + cluster_cg_en_o <= cluster_cg_en_n; + + eoc_o <= eoc_n; + event_o <= event_n; + + dbg_halt_mask_q <= dbg_halt_mask_n; + core_halted_any_q <= core_halted_any_n; + + boot_addr_o <= boot_addr_n; + + TCDM_arb_policy_o <= TCDM_arb_policy_n; + + if (start_fetch) + fetch_en_q <= '1; + else + fetch_en_q <= fetch_en_n; + + if (start_boot) begin + boot_addr_o[0] <= ROM_BOOT_ADDR; + fetch_en_q[0] <= 1'b1; + end + end + end + + // debug halt mode handling + assign core_halted_any_n = (|(core_halted_i & dbg_halt_mask_q)) & (~core_resume_o); + assign core_halt_rising_edge = (~core_halted_any_q) & core_halted_any_n; + + assign core_halt_o = {NB_CORES{core_halt_rising_edge}} & dbg_halt_mask_q; + + // to check with igor + assign speriph_slave.gnt = 1'b1; + assign speriph_slave.r_valid = rvalid_q; + assign speriph_slave.r_opc = 1'b0; + assign speriph_slave.r_id = id_q; + assign speriph_slave.r_rdata = rdata_q; + + assign rvalid_n = speriph_slave.req; + assign id_n = speriph_slave.id; + +endmodule diff --git a/hw/deps/cluster_peripherals/icache_ctrl_unit/interfaces/mp_pf_icache_ctrl_unit_bus.sv b/hw/deps/cluster_peripherals/icache_ctrl_unit/interfaces/mp_pf_icache_ctrl_unit_bus.sv new file mode 100644 index 0000000..975ad28 --- /dev/null +++ b/hw/deps/cluster_peripherals/icache_ctrl_unit/interfaces/mp_pf_icache_ctrl_unit_bus.sv @@ -0,0 +1,55 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +interface MP_PF_ICACHE_CTRL_UNIT_BUS #( + parameter int NB_CORES = 4 +); + + logic bypass_req; + logic [NB_CORES:0] bypass_ack; // NB_CORES + 1 + logic flush_req; + logic flush_ack; + + logic sel_flush_req; + logic [31:0] sel_flush_addr; + logic sel_flush_ack; + + logic [31:0] pf_addr; + logic [7:0] pf_size; + logic pf_req; + logic pf_ack; + logic pf_done; + + logic [31:0] global_hit_count; + logic [31:0] global_trans_count; + logic [31:0] global_miss_count; + + logic [NB_CORES-1:0][31:0] bank_hit_count; + logic [NB_CORES-1:0][31:0] bank_trans_count; + logic [NB_CORES-1:0][31:0] bank_miss_count; + + logic ctrl_clear_regs; + logic ctrl_enable_regs; + + modport Master ( + output bypass_req, flush_req, sel_flush_req, sel_flush_addr, pf_addr, pf_size, pf_req, + ctrl_clear_regs, ctrl_enable_regs, + input bypass_ack, flush_ack, sel_flush_ack, pf_ack, pf_done, global_hit_count, + global_trans_count, global_miss_count, bank_hit_count, bank_trans_count, bank_miss_count + ); + + modport Slave ( + input bypass_req, flush_req, sel_flush_req, sel_flush_addr, pf_addr, pf_size, pf_req, + ctrl_clear_regs, ctrl_enable_regs, + output bypass_ack, flush_ack, sel_flush_ack, pf_ack, pf_done, global_hit_count, + global_trans_count, global_miss_count, bank_hit_count, bank_trans_count, bank_miss_count + ); + +endinterface diff --git a/hw/deps/cluster_peripherals/icache_ctrl_unit/mp_pf_icache_ctrl_unit.sv b/hw/deps/cluster_peripherals/icache_ctrl_unit/mp_pf_icache_ctrl_unit.sv new file mode 100644 index 0000000..72adb04 --- /dev/null +++ b/hw/deps/cluster_peripherals/icache_ctrl_unit/mp_pf_icache_ctrl_unit.sv @@ -0,0 +1,432 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +// ============================================================================= // +// Company: Multitherman Laboratory @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// Create Date: 18/08/2014 // +// Design Name: icache_ctrl_unit // +// Module Name: icache_ctrl_unit // +// Project Name: PULP // +// Language: SystemVerilog // +// // +// Description: ICACHE control Unit, used to enable/disable icache banks // +// flush operations, and to debug the status og cache banks // +// // +// Revision: // +// Revision v0.1 - File Created // +// // +// ============================================================================= // + + `define ENABLE_ICACHE 6'b00_0000 + `define FLUSH_ICACHE 6'b00_0001 + `define SEL_FLUSH_ICACHE 6'b00_0011 + + `define PF_SIZE 6'b00_1000 + `define PF_ADDR 6'b00_1001 + + `define CLEAR_CNTS 6'b00_0100 + `define ENABLE_CNTS 6'b00_0101 + + `define READ_ICACHE_HIT_CORES 6'b01_0000 // R Only + `define READ_ICACHE_TRANS_CORES 6'b01_0001 // R Only + `define READ_ICACHE_MISS_CORES 6'b01_0001 // R Only + +//-----------------------------------// + + +module mp_pf_icache_ctrl_unit +#( + parameter int NB_CACHE_BANKS = 4, + parameter int NB_CORES = 4, + parameter int ID_WIDTH = 5, + parameter bit FEATURE_STAT = 1'b0 +) +( + input logic clk_i, + input logic rst_ni, + + XBAR_PERIPH_BUS.Slave speriph_slave, + MP_PF_ICACHE_CTRL_UNIT_BUS.Master IC_ctrl_unit_master_if, + + output logic pf_event_o +); + + int unsigned i,j,k,x,y; + + localparam NUM_REGS = 16; + + logic icache_bypass_req_o; + logic [NB_CORES:0] icache_bypass_ack_i; + + logic icache_flush_req_o; + logic icache_flush_ack_i; + + logic icache_sel_flush_req_o; + logic [31:0] icache_sel_flush_addr_o; + logic icache_sel_flush_ack_i; + + logic [31:0] pf_addr_o; + logic [7:0] pf_size_o; + logic pf_req_o; + logic pf_ack_i; + logic pf_done_i; + + + logic [31:0] ICACHE_CTRL_REGS[NUM_REGS]; + + // State of the main FSM + enum logic [2:0] { IDLE, ENABLE_ICACHE, DISABLE_ICACHE, FLUSH_ICACHE_CHECK, SEL_FLUSH_ICACHE, + CLEAR_STAT_REGS, ENABLE_STAT_REGS, TRIGGER_PF } CS, NS; + + // Exploded Interface --> PERIPHERAL INTERFACE + logic req; + logic [31:0] addr; + logic wen; + logic [31:0] wdata; + logic [3:0] be; + logic gnt; + logic [ID_WIDTH-1:0] id; + logic r_valid; + logic r_opc; + logic [ID_WIDTH-1:0] r_id; + logic [31:0] r_rdata; + + + // Internal FSM signals --> responses + logic r_valid_int; + logic [31:0] r_rdata_int; + + logic [NB_CORES-1:0] [31:0] hit_count; + logic [NB_CORES-1:0] [31:0] trans_count; + logic [NB_CORES-1:0] [31:0] miss_count; + logic [NB_CORES-1:0] clear_regs; + logic [NB_CORES-1:0] enable_regs; + + logic [31:0] global_hit_count; + logic [31:0] global_trans_count; + logic [31:0] global_miss_count; + + logic [7:0][31:0] bank_hit_count; + logic [7:0][31:0] bank_trans_count; + logic [7:0][31:0] bank_miss_count; + + logic is_write; + logic deliver_response; + logic clear_flush_reg; + + + // Interface binding + assign speriph_slave.gnt = gnt; + assign req = speriph_slave.req; + assign addr = speriph_slave.add; + assign wen = speriph_slave.wen; + assign wdata = speriph_slave.wdata; + assign be = speriph_slave.be; + assign id = speriph_slave.id; + assign speriph_slave.r_valid = r_valid; + assign speriph_slave.r_opc = r_opc; + assign speriph_slave.r_id = r_id; + assign speriph_slave.r_rdata = r_rdata; + + + + + genvar index; + + assign IC_ctrl_unit_master_if.pf_addr = pf_addr_o; + assign IC_ctrl_unit_master_if.pf_size = pf_size_o; + assign IC_ctrl_unit_master_if.pf_req = pf_req_o; + assign pf_ack_i = IC_ctrl_unit_master_if.pf_ack; + assign pf_done_i = IC_ctrl_unit_master_if.pf_done; + + assign IC_ctrl_unit_master_if.bypass_req = icache_bypass_req_o; + assign icache_bypass_ack_i = IC_ctrl_unit_master_if.bypass_ack; + assign IC_ctrl_unit_master_if.flush_req = icache_flush_req_o; + assign icache_flush_ack_i = IC_ctrl_unit_master_if.flush_ack; + + assign IC_ctrl_unit_master_if.sel_flush_req = icache_sel_flush_req_o; + assign IC_ctrl_unit_master_if.sel_flush_addr = icache_sel_flush_addr_o; + assign icache_sel_flush_ack_i = IC_ctrl_unit_master_if.sel_flush_ack; + + + if (FEATURE_STAT) begin + assign IC_ctrl_unit_master_if.ctrl_clear_regs = clear_regs; + assign IC_ctrl_unit_master_if.ctrl_enable_regs = enable_regs; + + assign global_hit_count = IC_ctrl_unit_master_if.global_hit_count; + assign global_trans_count = IC_ctrl_unit_master_if.global_trans_count; + assign global_miss_count = IC_ctrl_unit_master_if.global_miss_count; + + assign bank_hit_count[NB_CORES-1:0] = IC_ctrl_unit_master_if.bank_hit_count; + assign bank_trans_count[NB_CORES-1:0] = IC_ctrl_unit_master_if.bank_trans_count; + assign bank_miss_count[NB_CORES-1:0] = IC_ctrl_unit_master_if.bank_miss_count; + end + + + always_comb + begin : REGISTER_BIND_OUT + icache_bypass_req_o = ~ICACHE_CTRL_REGS[`ENABLE_ICACHE]; + icache_flush_req_o = ICACHE_CTRL_REGS[`FLUSH_ICACHE]; + icache_sel_flush_addr_o = ICACHE_CTRL_REGS[`SEL_FLUSH_ICACHE]; + + pf_addr_o = ICACHE_CTRL_REGS[`PF_ADDR][31:0]; + pf_size_o = ICACHE_CTRL_REGS[`PF_SIZE][7:0]; + + if (FEATURE_STAT) begin + enable_regs = ICACHE_CTRL_REGS[`ENABLE_CNTS][NB_CACHE_BANKS-1:0]; + end + end + + + + always_ff @(posedge clk_i, negedge rst_ni) + begin : SEQ_PROC + if(rst_ni == 1'b0) + begin + CS <= IDLE; + r_id <= '0; + r_valid <= 1'b0; + r_rdata <= '0; + r_opc <= '0; + + for(i=0;i all bypassed; 00000 --> all enabled + begin + NS = IDLE; + deliver_response = 1'b1; + end + else + begin + NS = ENABLE_ICACHE; + end + end //~ENABLE_ICACHE + + + + DISABLE_ICACHE: + begin + gnt = 1'b0; + + if(&icache_bypass_ack_i == 1'b1) //11111 --> all bypassed; 00000 --> all enabled + begin + NS = IDLE; + deliver_response = 1'b1; + end + else + begin + NS = DISABLE_ICACHE; + end + end //~DIABLE_ICACHE + + + + + FLUSH_ICACHE_CHECK: + begin + gnt = 1'b0; + + if(icache_flush_ack_i) + begin + NS = IDLE; + deliver_response = 1'b1; + clear_flush_reg = 1'b1; + end + else + begin + NS = FLUSH_ICACHE_CHECK; + end + end + + + SEL_FLUSH_ICACHE: + begin + + if(icache_sel_flush_ack_i) + begin + gnt = 1'b1; + NS = IDLE; + + deliver_response = 1'b1; + end + else + begin + NS = SEL_FLUSH_ICACHE; + end + end + + TRIGGER_PF: + begin + pf_req_o = 1'b1; + + if(pf_ack_i) + begin + NS = IDLE; + deliver_response = 1'b1; + end + else + begin + NS = TRIGGER_PF; + end + end + + + default : + begin + NS = IDLE; + end + endcase + end + + assign pf_event_o = pf_done_i; + +endmodule diff --git a/hw/deps/common_cells/src/addr_decode.sv b/hw/deps/common_cells/src/addr_decode.sv new file mode 100644 index 0000000..0b25a89 --- /dev/null +++ b/hw/deps/common_cells/src/addr_decode.sv @@ -0,0 +1,159 @@ +// Copyright 2019 ETH Zurich and 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. + +// Author: Wolfgang Roenninger + +/// Address Decoder: Maps the input address combinatorially to an index. +/// The address map `addr_map_i` is a packed array of rule_t structs. +/// The ranges of any two rules may overlap. If so, the rule at the higher (more significant) +/// position in `addr_map_i` prevails. +/// +/// There can be an arbitrary number of address rules. There can be multiple +/// ranges defined for the same index. The start address has to be less than the end address. +/// +/// There is the possibility to add a default mapping: +/// `en_default_idx_i`: Driving this port to `1'b1` maps all input addresses +/// for which no rule in `addr_map_i` exists to the default index specified by +/// `default_idx_i`. In this case, `dec_error_o` is always `1'b0`. +/// +/// Assertions: The module checks every time there is a change in the address mapping +/// if the resulting map is valid. It fatals if `start_addr` is higher than `end_addr` +/// or if a mapping targets an index that is outside the number of allowed indices. +/// It issues warnings if the address regions of any two mappings overlap. +module addr_decode #( + /// Highest index which can happen in a rule. + parameter int unsigned NoIndices = 32'd0, + /// Total number of rules. + parameter int unsigned NoRules = 32'd0, + /// Address type inside the rules and to decode. + parameter type addr_t = logic, + /// Rule packed struct type. + /// The address decoder expects three fields in `rule_t`: + /// + /// typedef struct packed { + /// int unsigned idx; + /// addr_t start_addr; + /// addr_t end_addr; + /// } rule_t; + /// + /// - `idx`: index of the rule, has to be < `NoIndices` + /// - `start_addr`: start address of the range the rule describes, value is included in range + /// - `end_addr`: end address of the range the rule describes, value is NOT included in range + parameter type rule_t = logic, + /// Dependent parameter, do **not** overwite! + /// + /// Width of the `idx_o` output port. + parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices), + /// Dependent parameter, do **not** overwite! + /// + /// Type of the `idx_o` output port. + parameter type idx_t = logic [IdxWidth-1:0] +) ( + /// Address to decode. + input addr_t addr_i, + /// Address map: rule with the highest array position wins on collision + input rule_t [NoRules-1:0] addr_map_i, + /// Decoded index. + output idx_t idx_o, + /// Decode is valid. + output logic dec_valid_o, + /// Decode is not valid, no matching rule found. + output logic dec_error_o, + /// Enable default port mapping. + /// + /// When not used, tie to `0`. + input logic en_default_idx_i, + /// Default port index. + /// + /// When `en_default_idx_i` is `1`, this will be the index when no rule matches. + /// + /// When not used, tie to `0`. + input idx_t default_idx_i +); + + logic [NoRules-1:0] matched_rules; // purely for address map debugging + + always_comb begin + // default assignments + matched_rules = '0; + dec_valid_o = 1'b0; + dec_error_o = (en_default_idx_i) ? 1'b0 : 1'b1; + idx_o = (en_default_idx_i) ? default_idx_i : '0; + + // match the rules + for (int unsigned i = 0; i < NoRules; i++) begin + if ((addr_i >= addr_map_i[i].start_addr) && (addr_i < addr_map_i[i].end_addr)) begin + matched_rules[i] = 1'b1; + dec_valid_o = 1'b1; + dec_error_o = 1'b0; + idx_o = idx_t'(addr_map_i[i].idx); + end + end + end + + // Assumptions and assertions + `ifndef VERILATOR + // pragma translate_off + initial begin : proc_check_parameters + assume ($bits(addr_i) == $bits(addr_map_i[0].start_addr)) else + $warning($sformatf("Input address has %d bits and address map has %d bits.", + $bits(addr_i), $bits(addr_map_i[0].start_addr))); + assume (NoRules > 0) else + $fatal(1, $sformatf("At least one rule needed")); + assume (NoIndices > 0) else + $fatal(1, $sformatf("At least one index needed")); + end + + assert final ($onehot0(matched_rules)) else + $warning("More than one bit set in the one-hot signal, matched_rules"); + + // These following assumptions check the validity of the address map. + // The assumptions gets generated for each distinct pair of rules. + // Each assumption is present two times, as they rely on one rules being + // effectively ordered. Only one of the rules with the same function is + // active at a time for a given pair. + // check_start: Enforces a smaller start than end address. + // check_idx: Enforces a valid index in the rule. + // check_overlap: Warns if there are overlapping address regions. + always @(addr_map_i) #0 begin : proc_check_addr_map + if (!$isunknown(addr_map_i)) begin + for (int unsigned i = 0; i < NoRules; i++) begin + check_start : assume (addr_map_i[i].start_addr < addr_map_i[i].end_addr) else + $fatal(1, $sformatf("This rule has a higher start than end address!!!\n\ + Violating rule %d.\n\ + Rule> IDX: %h START: %h END: %h\n\ + #####################################################", + i ,addr_map_i[i].idx, addr_map_i[i].start_addr, addr_map_i[i].end_addr)); + // check the SLV ids + check_idx : assume (addr_map_i[i].idx < NoIndices) else + $fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\ + Violating rule %d.\n\ + Rule> IDX: %h START: %h END: %h\n\ + Rule> MAX_IDX: %h\n\ + #####################################################", + i, addr_map_i[i].idx, addr_map_i[i].start_addr, addr_map_i[i].end_addr, + (NoIndices-1))); + for (int unsigned j = i + 1; j < NoRules; j++) begin + // overlap check + check_overlap : assume (!((addr_map_i[j].start_addr < addr_map_i[i].end_addr) && + (addr_map_i[j].end_addr > addr_map_i[i].start_addr))) else + $warning($sformatf("Overlapping address region found!!!\n\ + Rule %d: IDX: %h START: %h END: %h\n\ + Rule %d: IDX: %h START: %h END: %h\n\ + #####################################################", + i, addr_map_i[i].idx, addr_map_i[i].start_addr, addr_map_i[i].end_addr, + j, addr_map_i[j].idx, addr_map_i[j].start_addr, addr_map_i[j].end_addr)); + end + end + end + end + // pragma translate_on + `endif +endmodule diff --git a/hw/deps/common_cells/src/cf_math_pkg.sv b/hw/deps/common_cells/src/cf_math_pkg.sv new file mode 100644 index 0000000..c957dcf --- /dev/null +++ b/hw/deps/common_cells/src/cf_math_pkg.sv @@ -0,0 +1,85 @@ +// Copyright 2016 ETH Zurich and 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. + +/// cf_math_pkg: Constant Function Implementations of Mathematical Functions for HDL Elaboration +/// +/// This package contains a collection of mathematical functions that are commonly used when defining +/// the value of constants in HDL code. These functions are implemented as Verilog constants +/// functions. Introduced in Verilog 2001 (IEEE Std 1364-2001), a constant function (§ 10.3.5) is a +/// function whose value can be evaluated at compile time or during elaboration. A constant function +/// must be called with arguments that are constants. +package cf_math_pkg; + + /// Ceiled Division of Two Natural Numbers + /// + /// Returns the quotient of two natural numbers, rounded towards plus infinity. + function automatic integer ceil_div (input longint dividend, input longint divisor); + automatic longint remainder; + + // pragma translate_off + `ifndef VERILATOR + if (dividend < 0) begin + $fatal(1, "Dividend %0d is not a natural number!", dividend); + end + + if (divisor < 0) begin + $fatal(1, "Divisor %0d is not a natural number!", divisor); + end + + if (divisor == 0) begin + $fatal(1, "Division by zero!"); + end + `endif + // pragma translate_on + + remainder = dividend; + for (ceil_div = 0; remainder > 0; ceil_div++) begin + remainder = remainder - divisor; + end + endfunction + + /// Index width required to be able to represent up to `num_idx` indices as a binary + /// encoded signal. + /// Ensures that the minimum width if an index signal is `1`, regardless of parametrization. + /// + /// Sample usage in type definition: + /// As parameter: + /// `parameter type idx_t = logic[cf_math_pkg::idx_width(NumIdx)-1:0]` + /// As typedef: + /// `typedef logic [cf_math_pkg::idx_width(NumIdx)-1:0] idx_t` + function automatic integer unsigned idx_width (input integer unsigned num_idx); + return (num_idx > 32'd1) ? unsigned'($clog2(num_idx)) : 32'd1; + endfunction + + /// Ceiled Binary Logarithm of a Natural Number + /// + /// Returns the binary logarithm (i.e., the logarithm to the base 2) of a natural number rounded + /// towards plus infinity. + /// + /// Use this as drop-in replacement for the `$clog2` system function where the latter is not + /// supported by your toolchain. + function integer clog2 (input longint unsigned val); + automatic longint unsigned tmp; + + // pragma translate_off + `ifndef VERILATOR + if (val == 0) begin + $fatal(1, "Logarithm of 0 cannot be represented!"); + end + `endif + // pragma translate_on + + tmp = val - 1; + for (clog2 = 0; tmp > 0; clog2++) begin + tmp = tmp >> 1; + end + endfunction + +endpackage diff --git a/hw/deps/common_cells/src/counter.sv b/hw/deps/common_cells/src/counter.sv new file mode 100644 index 0000000..43392e4 --- /dev/null +++ b/hw/deps/common_cells/src/counter.sv @@ -0,0 +1,43 @@ +// Copyright 2018 ETH Zurich and 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. + +// Author: Florian Zaruba +// Description: Generic up/down counter + +module counter #( + parameter int unsigned WIDTH = 4, + parameter bit STICKY_OVERFLOW = 1'b0 +)( + input logic clk_i, + input logic rst_ni, + input logic clear_i, // synchronous clear + input logic en_i, // enable the counter + input logic load_i, // load a new value + input logic down_i, // downcount, default is up + input logic [WIDTH-1:0] d_i, + output logic [WIDTH-1:0] q_o, + output logic overflow_o +); + delta_counter #( + .WIDTH (WIDTH), + .STICKY_OVERFLOW (STICKY_OVERFLOW) + ) i_counter ( + .clk_i, + .rst_ni, + .clear_i, + .en_i, + .load_i, + .down_i, + .delta_i({{WIDTH-1{1'b0}}, 1'b1}), + .d_i, + .q_o, + .overflow_o + ); +endmodule diff --git a/hw/deps/common_cells/src/delta_counter.sv b/hw/deps/common_cells/src/delta_counter.sv new file mode 100644 index 0000000..90b5cff --- /dev/null +++ b/hw/deps/common_cells/src/delta_counter.sv @@ -0,0 +1,74 @@ +// Copyright 2018 ETH Zurich and 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. + +// Up/down counter with variable delta + +module delta_counter #( + parameter int unsigned WIDTH = 4, + parameter bit STICKY_OVERFLOW = 1'b0 +)( + input logic clk_i, + input logic rst_ni, + input logic clear_i, // synchronous clear + input logic en_i, // enable the counter + input logic load_i, // load a new value + input logic down_i, // downcount, default is up + input logic [WIDTH-1:0] delta_i, + input logic [WIDTH-1:0] d_i, + output logic [WIDTH-1:0] q_o, + output logic overflow_o +); + logic [WIDTH:0] counter_q, counter_d; + if (STICKY_OVERFLOW) begin : gen_sticky_overflow + logic overflow_d, overflow_q; + always_ff @(posedge clk_i or negedge rst_ni) overflow_q <= ~rst_ni ? 1'b0 : overflow_d; + always_comb begin + overflow_d = overflow_q; + if (clear_i || load_i) begin + overflow_d = 1'b0; + end else if (!overflow_q && en_i) begin + if (down_i) begin + overflow_d = delta_i > counter_q[WIDTH-1:0]; + end else begin + overflow_d = counter_q[WIDTH-1:0] > ({WIDTH{1'b1}} - delta_i); + end + end + end + assign overflow_o = overflow_q; + end else begin : gen_transient_overflow + // counter overflowed if the MSB is set + assign overflow_o = counter_q[WIDTH]; + end + assign q_o = counter_q[WIDTH-1:0]; + + always_comb begin + counter_d = counter_q; + + if (clear_i) begin + counter_d = '0; + end else if (load_i) begin + counter_d = {1'b0, d_i}; + end else if (en_i) begin + if (down_i) begin + counter_d = counter_q - delta_i; + end else begin + counter_d = counter_q + delta_i; + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + counter_q <= '0; + end else begin + counter_q <= counter_d; + end + end +endmodule diff --git a/hw/deps/common_cells/src/deprecated/fifo_v1.sv b/hw/deps/common_cells/src/deprecated/fifo_v1.sv new file mode 100644 index 0000000..31295e8 --- /dev/null +++ b/hw/deps/common_cells/src/deprecated/fifo_v1.sv @@ -0,0 +1,57 @@ +// Copyright 2018 ETH Zurich and 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. + +// Author: Florian Zaruba + +/* verilator lint_off DECLFILENAME */ +module fifo #( + parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode + parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic + parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32 + parameter int unsigned THRESHOLD = 1, // fill count until when to assert threshold_o + parameter type dtype = logic [DATA_WIDTH-1:0] +)( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic flush_i, // flush the queue + input logic testmode_i, // test_mode to bypass clock gating + // status flags + output logic full_o, // queue is full + output logic empty_o, // queue is empty + output logic threshold_o, // the FIFO is above the specified threshold + // as long as the queue is not full we can push new data + input dtype data_i, // data to push into the queue + input logic push_i, // data is valid and can be pushed to the queue + // as long as the queue is not empty we can pop new elements + output dtype data_o, // output data + input logic pop_i // pop head from queue +); + fifo_v2 #( + .FALL_THROUGH ( FALL_THROUGH ), + .DATA_WIDTH ( DATA_WIDTH ), + .DEPTH ( DEPTH ), + .ALM_FULL_TH ( THRESHOLD ), + .dtype ( dtype ) + ) impl ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .flush_i ( flush_i ), + .testmode_i ( testmode_i ), + .full_o ( full_o ), + .empty_o ( empty_o ), + .alm_full_o ( threshold_o ), + .alm_empty_o ( ), + .data_i ( data_i ), + .push_i ( push_i ), + .data_o ( data_o ), + .pop_i ( pop_i ) + ); +endmodule +/* verilator lint_on DECLFILENAME */ diff --git a/hw/deps/common_cells/src/deprecated/fifo_v2.sv b/hw/deps/common_cells/src/deprecated/fifo_v2.sv new file mode 100644 index 0000000..9c87ed9 --- /dev/null +++ b/hw/deps/common_cells/src/deprecated/fifo_v2.sv @@ -0,0 +1,79 @@ +// Copyright 2018 ETH Zurich and 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. + +// Author: Florian Zaruba + +module fifo_v2 #( + parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode + parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic + parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32 + parameter int unsigned ALM_EMPTY_TH = 1, // almost empty threshold (when to assert alm_empty_o) + parameter int unsigned ALM_FULL_TH = 1, // almost full threshold (when to assert alm_full_o) + parameter type dtype = logic [DATA_WIDTH-1:0], + // DO NOT OVERWRITE THIS PARAMETER + parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1 +)( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic flush_i, // flush the queue + input logic testmode_i, // test_mode to bypass clock gating + // status flags + output logic full_o, // queue is full + output logic empty_o, // queue is empty + output logic alm_full_o, // FIFO fillstate >= the specified threshold + output logic alm_empty_o, // FIFO fillstate <= the specified threshold + // as long as the queue is not full we can push new data + input dtype data_i, // data to push into the queue + input logic push_i, // data is valid and can be pushed to the queue + // as long as the queue is not empty we can pop new elements + output dtype data_o, // output data + input logic pop_i // pop head from queue +); + + logic [ADDR_DEPTH-1:0] usage; + + // generate threshold parameters + if (DEPTH == 0) begin + assign alm_full_o = 1'b0; // that signal does not make any sense in a FIFO of depth 0 + assign alm_empty_o = 1'b0; // that signal does not make any sense in a FIFO of depth 0 + end else begin + assign alm_full_o = (usage >= ALM_FULL_TH[ADDR_DEPTH-1:0]); + assign alm_empty_o = (usage <= ALM_EMPTY_TH[ADDR_DEPTH-1:0]); + end + + fifo_v3 #( + .FALL_THROUGH ( FALL_THROUGH ), + .DATA_WIDTH ( DATA_WIDTH ), + .DEPTH ( DEPTH ), + .dtype ( dtype ) + ) i_fifo_v3 ( + .clk_i, + .rst_ni, + .flush_i, + .testmode_i, + .full_o, + .empty_o, + .usage_o (usage), + .data_i, + .push_i, + .data_o, + .pop_i + ); + + // pragma translate_off + `ifndef VERILATOR + initial begin + assert (ALM_FULL_TH <= DEPTH) else $error("ALM_FULL_TH can't be larger than the DEPTH."); + assert (ALM_EMPTY_TH <= DEPTH) else $error("ALM_EMPTY_TH can't be larger than the DEPTH."); + end + `endif + // pragma translate_on + +endmodule // fifo_v2 diff --git a/hw/deps/common_cells/src/deprecated/generic_LFSR_8bit.sv b/hw/deps/common_cells/src/deprecated/generic_LFSR_8bit.sv new file mode 100644 index 0000000..fb0080a --- /dev/null +++ b/hw/deps/common_cells/src/deprecated/generic_LFSR_8bit.sv @@ -0,0 +1,64 @@ +// Copyright 2018 ETH Zurich and 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. + +// Igor Loi + +module generic_LFSR_8bit + #( + parameter OH_WIDTH = 4, + parameter BIN_WIDTH = $clog2(OH_WIDTH), + parameter SEED = 8'b00000000 + ) + ( + output logic [OH_WIDTH-1:0] data_OH_o, // One hot encoding + output logic [BIN_WIDTH-1:0] data_BIN_o, // Binary encoding + input logic enable_i, // + input logic clk, // + input logic rst_n // + ); + + logic [7:0] out; + logic linear_feedback; + logic [BIN_WIDTH-1:0] temp_ref_way; + + + //-------------Code Starts Here------- + assign linear_feedback = !(out[7] ^ out[3] ^ out[2] ^ out[1]); // TAPS for XOR feedback + + assign data_BIN_o = temp_ref_way; + + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) + begin + out <= SEED ; + end + else if (enable_i) + begin + out <= {out[6],out[5],out[4],out[3],out[2],out[1],out[0], linear_feedback}; + end + end + + generate + + if(OH_WIDTH == 2) + assign temp_ref_way = out[1]; + else + assign temp_ref_way = out[BIN_WIDTH:1]; + endgenerate + + // Bin to One Hot Encoder + always_comb + begin + data_OH_o = '0; + data_OH_o[temp_ref_way] = 1'b1; + end + +endmodule diff --git a/hw/deps/common_cells/src/deprecated/generic_fifo.sv b/hw/deps/common_cells/src/deprecated/generic_fifo.sv new file mode 100644 index 0000000..ece4aac --- /dev/null +++ b/hw/deps/common_cells/src/deprecated/generic_fifo.sv @@ -0,0 +1,274 @@ +// Copyright 2018 ETH Zurich and 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. + +// ============================================================================= // +// Company: Multitherman Laboratory @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 01/02/2014 // +// Design Name: MISC // +// Module Name: generic_fifo // +// Project Name: PULP // +// Language: SystemVerilog // +// // +// Description: A simple FIFO used in the D_address_decoder, and D_allocator // +// to store the destinations ports // +// // +// Revision: // +// Revision v0.1 - 01/02/2014 : File Created // +// Revision v0.2 - 02/09/2015 : Updated with a global CG cell // +// // +// ============================================================================= // + +module generic_fifo +#( + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned DATA_DEPTH = 8 +) +( + input logic clk, + input logic rst_n, + //PUSH SIDE + input logic [DATA_WIDTH-1:0] data_i, + input logic valid_i, + output logic grant_o, + //POP SIDE + output logic [DATA_WIDTH-1:0] data_o, + output logic valid_o, + input logic grant_i, + + input logic test_mode_i +); + + + // Local Parameter + localparam int unsigned ADDR_DEPTH = $clog2(DATA_DEPTH); + enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS; + // Internal Signals + + logic gate_clock; + logic clk_gated; + + logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS; + logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS; + logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0]; + int unsigned i; + + // Parameter Check + // synopsys translate_off + initial begin : parameter_check + integer param_err_flg; + param_err_flg = 0; + + if (DATA_WIDTH < 1) begin + param_err_flg = 1; + $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH (legal range: greater than 1)", DATA_WIDTH ); + end + + if (DATA_DEPTH < 1) begin + param_err_flg = 1; + $display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH (legal range: greater than 1)", DATA_DEPTH ); + end + end + // synopsys translate_on + +`ifndef PULP_FPGA_EMUL + cluster_clock_gating cg_cell + ( + .clk_i ( clk ), + .en_i (~gate_clock ), + .test_en_i ( test_mode_i ), + .clk_o ( clk_gated ) + ); +`else + assign clk_gated = clk; +`endif + + // UPDATE THE STATE + always_ff @(posedge clk, negedge rst_n) + begin + if(rst_n == 1'b0) + begin + CS <= EMPTY; + Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}}; + Push_Pointer_CS <= {ADDR_DEPTH {1'b0}}; + end + else + begin + CS <= NS; + Pop_Pointer_CS <= Pop_Pointer_NS; + Push_Pointer_CS <= Push_Pointer_NS; + end + end + + + // Compute Next State + always_comb + begin + gate_clock = 1'b0; + + case(CS) + + EMPTY: + begin + grant_o = 1'b1; + valid_o = 1'b0; + + case(valid_i) + 1'b0 : + begin + NS = EMPTY; + Push_Pointer_NS = Push_Pointer_CS; + Pop_Pointer_NS = Pop_Pointer_CS; + gate_clock = 1'b1; + end + + 1'b1: + begin + NS = MIDDLE; + Push_Pointer_NS = Push_Pointer_CS + 1'b1; + Pop_Pointer_NS = Pop_Pointer_CS; + end + + endcase + end//~EMPTY + + MIDDLE: + begin + grant_o = 1'b1; + valid_o = 1'b1; + + case({valid_i,grant_i}) + + 2'b01: + begin + gate_clock = 1'b1; + + if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0) )) + NS = EMPTY; + else + NS = MIDDLE; + + Push_Pointer_NS = Push_Pointer_CS; + + if(Pop_Pointer_CS == DATA_DEPTH-1) + Pop_Pointer_NS = 0; + else + Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; + end + + 2'b00 : + begin + gate_clock = 1'b1; + NS = MIDDLE; + Push_Pointer_NS = Push_Pointer_CS; + Pop_Pointer_NS = Pop_Pointer_CS; + end + + 2'b11: + begin + NS = MIDDLE; + + if(Push_Pointer_CS == DATA_DEPTH-1) + Push_Pointer_NS = 0; + else + Push_Pointer_NS = Push_Pointer_CS + 1'b1; + + if(Pop_Pointer_CS == DATA_DEPTH-1) + Pop_Pointer_NS = 0; + else + Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; + end + + 2'b10: + begin + if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || ( (Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0) )) + NS = FULL; + else + NS = MIDDLE; + + if(Push_Pointer_CS == DATA_DEPTH - 1) + Push_Pointer_NS = 0; + else + Push_Pointer_NS = Push_Pointer_CS + 1'b1; + + Pop_Pointer_NS = Pop_Pointer_CS; + end + + endcase + end + + FULL: + begin + grant_o = 1'b0; + valid_o = 1'b1; + gate_clock = 1'b1; + + case(grant_i) + 1'b1: + begin + NS = MIDDLE; + + Push_Pointer_NS = Push_Pointer_CS; + + if(Pop_Pointer_CS == DATA_DEPTH-1) + Pop_Pointer_NS = 0; + else + Pop_Pointer_NS = Pop_Pointer_CS + 1'b1; + end + + 1'b0: + begin + NS = FULL; + Push_Pointer_NS = Push_Pointer_CS; + Pop_Pointer_NS = Pop_Pointer_CS; + end + endcase + + end // end of FULL + + default : + begin + gate_clock = 1'b1; + grant_o = 1'b0; + valid_o = 1'b0; + NS = EMPTY; + Pop_Pointer_NS = 0; + Push_Pointer_NS = 0; + end + + endcase + end + + always_ff @(posedge clk_gated, negedge rst_n) + begin + if(rst_n == 1'b0) + begin + for (i=0; i< DATA_DEPTH; i++) + FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}}; + end + else + begin + if((grant_o == 1'b1) && (valid_i == 1'b1)) + FIFO_REGISTERS[Push_Pointer_CS] <= data_i; + end + end + + assign data_o = FIFO_REGISTERS[Pop_Pointer_CS]; + +endmodule // generic_fifo diff --git a/hw/deps/common_cells/src/edge_propagator_tx.sv b/hw/deps/common_cells/src/edge_propagator_tx.sv new file mode 100644 index 0000000..0274a43 --- /dev/null +++ b/hw/deps/common_cells/src/edge_propagator_tx.sv @@ -0,0 +1,40 @@ +// Copyright 2018 ETH Zurich and 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. + +// Antonio Pullini + +module edge_propagator_tx ( + input logic clk_i, + input logic rstn_i, + input logic valid_i, + input logic ack_i, + output logic valid_o +); + + logic [1:0] sync_a; + + logic r_input_reg; + logic s_input_reg_next; + + assign s_input_reg_next = valid_i | (r_input_reg & ~sync_a[0]); + + always @(negedge rstn_i or posedge clk_i) begin + if (~rstn_i) begin + r_input_reg <= 1'b0; + sync_a <= 2'b00; + end else begin + r_input_reg <= s_input_reg_next; + sync_a <= {ack_i,sync_a[1]}; + end + end + + assign valid_o = r_input_reg; + +endmodule diff --git a/hw/deps/common_cells/src/fall_through_register.sv b/hw/deps/common_cells/src/fall_through_register.sv new file mode 100644 index 0000000..fcbbe31 --- /dev/null +++ b/hw/deps/common_cells/src/fall_through_register.sv @@ -0,0 +1,58 @@ +// Copyright 2018 ETH Zurich and 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. + +// Fall-through register with a simple stream-like ready/valid handshake. +// This register does not cut combinatorial paths on any signals: in case the module at its output +// is ready to accept data within the same clock cycle, they are forwarded. Use this module to get a +// 'default ready' behavior towards the input. +module fall_through_register #( + parameter type T = logic // Vivado requires a default value for type parameters. +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous active-low reset + input logic clr_i, // Synchronous clear + input logic testmode_i, // Test mode to bypass clock gating + // Input port + input logic valid_i, + output logic ready_o, + input T data_i, + // Output port + output logic valid_o, + input logic ready_i, + output T data_o +); + + logic fifo_empty, + fifo_full; + + fifo_v2 #( + .FALL_THROUGH (1'b1), + .DATA_WIDTH ($size(T)), + .DEPTH (1), + .dtype (T) + ) i_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (clr_i), + .testmode_i (testmode_i), + .full_o (fifo_full), + .empty_o (fifo_empty), + .alm_full_o ( ), + .alm_empty_o ( ), + .data_i (data_i), + .push_i (valid_i & ~fifo_full), + .data_o (data_o), + .pop_i (ready_i & ~fifo_empty) + ); + + assign ready_o = ~fifo_full; + assign valid_o = ~fifo_empty; + +endmodule diff --git a/hw/deps/common_cells/src/fifo_v3.sv b/hw/deps/common_cells/src/fifo_v3.sv new file mode 100644 index 0000000..6da3268 --- /dev/null +++ b/hw/deps/common_cells/src/fifo_v3.sv @@ -0,0 +1,155 @@ +// Copyright 2018 ETH Zurich and 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. + +// Author: Florian Zaruba + +module fifo_v3 #( + parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode + parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic + parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32 + parameter type dtype = logic [DATA_WIDTH-1:0], + // DO NOT OVERWRITE THIS PARAMETER + parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1 +)( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic flush_i, // flush the queue + input logic testmode_i, // test_mode to bypass clock gating + // status flags + output logic full_o, // queue is full + output logic empty_o, // queue is empty + output logic [ADDR_DEPTH-1:0] usage_o, // fill pointer + // as long as the queue is not full we can push new data + input dtype data_i, // data to push into the queue + input logic push_i, // data is valid and can be pushed to the queue + // as long as the queue is not empty we can pop new elements + output dtype data_o, // output data + input logic pop_i // pop head from queue +); + // local parameter + // FIFO depth - handle the case of pass-through, synthesizer will do constant propagation + localparam int unsigned FIFO_DEPTH = (DEPTH > 0) ? DEPTH : 1; + // clock gating control + logic gate_clock; + // pointer to the read and write section of the queue + logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q; + // keep a counter to keep track of the current queue status + logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q; // this integer will be truncated by the synthesis tool + // actual memory + dtype [FIFO_DEPTH - 1:0] mem_n, mem_q; + + assign usage_o = status_cnt_q[ADDR_DEPTH-1:0]; + + if (DEPTH == 0) begin + assign empty_o = ~push_i; + assign full_o = ~pop_i; + end else begin + assign full_o = (status_cnt_q == FIFO_DEPTH[ADDR_DEPTH:0]); + assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i); + end + // status flags + + // read and write queue logic + always_comb begin : read_write_comb + // default assignment + read_pointer_n = read_pointer_q; + write_pointer_n = write_pointer_q; + status_cnt_n = status_cnt_q; + data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q]; + mem_n = mem_q; + gate_clock = 1'b1; + + // push a new element to the queue + if (push_i && ~full_o) begin + // push the data onto the queue + mem_n[write_pointer_q] = data_i; + // un-gate the clock, we want to write something + gate_clock = 1'b0; + // increment the write counter + if (write_pointer_q == FIFO_DEPTH[ADDR_DEPTH-1:0] - 1) + write_pointer_n = '0; + else + write_pointer_n = write_pointer_q + 1; + // increment the overall counter + status_cnt_n = status_cnt_q + 1; + end + + if (pop_i && ~empty_o) begin + // read from the queue is a default assignment + // but increment the read pointer... + if (read_pointer_n == FIFO_DEPTH[ADDR_DEPTH-1:0] - 1) + read_pointer_n = '0; + else + read_pointer_n = read_pointer_q + 1; + // ... and decrement the overall count + status_cnt_n = status_cnt_q - 1; + end + + // keep the count pointer stable if we push and pop at the same time + if (push_i && pop_i && ~full_o && ~empty_o) + status_cnt_n = status_cnt_q; + + // FIFO is in pass through mode -> do not change the pointers + if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin + data_o = data_i; + if (pop_i) begin + status_cnt_n = status_cnt_q; + read_pointer_n = read_pointer_q; + write_pointer_n = write_pointer_q; + end + end + end + + // sequential process + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + read_pointer_q <= '0; + write_pointer_q <= '0; + status_cnt_q <= '0; + end else begin + if (flush_i) begin + read_pointer_q <= '0; + write_pointer_q <= '0; + status_cnt_q <= '0; + end else begin + read_pointer_q <= read_pointer_n; + write_pointer_q <= write_pointer_n; + status_cnt_q <= status_cnt_n; + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + /* verilator lint_off WIDTHCONCAT */ + mem_q <= '0; + /* verilator lint_on WIDTHCONCAT */ + end else if (!gate_clock) begin + mem_q <= mem_n; + end + end + +// pragma translate_off +`ifndef VERILATOR + initial begin + assert (DEPTH > 0) else $error("DEPTH must be greater than 0."); + end + + full_write : assert property( + @(posedge clk_i) disable iff (~rst_ni) (full_o |-> ~push_i)) + else $fatal (1, "Trying to push new data although the FIFO is full."); + + empty_read : assert property( + @(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i)) + else $fatal (1, "Trying to pop data although the FIFO is empty."); +`endif +// pragma translate_on + +endmodule // fifo_v3 diff --git a/hw/deps/common_cells/src/id_queue.sv b/hw/deps/common_cells/src/id_queue.sv new file mode 100644 index 0000000..f67d166 --- /dev/null +++ b/hw/deps/common_cells/src/id_queue.sv @@ -0,0 +1,277 @@ +// Copyright 2018 ETH Zurich and 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. + +// ID Queue +// +// In an ID queue, every element has a numeric ID. Among all elements that have the same ID, the ID +// queue preserves FIFO order. +// +// This ID queue implementation allows to either push (through the `inp_*` signals) or pop (through +// the `oup_*` signals) one element per clock cycle. The `inp_` port has priority and grants a +// request iff the queue is not full. The `oup_` port dequeues an element iff `oup_pop_i` is +// asserted during an `oup_` handshake; otherwise, it performs a non-destructive read. `oup_data_o` +// is valid iff `oup_data_valid_o` is asserted during an `oup_` handshake. If `oup_data_valid_o` is +// not asserted, the queue did not contain an element with the provided ID. +// +// This ID queue additionally provides the `exists_` port, which searches for an element anywhere in +// the queue. The comparison performed during the search can be masked: for every bit that is +// asserted in `exists_mask_i`, the corresponding bit in the queue element and in `exists_data_i` +// must be equal for a match; the other bits are not compared. If masking is not required, tie +// `exists_mask_i_ to `'1` and the synthesizer should simplify the comparisons to unmasked ones. The +// `exists_` port operates independently of the `inp_` and `oup_` ports. If the `exists_` port is +// unused, tie `exists_req_i` to `1'b0` and the synthesizer should remove the internal comparators. +// +// This ID queue can store at most `CAPACITY` elements, independent of their ID. Let +// - C = `CAPACITY` +// - B = $bits(data_t) +// - I = 2**`ID_WIDTH` +// Then +// - the queue element storage requires O(C * (B + log2(C))) bit +// - the ID table requires O(H * log2(C)) bit, where H = min(C, I) +// +// Maintainers: +// - Andreas Kurth + +module id_queue #( + parameter int ID_WIDTH = 0, + parameter int CAPACITY = 0, + parameter type data_t = logic, + // Dependent parameters, DO NOT OVERRIDE! + localparam type id_t = logic[ID_WIDTH-1:0], + localparam type mask_t = logic[$bits(data_t)-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + input id_t inp_id_i, + input data_t inp_data_i, + input logic inp_req_i, + output logic inp_gnt_o, + + input data_t exists_data_i, + input mask_t exists_mask_i, + input logic exists_req_i, + output logic exists_o, + output logic exists_gnt_o, + + input id_t oup_id_i, + input logic oup_pop_i, + input logic oup_req_i, + output data_t oup_data_o, + output logic oup_data_valid_o, + output logic oup_gnt_o +); + + // Capacity of the head-tail table, which associates an ID with corresponding head and tail + // indices. + localparam int N_IDS = 2**ID_WIDTH; + localparam int HT_CAPACITY = (N_IDS <= CAPACITY) ? N_IDS : CAPACITY; + localparam int unsigned HT_IDX_WIDTH = HT_CAPACITY == 1 ? 1 : $clog2(HT_CAPACITY); + localparam int unsigned LD_IDX_WIDTH = CAPACITY == 1 ? 1 : $clog2(CAPACITY); + + // Type for indexing the head-tail table. + typedef logic [HT_IDX_WIDTH-1:0] ht_idx_t; + + // Type for indexing the lined data table. + typedef logic [LD_IDX_WIDTH-1:0] ld_idx_t; + + // Type of an entry in the head-tail table. + typedef struct packed { + id_t id; + ld_idx_t head, + tail; + logic free; + } head_tail_t; + + // Type of an entry in the linked data table. + typedef struct packed { + data_t data; + ld_idx_t next; + logic free; + } linked_data_t; + + head_tail_t [HT_CAPACITY-1:0] head_tail_d, head_tail_q; + + linked_data_t [CAPACITY-1:0] linked_data_d, linked_data_q; + + logic full, + match_id_valid, + no_id_match; + + logic [HT_CAPACITY-1:0] head_tail_free, + idx_matches_id; + + logic [CAPACITY-1:0] exists_match, + linked_data_free; + + id_t match_id; + + ht_idx_t head_tail_free_idx, + match_idx; + + ld_idx_t linked_data_free_idx; + + // Find the index in the head-tail table that matches a given ID. + for (genvar i = 0; i < HT_CAPACITY; i++) begin: gen_idx_match + assign idx_matches_id[i] = match_id_valid && (head_tail_q[i].id == match_id) && + !head_tail_q[i].free; + end + assign no_id_match = !(|idx_matches_id); + onehot_to_bin #( + .ONEHOT_WIDTH (HT_CAPACITY) + ) i_id_ohb ( + .onehot (idx_matches_id), + .bin (match_idx) + ); + + // Find the first free index in the head-tail table. + for (genvar i = 0; i < HT_CAPACITY; i++) begin: gen_head_tail_free + assign head_tail_free[i] = head_tail_q[i].free; + end + lzc #( + .WIDTH (HT_CAPACITY), + .MODE (0) // Start at index 0. + ) i_ht_free_lzc ( + .in_i (head_tail_free), + .cnt_o (head_tail_free_idx), + .empty_o () + ); + + // Find the first free index in the linked data table. + for (genvar i = 0; i < CAPACITY; i++) begin: gen_linked_data_free + assign linked_data_free[i] = linked_data_q[i].free; + end + lzc #( + .WIDTH (CAPACITY), + .MODE (0) // Start at index 0. + ) i_ld_free_lzc ( + .in_i (linked_data_free), + .cnt_o (linked_data_free_idx), + .empty_o () + ); + + // The queue is full if and only if there are no free items in the linked data structure. + assign full = !(|linked_data_free); + + assign inp_gnt_o = ~full; + always_comb begin + match_id = 'x; + match_id_valid = 1'b0; + head_tail_d = head_tail_q; + linked_data_d = linked_data_q; + oup_gnt_o = 1'b0; + oup_data_o = data_t'('x); + oup_data_valid_o = 1'b0; + if (inp_req_i && !full) begin + match_id = inp_id_i; + match_id_valid = 1'b1; + // If the ID does not yet exist in the queue, add a new ID entry. + if (no_id_match) begin + head_tail_d[head_tail_free_idx] = head_tail_t'{ + id: inp_id_i, + head: linked_data_free_idx, + tail: linked_data_free_idx, + free: 1'b0 + }; + // Otherwise append it to the existing ID subqueue. + end else begin + linked_data_d[head_tail_q[match_idx].tail].next = linked_data_free_idx; + head_tail_d[match_idx].tail = linked_data_free_idx; + end + linked_data_d[linked_data_free_idx] = linked_data_t'{ + data: inp_data_i, + next: 'x, + free: 1'b0 + }; + end else if (oup_req_i) begin + match_id = oup_id_i; + match_id_valid = 1'b1; + if (!no_id_match) begin + oup_data_o = data_t'(linked_data_q[head_tail_q[match_idx].head].data); + oup_data_valid_o = 1'b1; + if (oup_pop_i) begin + // Set free bit of linked data entry, all other bits are don't care. + linked_data_d[head_tail_q[match_idx].head] = 'x; + linked_data_d[head_tail_q[match_idx].head][0] = 1'b1; + if (head_tail_q[match_idx].head == head_tail_q[match_idx].tail) begin + head_tail_d[match_idx] = head_tail_t'{free: 1'b1, default: 'x}; + end else begin + head_tail_d[match_idx].head = linked_data_q[head_tail_q[match_idx].head].next; + end + end + end + // Always grant the output request. If there was no match, the default, invalid entry + // will be returned. + oup_gnt_o = 1'b1; + end + end + + // Exists Lookup + for (genvar i = 0; i < CAPACITY; i++) begin: gen_lookup + mask_t exists_match_bits; + for (genvar j = 0; j < $bits(data_t); j++) begin: gen_mask + always_comb begin + if (linked_data_q[i].free) begin + exists_match_bits[j] = 1'b0; + end else begin + if (!exists_mask_i[j]) begin + exists_match_bits[j] = 1'b1; + end else begin + exists_match_bits[j] = (linked_data_q[i].data[j] == exists_data_i[j]); + end + end + end + end + assign exists_match[i] = (&exists_match_bits); + end + always_comb begin + exists_gnt_o = 1'b0; + exists_o = 'x; + if (exists_req_i) begin + exists_gnt_o = 1'b1; + exists_o = (|exists_match); + end + end + + // Registers + for (genvar i = 0; i < HT_CAPACITY; i++) begin: gen_ht_ffs + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + head_tail_q[i] <= head_tail_t'{free: 1'b1, default: 'x}; + end else begin + head_tail_q[i] <= head_tail_d[i]; + end + end + end + for (genvar i = 0; i < CAPACITY; i++) begin: gen_data_ffs + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + // Set free bit of linked data entries, all other bits are don't care. + linked_data_q[i] <= 'x; + linked_data_q[i][0] <= 1'b1; + end else begin + linked_data_q[i] <= linked_data_d[i]; + end + end + end + + // Validate parameters. +// pragma translate_off +`ifndef VERILATOR + initial begin: validate_params + assert (ID_WIDTH >= 1) + else $fatal("The ID must at least be one bit wide!"); + assert (CAPACITY >= 1) + else $fatal("The queue must have capacity of at least one entry!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/common_cells/src/lzc.sv b/hw/deps/common_cells/src/lzc.sv new file mode 100644 index 0000000..90657f5 --- /dev/null +++ b/hw/deps/common_cells/src/lzc.sv @@ -0,0 +1,109 @@ +// Copyright (c) 2018 - 2019 ETH Zurich, University of Bologna +// All rights reserved. +// +// This code is under development and not yet released to the public. +// Until it is released, the code is under the copyright of ETH Zurich and +// the University of Bologna, and may contain confidential and/or unpublished +// work. Any reuse/redistribution is strictly forbidden without written +// permission from ETH Zurich. +// +// Bug fixes and contributions will eventually be released under the +// SolderPad open hardware license in the context of the PULP platform +// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the +// University of Bologna. + +/// A trailing zero counter / leading zero counter. +/// Set MODE to 0 for trailing zero counter => cnt_o is the number of trailing zeros (from the LSB) +/// Set MODE to 1 for leading zero counter => cnt_o is the number of leading zeros (from the MSB) +/// If the input does not contain a zero, `empty_o` is asserted. Additionally `cnt_o` contains +/// the maximum number of zeros - 1. For example: +/// in_i = 000_0000, empty_o = 1, cnt_o = 6 (mode = 0) +/// in_i = 000_0001, empty_o = 0, cnt_o = 0 (mode = 0) +/// in_i = 000_1000, empty_o = 0, cnt_o = 3 (mode = 0) +/// Furthermore, this unit contains a more efficient implementation for Verilator (simulation only). +/// This speeds up simulation significantly. +module lzc #( + /// The width of the input vector. + parameter int unsigned WIDTH = 2, + /// Mode selection: 0 -> trailing zero, 1 -> leading zero + parameter bit MODE = 1'b0, + /// Dependent parameter. Do **not** change! + /// + /// Width of the output signal with the zero count. + parameter int unsigned CNT_WIDTH = cf_math_pkg::idx_width(WIDTH) +) ( + /// Input vector to be counted. + input logic [WIDTH-1:0] in_i, + /// Count of the leading / trailing zeros. + output logic [CNT_WIDTH-1:0] cnt_o, + /// Counter is empty: Asserted if all bits in in_i are zero. + output logic empty_o +); + + if (WIDTH == 1) begin: gen_degenerate_lzc + + assign cnt_o[0] = !in_i[0]; + assign empty_o = !in_i[0]; + + end else begin: gen_lzc + + localparam int unsigned NUM_LEVELS = $clog2(WIDTH); + + // pragma translate_off + initial begin + assert(WIDTH > 0) else $fatal(1, "input must be at least one bit wide"); + end + // pragma translate_on + + logic [WIDTH-1:0][NUM_LEVELS-1:0] index_lut; + logic [2**NUM_LEVELS-1:0] sel_nodes /* verilator split_var */; + logic [2**NUM_LEVELS-1:0][NUM_LEVELS-1:0] index_nodes /* verilator split_var */; + + logic [WIDTH-1:0] in_tmp; + + // reverse vector if required + always_comb begin : flip_vector + for (int unsigned i = 0; i < WIDTH; i++) begin + in_tmp[i] = (MODE) ? in_i[WIDTH-1-i] : in_i[i]; + end + end + + for (genvar j = 0; unsigned'(j) < WIDTH; j++) begin : g_index_lut + assign index_lut[j] = (NUM_LEVELS)'(unsigned'(j)); + end + + for (genvar level = 0; unsigned'(level) < NUM_LEVELS; level++) begin : g_levels + if (unsigned'(level) == NUM_LEVELS-1) begin : g_last_level + for (genvar k = 0; k < 2**level; k++) begin : g_level + // if two successive indices are still in the vector... + if (unsigned'(k) * 2 < WIDTH-1) begin + assign sel_nodes[2**level-1+k] = in_tmp[k*2] | in_tmp[k*2+1]; + assign index_nodes[2**level-1+k] = (in_tmp[k*2] == 1'b1) ? index_lut[k*2] : + index_lut[k*2+1]; + end + // if only the first index is still in the vector... + if (unsigned'(k) * 2 == WIDTH-1) begin + assign sel_nodes[2**level-1+k] = in_tmp[k*2]; + assign index_nodes[2**level-1+k] = index_lut[k*2]; + end + // if index is out of range + if (unsigned'(k) * 2 > WIDTH-1) begin + assign sel_nodes[2**level-1+k] = 1'b0; + assign index_nodes[2**level-1+k] = '0; + end + end + end else begin + for (genvar l = 0; l < 2**level; l++) begin : g_level + assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1]; + assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ? index_nodes[2**(level+1)-1+l*2] : + index_nodes[2**(level+1)-1+l*2+1]; + end + end + end + + assign cnt_o = NUM_LEVELS > unsigned'(0) ? index_nodes[0] : {($clog2(WIDTH)){1'b0}}; + assign empty_o = NUM_LEVELS > unsigned'(0) ? ~sel_nodes[0] : ~(|in_i); + + end : gen_lzc + +endmodule : lzc diff --git a/hw/deps/common_cells/src/onehot_to_bin.sv b/hw/deps/common_cells/src/onehot_to_bin.sv new file mode 100644 index 0000000..272add4 --- /dev/null +++ b/hw/deps/common_cells/src/onehot_to_bin.sv @@ -0,0 +1,38 @@ +// Copyright 2018 ETH Zurich and 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. + +// Franceco Conti + +module onehot_to_bin #( + parameter int unsigned ONEHOT_WIDTH = 16, + // Do Not Change + parameter int unsigned BIN_WIDTH = ONEHOT_WIDTH == 1 ? 1 : $clog2(ONEHOT_WIDTH) +) ( + input logic [ONEHOT_WIDTH-1:0] onehot, + output logic [BIN_WIDTH-1:0] bin +); + + for (genvar j = 0; j < BIN_WIDTH; j++) begin : jl + logic [ONEHOT_WIDTH-1:0] tmp_mask; + for (genvar i = 0; i < ONEHOT_WIDTH; i++) begin : il + logic [BIN_WIDTH-1:0] tmp_i; + assign tmp_i = i; + assign tmp_mask[i] = tmp_i[j]; + end + assign bin[j] = |(tmp_mask & onehot); + end + +// pragma translate_off +`ifndef VERILATOR + //assert final ($onehot0(onehot)) else + // $fatal(1, "[onehot_to_bin] More than two bit set in the one-hot signal"); +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/common_cells/src/rr_arb_tree.sv b/hw/deps/common_cells/src/rr_arb_tree.sv new file mode 100644 index 0000000..7bdc7ae --- /dev/null +++ b/hw/deps/common_cells/src/rr_arb_tree.sv @@ -0,0 +1,341 @@ +// Copyright 2019 ETH Zurich and 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. +// +// Author: Michael Schaffner , ETH Zurich +// Wolfgang Roenninger , ETH Zurich +// Date: 02.04.2019 +// Description: logarithmic arbitration tree with round robin arbitration scheme. + +/// The rr_arb_tree employs non-starving round robin-arbitration - i.e., the priorities +/// rotate each cycle. +/// +/// ## Fair vs. unfair Arbitration +/// +/// This refers to fair throughput distribution when not all inputs have active requests. +/// This module has an internal state `rr_q` which defines the highest priority input. (When +/// `ExtPrio` is `1'b1` this state is provided from the outside.) The arbitration tree will +/// choose the input with the same index as currently defined by the state if it has an active +/// request. Otherwise a *random* other active input is selected. The parameter `FairArb` is used +/// to distinguish between two methods of calculating the next state. +/// * `1'b0`: The next state is calculated by advancing the current state by one. This leads to the +/// state being calculated without the context of the active request. Leading to an +/// unfair throughput distribution if not all inputs have active requests. +/// * `1'b1`: The next state jumps to the next unserved request with higher index. +/// This is achieved by using two trailing-zero-counters (`lzc`). The upper has the masked +/// `req_i` signal with all indices which will have a higher priority in the next state. +/// The trailing zero count defines the input index with the next highest priority after +/// the current one is served. When the upper is empty the lower `lzc` provides the +/// wrapped index if there are outstanding requests with lower or same priority. +/// The implication of throughput fairness on the module timing are: +/// * The trailing zero counter (`lzc`) has a loglog relation of input to output timing. This means +/// that in this module the input to register path scales with Log(Log(`NumIn`)). +/// * The `rr_arb_tree` data multiplexing scales with Log(`NumIn`). This means that the input to output +/// timing path of this module also scales scales with Log(`NumIn`). +/// This implies that in this module the input to output path is always longer than the input to +/// register path. As the output data usually also terminates in a register the parameter `FairArb` +/// only has implications on the area. When it is `1'b0` a static plus one adder is instantiated. +/// If it is `1'b1` two `lzc`, a masking logic stage and a two input multiplexer are instantiated. +/// However these are small in respect of the data multiplexers needed, as the width of the `req_i` +/// signal is usually less as than `DataWidth`. +module rr_arb_tree #( + /// Number of inputs to be arbitrated. + parameter int unsigned NumIn = 64, + /// Data width of the payload in bits. Not needed if `DataType` is overwritten. + parameter int unsigned DataWidth = 32, + /// Data type of the payload, can be overwritten with custom type. Only use of `DataWidth`. + parameter type DataType = logic [DataWidth-1:0], + /// The `ExtPrio` option allows to override the internal round robin counter via the + /// `rr_i` signal. This can be useful in case multiple arbiters need to have + /// rotating priorities that are operating in lock-step. If static priority arbitration + /// is needed, just connect `rr_i` to '0. + /// + /// Set to 1'b1 to enable. + parameter bit ExtPrio = 1'b0, + /// If `AxiVldRdy` is set, the req/gnt signals are compliant with the AXI style vld/rdy + /// handshake. Namely, upstream vld (req) must not depend on rdy (gnt), as it can be deasserted + /// again even though vld is asserted. Enabling `AxiVldRdy` leads to a reduction of arbiter + /// delay and area. + /// + /// Set to `1'b1` to treat req/gnt as vld/rdy. + parameter bit AxiVldRdy = 1'b0, + /// The `LockIn` option prevents the arbiter from changing the arbitration + /// decision when the arbiter is disabled. I.e., the index of the first request + /// that wins the arbitration will be locked in case the destination is not + /// able to grant the request in the same cycle. + /// + /// Set to `1'b1` to enable. + parameter bit LockIn = 1'b0, + /// When set, ensures that throughput gets distributed evenly between all inputs. + /// + /// Set to `1'b0` to disable. + parameter bit FairArb = 1'b1, + /// Dependent parameter, do **not** overwrite. + /// Width of the arbitration priority signal and the arbitrated index. + parameter int unsigned IdxWidth = (NumIn > 32'd1) ? unsigned'($clog2(NumIn)) : 32'd1, + /// Dependent parameter, do **not** overwrite. + /// Type for defining the arbitration priority and arbitrated index signal. + parameter type idx_t = logic [IdxWidth-1:0] +) ( + /// Clock, positive edge triggered. + input logic clk_i, + /// Asynchronous reset, active low. + input logic rst_ni, + /// Clears the arbiter state. Only used if `ExtPrio` is `1'b0` or `LockIn` is `1'b1`. + input logic flush_i, + /// External round-robin priority. Only used if `ExtPrio` is `1'b1.` + input idx_t rr_i, + /// Input requests arbitration. + input logic [NumIn-1:0] req_i, + /* verilator lint_off UNOPTFLAT */ + /// Input request is granted. + output logic [NumIn-1:0] gnt_o, + /* verilator lint_on UNOPTFLAT */ + /// Input data for arbitration. + input DataType [NumIn-1:0] data_i, + /// Output request is valid. + output logic req_o, + /// Output request is granted. + input logic gnt_i, + /// Output data. + output DataType data_o, + /// Index from which input the data came from. + output idx_t idx_o +); + + // pragma translate_off + `ifndef VERILATOR + // Default SVA reset + default disable iff (!rst_ni || flush_i); + `endif + // pragma translate_on + + // just pass through in this corner case + if (NumIn == unsigned'(1)) begin + assign req_o = req_i[0]; + assign gnt_o[0] = gnt_i; + assign data_o = data_i[0]; + assign idx_o = '0; + // non-degenerate cases + end else begin + localparam int unsigned NumLevels = unsigned'($clog2(NumIn)); + + /* verilator lint_off UNOPTFLAT */ + idx_t [2**NumLevels-2:0] index_nodes; // used to propagate the indices + DataType [2**NumLevels-2:0] data_nodes; // used to propagate the data + logic [2**NumLevels-2:0] gnt_nodes; // used to propagate the grant to masters + logic [2**NumLevels-2:0] req_nodes; // used to propagate the requests to slave + /* lint_off */ + idx_t rr_q; + logic [NumIn-1:0] req_d; + + // the final arbitration decision can be taken from the root of the tree + assign req_o = req_nodes[0]; + assign data_o = data_nodes[0]; + assign idx_o = index_nodes[0]; + + if (ExtPrio) begin : gen_ext_rr + assign rr_q = rr_i; + assign req_d = req_i; + end else begin : gen_int_rr + idx_t rr_d; + + // lock arbiter decision in case we got at least one req and no acknowledge + if (LockIn) begin : gen_lock + logic lock_d, lock_q; + logic [NumIn-1:0] req_q; + + assign lock_d = req_o & ~gnt_i; + assign req_d = (lock_q) ? req_q : req_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_lock_reg + if (!rst_ni) begin + lock_q <= '0; + end else begin + if (flush_i) begin + lock_q <= '0; + end else begin + lock_q <= lock_d; + end + end + end + + // pragma translate_off + `ifndef VERILATOR + lock: assert property( + @(posedge clk_i) LockIn |-> req_o && !gnt_i |=> idx_o == $past(idx_o)) else + $fatal (1, "Lock implies same arbiter decision in next cycle if output is not \ + ready."); + + logic [NumIn-1:0] req_tmp; + assign req_tmp = req_q & req_i; + lock_req: assume property( + @(posedge clk_i) LockIn |-> lock_d |=> req_tmp == req_q) else + $fatal (1, "It is disallowed to deassert unserved request signals when LockIn is \ + enabled."); + `endif + // pragma translate_on + + always_ff @(posedge clk_i or negedge rst_ni) begin : p_req_regs + if (!rst_ni) begin + req_q <= '0; + end else begin + if (flush_i) begin + req_q <= '0; + end else begin + req_q <= req_d; + end + end + end + end else begin : gen_no_lock + assign req_d = req_i; + end + + if (FairArb) begin : gen_fair_arb + logic [NumIn-1:0] upper_mask, lower_mask; + idx_t upper_idx, lower_idx, next_idx; + logic upper_empty, lower_empty; + + for (genvar i = 0; i < NumIn; i++) begin : gen_mask + assign upper_mask[i] = (i > rr_q) ? req_d[i] : 1'b0; + assign lower_mask[i] = (i <= rr_q) ? req_d[i] : 1'b0; + end + + lzc #( + .WIDTH ( NumIn ), + .MODE ( 1'b0 ) + ) i_lzc_upper ( + .in_i ( upper_mask ), + .cnt_o ( upper_idx ), + .empty_o ( upper_empty ) + ); + + lzc #( + .WIDTH ( NumIn ), + .MODE ( 1'b0 ) + ) i_lzc_lower ( + .in_i ( lower_mask ), + .cnt_o ( lower_idx ), + .empty_o ( /*unused*/ ) + ); + + assign next_idx = upper_empty ? lower_idx : upper_idx; + assign rr_d = (gnt_i && req_o) ? next_idx : rr_q; + + end else begin : gen_unfair_arb + assign rr_d = (gnt_i && req_o) ? ((rr_q == idx_t'(NumIn-1)) ? '0 : rr_q + 1'b1) : rr_q; + end + + // this holds the highest priority + always_ff @(posedge clk_i or negedge rst_ni) begin : p_rr_regs + if (!rst_ni) begin + rr_q <= '0; + end else begin + if (flush_i) begin + rr_q <= '0; + end else begin + rr_q <= rr_d; + end + end + end + end + + assign gnt_nodes[0] = gnt_i; + + // arbiter tree + for (genvar level = 0; unsigned'(level) < NumLevels; level++) begin : gen_levels + for (genvar l = 0; l < 2**level; l++) begin : gen_level + // local select signal + logic sel; + // index calcs + localparam int unsigned idx0 = 2**level-1+l;// current node + localparam int unsigned idx1 = 2**(level+1)-1+l*2; + ////////////////////////////////////////////////////////////// + // uppermost level where data is fed in from the inputs + if (unsigned'(level) == NumLevels-1) begin : gen_first_level + // if two successive indices are still in the vector... + if (unsigned'(l) * 2 < NumIn-1) begin + assign req_nodes[idx0] = req_d[l*2] | req_d[l*2+1]; + + // arbitration: round robin + assign sel = ~req_d[l*2] | req_d[l*2+1] & rr_q[NumLevels-1-level]; + + assign index_nodes[idx0] = idx_t'(sel); + assign data_nodes[idx0] = (sel) ? data_i[l*2+1] : data_i[l*2]; + assign gnt_o[l*2] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2]) & ~sel; + assign gnt_o[l*2+1] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2+1]) & sel; + end + // if only the first index is still in the vector... + if (unsigned'(l) * 2 == NumIn-1) begin + assign req_nodes[idx0] = req_d[l*2]; + assign index_nodes[idx0] = '0;// always zero in this case + assign data_nodes[idx0] = data_i[l*2]; + assign gnt_o[l*2] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2]); + end + // if index is out of range, fill up with zeros (will get pruned) + if (unsigned'(l) * 2 > NumIn-1) begin + assign req_nodes[idx0] = 1'b0; + assign index_nodes[idx0] = DataType'('0); + assign data_nodes[idx0] = DataType'('0); + end + ////////////////////////////////////////////////////////////// + // general case for other levels within the tree + end else begin : gen_other_levels + assign req_nodes[idx0] = req_nodes[idx1] | req_nodes[idx1+1]; + + // arbitration: round robin + assign sel = ~req_nodes[idx1] | req_nodes[idx1+1] & rr_q[NumLevels-1-level]; + + assign index_nodes[idx0] = (sel) ? idx_t'({1'b1, index_nodes[idx1+1][NumLevels-unsigned'(level)-2:0]}) : + idx_t'({1'b0, index_nodes[idx1][NumLevels-unsigned'(level)-2:0]}); + assign data_nodes[idx0] = (sel) ? data_nodes[idx1+1] : data_nodes[idx1]; + assign gnt_nodes[idx1] = gnt_nodes[idx0] & ~sel; + assign gnt_nodes[idx1+1] = gnt_nodes[idx0] & sel; + end + ////////////////////////////////////////////////////////////// + end + end + + // pragma translate_off + `ifndef VERILATOR + initial begin : p_assert + assert(NumIn) + else $fatal(1, "Input must be at least one element wide."); + assert(!(LockIn && ExtPrio)) + else $fatal(1,"Cannot use LockIn feature together with external ExtPrio."); + end + + hot_one : assert property( + @(posedge clk_i) $onehot0(gnt_o)) + else $fatal (1, "Grant signal must be hot1 or zero."); + + gnt0 : assert property( + @(posedge clk_i) |gnt_o |-> gnt_i) + else $fatal (1, "Grant out implies grant in."); + + gnt1 : assert property( + @(posedge clk_i) req_o |-> gnt_i |-> |gnt_o) + else $fatal (1, "Req out and grant in implies grant out."); + + gnt_idx : assert property( + @(posedge clk_i) req_o |-> gnt_i |-> gnt_o[idx_o]) + else $fatal (1, "Idx_o / gnt_o do not match."); + + req0 : assert property( + @(posedge clk_i) |req_i |-> req_o) + else $fatal (1, "Req in implies req out."); + + req1 : assert property( + @(posedge clk_i) req_o |-> |req_i) + else $fatal (1, "Req out implies req in."); + `endif + // pragma translate_on + end + +endmodule : rr_arb_tree diff --git a/hw/deps/common_cells/src/rstgen.sv b/hw/deps/common_cells/src/rstgen.sv new file mode 100644 index 0000000..a7dccc6 --- /dev/null +++ b/hw/deps/common_cells/src/rstgen.sv @@ -0,0 +1,30 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module rstgen ( + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + output logic rst_no, + output logic init_no +); + + rstgen_bypass i_rstgen_bypass ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .rst_test_mode_ni ( rst_ni ), + .test_mode_i ( test_mode_i ), + .rst_no ( rst_no ), + .init_no ( init_no ) + ); + +endmodule diff --git a/hw/deps/common_cells/src/rstgen_bypass.sv b/hw/deps/common_cells/src/rstgen_bypass.sv new file mode 100644 index 0000000..64102d8 --- /dev/null +++ b/hw/deps/common_cells/src/rstgen_bypass.sv @@ -0,0 +1,57 @@ +// Copyright 2018 ETH Zurich and 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. + +// Florian Zaruba +// Description: This module is a reset synchronizer with a dedicated reset bypass pin for testmode reset. +// Pro Tip: The wise Dr. Schaffner recommends at least 4 registers! + +module rstgen_bypass #( + parameter NumRegs = 4 +) ( + input logic clk_i, + input logic rst_ni, + input logic rst_test_mode_ni, + input logic test_mode_i, + output logic rst_no, + output logic init_no +); + + // internal reset + logic rst_n; + + logic [NumRegs-1:0] synch_regs_q; + // bypass mode + always_comb begin + if (test_mode_i == 1'b0) begin + rst_n = rst_ni; + rst_no = synch_regs_q[NumRegs-1]; + init_no = synch_regs_q[NumRegs-1]; + end else begin + rst_n = rst_test_mode_ni; + rst_no = rst_test_mode_ni; + init_no = 1'b1; + end + end + + always @(posedge clk_i or negedge rst_n) begin + if (~rst_n) begin + synch_regs_q <= 0; + end else begin + synch_regs_q <= {synch_regs_q[NumRegs-2:0], 1'b1}; + end + end + // pragma translate_off + `ifndef VERILATOR + initial begin : p_assertions + if (NumRegs < 1) $fatal(1, "At least one register is required."); + end + `endif + // pragma translate_on +endmodule diff --git a/hw/deps/common_cells/src/spill_register.sv b/hw/deps/common_cells/src/spill_register.sv new file mode 100644 index 0000000..d6f8d30 --- /dev/null +++ b/hw/deps/common_cells/src/spill_register.sv @@ -0,0 +1,95 @@ +// Copyright 2018 ETH Zurich and 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. +// +// Fabian Schuiki + + +/// A register with handshakes that completely cuts any combinational paths +/// between the input and output. +module spill_register #( + parameter type T = logic, + parameter bit Bypass = 1'b0 // make this spill register transparent +) ( + input logic clk_i , + input logic rst_ni , + input logic valid_i , + output logic ready_o , + input T data_i , + output logic valid_o , + input logic ready_i , + output T data_o +); + + if (Bypass) begin : gen_bypass + assign valid_o = valid_i; + assign ready_o = ready_i; + assign data_o = data_i; + end else begin : gen_spill_reg + // The A register. + T a_data_q; + logic a_full_q; + logic a_fill, a_drain; + logic a_en, a_en_data; + + always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_data + if (!rst_ni) + a_data_q <= '0; + else if (a_fill) + a_data_q <= data_i; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_full + if (!rst_ni) + a_full_q <= 0; + else if (a_fill || a_drain) + a_full_q <= a_fill; + end + + // The B register. + T b_data_q; + logic b_full_q; + logic b_fill, b_drain; + + always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_data + if (!rst_ni) + b_data_q <= '0; + else if (b_fill) + b_data_q <= a_data_q; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_full + if (!rst_ni) + b_full_q <= 0; + else if (b_fill || b_drain) + b_full_q <= b_fill; + end + + // Fill the A register when the A or B register is empty. Drain the A register + // whenever it is full and being filled. + assign a_fill = valid_i && ready_o; + assign a_drain = a_full_q && !b_full_q; + + // Fill the B register whenever the A register is drained, but the downstream + // circuit is not ready. Drain the B register whenever it is full and the + // downstream circuit is ready. + assign b_fill = a_drain && !ready_i; + assign b_drain = b_full_q && ready_i; + + // We can accept input as long as register B is not full. + assign ready_o = !a_full_q || !b_full_q; + + // The unit provides output as long as one of the registers is filled. + assign valid_o = a_full_q | b_full_q; + + // We empty the spill register before the slice register. + assign data_o = b_full_q ? b_data_q : a_data_q; + end +endmodule diff --git a/hw/deps/common_cells/src/stream_arbiter.sv b/hw/deps/common_cells/src/stream_arbiter.sv new file mode 100644 index 0000000..c8ca2a8 --- /dev/null +++ b/hw/deps/common_cells/src/stream_arbiter.sv @@ -0,0 +1,49 @@ +// Copyright 2018 ETH Zurich and 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. + +// Stream arbiter: Arbitrates a parametrizable number of input streams (i.e., valid-ready +// handshaking with dependency rules as in AXI4) to a single output stream. Once `oup_valid_o` is +// asserted, `oup_data_o` remains invariant until the output handshake has occurred. The +// arbitration scheme is round-robin with "look ahead", see the `rrarbiter` for details. + +module stream_arbiter #( + parameter type DATA_T = logic, // Vivado requires a default value for type parameters. + parameter integer N_INP = -1, // Synopsys DC requires a default value for parameters. + parameter ARBITER = "rr" // "rr" or "prio" +) ( + input logic clk_i, + input logic rst_ni, + + input DATA_T [N_INP-1:0] inp_data_i, + input logic [N_INP-1:0] inp_valid_i, + output logic [N_INP-1:0] inp_ready_o, + + output DATA_T oup_data_o, + output logic oup_valid_o, + input logic oup_ready_i +); + + stream_arbiter_flushable #( + .DATA_T (DATA_T), + .N_INP (N_INP), + .ARBITER (ARBITER) + ) i_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .inp_data_i (inp_data_i), + .inp_valid_i (inp_valid_i), + .inp_ready_o (inp_ready_o), + .oup_data_o (oup_data_o), + .oup_valid_o (oup_valid_o), + .oup_ready_i (oup_ready_i) + ); + +endmodule diff --git a/hw/deps/common_cells/src/stream_arbiter_flushable.sv b/hw/deps/common_cells/src/stream_arbiter_flushable.sv new file mode 100644 index 0000000..32946e6 --- /dev/null +++ b/hw/deps/common_cells/src/stream_arbiter_flushable.sv @@ -0,0 +1,82 @@ +// Copyright 2018 ETH Zurich and 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. + +// Stream arbiter: Arbitrates a parametrizable number of input streams (i.e., valid-ready +// handshaking with dependency rules as in AXI4) to a single output stream. Once `oup_valid_o` is +// asserted, `oup_data_o` remains invariant until the output handshake has occurred. The +// arbitration scheme is fair round-robin tree, see `rr_arb_tree` for details. + +module stream_arbiter_flushable #( + parameter type DATA_T = logic, // Vivado requires a default value for type parameters. + parameter integer N_INP = -1, // Synopsys DC requires a default value for parameters. + parameter ARBITER = "rr" // "rr" or "prio" +) ( + input logic clk_i, + input logic rst_ni, + input logic flush_i, + + input DATA_T [N_INP-1:0] inp_data_i, + input logic [N_INP-1:0] inp_valid_i, + output logic [N_INP-1:0] inp_ready_o, + + output DATA_T oup_data_o, + output logic oup_valid_o, + input logic oup_ready_i +); + + if (ARBITER == "rr") begin : gen_rr_arb + rr_arb_tree #( + .NumIn (N_INP), + .DataType (DATA_T), + .ExtPrio (1'b0), + .AxiVldRdy (1'b1), + .LockIn (1'b1) + ) i_arbiter ( + .clk_i, + .rst_ni, + .flush_i, + .rr_i ('0), + .req_i (inp_valid_i), + .gnt_o (inp_ready_o), + .data_i (inp_data_i), + .gnt_i (oup_ready_i), + .req_o (oup_valid_o), + .data_o (oup_data_o), + .idx_o () + ); + + end else if (ARBITER == "prio") begin : gen_prio_arb + rr_arb_tree #( + .NumIn (N_INP), + .DataType (DATA_T), + .ExtPrio (1'b1), + .AxiVldRdy (1'b1), + .LockIn (1'b1) + ) i_arbiter ( + .clk_i, + .rst_ni, + .flush_i, + .rr_i ('0), + .req_i (inp_valid_i), + .gnt_o (inp_ready_o), + .data_i (inp_data_i), + .gnt_i (oup_ready_i), + .req_o (oup_valid_o), + .data_o (oup_data_o), + .idx_o () + ); + + end else begin : gen_arb_error + // pragma translate_off + $fatal(1, "Invalid value for parameter 'ARBITER'!"); + // pragma translate_on + end + +endmodule diff --git a/hw/deps/common_cells/src/stream_demux.sv b/hw/deps/common_cells/src/stream_demux.sv new file mode 100644 index 0000000..69ad309 --- /dev/null +++ b/hw/deps/common_cells/src/stream_demux.sv @@ -0,0 +1,36 @@ +// Copyright 2018 ETH Zurich and 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. + +/// Connects the input stream (valid-ready) handshake to one of `N_OUP` output stream handshakes. +/// +/// This module has no data ports because stream data does not need to be demultiplexed: the data of +/// the input stream can just be applied at all output streams. +module stream_demux #( + /// Number of connected outputs. + parameter int unsigned N_OUP = 32'd1, + /// Dependent parameters, DO NOT OVERRIDE! + parameter int unsigned LOG_N_OUP = (N_OUP > 32'd1) ? unsigned'($clog2(N_OUP)) : 1'b1 +) ( + input logic inp_valid_i, + output logic inp_ready_o, + + input logic [LOG_N_OUP-1:0] oup_sel_i, + + output logic [N_OUP-1:0] oup_valid_o, + input logic [N_OUP-1:0] oup_ready_i +); + + always_comb begin + oup_valid_o = '0; + oup_valid_o[oup_sel_i] = inp_valid_i; + end + assign inp_ready_o = oup_ready_i[oup_sel_i]; + +endmodule diff --git a/hw/deps/common_cells/src/stream_fifo.sv b/hw/deps/common_cells/src/stream_fifo.sv new file mode 100644 index 0000000..e7c60e5 --- /dev/null +++ b/hw/deps/common_cells/src/stream_fifo.sv @@ -0,0 +1,66 @@ +// Copyright 2020 ETH Zurich and 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. + +// Author: Georg Rutishauser + +module stream_fifo #( + /// FIFO is in fall-through mode + parameter bit FALL_THROUGH = 1'b0, + /// Default data width if the fifo is of type logic + parameter int unsigned DATA_WIDTH = 32, + /// Depth can be arbitrary from 0 to 2**32 + parameter int unsigned DEPTH = 8, + parameter type T = logic [DATA_WIDTH-1:0], + // DO NOT OVERWRITE THIS PARAMETER + parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1 +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic flush_i, // flush the fifo + input logic testmode_i, // test_mode to bypass clock gating + output logic [ADDR_DEPTH-1:0] usage_o, // fill pointer + // input interface + input T data_i, // data to push into the fifo + input logic valid_i, // input data valid + output logic ready_o, // fifo is not full + // output interface + output T data_o, // output data + output logic valid_o, // fifo is not empty + input logic ready_i // pop head from fifo +); + + logic push, pop; + logic empty, full; + + assign push = valid_i & ~full; + assign pop = ready_i & ~empty; + assign ready_o = ~full; + assign valid_o = ~empty; + + fifo_v3 #( + .FALL_THROUGH (FALL_THROUGH), + .DATA_WIDTH (DATA_WIDTH), + .DEPTH (DEPTH), + .dtype(T) + ) fifo_i ( + .clk_i, + .rst_ni, + .flush_i, + .testmode_i, + .full_o (full), + .empty_o (empty), + .usage_o, + .data_i, + .push_i (push), + .data_o, + .pop_i (pop) + ); + +endmodule diff --git a/hw/deps/common_cells/src/stream_filter.sv b/hw/deps/common_cells/src/stream_filter.sv new file mode 100644 index 0000000..52a5835 --- /dev/null +++ b/hw/deps/common_cells/src/stream_filter.sv @@ -0,0 +1,26 @@ +// Copyright 2018 ETH Zurich and 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. + +// Stream filter: If `drop_i` is `1`, signal `ready` to the upstream regardless of the downstream, +// and do not propagate `valid` downstream. Otherwise, connect upstream to downstream. +module stream_filter ( + input logic valid_i, + output logic ready_o, + + input logic drop_i, + + output logic valid_o, + input logic ready_i +); + + assign valid_o = drop_i ? 1'b0 : valid_i; + assign ready_o = drop_i ? 1'b1 : ready_i; + +endmodule diff --git a/hw/deps/common_cells/src/stream_fork.sv b/hw/deps/common_cells/src/stream_fork.sv new file mode 100644 index 0000000..aebb0f5 --- /dev/null +++ b/hw/deps/common_cells/src/stream_fork.sv @@ -0,0 +1,133 @@ +// Copyright 2018 ETH Zurich and 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. + +// Stream fork: Connects the input stream (ready-valid) handshake to *all* of `N_OUP` output stream +// handshakes. For each input stream handshake, every output stream handshakes exactly once. The +// input stream only handshakes when all output streams have handshaked, but the output streams do +// not have to handshake simultaneously. +// +// This module has no data ports because stream data does not need to be forked: the data of the +// input stream can just be applied at all output streams. + +module stream_fork #( + parameter int unsigned N_OUP = 0 // Synopsys DC requires a default value for parameters. +) ( + input logic clk_i, + input logic rst_ni, + input logic valid_i, + output logic ready_o, + output logic [N_OUP-1:0] valid_o, + input logic [N_OUP-1:0] ready_i +); + + typedef enum logic {READY, WAIT} state_t; + + logic [N_OUP-1:0] oup_ready, + all_ones; + + state_t inp_state_d, inp_state_q; + + // Input control FSM + always_comb begin + // ready_o = 1'b0; + inp_state_d = inp_state_q; + + unique case (inp_state_q) + READY: begin + if (valid_i) begin + if (valid_o == all_ones && ready_i == all_ones) begin + // If handshake on all outputs, handshake on input. + ready_o = 1'b1; + end else begin + ready_o = 1'b0; + // Otherwise, wait for inputs that did not handshake yet. + inp_state_d = WAIT; + end + end else begin + ready_o = 1'b0; + end + end + WAIT: begin + if (valid_i && oup_ready == all_ones) begin + ready_o = 1'b1; + inp_state_d = READY; + end else begin + ready_o = 1'b0; + end + end + default: begin + inp_state_d = READY; + ready_o = 1'b0; + end + endcase + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + inp_state_q <= READY; + end else begin + inp_state_q <= inp_state_d; + end + end + + // Output control FSM + for (genvar i = 0; i < N_OUP; i++) begin: gen_oup_state + state_t oup_state_d, oup_state_q; + + always_comb begin + oup_ready[i] = 1'b1; + valid_o[i] = 1'b0; + oup_state_d = oup_state_q; + + unique case (oup_state_q) + READY: begin + if (valid_i) begin + valid_o[i] = 1'b1; + if (ready_i[i]) begin // Output handshake + if (!ready_o) begin // No input handshake yet + oup_state_d = WAIT; + end + end else begin // No output handshake + oup_ready[i] = 1'b0; + end + end + end + WAIT: begin + if (valid_i && ready_o) begin // Input handshake + oup_state_d = READY; + end + end + default: begin + oup_state_d = READY; + end + endcase + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + oup_state_q <= READY; + end else begin + oup_state_q <= oup_state_d; + end + end + end + + assign all_ones = '1; // Synthesis fix for Vivado, which does not correctly compute the width + // of the '1 literal when assigned to a port of parametrized width. + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (N_OUP >= 1) else $fatal("Number of outputs must be at least 1!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/common_cells/src/stream_fork_dynamic.sv b/hw/deps/common_cells/src/stream_fork_dynamic.sv new file mode 100644 index 0000000..e4720f7 --- /dev/null +++ b/hw/deps/common_cells/src/stream_fork_dynamic.sv @@ -0,0 +1,95 @@ +// Copyright 2020 ETH Zurich and 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. + +// Authors: +// - Andreas Kurth + +/// Dynamic stream fork: Connects the input stream (ready-valid) handshake to a combination of output +/// stream handshake. The combination is determined dynamically through another stream, which +/// provides a bitmask for the fork. For each input stream handshake, every output stream handshakes +/// exactly once. The input stream only handshakes when all output streams have handshaked, but the +/// output streams do not have to handshake simultaneously. +/// +/// This module has no data ports because stream data does not need to be forked: the data of the +/// input stream can just be applied at all output streams. +module stream_fork_dynamic #( + /// Number of output streams + parameter int unsigned N_OUP = 32'd0 // Synopsys DC requires a default value for parameters. +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Input stream valid handshake, + input logic valid_i, + /// Input stream ready handshake + output logic ready_o, + /// Selection mask for the output handshake + input logic [N_OUP-1:0] sel_i, + /// Selection mask valid + input logic sel_valid_i, + /// Selection mask ready + output logic sel_ready_o, + /// Output streams valid handshakes + output logic [N_OUP-1:0] valid_o, + /// Output streams ready handshakes + input logic [N_OUP-1:0] ready_i +); + + logic int_inp_valid, int_inp_ready; + logic [N_OUP-1:0] int_oup_valid, int_oup_ready; + + // Output handshaking + for (genvar i = 0; i < N_OUP; i++) begin : gen_oups + always_comb begin + valid_o[i] = 1'b0; + int_oup_ready[i] = 1'b0; + if (sel_valid_i) begin + if (sel_i[i]) begin + valid_o[i] = int_oup_valid[i]; + int_oup_ready[i] = ready_i[i]; + end else begin + int_oup_ready[i] = 1'b1; + end + end + end + end + + // Input handshaking + always_comb begin + int_inp_valid = 1'b0; + ready_o = 1'b0; + sel_ready_o = 1'b0; + if (sel_valid_i) begin + int_inp_valid = valid_i; + ready_o = int_inp_ready; + sel_ready_o = int_inp_ready; + end + end + + stream_fork #( + .N_OUP ( N_OUP ) + ) i_fork ( + .clk_i, + .rst_ni, + .valid_i ( int_inp_valid ), + .ready_o ( int_inp_ready ), + .valid_o ( int_oup_valid ), + .ready_i ( int_oup_ready ) + ); + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (N_OUP >= 1) else $fatal(1, "N_OUP must be at least 1!"); + end +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/common_cells/src/stream_join.sv b/hw/deps/common_cells/src/stream_join.sv new file mode 100644 index 0000000..2f210bc --- /dev/null +++ b/hw/deps/common_cells/src/stream_join.sv @@ -0,0 +1,43 @@ +// Copyright 2020 ETH Zurich and 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. + +// Authors: +// - Andreas Kurth + +/// Stream join: Joins a parametrizable number of input streams (i.e., valid-ready handshaking with +/// dependency rules as in AXI4) to a single output stream. The output handshake happens only once +/// all inputs are valid. The data channel flows outside of this module. +module stream_join #( + /// Number of input streams + parameter int unsigned N_INP = 32'd0 // Synopsys DC requires a default value for parameters. +) ( + /// Input streams valid handshakes + input logic [N_INP-1:0] inp_valid_i, + /// Input streams ready handshakes + output logic [N_INP-1:0] inp_ready_o, + /// Output stream valid handshake + output logic oup_valid_o, + /// Output stream ready handshake + input logic oup_ready_i +); + + assign oup_valid_o = (&inp_valid_i); + for (genvar i = 0; i < N_INP; i++) begin : gen_inp_ready + assign inp_ready_o[i] = oup_valid_o & oup_ready_i; + end + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (N_INP >= 1) else $fatal(1, "N_INP must be at least 1!"); + end +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/common_cells/src/stream_mux.sv b/hw/deps/common_cells/src/stream_mux.sv new file mode 100644 index 0000000..156c572 --- /dev/null +++ b/hw/deps/common_cells/src/stream_mux.sv @@ -0,0 +1,46 @@ +// Copyright 2018 ETH Zurich and 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. + +/// Stream multiplexer: connects the output to one of `N_INP` data streams with valid-ready +/// handshaking. + +module stream_mux #( + parameter type DATA_T = logic, // Vivado requires a default value for type parameters. + parameter integer N_INP = 0, // Synopsys DC requires a default value for value parameters. + /// Dependent parameters, DO NOT OVERRIDE! + parameter integer LOG_N_INP = $clog2(N_INP) +) ( + input DATA_T [N_INP-1:0] inp_data_i, + input logic [N_INP-1:0] inp_valid_i, + output logic [N_INP-1:0] inp_ready_o, + + input logic [LOG_N_INP-1:0] inp_sel_i, + + output DATA_T oup_data_o, + output logic oup_valid_o, + input logic oup_ready_i +); + + always_comb begin + inp_ready_o = '0; + inp_ready_o[inp_sel_i] = oup_ready_i; + end + assign oup_data_o = inp_data_i[inp_sel_i]; + assign oup_valid_o = inp_valid_i[inp_sel_i]; + +// pragma translate_off +`ifndef VERILATOR + initial begin: p_assertions + assert (N_INP >= 1) else $fatal ("The number of inputs must be at least 1!"); + end +`endif +// pragma translate_on + +endmodule diff --git a/hw/deps/common_cells/src/stream_register.sv b/hw/deps/common_cells/src/stream_register.sv new file mode 100644 index 0000000..e83228b --- /dev/null +++ b/hw/deps/common_cells/src/stream_register.sv @@ -0,0 +1,57 @@ +// Copyright 2018 ETH Zurich and 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. + +/// Register with a simple stream-like ready/valid handshake. +/// This register does not cut combinatorial paths on all control signals; if you need a complete +/// cut, use the `spill_register`. +module stream_register #( + parameter type T = logic // Vivado requires a default value for type parameters. +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous active-low reset + input logic clr_i, // Synchronous clear + input logic testmode_i, // Test mode to bypass clock gating + // Input port + input logic valid_i, + output logic ready_o, + input T data_i, + // Output port + output logic valid_o, + input logic ready_i, + output T data_o +); + + logic fifo_empty, + fifo_full; + + fifo_v2 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH ($size(T)), + .DEPTH (1), + .dtype (T) + ) i_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (clr_i), + .testmode_i (testmode_i), + .full_o (fifo_full), + .empty_o (fifo_empty), + .alm_full_o ( ), + .alm_empty_o ( ), + .data_i (data_i), + .push_i (valid_i & ~fifo_full), + .data_o (data_o), + .pop_i (ready_i & ~fifo_empty) + ); + + assign ready_o = ~fifo_full; + assign valid_o = ~fifo_empty; + +endmodule diff --git a/hw/deps/common_cells/src/stream_to_mem.sv b/hw/deps/common_cells/src/stream_to_mem.sv new file mode 100644 index 0000000..00c3086 --- /dev/null +++ b/hw/deps/common_cells/src/stream_to_mem.sv @@ -0,0 +1,134 @@ +// Copyright 2020 ETH Zurich and 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. + +// Authors: +// - Andreas Kurth + +/// `stream_to_mem`: Allows to use memories with flow control (`valid`/`ready`) for requests but without flow +/// control for output data to be used in streams. +`include "common_cells/registers.svh" +module stream_to_mem #( + /// Memory request payload type, usually write enable, write data, etc. + parameter type mem_req_t = logic, + /// Memory response payload type, usually read data + parameter type mem_resp_t = logic, + /// Number of buffered responses (fall-through, thus no additional latency). This defines the + /// maximum number of outstanding requests on the memory interface. If the attached memory + /// responds in the same cycle a request is applied, this MUST be 0. If the attached memory + /// responds at least one cycle after a request, this MUST be >= 1 and should be equal to the + /// response latency of the memory to saturate bandwidth. + parameter int unsigned BufDepth = 32'd1 +) ( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Request stream interface, payload + input mem_req_t req_i, + /// Request stream interface, payload is valid for transfer + input logic req_valid_i, + /// Request stream interface, payload can be accepted + output logic req_ready_o, + /// Response stream interface, payload + output mem_resp_t resp_o, + /// Response stream interface, payload is valid for transfer + output logic resp_valid_o, + /// Response stream interface, payload can be accepted + input logic resp_ready_i, + /// Memory request interface, payload + output mem_req_t mem_req_o, + /// Memory request interface, payload is valid for transfer + output logic mem_req_valid_o, + /// Memory request interface, payload can be accepted + input logic mem_req_ready_i, + /// Memory response interface, payload + input mem_resp_t mem_resp_i, + /// Memory response interface, payload is valid + input logic mem_resp_valid_i +); + + typedef logic [$clog2(BufDepth+1):0] cnt_t; + + cnt_t cnt_d, cnt_q; + logic buf_ready, + req_ready; + + if (BufDepth > 0) begin : gen_buf + // Count number of outstanding requests. + always_comb begin + cnt_d = cnt_q; + if (req_valid_i && req_ready_o) begin + cnt_d++; + end + if (resp_valid_o && resp_ready_i) begin + cnt_d--; + end + end + + // Can issue another request if the counter is not at its limit or a response is delivered in + // the current cycle. + assign req_ready = (cnt_q < BufDepth) | (resp_valid_o & resp_ready_i); + + // Control request and memory request interface handshakes. + assign req_ready_o = mem_req_ready_i & req_ready; + assign mem_req_valid_o = req_valid_i & req_ready; + + // Buffer responses. + stream_fifo #( + .FALL_THROUGH ( 1'b1 ), + .DEPTH ( BufDepth ), + .T ( mem_resp_t ) + ) i_resp_buf ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .data_i ( mem_resp_i ), + .valid_i ( mem_resp_valid_i ), + .ready_o ( buf_ready ), + .data_o ( resp_o ), + .valid_o ( resp_valid_o ), + .ready_i ( resp_ready_i ), + .usage_o ( /* unused */ ) + ); + + // Register + `FFARN(cnt_q, cnt_d, '0, clk_i, rst_ni) + + end else begin : gen_no_buf + // Control request, memory request, and response interface handshakes. + assign mem_req_valid_o = req_valid_i; + assign resp_valid_o = mem_req_valid_o & mem_req_ready_i & mem_resp_valid_i; + assign req_ready_o = resp_ready_i & resp_valid_o; + + // Forward responses. + assign resp_o = mem_resp_i; + end + + // Forward requests. + assign mem_req_o = req_i; + +// Assertions +// pragma translate_off +`ifndef VERILATOR + if (BufDepth > 0) begin : gen_buf_asserts + assert property (@(posedge clk_i) mem_resp_valid_i |-> buf_ready) + else $error("Memory response lost!"); + assert property (@(posedge clk_i) cnt_q == '0 |=> cnt_q != '1) + else $error("Counter underflowed!"); + assert property (@(posedge clk_i) cnt_q == BufDepth |=> cnt_q != BufDepth + 1) + else $error("Counter overflowed!"); + end else begin : gen_no_buf_asserts + assume property (@(posedge clk_i) mem_req_valid_o & mem_req_ready_i |-> mem_resp_valid_i) + else $error("Without BufDepth = 0, the memory must respond in the same cycle!"); + end +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/event_unit_flex/event_unit_core.sv b/hw/deps/event_unit_flex/event_unit_core.sv new file mode 100644 index 0000000..b7d294c --- /dev/null +++ b/hw/deps/event_unit_flex/event_unit_core.sv @@ -0,0 +1,577 @@ +// Copyright 2018 ETH Zurich and 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. + +module event_unit_core +#( + parameter NB_CORES = 4, + parameter NB_SW_EVT = 8, + parameter NB_BARR = NB_CORES/2, + parameter NB_HW_MUT = 2, + parameter MUTEX_MSG_W = 32, + parameter PER_ID_WIDTH = 5 +) +( + // clock and reset + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + + // master event lines, partially private for a specific core + input logic [31:0] master_event_lines_i, + + // sw event generation output + output logic [NB_SW_EVT-1:0] core_sw_events_o, + output logic [NB_CORES-1:0] core_sw_events_mask_o, + + // barrier trigger output + output logic [NB_BARR-1:0] hw_barr_id_o, + + // request and message for mutex units + output logic [NB_HW_MUT-1:0] mutex_rd_req_o, + output logic [NB_HW_MUT-1:0] mutex_wr_req_o, + output logic [NB_HW_MUT-1:0][MUTEX_MSG_W-1:0] mutex_msg_wdata_o, + input logic [NB_HW_MUT-1:0][MUTEX_MSG_W-1:0] mutex_msg_rdata_i, + + // signals for entry point dispatch + output logic dispatch_pop_req_o, + output logic dispatch_pop_ack_o, + input logic [31:0] dispatch_value_i, + + output logic dispatch_w_req_o, + output logic [31:0] dispatch_w_data_o, + output logic [1:0] dispatch_reg_sel_o, + + // clock and interrupt request to core + output logic core_irq_req_o, + output logic [4:0] core_irq_id_o, + input logic core_irq_ack_i, + input logic [4:0] core_irq_ack_id_i, + + input logic core_busy_i, + output logic core_clock_en_o, + + // periph bus slave for regular register access + XBAR_PERIPH_BUS.Slave periph_int_bus_slave, + // demuxed periph for fast register access and event trigger + XBAR_PERIPH_BUS.Slave eu_direct_link_slave + +); + + // registers + logic [31:0] event_mask_DP, event_mask_DN; + logic [31:0] irq_mask_DP, irq_mask_DN; + logic [31:0] event_buffer_DP, event_buffer_DN; + + logic irq_req_del_SP, irq_req_del_SN; + + logic [NB_CORES-1:0] sw_events_mask_DP, sw_events_mask_DN; + logic wait_clear_access_SP, wait_clear_access_SN; + + // calculated write data + logic [31:0] wdata_event_mask_demux, wdata_event_mask_interc; + logic [31:0] wdata_irq_mask_demux, wdata_irq_mask_interc; + logic [31:0] wdata_event_buffer_demux, wdata_event_buffer_interc; + + logic [NB_CORES-1:0] wdata_sw_events_mask_demux, wdata_sw_events_mask_interc; + + // write control + logic [3:0] we_demux, we_interc; + + // combinational signals + logic [31:0] event_buffer_masked, irq_buffer_masked; + logic write_conflict, demux_add_is_sleep, demux_add_is_clear, replay_sleep_req; + logic stop_core_clock, core_clock_en, wait_core_idle; + + logic [31:0] irq_clear_mask; + logic [4:0] irq_sel_id; + logic irq_pending; + logic irq_mask_fsm; + + + // multiple sources for sw events (write to trigger and read from wait regs) + logic [NB_SW_EVT-1:0] sw_events_reg, sw_events_wait; + logic [NB_CORES-1:0] sw_events_mask_reg, sw_events_mask_wait; + + // (delayed) bus signals + logic p_interc_vld_SP, p_interc_vld_SN; + logic p_interc_gnt; + logic p_interc_req_del_SP, p_interc_req_del_SN; + logic p_interc_wen_del_SP, p_interc_wen_del_SN; + logic [3:0] p_interc_add_del_SP, p_interc_add_del_SN; + + logic p_demux_vld_SP, p_demux_vld_SN; + logic p_demux_gnt, p_demux_gnt_sleep_fsm; + logic p_demux_req_del_SP, p_demux_req_del_SN; + logic p_demux_wen_del_SP, p_demux_wen_del_SN; + logic [7:0] p_demux_add_del_SP, p_demux_add_del_SN; + + logic inhibit_req; + + // core clock FSM + enum logic [2:0] { ACTIVE, SLEEP, WAKEUP_SLEEP, WAKEUP_SLEEP_DEL, WAKEUP_IRQ, IRQ_WHILE_SLEEP } core_clock_CS, core_clock_NS; + + // ORing of sw event sources + assign core_sw_events_o = sw_events_reg | sw_events_wait; + assign core_sw_events_mask_o = sw_events_mask_reg | sw_events_mask_wait; + + // masking and reduction of buffer + assign event_buffer_masked = event_buffer_DP & event_mask_DP; + assign irq_buffer_masked = event_buffer_DP & irq_mask_DP; + + // calculation of one-hot clear mask for interrupts + assign irq_pending = |irq_buffer_masked; + assign irq_clear_mask = (core_irq_ack_i) ? ~(1'b1 << core_irq_ack_id_i) : '1; + + // new req/ack handling scheme for interrupts + assign irq_mask_fsm = stop_core_clock & ((core_clock_CS == ACTIVE) | (core_clock_CS == WAKEUP_SLEEP) | (core_clock_CS == WAKEUP_SLEEP_DEL)) & ~irq_req_del_SP; + assign irq_req_del_SN = irq_pending & ~irq_mask_fsm; + assign core_irq_req_o = irq_req_del_SN; + assign core_irq_id_o = irq_sel_id; + + // handle sleeping requests and conflicting write accesses + assign demux_add_is_sleep = ( ({eu_direct_link_slave.add[9:8],eu_direct_link_slave.add[5:3]} == 5'b00_111) || // core regs _wait and _wait_clear + ( eu_direct_link_slave.add[9:6] == 4'b0_101) || // sw events _wait + ( eu_direct_link_slave.add[9:6] == 4'b0_110) || // sw events _wait_clear + ({eu_direct_link_slave.add[9],eu_direct_link_slave.add[4:2]} == 4'b1_110) || // barriers _wait + ({eu_direct_link_slave.add[9],eu_direct_link_slave.add[4:2]} == 4'b1_111) || // barriers _wait_clear + ( eu_direct_link_slave.add[9:6] == 4'b0_011) || // hw mutexes + ({eu_direct_link_slave.add[9:6],eu_direct_link_slave.add[3:2]} == 6'b0010_00 ) ); // hw dispatch fifo_read + + assign demux_add_is_clear = ( ( eu_direct_link_slave.add[9:2] == 8'b00_0011_11) || // core regs _wait_clear + ( eu_direct_link_slave.add[9:6] == 4'b01_10) || // sw events _wait_clear + ({eu_direct_link_slave.add[9],eu_direct_link_slave.add[4:2]} == 4'b1_111) || // barriers _wait_clear + ( eu_direct_link_slave.add[9:6] == 4'b00_11) || // hw mutex units - always _wait_clear + ({eu_direct_link_slave.add[9:6],eu_direct_link_slave.add[3:2]} == 6'b0010_00 ) ); // hw dispatch fifo_read + + assign stop_core_clock = ( (eu_direct_link_slave.req == 1'b1) && (eu_direct_link_slave.wen == 1'b1) && (demux_add_is_sleep == 1'b1) ); + + assign write_conflict = ( ({periph_int_bus_slave.req, eu_direct_link_slave.req} == 2'b11) && + ({periph_int_bus_slave.wen, eu_direct_link_slave.wen} == 2'b00) ); + + // link from peripheral demux + assign p_demux_gnt = eu_direct_link_slave.req & p_demux_gnt_sleep_fsm; + assign p_demux_vld_SN = p_demux_gnt; + + assign eu_direct_link_slave.gnt = p_demux_gnt; + assign eu_direct_link_slave.r_id = '0; + assign eu_direct_link_slave.r_opc = 1'b0; + assign eu_direct_link_slave.r_valid = p_demux_vld_SP; + + assign p_demux_req_del_SN = eu_direct_link_slave.req; + assign p_demux_wen_del_SN = eu_direct_link_slave.wen; + assign p_demux_add_del_SN = eu_direct_link_slave.add[9:2]; + + + // link from peripheral interconnect + assign p_interc_gnt = ( (periph_int_bus_slave.req == 1'b1) && (write_conflict == 1'b0) ); + assign p_interc_vld_SN = p_interc_gnt; + + assign periph_int_bus_slave.gnt = p_interc_gnt; + assign periph_int_bus_slave.r_opc = 1'b0; + assign periph_int_bus_slave.r_valid = p_interc_vld_SP; + assign periph_int_bus_slave.r_id = '0; + + assign p_interc_req_del_SN = periph_int_bus_slave.req; + assign p_interc_wen_del_SN = periph_int_bus_slave.wen; + assign p_interc_add_del_SN = periph_int_bus_slave.add[5:2]; + + assign inhibit_req = (core_clock_CS == SLEEP) || (core_clock_CS == WAKEUP_SLEEP) || + (core_clock_CS == WAKEUP_IRQ) || (wait_core_idle == 1'b1); + + //write logic for demux and interconnect port + always_comb begin + // default register DN data + event_mask_DN = event_mask_DP; + irq_mask_DN = irq_mask_DP; + sw_events_mask_DN = sw_events_mask_DP; + // keep old buffer state and buffer newly triggered events + event_buffer_DN = (event_buffer_DP | master_event_lines_i) & irq_clear_mask; + + // default: don't write any register + we_demux = '0; + wdata_event_mask_demux = '0; + wdata_irq_mask_demux = '0; + wdata_event_buffer_demux = '0; + wdata_sw_events_mask_demux = '0; + + we_interc = '0; + wdata_event_mask_interc = '0; + wdata_irq_mask_interc = '0; + wdata_event_buffer_interc = '0; + wdata_sw_events_mask_interc = '0; + + // default: don't trigger any sw event or barrier + sw_events_reg = '0; + sw_events_mask_reg = '0; + + // default: don't unlock (write) a mutex + mutex_wr_req_o = '0; + mutex_msg_wdata_o = '0; + + // default: don't push a value to or configure the HW dispatch + dispatch_w_req_o = 1'b0; + dispatch_w_data_o = '0; + dispatch_reg_sel_o = '0; + + // periph demux write access + if ( (eu_direct_link_slave.req == 1'b1) && (eu_direct_link_slave.wen == 1'b0) ) begin + casex (eu_direct_link_slave.add[9:6]) // decode reg group + 4'b00_00: begin + // eu core registers + case (eu_direct_link_slave.add[5:2]) + 4'h0: begin we_demux[0] = 1'b1; wdata_event_mask_demux = eu_direct_link_slave.wdata; end + 4'h1: begin we_demux[0] = 1'b1; wdata_event_mask_demux = event_mask_DP & ~eu_direct_link_slave.wdata; end + 4'h2: begin we_demux[0] = 1'b1; wdata_event_mask_demux = event_mask_DP | eu_direct_link_slave.wdata; end + 4'h3: begin we_demux[1] = 1'b1; wdata_irq_mask_demux = eu_direct_link_slave.wdata; end + 4'h4: begin we_demux[1] = 1'b1; wdata_irq_mask_demux = irq_mask_DP & ~eu_direct_link_slave.wdata; end + 4'h5: begin we_demux[1] = 1'b1; wdata_irq_mask_demux = irq_mask_DP | eu_direct_link_slave.wdata; end + 4'ha: begin we_demux[2] = 1'b1; wdata_event_buffer_demux = event_buffer_DP & ~eu_direct_link_slave.wdata; end + 4'hb: begin we_demux[3] = 1'b1; wdata_sw_events_mask_demux = eu_direct_link_slave.wdata[NB_CORES-1:0]; end + 4'hc: begin we_demux[3] = 1'b1; wdata_sw_events_mask_demux = sw_events_mask_DP & ~eu_direct_link_slave.wdata[NB_CORES-1:0]; end + 4'hd: begin we_demux[3] = 1'b1; wdata_sw_events_mask_demux = sw_events_mask_DP | eu_direct_link_slave.wdata[NB_CORES-1:0]; end + endcase + end + 4'b00_10: begin + // hw dispatch + dispatch_w_req_o = 1'b1; + dispatch_w_data_o = eu_direct_link_slave.wdata; + dispatch_reg_sel_o = eu_direct_link_slave.add[3:2]; + end + 4'b00_11: begin + // hw mutexes + mutex_wr_req_o[eu_direct_link_slave.add[5:2]] = 1'b1; + mutex_msg_wdata_o[eu_direct_link_slave.add[5:2]] = eu_direct_link_slave.wdata; + end + 4'b01_??: begin + // handle sw event triggering + if ( eu_direct_link_slave.add[7:6] == 2'b00 ) begin + sw_events_reg[eu_direct_link_slave.add[4:2]] = 1'b1; + // use all-0 state to trigger all cores + if ( eu_direct_link_slave.wdata[NB_CORES-1:0] == '0 ) + sw_events_mask_reg = '1; + else + sw_events_mask_reg = eu_direct_link_slave.wdata[NB_CORES-1:0]; + end + end + endcase + end + + // periph interconnect write access + if ( (periph_int_bus_slave.req == 1'b1) && (periph_int_bus_slave.wen == 1'b0) ) begin + case (periph_int_bus_slave.add[5:2]) + 4'h0: begin we_interc[0] = 1'b1; wdata_event_mask_interc = periph_int_bus_slave.wdata; end + 4'h1: begin we_interc[0] = 1'b1; wdata_event_mask_interc = event_mask_DP & ~periph_int_bus_slave.wdata; end + 4'h2: begin we_interc[0] = 1'b1; wdata_event_mask_interc = event_mask_DP | periph_int_bus_slave.wdata; end + 4'h3: begin we_interc[1] = 1'b1; wdata_irq_mask_interc = periph_int_bus_slave.wdata; end + 4'h4: begin we_interc[1] = 1'b1; wdata_irq_mask_interc = irq_mask_DP & ~periph_int_bus_slave.wdata; end + 4'h5: begin we_interc[1] = 1'b1; wdata_irq_mask_interc = irq_mask_DP | periph_int_bus_slave.wdata; end + 4'ha: begin we_interc[2] = 1'b1; wdata_event_buffer_interc = event_buffer_DP & ~periph_int_bus_slave.wdata; end + 4'hb: begin we_interc[3] = 1'b1; wdata_sw_events_mask_interc = periph_int_bus_slave.wdata[NB_CORES-1:0]; end + 4'hc: begin we_interc[3] = 1'b1; wdata_sw_events_mask_interc = sw_events_mask_DP & ~periph_int_bus_slave.wdata[NB_CORES-1:0]; end + 4'hd: begin we_interc[3] = 1'b1; wdata_sw_events_mask_interc = sw_events_mask_DP | periph_int_bus_slave.wdata[NB_CORES-1:0]; end + endcase + end + + // write arbiters - demux write access takes priority + if ( we_demux[0] == 1'b1 ) + event_mask_DN = wdata_event_mask_demux; + else if ( we_interc[0] == 1'b1 ) + event_mask_DN = wdata_event_mask_interc; + + if ( we_demux[1] == 1'b1 ) + irq_mask_DN = wdata_irq_mask_demux; + else if ( we_interc[1] == 1'b1 ) + irq_mask_DN = wdata_irq_mask_interc; + + + if ( wait_clear_access_SP == 1'b1 ) + event_buffer_DN = ((event_buffer_DP | master_event_lines_i) & ~event_mask_DP) & irq_clear_mask; + else if ( we_demux[2] == 1'b1 ) + event_buffer_DN = (wdata_event_buffer_demux | master_event_lines_i) & irq_clear_mask; + else if ( we_interc[2] == 1'b1 ) + event_buffer_DN = (wdata_event_buffer_interc | master_event_lines_i) & irq_clear_mask; + + + if ( we_demux[3] == 1'b1 ) + sw_events_mask_DN = wdata_sw_events_mask_demux; + else if ( we_interc[3] == 1'b1 ) + sw_events_mask_DN = wdata_sw_events_mask_interc; + + end + + // read muxes for both links + always_comb begin + eu_direct_link_slave.r_rdata = '0; + periph_int_bus_slave.r_rdata = '0; + + // default: don't trigger any sw event or barrier or mutex + sw_events_wait = '0; + sw_events_mask_wait = '0; + hw_barr_id_o = '0; + mutex_rd_req_o = '0; + + // default: dont'r request to pop a value from the dispatch FIFO + dispatch_pop_req_o = 1'b0; + + // read accesses for periph demux port; inclues _wait and _wait_clear regs + if ( (p_demux_req_del_SP == 1'b1) && (p_demux_wen_del_SP == 1'b1) ) begin + case (p_demux_add_del_SP[7:4]) // decode reg group + 4'b00_00: begin // eu core registers + case (p_demux_add_del_SP[3:0]) + 4'h0: eu_direct_link_slave.r_rdata = event_mask_DP; + 4'h3: eu_direct_link_slave.r_rdata = irq_mask_DP; + 4'h6: eu_direct_link_slave.r_rdata = {31'b0, core_clock_en}; + 4'h7: eu_direct_link_slave.r_rdata = event_buffer_DP; + 4'h8: eu_direct_link_slave.r_rdata = event_buffer_masked; + 4'h9: eu_direct_link_slave.r_rdata = irq_buffer_masked; + 4'hb: eu_direct_link_slave.r_rdata = {{(32-NB_CORES){1'b0}}, sw_events_mask_DP}; + 4'he: eu_direct_link_slave.r_rdata = event_buffer_masked; + 4'hf: eu_direct_link_slave.r_rdata = event_buffer_masked; + endcase + end + 4'b00_10: begin // hw dispatch pop request + if ( p_demux_add_del_SP[1:0] == 2'b00 ) + eu_direct_link_slave.r_rdata = dispatch_value_i; + end + // mutex read/lock request + 4'b00_11: eu_direct_link_slave.r_rdata = mutex_msg_rdata_i[p_demux_add_del_SP[3:0]]; + // some wait register for either sw_event or barrier + 4'b0101,4'b0110,4'b1011,4'b1100: eu_direct_link_slave.r_rdata = event_buffer_masked; + endcase + end + + if ( (eu_direct_link_slave.req == 1'b1) && (eu_direct_link_slave.wen == 1'b1) && + (replay_sleep_req == 1'b0) && (inhibit_req == 1'b0) ) begin + // trigger sw_event+read buffer+sleep(+clear) accesses + if ( (eu_direct_link_slave.add[9:6] == 4'b0101) || (eu_direct_link_slave.add[9:6] == 4'b0110) ) begin + sw_events_wait[eu_direct_link_slave.add[4:2]] = 1'b1; + // use all-0 state to trigger all cores + if ( sw_events_mask_DP == '0 ) + sw_events_mask_wait = '1; + else + sw_events_mask_wait = sw_events_mask_DP; + end + + // trigger hw_barrier+read buffer+sleep(+clear) accesses + if ( ({eu_direct_link_slave.add[9],eu_direct_link_slave.add[4:2]} == 4'b1_110) || + ({eu_direct_link_slave.add[9],eu_direct_link_slave.add[4:2]} == 4'b1_111) ) + begin + hw_barr_id_o[eu_direct_link_slave.add[8:5]] = 1'b1; ; + end + + // try to lock a mutex + if ( eu_direct_link_slave.add[9:6] == 4'b0_011 ) + mutex_rd_req_o[eu_direct_link_slave.add[5:2]] = 1'b1; + + // try to pop a value from the dispatch FIFO + if ( eu_direct_link_slave.add[9:2] == 8'b0_01000_00 ) + dispatch_pop_req_o = 1'b1; + + end + + // only regular read accesses for interconnect port + if ( (p_interc_req_del_SP == 1'b1) && (p_interc_wen_del_SP == 1'b1) ) begin + case (p_interc_add_del_SP) + 4'h0: periph_int_bus_slave.r_rdata = event_mask_DP; + 4'h3: periph_int_bus_slave.r_rdata = irq_mask_DP; + 4'h6: periph_int_bus_slave.r_rdata = {31'b0, core_clock_en}; + 4'h7: periph_int_bus_slave.r_rdata = event_buffer_DP; + 4'h8: periph_int_bus_slave.r_rdata = event_buffer_masked; + 4'h9: periph_int_bus_slave.r_rdata = irq_buffer_masked; + 4'hb: periph_int_bus_slave.r_rdata = {{(32-NB_CORES){1'b0}}, sw_events_mask_DP}; + endcase + end + end + + + // FSM for controlling the core clock + always_comb begin + core_clock_NS = core_clock_CS; + core_clock_en = 1'b1; + replay_sleep_req = 1'b0; + p_demux_gnt_sleep_fsm = 1'b1; + wait_clear_access_SN = 1'b0; + wait_core_idle = 1'b0; + dispatch_pop_ack_o = 1'b0; + + case (core_clock_CS) + ACTIVE: begin + // check if there is any sleep request at all + if ( stop_core_clock ) begin + if ( irq_req_del_SP ) + core_clock_NS = IRQ_WHILE_SLEEP; + else begin + // corner-case: event already triggered while going to sleep + if ( |event_buffer_masked ) begin + // inform dispatch that value is consumed + dispatch_pop_ack_o = 1'b1; + // handle buffer clear cases + if ( demux_add_is_clear == 1'b1 ) + wait_clear_access_SN = 1'b1; + end + else begin + p_demux_gnt_sleep_fsm = 1'b0; + if (core_busy_i == 1'b0) + core_clock_NS = SLEEP; + else + wait_core_idle = 1'b1; + end + end + end + end + SLEEP: begin + core_clock_en = 1'b0; + p_demux_gnt_sleep_fsm = 1'b0; + + if ( irq_pending ) begin + core_clock_en = 1'b1; + core_clock_NS = WAKEUP_IRQ; + end + else if ( |event_buffer_masked == 1'b1 ) begin + core_clock_NS = WAKEUP_SLEEP; + end + end + WAKEUP_IRQ: begin + core_clock_NS = IRQ_WHILE_SLEEP; + end + WAKEUP_SLEEP: begin + // we can be sure that dispatch value is consumed + dispatch_pop_ack_o = 1'b1; + // handle buffer clear cases + if ( demux_add_is_clear == 1'b1 ) begin + wait_clear_access_SN = 1'b1; + // allow 1 more cycle to clear event buffer to not skip immediately following sleep requests + core_clock_NS = WAKEUP_SLEEP_DEL; + end + else begin + core_clock_NS = ACTIVE; + end + end + WAKEUP_SLEEP_DEL: begin + // possible that we already have a new sleep request - stall the requesting core 1 cycle + if ( stop_core_clock ) + p_demux_gnt_sleep_fsm = 1'b0; + core_clock_NS = ACTIVE; + end + IRQ_WHILE_SLEEP: begin + if ( stop_core_clock == 1'b1 ) begin + replay_sleep_req = 1'b1; + if ( irq_pending == 1'b0 ) begin + if ( |event_buffer_masked == 1'b1 ) begin + core_clock_NS = WAKEUP_SLEEP; + // handle buffer clear cases + if ( demux_add_is_clear == 1'b1 ) + wait_clear_access_SN = 1'b1; + end + else begin + p_demux_gnt_sleep_fsm = 1'b0; + if (core_busy_i == 1'b0) + core_clock_NS = SLEEP; + end + end + end + end + endcase // core_clock_CS + end + + assign core_clock_en_o = core_clock_en; + + // find first leading 1 for current irq priorization scheme + fl1_loop #( + .WIDTH(32) ) + fl1_loop_i ( + .vector_i(irq_buffer_masked), + .idx_bin_o(irq_sel_id), + .no1_o() + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin + if ( rst_ni == 1'b0 ) begin + core_clock_CS <= ACTIVE; + event_mask_DP <= '0; + irq_mask_DP <= '0; + irq_req_del_SP <= '0; + event_buffer_DP <= '0; + wait_clear_access_SP <= '0; + sw_events_mask_DP <= '0; + + p_demux_vld_SP <= 1'b0; + p_demux_add_del_SP <= '0; + p_demux_req_del_SP <= 1'b0; + p_demux_wen_del_SP <= 1'b0; + p_interc_vld_SP <= 1'b0; + p_interc_add_del_SP <= '0; + p_interc_req_del_SP <= 1'b0; + p_interc_wen_del_SP <= 1'b0; + end + else begin + core_clock_CS <= core_clock_NS; + + if ( we_demux[0] == 1'b1 ) + event_mask_DP <= wdata_event_mask_demux; + else if ( we_interc[0] == 1'b1 ) + event_mask_DP <= wdata_event_mask_interc; + + if ( wait_clear_access_SP | core_irq_ack_i | (|master_event_lines_i) | we_demux[2] | we_interc[2] ) + event_buffer_DP <= event_buffer_DN; + + event_mask_DP <= event_mask_DN; + irq_mask_DP <= irq_mask_DN; + irq_req_del_SP <= irq_req_del_SN; + + wait_clear_access_SP <= wait_clear_access_SN; + sw_events_mask_DP <= sw_events_mask_DN; + + p_demux_vld_SP <= p_demux_vld_SN; + + if(eu_direct_link_slave.req & eu_direct_link_slave.gnt) + p_demux_add_del_SP <= p_demux_add_del_SN; + + p_demux_req_del_SP <= p_demux_req_del_SN; + p_demux_wen_del_SP <= p_demux_wen_del_SN; + p_interc_vld_SP <= p_interc_vld_SN; + + if(periph_int_bus_slave.req & periph_int_bus_slave.gnt) + p_interc_add_del_SP <= p_interc_add_del_SN; + + p_interc_req_del_SP <= p_interc_req_del_SN; + p_interc_wen_del_SP <= p_interc_wen_del_SN; + end + end + +endmodule // event_unit_core + +module fl1_loop +#( + parameter WIDTH = 4 +) +( + input logic [WIDTH-1:0] vector_i, + output logic [$clog2(WIDTH)-1:0] idx_bin_o, + output logic no1_o +); + + assign no1_o = ~(|vector_i); + + logic found; + + always_comb begin + found = 1'b0; + idx_bin_o = '0; + + for (int i = WIDTH-1; i > 0; i--) begin + if ( (vector_i[i] == 1'b1) && (found == 1'b0) ) begin + found = 1'b1; + idx_bin_o = i; + end + end + end + +endmodule diff --git a/hw/deps/event_unit_flex/event_unit_interface_mux.sv b/hw/deps/event_unit_flex/event_unit_interface_mux.sv new file mode 100644 index 0000000..1360689 --- /dev/null +++ b/hw/deps/event_unit_flex/event_unit_interface_mux.sv @@ -0,0 +1,330 @@ +// Copyright 2018 ETH Zurich and 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. + +module event_unit_interface_mux +#( + parameter NB_CORES = 4, + parameter NB_BARR = NB_CORES/2, + parameter PER_ID_WIDTH = NB_CORES+1 +) +( + // clock and reset + input logic clk_i, + input logic rst_ni, + + // slave port from periph interconnect, decode requests + XBAR_PERIPH_BUS.Slave speriph_slave, + XBAR_PERIPH_BUS.Master periph_int_bus_master[NB_CORES+NB_BARR+2:0], + + // demuxed slave ports from each core, redistribute to eu_core and barrier units + XBAR_PERIPH_BUS.Slave demux_slave[NB_CORES-1:0], + XBAR_PERIPH_BUS.Master demux_int_bus_core_master[NB_CORES-1:0], + XBAR_PERIPH_BUS.Master demux_int_bus_barrier_master[NB_CORES*NB_BARR-1:0] +); + + + genvar I,J; + + + //*************************************************************// + // // + // ██████╗ ███████╗███╗ ███╗██╗ ██╗██╗ ██╗ // + // ██╔══██╗██╔════╝████╗ ████║██║ ██║╚██╗██╔╝ // + // ██║ ██║█████╗ ██╔████╔██║██║ ██║ ╚███╔╝ // + // ██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║ ██╔██╗ // + // ██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝██╔╝ ██╗ // + // ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ // + // // + //*************************************************************// + + + // response channel for demux plug + logic [NB_CORES-1:0][4:0] demux_ip_sel_SP, demux_ip_sel_SN; + logic [NB_CORES-1:0] demux_slave_req_del; + logic [NB_CORES-1:0] demux_slave_update; + logic [NB_CORES-1:0] demux_add_is_core; + logic [NB_CORES-1:0] demux_slave_gnt_mux; + + // helper arrays to work around sv dynamic bus index select limitation + logic [NB_CORES-1:0] demux_slaves_core_req; + + logic [NB_CORES*NB_BARR-1:0][31:0] demux_int_bus_barrier_master_rdata; + logic [NB_CORES*NB_BARR-1:0] demux_slaves_barrier_req; + logic [NB_CORES-1:0][NB_BARR-1:0] demux_slv_bar_req_int; + logic [NB_BARR-1:0][NB_CORES-1:0] demux_slv_bar_req_int_transp; + + generate + for ( I = 0; I < NB_CORES; I++ ) begin + // slave->master: output ports to cores + assign demux_slave[I].gnt = demux_slave_gnt_mux[I]; + assign demux_slave[I].r_opc = 1'b0; + assign demux_slave[I].r_id = '0; + // activation condition for responses on each demux plug + assign demux_slave_update[I] = ( (demux_slave[I].req & ~demux_slave_req_del[I]) || + (~demux_slave[I].req & demux_slave_req_del[I]) || + (demux_slave[I].req & demux_slave_gnt_mux[I]) ); + // check if Core I wants to access its private event_unit_core + assign demux_add_is_core[I] = ( ( demux_slave[I].add[9] == 1'b0 ) || // some core reg + ({demux_slave[I].add[9],demux_slave[I].add[4:2]} == 4'b1_110) || // barrier_trigg_wait + ({demux_slave[I].add[9],demux_slave[I].add[4:2]} == 4'b1_111) ); // barrier_trigg_wait_clear + assign demux_ip_sel_SN[I] = demux_add_is_core[I] ? '0 : {1'b1,demux_slave[I].add[8:5]}; + end + endgenerate + + generate + for ( J = 0; J < NB_BARR; J++ ) begin + for ( I = 0; I < NB_CORES; I++ ) assign demux_slv_bar_req_int_transp[J][I] = demux_slv_bar_req_int[I][J]; + assign demux_slaves_barrier_req[(J+1)*NB_CORES-1:J*NB_CORES] = demux_slv_bar_req_int_transp[J]; + end + endgenerate + + generate + for ( I = 0; I < NB_CORES; I++ ) begin + // master->slave + assign demux_int_bus_core_master[I].req = demux_slaves_core_req[I]; + assign demux_int_bus_core_master[I].add = demux_slave[I].add; + assign demux_int_bus_core_master[I].wen = demux_slave[I].wen; + assign demux_int_bus_core_master[I].wdata = demux_slave[I].wdata; + + assign demux_int_bus_core_master[I].id = '0; + assign demux_int_bus_core_master[I].be = '0; + end + endgenerate + + generate + for ( I = 0; I < NB_CORES*NB_BARR; I++ ) begin + // master->slave + assign demux_int_bus_barrier_master[I].req = demux_slaves_barrier_req[I]; + assign demux_int_bus_barrier_master[I].add = demux_slave[I % NB_CORES].add; + assign demux_int_bus_barrier_master[I].wen = demux_slave[I % NB_CORES].wen; + assign demux_int_bus_barrier_master[I].wdata = demux_slave[I % NB_CORES].wdata; + + assign demux_int_bus_barrier_master[I].id = '0; + assign demux_int_bus_barrier_master[I].be = '0; + + // slave->master: intermediate level + assign demux_int_bus_barrier_master_rdata[I] = demux_int_bus_barrier_master[I].r_rdata; + end + endgenerate + + generate + for ( I = 0; I < NB_CORES; I++ ) begin + // decoding of IP select part of address in case of request, selection of correct gnt + always_comb begin + demux_slv_bar_req_int[I] = '0; + + demux_slaves_core_req[I] = 1'b0; + demux_slave_gnt_mux[I] = 1'b0; + + if ( demux_slave[I].req == 1'b1 ) begin + // send request to private core unit, mux gnt back + if ( demux_add_is_core[I] ) begin + demux_slaves_core_req[I] = 1'b1; + demux_slave_gnt_mux[I] = demux_int_bus_core_master[I].gnt; + end + // send request to correct barrier unit, gnt can directly be given + else begin + demux_slv_bar_req_int[I][demux_slave[I].add[8:5]] = 1'b1; + demux_slave_gnt_mux[I] = 1'b1; + end + end + end + + // delayed muxing of correct response + always_comb begin + + // default: silence response channel + demux_slave[I].r_valid = 1'b0; + demux_slave[I].r_rdata = '0; + + if ( demux_slave_req_del[I] ) begin + if ( ~demux_ip_sel_SP[I][4] ) begin + demux_slave[I].r_valid = demux_int_bus_core_master[I].r_valid; + demux_slave[I].r_rdata = demux_int_bus_core_master[I].r_rdata; + end + else begin + demux_slave[I].r_valid = 1'b1; + demux_slave[I].r_rdata = demux_int_bus_barrier_master_rdata[NB_CORES*demux_ip_sel_SP[I][3:0]+I]; + end + end + end + + // 5 FF per core to store the response source + always_ff @(posedge clk_i, negedge rst_ni) + begin + if (~rst_ni) + begin + demux_ip_sel_SP[I] <= '0; + demux_slave_req_del[I] <= 1'b0; + end + else + begin + demux_slave_req_del[I] <= demux_slave[I].req; + if ( demux_slave_update[I] ) + demux_ip_sel_SP[I] <= demux_ip_sel_SN[I]; + end + end + end + endgenerate + + + //*************************************************************// + // // + // ██╗███╗ ██╗████████╗███████╗██████╗ ██████╗ // + // ██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗██╔════╝ // + // ██║██╔██╗ ██║ ██║ █████╗ ██████╔╝██║ // + // ██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗██║ // + // ██║██║ ╚████║ ██║ ███████╗██║ ██║╚██████╗ // + // ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ // + // // + //*************************************************************// + + // response channel for interconnect plug + logic [5:0] interc_ip_sel_SP, interc_ip_sel_SN; + logic speriph_slave_req_del; + logic speriph_slave_update; + logic speriph_slave_gnt_mux; + + logic [NB_CORES+NB_BARR+2:0] interc_slaves_req; + + // helper arrays to work around sv dynamic bus index select limitation + logic [NB_CORES-1:0][31:0] periph_int_bus_core_rdata; + logic [NB_BARR-1:0][31:0] periph_int_bus_barr_rdata; + logic [NB_CORES-1:0] periph_int_bus_core_rvalid; + logic [NB_BARR-1:0] periph_int_bus_barr_rvalid; + logic [NB_CORES-1:0] periph_int_bus_core_gnt; + logic [NB_BARR-1:0] periph_int_bus_barr_gnt; + + assign interc_ip_sel_SN = speriph_slave.add[10:5]; + + // activation condition for speriph slave responses + assign speriph_slave_update = ( (speriph_slave.req & ~speriph_slave_req_del) || + (~speriph_slave.req & speriph_slave_req_del) || + (speriph_slave.req & speriph_slave_gnt_mux) ); + + // broadcast master->slave signals with exception of req + generate + for ( I = 0; I < NB_CORES+NB_BARR+3; I++ ) begin + assign periph_int_bus_master[I].wdata = speriph_slave.wdata; + assign periph_int_bus_master[I].add = speriph_slave.add; + assign periph_int_bus_master[I].wen = speriph_slave.wen; + assign periph_int_bus_master[I].be = '1; + assign periph_int_bus_master[I].id = '0; + assign periph_int_bus_master[I].req = interc_slaves_req[I]; + end + endgenerate + + // assign slave->master signals + generate + for ( I = 0; I < NB_CORES; I++ ) begin + assign periph_int_bus_core_rdata[I] = periph_int_bus_master[I].r_rdata; + assign periph_int_bus_core_rvalid[I] = periph_int_bus_master[I].r_valid; + assign periph_int_bus_core_gnt[I] = periph_int_bus_master[I].gnt; + end + for ( I = 0; I < NB_BARR; I++ ) begin + assign periph_int_bus_barr_rdata[I] = periph_int_bus_master[NB_CORES+I].r_rdata; + assign periph_int_bus_barr_rvalid[I] = periph_int_bus_master[NB_CORES+I].r_valid; + assign periph_int_bus_barr_gnt[I] = periph_int_bus_master[NB_CORES+I].gnt; + end + endgenerate + + // assign muxed slave->master gnt + assign speriph_slave.gnt = speriph_slave_gnt_mux; + assign speriph_slave.r_opc = 1'b0; + + // decoding of IP select part of address in case of request, selection of correct gnt + always_comb begin + interc_slaves_req = '0; + speriph_slave_gnt_mux = 1'b0; + + if ( speriph_slave.req == 1'b1 ) begin + casex ( speriph_slave.add[10:7] ) + 4'b0???: begin // core units - each 0x40 (16 regs) long, [9:6] decides about which unit + interc_slaves_req[speriph_slave.add[9:6]] = 1'b1; + speriph_slave_gnt_mux = periph_int_bus_core_gnt[speriph_slave.add[9:6]]; + end + 4'b10??: begin // hw barrier - each 0x20 (8 regs) long, [8:5] decides about which unit + interc_slaves_req[NB_CORES+speriph_slave.add[8:5]] = 1'b1; + speriph_slave_gnt_mux = periph_int_bus_barr_gnt[speriph_slave.add[8:5]]; + end + 4'b110?: begin // external sw event triggering + interc_slaves_req[NB_CORES+NB_BARR] = 1'b1; + speriph_slave_gnt_mux = periph_int_bus_master[NB_CORES+NB_BARR].gnt; + end + 4'b1110: begin // soc event FIFO + interc_slaves_req[NB_CORES+NB_BARR+1] = 1'b1; + speriph_slave_gnt_mux = periph_int_bus_master[NB_CORES+NB_BARR+1].gnt; + end + 4'b1111: begin // inter-cluster FIFOs + interc_slaves_req[NB_CORES+NB_BARR+2] = 1'b1; + speriph_slave_gnt_mux = periph_int_bus_master[NB_CORES+NB_BARR+2].gnt; + end + endcase + end + end + + // delayed muxing of correct response + always_comb begin + + // default: silence response channel + speriph_slave.r_valid = 1'b0; + speriph_slave.r_rdata = '0; + + if ( speriph_slave_req_del ) begin + casex ( interc_ip_sel_SP[5:2] ) + 4'b0???: begin // core units + speriph_slave.r_valid = periph_int_bus_core_rvalid[interc_ip_sel_SP[4:1]]; + speriph_slave.r_rdata = periph_int_bus_core_rdata[interc_ip_sel_SP[4:1]]; + end + 4'b10??: begin // barrier units + speriph_slave.r_valid = periph_int_bus_barr_rvalid[interc_ip_sel_SP[3:0]]; + speriph_slave.r_rdata = periph_int_bus_barr_rdata[interc_ip_sel_SP[3:0]]; + end + 4'b110?: begin // external sw event trigger + speriph_slave.r_valid = periph_int_bus_master[NB_CORES+NB_BARR].r_valid; + speriph_slave.r_rdata = periph_int_bus_master[NB_CORES+NB_BARR].r_rdata; + end + 4'b1110: begin // soc event FIFO + speriph_slave.r_valid = periph_int_bus_master[NB_CORES+NB_BARR+1].r_valid; + speriph_slave.r_rdata = periph_int_bus_master[NB_CORES+NB_BARR+1].r_rdata; + end + 4'b1111: begin // inter-cluster FIFOs + speriph_slave.r_valid = periph_int_bus_master[NB_CORES+NB_BARR+2].r_valid; + speriph_slave.r_rdata = periph_int_bus_master[NB_CORES+NB_BARR+2].r_rdata; + end + default: begin + speriph_slave.r_valid = 1'b0; + speriph_slave.r_rdata = '0; + end + endcase + end + + end + + // delay for interconnect signals + always_ff @(posedge clk_i, negedge rst_ni) + begin + if (~rst_ni) begin + speriph_slave.r_id <= '0; + interc_ip_sel_SP <= '0; + speriph_slave_req_del <= 1'b0; + end + else + begin + speriph_slave_req_del <= speriph_slave.req; + if ( speriph_slave_update ) + begin + speriph_slave.r_id <= speriph_slave.id; + interc_ip_sel_SP <= interc_ip_sel_SN; + end + end + end + +endmodule // event_unit_interface_mux diff --git a/hw/deps/event_unit_flex/event_unit_top.sv b/hw/deps/event_unit_flex/event_unit_top.sv new file mode 100644 index 0000000..5b32d84 --- /dev/null +++ b/hw/deps/event_unit_flex/event_unit_top.sv @@ -0,0 +1,338 @@ +// Copyright 2018 ETH Zurich and 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. + +module event_unit_top +#( + parameter NB_CORES = 8, + parameter NB_SW_EVT = 8, + parameter NB_BARR = 8, + parameter NB_HW_MUT = 1, + parameter MUTEX_MSG_W = 32, + parameter DISP_FIFO_DEPTH = 8, + parameter PER_ID_WIDTH = 9, + parameter EVNT_WIDTH = 8, + parameter SOC_FIFO_DEPTH = 8 +) +( + // clock and reset + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + + // all kinds of cluster internal events, split into different signals for readability + input logic [NB_CORES-1:0][3:0] acc_events_i, + input logic [NB_CORES-1:0][1:0] dma_events_i, + input logic [NB_CORES-1:0][1:0] timer_events_i, + // usually much less than 32 bit, only for flexibility for different chips + input logic [NB_CORES-1:0][31:0] cluster_events_i, + + output logic [NB_CORES-1:0] core_irq_req_o, + output logic [NB_CORES-1:0][4:0] core_irq_id_o, + input logic [NB_CORES-1:0] core_irq_ack_i, + input logic [NB_CORES-1:0][4:0] core_irq_ack_id_i, + + input logic [NB_CORES-1:0] core_busy_i, + output logic [NB_CORES-1:0] core_clock_en_o, + + // bus slave connections - periph bus and eu_direct_link + XBAR_PERIPH_BUS.Slave speriph_slave, + XBAR_PERIPH_BUS.Slave eu_direct_link[NB_CORES-1:0], + + // soc periph events + input logic soc_periph_evt_valid_i, + output logic soc_periph_evt_ready_o, + input logic [EVNT_WIDTH-1:0] soc_periph_evt_data_i, + + // message bus connections - dummy implementation + MESSAGE_BUS.Master message_master + + ); + + // event lines from soc periph fifo and inter-cluster event dispatch + logic soc_periph_event; + + // sw events and target core mask from each core + logic [NB_SW_EVT-1:0][NB_CORES-1:0] core_sw_events; + logic [NB_CORES-1:0][NB_SW_EVT-1:0] core_sw_events_transp; + logic [NB_CORES-1:0][NB_CORES-1:0] core_sw_events_mask; + logic [NB_CORES-1:0][NB_CORES-1:0] core_sw_events_mask_transp; + logic [NB_CORES-1:0][7:0] sw_events_combined; + // sw events from interconnect + logic [NB_CORES-1:0][NB_SW_EVT-1:0] interc_int_events_sw; + + + // cluster internal event matrix: sw, barr and other cluster events + logic [NB_CORES-1:0][31:0] cluster_int_events; + + // link between hw barrier and eu core units to fast trigger barriers + logic [NB_CORES-1:0][NB_BARR-1:0] hw_barr_trigger; + logic [NB_BARR-1:0][NB_CORES-1:0] hw_barr_trigger_transp; + + // intermediate signals for assigning + logic [NB_CORES-1:0][NB_SW_EVT-1:0] cluster_int_events_sw; + logic [NB_CORES-1:0][NB_BARR-1:0] cluster_int_events_barr; + logic [NB_BARR-1:0][NB_CORES-1:0] cluster_int_events_barr_transp; + logic [NB_CORES-1:0] cluster_int_events_barr_red; + logic [NB_CORES-1:0][NB_HW_MUT-1:0] cluster_int_events_mutex; + logic [NB_HW_MUT-1:0][NB_CORES-1:0] cluster_int_events_mutex_transp; + logic [NB_CORES-1:0] cluster_int_events_mutex_red; + logic [NB_CORES-1:0] cluster_int_events_dispatch; + + // hw mutex related signals + logic [NB_CORES-1:0][NB_HW_MUT-1:0] mutex_lock_req; + logic [NB_HW_MUT-1:0][NB_CORES-1:0] mutex_lock_req_transp; + logic [NB_CORES-1:0][NB_HW_MUT-1:0] mutex_unlock_req; + logic [NB_HW_MUT-1:0][NB_CORES-1:0] mutex_unlock_req_transp; + + logic [NB_HW_MUT-1:0][MUTEX_MSG_W-1:0] mutex_msg_rdata; + logic [NB_CORES-1:0][NB_HW_MUT-1:0][MUTEX_MSG_W-1:0] mutex_msg_wdata; + logic [NB_HW_MUT-1:0][MUTEX_MSG_W-1:0][NB_CORES-1:0] mutex_msg_wdata_transp; + logic [NB_HW_MUT-1:0][MUTEX_MSG_W-1:0] mutex_msg_wdata_transp_red; + + // hw dispatch related signals + logic [NB_CORES-1:0] disp_pop_req; + logic [NB_CORES-1:0] disp_pop_ack; + logic [NB_CORES-1:0][31:0] disp_value; + + logic [NB_CORES-1:0] disp_w_req; + logic [NB_CORES-1:0][31:0] disp_w_data; + logic [NB_CORES-1:0][1:0] disp_reg_sel; + + // periph bus links to all subcomponents + XBAR_PERIPH_BUS periph_int_bus[NB_CORES+NB_BARR+2:0](); + + // demux periph bus to eu_core and barrier units + XBAR_PERIPH_BUS demux_int_bus_core[NB_CORES-1:0](); + XBAR_PERIPH_BUS demux_int_bus_barrier[NB_CORES*NB_BARR-1:0](); + + genvar I,J,K; + + // combination of trigger sources for sw events + generate + for ( I = 0; I < NB_CORES; I++ ) begin : SW_EVENTS_COMBINE + always_comb begin + sw_events_combined[I][7:0] = '0; + sw_events_combined[I][NB_SW_EVT-1:0] = cluster_int_events_sw[I] | interc_int_events_sw[I]; + end + end + endgenerate + + cluster_event_map #( + .NB_CORES ( NB_CORES ) ) + cluster_event_map_i ( + .sw_events_i ( sw_events_combined ), + .barrier_events_i ( cluster_int_events_barr_red ), + .mutex_events_i ( cluster_int_events_mutex_red ), + .dispatch_events_i ( cluster_int_events_dispatch ), + .periph_fifo_event_i ( soc_periph_event ), + + .acc_events_i ( acc_events_i ), + .dma_events_i ( dma_events_i ), + .timer_events_i ( timer_events_i ), + .cluster_events_i ( cluster_events_i ), + + .events_mapped_o ( cluster_int_events ) + ); + + // combinational calculation of every sw event line for every core + // transposing and combinational reduction of barrier and mutex events and signals + generate + for ( I=0; I < NB_CORES; I++ ) begin : EU_LOOP_CORE + assign cluster_int_events_barr_red[I] = |cluster_int_events_barr[I]; + assign cluster_int_events_mutex_red[I] = |cluster_int_events_mutex[I]; + + for ( J=0; J < NB_BARR; J++ ) begin : EU_LOOP_HW_BARR_TRANSP + assign hw_barr_trigger_transp[J][I] = hw_barr_trigger[I][J]; + assign cluster_int_events_barr[I][J] = cluster_int_events_barr_transp[J][I]; + end + + for ( J=0; J < NB_SW_EVT; J++ ) begin : EU_LOOP_SW_EVTS_TRANSP + assign core_sw_events[J][I] = core_sw_events_transp[I][J]; + end + + for ( J=0; J < NB_CORES; J++ ) begin : EU_LOOP_SW_EVTS_MASK_TRANSP + assign core_sw_events_mask[J][I] = core_sw_events_mask_transp[I][J]; + end + + for ( J=0; J < NB_SW_EVT; J++ ) begin : EU_LOOP_SW_EVTS_MASK_APPLY + assign cluster_int_events_sw[I][J] = (core_sw_events[J][NB_CORES-1:0] & core_sw_events_mask[I][NB_CORES-1:0]) != '0; + end + + for ( J=0; J < NB_HW_MUT; J++ ) begin : EU_LOOP_HW_MUTEX_TRANSP + assign cluster_int_events_mutex[I][J] = cluster_int_events_mutex_transp[J][I]; + assign mutex_lock_req_transp[J][I] = mutex_lock_req[I][J]; + assign mutex_unlock_req_transp[J][I] = mutex_unlock_req[I][J]; + for ( K=0; K < MUTEX_MSG_W; K++ ) begin : EU_LOOP_HW_MUTEX_TRANSP_MSG + assign mutex_msg_wdata_transp[J][K][I] = mutex_msg_wdata[I][J][K]; + end + end + end + + for ( J=0; J < NB_HW_MUT; J++ ) begin : EU_LOOP_HW_MUTEX_REDUCE_STG1 + for ( K=0; K < MUTEX_MSG_W; K++ ) begin : EU_LOOP_HW_MUTEX_REDUCE_STG2 + assign mutex_msg_wdata_transp_red[J][K] = |mutex_msg_wdata_transp[J][K]; + end + end + endgenerate + + // dummy assignments + assign periph_int_bus[NB_CORES+NB_BARR+2].gnt = 1'b0; + assign periph_int_bus[NB_CORES+NB_BARR+2].r_opc = 1'b0; + assign periph_int_bus[NB_CORES+NB_BARR+2].r_valid = 1'b0; + assign periph_int_bus[NB_CORES+NB_BARR+2].r_rdata = '0; + assign periph_int_bus[NB_CORES+NB_BARR+2].r_id = '0; + + // will become the master port for cluster messages + assign message_master.wdata = '0; + assign message_master.req = 1'b0; + assign message_master.wen = 1'b1; + assign message_master.add = '0; + assign message_master.be = '0; + assign message_master.id = '0; + + + event_unit_interface_mux #( + .NB_CORES ( NB_CORES ), + .NB_BARR ( NB_BARR ) ) + event_unit_interface_mux_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .speriph_slave ( speriph_slave ), + .periph_int_bus_master ( periph_int_bus ), + + .demux_slave ( eu_direct_link ), + .demux_int_bus_core_master ( demux_int_bus_core ), + .demux_int_bus_barrier_master ( demux_int_bus_barrier ) + ); + + + interc_sw_evt_trig #( + .NB_CORES ( NB_CORES ), + .NB_SW_EVT ( NB_SW_EVT ) ) + interc_sw_evt_trig_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .sw_events_o ( interc_int_events_sw ), + + .periph_int_bus_slave ( periph_int_bus[NB_CORES+NB_BARR] ) + ); + + assign soc_periph_event = '0; + + generate + for ( I=0; I < NB_CORES; I++ ) begin : EU_CORE + event_unit_core #( + .NB_CORES ( NB_CORES ), + .NB_SW_EVT ( NB_SW_EVT ), + .NB_BARR ( NB_BARR ), + .NB_HW_MUT ( NB_HW_MUT ), + .MUTEX_MSG_W ( MUTEX_MSG_W ) ) + event_unit_core_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_mode_i ( test_mode_i ), + + .master_event_lines_i ( cluster_int_events[I] ), + + .core_sw_events_o ( core_sw_events_transp[I][NB_SW_EVT-1:0] ), + .core_sw_events_mask_o ( core_sw_events_mask_transp[I][NB_CORES-1:0] ), + + .hw_barr_id_o ( hw_barr_trigger[I][NB_BARR-1:0] ), + + .mutex_rd_req_o ( mutex_lock_req[I] ), + .mutex_wr_req_o ( mutex_unlock_req[I] ), + .mutex_msg_wdata_o ( mutex_msg_wdata[I] ), + .mutex_msg_rdata_i ( mutex_msg_rdata ), + + .dispatch_pop_req_o ( disp_pop_req[I] ), + .dispatch_pop_ack_o ( disp_pop_ack[I] ), + .dispatch_value_i ( disp_value[I] ), + + .dispatch_w_req_o ( disp_w_req[I] ), + .dispatch_w_data_o ( disp_w_data[I] ), + .dispatch_reg_sel_o ( disp_reg_sel[I] ), + + .core_irq_req_o ( core_irq_req_o[I] ), + .core_irq_id_o ( core_irq_id_o[I] ), + .core_irq_ack_i ( core_irq_ack_i[I] ), + .core_irq_ack_id_i ( core_irq_ack_id_i[I] ), + + .core_busy_i ( core_busy_i[I] ), + .core_clock_en_o ( core_clock_en_o[I] ), + + .periph_int_bus_slave ( periph_int_bus[I] ), + .eu_direct_link_slave ( demux_int_bus_core[I] ) + ); + end + endgenerate + + + // instantiation of NB_BARR barrier units + generate + for ( I = 0; I < NB_BARR; I++ ) begin : HW_BARRIER_UNIT + hw_barrier_unit #( + .NB_CORES ( NB_CORES ) ) + hw_barrier_unit_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .barrier_trigger_core_i ( hw_barr_trigger_transp[I] ), + .barrier_status_o ( ), + .barrier_events_o ( cluster_int_events_barr_transp[I] ), + + .demux_bus_slaves ( demux_int_bus_barrier[(I+1)*NB_CORES-1:I*NB_CORES] ), + .periph_bus_slave ( periph_int_bus[NB_CORES+I] ) + ); + end + endgenerate + + + generate + for ( I=0; I < NB_HW_MUT; I++ ) begin : HW_MUT + hw_mutex_unit #( + .NB_CORES ( NB_CORES ), + .MUTEX_MSG_W ( MUTEX_MSG_W ) ) + hw_mutex_unit_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .lock_req_i ( mutex_lock_req_transp[I] ), + .unlock_req_i ( mutex_unlock_req_transp[I] ), + + .mutex_msg_wdata_i ( mutex_msg_wdata_transp_red[I] ), + .mutex_msg_rdata_o ( mutex_msg_rdata[I] ), + + .mutex_event_o ( cluster_int_events_mutex_transp[I] ) + ); + end + endgenerate + + hw_dispatch #( + .NB_CORES ( NB_CORES ), + .FIFO_DEPTH ( DISP_FIFO_DEPTH ) ) + hw_dispatch_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .pop_req_i ( disp_pop_req ), + .pop_ack_i ( disp_pop_ack ), + + .dispatch_value_o ( disp_value ), + + .w_req_i ( disp_w_req ), + .w_data_i ( disp_w_data ), + .reg_sel_i ( disp_reg_sel ), + + .dispatch_event_o ( cluster_int_events_dispatch ) + ); + +endmodule // event_unit_top diff --git a/hw/deps/event_unit_flex/hw_barrier_unit.sv b/hw/deps/event_unit_flex/hw_barrier_unit.sv new file mode 100644 index 0000000..2ef91d3 --- /dev/null +++ b/hw/deps/event_unit_flex/hw_barrier_unit.sv @@ -0,0 +1,225 @@ +// Copyright 2018 ETH Zurich and 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. + +module hw_barrier_unit +#( + parameter NB_CORES = 4 +) +( + // clock and reset + input logic clk_i, + input logic rst_ni, + + // trigger inputs from all cores + input logic [NB_CORES-1:0] barrier_trigger_core_i, + // direct output of status reg for summary status computation in top level + output logic [NB_CORES-1:0] barrier_status_o, + // generated event, masked with target core mask -> to eu_matrix + output logic [NB_CORES-1:0] barrier_events_o, + + // demuxed slave ports from each core + XBAR_PERIPH_BUS.Slave demux_bus_slaves[NB_CORES-1:0], + // single plug from periph interconnect with pre-decoded requests + XBAR_PERIPH_BUS.Slave periph_bus_slave + + ); + + // actual registers + logic [NB_CORES-1:0] trigger_mask_DP, trigger_mask_DN; + logic [NB_CORES-1:0] target_mask_DP, target_mask_DN; + logic [NB_CORES-1:0] trigger_status_DP, trigger_status_DN; + + // combinational signals that need to be ORed in the end + logic [NB_CORES-1:0][NB_CORES-1:0] demux_wdata_trigger_mask, demux_wdata_target_mask; + logic [NB_CORES-1:0][NB_CORES-1:0] demux_wdata_trigger_mask_transp, demux_wdata_target_mask_transp; + logic [NB_CORES-1:0] demux_wdata_trigger_mask_red, demux_wdata_target_mask_red; + logic [NB_CORES+1:0][NB_CORES-1:0] trigger_matrix; // first NB_CORES rows for demuxed ports, then interc, then core_trigger + logic [NB_CORES-1:0][NB_CORES+1:0] trigger_matrix_transp; + logic [NB_CORES-1:0] trigger_matrix_red; + + logic [NB_CORES-1:0] demux_we_trigger_mask, demux_we_target_mask; + logic interc_we_trigger_mask, interc_we_target_mask; + logic [NB_CORES-1:0] demux_bus_req_all; + + // delayed read requests + logic [NB_CORES-1:0][1:0] demux_read_req_del_SP, demux_read_req_del_SN; + logic [1:0] interc_read_req_del_SP, interc_read_req_del_SN; + + logic interc_gnt_del_SP, interc_gnt_del_SN; + logic [NB_CORES-1:0] write_conflict; + + logic barrier_matched; + + genvar I,J; + + // calculation of outputs + assign barrier_status_o = trigger_status_DP; + assign barrier_matched = (trigger_mask_DP != '0) && (trigger_status_DP == trigger_mask_DP); + assign barrier_events_o = (barrier_matched == 1'b1) ? target_mask_DP : '0; + + // bus logic for demuxed ports - replicated NB_CORES times + generate + for ( I = 0; I < NB_CORES; I++ ) begin + // read/write logic for demuxed ports + always_comb begin + demux_we_trigger_mask[I] = 1'b0; + demux_we_target_mask[I] = 1'b0; + demux_read_req_del_SN[I] = 2'b00; + + demux_bus_slaves[I].r_rdata = '0; + demux_bus_slaves[I].r_opc = 1'b0; + demux_bus_slaves[I].r_id = '0; + demux_bus_slaves[I].gnt = 1'b1; + demux_bus_slaves[I].r_valid = 1'b1; + + trigger_matrix[I] = '0; + + if ( demux_bus_slaves[I].req == 1'b1 ) begin + if ( demux_bus_slaves[I].wen == 1'b1 ) begin + // minimal encoding of requested read data + case ( demux_bus_slaves[I].add[4:2] ) + 3'b000: demux_read_req_del_SN[I] = 2'b01; + 3'b001: demux_read_req_del_SN[I] = 2'b10; + 3'b011: demux_read_req_del_SN[I] = 2'b11; + endcase + end + else begin + case ( demux_bus_slaves[I].add[4:2] ) + 3'b000: demux_we_trigger_mask[I] = 1'b1; + 3'b011: demux_we_target_mask[I] = 1'b1; + 3'b100: trigger_matrix[I] = demux_bus_slaves[I].wdata[NB_CORES-1:0]; + endcase + end + end + // evaluate delayed read request + case ( demux_read_req_del_SP[I] ) + 2'b01: demux_bus_slaves[I].r_rdata[NB_CORES-1:0] = trigger_mask_DP; + 2'b10: demux_bus_slaves[I].r_rdata[NB_CORES-1:0] = trigger_status_DP; + 2'b11: demux_bus_slaves[I].r_rdata[NB_CORES-1:0] = target_mask_DP; + endcase + end + + // activation condition for read address + assign demux_bus_req_all[I] = demux_bus_slaves[I].req; + + // each bit represents a write collision between a demux and the interconnect port + assign write_conflict[I] = ( (demux_bus_slaves[I].req == 1'b1) && (periph_bus_slave.req == 1'b1) ) && + ( (demux_bus_slaves[I].wen == 1'b0) && (periph_bus_slave.wen == 1'b0) ) && + ( demux_bus_slaves[I].add == periph_bus_slave.add ); + // assignment of write data + assign demux_wdata_trigger_mask[I] = (demux_we_trigger_mask[I] == 1'b1) ? demux_bus_slaves[I].wdata[NB_CORES-1:0] : '0; + assign demux_wdata_target_mask[I] = (demux_we_target_mask[I] == 1'b1) ? demux_bus_slaves[I].wdata[NB_CORES-1:0] : '0; + for ( J = 0; J < NB_CORES; J++ ) begin + assign demux_wdata_trigger_mask_transp[J][I] = demux_wdata_trigger_mask[I][J]; + assign demux_wdata_target_mask_transp[J][I] = demux_wdata_target_mask[I][J]; + end + assign demux_wdata_trigger_mask_red[I] = |demux_wdata_trigger_mask_transp[I]; + assign demux_wdata_target_mask_red[I] = |demux_wdata_target_mask_transp[I]; + end + endgenerate + + // protocol logic for interconnect port - stall interconnect port on write conflict + assign interc_gnt_del_SN = periph_bus_slave.req && (|write_conflict == 1'b0); + assign periph_bus_slave.gnt = interc_gnt_del_SN; + assign periph_bus_slave.r_valid = interc_gnt_del_SP; + assign periph_bus_slave.r_opc = 1'b0; + assign periph_bus_slave.r_id = '0; + + // read/write logic for interconnect port + always_comb begin + interc_we_trigger_mask = 1'b0; + interc_we_target_mask = 1'b0; + interc_read_req_del_SN = 2'b0; + periph_bus_slave.r_rdata = '0; + trigger_matrix[NB_CORES] = '0; + + if ( periph_bus_slave.req == 1'b1 ) begin + if ( periph_bus_slave.wen == 1'b1 ) begin + case ( periph_bus_slave.add[4:2] ) + 3'b000: interc_read_req_del_SN = 2'b01; + 3'b001: interc_read_req_del_SN = 2'b10; + 3'b011: interc_read_req_del_SN = 2'b11; + endcase + end + else begin + case ( periph_bus_slave.add[4:2] ) + 3'b000: interc_we_trigger_mask = 1'b1; + 3'b011: interc_we_target_mask = 1'b1; + 3'b100: trigger_matrix[NB_CORES] = periph_bus_slave.wdata[NB_CORES-1:0]; + endcase + end + end + // evaluate delayed read request + case ( interc_read_req_del_SP ) + 2'b01: periph_bus_slave.r_rdata[NB_CORES-1:0] = trigger_mask_DP; + 2'b10: periph_bus_slave.r_rdata[NB_CORES-1:0] = trigger_status_DP; + 2'b11: periph_bus_slave.r_rdata[NB_CORES-1:0] = target_mask_DP; + endcase + end + + // combination of all trigger signals and status clear logic + assign trigger_matrix[NB_CORES+1] = barrier_trigger_core_i; + generate + for ( I = 0; I < NB_CORES; I++ ) begin + for ( J = 0; J < NB_CORES+2; J++ ) assign trigger_matrix_transp[I][J] = trigger_matrix[J][I]; + assign trigger_matrix_red[I] = |trigger_matrix_transp[I]; + end + endgenerate + assign trigger_status_DN = (barrier_matched == 1'b1) ? '0 : (trigger_status_DP | trigger_matrix_red); + + // summarization of write data for trigger and target masks + always_comb begin + trigger_mask_DN = trigger_mask_DP; + target_mask_DN = target_mask_DP; + + if ( demux_we_trigger_mask != '0 ) + trigger_mask_DN = demux_wdata_trigger_mask_red; + else if ( interc_we_trigger_mask == 1'b1 ) + trigger_mask_DN = periph_bus_slave.wdata[NB_CORES-1:0]; + + if ( demux_we_target_mask != '0 ) + target_mask_DN = demux_wdata_target_mask_red; + else if ( interc_we_target_mask == 1'b1 ) + target_mask_DN = periph_bus_slave.wdata[NB_CORES-1:0]; + end + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if ( rst_ni == 1'b0 ) + begin + trigger_mask_DP <= '0; + target_mask_DP <= '0; + trigger_status_DP <= '0; + demux_read_req_del_SP <= '0; + interc_read_req_del_SP <= '0; + interc_gnt_del_SP <= '0; + end + else + begin + trigger_mask_DP <= trigger_mask_DN; + target_mask_DP <= target_mask_DN; + + if((barrier_matched == 1'b1)) + trigger_status_DP <= '0; + else if(|trigger_matrix_red) + trigger_status_DP <= (trigger_status_DP | trigger_matrix_red); + + + if ( |demux_bus_req_all ) begin + demux_read_req_del_SP <= demux_read_req_del_SN; + end + if ( periph_bus_slave.req ) begin + interc_read_req_del_SP <= interc_read_req_del_SN; + interc_gnt_del_SP <= interc_gnt_del_SN; + end + end + end + +endmodule // hw_barrier_unit diff --git a/hw/deps/event_unit_flex/hw_dispatch.sv b/hw/deps/event_unit_flex/hw_dispatch.sv new file mode 100644 index 0000000..7f2a19d --- /dev/null +++ b/hw/deps/event_unit_flex/hw_dispatch.sv @@ -0,0 +1,179 @@ +// Copyright 2018 ETH Zurich and 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. + +module hw_dispatch +#( + parameter NB_CORES = 4, + parameter FIFO_DEPTH = 4 +) +( + // clock and reset + input logic clk_i, + input logic rst_ni, + + // pop request and ack from each core + input logic [NB_CORES-1:0] pop_req_i, + input logic [NB_CORES-1:0] pop_ack_i, + // current read data for each core + output logic [NB_CORES-1:0][31:0] dispatch_value_o, + + // value push and team configuration by master + input logic [NB_CORES-1:0] w_req_i, + input logic [NB_CORES-1:0][31:0] w_data_i, + input logic [NB_CORES-1:0][1:0] reg_sel_i, + + // event output to flag availability of a value to a specific core + output logic [NB_CORES-1:0] dispatch_event_o + +); + + // registers + logic [FIFO_DEPTH-1:0][31:0] dispatch_fifo_DP, dispatch_fifo_DN; + + logic [NB_CORES-1:0] core_set_conf_DP, core_set_conf_DN; + logic [NB_CORES-1:0] req_in_progr_SP, req_in_progr_SN; + logic [NB_CORES-1:0] incr_rptr_del_SP, incr_rptr_del_SN; + + logic [FIFO_DEPTH-1:0][NB_CORES-1:0] core_set_stat_DP, core_set_stat_DN; + + logic [NB_CORES-1:0][$clog2(FIFO_DEPTH)-1:0] read_ptr_DP, read_ptr_DN; + logic [$clog2(FIFO_DEPTH)-1:0] write_ptr_DP, write_ptr_DN; + + // internal signals + logic [NB_CORES-1:0][1:0][31:0] w_data_int; + logic [1:0][31:0][NB_CORES-1:0] w_data_int_transp; + logic [1:0][31:0] w_data_int_red; + logic [1:0][NB_CORES-1:0] w_req_int; + + logic [NB_CORES-1:0][FIFO_DEPTH-1:0] clr_core_stat; + logic [FIFO_DEPTH-1:0][NB_CORES-1:0] clr_core_stat_transp; + + genvar I,J,K; + + // workaround for language limitation + generate + for (I=0; I CH0; 1 --> CH1 + always_comb + begin + request_o = request_ch0_i | request_ch1_i; + ch_selector = ~request_ch0_i | ( Flag_i & request_ch1_i ); + grant_ch0_o = (( request_ch0_i & ~request_ch1_i) | ( request_ch0_i & ~Flag_i)) & grant_i; + grant_ch1_o = ((~request_ch0_i & request_ch1_i) | ( request_ch1_i & Flag_i)) & grant_i; + case(ch_selector) + 1'b1: begin address_o = address_ch1_i; UID_o = UID_ch1_i; end + 1'b0: begin address_o = address_ch0_i; UID_o = UID_ch0_i; end + endcase + end + +endmodule diff --git a/hw/deps/icache-intc/RoutingBlock_Req_icache_intc.sv b/hw/deps/icache-intc/RoutingBlock_Req_icache_intc.sv new file mode 100644 index 0000000..a50a058 --- /dev/null +++ b/hw/deps/icache-intc/RoutingBlock_Req_icache_intc.sv @@ -0,0 +1,94 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: icache_intc // +// Module Name: RoutingBlock_Req_icache_intc.sv // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: Block that embeds the arbitration/routing tree and the // +// decoding logic for the response coming from the memory side // +// // +// Revision v0.1 - 16/02/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +module RoutingBlock_Req_icache_intc +#( + parameter int unsigned ADDRESS_WIDTH = 32, + parameter int unsigned N_CORES = 16, + parameter int unsigned UID_WIDTH = N_CORES, + parameter int unsigned N_CACHE_BANKS = 8, + parameter int unsigned DATA_WIDTH = 32 +) +( + input logic clk_i, + input logic rst_ni, + + output logic request_o, + output logic [ADDRESS_WIDTH-1:0] address_o, + output logic [UID_WIDTH-1:0] UID_o, + input logic grant_i, + + input logic [N_CORES-1:0] request_i, + input logic [N_CORES-1:0][ADDRESS_WIDTH-1:0] address_i, + input logic [N_CORES-1:0][UID_WIDTH-1:0] UID_i, + output logic [N_CORES-1:0] grant_o, + + input logic response_i, + input logic [UID_WIDTH-1:0] response_UID_i, + output logic [N_CORES-1:0] response_o +); + assign response_o = {UID_WIDTH{response_i}} & response_UID_i; + + generate + if(N_CORES > 1) + begin : MULTI_CORE + DistributedArbitrationNetwork_Req_icache_intc #( .ADDRESS_WIDTH (ADDRESS_WIDTH), .UID_WIDTH(UID_WIDTH), .N_CORES(N_CORES) ) DistributedArbitrationNetwork_Req_icache_intc_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .request_i ( request_i ), + .address_i ( address_i ), + .UID_i ( UID_i ), + .grant_o ( grant_o ), + .request_o ( request_o ), + .address_o ( address_o ), + .UID_o ( UID_o ), + .grant_i ( grant_i ) + ); + end + else + begin : SINGLE_CORE + assign request_o = request_i; + assign address_o = address_i; + assign UID_o = UID_i; + assign grant_o = grant_i; + end + endgenerate + +endmodule diff --git a/hw/deps/icache-intc/RoutingBlock_Resp_icache_intc.sv b/hw/deps/icache-intc/RoutingBlock_Resp_icache_intc.sv new file mode 100644 index 0000000..b98c01f --- /dev/null +++ b/hw/deps/icache-intc/RoutingBlock_Resp_icache_intc.sv @@ -0,0 +1,86 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: icache_intc // +// Module Name: RoutingBlock_Resp_icache_intc.sv // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: Block that embeds the routing tree for the response side // +// and the decoding logic for the request coming from the // +// fetch side. // +// // +// Revision v0.1 - 16/02/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +module RoutingBlock_Resp_icache_intc +#( + parameter int unsigned UID_WIDTH = 8, + parameter int unsigned UID = 1, + parameter int unsigned N_CACHE_BANKS = 16, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned DEST_WIDTH = 1 +) +( + input logic [N_CACHE_BANKS-1:0] response_i, + input logic [N_CACHE_BANKS-1:0][DATA_WIDTH-1:0] read_data_i, + + output logic response_o, + output logic [DATA_WIDTH-1:0] read_data_o, + + input logic request_i, + input logic [DEST_WIDTH-1:0] destination_i, + output logic grant_o, + + output logic [N_CACHE_BANKS-1:0] request_o, + input logic [N_CACHE_BANKS-1:0] grant_i, + output logic [UID_WIDTH-1:0] UID_o +); + typedef logic [UID_WIDTH-1:0] logic_uid_type; + + DistributedArbitrationNetwork_Resp_icache_intc #( .N_CACHE_BANKS(N_CACHE_BANKS), .DATA_WIDTH(DATA_WIDTH) ) DistributedArbitrationNetwork_Resp_icache_intc_i + ( + .response_i ( response_i ), + .read_data_i ( read_data_i ), + .response_o ( response_o ), + .read_data_o ( read_data_o ) + ); + + + // Decoding Logic + always @(*) + begin + request_o = '0; + request_o [destination_i] = request_i; + grant_o = grant_i[destination_i]; + UID_o = logic_uid_type'(UID); + end + + + +endmodule diff --git a/hw/deps/icache-intc/icache_intc.sv b/hw/deps/icache-intc/icache_intc.sv new file mode 100644 index 0000000..2d36a1c --- /dev/null +++ b/hw/deps/icache-intc/icache_intc.sv @@ -0,0 +1,170 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: icache_intc // +// Module Name: icache_intc.sv // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: top_level, that instanciates the routing and response // +// blocks. It is fully parametric, and it is possible to // +// to have N+M Channels where M and N are integers, powerof 2 // +// fair arbitration is provided through distrubuted Round // +// robin arbiters. // +// // +// Revision: // +// Revision v0.1 - 16/02/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + +module icache_intc +#( + parameter ADDRESS_WIDTH = 32, + parameter N_CORES = 8, + parameter N_AUX_CHANNEL = 0, + parameter UID_WIDTH = N_CORES+N_AUX_CHANNEL, + parameter DATA_WIDTH = 32, + parameter N_CACHE_BANKS = 16, + parameter OFFSET = $clog2(DATA_WIDTH)-3 +) +( + input logic clk_i, + input logic rst_ni, + + input logic [N_CORES+N_AUX_CHANNEL-1:0] request_i, + input logic [N_CORES+N_AUX_CHANNEL-1:0][ADDRESS_WIDTH-1:0] address_i, + output logic [N_CORES+N_AUX_CHANNEL-1:0] grant_o, + output logic [N_CORES+N_AUX_CHANNEL-1:0] response_o, + output logic [N_CORES+N_AUX_CHANNEL-1:0][DATA_WIDTH-1:0] read_data_o, + + output logic [N_CACHE_BANKS-1:0] request_o, + output logic [N_CACHE_BANKS-1:0][ADDRESS_WIDTH-1:0] address_o, + output logic [N_CACHE_BANKS-1:0][UID_WIDTH-1:0] UID_o, + input logic [N_CACHE_BANKS-1:0] grant_i, + + input logic [N_CACHE_BANKS-1:0][DATA_WIDTH-1:0] read_data_i, + input logic [N_CACHE_BANKS-1:0] response_i, + input logic [N_CACHE_BANKS-1:0][UID_WIDTH-1:0] response_UID_i +); + localparam DEST_WIDTH = (N_CACHE_BANKS == 1) ? 1'b1 : $clog2(N_CACHE_BANKS); + + logic [N_CORES+N_AUX_CHANNEL-1:0][UID_WIDTH-1:0] UID_int; + logic [N_CORES+N_AUX_CHANNEL-1:0] grant_from_CB [N_CACHE_BANKS-1:0]; + + logic [N_CACHE_BANKS-1:0] request_from_CORE [N_CORES+N_AUX_CHANNEL-1:0]; + logic [N_CORES+N_AUX_CHANNEL-1:0] response_from_CB [N_CACHE_BANKS-1:0]; + logic [N_CACHE_BANKS-1:0] response_to_CORE [N_CORES+N_AUX_CHANNEL-1:0]; + logic [N_CORES+N_AUX_CHANNEL-1:0] request_to_CB [N_CACHE_BANKS-1:0]; + logic [N_CACHE_BANKS-1:0] grant_to_CORE [N_CORES+N_AUX_CHANNEL-1:0]; + logic [N_CORES+N_AUX_CHANNEL-1:0][DEST_WIDTH-1:0] destination; + + genvar j,k; + generate + for (k=0; k TAG SCM Unified PORT + output logic SCM_TAG_write_req_o, + output logic [SCM_ADDR_WIDTH-1:0] SCM_TAG_write_addr_o, + output logic [$clog2(NB_BANKS)-1:0] SCM_TAG_write_dest_o, + output logic [SCM_TAG_WIDTH-1:0] SCM_TAG_write_wdata_o, + output logic [NB_WAYS-1:0] SCM_TAG_write_way_o, + + // interface with WRITE PORT --> DATA SCM Unified PORT + output logic SCM_DATA_write_req_o, + output logic [SCM_ADDR_WIDTH-1:0] SCM_DATA_write_addr_o, // double number of rows with respect TAG SCM ARRAY + output logic [$clog2(NB_BANKS)-1:0] SCM_DATA_write_dest_o, + output logic [SCM_DATA_WIDTH-1:0] SCM_DATA_write_wdata_o, + output logic [NB_WAYS-1:0] SCM_DATA_write_way_o, + + //AXI read address bus ------------------------------------------- + output logic [AXI_ID-1:0] axi_master_arid_o, + output logic [AXI_ADDR-1:0] axi_master_araddr_o, + output logic [7:0] axi_master_arlen_o, //burst length - 1 to 16 + output logic [2:0] axi_master_arsize_o, //size of each transfer in burst + output logic [1:0] axi_master_arburst_o, //for bursts>1, accept only incr burst=01 + output logic axi_master_arlock_o, //only normal access supported axs_awlock=00 + output logic [3:0] axi_master_arcache_o, + output logic [2:0] axi_master_arprot_o, + output logic [3:0] axi_master_arregion_o, // + output logic [AXI_USER-1:0] axi_master_aruser_o, // + output logic [3:0] axi_master_arqos_o, // + output logic axi_master_arvalid_o, //master addr valid + input logic axi_master_arready_i, //slave ready to accept + // --------------------------------------------------------------- + + + //AXI BACKWARD read data bus ---------------------------------------------- + input logic [AXI_ID-1:0] axi_master_rid_i, + input logic [AXI_DATA-1:0] axi_master_rdata_i, + input logic [1:0] axi_master_rresp_i, + input logic axi_master_rlast_i, //last transfer in burst + input logic [AXI_USER-1:0] axi_master_ruser_i, + input logic axi_master_rvalid_i, //slave data valid + output logic axi_master_rready_o //master ready to accept +); + + localparam DEPTH = NB_CORES; + localparam LOG2_DEPTH = $clog2(DEPTH); + + // FSM State declaration + enum logic {IDLE_COMP, DISP_COMP } CS_COMP, NS_COMP; + + // interface with CTRL WRITE PORT --> SCM DATA + logic ctrl_SCM_write_req; + logic [$clog2(NB_BANKS)-1:0] ctrl_SCM_write_dest; + logic [SCM_ADDR_WIDTH-1:0] ctrl_SCM_write_addr; + logic [SCM_TAG_WIDTH-1:0] ctrl_SCM_write_wdata; + logic [NB_WAYS-1:0] ctrl_SCM_write_way; + + // interface with REFILL WRITE PORT --> SCM DATA + logic refill_TAG_SCM_write_req; + logic [$clog2(NB_BANKS)-1:0] refill_TAG_SCM_write_dest; + logic [SCM_ADDR_WIDTH-1:0] refill_TAG_SCM_write_addr; + logic [SCM_TAG_WIDTH-1:0] refill_TAG_SCM_write_wdata; + logic [NB_WAYS-1:0] refill_TAG_SCM_write_way; + + // interface with REFILL WRITE PORT --> SCM DATA + logic refill_DATA_SCM_write_req; + logic [$clog2(NB_BANKS)-1:0] refill_DATA_SCM_write_dest; + logic [SCM_ADDR_WIDTH:0] refill_DATA_SCM_write_addr; + logic [SCM_DATA_WIDTH-1:0] refill_DATA_SCM_write_wdata; + logic [NB_WAYS-1:0] refill_DATA_SCM_write_way; + + + + logic [NB_WAYS-1:0] refill_way_int; + logic [FETCH_ADDR_WIDTH-1:0] refill_address_int; + + + logic fetch_req_int; + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_int; + logic [NB_WAYS-1:0] fetch_way_int; + + logic [NB_CORES-1:0] fetch_ID_OH_int; // ID is one hot --> NB_CORES bit + logic [$clog2(NB_CORES)-1:0] fetch_ID_BIN_int; // ID is one hot --> NB_CORES bit + logic fetch_gnt_int; + + logic fetch_rvalid_int; + logic [FETCH_DATA_WIDTH-1:0] fetch_rdata_int; + logic [NB_CORES:0] fetch_rID_OH_int; // ID is one hot --> NB_CORES bit + + logic [NB_CORES-1:0][FETCH_ADDR_WIDTH+NB_WAYS-1:0] compact_data_add_i; + + logic [$clog2(FETCH_DATA_WIDTH/AXI_DATA)-1:0] rel_chunk_CS, rel_chunk_NS; + logic [FETCH_DATA_WIDTH/AXI_DATA-1:0][AXI_DATA-1:0] axi_master_rdata_int; + logic [AXI_ID-1:0] axi_master_rid_int; + logic axi_master_rvalid_int; + logic sample_rdata; + + logic fetch_rvalid_core, fetch_rvalid_pf; + logic fetch_req_muxed; + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_muxed; + logic [NB_WAYS-1:0] fetch_way_muxed; + logic fetch_gnt_muxed; + logic [NB_CORES:0] fetch_ID_OH_muxed; // ID is one hot --> NB_CORES bit + logic [$clog2(NB_CORES+1)-1:0] fetch_ID_BIN_muxed; // ID is one hot --> NB_CORES bit + + + // Compact data sent along the address of the LOG interco: { FETCH_WAY, FETCH_ADDR } + genvar i; + generate + for(i=0; i SCM Unified PORT + .SCM_TAG_write_req_o ( SCM_TAG_write_req_o ), + .SCM_TAG_write_addr_o ( SCM_TAG_write_addr_o ), + .SCM_TAG_write_dest_o ( SCM_TAG_write_dest_o ), + .SCM_TAG_write_wdata_o ( SCM_TAG_write_wdata_o ), + .SCM_TAG_write_way_o ( SCM_TAG_write_way_o ), + + // interface with WRITE PORT --> SCM Unified PORT + .SCM_DATA_write_req_o ( SCM_DATA_write_req_o ), + .SCM_DATA_write_addr_o ( SCM_DATA_write_addr_o ), // DATA SCM has double number of rows + .SCM_DATA_write_dest_o ( SCM_DATA_write_dest_o ), + .SCM_DATA_write_wdata_o ( SCM_DATA_write_wdata_o ), + .SCM_DATA_write_way_o ( SCM_DATA_write_way_o ) + ); + if (AXI_ADDR > FETCH_ADDR_WIDTH) begin : gen_zero_extend_araddr + assign axi_master_araddr_o[AXI_ADDR-1:FETCH_ADDR_WIDTH] = '0; + end + + //always accept read data + assign axi_master_rready_o = 1'b1; + assign axi_master_arlen_o = 8'h01; // FIXME for different cache line sizes + assign axi_master_arsize_o = 3'b011; // FIXME for different cache line sizes + assign axi_master_arburst_o = 2'b01; //for bursts>1, accept only incr burst=01 + assign axi_master_arlock_o = 1'b0; //only normal access supported axs_awlock=00 + assign axi_master_arcache_o = 4'b0000; + assign axi_master_arprot_o = 3'b000; + assign axi_master_arregion_o = '0; + assign axi_master_aruser_o = '0; + assign axi_master_arqos_o = 4'b0000; + + + + onehot_to_bin #( .ONEHOT_WIDTH(NB_CORES+1) ) ID_OH_to_BIN (.onehot(fetch_ID_OH_muxed), .bin(fetch_ID_BIN_muxed) ); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // █████╗ ██╗ ██╗██╗ ███████╗██╗███████╗███████╗ ██████╗ ██████╗ ███╗ ██╗██╗ ██╗ /// + // ██╔══██╗╚██╗██╔╝██║ ██╔════╝██║╚══███╔╝██╔════╝ ██╔════╝██╔═══██╗████╗ ██║██║ ██║ /// + // ███████║ ╚███╔╝ ██║ ███████╗██║ ███╔╝ █████╗ ██║ ██║ ██║██╔██╗ ██║██║ ██║ /// + // ██╔══██║ ██╔██╗ ██║ ╚════██║██║ ███╔╝ ██╔══╝ ██║ ██║ ██║██║╚██╗██║╚██╗ ██╔╝ /// + // ██║ ██║██╔╝ ██╗██║███████╗███████║██║███████╗███████╗███████╗╚██████╗╚██████╔╝██║ ╚████║ ╚████╔╝ /// + // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═══╝ /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // AXI COMPACTOR 64 bit to 128 bit!!! Data comes back as 64 bit chunks. + // This logic creates atomic responses (same with as the cache line size --> 128bit ) + always_ff @(posedge clk, negedge rst_n) + begin + if(~rst_n) + begin + CS_COMP <= IDLE_COMP; + rel_chunk_CS <= '0; + + axi_master_rdata_int <= '0; + axi_master_rid_int <= '0; + end + else + begin + CS_COMP <= NS_COMP; + rel_chunk_CS <= rel_chunk_NS; + + if(sample_rdata) + begin + axi_master_rdata_int[rel_chunk_CS] <= axi_master_rdata_i; + axi_master_rid_int <= axi_master_rid_i; + end + + end + end + + assign sample_rdata = axi_master_rvalid_i; + + always_comb + begin + rel_chunk_NS = rel_chunk_CS; + NS_COMP = CS_COMP; + + case (CS_COMP) + IDLE_COMP: + begin + axi_master_rvalid_int = 1'b0; + + if(axi_master_rvalid_i) + begin + if(axi_master_rlast_i) + begin + NS_COMP = DISP_COMP; + rel_chunk_NS = '0; + end + else + begin + NS_COMP = IDLE_COMP; + rel_chunk_NS = rel_chunk_CS + 1'b1; + end + end + else + begin + NS_COMP = IDLE_COMP; + rel_chunk_NS = rel_chunk_CS; + end + + end + + DISP_COMP: + begin + axi_master_rvalid_int = 1'b1; + NS_COMP = IDLE_COMP; + + if(axi_master_rvalid_i) + begin + if(axi_master_rlast_i) + begin + NS_COMP = DISP_COMP; + rel_chunk_NS = '0; + end + else + begin + NS_COMP = IDLE_COMP; + rel_chunk_NS = 1; + end + end + else + begin + NS_COMP = IDLE_COMP; + rel_chunk_NS = '0; + end + end + + default: + begin + NS_COMP = IDLE_COMP; + end + endcase + + end + + + +endmodule diff --git a/hw/deps/icache_mp_128_pf/RTL/central_controller_128.sv b/hw/deps/icache_mp_128_pf/RTL/central_controller_128.sv new file mode 100644 index 0000000..e158a1c --- /dev/null +++ b/hw/deps/icache_mp_128_pf/RTL/central_controller_128.sv @@ -0,0 +1,508 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: ICACHE_MP_128_PF // +// Module Name: central_controller_128 // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: This block represents the master cache controller that // +// receives the requests (multiplexed) from different cache // +// banks or HW prefetchre and checks if there are pending // +// refill on that cache line, it also handles the writes on // +// tag and data arrays. // +// // +// // +// Revision: // +// Revision v0.1 - 22/01/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + +module central_controller_128 +#( + parameter ID_WIDTH = 9, + parameter LOG2_ID_WIDTH = $clog2(ID_WIDTH), + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 128, + parameter DEPTH = 16, + parameter LOG2_DEPTH = $clog2(DEPTH), + + parameter SCM_ADDR_WIDTH = 6, + parameter SCM_TAG_WIDTH = 6, + parameter SCM_DATA_WIDTH = 128, + parameter NB_BANKS = 4, + parameter NB_WAYS = 4, + parameter NB_CORES = 8, + + parameter ADDR_CHECK_LSB = 4, + parameter ADDR_CHECK_MSB = ADDR_WIDTH-1, + + parameter ID_LSB = 6, + parameter ID_MSB = 11, + parameter TAG_LSB = 12, + parameter TAG_MSB = SCM_TAG_WIDTH+TAG_LSB-2, + parameter DEST_LSB = 4, + parameter DEST_MSB = 5 +) +( + input logic clk, + input logic rst_n, + input logic test_en_i, + + input logic bypass_icache_i, + output logic cache_bypassed_o, + input logic [NB_CORES:0] bypass_status_i, + + input logic flush_icache_i, + output logic flush_ack_o, + + input logic sel_flush_req_i, + input logic [ADDR_WIDTH-1:0] sel_flush_addr_i, + output logic sel_flush_ack_o, + + output logic empty_fifo_o, + output logic [ID_WIDTH-1:0] retry_fetch_o, + + + output logic [ID_WIDTH-1:0] notify_refill_done_o, + + + input logic fetch_req_i, + input logic [LOG2_ID_WIDTH-1:0] fetch_ID_BIN_i, + input logic [ID_WIDTH-1:0] fetch_ID_OH_i, + input logic [ADDR_WIDTH-1:0] fetch_addr_i, + input logic [NB_WAYS-1:0] fetch_way_i, + output logic fetch_gnt_o, + + output logic fetch_rvalid_o, + output logic [DATA_WIDTH-1:0] fetch_rdata_o, + output logic [ID_WIDTH-1:0] fetch_rID_o, + + + + output logic AXI_req_o, + output logic [ADDR_WIDTH-1:0] AXI_addr_o, + output logic [LOG2_DEPTH-1:0] AXI_ID_o, + input logic AXI_gnt_i, + + input logic AXI_rvalid_i, + input logic [LOG2_DEPTH-1:0] AXI_rID_i, + input logic [DATA_WIDTH-1:0] AXI_rdata_i, + + output logic SCM_TAG_write_req_o, + output logic [SCM_ADDR_WIDTH-1:0] SCM_TAG_write_addr_o, + output logic [$clog2(NB_BANKS)-1:0] SCM_TAG_write_dest_o, + output logic [SCM_TAG_WIDTH-1:0] SCM_TAG_write_wdata_o, + output logic [NB_WAYS-1:0] SCM_TAG_write_way_o, + + // interface with WRITE PORT --> SCM Unified PORT + output logic SCM_DATA_write_req_o, + output logic [SCM_ADDR_WIDTH-1:0] SCM_DATA_write_addr_o, // DATA SCM has double number of rows + output logic [$clog2(NB_BANKS)-1:0] SCM_DATA_write_dest_o, + output logic [SCM_DATA_WIDTH-1:0] SCM_DATA_write_wdata_o, + output logic [NB_WAYS-1:0] SCM_DATA_write_way_o + +); + + // STATE ENCODING + enum logic [2:0] {INVALIDATE, BYPASSED, WAIT_EMPTY_BYPASS_FIFO, ENABLED, GOING_BYPASS, FLUSH_SET_ID } CS, NS; + + // signals declaration + logic [$clog2(NB_BANKS)+SCM_ADDR_WIDTH-1:0] counter_CS, counter_NS; + + logic CAM_empty; + //TO REFILL CAM + logic CAM_grant; + logic CAM_fetch_req; + // From CAM to AXI MUX + logic CAM_AXI_req; + logic [ADDR_WIDTH-1:0] CAM_AXI_addr; + logic [LOG2_DEPTH-1:0] CAM_AXI_ID; + + // for refill PURPOSE ONLY + logic [ADDR_WIDTH-1:0] CAM_refill_addr; + logic [ID_WIDTH-1:0] CAM_refill_ID; + logic [NB_WAYS-1:0] CAM_refill_way; + + logic fifo_rel_chunk_gnt; + logic fifo_rel_chunk_valid; + + // Notify to different cache bank as soon the refill is committed in the DAT/TAG. + // A new fetch attempt will be performed + assign notify_refill_done_o = (~cache_bypassed_o & AXI_rvalid_i) ? CAM_refill_ID : '0; + + // CS and Counters Flip Flops + always_ff @(posedge clk or negedge rst_n) + begin : Seq_CS_counters + if(~rst_n) + begin + CS <= INVALIDATE; + counter_CS <= '0; + end + else + begin + CS <= NS; + counter_CS <= counter_NS; + end + end + + + always_comb + begin : Comb_logic_main_FSM + + // Default values for FSM outputs + NS = CS; + counter_NS = counter_CS; + + fetch_gnt_o = 1'b0; + + fetch_rvalid_o = 1'b0; + + fetch_rdata_o = AXI_rdata_i; + fetch_rID_o = 1< sel_flush_addr_i[ID_MSB:ID_LSB]; + SCM_TAG_write_req_o = 1'b1; + SCM_TAG_write_addr_o = sel_flush_addr_i[ID_MSB:ID_LSB]; + SCM_TAG_write_dest_o = sel_flush_addr_i[DEST_MSB:DEST_LSB]; + SCM_TAG_write_wdata_o = '0; + SCM_TAG_write_way_o = '1; + cache_bypassed_o = 1'b0; + + sel_flush_ack_o = 1'b1; + + // at any point in time check if there are Bypass request. + // In case, just serve it and go in the proper state + if(bypass_icache_i) + NS = BYPASSED; + else + NS = ENABLED; + end + + + // State used to invalidate the cache + INVALIDATE: + begin + // Invalidate all cache Lines + SCM_TAG_write_req_o = 1'b1; + SCM_TAG_write_addr_o = counter_CS[SCM_ADDR_WIDTH-1:0]; + SCM_TAG_write_dest_o = counter_CS[$clog2(NB_BANKS)+SCM_ADDR_WIDTH-1:SCM_ADDR_WIDTH]; + SCM_TAG_write_wdata_o = '0; + SCM_TAG_write_way_o = '1; + cache_bypassed_o = 1'b1; + + // Iterate on all cache lines (not in parallel, one cache line at the time) + if(counter_CS < NB_BANKS * (2**SCM_ADDR_WIDTH) -1 ) + begin + NS = INVALIDATE; + counter_NS = counter_CS + 1'b1; + end + else + begin + flush_ack_o = 1'b1; + + if(bypass_icache_i) + NS = BYPASSED; + else + NS = ENABLED; + + counter_NS = '0; + end + end + + //Main state for cache bypassed (not enabled). + BYPASSED: + begin + cache_bypassed_o = 1'b1; + flush_ack_o = 1'b1; + sel_flush_ack_o = 1'b1; + + fetch_rvalid_o = AXI_rvalid_i; + fetch_gnt_o = AXI_gnt_i & fifo_rel_chunk_gnt; + + AXI_req_o = fetch_req_i & fifo_rel_chunk_gnt; + AXI_addr_o = fetch_addr_i & 32'hFFFF_FFF0; // Mast bits from [3:0] --> 128 bit access + + // DEPTH > ID_WIDTH + if(LOG2_DEPTH == LOG2_ID_WIDTH) + AXI_ID_o = fetch_ID_BIN_i; + else + AXI_ID_o = { {(LOG2_DEPTH-LOG2_ID_WIDTH){1'b0}} , fetch_ID_BIN_i}; + + + + // Check if there is a bypass req, a flush or a selective FLush + // If one of these signals is 1, then thre is nothing to do + // cache is already bypassed, so flush or selective flush does + // not perform any further action. + if(bypass_icache_i) + NS = BYPASSED; + else + NS = WAIT_EMPTY_BYPASS_FIFO; + end + + + // Stay in this state untill the + WAIT_EMPTY_BYPASS_FIFO: + begin + cache_bypassed_o = 1'b1; + + fetch_rvalid_o = AXI_rvalid_i; + + + fetch_gnt_o = 1'b0; + if(fifo_rel_chunk_valid == 1'b0) // no longer transactions in the BYPASS FIFO. + begin + NS = INVALIDATE; + end + else + begin + NS = WAIT_EMPTY_BYPASS_FIFO; + end + end + + + // Main State When cache is Enabled + ENABLED: + begin + cache_bypassed_o = 1'b0; + + AXI_req_o = CAM_AXI_req; + AXI_addr_o = CAM_AXI_addr; + AXI_ID_o = CAM_AXI_ID; + + fetch_gnt_o = CAM_grant; + fetch_rvalid_o = 1'b0; + + + // Check if there is a bypass req, a flush or a selective FLush + // If one of these signals is 1, then the controller performs the + // right action + if( bypass_icache_i | flush_icache_i | sel_flush_req_i ) + begin + NS = GOING_BYPASS; + end + else + begin + NS = ENABLED ; + end + + + + // Handle teh Backwrite of the refill in the SCM banks + SCM_DATA_write_way_o = CAM_refill_way; + SCM_DATA_write_addr_o = CAM_refill_addr[ID_MSB:ID_LSB]; + SCM_DATA_write_dest_o = CAM_refill_addr[DEST_MSB:DEST_LSB] ; + SCM_DATA_write_wdata_o = AXI_rdata_i; + + SCM_TAG_write_way_o = CAM_refill_way; + SCM_TAG_write_addr_o = CAM_refill_addr[ID_MSB:ID_LSB]; + SCM_TAG_write_dest_o = CAM_refill_addr[DEST_MSB:DEST_LSB]; + + if(AXI_rvalid_i) + begin + SCM_DATA_write_req_o = ~cache_bypassed_o; + SCM_TAG_write_req_o = ~cache_bypassed_o; + SCM_TAG_write_wdata_o = {1'b1, CAM_refill_addr[TAG_MSB:TAG_LSB]}; + end + else // AXI_rvalid_i == 0 + begin + SCM_DATA_write_req_o = '0; + SCM_TAG_write_req_o = '0; + SCM_TAG_write_wdata_o = '0; + end + + end + + // Cache is Enabled but there was a Request to Disable, + // Empty the refill storage before switching + GOING_BYPASS: + begin + fetch_gnt_o = 1'b0; + cache_bypassed_o = 1'b0; + + // Handle teh Backwrite of the refill in the SCM banks + SCM_DATA_write_way_o = CAM_refill_way; + SCM_DATA_write_addr_o = CAM_refill_addr[ID_MSB:ID_LSB]; + SCM_DATA_write_dest_o = CAM_refill_addr[DEST_MSB:DEST_LSB] ; + SCM_DATA_write_wdata_o = AXI_rdata_i; + + SCM_TAG_write_way_o = CAM_refill_way; + SCM_TAG_write_addr_o = CAM_refill_addr[ID_MSB:ID_LSB]; + SCM_TAG_write_dest_o = CAM_refill_addr[DEST_MSB:DEST_LSB]; + + if(AXI_rvalid_i) + begin + SCM_DATA_write_req_o = ~cache_bypassed_o; + SCM_TAG_write_req_o = ~cache_bypassed_o; + SCM_TAG_write_wdata_o = {1'b1, CAM_refill_addr[TAG_MSB:TAG_LSB]}; + end + else // AXI_rvalid_i == 0 + begin + SCM_DATA_write_req_o = '0; + SCM_TAG_write_req_o = '0; + SCM_TAG_write_wdata_o = '0; + end + + + //Finally , if the CAM is EMpty, switch to BYPASSED state + if(CAM_empty) + begin + if( flush_icache_i ) + begin + NS = INVALIDATE; + end + else if( sel_flush_req_i ) + begin + NS = FLUSH_SET_ID; + end + else + begin + NS = BYPASSED; + end + end + else // CAM is not empty + begin + NS = GOING_BYPASS; + end + end + + + default: + begin + // In case something goes wrong, commute to Invalidated then --> Bypass or Enabled + cache_bypassed_o = 1'b1; + NS = INVALIDATE; + end + + endcase + end + + + // This FIFO holds information about in fligth fetches when cache is bypassed + generic_fifo + #( + .DATA_WIDTH ( 1 ), + .DATA_DEPTH ( DEPTH ) + ) + REL_CHUNK_FIFO + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .data_i ( ), + .valid_i ( fetch_req_i & AXI_gnt_i & (CS == BYPASSED) ), // cache in bypass mode, LOOKUPTABLE empty + .grant_o ( fifo_rel_chunk_gnt ), + + .data_o ( ), + .valid_o ( fifo_rel_chunk_valid ), + .grant_i ( AXI_rvalid_i ), + + .test_mode_i ( test_en_i ) + ); + + + + // This storage is a CAM, that stores pending refills: + // REfills are merged toghether if they compete to the same cache line. + // in case multiple cache banks have requested to the same cache line (in different moments) + // this cam updates these infos, and as soon the refill from axi side arrives, the master cache + // controller updates DATA/TAG and then notifies to those cache master to retry a fetch. + merge_refill_cam_128_16 + #( + .NB_WAYS ( NB_WAYS ), + .ID_WIDTH ( ID_WIDTH ), + .LOG2_ID_WIDTH ( LOG2_ID_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .DEPTH ( 16 ), + .LOG2_DEPTH ( 4 ), + .ADDR_CHECK_LSB ( ADDR_CHECK_LSB ), + .ADDR_CHECK_MSB ( ADDR_CHECK_MSB ) + ) + MERGE_CAM + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .empty_o ( CAM_empty ), + .retry_fetch_o ( retry_fetch_o ), + + .fetch_req_i ( fetch_req_i & fetch_gnt_o & ~cache_bypassed_o ), + .fetch_ID_BIN_i ( fetch_ID_BIN_i ), + .fetch_ID_OH_i ( fetch_ID_OH_i ), + .fetch_addr_i ( fetch_addr_i ), + .fetch_way_i ( fetch_way_i ), + .fetch_gnt_o ( CAM_grant ), + + .AXI_rvalid_i ( AXI_rvalid_i ), + .AXI_rID_i ( AXI_rID_i ), + + .AXI_req_o ( CAM_AXI_req ), + .AXI_addr_o ( CAM_AXI_addr ), + .AXI_ID_o ( CAM_AXI_ID ), + .AXI_gnt_i ( AXI_gnt_i ), + + + .refill_addr_o ( CAM_refill_addr ), + .refill_ID_o ( CAM_refill_ID ), + .refill_way_o ( CAM_refill_way ) + ); + + + assign empty_fifo_o = CAM_empty & ~fifo_rel_chunk_valid; + + +endmodule // central_controller diff --git a/hw/deps/icache_mp_128_pf/RTL/icache_bank_mp_128.sv b/hw/deps/icache_mp_128_pf/RTL/icache_bank_mp_128.sv new file mode 100644 index 0000000..149fd3c --- /dev/null +++ b/hw/deps/icache_mp_128_pf/RTL/icache_bank_mp_128.sv @@ -0,0 +1,610 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: ICACHE_MP_128_PF // +// Module Name: icache_bank_mp_128 // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: This block represents private cache controller that // +// receives the requests from the process fetch unit // +// and perform TAG access for TAG hit check. In case of MISS // +// the refill is forwarded to the main cache controller (TOP) // +// // +// // +// Revision: // +// Revision v0.1 - 22/01/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`define USE_REQ_BUFFER + +module icache_bank_mp_128 +#( + parameter int FETCH_ADDR_WIDTH = 32, + parameter int FETCH_DATA_WIDTH = 128, + + parameter int NB_CORES = 4, + parameter int BANK_ID = 0, + parameter int NB_BANKS = 4, + parameter int NB_WAYS = 4, + parameter int CACHE_LINE = 1, + + parameter int SCM_ADDR_WIDTH = 16, + parameter int SCM_TAG_WIDTH = 6, + parameter int SCM_DATA_WIDTH = 128, + + parameter int SET_ID_LSB = $clog2(NB_BANKS)+$clog2(SCM_DATA_WIDTH*CACHE_LINE)-3, + parameter int SET_ID_MSB = SET_ID_LSB + SCM_ADDR_WIDTH - 1, + parameter int TAG_LSB = SET_ID_MSB + 1, + parameter int TAG_MSB = TAG_LSB + SCM_TAG_WIDTH - 2, + + parameter bit FEATURE_STAT = 1'b0, + + parameter int AXI_ID = 4, + parameter int AXI_ADDR = FETCH_ADDR_WIDTH, + parameter int AXI_USER = 6, + parameter int AXI_DATA = 64 +) +( + input logic clk, + input logic rst_n, + input logic test_en_i, + + input logic notify_refill_done_i, + input logic bypass_icache_i, + input logic empty_fifo_i, + output logic cache_is_bypassed_o, + input logic [NB_CORES:0] bypass_status_i, + input logic retry_fetch_i, + + // interface with processor + input logic fetch_req_i, + input logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_i, + output logic fetch_gnt_o, + output logic fetch_rvalid_o, + output logic [FETCH_DATA_WIDTH-1:0] fetch_rdata_o, + + + // interface with READ PORT --> SCM DATA + output logic [NB_BANKS-1:0] DATA_read_req_o, + output logic [SCM_ADDR_WIDTH-1:0] DATA_read_addr_o, + input logic [NB_BANKS-1:0][NB_WAYS-1:0][SCM_DATA_WIDTH-1:0] DATA_read_rdata_i, + + // interface with READ PORT --> SCM TAG + output logic [NB_BANKS-1:0] TAG_read_req_o, + output logic [SCM_ADDR_WIDTH-1:0] TAG_read_addr_o, + input logic [NB_BANKS-1:0][NB_WAYS-1:0][SCM_TAG_WIDTH-1:0] TAG_read_rdata_i, + + + + + + // Interface to cache_controller_to_axi + output logic fetch_req_o, + output logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_o, + output logic [NB_WAYS-1:0] fetch_way_o, + input logic fetch_gnt_i, + input logic fetch_rvalid_i, + input logic [FETCH_DATA_WIDTH-1:0] fetch_rdata_i, + output logic [31:0] ctrl_hit_count_icache_o, + output logic [31:0] ctrl_trans_count_icache_o, + output logic [31:0] ctrl_miss_count_icache_o, + input logic ctrl_clear_regs_icache_i, + input logic ctrl_enable_regs_icache_i +); + + + localparam OFFSET = $clog2(SCM_DATA_WIDTH*CACHE_LINE)-3; + + // Finite State declaration: PS is Past State, used only for Statistic (perf Counters) + enum logic [2:0] { DISABLED_ICACHE, WAIT_NOTIFICATION, OPERATIVE, REQ_REFILL , WAIT_EMPTY_FIFOS, ENTER_BYPASS } CS, NS, PS; + + // signals declaration + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_Q; + logic fetch_req_Q; + + logic save_fetch; + logic save_pipe_status; + logic clear_pipe; + logic enable_pipe; + + logic [$clog2(NB_BANKS)-1:0] fetch_dest_Q; //Target BANK + logic [NB_WAYS-1:0][SCM_DATA_WIDTH-1:0] DATA_read_rdata_int; + logic [NB_WAYS-1:0][SCM_TAG_WIDTH-1:0] TAG_read_rdata_int; + + + logic [NB_WAYS-1:0] way_match; + logic [NB_WAYS-1:0] way_valid; + logic [NB_WAYS-1:0] way_match_bin; + logic [NB_WAYS-1:0] way_match_Q; + logic [NB_WAYS-1:0] way_valid_Q; + + logic [NB_WAYS-1:0] random_way; + logic [$clog2(NB_WAYS)-1:0] first_available_way; + logic [NB_WAYS-1:0] first_available_way_OH; + + logic [$clog2(NB_WAYS)-1:0] HIT_WAY; + + assign first_available_way_OH = 1 << first_available_way; + + + + int unsigned i,j,index; + + + logic update_lfsr; + + logic [31:0] Count_Evictions; + + logic fetch_req_int; + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_int; + logic [NB_WAYS-1:0] fetch_way_int; + logic fetch_gnt_int; +`ifdef USE_REQ_BUFFER + logic [FETCH_ADDR_WIDTH+NB_WAYS-1:0] s_data_in; + logic [FETCH_ADDR_WIDTH+NB_WAYS-1:0] s_data_out; +`endif + + + // Sequential Logic (state, counters and registrered signals) + always_ff @(posedge clk, negedge rst_n) + begin : Seq_logic + if(~rst_n) + begin + CS <= DISABLED_ICACHE; + PS <= DISABLED_ICACHE; + fetch_addr_Q <= '0; + fetch_req_Q <= 1'b0; + way_match_Q <= '0; + way_valid_Q <= '0; + if (FEATURE_STAT) begin + ctrl_hit_count_icache_o <= '0; + ctrl_trans_count_icache_o <= '0; + ctrl_miss_count_icache_o <= '0; + Count_Evictions <= '0; + ctrl_miss_count_icache_o <= '0; + end + end + else + begin + CS <= NS; + PS <= CS; + + + if (FEATURE_STAT) begin + if(ctrl_clear_regs_icache_i) + begin + ctrl_hit_count_icache_o <= '0; + ctrl_trans_count_icache_o <= '0; + Count_Evictions <= '0; + ctrl_miss_count_icache_o <= '0; + end + else + if(ctrl_enable_regs_icache_i) + begin + // Count incoming transactions + if(fetch_req_i & fetch_gnt_o) + ctrl_trans_count_icache_o <= ctrl_trans_count_icache_o + 1'b1; + + if( (CS == OPERATIVE) & fetch_req_Q & (|way_match) & (PS != WAIT_NOTIFICATION)) + ctrl_hit_count_icache_o <= ctrl_hit_count_icache_o + 1'b1; + + if( update_lfsr ) + Count_Evictions <= Count_Evictions + 1'b1; + + if( (CS == REQ_REFILL ) & fetch_gnt_int ) + ctrl_miss_count_icache_o<= ctrl_miss_count_icache_o + 1'b1; + + end + end + + if(save_pipe_status) + begin + way_match_Q <= way_match; + way_valid_Q <= way_valid; + end + + + if(enable_pipe) + begin + fetch_req_Q <= 1'b1; + fetch_addr_Q <= fetch_addr_i; + end + else if(clear_pipe) + begin + fetch_req_Q <= '0; + end + + end + end + + + + assign fetch_dest_Q = fetch_addr_Q[$clog2(NB_BANKS)+OFFSET-1:OFFSET]; + assign TAG_read_rdata_int = TAG_read_rdata_i[fetch_dest_Q] ; + assign DATA_read_rdata_int = DATA_read_rdata_i[fetch_dest_Q] ; + + + + + // Logic to check TAG HIT/MISS + // --------------------- // + // TAG CHECK MULTI WAY // + // --------------------- // + genvar k; + generate + for(k=0; k SCM TAG + output logic [NB_BANKS-1:0] TAG_read_req_o, + output logic [SCM_ADDR_WIDTH-1:0] TAG_read_addr_o, + input logic [NB_BANKS-1:0][NB_WAYS-1:0][SCM_TAG_WIDTH-1:0] TAG_read_rdata_i, + + + // Interface to cache_controller_to_axi + output logic fetch_req_o, + output logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_o, + output logic [NB_WAYS-1:0] fetch_way_o, + input logic fetch_gnt_i, + input logic fetch_rvalid_i +); + + + localparam OFFSET = $clog2(SCM_DATA_WIDTH*CACHE_LINE)-3; + + // Finite State declaration: PS is Past State, used only for Statistic (perf Counters) + enum logic [2:0] { DISABLED_ICACHE, WAIT_NOTIFICATION, OPERATIVE, REQ_REFILL , WAIT_EMPTY_FIFOS, ENTER_BYPASS } CS, NS, PS; + + // signals declaration + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_Q; + logic fetch_req_Q; + + logic save_fetch; + logic save_pipe_status; + logic clear_pipe; + logic enable_pipe; + + logic [$clog2(NB_BANKS)-1:0] fetch_dest_Q; //Target BANK + logic [NB_WAYS-1:0][SCM_TAG_WIDTH-1:0] TAG_read_rdata_int; + + logic [NB_WAYS-1:0] way_match; + logic [NB_WAYS-1:0] way_valid; + logic [NB_WAYS-1:0] way_match_bin; + logic [NB_WAYS-1:0] way_match_Q; + logic [NB_WAYS-1:0] way_valid_Q; + + logic [NB_WAYS-1:0] random_way; // In case of Way replacement // Driven By LFSR + logic [$clog2(NB_WAYS)-1:0] first_available_way; + logic [NB_WAYS-1:0] first_available_way_OH; + + logic [$clog2(NB_WAYS)-1:0] HIT_WAY; + + assign first_available_way_OH = 1 << first_available_way; + + + + int unsigned i,j,index; + + + logic update_lfsr; + + + logic fetch_req_int; + logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_int; + logic [NB_WAYS-1:0] fetch_way_int; + logic fetch_gnt_int; +`ifdef USE_REQ_BUFFER + logic [FETCH_ADDR_WIDTH+NB_WAYS-1:0] s_data_in; + logic [FETCH_ADDR_WIDTH+NB_WAYS-1:0] s_data_out; +`endif + + + + // Sequential Logic (state, counters and registrered signals) + always_ff @(posedge clk, negedge rst_n) + begin : Seq_logic + if(~rst_n) + begin + CS <= DISABLED_ICACHE; + PS <= DISABLED_ICACHE; + fetch_addr_Q <= '0; + fetch_req_Q <= 1'b0; + way_match_Q <= '0; + way_valid_Q <= '0; + end + else + begin + CS <= NS; + PS <= CS; + + if(save_pipe_status) + begin + way_match_Q <= way_match; + way_valid_Q <= way_valid; + end + + + if(enable_pipe) + begin + fetch_req_Q <= 1'b1; + fetch_addr_Q <= fetch_addr_i; + end + else if(clear_pipe) + begin + fetch_req_Q <= '0; + end + + end + end + + + + assign fetch_dest_Q = fetch_addr_Q[$clog2(NB_BANKS)+OFFSET-1:OFFSET]; + assign TAG_read_rdata_int = TAG_read_rdata_i[fetch_dest_Q] ; + + + + // Logic to check TAG HIT/MISS + // --------------------- // + // TAG CHECK MULTI WAY // + // --------------------- // + genvar k; + generate + for(k=0; k1, accept only incr burst=01 + output logic axi_master_arlock_o, //only normal access supported axs_awlock=00 + output logic [ 3:0] axi_master_arcache_o, + output logic [ 2:0] axi_master_arprot_o, + output logic [ 3:0] axi_master_arregion_o, // + output logic [ AXI_USER-1:0] axi_master_aruser_o, // + output logic [ 3:0] axi_master_arqos_o, // + output logic axi_master_arvalid_o, //master addr valid + input logic axi_master_arready_i, //slave ready to accept + // --------------------------------------------------------------- + + + //AXI BACKWARD read data bus ---------------------------------------------- + input logic [AXI_ID-1:0] axi_master_rid_i, + input logic [AXI_DATA-1:0] axi_master_rdata_i, + input logic [1:0] axi_master_rresp_i, + input logic axi_master_rlast_i, //last transfer in burst + input logic [AXI_USER-1:0] axi_master_ruser_i, + input logic axi_master_rvalid_i, //slave data valid + output logic axi_master_rready_o, //master ready to accept + + // NOT USED ---------------------------------------------- + output logic [AXI_ID-1:0] axi_master_awid_o, + output logic [AXI_ADDR-1:0] axi_master_awaddr_o, + output logic [ 7:0] axi_master_awlen_o, + output logic [ 2:0] axi_master_awsize_o, + output logic [ 1:0] axi_master_awburst_o, + output logic axi_master_awlock_o, + output logic [ 3:0] axi_master_awcache_o, + output logic [ 2:0] axi_master_awprot_o, + output logic [ 3:0] axi_master_awregion_o, + output logic [ AXI_USER-1:0] axi_master_awuser_o, + output logic [ 3:0] axi_master_awqos_o, + output logic axi_master_awvalid_o, + input logic axi_master_awready_i, + + // NOT USED ---------------------------------------------- + output logic [AXI_DATA-1:0] axi_master_wdata_o, + output logic [AXI_DATA/8-1:0] axi_master_wstrb_o, + output logic axi_master_wlast_o, + output logic [ AXI_USER-1:0] axi_master_wuser_o, + output logic axi_master_wvalid_o, + input logic axi_master_wready_i, + // --------------------------------------------------------------- + + // NOT USED ---------------------------------------------- + input logic [AXI_ID-1:0] axi_master_bid_i, + input logic [ 1:0] axi_master_bresp_i, + input logic [ AXI_USER-1:0] axi_master_buser_i, + input logic axi_master_bvalid_i, + output logic axi_master_bready_o, + // --------------------------------------------------------------- + + MP_PF_ICACHE_CTRL_UNIT_BUS.Slave IC_ctrl_unit_slave_if +); + + // Parameter to reduce the TAG bits (cachin only L2 and not on 4GB memory space) + // The assumption is that During ROM reading cache is Disabled. + localparam REDUCE_TAG_WIDTH = $clog2(L2_SIZE/CACHE_SIZE)+$clog2(NB_WAYS); + + localparam OFFSET = $clog2(FETCH_DATA_WIDTH)-3; // log2(128)-3 = 4; + localparam BANK_SIZE = CACHE_SIZE/NB_BANKS; + localparam WAY_SIZE = BANK_SIZE/NB_WAYS; + localparam SCM_NUM_ROWS = WAY_SIZE/(CACHE_LINE*FETCH_DATA_WIDTH/8); // TAG + localparam SCM_TAG_ADDR_WIDTH = $clog2(SCM_NUM_ROWS); + + localparam TAG_WIDTH = USE_REDUCED_TAG ? REDUCE_TAG_WIDTH : (FETCH_ADDR_WIDTH - SCM_TAG_ADDR_WIDTH - $clog2(NB_BANKS) - $clog2(CACHE_LINE) - OFFSET + 1); + + localparam DATA_WIDTH = FETCH_DATA_WIDTH; + localparam SCM_DATA_ADDR_WIDTH = SCM_TAG_ADDR_WIDTH; + + localparam AXI_ID_INT = $clog2(NB_CORES+1); + + localparam SET_ID_LSB = $clog2(NB_BANKS)+$clog2(FETCH_DATA_WIDTH*CACHE_LINE)-3; + localparam SET_ID_MSB = SET_ID_LSB + SCM_TAG_ADDR_WIDTH - 1; + localparam TAG_LSB = SET_ID_MSB + 1; + localparam TAG_MSB = TAG_LSB + TAG_WIDTH - 2 ; //1 bit is count for valid + + + // interface with READ PORT --> SCM DATA + logic [NB_CORES-1:0][NB_BANKS-1:0] DATA_read_req_int; + logic [NB_CORES-1:0][SCM_DATA_ADDR_WIDTH-1:0] DATA_read_addr_int; + logic [NB_BANKS-1:0][NB_WAYS-1:0][NB_CORES-1:0][FETCH_DATA_WIDTH-1:0] DATA_read_rdata_int; + + // interface with READ PORT --> SCM TAG + logic [NB_CORES:0][NB_BANKS-1:0] TAG_read_req_int; + logic [NB_CORES:0][SCM_TAG_ADDR_WIDTH-1:0] TAG_read_addr_int; + logic [NB_BANKS-1:0][NB_WAYS-1:0][NB_CORES:0][TAG_WIDTH-1:0] TAG_read_rdata_int; + + + // interface with WRITE PORT --> TAG SCM UNIFIED + logic SCM_TAG_write_req_int; + logic [SCM_TAG_ADDR_WIDTH-1:0] SCM_TAG_write_addr_int; + logic [$clog2(NB_BANKS)-1:0] SCM_TAG_write_dest_int; + logic [TAG_WIDTH-1:0] SCM_TAG_write_wdata_int; + logic [NB_WAYS-1:0] SCM_TAG_write_way_int; + + // interface with WRITE PORT --> DATA SCM UNIFIED + logic SCM_DATA_write_req_int; + logic [SCM_DATA_ADDR_WIDTH-1:0] SCM_DATA_write_addr_int; + logic [$clog2(NB_BANKS)-1:0] SCM_DATA_write_dest_int; + logic [FETCH_DATA_WIDTH-1:0] SCM_DATA_write_wdata_int; + logic [NB_WAYS-1:0] SCM_DATA_write_way_int; + + + + logic [NB_BANKS-1:0] [NB_CORES:0] TAG_ReadEnable; + logic [NB_BANKS-1:0] [NB_CORES-1:0] DATA_ReadEnable; + logic [NB_CORES:0] [NB_BANKS-1:0][NB_WAYS-1:0] [TAG_WIDTH-1:0] TAG_ReadData; + logic [NB_CORES-1:0] [NB_BANKS-1:0][NB_WAYS-1:0] [FETCH_DATA_WIDTH-1:0] DATA_ReadData; + + logic [NB_CORES:0] notify_refill_done; + + logic [NB_CORES-1:0][NB_WAYS-1:0] fetch_way_int; + + logic [NB_CORES-1:0] fetch_req_int; + logic [NB_CORES-1:0][FETCH_ADDR_WIDTH-1:0] fetch_addr_int; + logic [NB_CORES-1:0] fetch_gnt_int; + logic [NB_CORES-1:0] fetch_rvalid_int; + logic [NB_CORES-1:0][FETCH_DATA_WIDTH-1:0] fetch_rdata_int; + + logic [NB_BANKS-1:0] SCM_TAG_write_dest_OH_int; + logic [NB_BANKS-1:0] SCM_DATA_write_dest_OH_int; + logic [NB_CORES+1:0] cache_is_bypassed; // NB_CORES+CENTRL_CACHE_CTRL+HW prefetcher + + logic [NB_CORES:0] retry_fetch; + + + logic bypass_icache; + logic empty_fifo; + logic flush_icache; + logic flush_ack; + logic sel_flush_req; + logic [FETCH_ADDR_WIDTH-1:0] sel_flush_addr; + logic sel_flush_ack; + + + logic [AXI_ID_INT-1:0] axi_master_arid_int; + logic [AXI_ADDR-1:0] axi_master_araddr_int; + logic [ 7:0] axi_master_arlen_int; + logic [ 2:0] axi_master_arsize_int; + logic [ 1:0] axi_master_arburst_int; + logic axi_master_arlock_int; + logic [ 3:0] axi_master_arcache_int; + logic [ 2:0] axi_master_arprot_int; + logic [ 3:0] axi_master_arregion_int; + logic [ AXI_USER-1:0] axi_master_aruser_int; + logic [ 3:0] axi_master_arqos_int; + logic axi_master_arvalid_int; + logic axi_master_arready_int; + + + logic [AXI_ID_INT-1:0] axi_master_rid_int; + logic [AXI_DATA-1:0] axi_master_rdata_int; + logic [1:0] axi_master_rresp_int; + logic axi_master_rlast_int; + logic [AXI_USER-1:0] axi_master_ruser_int; + logic axi_master_rvalid_int; + logic axi_master_rready_int; + + + // Signals from Prefetcher control unit to HW prefetcher Block + logic pf_req_to_cc; + logic [31:0] pf_addr_to_cc; + logic pf_gnt_from_cc; + logic pf_rvalid_from_cc; + + // Signal from HW prefetcher to main cache controller + logic pf_req_to_master_cc; + logic [31:0] pf_addr_to_master_cc; + logic [NB_WAYS-1:0] pf_way_to_master_cc; + logic pf_gnt_from_master_cc; + logic pf_rvalid_from_master_cc; + + + + + // Performamce counters + logic [31:0] total_hit_count; + logic [31:0] total_trans_count; + logic [31:0] total_miss_count; + + logic [NB_CORES-1:0][31:0] bank_hit_count; + logic [NB_CORES-1:0][31:0] bank_trans_count; + logic [NB_CORES-1:0][31:0] bank_miss_count; + + assign SCM_TAG_write_dest_OH_int = (1 << SCM_TAG_write_dest_int); + assign SCM_DATA_write_dest_OH_int = (1 << SCM_DATA_write_dest_int); + + genvar i,j,k,z; + int unsigned index; + + + assign bypass_icache = IC_ctrl_unit_slave_if.bypass_req; + assign IC_ctrl_unit_slave_if.bypass_ack = cache_is_bypassed; + assign flush_icache = IC_ctrl_unit_slave_if.flush_req; + assign IC_ctrl_unit_slave_if.flush_ack = flush_ack; + + assign sel_flush_req = IC_ctrl_unit_slave_if.sel_flush_req; + assign sel_flush_addr = IC_ctrl_unit_slave_if.sel_flush_addr; + assign IC_ctrl_unit_slave_if.sel_flush_ack = sel_flush_ack; + + // Performamce counters + if (FEATURE_STAT) begin + assign IC_ctrl_unit_slave_if.global_hit_count = total_hit_count; + assign IC_ctrl_unit_slave_if.global_trans_count = total_trans_count; + assign IC_ctrl_unit_slave_if.global_miss_count = total_miss_count; + + always_comb + begin + total_hit_count = '0; + total_trans_count = '0; + for (index=0; index SCM DATA + .DATA_read_req_o ( DATA_read_req_int[i] ), + .DATA_read_addr_o ( DATA_read_addr_int[i] ), + .DATA_read_rdata_i ( DATA_ReadData[i] ), + + // interface with READ PORT --> SCM TAG + .TAG_read_req_o ( TAG_read_req_int[i] ), + .TAG_read_addr_o ( TAG_read_addr_int[i] ), + .TAG_read_rdata_i ( TAG_ReadData[i] ), + + // interface to CC to AXI bridge + .fetch_req_o ( fetch_req_int[i] ), + .fetch_addr_o ( fetch_addr_int[i] ), + .fetch_way_o ( fetch_way_int[i] ), + + .fetch_gnt_i ( fetch_gnt_int[i] ), + .fetch_rvalid_i ( fetch_rvalid_int[i] ), + .fetch_rdata_i ( fetch_rdata_int[i] ), + .ctrl_hit_count_icache_o ( bank_hit_count[i] ), + .ctrl_trans_count_icache_o ( bank_trans_count[i] ), + .ctrl_miss_count_icache_o ( bank_miss_count[i] ), + .ctrl_clear_regs_icache_i ( IC_ctrl_unit_slave_if.ctrl_clear_regs ), + .ctrl_enable_regs_icache_i ( IC_ctrl_unit_slave_if.ctrl_enable_regs ) + ); + end + + + + + for(i=0;i TAG SCM Unified PORT + .SCM_TAG_write_req_o ( SCM_TAG_write_req_int ), + .SCM_TAG_write_addr_o ( SCM_TAG_write_addr_int ), + .SCM_TAG_write_dest_o ( SCM_TAG_write_dest_int ), + .SCM_TAG_write_wdata_o ( SCM_TAG_write_wdata_int ), + .SCM_TAG_write_way_o ( SCM_TAG_write_way_int ), + + // interface with WRITE PORT --> DATA SCM Unified PORT + .SCM_DATA_write_req_o ( SCM_DATA_write_req_int ), + .SCM_DATA_write_addr_o ( SCM_DATA_write_addr_int ), // double number of rows with respect TAG SCM ARRAY + .SCM_DATA_write_dest_o ( SCM_DATA_write_dest_int ), + .SCM_DATA_write_wdata_o( SCM_DATA_write_wdata_int ), + .SCM_DATA_write_way_o ( SCM_DATA_write_way_int ), + + //AXI read address bus ------------------------------------------- + .axi_master_arid_o ( axi_master_arid_int[AXI_ID_INT-1:0] ), + .axi_master_araddr_o ( axi_master_araddr_int ), + .axi_master_arlen_o ( axi_master_arlen_int ), + .axi_master_arsize_o ( axi_master_arsize_int ), + .axi_master_arburst_o ( axi_master_arburst_int ), + .axi_master_arlock_o ( axi_master_arlock_int ), + .axi_master_arcache_o ( axi_master_arcache_int ), + .axi_master_arprot_o ( axi_master_arprot_int ), + .axi_master_arregion_o ( axi_master_arregion_int ), + .axi_master_aruser_o ( axi_master_aruser_int ), + .axi_master_arqos_o ( axi_master_arqos_int ), + .axi_master_arvalid_o ( axi_master_arvalid_int ), + .axi_master_arready_i ( axi_master_arready_int ), + // --------------------------------------------------------------- + + + //AXI BACKWARD read data bus ---------------------------------------------- + .axi_master_rid_i ( axi_master_rid_int[AXI_ID_INT-1:0] ), + .axi_master_rdata_i ( axi_master_rdata_int ), + .axi_master_rresp_i ( axi_master_rresp_int ), + .axi_master_rlast_i ( axi_master_rlast_int ), + .axi_master_ruser_i ( axi_master_ruser_int ), + .axi_master_rvalid_i ( axi_master_rvalid_int ), + .axi_master_rready_o ( axi_master_rready_int ) + ); + + + + // Axi Write Channels tied to 0 + + assign axi_master_arid_o[AXI_ID-1:AXI_ID_INT] = '0; + + assign axi_master_awid_o = '0; + assign axi_master_awaddr_o = '0; + assign axi_master_awlen_o = '0; + assign axi_master_awsize_o = '0; + assign axi_master_awburst_o = '0; + assign axi_master_awlock_o = '0; + assign axi_master_awcache_o = '0; + assign axi_master_awprot_o = '0; + assign axi_master_awregion_o = '0; + assign axi_master_awuser_o = '0; + assign axi_master_awqos_o = '0; + assign axi_master_awvalid_o = '0; + assign axi_master_wdata_o = '0; + assign axi_master_wstrb_o = '0; + assign axi_master_wlast_o = '0; + assign axi_master_wuser_o = '0; + assign axi_master_wvalid_o = '0; + assign axi_master_bready_o = '0; + + +`ifdef USE_AXI_SLICES + + //////////////////////////////////////////////////////////////////////// + // █████╗ ██╗ ██╗██╗ ███████╗██╗ ██╗ ██████╗███████╗███████╗ // + // ██╔══██╗╚██╗██╔╝██║ ██╔════╝██║ ██║██╔════╝██╔════╝██╔════╝ // + // ███████║ ╚███╔╝ ██║ ███████╗██║ ██║██║ █████╗ ███████╗ // + // ██╔══██║ ██╔██╗ ██║ ╚════██║██║ ██║██║ ██╔══╝ ╚════██║ // + // ██║ ██║██╔╝ ██╗██║ ███████║███████╗██║╚██████╗███████╗███████║ // + // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═════╝╚══════╝╚══════╝ // + //////////////////////////////////////////////////////////////////////// + // to alleviate pressure on AXI side, this SLice can be added or not + // by defining the USE_AXI_SLICES macro. It will insert a AR and R slice on the AXI plug + axi_ar_buffer + #( + .ID_WIDTH ( AXI_ID_INT ), + .ADDR_WIDTH ( AXI_ADDR ), + .USER_WIDTH ( AXI_USER ), + .BUFFER_DEPTH ( 2 ) + ) + i_AXI_AR_BUFFER + ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_master_arvalid_int ), + .slave_addr_i ( axi_master_araddr_int ), + .slave_prot_i ( axi_master_arprot_int ), + .slave_region_i ( axi_master_arregion_int ), + .slave_len_i ( axi_master_arlen_int ), + .slave_size_i ( axi_master_arsize_int ), + .slave_burst_i ( axi_master_arburst_int ), + .slave_lock_i ( axi_master_arlock_int ), + .slave_cache_i ( axi_master_arcache_int ), + .slave_qos_i ( axi_master_arqos_int ), + .slave_id_i ( axi_master_arid_int[AXI_ID_INT-1:0] ), + .slave_user_i ( axi_master_aruser_int ), + .slave_ready_o ( axi_master_arready_int ), + + .master_valid_o ( axi_master_arvalid_o ), + .master_addr_o ( axi_master_araddr_o ), + .master_prot_o ( axi_master_arprot_o ), + .master_region_o ( axi_master_arregion_o ), + .master_len_o ( axi_master_arlen_o ), + .master_size_o ( axi_master_arsize_o ), + .master_burst_o ( axi_master_arburst_o ), + .master_lock_o ( axi_master_arlock_o ), + .master_cache_o ( axi_master_arcache_o ), + .master_qos_o ( axi_master_arqos_o ), + .master_id_o ( axi_master_arid_o[AXI_ID_INT-1:0] ), + .master_user_o ( axi_master_aruser_o ), + .master_ready_i ( axi_master_arready_i ) + ); + + axi_r_buffer + #( + .ID_WIDTH ( AXI_ID_INT ), + .DATA_WIDTH ( AXI_DATA ), + .USER_WIDTH ( AXI_USER ), + .BUFFER_DEPTH ( 2 ) + ) + i_AXI_R_BUFFER + ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_master_rvalid_i ), + .slave_data_i ( axi_master_rdata_i ), + .slave_resp_i ( axi_master_rresp_i ), + .slave_user_i ( axi_master_ruser_i ), + .slave_id_i ( axi_master_rid_i[AXI_ID_INT-1:0] ), + .slave_last_i ( axi_master_rlast_i ), + .slave_ready_o ( axi_master_rready_o ), + + .master_valid_o ( axi_master_rvalid_int ), + .master_data_o ( axi_master_rdata_int ), + .master_resp_o ( axi_master_rresp_int ), + .master_user_o ( axi_master_ruser_int ), + .master_id_o ( axi_master_rid_int[AXI_ID_INT-1:0] ), + .master_last_o ( axi_master_rlast_int ), + .master_ready_i ( axi_master_rready_int ) +); + +`else + assign axi_master_rvalid_int = axi_master_rvalid_i ; + assign axi_master_rdata_int = axi_master_rdata_i ; + assign axi_master_rresp_int = axi_master_rresp_i ; + assign axi_master_ruser_int = axi_master_ruser_i ; + assign axi_master_rid_int[AXI_ID_INT-1:0] = axi_master_rid_i[AXI_ID_INT-1:0] ; + assign axi_master_rlast_int = axi_master_rlast_i ; + assign axi_master_rready_o = axi_master_rready_int ; + + assign axi_master_arvalid_o = axi_master_arvalid_int ; + assign axi_master_araddr_o = axi_master_araddr_int ; + assign axi_master_arprot_o = axi_master_arprot_int ; + assign axi_master_arregion_o = axi_master_arregion_int ; + assign axi_master_arlen_o = axi_master_arlen_int ; + assign axi_master_arsize_o = axi_master_arsize_int ; + assign axi_master_arburst_o = axi_master_arburst_int ; + assign axi_master_arlock_o = axi_master_arlock_int ; + assign axi_master_arcache_o = axi_master_arcache_int ; + assign axi_master_arqos_o = axi_master_arqos_int ; + assign axi_master_arid_o[AXI_ID_INT-1:0] = axi_master_arid_int[AXI_ID_INT-1:0] ; + assign axi_master_aruser_o = axi_master_aruser_int ; + assign axi_master_arready_int = axi_master_arready_i ; +`endif + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ██████╗ ██████╗ ███████╗███████╗███████╗████████╗ ██████╗██╗ ██╗███████╗██████╗ ██████╗ ██████╗ // + // ██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝██║ ██║██╔════╝██╔══██╗ ██╔════╝██╔════╝ // + // ██████╔╝██████╔╝█████╗ █████╗ █████╗ ██║ ██║ ███████║█████╗ ██████╔╝ ██║ ██║ // + // ██╔═══╝ ██╔══██╗██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██╔══██║██╔══╝ ██╔══██╗ ██║ ██║ // + // ██║ ██║ ██║███████╗██║ ███████╗ ██║ ╚██████╗██║ ██║███████╗██║ ██║ ╚██████╗╚██████╗ // + // ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ // + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + + icache_bank_mp_128_PF + #( + .FETCH_ADDR_WIDTH ( FETCH_ADDR_WIDTH ), + .FETCH_DATA_WIDTH ( FETCH_DATA_WIDTH ), + + .NB_CORES ( NB_CORES+1 ), + .BANK_ID ( NB_CORES ), + .NB_BANKS ( NB_BANKS ), + .NB_WAYS ( NB_WAYS ), + .CACHE_LINE ( CACHE_LINE ), + + .SCM_ADDR_WIDTH ( SCM_TAG_ADDR_WIDTH ), + .SCM_TAG_WIDTH ( TAG_WIDTH ), + .SCM_DATA_WIDTH ( FETCH_DATA_WIDTH ), + + .SET_ID_LSB ( SET_ID_LSB ), + .SET_ID_MSB ( SET_ID_MSB ), + .TAG_LSB ( TAG_LSB ), + .TAG_MSB ( TAG_MSB ), + + .AXI_ID ( AXI_ID ), + .AXI_ADDR ( AXI_ADDR ), + .AXI_USER ( AXI_USER ), + .AXI_DATA ( AXI_DATA ) + ) + pf_cc + ( + .clk ( clk ), + .rst_n ( rst_n ), + .test_en_i ( test_en_i ), + + .notify_refill_done_i ( notify_refill_done[NB_CORES] ), + .bypass_icache_i ( bypass_icache ), + .empty_fifo_i ( empty_fifo ), + .cache_is_bypassed_o ( cache_is_bypassed[NB_CORES] ), + .bypass_status_i ( cache_is_bypassed ), + .retry_fetch_i ( retry_fetch[NB_CORES] ), + + + .fetch_req_i ( pf_req_to_cc ), + .fetch_addr_i ( pf_addr_to_cc ), + .fetch_gnt_o ( pf_gnt_from_cc ), + .fetch_rvalid_o ( pf_rvalid_from_cc ), + + .TAG_read_req_o ( TAG_read_req_int[NB_CORES] ), + .TAG_read_addr_o ( TAG_read_addr_int[NB_CORES] ), + .TAG_read_rdata_i ( TAG_ReadData[NB_CORES] ), + + + // To be multiplexed at the output of the XBAR_ICACHE + .fetch_req_o ( pf_req_to_master_cc ), + .fetch_addr_o ( pf_addr_to_master_cc ), + .fetch_way_o ( pf_way_to_master_cc ), + .fetch_gnt_i ( pf_gnt_from_master_cc ), + .fetch_rvalid_i ( pf_rvalid_from_master_cc ) + ); + + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ██╗ ██╗██╗ ██╗ ██████╗ ██████╗ ███████╗███████╗███████╗████████╗ ██████╗██╗ ██╗███████╗██████╗ // + // ██║ ██║██║ ██║ ██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝██║ ██║██╔════╝██╔══██╗ // + // ███████║██║ █╗ ██║ ██████╔╝██████╔╝█████╗ █████╗ █████╗ ██║ ██║ ███████║█████╗ ██████╔╝ // + // ██╔══██║██║███╗██║ ██╔═══╝ ██╔══██╗██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██╔══██║██╔══╝ ██╔══██╗ // + // ██║ ██║╚███╔███╔╝ ██║ ██║ ██║███████╗██║ ███████╗ ██║ ╚██████╗██║ ██║███████╗██║ ██║ // + // ╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ // + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + prefetcher_if sw_prefetcher_if + ( + .clk ( clk ), + .rst_n ( rst_n ), + .test_en_i ( test_en_i ), + + + .pf_addr_i ( IC_ctrl_unit_slave_if.pf_addr ), + .pf_size_i ( IC_ctrl_unit_slave_if.pf_size ), + .pf_req_i ( IC_ctrl_unit_slave_if.pf_req ), + .pf_ack_o ( IC_ctrl_unit_slave_if.pf_ack ), + .pf_done_o ( IC_ctrl_unit_slave_if.pf_done ), + + + .pf_req_o ( pf_req_to_cc ), + .pf_addr_o ( pf_addr_to_cc ), + .pf_gnt_i ( pf_gnt_from_cc ), + .pf_rvalid_i ( pf_rvalid_from_cc ) + ); +endmodule // icache_top_scm_mp diff --git a/hw/deps/icache_mp_128_pf/RTL/merge_refill_cam_128_16.sv b/hw/deps/icache_mp_128_pf/RTL/merge_refill_cam_128_16.sv new file mode 100644 index 0000000..c9c7bd6 --- /dev/null +++ b/hw/deps/icache_mp_128_pf/RTL/merge_refill_cam_128_16.sv @@ -0,0 +1,544 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2018 ETH Zurich and 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. // +// // +// Company: Micrel Lab @ DEIS - University of Bologna // +// Viale Risorgimento 2 40136 // +// Bologna - fax 0512093785 - // +// // +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// // +// // +// // +// Create Date: 22/01/2018 // +// Design Name: ICACHE_MP_128_PF // +// Module Name: merge_refill_cam_128_16 // +// Project Name: MrWolf // +// Language: SystemVerilog // +// // +// Description: This block implemets a CAM with 16 slots, used to track // +// outstanding refills. Anytime a refill is required, the // +// main CC first checks that there is not yet a pending refill// +// on that cache line. If yes, it simply updated that Entry // +// of the cam. In case there is no valid entry, it pushed // +// refill info in the CAM , and it assertd a refill. // +// When Refill is Back from AXI port, the related entry is // +// popped, and all the related processor are notified. // +// // +// // +// Revision: // +// Revision v0.1 - 22/01/2018 : File Created // +// Additional Comments: // +// // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + + +module merge_refill_cam_128_16 +#( + parameter NB_WAYS = 4, + parameter ID_WIDTH = 4, + parameter LOG2_ID_WIDTH = $clog2(ID_WIDTH), + parameter ADDR_WIDTH = 32, + parameter DEPTH = 16, + parameter LOG2_DEPTH = $clog2(DEPTH), + parameter ADDR_CHECK_LSB = 4, + parameter ADDR_CHECK_MSB = ADDR_WIDTH-1 +) +( + input logic clk, + input logic rst_n, + + output logic empty_o, + + input logic fetch_req_i, + input logic [LOG2_ID_WIDTH-1:0] fetch_ID_BIN_i, + input logic [ID_WIDTH-1:0] fetch_ID_OH_i, + input logic [ADDR_WIDTH-1:0] fetch_addr_i, + input logic [NB_WAYS-1:0] fetch_way_i, + output logic fetch_gnt_o, + output logic [ID_WIDTH-1:0] retry_fetch_o, + + input logic AXI_rvalid_i, + input logic [LOG2_DEPTH-1:0] AXI_rID_i, + + output logic AXI_req_o, + output logic [ADDR_WIDTH-1:0] AXI_addr_o, + output logic [LOG2_DEPTH-1:0] AXI_ID_o, + input logic AXI_gnt_i, + + + // for refill PURPOSE ONLY + output logic [ADDR_WIDTH-1:0] refill_addr_o, + output logic [ID_WIDTH-1:0] refill_ID_o, + output logic [NB_WAYS-1:0] refill_way_o +); + + + logic [DEPTH-1:0] LOOKUP_TABLE; + logic [ID_WIDTH-1:0] ID_TABLE [DEPTH-1:0]; + logic [NB_WAYS+ADDR_WIDTH-1:0] ADDR_TABLE [DEPTH-1:0]; + + logic [DEPTH-1:0] check_push_Match_addr; + logic [$clog2(DEPTH)-1:0] push_MATCH_index; + + logic [ADDR_WIDTH-1:0] last_refill_addr; + logic last_refill_valid; + logic FIFO_full; + + + + assign FIFO_full = (&LOOKUP_TABLE) ? 1'b1 : 1'b0; + assign empty_o = (|LOOKUP_TABLE) ? 1'b0 : 1'b1; + + + assign refill_addr_o = {ADDR_TABLE[AXI_rID_i][ADDR_WIDTH-1:0]}; + assign refill_way_o = ADDR_TABLE[AXI_rID_i][NB_WAYS+ADDR_WIDTH-1:ADDR_WIDTH]; + assign refill_ID_o = ID_TABLE[AXI_rID_i]; + + + int unsigned i,j,k; + + + always_ff @(posedge clk or negedge rst_n) + begin + if(~rst_n) + begin + for(i=0; i + +module per2axi +#( + parameter NB_CORES = 4, + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + // PERIPHERAL INTERCONNECT SLAVE + //*************************************** + //REQUEST CHANNEL + input logic per_slave_req_i, + input logic [PER_ADDR_WIDTH-1:0] per_slave_add_i, + input logic per_slave_we_i, + input logic [5:0] per_slave_atop_i, + input logic [31:0] per_slave_wdata_i, + input logic [3:0] per_slave_be_i, + input logic [PER_ID_WIDTH-1:0] per_slave_id_i, + output logic per_slave_gnt_o, + + //RESPONSE CHANNEL + output logic per_slave_r_valid_o, + output logic per_slave_r_opc_o, + output logic [PER_ID_WIDTH-1:0] per_slave_r_id_o, + output logic [31:0] per_slave_r_rdata_o, + + // TRYX CTRL + input logic [NB_CORES-1:0][AXI_USER_WIDTH-1:0] axi_axuser_i, + output logic [NB_CORES-1:0] axi_xresp_decerr_o, + output logic [NB_CORES-1:0] axi_xresp_slverr_o, + output logic [NB_CORES-1:0] axi_xresp_valid_o, + + // AXI4 MASTER + //*************************************** + // WRITE ADDRESS CHANNEL + output logic axi_master_aw_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_aw_addr_o, + output logic [2:0] axi_master_aw_prot_o, + output logic [3:0] axi_master_aw_region_o, + output logic [7:0] axi_master_aw_len_o, + output logic [2:0] axi_master_aw_size_o, + output logic [1:0] axi_master_aw_burst_o, + output logic axi_master_aw_lock_o, + output logic [5:0] axi_master_aw_atop_o, + output logic [3:0] axi_master_aw_cache_o, + output logic [3:0] axi_master_aw_qos_o, + output logic [AXI_ID_WIDTH-1:0] axi_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_aw_user_o, + input logic axi_master_aw_ready_i, + + // READ ADDRESS CHANNEL + output logic axi_master_ar_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_ar_addr_o, + output logic [2:0] axi_master_ar_prot_o, + output logic [3:0] axi_master_ar_region_o, + output logic [7:0] axi_master_ar_len_o, + output logic [2:0] axi_master_ar_size_o, + output logic [1:0] axi_master_ar_burst_o, + output logic axi_master_ar_lock_o, + output logic [3:0] axi_master_ar_cache_o, + output logic [3:0] axi_master_ar_qos_o, + output logic [AXI_ID_WIDTH-1:0] axi_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_ar_user_o, + input logic axi_master_ar_ready_i, + + // WRITE DATA CHANNEL + output logic axi_master_w_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_master_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] axi_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_w_user_o, + output logic axi_master_w_last_o, + input logic axi_master_w_ready_i, + + // READ DATA CHANNEL + input logic axi_master_r_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_master_r_data_i, + input logic [1:0] axi_master_r_resp_i, + input logic axi_master_r_last_i, + input logic [AXI_ID_WIDTH-1:0] axi_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_r_user_i, + output logic axi_master_r_ready_o, + + // WRITE RESPONSE CHANNEL + input logic axi_master_b_valid_i, + input logic [1:0] axi_master_b_resp_i, + input logic [AXI_ID_WIDTH-1:0] axi_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_b_user_i, + output logic axi_master_b_ready_o, + + // BUSY SIGNAL + output logic busy_o + ); + + // SIGNAL DECLARATION + logic s_aw_valid; + logic [AXI_ADDR_WIDTH-1:0] s_aw_addr; + logic [2:0] s_aw_prot; + logic [3:0] s_aw_region; + logic [7:0] s_aw_len; + logic [2:0] s_aw_size; + logic [1:0] s_aw_burst; + logic s_aw_lock; + logic [5:0] s_aw_atop; + logic [3:0] s_aw_cache; + logic [3:0] s_aw_qos; + logic [AXI_ID_WIDTH-1:0] s_aw_id; + logic [AXI_USER_WIDTH-1:0] s_aw_user; + logic s_aw_ready; + + logic s_ar_valid; + logic [AXI_ADDR_WIDTH-1:0] s_ar_addr; + logic [2:0] s_ar_prot; + logic [3:0] s_ar_region; + logic [7:0] s_ar_len; + logic [2:0] s_ar_size; + logic [1:0] s_ar_burst; + logic s_ar_lock; + logic [3:0] s_ar_cache; + logic [3:0] s_ar_qos; + logic [AXI_ID_WIDTH-1:0] s_ar_id; + logic [AXI_USER_WIDTH-1:0] s_ar_user; + logic s_ar_ready; + + logic s_w_valid; + logic [AXI_DATA_WIDTH-1:0] s_w_data; + logic [AXI_STRB_WIDTH-1:0] s_w_strb; + logic [AXI_USER_WIDTH-1:0] s_w_user; + logic s_w_last; + logic s_w_ready; + + logic s_r_valid; + logic [AXI_DATA_WIDTH-1:0] s_r_data; + logic [1:0] s_r_resp; + logic s_r_last; + logic [AXI_ID_WIDTH-1:0] s_r_id; + logic [AXI_USER_WIDTH-1:0] s_r_user; + logic s_r_ready; + + logic s_b_valid; + logic [1:0] s_b_resp; + logic [AXI_ID_WIDTH-1:0] s_b_id; + logic [AXI_USER_WIDTH-1:0] s_b_user; + logic s_b_ready; + + logic s_atop_req; + logic [AXI_ID_WIDTH-1:0] s_atop_id; + logic [AXI_ADDR_WIDTH-1:0] s_atop_add; + + logic s_trans_req; + logic [AXI_ID_WIDTH-1:0] s_trans_id; + logic [AXI_ADDR_WIDTH-1:0] s_trans_add; + + + // PER2AXI REQUEST CHANNEL + per2axi_req_channel + #( + .NB_CORES ( NB_CORES ), + .PER_ID_WIDTH ( PER_ID_WIDTH ), + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ) + ) + req_channel_i + ( + .clk_i, + .rst_ni, + .per_slave_req_i ( per_slave_req_i ), + .per_slave_add_i ( per_slave_add_i ), + .per_slave_we_i ( per_slave_we_i ), + .per_slave_atop_i ( per_slave_atop_i ), + .per_slave_wdata_i ( per_slave_wdata_i ), + .per_slave_be_i ( per_slave_be_i ), + .per_slave_id_i ( per_slave_id_i ), + .per_slave_gnt_o ( per_slave_gnt_o ), + + .axi_axuser_i ( axi_axuser_i ), + + .axi_master_aw_valid_o ( s_aw_valid ), + .axi_master_aw_addr_o ( s_aw_addr ), + .axi_master_aw_prot_o ( s_aw_prot ), + .axi_master_aw_region_o ( s_aw_region ), + .axi_master_aw_len_o ( s_aw_len ), + .axi_master_aw_size_o ( s_aw_size ), + .axi_master_aw_burst_o ( s_aw_burst ), + .axi_master_aw_lock_o ( s_aw_lock ), + .axi_master_aw_atop_o ( s_aw_atop ), + .axi_master_aw_cache_o ( s_aw_cache ), + .axi_master_aw_qos_o ( s_aw_qos ), + .axi_master_aw_id_o ( s_aw_id ), + .axi_master_aw_user_o ( s_aw_user ), + .axi_master_aw_ready_i ( s_aw_ready ), + + .axi_master_ar_valid_o ( s_ar_valid ), + .axi_master_ar_addr_o ( s_ar_addr ), + .axi_master_ar_prot_o ( s_ar_prot ), + .axi_master_ar_region_o ( s_ar_region ), + .axi_master_ar_len_o ( s_ar_len ), + .axi_master_ar_size_o ( s_ar_size ), + .axi_master_ar_burst_o ( s_ar_burst ), + .axi_master_ar_lock_o ( s_ar_lock ), + .axi_master_ar_cache_o ( s_ar_cache ), + .axi_master_ar_qos_o ( s_ar_qos ), + .axi_master_ar_id_o ( s_ar_id ), + .axi_master_ar_user_o ( s_ar_user ), + .axi_master_ar_ready_i ( s_ar_ready ), + + .axi_master_w_valid_o ( s_w_valid ), + .axi_master_w_data_o ( s_w_data ), + .axi_master_w_strb_o ( s_w_strb ), + .axi_master_w_user_o ( s_w_user ), + .axi_master_w_last_o ( s_w_last ), + .axi_master_w_ready_i ( s_w_ready ), + + .atop_req_o ( s_atop_req ), + .atop_id_o ( s_atop_id ), + .atop_add_o ( s_atop_add ), + + .trans_req_o ( s_trans_req ), + .trans_id_o ( s_trans_id ), + .trans_add_o ( s_trans_add ) + ); + + // PER2AXI RESPONSE CHANNEL + per2axi_res_channel + #( + .NB_CORES ( NB_CORES ), + .PER_ID_WIDTH ( PER_ID_WIDTH ), + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) + res_channel_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .per_slave_r_valid_o ( per_slave_r_valid_o ), + .per_slave_r_opc_o ( per_slave_r_opc_o ), + .per_slave_r_id_o ( per_slave_r_id_o ), + .per_slave_r_rdata_o ( per_slave_r_rdata_o ), + + .axi_xresp_decerr_o ( axi_xresp_decerr_o ), + .axi_xresp_slverr_o ( axi_xresp_slverr_o ), + .axi_xresp_valid_o ( axi_xresp_valid_o ), + + .axi_master_r_valid_i ( s_r_valid ), + .axi_master_r_data_i ( s_r_data ), + .axi_master_r_resp_i ( s_r_resp ), + .axi_master_r_last_i ( s_r_last ), + .axi_master_r_id_i ( s_r_id ), + .axi_master_r_user_i ( s_r_user ), + .axi_master_r_ready_o ( s_r_ready ), + + .axi_master_b_valid_i ( s_b_valid ), + .axi_master_b_resp_i ( s_b_resp ), + .axi_master_b_id_i ( s_b_id ), + .axi_master_b_user_i ( s_b_user ), + .axi_master_b_ready_o ( s_b_ready ), + + .atop_req_i ( s_atop_req ), + .atop_id_i ( s_atop_id ), + .atop_add_i ( s_atop_add ), + + .trans_req_i ( s_trans_req ), + .trans_id_i ( s_trans_id ), + .trans_add_i ( s_trans_add ) + ); + + // BUSY UNIT + per2axi_busy_unit busy_unit_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + // WRITE INTERFACE + .aw_sync_i ( s_aw_valid & s_aw_ready ), + .b_sync_i ( s_b_valid & s_b_ready ), + + // READ INTERFACE + .ar_sync_i ( s_ar_valid & s_ar_ready ), + .r_sync_i ( s_r_valid & s_r_ready & s_r_last ), + + // BUSY SIGNAL + .busy_o ( busy_o ) + ); + + // AXI WRITE ADDRESS CHANNEL BUFFER + axi_aw_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( NB_CORES ) + ) + aw_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( s_aw_valid ), + .slave_addr_i ( s_aw_addr ), + .slave_prot_i ( s_aw_prot ), + .slave_region_i ( s_aw_region ), + .slave_len_i ( s_aw_len ), + .slave_size_i ( s_aw_size ), + .slave_burst_i ( s_aw_burst ), + .slave_lock_i ( s_aw_lock ), + .slave_atop_i ( s_aw_atop ), + .slave_cache_i ( s_aw_cache ), + .slave_qos_i ( s_aw_qos ), + .slave_id_i ( s_aw_id ), + .slave_user_i ( s_aw_user ), + .slave_ready_o ( s_aw_ready ), + + .master_valid_o ( axi_master_aw_valid_o ), + .master_addr_o ( axi_master_aw_addr_o ), + .master_prot_o ( axi_master_aw_prot_o ), + .master_region_o ( axi_master_aw_region_o ), + .master_len_o ( axi_master_aw_len_o ), + .master_size_o ( axi_master_aw_size_o ), + .master_burst_o ( axi_master_aw_burst_o ), + .master_lock_o ( axi_master_aw_lock_o ), + .master_atop_o ( axi_master_aw_atop_o ), + .master_cache_o ( axi_master_aw_cache_o ), + .master_qos_o ( axi_master_aw_qos_o ), + .master_id_o ( axi_master_aw_id_o ), + .master_user_o ( axi_master_aw_user_o ), + .master_ready_i ( axi_master_aw_ready_i ) + ); + + // AXI READ ADDRESS CHANNEL BUFFER + axi_ar_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( NB_CORES ) + ) + ar_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( s_ar_valid ), + .slave_addr_i ( s_ar_addr ), + .slave_prot_i ( s_ar_prot ), + .slave_region_i ( s_ar_region ), + .slave_len_i ( s_ar_len ), + .slave_size_i ( s_ar_size ), + .slave_burst_i ( s_ar_burst ), + .slave_lock_i ( s_ar_lock ), + .slave_cache_i ( s_ar_cache ), + .slave_qos_i ( s_ar_qos ), + .slave_id_i ( s_ar_id ), + .slave_user_i ( s_ar_user ), + .slave_ready_o ( s_ar_ready ), + + .master_valid_o ( axi_master_ar_valid_o ), + .master_addr_o ( axi_master_ar_addr_o ), + .master_prot_o ( axi_master_ar_prot_o ), + .master_region_o ( axi_master_ar_region_o ), + .master_len_o ( axi_master_ar_len_o ), + .master_size_o ( axi_master_ar_size_o ), + .master_burst_o ( axi_master_ar_burst_o ), + .master_lock_o ( axi_master_ar_lock_o ), + .master_cache_o ( axi_master_ar_cache_o ), + .master_qos_o ( axi_master_ar_qos_o ), + .master_id_o ( axi_master_ar_id_o ), + .master_user_o ( axi_master_ar_user_o ), + .master_ready_i ( axi_master_ar_ready_i ) + ); + + // WRITE DATA CHANNEL BUFFER + axi_w_buffer + #( + .DATA_WIDTH ( AXI_DATA_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( NB_CORES ) + ) + w_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( s_w_valid ), + .slave_data_i ( s_w_data ), + .slave_strb_i ( s_w_strb ), + .slave_user_i ( s_w_user ), + .slave_last_i ( s_w_last ), + .slave_ready_o ( s_w_ready ), + + .master_valid_o ( axi_master_w_valid_o ), + .master_data_o ( axi_master_w_data_o ), + .master_strb_o ( axi_master_w_strb_o ), + .master_user_o ( axi_master_w_user_o ), + .master_last_o ( axi_master_w_last_o ), + .master_ready_i ( axi_master_w_ready_i ) + ); + + // READ DATA CHANNEL BUFFER + axi_r_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .DATA_WIDTH ( AXI_DATA_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( 2 ) + ) + r_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_master_r_valid_i ), + .slave_data_i ( axi_master_r_data_i ), + .slave_resp_i ( axi_master_r_resp_i ), + .slave_user_i ( axi_master_r_user_i ), + .slave_id_i ( axi_master_r_id_i ), + .slave_last_i ( axi_master_r_last_i ), + .slave_ready_o ( axi_master_r_ready_o ), + + .master_valid_o ( s_r_valid ), + .master_data_o ( s_r_data ), + .master_resp_o ( s_r_resp ), + .master_user_o ( s_r_user ), + .master_id_o ( s_r_id ), + .master_last_o ( s_r_last ), + .master_ready_i ( s_r_ready ) + ); + + // WRITE RESPONSE CHANNEL BUFFER + axi_b_buffer + #( + .ID_WIDTH ( AXI_ID_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_DEPTH ( 2 ) + ) + b_buffer_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .slave_valid_i ( axi_master_b_valid_i ), + .slave_resp_i ( axi_master_b_resp_i ), + .slave_id_i ( axi_master_b_id_i ), + .slave_user_i ( axi_master_b_user_i ), + .slave_ready_o ( axi_master_b_ready_o ), + + .master_valid_o ( s_b_valid ), + .master_resp_o ( s_b_resp ), + .master_id_o ( s_b_id ), + .master_user_o ( s_b_user ), + .master_ready_i ( s_b_ready ) + ); + +endmodule diff --git a/hw/deps/per2axi/src/per2axi_busy_unit.sv b/hw/deps/per2axi/src/per2axi_busy_unit.sv new file mode 100644 index 0000000..315567e --- /dev/null +++ b/hw/deps/per2axi/src/per2axi_busy_unit.sv @@ -0,0 +1,72 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module per2axi_busy_unit +( + input logic clk_i, + input logic rst_ni, + + // WRITE INTERFACE + input logic aw_sync_i, + input logic b_sync_i, + + // READ INTERFACE + input logic ar_sync_i, + input logic r_sync_i, + + // BUSY SIGNAL + output logic busy_o +); + + logic [3:0] s_aw_trans_count; + logic [3:0] s_ar_trans_count; + + //COUNTER FOR NUMBER OF AW TRANSACTIONS + always_ff @ (posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + s_aw_trans_count <= '0; + else + if ( aw_sync_i == 1'b1 && b_sync_i == 1'b0 ) + s_aw_trans_count <= s_aw_trans_count+1; + else + if ( aw_sync_i == 1'b0 && b_sync_i == 1'b1 ) + s_aw_trans_count <= s_aw_trans_count-1; + else + s_aw_trans_count <= s_aw_trans_count; + end + + //COUNTER FOR NUMBER OF AR TRANSACTIONS + always_ff @ (posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + s_ar_trans_count <= '0; + else + if ( ar_sync_i == 1'b1 && r_sync_i == 1'b0 ) + s_ar_trans_count <= s_ar_trans_count+1; + else + if ( ar_sync_i == 1'b0 && r_sync_i == 1'b1 ) + s_ar_trans_count <= s_ar_trans_count-1; + else + s_ar_trans_count <= s_ar_trans_count; + end + + // GENERATION OF BUSY SIGNAL + always_comb + begin + if ( s_ar_trans_count == 0 && s_aw_trans_count == 0 ) + busy_o = 1'b0; + else + busy_o = 1'b1; + end + +endmodule diff --git a/hw/deps/per2axi/src/per2axi_req_channel.sv b/hw/deps/per2axi/src/per2axi_req_channel.sv new file mode 100644 index 0000000..6dce9ad --- /dev/null +++ b/hw/deps/per2axi/src/per2axi_req_channel.sv @@ -0,0 +1,309 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +import riscv_defines::*; + +module per2axi_req_channel +#( + // PARAMETERS + parameter NB_CORES = 4, + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3, + // LOCAL PARAMETERS --> DO NOT OVERRIDE + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 // DO NOT OVERRIDE +) +( + input logic clk_i, + input logic rst_ni, + + // PERIPHERAL INTERCONNECT SLAVE + //*************************************** + //REQUEST CHANNEL + input logic per_slave_req_i, + input logic [PER_ADDR_WIDTH-1:0] per_slave_add_i, + input logic per_slave_we_i, + input logic [5:0] per_slave_atop_i, + input logic [31:0] per_slave_wdata_i, + input logic [3:0] per_slave_be_i, + input logic [PER_ID_WIDTH-1:0] per_slave_id_i, + output logic per_slave_gnt_o, + + // TRYX CTRL + input logic [NB_CORES-1:0][AXI_USER_WIDTH-1:0] axi_axuser_i, + + // AXI4 MASTER + //*************************************** + // WRITE ADDRESS CHANNEL + output logic axi_master_aw_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_aw_addr_o, + output logic [2:0] axi_master_aw_prot_o, + output logic [3:0] axi_master_aw_region_o, + output logic [7:0] axi_master_aw_len_o, + output logic [2:0] axi_master_aw_size_o, + output logic [1:0] axi_master_aw_burst_o, + output logic axi_master_aw_lock_o, + output logic [5:0] axi_master_aw_atop_o, + output logic [3:0] axi_master_aw_cache_o, + output logic [3:0] axi_master_aw_qos_o, + output logic [AXI_ID_WIDTH-1:0] axi_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_aw_user_o, + input logic axi_master_aw_ready_i, + + // READ ADDRESS CHANNEL + output logic axi_master_ar_valid_o, + output logic [AXI_ADDR_WIDTH-1:0] axi_master_ar_addr_o, + output logic [2:0] axi_master_ar_prot_o, + output logic [3:0] axi_master_ar_region_o, + output logic [7:0] axi_master_ar_len_o, + output logic [2:0] axi_master_ar_size_o, + output logic [1:0] axi_master_ar_burst_o, + output logic axi_master_ar_lock_o, + output logic [3:0] axi_master_ar_cache_o, + output logic [3:0] axi_master_ar_qos_o, + output logic [AXI_ID_WIDTH-1:0] axi_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_ar_user_o, + input logic axi_master_ar_ready_i, + + // WRITE DATA CHANNEL + output logic axi_master_w_valid_o, + output logic [AXI_DATA_WIDTH-1:0] axi_master_w_data_o, + output logic [AXI_STRB_WIDTH-1:0] axi_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] axi_master_w_user_o, + output logic axi_master_w_last_o, + input logic axi_master_w_ready_i, + + // CONTROL SIGNALS + output logic atop_req_o, + output logic [AXI_ID_WIDTH-1:0] atop_id_o, + output logic [AXI_ADDR_WIDTH-1:0] atop_add_o, + + output logic trans_req_o, + output logic [AXI_ID_WIDTH-1:0] trans_id_o, + output logic [AXI_ADDR_WIDTH-1:0] trans_add_o +); + + integer i; + + // AWATOP signal for AXI-5 + // TODO: When upgrading to AXI-5 declare as output + logic [5:0] awatop; + + // Input data signal + logic [31:0] per_slave_wdata; + logic inv_wdata; + + // Atomic operation defines + parameter AWATOP_SWAP = 6'b110000; + parameter AWATOP_COMPARE = 6'b110001; + + parameter AWATOP_STORE = 3'b010; + parameter AWATOP_LOAD = 3'b100; + + parameter AWATOP_ADD = 3'b000; + parameter AWATOP_CLR = 3'b001; + parameter AWATOP_XOR = 3'b010; + parameter AWATOP_SET = 3'b011; + parameter AWATOP_SMAX = 3'b100; + parameter AWATOP_SMIN = 3'b101; + parameter AWATOP_UMAX = 3'b110; + parameter AWATOP_UMIN = 3'b111; + + assign axi_master_aw_atop_o = awatop; + + // AXI REQUEST GENERATION + always_comb + begin + axi_master_ar_valid_o = 1'b0; + axi_master_aw_valid_o = 1'b0; + axi_master_w_valid_o = 1'b0; + axi_master_w_last_o = 1'b0; + + if (per_slave_req_i == 1'b1 && // REQUEST FROM PERIPHERAL INTERCONNECT + per_slave_we_i == 1'b0 && // WRITE OPERATION + axi_master_aw_ready_i == 1'b1 && // AXI WRITE ADDRESS CHANNEL AVAILABLE + axi_master_w_ready_i == 1'b1 ) // AXI WRITE DATA CHANNEL AVAILABLE + begin + axi_master_aw_valid_o = 1'b1; + axi_master_w_valid_o = 1'b1; + axi_master_w_last_o = 1'b1; + end + else + if (per_slave_req_i == 1'b1 && // REQUEST FROM PERIPHERAL INTERCONNECT + per_slave_we_i == 1'b1 && // READ OPERATION + axi_master_ar_ready_i == 1'b1) // AXI WRITE ADDRESS CHANNEL AVAILABLE + begin + axi_master_ar_valid_o = 1'b1; + end + end + + // AXI ATOMIC ACCESS LOCK GENERATION + always_comb + begin + axi_master_aw_lock_o = 1'b0; + axi_master_ar_lock_o = 1'b0; + awatop = 6'b000000; + inv_wdata = 1'b0; + + if (per_slave_atop_i[5] == 1'b1) begin + unique case (per_slave_atop_i[4:0]) + AMO_LR: begin // ATOMIC LOAD-RESERVED OPERATION + axi_master_ar_lock_o = 1'b1; + end + AMO_SC: begin // ATOMIC STORE-CONDITIONAL OPERATION + axi_master_aw_lock_o = 1'b1; + end + AMO_SWAP: begin + awatop = AWATOP_SWAP; + end + AMO_ADD: begin + awatop = {AWATOP_LOAD, AWATOP_ADD}; + end + AMO_XOR: begin + awatop = {AWATOP_LOAD, AWATOP_XOR}; + end + AMO_AND: begin + awatop = {AWATOP_LOAD, AWATOP_CLR}; + inv_wdata = 1'b1; // Invert data to emulate an AND with a clear + end + AMO_OR: begin + awatop = {AWATOP_LOAD, AWATOP_SET}; + end + AMO_MIN: begin + awatop = {AWATOP_LOAD, AWATOP_SMIN}; + end + AMO_MAX: begin + awatop = {AWATOP_LOAD, AWATOP_SMAX}; + end + AMO_MINU: begin + awatop = {AWATOP_LOAD, AWATOP_UMIN}; + end + AMO_MAXU: begin + awatop = {AWATOP_LOAD, AWATOP_UMAX}; + end + default : begin end + endcase + end + end + + // AXI ADDRESS GENERATION + assign axi_master_aw_addr_o = per_slave_add_i; + assign axi_master_ar_addr_o = per_slave_add_i; + + // AXI ID GENERATION - ONEHOT TO BIN DECODING + always_comb + begin + axi_master_aw_id_o = '0; + axi_master_ar_id_o = '0; + for ( i=0; i per_slave_be_i[per_slave_add_i[1:0]]) + else $error("Byte enable of addressed byte must be active"); + logic [1:0] be_trailing_zeros; + lzc #( + .WIDTH (4), + .MODE (1'b0) + ) i_lzc_be_trailing ( + .in_i (per_slave_be_i), + .cnt_o (be_trailing_zeros), + .empty_o (/* unused */) + ); + assume property (@(posedge clk_i) per_slave_req_i + |-> per_slave_add_i[1:0] == be_trailing_zeros) + else $error("No byte enable below addressed byte may be active!"); + `endif + `endif + + // use FIXED burst type, length is anyway 0 + assign axi_master_aw_burst_o = 2'b00; + assign axi_master_ar_burst_o = 2'b00; + + // TRANSACTION REQUEST GENERATION + assign trans_req_o = axi_master_ar_valid_o; + assign trans_id_o = axi_master_ar_id_o; + assign trans_add_o = axi_master_ar_addr_o; + + assign atop_req_o = (axi_master_aw_atop_o[5:3] == AWATOP_STORE) ? 1'b0 : |axi_master_aw_atop_o; + assign atop_id_o = axi_master_aw_id_o; + assign atop_add_o = axi_master_aw_addr_o; + + // UNUSED SIGNALS + assign axi_master_aw_prot_o = '0; + assign axi_master_aw_region_o = '0; + assign axi_master_aw_len_o = '0; + assign axi_master_aw_cache_o = '0; + assign axi_master_aw_qos_o = 4'b0001; + assign axi_master_aw_user_o = axi_axuser_i[axi_master_aw_id_o]; + + assign axi_master_ar_prot_o = '0; + assign axi_master_ar_region_o = '0; + assign axi_master_ar_len_o = '0; + assign axi_master_ar_cache_o = '0; + assign axi_master_ar_qos_o = 4'b0001; + assign axi_master_ar_user_o = axi_axuser_i[axi_master_aw_id_o]; + + assign axi_master_w_user_o = '0; + +endmodule diff --git a/hw/deps/per2axi/src/per2axi_res_channel.sv b/hw/deps/per2axi/src/per2axi_res_channel.sv new file mode 100644 index 0000000..a5e8c23 --- /dev/null +++ b/hw/deps/per2axi/src/per2axi_res_channel.sv @@ -0,0 +1,213 @@ +// Copyright 2018 ETH Zurich and 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. + +// Davide Rossi + +module per2axi_res_channel +#( + // PARAMETERS + parameter NB_CORES = 4, + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 3 +) +( + input logic clk_i, + input logic rst_ni, + + // PERIPHERAL INTERCONNECT SLAVE + //*************************************** + //RESPONSE CHANNEL + output logic per_slave_r_valid_o, + output logic per_slave_r_opc_o, + output logic [PER_ID_WIDTH-1:0] per_slave_r_id_o, + output logic [31:0] per_slave_r_rdata_o, + + // TRYX CTRL + output logic [NB_CORES-1:0] axi_xresp_decerr_o, + output logic [NB_CORES-1:0] axi_xresp_slverr_o, + output logic [NB_CORES-1:0] axi_xresp_valid_o, + + // AXI4 MASTER + //*************************************** + // READ DATA CHANNEL + input logic axi_master_r_valid_i, + input logic [AXI_DATA_WIDTH-1:0] axi_master_r_data_i, + input logic [1:0] axi_master_r_resp_i, + input logic axi_master_r_last_i, + input logic [AXI_ID_WIDTH-1:0] axi_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_r_user_i, + output logic axi_master_r_ready_o, + + // WRITE RESPONSE CHANNEL + input logic axi_master_b_valid_i, + input logic [1:0] axi_master_b_resp_i, + input logic [AXI_ID_WIDTH-1:0] axi_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] axi_master_b_user_i, + output logic axi_master_b_ready_o, + + // CONTROL SIGNALS + input logic atop_req_i, + input logic [AXI_ID_WIDTH-1:0] atop_id_i, + input logic [AXI_ADDR_WIDTH-1:0] atop_add_i, + + input logic trans_req_i, + input logic [AXI_ID_WIDTH-1:0] trans_id_i, + input logic [AXI_ADDR_WIDTH-1:0] trans_add_i +); + + logic [31:0] s_per_slave_r_data; + logic [PER_ID_WIDTH-1:0] s_read_add_buf; + + typedef enum logic [1:0] { NONE, REQUEST, WAIT_R, WAIT_B } atop_res_t; + atop_res_t [PER_ID_WIDTH-1:0] atop_state_d, atop_state_q; + + // Handle responses. + always_comb begin + axi_master_b_ready_o = 1'b0; + axi_master_r_ready_o = 1'b0; + axi_xresp_decerr_o = '0; + axi_xresp_slverr_o = '0; + axi_xresp_valid_o = '0; + per_slave_r_id_o = '0; + per_slave_r_opc_o = '0; + per_slave_r_rdata_o = '0; + per_slave_r_valid_o = 1'b0; + + if (axi_master_r_valid_i) begin + axi_master_r_ready_o = 1'b1; + per_slave_r_id_o[axi_master_r_id_i] = 1'b1; + per_slave_r_rdata_o = s_per_slave_r_data; + per_slave_r_valid_o = 1'b1; + if (axi_master_r_resp_i[1]) begin // error + axi_xresp_valid_o[axi_master_r_id_i] = 1'b1; + if (axi_master_r_resp_i[0]) begin // decoding error + axi_xresp_decerr_o[axi_master_r_id_i] = 1'b1; + end else begin // slave error (e.g. RAB miss) + axi_xresp_slverr_o[axi_master_r_id_i] = 1'b1; + end + end + end else if (axi_master_b_valid_i) begin + axi_master_b_ready_o = 1'b1; + if (atop_state_q[axi_master_b_id_i] == NONE) begin + per_slave_r_valid_o = 1'b1; + per_slave_r_id_o[axi_master_b_id_i] = 1'b1; + + // Forward response/error to core. + // axi_master_b_resp_i[1:0] -> per_slave_r_rdata_o[1:0] + // 00 -> 01, 01 -> 00, 10 -> 10, 11 -> 11 + per_slave_r_rdata_o + = {30'b0, axi_master_b_resp_i[1], axi_master_b_resp_i[1] ~^ axi_master_b_resp_i[0]}; + if (axi_master_b_resp_i[1]) begin // error + axi_xresp_valid_o [axi_master_b_id_i] = 1'b1; + if (axi_master_b_resp_i[0]) begin // decoding error + axi_xresp_decerr_o[axi_master_b_id_i] = 1'b1; + end else begin // slave error (e.g. RAB miss) + axi_xresp_slverr_o[axi_master_b_id_i] = 1'b1; + end + end + end + end + end + + // Atomic memory operations + + generate + for (genvar i = 0; i < PER_ID_WIDTH; i++) begin + always_comb begin + atop_state_d[i] = atop_state_q[i]; + + unique case (atop_state_q[i]) + NONE: begin + if (atop_req_i && (atop_id_i == i)) begin + atop_state_d[i] = REQUEST; + end + end + + REQUEST: begin + if (axi_master_r_valid_i && axi_master_r_ready_o && (axi_master_r_id_i == i)) begin + atop_state_d[i] = WAIT_B; + end + if (axi_master_b_valid_i && axi_master_b_ready_o && (axi_master_b_id_i == i)) begin + atop_state_d[i] = WAIT_R; + end + if (axi_master_r_valid_i && axi_master_r_ready_o && (axi_master_r_id_i == i) && + axi_master_b_valid_i && axi_master_b_ready_o && (axi_master_b_id_i == i)) begin + atop_state_d[i] = NONE; + end + end + + WAIT_R: begin + if (axi_master_r_valid_i && axi_master_r_ready_o && (axi_master_r_id_i == i)) begin + atop_state_d[i] = NONE; + end + end + + WAIT_B: begin + if (axi_master_b_valid_i && axi_master_b_ready_o && (axi_master_b_id_i == i)) begin + atop_state_d[i] = NONE; + end + end + + default : /* default */; + endcase + + + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + atop_state_q[i] <= NONE; + end else begin + atop_state_q[i] <= atop_state_d[i]; + end + end + + end + endgenerate + + + // STORES REQUEST ADDRESS BIT 2 ONLY IF A READ OPERATION OCCURS + always_ff @ (posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + begin + s_read_add_buf <= '0; + end + else + begin + if(trans_req_i == 1'b1) + begin + s_read_add_buf[trans_id_i] <= trans_add_i[2]; + end + if(atop_req_i == 1'b1) + begin + s_read_add_buf[atop_id_i] <= atop_add_i[2]; + end + end + end + + // FORWARD 32-bit AXI MSBs or LSBs TO THE PERIPHERAL INTERCONNECT DEPENDING ON THE REQUEST ADDRESS + always_comb + begin + if ( s_read_add_buf[axi_master_r_id_i] == 1'b0 ) + begin + s_per_slave_r_data = axi_master_r_data_i[31:0]; + end + else + begin + s_per_slave_r_data = axi_master_r_data_i[63:32]; + end + end + +endmodule diff --git a/hw/deps/pulp_cluster/packages/apu_package.sv b/hw/deps/pulp_cluster/packages/apu_package.sv new file mode 100644 index 0000000..32aeec0 --- /dev/null +++ b/hw/deps/pulp_cluster/packages/apu_package.sv @@ -0,0 +1,52 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * apu_package.sv + * Michael Gautschi + */ + +package apu_package; + + import apu_core_package::*; + + parameter FPU = 1; + + parameter SHARED_FP = 1; + parameter SHARED_DSP_MULT = SHARED_FP ? 1 : 0; // only available with shared FPU + parameter SHARED_INT_DIV = SHARED_FP ? 0 : 0; // only available with shared FPU + + // Shared div/sqrt implementation 0=none, 1=pipelined version, 2=iterative shared unit + parameter SHARED_FP_DIVSQRT = 2; + + //////////////////////////////////////////////////////////////////////////////////////// + // IMPORTANT!! // + //////////////////////////////////////////////////////////////////////////////////////// + // THESE PARAMETERS HAVE TO MATCH THE ones in ips/riscv/includes/apu_core_package.sv // + //////////////////////////////////////////////////////////////////////////////////////// + + // CPU side / general params + parameter NARGS_CPU = 3; + parameter WOP_CPU = 6; + parameter NUSFLAGS_CPU = 5; + parameter NDSFLAGS_CPU = 15; + ///////////////////////////////////////////////////////////////////////////// + // until here // + ///////////////////////////////////////////////////////////////////////////// + + // FP-general + parameter APUTYPE_FP = (SHARED_FP) ? SHARED_DSP_MULT + SHARED_INT_MULT + SHARED_INT_DIV : 0; + + // generated values + parameter C_APUTYPES = (SHARED_FP) ? (SHARED_FP_DIVSQRT==1) ? APUTYPE_FP+6 : (SHARED_FP_DIVSQRT==2) ? APUTYPE_FP+5 : APUTYPE_FP+4 : SHARED_DSP_MULT + SHARED_INT_DIV + SHARED_INT_MULT; + + parameter WAPUTYPE = $clog2(C_APUTYPES); + +endpackage diff --git a/hw/deps/pulp_cluster/packages/pulp_cluster_package.sv b/hw/deps/pulp_cluster/packages/pulp_cluster_package.sv new file mode 100644 index 0000000..def2e22 --- /dev/null +++ b/hw/deps/pulp_cluster/packages/pulp_cluster_package.sv @@ -0,0 +1,43 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * pulp_cluster_package.sv + * Davide Rossi + * Michael Gautschi + */ + +package pulp_cluster_package; + + parameter NB_SPERIPH_PLUGS_EU = 2; + + // position of peripherals on slave port of periph interconnect + parameter SPER_EOC_ID = 0; + parameter SPER_TIMER_ID = 1; + parameter SPER_EVENT_U_ID = 2; + parameter SPER_HWPE_ID = 4; + parameter SPER_ICACHE_CTRL = 5; + parameter SPER_DMA_ID = 6; + parameter SPER_EXT_ID = 7; + + // if set to 1, then instantiate APU in the cluster + parameter APU_CLUSTER = 0; + + // // if set to 1, the 0x0000_0000 to 0x0040_0000 is the alias of the current cluster address space (eg cluster 0 is from 0x1000_0000 to 0x1040_0000) + // parameter CLUSTER_ALIAS = 1; + + // // if set to 1, the DEMUX peripherals (EU, MCHAN) are placed right before the test and set region. + // // This will steal 16KB from the 1MB TCDM reegion. + // // EU is mapped from 0x10100000 - 0x400 + // // MCHAN regs are mapped from 0x10100000 - 0x800 + // // remember to change the defines in the pulp.h as well to be coherent with this approach + // parameter DEM_PER_BEFORE_TCDM_TS = 0; + +endpackage diff --git a/hw/deps/pulp_cluster/rtl/axi2per_wrap.sv b/hw/deps/pulp_cluster/rtl/axi2per_wrap.sv new file mode 100644 index 0000000..0e0d19c --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/axi2per_wrap.sv @@ -0,0 +1,120 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * axi2per_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module axi2per_wrap +#( + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 6, + parameter BUFFER_DEPTH = 2, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic [5:0] cluster_id_i, + AXI_BUS.Slave axi_slave, + XBAR_TCDM_BUS.Master periph_master, + output logic busy_o +); + + axi2per #( + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .PER_ID_WIDTH ( PER_ID_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ), + .BUFFER_DEPTH ( BUFFER_DEPTH ) + ) axi2per_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .cluster_id_i ( cluster_id_i ), + + .axi_slave_aw_valid_i ( axi_slave.aw_valid ), + .axi_slave_aw_addr_i ( axi_slave.aw_addr ), + .axi_slave_aw_prot_i ( axi_slave.aw_prot ), + .axi_slave_aw_region_i ( axi_slave.aw_region ), + .axi_slave_aw_len_i ( axi_slave.aw_len ), + .axi_slave_aw_size_i ( axi_slave.aw_size ), + .axi_slave_aw_burst_i ( axi_slave.aw_burst ), + .axi_slave_aw_lock_i ( axi_slave.aw_lock ), + .axi_slave_aw_atop_i ( axi_slave.aw_atop ), + .axi_slave_aw_cache_i ( axi_slave.aw_cache ), + .axi_slave_aw_qos_i ( axi_slave.aw_qos ), + .axi_slave_aw_id_i ( axi_slave.aw_id ), + .axi_slave_aw_user_i ( axi_slave.aw_user ), + .axi_slave_aw_ready_o ( axi_slave.aw_ready ), + + .axi_slave_ar_valid_i ( axi_slave.ar_valid ), + .axi_slave_ar_addr_i ( axi_slave.ar_addr ), + .axi_slave_ar_prot_i ( axi_slave.ar_prot ), + .axi_slave_ar_region_i ( axi_slave.ar_region ), + .axi_slave_ar_len_i ( axi_slave.ar_len ), + .axi_slave_ar_size_i ( axi_slave.ar_size ), + .axi_slave_ar_burst_i ( axi_slave.ar_burst ), + .axi_slave_ar_lock_i ( axi_slave.ar_lock ), + .axi_slave_ar_cache_i ( axi_slave.ar_cache ), + .axi_slave_ar_qos_i ( axi_slave.ar_qos ), + .axi_slave_ar_id_i ( axi_slave.ar_id ), + .axi_slave_ar_user_i ( axi_slave.ar_user ), + .axi_slave_ar_ready_o ( axi_slave.ar_ready ), + + .axi_slave_w_valid_i ( axi_slave.w_valid ), + .axi_slave_w_data_i ( axi_slave.w_data ), + .axi_slave_w_strb_i ( axi_slave.w_strb ), + .axi_slave_w_user_i ( axi_slave.w_user ), + .axi_slave_w_last_i ( axi_slave.w_last ), + .axi_slave_w_ready_o ( axi_slave.w_ready ), + + .axi_slave_r_valid_o ( axi_slave.r_valid ), + .axi_slave_r_data_o ( axi_slave.r_data ), + .axi_slave_r_resp_o ( axi_slave.r_resp ), + .axi_slave_r_last_o ( axi_slave.r_last ), + .axi_slave_r_id_o ( axi_slave.r_id ), + .axi_slave_r_user_o ( axi_slave.r_user ), + .axi_slave_r_ready_i ( axi_slave.r_ready ), + + .axi_slave_b_valid_o ( axi_slave.b_valid ), + .axi_slave_b_resp_o ( axi_slave.b_resp ), + .axi_slave_b_id_o ( axi_slave.b_id ), + .axi_slave_b_user_o ( axi_slave.b_user ), + .axi_slave_b_ready_i ( axi_slave.b_ready ), + + .per_master_req_o ( periph_master.req ), + .per_master_add_o ( periph_master.add ), + .per_master_we_no ( periph_master.wen ), + .per_master_atop_o ( /* unused */ ), + .per_master_wdata_o ( periph_master.wdata ), + .per_master_be_o ( periph_master.be ), + .per_master_gnt_i ( periph_master.gnt ), + + .per_master_r_valid_i ( periph_master.r_valid ), + .per_master_r_opc_i ( periph_master.r_opc ), + .per_master_r_rdata_i ( periph_master.r_rdata ), + + .busy_o(busy_o) + ); + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/cluster_bus_wrap.sv b/hw/deps/pulp_cluster/rtl/cluster_bus_wrap.sv new file mode 100644 index 0000000..8b000e8 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/cluster_bus_wrap.sv @@ -0,0 +1,121 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * cluster_bus_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + * Andreas Kurth + */ + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module cluster_bus_wrap +#( + parameter NB_CORES = 4 , + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_ID_IN_WIDTH = 4 , + parameter AXI_ID_OUT_WIDTH = 6 , + parameter AXI_USER_WIDTH = 6 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input logic [5:0] cluster_id_i, + + AXI_BUS.Slave data_slave, + AXI_BUS.Slave dma_slave, + AXI_BUS.Slave ext_slave, + + AXI_BUS.Master tcdm_master, + AXI_BUS.Master periph_master, + AXI_BUS.Master ext_master +); + + localparam int unsigned NumRules = 2; + typedef axi_pkg::xbar_rule_32_t xbar_rule_t; + axi_pkg::xbar_rule_32_t [NumRules-1:0] addr_map; + logic [31:0] cluster_base_addr; + assign cluster_base_addr = 32'h1000_0000 + (cluster_id_i << 22); + assign addr_map = '{ + '{ // TCDM + start_addr: cluster_base_addr + 24'h00_0000, + end_addr: cluster_base_addr + 24'h10_0000, + idx: 0 + }, + '{ // Peripherals + start_addr: cluster_base_addr + 24'h20_0000, + end_addr: cluster_base_addr + 24'h40_0000, + idx: 1 + } + }; + localparam NumMstPorts = 3; + localparam NumSlvPorts = 3; + /* verilator lint_off WIDTHCONCAT */ + localparam axi_pkg::xbar_cfg_t XbarCfg = '{ + NoSlvPorts: NumSlvPorts, + NoMstPorts: NumMstPorts, + MaxMstTrans: 16, + MaxSlvTrans: 32, + FallThrough: 1'b0, + LatencyMode: axi_pkg::CUT_ALL_PORTS, + AxiIdWidthSlvPorts: AXI_ID_IN_WIDTH, + AxiIdUsedSlvPorts: AXI_ID_IN_WIDTH, + AxiAddrWidth: AXI_ADDR_WIDTH, + AxiDataWidth: AXI_DATA_WIDTH, + NoAddrRules: NumRules + }; + /* verilator lint_on WIDTHCONCAT */ + + AXI_BUS #( + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (AXI_ID_OUT_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) mst_ports [2:0] (); + + AXI_BUS #( + .AXI_ADDR_WIDTH(AXI_ADDR_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH (AXI_ID_IN_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) slv_ports [2:0] (); + + `AXI_ASSIGN (ext_master, mst_ports[2]) + `AXI_ASSIGN (periph_master, mst_ports[1]) + `AXI_ASSIGN (tcdm_master, mst_ports[0]) + + `AXI_ASSIGN (slv_ports[2], data_slave) + `AXI_ASSIGN (slv_ports[1], dma_slave) + `AXI_ASSIGN (slv_ports[0], ext_slave) + + logic [$clog2(NumMstPorts)-1:0] default_mst_port; + assign default_mst_port = 2; // default to external master + axi_xbar_intf #( + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .Cfg ( XbarCfg ), + .rule_t ( xbar_rule_t ) + ) i_axi_xbar ( + .clk_i, + .rst_ni, + .test_i ( test_en_i ), + .slv_ports ( slv_ports ), + .mst_ports ( mst_ports ), + .addr_map_i ( addr_map ), + .en_default_mst_port_i ( '1 ), + .default_mst_port_i ( {NumSlvPorts{default_mst_port}} ) + ); + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/cluster_event_map.sv b/hw/deps/pulp_cluster/rtl/cluster_event_map.sv new file mode 100644 index 0000000..a204154 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/cluster_event_map.sv @@ -0,0 +1,58 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * cluster_event_map.sv + * Florian Glaser + */ + +module cluster_event_map +#( + parameter NB_CORES = 4 +) +( + // events generated inside event unit + input logic [NB_CORES-1:0][7:0] sw_events_i, + input logic [NB_CORES-1:0] barrier_events_i, + input logic [NB_CORES-1:0] mutex_events_i, + input logic [NB_CORES-1:0] dispatch_events_i, + input logic periph_fifo_event_i, + + // events from cluster blocks + input logic [NB_CORES-1:0][3:0] acc_events_i, + input logic [NB_CORES-1:0][1:0] dma_events_i, + input logic [NB_CORES-1:0][1:0] timer_events_i, + input logic [NB_CORES-1:0][31:0] cluster_events_i, + + output logic [NB_CORES-1:0][31:0] events_mapped_o +); + + genvar I; + + generate + for ( I = 0; I < NB_CORES; I++ ) begin : CL_EVENT_MAP + assign events_mapped_o[I][31:28] = '0; + assign events_mapped_o[I][27] = periph_fifo_event_i; + assign events_mapped_o[I][26:24] = '0; + assign events_mapped_o[I][23:22] = cluster_events_i[I][1:0]; + assign events_mapped_o[I][21:19] = '0; + + assign events_mapped_o[I][18] = dispatch_events_i[I]; + assign events_mapped_o[I][17] = mutex_events_i[I]; + assign events_mapped_o[I][16] = barrier_events_i[I]; + + assign events_mapped_o[I][15:12] = acc_events_i[I]; + assign events_mapped_o[I][11:10] = timer_events_i[I]; + assign events_mapped_o[I][9:8] = dma_events_i[I]; + assign events_mapped_o[I][7:0] = sw_events_i[I]; + end + endgenerate + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/cluster_interconnect_wrap.sv b/hw/deps/pulp_cluster/rtl/cluster_interconnect_wrap.sv new file mode 100644 index 0000000..3518ad4 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/cluster_interconnect_wrap.sv @@ -0,0 +1,672 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * cluster_interconnect_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + * Thomas Benz + */ + +module cluster_interconnect_wrap +#( + parameter NB_CORES = 8, + parameter NB_HWACC_PORTS = 4, + parameter NB_DMAS = 4, + parameter NB_EXT = 4, + parameter NB_MPERIPHS = 1, + parameter NB_TCDM_BANKS = 16, + parameter NB_SPERIPHS = 3, + parameter DATA_WIDTH = 32, + parameter ADDR_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8, + //TCDM PARAMETERS + parameter TEST_SET_BIT = 20, + parameter ADDR_MEM_WIDTH = 11, + parameter LOG_CLUSTER = 5, + parameter PE_ROUTING_LSB = 16, + parameter PE_ROUTING_MSB = 19, + parameter CLUSTER_ALIAS = 1'b0, + parameter CLUSTER_ALIAS_BASE = 12'h000 +) +( + input logic clk_i, + input logic rst_ni, + XBAR_TCDM_BUS.Slave core_tcdm_slave[NB_CORES+NB_HWACC_PORTS-1:0], + input logic [NB_CORES-1:0][5:0] core_tcdm_slave_atop, + XBAR_PERIPH_BUS.Slave core_periph_slave[NB_CORES-1:0], + input logic [NB_CORES-1:0][5:0] core_periph_slave_atop, + XBAR_TCDM_BUS.Slave ext_slave[NB_EXT-1:0], + input logic [NB_EXT-1:0][5:0] ext_slave_atop, + XBAR_TCDM_BUS.Slave dma_slave[NB_DMAS-1:0], + XBAR_TCDM_BUS.Slave mperiph_slave[NB_MPERIPHS-1:0], + TCDM_BANK_MEM_BUS.Master tcdm_sram_master[NB_TCDM_BANKS-1:0], + XBAR_PERIPH_BUS.Master speriph_master[NB_SPERIPHS-1:0], + output logic [NB_SPERIPHS-1:0][5:0] speriph_master_atop, + input logic [1:0] TCDM_arb_policy_i, + WIDE_DMA_TCDM_BUS.Slave s_wide_dma_a_superbanks, + WIDE_DMA_TCDM_BUS.Slave s_wide_dma_b_superbanks +); + + localparam TCDM_ID_WIDTH = NB_CORES+NB_DMAS+NB_EXT+NB_HWACC_PORTS; + + localparam DMA_DATA_WIDTH = 512; + localparam DMA_ADDR_WIDTH = 64; + localparam BANKS_PER_SUPERBANK = DMA_DATA_WIDTH / DATA_WIDTH; + localparam NB_SUPERBANKS = NB_TCDM_BANKS / BANKS_PER_SUPERBANK; + + // DMA --> LOGARITHMIC INTERCONNECT BUS SIGNALS + logic [NB_EXT+NB_DMAS-1:0][DATA_WIDTH-1:0] s_dma_bus_wdata; + logic [NB_EXT+NB_DMAS-1:0][ADDR_WIDTH-1:0] s_dma_bus_add; + logic [NB_EXT+NB_DMAS-1:0] s_dma_bus_req; + logic [NB_EXT+NB_DMAS-1:0] s_dma_bus_wen; + logic [NB_EXT+NB_DMAS-1:0][BE_WIDTH-1:0] s_dma_bus_be; + logic [NB_EXT+NB_DMAS-1:0] s_dma_bus_gnt; + logic [NB_EXT+NB_DMAS-1:0][DATA_WIDTH-1:0] s_dma_bus_r_rdata; + logic [NB_EXT+NB_DMAS-1:0] s_dma_bus_r_valid; + + // MASTER PERIPHERALS --> PERIPHERAL INTERCONNECT BUS SIGNALS + logic [NB_MPERIPHS-1:0][DATA_WIDTH-1:0] s_mperiph_bus_wdata; + logic [NB_MPERIPHS-1:0][ADDR_WIDTH-1:0] s_mperiph_bus_add; + logic [NB_MPERIPHS-1:0] s_mperiph_bus_req; + logic [NB_MPERIPHS-1:0] s_mperiph_bus_wen; + logic [NB_MPERIPHS-1:0][BE_WIDTH-1:0] s_mperiph_bus_be; + logic [NB_MPERIPHS-1:0] s_mperiph_bus_gnt ; + logic [NB_MPERIPHS-1:0] s_mperiph_bus_r_opc; + logic [NB_MPERIPHS-1:0][DATA_WIDTH-1:0] s_mperiph_bus_r_rdata; + logic [NB_MPERIPHS-1:0] s_mperiph_bus_r_valid; + + // DEMUX --> LOGARITHMIC INTERCONNECT BUS SIGNALS + logic [NB_CORES+NB_HWACC_PORTS-1:0][DATA_WIDTH-1:0] s_core_tcdm_bus_wdata; + logic [NB_CORES+NB_HWACC_PORTS-1:0][ADDR_WIDTH-1:0] s_core_tcdm_bus_add; + logic [NB_CORES+NB_HWACC_PORTS-1:0] s_core_tcdm_bus_req; + logic [NB_CORES+NB_HWACC_PORTS-1:0] s_core_tcdm_bus_wen; + logic [NB_CORES+NB_HWACC_PORTS-1:0][BE_WIDTH-1:0] s_core_tcdm_bus_be; + logic [NB_CORES+NB_HWACC_PORTS-1:0] s_core_tcdm_bus_gnt; + logic [NB_CORES+NB_HWACC_PORTS-1:0][DATA_WIDTH-1:0] s_core_tcdm_bus_r_rdata; + logic [NB_CORES+NB_HWACC_PORTS-1:0] s_core_tcdm_bus_r_valid; + + // DEMUX --> PERIPHERAL INTERCONNECT BUS SIGNALS + logic [NB_CORES-1:0][ADDR_WIDTH-1:0] s_core_periph_bus_add; + logic [NB_CORES-1:0] s_core_periph_bus_req; + logic [NB_CORES-1:0][DATA_WIDTH-1:0] s_core_periph_bus_wdata; + logic [NB_CORES-1:0] s_core_periph_bus_wen; + logic [NB_CORES-1:0][5:0] s_core_periph_bus_atop; + logic [NB_CORES-1:0][BE_WIDTH-1:0] s_core_periph_bus_be; + logic [NB_CORES-1:0] s_core_periph_bus_gnt; + logic [NB_CORES-1:0] s_core_periph_bus_r_opc; + logic [NB_CORES-1:0] s_core_periph_bus_r_valid; + logic [NB_CORES-1:0][DATA_WIDTH-1:0] s_core_periph_bus_r_rdata; + + // LOGARITHMIC INTERCONNECT --> Superbank MUX + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][ADDR_MEM_WIDTH-1:0] s_tcdm_bus_sb_mux_add; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_tcdm_bus_sb_mux_req; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_tcdm_bus_sb_mux_gnt; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_tcdm_bus_sb_mux_wen; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][5:0] s_tcdm_bus_sb_mux_atop; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][DATA_WIDTH-1:0] s_tcdm_bus_sb_mux_wdata; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][BE_WIDTH-1:0] s_tcdm_bus_sb_mux_be; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][DATA_WIDTH-1:0] s_tcdm_bus_sb_mux_rdata; + + // Superbank MUX --> Amo Shims + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][ADDR_MEM_WIDTH-1:0] s_sb_mux_amo_shim_add; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_sb_mux_amo_shim_req; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_sb_mux_amo_shim_gnt; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0] s_sb_mux_amo_shim_wen; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][5:0] s_sb_mux_amo_shim_atop; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][DATA_WIDTH-1:0] s_sb_mux_amo_shim_wdata; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][BE_WIDTH-1:0] s_sb_mux_amo_shim_be; + logic [NB_SUPERBANKS-1:0][BANKS_PER_SUPERBANK-1:0][DATA_WIDTH-1:0] s_sb_mux_amo_shim_rdata; + + // DMA Superbank Decoder -> Superbank MUX + logic [NB_SUPERBANKS-1:0] s_decoder_sb_a_mux_req; + logic [NB_SUPERBANKS-1:0] s_decoder_sb_a_mux_gnt; + logic [NB_SUPERBANKS-1:0][ADDR_MEM_WIDTH-1:0] s_decoder_sb_a_mux_add; + logic [NB_SUPERBANKS-1:0][5:0] s_decoder_sb_a_mux_amo; + logic [NB_SUPERBANKS-1:0] s_decoder_sb_a_mux_wen; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH-1:0] s_decoder_sb_a_mux_wdata; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH/8-1:0] s_decoder_sb_a_mux_be; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH-1:0] s_decoder_sb_a_mux_rdata; + + // DMA Superbank Decoder -> Superbank MUX + logic [NB_SUPERBANKS-1:0] s_decoder_sb_b_mux_req; + logic [NB_SUPERBANKS-1:0] s_decoder_sb_b_mux_gnt; + logic [NB_SUPERBANKS-1:0][ADDR_MEM_WIDTH-1:0] s_decoder_sb_b_mux_add; + logic [NB_SUPERBANKS-1:0][5:0] s_decoder_sb_b_mux_amo; + logic [NB_SUPERBANKS-1:0] s_decoder_sb_b_mux_wen; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH-1:0] s_decoder_sb_b_mux_wdata; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH/8-1:0] s_decoder_sb_b_mux_be; + logic [NB_SUPERBANKS-1:0][DMA_DATA_WIDTH-1:0] s_decoder_sb_b_mux_rdata; + + // DMA -> DMA Superbank Decoder a + logic s_dma_decoder_a_req; + logic s_dma_decoder_a_gnt; + logic [DMA_ADDR_WIDTH-1:0] s_dma_decoder_a_add; + logic [5:0] s_dma_decoder_a_amo; + logic s_dma_decoder_a_wen; + logic [DMA_DATA_WIDTH-1:0] s_dma_decoder_a_wdata; + logic [DMA_DATA_WIDTH/8-1:0] s_dma_decoder_a_be; + logic [DMA_DATA_WIDTH-1:0] s_dma_decoder_a_rdata; + + // DMA -> DMA Superbank Decoder b + logic s_dma_decoder_b_req; + logic s_dma_decoder_b_gnt; + logic [DMA_ADDR_WIDTH-1:0] s_dma_decoder_b_add; + logic [5:0] s_dma_decoder_b_amo; + logic s_dma_decoder_b_wen; + logic [DMA_DATA_WIDTH-1:0] s_dma_decoder_b_wdata; + logic [DMA_DATA_WIDTH/8-1:0] s_dma_decoder_b_be; + logic [DMA_DATA_WIDTH-1:0] s_dma_decoder_b_rdata; + + // PERIPHERAL INTERCONNECT INTERCONNECT --> SLAVE PERIPHERALS BUS SIGNALS + logic [NB_SPERIPHS-1:0][DATA_WIDTH-1:0] s_speriph_bus_wdata; + logic [NB_SPERIPHS-1:0][ADDR_WIDTH-1:0] s_speriph_bus_add; + logic [NB_SPERIPHS-1:0] s_speriph_bus_req; + logic [NB_SPERIPHS-1:0] s_speriph_bus_wen; + logic [NB_SPERIPHS-1:0][5:0] s_speriph_bus_atop; + logic [NB_SPERIPHS-1:0][BE_WIDTH-1:0] s_speriph_bus_be; + logic [NB_SPERIPHS-1:0][NB_CORES+NB_MPERIPHS-1:0] s_speriph_bus_id; + logic [NB_SPERIPHS-1:0] s_speriph_bus_gnt ; + logic [NB_SPERIPHS-1:0] s_speriph_bus_r_opc; + logic [NB_SPERIPHS-1:0][NB_CORES+NB_MPERIPHS-1:0] s_speriph_bus_r_id; + logic [NB_SPERIPHS-1:0][DATA_WIDTH-1:0] s_speriph_bus_r_rdata; + logic [NB_SPERIPHS-1:0] s_speriph_bus_r_valid; + + //******************************************************** + //****** BINDING INTERFACES TO INTERNAL BUS SINGALS ****** + //******************************************************** + generate + for (genvar i=0; i + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +import pulp_cluster_package::*; + +module cluster_peripherals +#( + parameter NB_CORES = 4, + parameter NB_MPERIPHS = 1, + parameter NB_CACHE_BANKS = 4, + parameter NB_SPERIPHS = 8, + parameter NB_TCDM_BANKS = 8, + parameter NB_HWPE_PORTS = 1, + parameter ROM_BOOT_ADDR = 32'h1A000000, + parameter BOOT_ADDR = 32'h1C000000, + parameter EVNT_WIDTH = 8, + parameter FEATURE_DEMUX_MAPPED = 1 +) +( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + input logic test_mode_i, + + input logic [NB_CORES-1:0] dma_events_i, + input logic [NB_CORES-1:0] dma_irq_i, + input logic en_sa_boot_i, + input logic fetch_en_i, + input logic [NB_CORES-1:0] core_busy_i, + output logic [NB_CORES-1:0] core_clk_en_o, + output logic fregfile_disable_o, + + output logic [NB_CORES-1:0][31:0] boot_addr_o, + + output logic cluster_cg_en_o, + + output logic busy_o, + + XBAR_PERIPH_BUS.Slave speriph_slave[NB_SPERIPHS-2:0], + XBAR_PERIPH_BUS.Slave core_eu_direct_link[NB_CORES-1:0], + + XBAR_PERIPH_BUS.Master dma_cfg_master, + input logic dma_pe_irq_i, + output logic pf_event_o, + + output logic soc_periph_evt_ready_o, + input logic soc_periph_evt_valid_i, + input logic [EVNT_WIDTH-1:0] soc_periph_evt_data_i, + + input logic [NB_CORES-1:0] dbg_core_halted_i, + output logic [NB_CORES-1:0] dbg_core_halt_o, + output logic [NB_CORES-1:0] dbg_core_resume_o, + + output logic eoc_o, + output logic [NB_CORES-1:0] fetch_enable_reg_o, //fetch enable driven by the internal register + output logic [NB_CORES-1:0][4:0] irq_id_o, + input logic [NB_CORES-1:0][4:0] irq_ack_id_i, + output logic [NB_CORES-1:0] irq_req_o, + input logic [NB_CORES-1:0] irq_ack_i, + + // SRAM SPEED REGULATION --> TCDM + output logic [1:0] TCDM_arb_policy_o, + + XBAR_PERIPH_BUS.Master hwce_cfg_master, + input logic [NB_CORES-1:0][3:0] hwacc_events_i, + output logic hwpe_sel_o, + output logic hwpe_en_o, + + // Control ports + MP_PF_ICACHE_CTRL_UNIT_BUS.Master IC_ctrl_unit_bus +); + + logic s_timer_out_lo_event; + logic s_timer_out_hi_event; + logic s_timer_in_lo_event; + logic s_timer_in_hi_event; + + logic [NB_CORES-1:0][31:0] s_cluster_events; + logic [NB_CORES-1:0][3:0] s_acc_events; + logic [NB_CORES-1:0][1:0] s_timer_events; + logic [NB_CORES-1:0][1:0] s_dma_events; + + logic [NB_CORES-1:0] s_fetch_en_cc; + + logic [NB_SPERIPH_PLUGS_EU-1:0] eu_speriph_plug_req; + logic [NB_SPERIPH_PLUGS_EU-1:0][31:0] eu_speriph_plug_add; + logic [NB_SPERIPH_PLUGS_EU-1:0] eu_speriph_plug_wen; + logic [NB_SPERIPH_PLUGS_EU-1:0][31:0] eu_speriph_plug_wdata; + logic [NB_SPERIPH_PLUGS_EU-1:0][3:0] eu_speriph_plug_be; + logic [NB_SPERIPH_PLUGS_EU-1:0][NB_CORES:0] eu_speriph_plug_id; + + logic soc_periph_evt_valid, soc_periph_evt_ready; + logic [7:0] soc_periph_evt_data; + + // internal speriph bus to combine multiple plugs to new event unit + XBAR_PERIPH_BUS speriph_slave_eu_comb(); + MESSAGE_BUS eu_message_master(); + + // decide between common or core-specific event sources + generate + for (genvar I=0; I + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module cluster_timer_wrap + #( + parameter ID_WIDTH = 2 + ) + ( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + + XBAR_PERIPH_BUS.Slave periph_slave, + + input logic event_lo_i, + input logic event_hi_i, + + output logic irq_lo_o, + output logic irq_hi_o, + + output logic busy_o + ); + + timer_unit + #( + .ID_WIDTH ( ID_WIDTH ) + ) + timer_unit_i + ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .ref_clk_i ( ref_clk_i ), + + .req_i ( periph_slave.req ), + .addr_i ( periph_slave.add ), + .wen_i ( periph_slave.wen ), + .wdata_i ( periph_slave.wdata ), + .be_i ( periph_slave.be ), + .id_i ( periph_slave.id ), + .gnt_o ( periph_slave.gnt ), + + .r_valid_o ( periph_slave.r_valid ), + .r_opc_o ( periph_slave.r_opc ), + .r_id_o ( periph_slave.r_id ), + .r_rdata_o ( periph_slave.r_rdata ), + + .event_lo_i ( event_lo_i ), + .event_hi_i ( event_hi_i ), + + .irq_lo_o ( irq_lo_o ), + .irq_hi_o ( irq_hi_o ), + + .busy_o ( busy_o ) + ); + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/core_demux.sv b/hw/deps/pulp_cluster/rtl/core_demux.sv new file mode 100644 index 0000000..f9e6cdd --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/core_demux.sv @@ -0,0 +1,568 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * core_demux.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +//`define PERF_CNT + +module core_demux +#( + parameter int ADDR_WIDTH = 32, + parameter int DATA_WIDTH = 32, + parameter int BYTE_ENABLE_BIT = DATA_WIDTH/8, + parameter bit CLUSTER_ALIAS = 1'b1, + parameter int CLUSTER_ALIAS_BASE = 12'h000, + parameter bit DEM_PER_BEFORE_TCDM_TS = 1'b0, + parameter bit REMAP_ADDRESS = 1'b0 +) +( + input logic clk, + input logic rst_ni, + input logic test_en_i, + input logic [3:0] base_addr_i, + + // CORE SIDE + input logic data_req_i, + input logic [ADDR_WIDTH - 1:0] data_add_i, + input logic data_wen_i, + input logic [5:0] data_atop_i, + input logic [DATA_WIDTH - 1:0] data_wdata_i, + input logic [BYTE_ENABLE_BIT - 1:0] data_be_i, + output logic data_gnt_o, + + input logic data_r_gnt_i, // Data Response Grant (For LOAD/STORE commands) + output logic data_r_valid_o, // Data Response Valid (For LOAD/STORE commands) + output logic [DATA_WIDTH - 1:0] data_r_rdata_o, // Data Response DATA (For LOAD commands) + output logic data_r_opc_o, // Data Response Error + + // Low Latency log interconnect + output logic data_req_o_SH, + output logic [ADDR_WIDTH - 1:0] data_add_o_SH, + output logic data_wen_o_SH, + output logic [5:0] data_atop_o_SH, + output logic [DATA_WIDTH - 1:0] data_wdata_o_SH, + output logic [BYTE_ENABLE_BIT - 1:0] data_be_o_SH, + input logic data_gnt_i_SH, + input logic data_r_valid_i_SH, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_SH, + + // externally memory-mapped peripherals + output logic data_req_o_EXT, + output logic [ADDR_WIDTH - 1:0] data_add_o_EXT, + output logic data_wen_o_EXT, + output logic [DATA_WIDTH - 1:0] data_wdata_o_EXT, + output logic [BYTE_ENABLE_BIT - 1:0] data_be_o_EXT, + input logic data_gnt_i_EXT, + input logic data_r_valid_i_EXT, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_EXT, + input logic data_r_opc_i_EXT, + + // Peripheral interconnect + output logic data_req_o_PE, + output logic [ADDR_WIDTH - 1:0] data_add_o_PE, + output logic data_wen_o_PE, + output logic [5:0] data_atop_o_PE, + output logic [DATA_WIDTH - 1:0] data_wdata_o_PE, + output logic [BYTE_ENABLE_BIT - 1:0] data_be_o_PE, + input logic data_gnt_i_PE, + input logic data_r_valid_i_PE, + input logic data_r_opc_i_PE, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_PE, + + // Performance Counters + output logic perf_l2_ld_o, // nr of L2 loads + output logic perf_l2_st_o, // nr of L2 stores + output logic perf_l2_ld_cyc_o, // cycles used for L2 loads + output logic perf_l2_st_cyc_o, // cycles used for L2 stores + + input logic [5:0] CLUSTER_ID +); + + logic [10:0] CLUSTER_ALIAS_BASE_11; + logic [11:0] CLUSTER_ALIAS_BASE_12, + CLUSTER_ALIAS_TCDM_RW, + CLUSTER_ALIAS_TCDM_TS, + CLUSTER_ALIAS_DEM_PER; + + logic s_data_req_PE; + logic s_data_gnt_PE; + logic [DATA_WIDTH - 1:0] s_data_r_data_PE; + logic s_data_r_valid_PE; + logic s_data_r_opc_PE; + logic [DATA_WIDTH - 1:0] s_data_r_data_PE_0; + logic s_data_r_valid_PE_0; + logic s_data_r_opc_PE_0; + + enum logic [1:0] { TRANS_IDLE, TRANS_PENDING, TRANS_GRANTED } CS, NS; + + // From L1 Arbiter + logic data_req_to_L2; + logic [ADDR_WIDTH - 1:0] data_add_to_L2; + logic data_wen_to_L2; + logic [DATA_WIDTH - 1:0] data_wdata_to_L2; + logic [BYTE_ENABLE_BIT - 1:0] data_be_to_L2; + logic data_gnt_from_L2; + + enum logic [1:0] {SH, PE, EXT } request_destination, destination; + + logic [ADDR_WIDTH - 1:0] data_add_int; + + // Signal to PERIPH FIFO + logic data_busy_PE_fifo; + logic data_req_PE_fifo; + logic [ADDR_WIDTH - 1:0] data_add_PE_fifo; + logic data_wen_PE_fifo; + logic [5:0] data_atop_PE_fifo; + logic [DATA_WIDTH - 1:0] data_wdata_PE_fifo; + logic [BYTE_ENABLE_BIT - 1:0] data_be_PE_fifo; + logic data_gnt_PE_fifo; + + logic data_r_valid_PE_fifo; + logic data_r_opc_PE_fifo; + logic [DATA_WIDTH - 1:0] data_r_rdata_PE_fifo; + + logic [11:0] TCDM_RW; + logic [11:0] TCDM_TS; + logic [11:0] DEM_PER; + + assign CLUSTER_ALIAS_BASE_12 = CLUSTER_ALIAS_BASE; + assign CLUSTER_ALIAS_BASE_11 = CLUSTER_ALIAS_BASE_12[11:1]; + assign CLUSTER_ALIAS_TCDM_RW = CLUSTER_ALIAS_BASE_12 + 0; + assign CLUSTER_ALIAS_TCDM_TS = CLUSTER_ALIAS_BASE_12 + 1; + assign CLUSTER_ALIAS_DEM_PER = CLUSTER_ALIAS_BASE_12 + 2; + + assign TCDM_RW = 12'h100 + (CLUSTER_ID << 2) + 0; + assign TCDM_TS = 12'h100 + (CLUSTER_ID << 2) + 1; + assign DEM_PER = 12'h100 + (CLUSTER_ID << 2) + 2; + + // This section is used to swap the 4 most significant bits of the address + // with the ones that are provided by the base_addr_i + // If data_add_i[31:28] == base_addr_i then data_add_i[31:28] are changed in 4'b0001 + // If data_add_i[31:28] == 4'b0001 --> then th data_add_i[31:28] is changed in base_addr_i + // In the other cases, the address is unchanged + + assign data_add_int[27:0] = data_add_i[27:0]; + + if (REMAP_ADDRESS) begin : gen_remap_address + always_comb begin + if (data_add_i[31:28] == base_addr_i) begin + data_add_int[31:28] = 4'b0001; + end else if (data_add_int[31:28] == 4'b0001) begin + data_add_int[31:28] = base_addr_i; + end else begin + data_add_int[31:28] = data_add_i[31:28]; + end + end + end else begin : gen_no_remap_address + assign data_add_int[31:28] = data_add_i[31:28]; + end + + // level 1 request arbiter + assign data_add_o_SH = data_add_int; + assign data_wen_o_SH = data_wen_i; + assign data_atop_o_SH = data_atop_i; + assign data_wdata_o_SH = data_wdata_i; + assign data_be_o_SH = data_be_i; + + assign data_add_to_L2 = data_add_int; + assign data_wen_to_L2 = data_wen_i; + assign data_wdata_to_L2 = data_wdata_i; + assign data_be_to_L2 = data_be_i; + + always_ff @(posedge clk, negedge rst_ni) + begin : _UPDATE_RESPONSE_DESTINATION_ + if(rst_ni == 1'b0) begin + request_destination <= SH; + end + else if (data_req_i) begin + if (DEM_PER_BEFORE_TCDM_TS) begin + + + case ({CLUSTER_ALIAS, data_add_int[31:20]}) + {1'b0, TCDM_RW}, + {1'b1, TCDM_RW}, + {1'b1, CLUSTER_ALIAS_TCDM_RW}: begin + if (data_add_int[19:14] == 6'b11_1111) begin + request_destination <= EXT; + end else begin + request_destination <= SH; + end + end + + {1'b0, TCDM_TS}, + {1'b1, TCDM_TS}, + {1'b1, CLUSTER_ALIAS_TCDM_TS}: begin + request_destination <= SH; + end + + {1'b0, DEM_PER}, + {1'b1, DEM_PER}, + {1'b1, CLUSTER_ALIAS_DEM_PER}: begin + request_destination <= PE; + end + + default: request_destination <= PE; + endcase + + + end else begin + case ({CLUSTER_ALIAS, data_add_int[31:20]}) + {1'b0, TCDM_RW}, + {1'b1, TCDM_RW}, + {1'b1, CLUSTER_ALIAS_TCDM_RW}, + {1'b0, TCDM_TS}, + {1'b1, TCDM_TS}, + {1'b1, CLUSTER_ALIAS_TCDM_TS}: begin + request_destination <= SH; + end + + {1'b0, DEM_PER}, + {1'b1, DEM_PER}, + {1'b1, CLUSTER_ALIAS_DEM_PER}: begin + if (data_add_int[14]) begin // DEMUX PERIPHERALS + request_destination <= EXT; + end else begin + request_destination <= PE; + end + end + + default: request_destination <= PE; + endcase + end + end + end + + always_comb + begin : _UPDATE_REQUEST_DESTINATION_ + if (DEM_PER_BEFORE_TCDM_TS) begin + case ({CLUSTER_ALIAS, data_add_int[31:20]}) + {1'b0, TCDM_RW}, + {1'b1, TCDM_RW}, + {1'b1, CLUSTER_ALIAS_TCDM_RW}: begin + if (data_add_int[19:14] == 6'b11_1111) begin + destination = EXT; + end else begin + destination = SH; + end + end // CLUSTER or DEM peripherals (mappping based on Germain suggestion) + + {1'b0, TCDM_TS}, + {1'b1, TCDM_TS}, + {1'b1, CLUSTER_ALIAS_TCDM_TS}: begin + destination = SH; + end + + {1'b0, DEM_PER}, + {1'b1, DEM_PER}, + {1'b1, CLUSTER_ALIAS_DEM_PER}: begin + destination = PE; + end + + default: begin + destination = PE; + end // CLUSTER PERIPHERAL and rest of the memory map + + endcase + end else begin + case ({CLUSTER_ALIAS, data_add_int[31:20]}) + {1'b0, TCDM_RW}, + {1'b1, TCDM_RW}, + {1'b1, CLUSTER_ALIAS_TCDM_RW}, + {1'b0, TCDM_TS}, + {1'b1, TCDM_TS}, + {1'b1, CLUSTER_ALIAS_TCDM_TS}: begin + destination = SH; + end + + {1'b0, DEM_PER}, + {1'b1, DEM_PER}, + {1'b1, CLUSTER_ALIAS_DEM_PER}: begin + if(data_add_int[14]) begin // DEMUX PERIPHERALS + destination = EXT; + end else begin + destination = PE; + end + end + + default: begin + destination = PE; + end + endcase + end + end + + always_comb + begin : L1_REQUEST_ARBITER + if (DEM_PER_BEFORE_TCDM_TS) begin + if (data_add_int[31:21] == TCDM_RW[11:1] || //LOGARITHMIC INTERCONNECT --> 31:20 --> 0x100 or 0x101 + (CLUSTER_ALIAS && data_add_int[31:21] == CLUSTER_ALIAS_BASE_11) //LOGARITHMIC INTERCONNECT --> 31:20 --> 0x100 or 0x101 or ALIAS (0x000 or 0x001) or DEM PERIPH + ) begin: _TO_DEM_PER_L2_ + if (data_add_int[19:14] == 6'b11_1111) begin + data_req_o_SH = 1'b0; + data_req_to_L2 = data_req_i; + data_gnt_o = data_gnt_from_L2; + end else begin: _TO_CLUSTER_L1_ + data_req_o_SH = data_req_i; + data_req_to_L2 = 1'b0; + data_gnt_o = data_gnt_i_SH; + end + end else begin: _DPBTT_TO_L2_LEVEL_ + data_req_o_SH = 1'b0; + data_req_to_L2 = data_req_i; + data_gnt_o = data_gnt_from_L2; + end + end else begin + if (data_add_int[31:21] == TCDM_RW[11:1] || //LOGARITHMIC INTERCONNECT --> 31:20 --> 0x100 or 0x101 + (CLUSTER_ALIAS && data_add_int[31:21] == CLUSTER_ALIAS_BASE_11) //LOGARITHMIC INTERCONNECT --> 31:20 --> 0x100 or 0x101 or ALIAS (0x000 or 0x001) or DEM PERIPH + ) begin: _TO_CLUSTER_ + data_req_o_SH = data_req_i; + data_req_to_L2 = 1'b0; + data_gnt_o = data_gnt_i_SH; + end else begin: _TO_L2_LEVEL_ + data_req_o_SH = 1'b0; + data_req_to_L2 = data_req_i; + data_gnt_o = data_gnt_from_L2; + end + end + end + + // level 2 request arbiter + assign data_add_PE_fifo = data_add_int; + assign data_wen_PE_fifo = data_wen_i; + assign data_atop_PE_fifo = data_atop_i; + assign data_wdata_PE_fifo = data_wdata_i; + assign data_be_PE_fifo = data_be_i; + + assign data_add_o_EXT = data_add_int; + assign data_wen_o_EXT = data_wen_i; + assign data_wdata_o_EXT = data_wdata_i; + assign data_be_o_EXT = data_be_i; + + always_comb + begin : _L2_REQUEST_ARBITER_ + if (DEM_PER_BEFORE_TCDM_TS) begin + if (data_add_int[19:14] == 6'b11_1111 && ( + ( CLUSTER_ALIAS && ( + data_add_int[31:20] == TCDM_RW || data_add_int[31:20] == CLUSTER_ALIAS_TCDM_RW) + ) || + (!CLUSTER_ALIAS && data_add_int[31:20] == DEM_PER) + )) begin: _DPBTT_TO_DEMUX_PERIPH_ //Peripheral --> add_i[31:0] --> 0x100F_FC00 to 0x100F_FFFF + data_req_PE_fifo = 1'b0; + data_req_o_EXT = data_req_to_L2; + data_gnt_from_L2 = data_gnt_i_EXT; + end else begin: _DPBTT_TO_PERIPHERAL_INTERCO_ + data_req_PE_fifo = s_data_req_PE; + data_req_o_EXT = 1'b0; + data_gnt_from_L2 = s_data_gnt_PE; + end + end else begin + if (data_add_int[14] && ( + data_add_int[31:20] == DEM_PER || + (CLUSTER_ALIAS && data_add_int[31:20] == CLUSTER_ALIAS_DEM_PER) + )) begin: _TO_DEMUX_PERIPH_ //Peripheral --> add_i[31:0] --> 0x1020_4000 to 0x1020_7FFF + data_req_PE_fifo = 1'b0; + data_req_o_EXT = data_req_to_L2; + data_gnt_from_L2 = data_gnt_i_EXT; + end else begin: _TO_PERIPHERAL_INTERCO_ + data_req_PE_fifo = s_data_req_PE; + data_req_o_EXT = 1'b0; + data_gnt_from_L2 = s_data_gnt_PE; + end + end + end + + // response arbiter + always_comb + begin: _RESPONSE_ARBITER_ + case(request_destination) + SH : begin + data_r_valid_o = data_r_valid_i_SH; + data_r_rdata_o = data_r_rdata_i_SH; + data_r_opc_o = 1'b0; + end + + PE : begin + data_r_valid_o = s_data_r_valid_PE; + data_r_rdata_o = s_data_r_data_PE; + data_r_opc_o = s_data_r_opc_PE; + end + + EXT : begin + data_r_valid_o = data_r_valid_i_EXT; + data_r_rdata_o = data_r_rdata_i_EXT; + data_r_opc_o = data_r_opc_i_EXT; + end + + default : begin + data_r_valid_o = 1'b0; + data_r_rdata_o = 'x; + data_r_opc_o = 1'b0; + end + endcase + end + + // pe interface + always_ff @(posedge clk, negedge rst_ni) + begin + if(rst_ni == 1'b0) begin + CS <= TRANS_IDLE; + end + else begin + CS <= NS; + end + end + + always_comb + begin + s_data_gnt_PE = 1'b0; + s_data_req_PE = 1'b0; + case(CS) + TRANS_IDLE : begin + if( ( data_req_i == 1'b1 ) && ( destination == PE ) ) begin + s_data_req_PE = 1'b1; + if (data_gnt_PE_fifo == 1'b1) begin + NS = TRANS_PENDING; + end + else begin + NS = TRANS_IDLE; + end + end + else begin + NS = TRANS_IDLE; + end + end + TRANS_PENDING : begin + if (data_r_valid_PE_fifo == 1'b1) begin + NS = TRANS_GRANTED; + end + else begin + NS = TRANS_PENDING; + end + end + TRANS_GRANTED : begin + s_data_gnt_PE = 1'b1; + NS = TRANS_IDLE; + end + default : begin + NS = TRANS_IDLE; + end + endcase + end + + // periph response generation + always_ff @(posedge clk, negedge rst_ni) + begin + if(rst_ni == 1'b0) begin + s_data_r_valid_PE_0 <= '0; + s_data_r_data_PE_0 <= '0; + s_data_r_opc_PE_0 <= '0; + end + else begin + s_data_r_valid_PE_0 <= data_r_valid_PE_fifo; + if(data_r_valid_PE_fifo) begin + s_data_r_data_PE_0 <= data_r_rdata_PE_fifo; + s_data_r_opc_PE_0 <= data_r_opc_PE_fifo; + end + end + end + + always_ff @(posedge clk, negedge rst_ni) begin + if(rst_ni == 1'b0) begin + s_data_r_valid_PE <= '0; + s_data_r_data_PE <= '0; + s_data_r_opc_PE <= '0; + end + else begin + s_data_r_valid_PE <= s_data_r_valid_PE_0; + if(s_data_r_valid_PE_0) begin + s_data_r_data_PE <= s_data_r_data_PE_0; + s_data_r_opc_PE <= s_data_r_opc_PE_0; + end + end + end + + periph_FIFO #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BYTE_ENABLE_BIT ( DATA_WIDTH/8 ) + ) periph_FIFO_i ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + //Input SIde REQ + .data_req_i ( data_req_PE_fifo ), + .data_add_i ( data_add_PE_fifo ), + .data_wen_i ( data_wen_PE_fifo ), + .data_atop_i ( data_atop_PE_fifo ), + .data_wdata_i ( data_wdata_PE_fifo ), + .data_be_i ( data_be_PE_fifo ), + .data_gnt_o ( data_gnt_PE_fifo ), + + //Output side REQ + .data_req_o ( data_req_o_PE ), + .data_add_o ( data_add_o_PE ), + .data_wen_o ( data_wen_o_PE ), + .data_atop_o ( data_atop_o_PE ), + .data_wdata_o ( data_wdata_o_PE ), + .data_be_o ( data_be_o_PE ), + .data_gnt_i ( data_gnt_i_PE ), + + //Input Side RESP + .data_r_valid_i ( data_r_valid_i_PE ), + .data_r_opc_i ( data_r_opc_i_PE ), + .data_r_rdata_i ( data_r_rdata_i_PE ), + + //Output Side RESP + .data_r_valid_o ( data_r_valid_PE_fifo ), + .data_r_opc_o ( data_r_opc_PE_fifo ), + .data_r_rdata_o ( data_r_rdata_PE_fifo ) + ); + + // Performance Counters + assign perf_l2_ld_o = data_req_to_L2 & data_gnt_from_L2 & data_wen_i; + assign perf_l2_st_o = data_req_to_L2 & data_gnt_from_L2 & (~data_wen_i); + assign perf_l2_ld_cyc_o = data_req_to_L2 & data_wen_i; + assign perf_l2_st_cyc_o = data_req_to_L2 & (~data_wen_i); + +`ifdef PERF_CNT + logic [31:0] STALL_TCDM; + logic [31:0] STALL_L2; + + logic clear_regs, enable_regs; + + always_ff @(posedge clk or negedge rst_ni) + begin + if(~rst_ni) begin + STALL_TCDM <= '0; + STALL_L2 <= '0; + end + else begin + if(clear_regs) begin + STALL_TCDM <= '0; + STALL_L2 <= '0; + end + else if(enable_regs) begin + if( data_req_o_SH & ~data_gnt_i_SH ) + STALL_TCDM <= STALL_TCDM + 1'b1; + if( data_req_to_L2 & ~data_gnt_from_L2 ) + STALL_L2 <= STALL_L2 + 1'b1; + end + end + end +`endif + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/core_region.sv b/hw/deps/pulp_cluster/rtl/core_region.sv new file mode 100644 index 0000000..1b1fcad --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/core_region.sv @@ -0,0 +1,573 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * core_region.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +import apu_package::*; + +/* verilator tracing_on */ + +// USER DEFINED MACROS to improve self-testing capabilities +`ifndef PULP_FPGA_SIM + `define DEBUG_FETCH_INTERFACE +`endif +//`define DATA_MISS +//`define DUMP_INSTR_FETCH + +module core_region +#( + // CORE PARAMETERS + parameter int CORE_ID = 0, + parameter int ADDR_WIDTH = 32, + parameter int DATA_WIDTH = 32, + parameter int INSTR_RDATA_WIDTH = 32, + parameter bit CLUSTER_ALIAS = 1'b1, + parameter int CLUSTER_ALIAS_BASE = 12'h000, + parameter int REMAP_ADDRESS = 0, + parameter bit DEM_PER_BEFORE_TCDM_TS = 1'b0, + parameter int INTER_CORE_FIFO_DEPTH = 0, + parameter int N_PMP_ENTRIES = 16 +`ifndef SYNTHESIS + , + parameter string L2_SLM_FILE = "./slm_files/l2_stim.slm", + parameter string ROM_SLM_FILE = "../sw/apps/boot/slm_files/l2_stim.slm" +`endif +) +( + input logic clk_i, + input logic rst_ni, + input logic init_ni, + + input logic [3:0] base_addr_i, // FOR CLUSTER VIRTUALIZATION + + input logic [5:0] cluster_id_i, + + input logic irq_req_i, + output logic irq_ack_o, + input logic [4:0] irq_id_i, + output logic [4:0] irq_ack_id_o, + + input logic clock_en_i, + input logic fetch_en_i, + input logic fregfile_disable_i, + + input logic [31:0] boot_addr_i, + + input logic test_mode_i, + + output logic core_busy_o, + + // Interface to Instruction Logarithmic interconnect (Req->grant handshake) + output logic instr_req_o, + input logic instr_gnt_i, + output logic [31:0] instr_addr_o, + input logic [INSTR_RDATA_WIDTH-1:0] instr_r_rdata_i, + input logic instr_r_valid_i, + + XBAR_TCDM_BUS.Slave debug_bus, + output logic debug_core_halted_o, + input logic debug_core_halt_i, + input logic debug_core_resume_i, + + output logic unaligned_o, + + // Interface for DEMUX to TCDM INTERCONNECT ,PERIPHERAL INTERCONNECT and DMA CONTROLLER + XBAR_TCDM_BUS.Master tcdm_data_master, + output logic [5:0] tcdm_data_master_atop, + XBAR_TCDM_BUS.Master dma_ctrl_master, + XBAR_PERIPH_BUS.Master eu_ctrl_master, + XBAR_PERIPH_BUS.Master periph_data_master, + output logic [5:0] periph_data_master_atop, + + XBAR_PERIPH_BUS.Slave this_fifo_slave, + XBAR_PERIPH_BUS.Master next_fifo_master, + + XBAR_PERIPH_BUS.Master hpu_driver_master, + + // APU interconnect interface + cpu_marx_if.cpu apu_master, + + //interface for configuring PMP from external + input logic pmp_conf_override_i, + input logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_i, + input logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_i +); + + XBAR_DEMUX_BUS s_core_bus(); // Internal interface between CORE <--> DEMUX + XBAR_PERIPH_BUS periph_demux_bus(); // Internal interface between CORE_DEMUX <--> PERIPHERAL DEMUX + XBAR_PERIPH_BUS this_fifo(); + XBAR_PERIPH_BUS periph_data(), periph_data_buf(); + + logic core_buffer; + logic [5:0] periph_data_atop, + periph_data_buf_atop; + + logic [4:0] perf_counters; + logic clk_int; + + // clock gate of the core_region less the core itself + cluster_clock_gating clock_gate_i ( + .clk_i ( clk_i ), + .en_i ( clock_en_i ), + .test_en_i ( test_mode_i ), + .clk_o ( clk_int ) + ); + + + logic [31:0] hart_id; + always_comb begin + hart_id = '0; + hart_id[3:0] = CORE_ID[3:0]; + hart_id[10:5] = cluster_id_i; + end + logic [5:0] irq_ack_id; + assign irq_ack_id_o = irq_ack_id[4:0]; + assert property (@(posedge clk_i) irq_ack_o |-> !irq_ack_id[5]); + riscv_core #( + .N_EXT_PERF_COUNTERS ( 5 ), + .FPU ( FPU ), + .SHARED_FP ( SHARED_FP ), + .SHARED_DSP_MULT ( SHARED_DSP_MULT ), + .SHARED_INT_DIV ( SHARED_INT_DIV ), + .SHARED_FP_DIVSQRT ( SHARED_FP_DIVSQRT ), + .WAPUTYPE ( WAPUTYPE ), + .PULP_HWLP ( 1 ), + .N_PMP_ENTRIES ( N_PMP_ENTRIES ) + ) RISCV_CORE ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .clock_en_i ( clock_en_i ), + .scan_cg_en_i ( test_mode_i ), + + .boot_addr_i ( boot_addr_i ), + .dm_halt_addr_i ( '0 ), + .hart_id_i ( hart_id ), + + .instr_req_o ( instr_req_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_r_valid_i ), + .instr_addr_o ( instr_addr_o ), + .instr_rdata_i ( instr_r_rdata_i ), + + .data_req_o ( s_core_bus.req ), + .data_gnt_i ( s_core_bus.gnt ), + .data_rvalid_i ( s_core_bus.r_valid ), + .data_we_o ( s_core_bus.we ), + .data_be_o ( s_core_bus.be ), + .data_addr_o ( s_core_bus.add ), + .data_wdata_o ( s_core_bus.wdata ), + .data_rdata_i ( s_core_bus.r_rdata ), + + .data_atop_o ( s_core_bus.atop ), + .data_buffer_o ( core_buffer ), + .data_unaligned_o ( unaligned_o ), + + // apu-interconnect + // handshake signals + .apu_master_req_o ( /* unused */ ), + .apu_master_ready_o ( /* unused */ ), + .apu_master_gnt_i ( '0 ), + // request channel + .apu_master_operands_o ( /* unused */ ), + .apu_master_op_o ( /* unused */ ), + .apu_master_type_o ( /* unused */ ), + .apu_master_flags_o ( /* unused */ ), + // response channel + .apu_master_valid_i ( '0 ), + .apu_master_result_i ( '0 ), + .apu_master_flags_i ( '0 ), + + .irq_ack_o ( irq_ack_o ), + .irq_id_o ( irq_ack_id ), + + .irq_software_i ( '0 ), + .irq_timer_i ( '0 ), + .irq_external_i ( '0 ), + .irq_fast_i ( '0 ), + + .debug_req_i ( debug_bus.req ), + + .fetch_enable_i ( fetch_en_i ), + .core_busy_o ( core_busy_o ), + + .pmp_conf_override_i ( pmp_conf_override_i ), + .pmp_cfg_i ( pmp_cfg_i ), + .pmp_addr_i ( pmp_addr_i ) + ); + + assign debug_bus.r_opc = 1'b0; + + // Bind to 0 Unused Signals in CORE interface + assign s_core_bus.r_gnt = 1'b0; + assign s_core_bus.barrier = 1'b0; + assign s_core_bus.exec_cancel = 1'b0; + assign s_core_bus.exec_stall = 1'b0; + + // Performance Counters + assign perf_counters[4] = tcdm_data_master.req & (~tcdm_data_master.gnt); // Cycles lost due to contention + + // demuxes to TCDM & memory hierarchy + core_demux #( + .ADDR_WIDTH ( 32 ), + .DATA_WIDTH ( 32 ), + .BYTE_ENABLE_BIT ( DATA_WIDTH/8 ), + .CLUSTER_ALIAS ( CLUSTER_ALIAS ), + .CLUSTER_ALIAS_BASE ( CLUSTER_ALIAS_BASE ), + .DEM_PER_BEFORE_TCDM_TS ( DEM_PER_BEFORE_TCDM_TS ), + .REMAP_ADDRESS ( REMAP_ADDRESS ) + ) core_demux_i ( + .clk ( clk_int ), + .rst_ni ( rst_ni ), + .test_en_i ( test_mode_i ), + .base_addr_i ( base_addr_i ), + + .data_req_i ( s_core_bus.req ), + .data_add_i ( s_core_bus.add ), + .data_wen_i ( ~s_core_bus.we ), //inverted when using OR10N + .data_atop_i ( s_core_bus.atop ), + .data_wdata_i ( s_core_bus.wdata ), + .data_be_i ( s_core_bus.be ), + .data_gnt_o ( s_core_bus.gnt ), + .data_r_gnt_i ( s_core_bus.r_gnt ), + .data_r_valid_o ( s_core_bus.r_valid ), + .data_r_opc_o ( ), + .data_r_rdata_o ( s_core_bus.r_rdata ), + + .data_req_o_SH ( tcdm_data_master.req ), + .data_add_o_SH ( tcdm_data_master.add ), + .data_wen_o_SH ( tcdm_data_master.wen ), + .data_atop_o_SH ( tcdm_data_master_atop ), + .data_wdata_o_SH ( tcdm_data_master.wdata ), + .data_be_o_SH ( tcdm_data_master.be ), + .data_gnt_i_SH ( tcdm_data_master.gnt ), + .data_r_valid_i_SH ( tcdm_data_master.r_valid ), + .data_r_rdata_i_SH ( tcdm_data_master.r_rdata ), + + .data_req_o_EXT ( periph_demux_bus.req ), + .data_add_o_EXT ( periph_demux_bus.add ), + .data_wen_o_EXT ( periph_demux_bus.wen ), + .data_wdata_o_EXT ( periph_demux_bus.wdata ), + .data_be_o_EXT ( periph_demux_bus.be ), + .data_gnt_i_EXT ( periph_demux_bus.gnt ), + .data_r_valid_i_EXT ( periph_demux_bus.r_valid ), + .data_r_rdata_i_EXT ( periph_demux_bus.r_rdata ), + .data_r_opc_i_EXT ( periph_demux_bus.r_opc ), + + .data_req_o_PE ( periph_data.req ), + .data_add_o_PE ( periph_data.add ), + .data_wen_o_PE ( periph_data.wen ), + .data_atop_o_PE ( periph_data_atop ), + .data_wdata_o_PE ( periph_data.wdata ), + .data_be_o_PE ( periph_data.be ), + .data_gnt_i_PE ( periph_data.gnt ), + .data_r_valid_i_PE ( periph_data.r_valid ), + .data_r_rdata_i_PE ( periph_data.r_rdata ), + .data_r_opc_i_PE ( periph_data.r_opc ), + + .perf_l2_ld_o ( perf_counters[0] ), + .perf_l2_st_o ( perf_counters[1] ), + .perf_l2_ld_cyc_o ( perf_counters[2] ), + .perf_l2_st_cyc_o ( perf_counters[3] ), + .CLUSTER_ID ( cluster_id_i ) + ); + + riscv_store_buffer #( + .Depth (16), + .AddrWidth (32), + .DataWidth (32) + ) i_store_buf ( + .clk_i ( clk_int ), + .rst_ni, + // Upstream + .addr_i ( periph_data.add ), + .we_ni ( periph_data.wen ), + .buffer_i ( core_buffer ), + .be_i ( periph_data.be ), + .wdata_i ( periph_data.wdata ), + .atop_i ( periph_data_atop ), + .req_i ( periph_data.req ), + .gnt_o ( periph_data.gnt ), + .rdata_o ( periph_data.r_rdata ), + .rvalid_o ( periph_data.r_valid ), + // Downstream + .addr_o ( periph_data_buf.add ), + .we_no ( periph_data_buf.wen ), + .be_o ( periph_data_buf.be ), + .wdata_o ( periph_data_buf.wdata ), + .atop_o ( periph_data_buf_atop ), + .req_o ( periph_data_buf.req ), + .gnt_i ( periph_data_buf.gnt ), + .rdata_i ( periph_data_buf.r_rdata ), + .rvalid_i ( periph_data_buf.r_valid ) + ); + assign periph_data.r_id = '0; + assign periph_data.r_opc = 1'b0; + assign periph_data_buf.id = periph_data.id; + + periph_demux #( + .DEM_PER_BEFORE_TCDM_TS (DEM_PER_BEFORE_TCDM_TS) + ) periph_demux_i ( + .clk ( clk_int ), + .rst_ni ( rst_ni ), + + .data_req_i ( periph_demux_bus.req ), + .data_add_i ( periph_demux_bus.add ), + .data_wen_i ( periph_demux_bus.wen ), + .data_wdata_i ( periph_demux_bus.wdata ), + .data_be_i ( periph_demux_bus.be ), + .data_gnt_o ( periph_demux_bus.gnt ), + + .data_r_valid_o ( periph_demux_bus.r_valid ), + .data_r_opc_o ( periph_demux_bus.r_opc ), + .data_r_rdata_o ( periph_demux_bus.r_rdata ), + + .data_req_o_MH ( dma_ctrl_master.req ), + .data_add_o_MH ( dma_ctrl_master.add ), + .data_wen_o_MH ( dma_ctrl_master.wen ), + .data_wdata_o_MH ( dma_ctrl_master.wdata ), + .data_be_o_MH ( dma_ctrl_master.be ), + .data_gnt_i_MH ( dma_ctrl_master.gnt ), + + .data_r_valid_i_MH ( dma_ctrl_master.r_valid ), + .data_r_rdata_i_MH ( dma_ctrl_master.r_rdata ), + .data_r_opc_i_MH ( dma_ctrl_master.r_opc ), + + .data_req_o_EU ( eu_ctrl_master.req ), + .data_add_o_EU ( eu_ctrl_master.add ), + .data_wen_o_EU ( eu_ctrl_master.wen ), + .data_wdata_o_EU ( eu_ctrl_master.wdata ), + .data_be_o_EU ( eu_ctrl_master.be ), + .data_gnt_i_EU ( eu_ctrl_master.gnt ), + + .data_r_valid_i_EU ( eu_ctrl_master.r_valid ), + .data_r_rdata_i_EU ( eu_ctrl_master.r_rdata ), + .data_r_opc_i_EU ( eu_ctrl_master.r_opc ), + + .data_req_o_MYF ( this_fifo.req ), + .data_add_o_MYF ( this_fifo.add ), + .data_wen_o_MYF ( this_fifo.wen ), + .data_wdata_o_MYF ( this_fifo.wdata ), + .data_be_o_MYF ( this_fifo.be ), + .data_gnt_i_MYF ( this_fifo.gnt ), + + .data_r_valid_i_MYF( this_fifo.r_valid ), + .data_r_rdata_i_MYF( this_fifo.r_rdata ), + .data_r_opc_i_MYF ( this_fifo.r_opc ), + + .data_req_o_NBF ( next_fifo_master.req ), + .data_add_o_NBF ( next_fifo_master.add ), + .data_wen_o_NBF ( next_fifo_master.wen ), + .data_wdata_o_NBF ( next_fifo_master.wdata ), + .data_be_o_NBF ( next_fifo_master.be ), + .data_gnt_i_NBF ( next_fifo_master.gnt ), + + .data_r_valid_i_NBF( next_fifo_master.r_valid ), + .data_r_rdata_i_NBF( next_fifo_master.r_rdata ), + .data_r_opc_i_NBF ( next_fifo_master.r_opc ), + + .data_req_o_HDRV ( hpu_driver_master.req ), + .data_add_o_HDRV ( hpu_driver_master.add ), + .data_wen_o_HDRV ( hpu_driver_master.wen ), + .data_wdata_o_HDRV ( hpu_driver_master.wdata), + .data_be_o_HDRV ( hpu_driver_master.be ), + .data_gnt_i_HDRV ( hpu_driver_master.gnt ), + + .data_r_valid_i_HDRV( hpu_driver_master.r_valid ), + .data_r_rdata_i_HDRV( hpu_driver_master.r_rdata ), + .data_r_opc_i_HDRV ( hpu_driver_master.r_opc ) + + + ); + + if (INTER_CORE_FIFO_DEPTH > 0) begin : gen_inter_core_fifo + inter_core_fifo #( + .Depth (INTER_CORE_FIFO_DEPTH) + ) i_inter_core_fifo ( + .clk_i, + .rst_ni, + .push_slv (this_fifo_slave), + .pop_slv (this_fifo) + ); + end else begin : gen_no_inter_core_fifo + assign this_fifo_slave.gnt = 1'b1; + assign this_fifo_slave.r_valid = 1'b1; + assign this_fifo_slave.r_rdata = '0; + assign this_fifo_slave.r_opc = '0; + assign this_fifo.gnt = 1'b1; + assign this_fifo.r_valid = 1'b1; + assign this_fifo.r_rdata = '0; + assign this_fifo.r_opc = '0; + end + + virtual_stdout_demux #( + .CoreId (CORE_ID) + ) i_stdout ( + .clk_i (clk_int), + .rst_ni, + .cluster_id_i, + .periph_slv (periph_data_buf), + .periph_slv_atop_i (periph_data_buf_atop), + .periph_mst (periph_data_master), + .periph_mst_atop_o (periph_data_master_atop) + ); + + /* debug stuff */ + //synopsys translate_off + + // COMPARE THE output of the instruction CACHE with the slm files generated by the compiler +`ifdef DEBUG_FETCH_INTERFACE + integer FILE; + string FILENAME; + string FILE_ID; + + logic instr_gnt_L2; + logic instr_gnt_ROM; + logic [INSTR_RDATA_WIDTH-1:0] instr_r_rdata_ROM; + logic instr_r_valid_ROM; + logic [INSTR_RDATA_WIDTH-1:0] instr_r_rdata_L2; + logic instr_r_valid_L2; + logic destination; //--> 0 fetch from BOOT_ROM, 1--> fetch from L2_MEMORY + + initial + begin + FILE_ID.itoa(CORE_ID); + FILENAME = {"FETCH_CORE_", FILE_ID, ".log" }; + FILE=$fopen(FILENAME,"w"); + end + + // BOOT code is loaded in this dummy ROM_MEMORY +/* -----\/----- EXCLUDED -----\/----- + generate + case(INSTR_RDATA_WIDTH) + 128: begin + ibus_lint_memory_128 #( + .addr_width ( 16 ), + .INIT_MEM_FILE ( ROM_SLM_FILE ) + ) ROM_MEMORY ( + .clk ( clk_i ), + .rst_n ( rst_ni ), + .lint_req_i ( instr_req_o ), + .lint_grant_o ( instr_gnt_ROM ), + .lint_addr_i ( instr_addr_o[19:4] ), //instr_addr_o[17:2] --> 2^17 bytes max program + .lint_r_rdata_o ( instr_r_rdata_ROM ), + .lint_r_valid_o ( instr_r_valid_ROM ) + ); + + // application code is loaded in this dummy L2_MEMORY + ibus_lint_memory_128 #( + .addr_width ( 16 ), + .INIT_MEM_FILE ( L2_SLM_FILE ) + ) L2_MEMORY ( + .clk ( clk_i ), + .rst_n ( rst_ni ), + .lint_req_i ( instr_req_o ), + .lint_grant_o ( instr_gnt_L2 ), + .lint_addr_i ( instr_addr_o[19:4] ), //instr_addr_o[17:2] --> 2^17 bytes max program + .lint_r_rdata_o ( instr_r_rdata_L2 ), + .lint_r_valid_o ( instr_r_valid_L2 ) + ); + end + 32: begin + ibus_lint_memory #( + .addr_width ( 16 ), + .INIT_MEM_FILE ( ROM_SLM_FILE ) + ) ROM_MEMORY ( + .clk ( clk_i ), + .rst_n ( rst_ni ), + .lint_req_i ( instr_req_o ), + .lint_grant_o ( instr_gnt_ROM ), + .lint_addr_i ( instr_addr_o[17:2] ), //instr_addr_o[17:2] --> 2^17 bytes max program + .lint_r_rdata_o ( instr_r_rdata_ROM ), + .lint_r_valid_o ( instr_r_valid_ROM ) + ); + + // application code is loaded in this dummy L2_MEMORY + ibus_lint_memory #( + .addr_width ( 16 ), + .INIT_MEM_FILE ( L2_SLM_FILE ) + ) L2_MEMORY ( + .clk ( clk_i ), + .rst_n ( rst_ni ), + .lint_req_i ( instr_req_o ), + .lint_grant_o ( instr_gnt_L2 ), + .lint_addr_i ( instr_addr_o[17:2] ), //instr_addr_o[17:2] --> 2^17 bytes max program + .lint_r_rdata_o ( instr_r_rdata_L2 ), + .lint_r_valid_o ( instr_r_valid_L2 ) + ); + end + endcase // INSTR_RDATA_WIDTH + endgenerate + -----/\----- EXCLUDED -----/\----- */ + + // SELF CHECK ROUTINES TO compare isntruction fetches with slm files + always_ff @(posedge clk_i) + begin + if(instr_r_valid_i) begin + $fwrite( FILE , "\t --> %8h\n",instr_r_rdata_i); + case(destination) + 1'b1: begin + // Not active by default as it is wrong once the code is dynamically modified + //if(instr_r_rdata_i !== instr_r_rdata_L2) + //begin + // $warning("Error DURING L2 fetch: %x != %x", instr_r_rdata_i, instr_r_rdata_L2); + // $stop(); + //end + end + 1'b0: begin + if(instr_r_rdata_i !== instr_r_rdata_ROM) begin + $warning("Error DURING ROM Fetch: %x != %x", instr_r_rdata_i, instr_r_rdata_ROM); + $stop(); + end + end + endcase + end + //DUMP TO FILE every transaction to instruction cache + if(instr_req_o & instr_gnt_i) begin + if(instr_addr_o[31:24] == 8'h1A) + destination <= 1'b0; + else + destination <= 1'b1; +`ifdef DUMP_INSTR_FETCH + $fwrite( FILE , "%t [ns]: FETCH at address %8h",$time/1000, instr_addr_o); +`endif + end + end +`endif + +`ifdef DATA_MISS + logic data_hit; + logic req; +`endif + logic reg_cache_refill; + + always_ff @(posedge clk_i , negedge rst_ni) + begin + if ( rst_ni == 1'b0 ) begin + reg_cache_refill <= 1'b0; + end + else begin + if (instr_req_o) + reg_cache_refill <= 1'b1; + else if(instr_r_valid_i && !instr_req_o) + reg_cache_refill <= 1'b0; + end + end +//synopsys translate_on + +/* verilator tracing_off */ + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/cpu_marx_if.sv b/hw/deps/pulp_cluster/rtl/cpu_marx_if.sv new file mode 100644 index 0000000..971d8dd --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/cpu_marx_if.sv @@ -0,0 +1,63 @@ +// Copyright 2018 ETH Zurich and 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. + +interface cpu_marx_if #( + parameter WOP_CPU = 0, + parameter WAPUTYPE = 0, + parameter NUSFLAGS_CPU = 1, + parameter NDSFLAGS_CPU = 1, + parameter WRESULT = 32, + parameter WARG = 32, + parameter NARGS_CPU = 3 +); + + // Downstream + logic req_ds_s; + logic ack_ds_s; + logic [WAPUTYPE-1:0] type_ds_d; + logic [WARG-1:0] operands_ds_d [NARGS_CPU-1:0]; + logic [WOP_CPU-1:0] op_ds_d; + logic [NDSFLAGS_CPU-1:0] flags_ds_d; + + // Upstream + logic valid_us_s; + logic ready_us_s; + logic [WRESULT-1:0] result_us_d; + logic [NUSFLAGS_CPU-1:0] flags_us_d; + + // The interface from the perspective of the core. + modport cpu ( + output req_ds_s, + output type_ds_d, + output operands_ds_d, + output op_ds_d, + output flags_ds_d, + output ready_us_s, + input ack_ds_s, + input valid_us_s, + input result_us_d, + input flags_us_d + ); + + // The interface from the perspective of the interconnect. + modport marx ( + input req_ds_s, + input type_ds_d, + input operands_ds_d, + input op_ds_d, + input ready_us_s, + input flags_ds_d, + output ack_ds_s, + output valid_us_s, + output result_us_d, + output flags_us_d + ); + +endinterface diff --git a/hw/deps/pulp_cluster/rtl/dmac_wrap.sv b/hw/deps/pulp_cluster/rtl/dmac_wrap.sv new file mode 100644 index 0000000..21eea72 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/dmac_wrap.sv @@ -0,0 +1,359 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * dmac_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + * Thomas Benz + */ + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module dmac_wrap +#( + parameter NB_CORES = 4, + parameter NB_OUTSND_BURSTS = 8, + parameter MCHAN_BURST_LENGTH = 256, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 4, + parameter PE_ID_WIDTH = 1, + parameter TCDM_ADD_WIDTH = 13, + parameter DATA_WIDTH = 32, + parameter ADDR_WIDTH = 32, + parameter BE_WIDTH = DATA_WIDTH/8, + parameter DMA_AXI_AW_WIDTH = 32, + parameter DMA_AXI_DW_WIDTH = 512, + parameter DMA_AXI_ID_WIDTH = 4, + parameter DMA_AXI_UW_WIDTH = 4, + parameter TF_REQ_FIFO_DEPTH = 4, + + parameter type dma_transf_descr_t = logic +) +( + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + input logic [5:0] cluster_id_i, + XBAR_PERIPH_BUS.Slave pe_ctrl_slave, + XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], + XBAR_TCDM_BUS.Master tcdm_master[3:0], + AXI_BUS.Master ext_master, + AXI_BUS.Master s_wide_dma_soc, + WIDE_DMA_TCDM_BUS.Master s_wide_dma_superbanks, + output logic [NB_CORES-1:0] term_event_o, + output logic [NB_CORES-1:0] term_irq_o, + output logic term_event_pe_o, + output logic term_irq_pe_o, + output logic busy_o, + + input logic ext_dma_req_valid_i, + output logic ext_dma_req_ready_o, + input dma_transf_descr_t ext_dma_req_i, + + output logic ext_dma_rsp_valid_o, + + output logic [NB_CORES-1:0] no_req_pending_o + +); + + // CORE --> MCHAN CTRL INTERFACE BUS SIGNALS + logic [NB_CORES-1:0][DATA_WIDTH-1:0] s_ctrl_bus_wdata; + logic [NB_CORES-1:0][ADDR_WIDTH-1:0] s_ctrl_bus_add; + logic [NB_CORES-1:0] s_ctrl_bus_req; + logic [NB_CORES-1:0] s_ctrl_bus_wen; + logic [NB_CORES-1:0][BE_WIDTH-1:0] s_ctrl_bus_be; + logic [NB_CORES-1:0] s_ctrl_bus_gnt; + logic [NB_CORES-1:0][DATA_WIDTH-1:0] s_ctrl_bus_r_rdata; + logic [NB_CORES-1:0] s_ctrl_bus_r_valid; + + // MCHAN TCDM INIT --> TCDM MEMORY BUS SIGNALS + logic [3:0][DATA_WIDTH-1:0] s_tcdm_bus_wdata; + logic [3:0][ADDR_WIDTH-1:0] s_tcdm_bus_add; + logic [3:0] s_tcdm_bus_req; + logic [3:0] s_tcdm_bus_wen; + logic [3:0][BE_WIDTH-1:0] s_tcdm_bus_be; + logic [3:0] s_tcdm_bus_gnt; + logic [3:0][DATA_WIDTH-1:0] s_tcdm_bus_r_rdata; + logic [3:0] s_tcdm_bus_r_valid; + + generate + for (genvar i=0; i this delay needs to be explicitly + // calculated. + logic ext_dma_vld; + always_ff @(posedge clk_i) begin : proc_delay_gnt_by_one + if(~rst_ni) begin + ext_dma_vld <= 0; + end else begin + ext_dma_vld <= s_wide_dma_superbanks.gnt & s_wide_dma_superbanks.req; + end + end + + axi_to_mem_interleaved #( + .axi_req_t ( axi_dma_req_t ), + .axi_resp_t ( axi_dma_resp_t ), + .AddrWidth ( DMA_AXI_AW_WIDTH ), + .DataWidth ( DMA_AXI_DW_WIDTH ), + .IdWidth ( DMA_AXI_ID_WIDTH ), + .NumBanks ( 1 ), // Needs to be 1 + .BufDepth ( 4 ) // TODO: tune me + ) i_axi_to_mem ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .busy_o ( ), + .axi_req_i ( axi_dma_tcdm_req ), + .axi_resp_o ( axi_dma_tcdm_res ), + .mem_req_o ( s_wide_dma_superbanks.req ), + .mem_gnt_i ( s_wide_dma_superbanks.gnt ), + .mem_addr_o ( s_wide_dma_superbanks.add ), + .mem_wdata_o ( s_wide_dma_superbanks.wdata ), + .mem_strb_o ( s_wide_dma_superbanks.be ), + .mem_atop_o ( ), + .mem_we_o ( s_wide_dma_superbanks.wen ), + .mem_rvalid_i ( ext_dma_vld ), + .mem_rdata_i ( s_wide_dma_superbanks.r_rdata ) + ); + + // tie-off unused pulp ports + assign s_tcdm_bus_req = '0; + assign s_tcdm_bus_add = '0; + assign s_tcdm_bus_wen = '0; + assign s_tcdm_bus_be = '0; + assign s_tcdm_bus_wdata = '0; + assign internal.aw_valid = '0; + assign internal.aw_addr = '0; + assign internal.aw_prot = '0; + assign internal.aw_region = '0; + assign internal.aw_atop = '0; + assign internal.aw_len = '0; + assign internal.aw_size = '0; + assign internal.aw_burst = '0; + assign internal.aw_lock = '0; + assign internal.aw_cache = '0; + assign internal.aw_qos = '0; + assign internal.aw_id[AXI_ID_WIDTH-1:0] = '0; + assign internal.aw_user = '0; + assign internal.ar_valid = '0; + assign internal.ar_addr = '0; + assign internal.ar_prot = '0; + assign internal.ar_region = '0; + assign internal.ar_len = '0; + assign internal.ar_size = '0; + assign internal.ar_burst = '0; + assign internal.ar_lock = '0; + assign internal.ar_cache = '0; + assign internal.ar_qos = '0; + assign internal.ar_id[AXI_ID_WIDTH-1:0] = '0; + assign internal.ar_user = '0; + assign internal.w_valid = '0; + assign internal.w_data = '0; + assign internal.w_strb = '0; + assign internal.w_user = '0; + assign internal.r_ready = '0; + assign internal.b_ready = '0; + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/inter_core_fifo.sv b/hw/deps/pulp_cluster/rtl/inter_core_fifo.sv new file mode 100644 index 0000000..6eff249 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/inter_core_fifo.sv @@ -0,0 +1,116 @@ +// Copyright 2020 ETH Zurich and 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. + +`include "common_cells/registers.svh" + +module inter_core_fifo #( + parameter int unsigned Depth = 32'd0 +) ( + input logic clk_i, + input logic rst_ni, + XBAR_PERIPH_BUS.Slave push_slv, + XBAR_PERIPH_BUS.Slave pop_slv +); + + localparam int unsigned CntWidth = (Depth > 1) ? $clog2(Depth) : 1; + localparam int unsigned DataWidth = 32; + + typedef logic [CntWidth-1:0] cnt_t; + typedef logic [DataWidth-1:0] data_t; + + cnt_t usage; + data_t pop_data; + logic pop_rvalid_d, pop_rvalid_q, + push_rvalid_d, push_rvalid_q, + push_valid, + push_ready, + pop_valid, + pop_ready; + enum logic {Data, Usage} + pop_rdata_src_d, pop_rdata_src_q; + + stream_fifo #( + .FALL_THROUGH (1'b0), + .DEPTH (Depth), + .T (data_t) + ) i_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i (1'b0), + .data_i (push_slv.wdata), + .valid_i (push_valid), + .ready_o (push_ready), + .data_o (pop_data), + .valid_o (pop_valid), + .ready_i (pop_ready), + .usage_o (usage) + ); + + // Handle push interface. + assign push_slv.r_rdata = {{DataWidth-CntWidth{1'b0}}, usage}; + assign push_slv.r_opc = '0; + assign push_slv.r_id = '0; + assign push_slv.r_valid = push_rvalid_q; + always_comb begin + push_rvalid_d = 1'b0; + push_slv.gnt = 1'b0; + push_valid = 1'b0; + if (push_slv.req) begin + unique case ({push_slv.wen, push_slv.add[3:0]}) + {1'b0, 4'h0}: begin // write to push address + push_valid = 1'b1; + push_slv.gnt = push_ready; + if (push_ready) begin + push_rvalid_d = 1'b1; + end + end + default: begin // all reads and other writes return the current fill count + push_slv.gnt = 1'b1; + push_rvalid_d = 1'b1; + end + endcase + end + end + + // Handle pop interface. + assign pop_ready = pop_rvalid_q; + assign pop_slv.r_valid = pop_rvalid_q; + assign pop_slv.r_rdata = pop_rdata_src_q == Data ? pop_data : {{DataWidth-CntWidth{1'b0}}, usage}; + always_comb begin + pop_rdata_src_d = Data; + pop_rvalid_d = 1'b0; + pop_slv.gnt = 1'b0; + if (pop_slv.req) begin + unique case ({pop_slv.wen, pop_slv.add[3:0]}) + {1'b1, 4'h0}: begin // read from pop address + // Since the actual pop happens in the next cycle, we need to prevent an underrun by + // accepting two consecutive pop requests if the current usage is 1. So if the usage is + // one, we require that we are not popping in the current cycle. + if (pop_valid && (usage != 1 || !pop_ready)) begin + pop_slv.gnt = 1'b1; + pop_rvalid_d = 1'b1; + end + end + default: begin // all writes and other reads return the current fill count + pop_slv.gnt = 1'b1; + pop_rdata_src_d = Usage; + pop_rvalid_d = 1'b1; + end + endcase + end + end + + `FFARN(pop_rdata_src_q, pop_rdata_src_d, Data, clk_i, rst_ni) + `FFARN(pop_rvalid_q, pop_rvalid_d, 1'b0, clk_i, rst_ni) + `FFARN(push_rvalid_q, push_rvalid_d, 1'b0, clk_i, rst_ni) + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/nhi_port_wrap.sv b/hw/deps/pulp_cluster/rtl/nhi_port_wrap.sv new file mode 100644 index 0000000..7a469f6 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/nhi_port_wrap.sv @@ -0,0 +1,86 @@ +// Copyright 2020 ETH Zurich and 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. + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module nhi_port_wrap +#( + parameter DMA_AXI_AW_WIDTH = 32, + parameter DMA_AXI_DW_WIDTH = 512, + parameter DMA_AXI_ID_WIDTH = 4, + parameter DMA_AXI_UW_WIDTH = 4 +) ( + input logic clk_i, + input logic rst_ni, + + WIDE_DMA_TCDM_BUS.Master s_wide_dma_superbanks, + AXI_BUS.Slave s_wide_dma_nhi +); + + // axi definition + typedef logic [DMA_AXI_AW_WIDTH-1 :0] addr_t; + typedef logic [DMA_AXI_DW_WIDTH-1 :0] data_t; + typedef logic [DMA_AXI_ID_WIDTH-1 :0] id_oup_t; + typedef logic [DMA_AXI_DW_WIDTH/8-1:0] strb_t; + typedef logic [DMA_AXI_UW_WIDTH-1 :0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_oup_t, user_t); + `AXI_TYPEDEF_W_CHAN_T (w_chan_t, data_t, strb_t, user_t); + `AXI_TYPEDEF_B_CHAN_T (b_chan_t, id_oup_t, user_t); + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_oup_t, user_t); + `AXI_TYPEDEF_R_CHAN_T (r_chan_t, data_t, id_oup_t, user_t); + `AXI_TYPEDEF_REQ_T (axi_dma_req_t, aw_chan_t, w_chan_t, ar_chan_t); + `AXI_TYPEDEF_RESP_T (axi_dma_resp_t, b_chan_t, r_chan_t); + axi_dma_req_t axi_dma_tcdm_req; + axi_dma_resp_t axi_dma_tcdm_res; + + // connect to external AXI + `AXI_ASSIGN_TO_REQ(axi_dma_tcdm_req, s_wide_dma_nhi); + `AXI_ASSIGN_FROM_RESP (s_wide_dma_nhi, axi_dma_tcdm_res); + + // the data returned by the memories is always valid 1 cycle later + // this is usually handled by the TCDM interconnect correctly + // we bypass TCDM ic here -> this delay needs to be explicitly + // calculated. + logic ext_dma_vld; + always_ff @(posedge clk_i) begin : proc_delay_gnt_by_one + if(~rst_ni) begin + ext_dma_vld <= 0; + end else begin + ext_dma_vld <= s_wide_dma_superbanks.gnt & s_wide_dma_superbanks.req; + end + end + + axi_to_mem_interleaved #( + .axi_req_t ( axi_dma_req_t ), + .axi_resp_t ( axi_dma_resp_t ), + .AddrWidth ( DMA_AXI_AW_WIDTH ), + .DataWidth ( DMA_AXI_DW_WIDTH ), + .IdWidth ( DMA_AXI_ID_WIDTH ), + .NumBanks ( 1 ), // Needs to be 1 + .BufDepth ( 4 ) // TODO: tune me + ) i_axi_to_mem_nhi ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .busy_o ( ), + .axi_req_i ( axi_dma_tcdm_req ), + .axi_resp_o ( axi_dma_tcdm_res ), + .mem_req_o ( s_wide_dma_superbanks.req ), + .mem_gnt_i ( s_wide_dma_superbanks.gnt ), + .mem_addr_o ( s_wide_dma_superbanks.add ), + .mem_wdata_o ( s_wide_dma_superbanks.wdata ), + .mem_strb_o ( s_wide_dma_superbanks.be ), + .mem_atop_o ( ), + .mem_we_o ( s_wide_dma_superbanks.wen ), + .mem_rvalid_i ( ext_dma_vld ), + .mem_rdata_i ( s_wide_dma_superbanks.r_rdata ) + ); + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/per2axi_wrap.sv b/hw/deps/pulp_cluster/rtl/per2axi_wrap.sv new file mode 100644 index 0000000..76d4557 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/per2axi_wrap.sv @@ -0,0 +1,129 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * per2axi_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module per2axi_wrap +#( + parameter NB_CORES = 4, + parameter PER_ADDR_WIDTH = 32, + parameter PER_ID_WIDTH = 5, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64, + parameter AXI_USER_WIDTH = 6, + parameter AXI_ID_WIDTH = 4, + parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + XBAR_PERIPH_BUS.Slave periph_slave, + input logic [5:0] periph_slave_atop_i, + input logic [NB_CORES-1:0][AXI_USER_WIDTH-1:0] axi_axuser_i, + output logic [NB_CORES-1:0] axi_xresp_decerr_o, + output logic [NB_CORES-1:0] axi_xresp_slverr_o, + output logic [NB_CORES-1:0] axi_xresp_valid_o, + AXI_BUS.Master axi_master, + output logic busy_o +); + + per2axi #( + .NB_CORES ( NB_CORES ), + .PER_ADDR_WIDTH ( PER_ADDR_WIDTH ), + .PER_ID_WIDTH ( PER_ID_WIDTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ) + ) per2axi_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( test_en_i ), + + .per_slave_req_i ( periph_slave.req ), + .per_slave_add_i ( periph_slave.add ), + .per_slave_we_i ( periph_slave.wen ), + .per_slave_atop_i ( periph_slave_atop_i ), + .per_slave_wdata_i ( periph_slave.wdata ), + .per_slave_be_i ( periph_slave.be ), + .per_slave_id_i ( periph_slave.id[PER_ID_WIDTH-1:0] ), + .per_slave_gnt_o ( periph_slave.gnt ), + + .per_slave_r_valid_o ( periph_slave.r_valid ), + .per_slave_r_opc_o ( periph_slave.r_opc ), + .per_slave_r_id_o ( periph_slave.r_id[PER_ID_WIDTH-1:0] ), + .per_slave_r_rdata_o ( periph_slave.r_rdata ), + + .axi_axuser_i ( axi_axuser_i ), + .axi_xresp_decerr_o ( axi_xresp_decerr_o ), + .axi_xresp_slverr_o ( axi_xresp_slverr_o ), + .axi_xresp_valid_o ( axi_xresp_valid_o ), + + .axi_master_aw_valid_o ( axi_master.aw_valid ), + .axi_master_aw_addr_o ( axi_master.aw_addr ), + .axi_master_aw_prot_o ( axi_master.aw_prot ), + .axi_master_aw_region_o ( axi_master.aw_region ), + .axi_master_aw_len_o ( axi_master.aw_len ), + .axi_master_aw_size_o ( axi_master.aw_size ), + .axi_master_aw_burst_o ( axi_master.aw_burst ), + .axi_master_aw_lock_o ( axi_master.aw_lock ), + .axi_master_aw_atop_o ( axi_master.aw_atop ), + .axi_master_aw_cache_o ( axi_master.aw_cache ), + .axi_master_aw_qos_o ( axi_master.aw_qos ), + .axi_master_aw_id_o ( axi_master.aw_id[AXI_ID_WIDTH-1:0] ), + .axi_master_aw_user_o ( axi_master.aw_user ), + .axi_master_aw_ready_i ( axi_master.aw_ready ), + + .axi_master_ar_valid_o ( axi_master.ar_valid ), + .axi_master_ar_addr_o ( axi_master.ar_addr ), + .axi_master_ar_prot_o ( axi_master.ar_prot ), + .axi_master_ar_region_o ( axi_master.ar_region ), + .axi_master_ar_len_o ( axi_master.ar_len ), + .axi_master_ar_size_o ( axi_master.ar_size ), + .axi_master_ar_burst_o ( axi_master.ar_burst ), + .axi_master_ar_lock_o ( axi_master.ar_lock ), + .axi_master_ar_cache_o ( axi_master.ar_cache ), + .axi_master_ar_qos_o ( axi_master.ar_qos ), + .axi_master_ar_id_o ( axi_master.ar_id[AXI_ID_WIDTH-1:0] ), + .axi_master_ar_user_o ( axi_master.ar_user ), + .axi_master_ar_ready_i ( axi_master.ar_ready ), + + .axi_master_w_valid_o ( axi_master.w_valid ), + .axi_master_w_data_o ( axi_master.w_data ), + .axi_master_w_strb_o ( axi_master.w_strb ), + .axi_master_w_user_o ( axi_master.w_user ), + .axi_master_w_last_o ( axi_master.w_last ), + .axi_master_w_ready_i ( axi_master.w_ready ), + + .axi_master_r_valid_i ( axi_master.r_valid ), + .axi_master_r_data_i ( axi_master.r_data ), + .axi_master_r_resp_i ( axi_master.r_resp ), + .axi_master_r_last_i ( axi_master.r_last ), + .axi_master_r_id_i ( axi_master.r_id[AXI_ID_WIDTH-1:0] ), + .axi_master_r_user_i ( axi_master.r_user ), + .axi_master_r_ready_o ( axi_master.r_ready ), + + .axi_master_b_valid_i ( axi_master.b_valid ), + .axi_master_b_resp_i ( axi_master.b_resp ), + .axi_master_b_id_i ( axi_master.b_id[AXI_ID_WIDTH-1:0] ), + .axi_master_b_user_i ( axi_master.b_user ), + .axi_master_b_ready_o ( axi_master.b_ready ), + + .busy_o ( busy_o ) + ); + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/per_demux_wrap.sv b/hw/deps/pulp_cluster/rtl/per_demux_wrap.sv new file mode 100644 index 0000000..fc7bee2 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/per_demux_wrap.sv @@ -0,0 +1,75 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * per_demux_wrap.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module per_demux_wrap +#( + parameter NB_MASTERS = 2, + parameter ADDR_OFFSET = 10 +) +( + input logic clk_i, + input logic rst_ni, + XBAR_TCDM_BUS.Slave slave, + XBAR_TCDM_BUS.Master masters[NB_MASTERS-1:0] +); + + localparam NB_MASTERS_LOG = $clog2(NB_MASTERS); + + logic [NB_MASTERS_LOG-1:0] dest_q, dest_n; + + // need to explode the interfaces here because SystemVerilog does not allow + // to use it directly...... + logic [NB_MASTERS-1:0] masters_gnt; + logic [NB_MASTERS-1:0] masters_r_valid; + logic [NB_MASTERS-1:0] masters_r_opc; + logic [NB_MASTERS-1:0][31:0] masters_r_data; + + generate + for (genvar i = 0; i < NB_MASTERS; i++) begin + assign masters[i].req = (dest_n == i) ? slave.req : 1'b0; + assign masters[i].add = slave.add; + assign masters[i].wen = slave.wen; + assign masters[i].wdata = slave.wdata; + assign masters[i].be = slave.be; + + // for exploded interface + assign masters_gnt[i] = masters[i].gnt; + assign masters_r_valid[i] = masters[i].r_valid; + assign masters_r_opc[i] = masters[i].r_opc; + assign masters_r_data[i] = masters[i].r_rdata; + end + endgenerate + + assign slave.gnt = masters_gnt[dest_n]; + assign slave.r_valid = masters_r_valid[dest_q]; + assign slave.r_opc = masters_r_opc[dest_q]; + assign slave.r_rdata = masters_r_data[dest_q]; + + assign dest_n = slave.add[NB_MASTERS_LOG-1+ADDR_OFFSET:ADDR_OFFSET]; + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if (~rst_ni) begin + dest_q <= '0; + end + else begin + dest_q <= dest_n; + end + end + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/periph_FIFO.sv b/hw/deps/pulp_cluster/rtl/periph_FIFO.sv new file mode 100644 index 0000000..e5500df --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/periph_FIFO.sv @@ -0,0 +1,86 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * periph_FIFO.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module periph_FIFO +#( + parameter ADDR_WIDTH=32, + parameter DATA_WIDTH=32, + parameter BYTE_ENABLE_BIT=DATA_WIDTH/8 +) +( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + + //Input SIde REQ + input logic data_req_i, + input logic [ADDR_WIDTH - 1:0] data_add_i, + input logic data_wen_i, + input logic [5:0] data_atop_i, + input logic [DATA_WIDTH - 1:0] data_wdata_i, + input logic [BYTE_ENABLE_BIT - 1:0] data_be_i, + output logic data_gnt_o, + + //Output side REQ + output logic data_req_o, + output logic [ADDR_WIDTH - 1:0] data_add_o, + output logic data_wen_o, + output logic [5:0] data_atop_o, + output logic [DATA_WIDTH - 1:0] data_wdata_o, + output logic [BYTE_ENABLE_BIT - 1:0] data_be_o, + input logic data_gnt_i, + + //Input SIde RESP + input logic data_r_valid_i, + input logic data_r_opc_i, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i, + + //Output SIde RESP + output logic data_r_valid_o, + output logic data_r_opc_o, + output logic [DATA_WIDTH - 1:0] data_r_rdata_o +); + + localparam FIFO_DW = ADDR_WIDTH + 1 + 6 + DATA_WIDTH + BYTE_ENABLE_BIT; + + logic [FIFO_DW-1:0] DATA_IN; + logic [FIFO_DW-1:0] DATA_OUT; + + assign DATA_IN = { data_add_i, data_wen_i, data_atop_i, data_wdata_i, data_be_i }; + assign { data_add_o, data_wen_o, data_atop_o, data_wdata_o, data_be_o } = DATA_OUT; + + generic_fifo #( + .DATA_WIDTH ( FIFO_DW ), + .DATA_DEPTH ( 2 ) + ) FIFO_REQ ( + .clk ( clk_i ), + .rst_n ( rst_ni ), + .test_mode_i ( test_en_i ), + .data_i ( DATA_IN ), + .valid_i ( data_req_i ), + .grant_o ( data_gnt_o ), + .data_o ( DATA_OUT ), + .valid_o ( data_req_o ), + .grant_i ( data_gnt_i ) + ); + + assign data_r_valid_o = data_r_valid_i; + assign data_r_opc_o = data_r_opc_i; + assign data_r_rdata_o = data_r_rdata_i; + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/periph_demux.sv b/hw/deps/pulp_cluster/rtl/periph_demux.sv new file mode 100644 index 0000000..1c3a293 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/periph_demux.sv @@ -0,0 +1,267 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * periph_demux.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + */ + +module periph_demux +#( + parameter int ADDR_WIDTH = 32, + parameter int DATA_WIDTH = 32, + parameter int BE_WIDTH = DATA_WIDTH/8, + parameter bit DEM_PER_BEFORE_TCDM_TS = 1'b0 +) +( + input logic clk, + input logic rst_ni, + + // CORE SIDE + input logic data_req_i, + input logic [ADDR_WIDTH - 1:0] data_add_i, + input logic data_wen_i, + input logic [DATA_WIDTH - 1:0] data_wdata_i, + input logic [BE_WIDTH - 1:0] data_be_i, + output logic data_gnt_o, + + output logic data_r_valid_o, // Data Response Valid (For LOAD/STORE commands) + output logic [DATA_WIDTH - 1:0] data_r_rdata_o, // Data Response DATA (For LOAD commands) + output logic data_r_opc_o, // Data Response Error + + // Low Latency log interconnect SIDE + output logic data_req_o_MH, + output logic [ADDR_WIDTH - 1:0] data_add_o_MH, + output logic data_wen_o_MH, + output logic [DATA_WIDTH - 1:0] data_wdata_o_MH, + output logic [BE_WIDTH - 1:0] data_be_o_MH, + input logic data_gnt_i_MH, + input logic data_r_valid_i_MH, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_MH, + input logic data_r_opc_i_MH, + + //low latency event unit access, sleep_req,clear buffer_req + output logic data_req_o_EU, + output logic [ADDR_WIDTH - 1:0] data_add_o_EU, + output logic data_wen_o_EU, + output logic [DATA_WIDTH - 1:0] data_wdata_o_EU, + output logic [BE_WIDTH - 1:0] data_be_o_EU, + input logic data_gnt_i_EU, + input logic data_r_valid_i_EU, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_EU, + input logic data_r_opc_i_EU, + + // my FIFO + output logic data_req_o_MYF, + output logic [ADDR_WIDTH - 1:0] data_add_o_MYF, + output logic data_wen_o_MYF, + output logic [DATA_WIDTH - 1:0] data_wdata_o_MYF, + output logic [BE_WIDTH - 1:0] data_be_o_MYF, + input logic data_gnt_i_MYF, + input logic data_r_valid_i_MYF, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_MYF, + input logic data_r_opc_i_MYF, + + // neighbor FIFO + output logic data_req_o_NBF, + output logic [ADDR_WIDTH - 1:0] data_add_o_NBF, + output logic data_wen_o_NBF, + output logic [DATA_WIDTH - 1:0] data_wdata_o_NBF, + output logic [BE_WIDTH - 1:0] data_be_o_NBF, + input logic data_gnt_i_NBF, + input logic data_r_valid_i_NBF, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_NBF, + input logic data_r_opc_i_NBF, + + // HPU driver + output logic data_req_o_HDRV, + output logic [ADDR_WIDTH - 1:0] data_add_o_HDRV, + output logic data_wen_o_HDRV, + output logic [DATA_WIDTH - 1:0] data_wdata_o_HDRV, + output logic [BE_WIDTH - 1:0] data_be_o_HDRV, + input logic data_gnt_i_HDRV, + input logic data_r_valid_i_HDRV, + input logic [DATA_WIDTH - 1:0] data_r_rdata_i_HDRV, + input logic data_r_opc_i_HDRV +); + + enum logic [2:0] {MH, EU, MYF, NBF, HDRV, UNMAPPED } request_destination; + + always_ff @(posedge clk, negedge rst_ni) begin : _UPDATE_RESPONSE_DESTINATION_ + if(rst_ni == 1'b0) begin + request_destination <= MH; + end + else begin + if (data_req_i) begin + if (DEM_PER_BEFORE_TCDM_TS) begin + case(data_add_i[13:10]) + 4'b1111 : begin : _DPBTT_EVENT_UNIT_REGS + request_destination <= EU; + end + 4'b1110 : begin : _DPBTT_MCHAN_REGISTERS_ + request_destination <= MH; + end + default: begin : _DPBTT_UNMAPPED_REGION_ + request_destination <= UNMAPPED; + end + endcase // data_add_i[13:10] + end else begin + if( (data_add_i[19:14] == 6'b000001 ) ) begin // this means 0x1020_4000 to 1020_7FFF + case(data_add_i[13:10]) + 0 : begin : _EVENT_UNIT_REGS + request_destination <= EU; + end + 1 : begin : _MCHAN_REGISTERS_ + request_destination <= MH; + end + 2 : begin + request_destination <= MYF; + end + 3 : begin + request_destination <= NBF; + end + 4 : begin + request_destination <= HDRV; + end + default : begin : _UNMAPPED_REGION_ + request_destination <= UNMAPPED; + end + endcase // data_add_i[10:13] + end + end + end + end + end + + assign data_add_o_MH = data_add_i; + assign data_wen_o_MH = data_wen_i; + assign data_wdata_o_MH = data_wdata_i; + assign data_be_o_MH = data_be_i; + + assign data_add_o_EU = data_add_i; + assign data_wen_o_EU = data_wen_i; + assign data_wdata_o_EU = data_wdata_i; + assign data_be_o_EU = data_be_i; + + assign data_add_o_MYF = data_add_i; + assign data_wen_o_MYF = data_wen_i; + assign data_wdata_o_MYF = data_wdata_i; + assign data_be_o_MYF = data_be_i; + + assign data_add_o_NBF = data_add_i; + assign data_wen_o_NBF = data_wen_i; + assign data_wdata_o_NBF = data_wdata_i; + assign data_be_o_NBF = data_be_i; + + assign data_add_o_HDRV = data_add_i; + assign data_wen_o_HDRV = data_wen_i; + assign data_wdata_o_HDRV = data_wdata_i; + assign data_be_o_HDRV = data_be_i; + + always_comb + begin : _HANDLE_REQ_ + data_req_o_MH = 1'b0; + data_req_o_EU = 1'b0; + data_req_o_MYF = 1'b0; + data_req_o_NBF = 1'b0; + data_req_o_HDRV = 1'b0; + data_gnt_o = 1'b0; + if (DEM_PER_BEFORE_TCDM_TS) begin + case(data_add_i[13:10]) + 4'b1111 : begin + data_req_o_EU = data_req_i; + data_gnt_o = data_gnt_i_EU; + end + 4'b1110 : begin + data_req_o_MH = data_req_i; + data_gnt_o = data_gnt_i_MH; + end + default : begin : _TO_UNMAPPED_REGION_ + data_req_o_MH = 1'b0; + data_req_o_EU = 1'b0; + data_gnt_o = 1'b0; + end + endcase // data_add_i[13:10] + end else begin + if( (data_add_i[19:14] == 6'b000001 ) ) begin // this means 0x1020_4000 to 1020_7FFF + case(data_add_i[13:10]) + 0 : begin + data_req_o_EU = data_req_i; + data_gnt_o = data_gnt_i_EU; + end + 1 : begin + data_req_o_MH = data_req_i; + data_gnt_o = data_gnt_i_MH; + end + 2 : begin + data_req_o_MYF = data_req_i; + data_gnt_o = data_gnt_i_MYF; + end + 3 : begin + data_req_o_NBF = data_req_i; + data_gnt_o = data_gnt_i_NBF; + end + 4 : begin + data_req_o_HDRV = data_req_i; + data_gnt_o = data_gnt_i_HDRV; + end + default : begin + data_req_o_MH = 1'b0; + data_req_o_EU = 1'b0; + data_req_o_MYF = 1'b0; + data_req_o_NBF = 1'b0; + data_req_o_HDRV = 1'b0; + data_gnt_o = 1'b0; + end + endcase // data_add_i[10:13] + end + end + end + + always_comb + begin : _HANDLE_RESP_ + case(request_destination) + MH : begin : _RESP_FROM_MCHAN_ + data_r_valid_o = data_r_valid_i_MH; + data_r_rdata_o = data_r_rdata_i_MH; + data_r_opc_o = 1'b0; + end + EU : begin : _RESP_FROM_EVENT_UNIT_ + data_r_valid_o = data_r_valid_i_EU; + data_r_rdata_o = data_r_rdata_i_EU; + data_r_opc_o = 1'b0; + end + MYF: begin + data_r_valid_o = data_r_valid_i_MYF; + data_r_rdata_o = data_r_rdata_i_MYF; + data_r_opc_o = 1'b0; + end + NBF: begin + data_r_valid_o = data_r_valid_i_NBF; + data_r_rdata_o = data_r_rdata_i_NBF; + data_r_opc_o = 1'b0; + end + HDRV: begin + data_r_valid_o = data_r_valid_i_HDRV; + data_r_rdata_o = data_r_rdata_i_HDRV; + data_r_opc_o = 1'b0; + end + default : begin : _UNMAPPED_RESP_ + data_r_valid_o = 1'b0; + data_r_rdata_o = '0; + data_r_opc_o = 1'b0; + end + endcase + end + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/pulp_cluster.sv b/hw/deps/pulp_cluster/rtl/pulp_cluster.sv new file mode 100644 index 0000000..cf2a312 --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/pulp_cluster.sv @@ -0,0 +1,1844 @@ +// Copyright 2018 ETH Zurich and 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. + +/* + * pulp_cluster.sv + * Davide Rossi + * Antonio Pullini + * Igor Loi + * Francesco Conti + * Thomas Benz + */ + +import pulp_cluster_package::*; +import apu_package::*; + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module pulp_cluster +#( + // cluster parameters + parameter bit ASYNC_INTF = 1'b1, + parameter int NB_CORES = 8, + parameter int NB_HWACC_PORTS = 0, + parameter int NB_DMAS = 4, + parameter int NB_EXT2MEM = 2, + parameter int NB_MPERIPHS = 1, + parameter int NB_SPERIPHS = 8, + parameter bit CLUSTER_ALIAS = 1'b1, + parameter int CLUSTER_ALIAS_BASE = 12'h1B0, + parameter int TCDM_SIZE = 256*1024, // [B], must be 2**N + parameter int NB_TCDM_BANKS = 16, // must be 2**N + parameter int TCDM_BANK_SIZE = TCDM_SIZE/NB_TCDM_BANKS, // [B] + parameter int TCDM_NUM_ROWS = TCDM_BANK_SIZE/4, // [words] + parameter bit XNE_PRESENT = 0, // set to 1 if XNE is present in the cluster + + // I$ parameters + parameter int SET_ASSOCIATIVE = 4, + parameter int NB_CACHE_BANKS = 4, + parameter int CACHE_LINE = 1, + parameter int CACHE_SIZE = 4096, + parameter int ICACHE_DATA_WIDTH = 128, + parameter int L2_SIZE = 256*1024, + parameter bit USE_REDUCED_TAG = 1'b1, + + // core parameters + parameter bit DEM_PER_BEFORE_TCDM_TS = 1'b0, + parameter int ROM_BOOT_ADDR = 32'h1A000000, + parameter int BOOT_ADDR = 32'h1C000000, + parameter int INSTR_RDATA_WIDTH = 128, + + // AXI parameters + parameter int AXI_ADDR_WIDTH = 32, + parameter int AXI_DATA_C2S_WIDTH = 64, + parameter int AXI_DATA_S2C_WIDTH = 64, + parameter int AXI_USER_WIDTH = 6, + parameter int AXI_ID_IN_WIDTH = 4, + parameter int AXI_ID_OUT_WIDTH = 6, + parameter int AXI_STRB_C2S_WIDTH = AXI_DATA_C2S_WIDTH/8, + parameter int AXI_STRB_S2C_WIDTH = AXI_DATA_S2C_WIDTH/8, + parameter int DC_SLICE_BUFFER_WIDTH = 8, + + // TCDM and log interconnect parameters + parameter int DATA_WIDTH = 32, + parameter int ADDR_WIDTH = 32, + parameter int BE_WIDTH = DATA_WIDTH/8, + parameter int TEST_SET_BIT = 20, // bit used to indicate a test-and-set operation during a load in TCDM + parameter int ADDR_MEM_WIDTH = $clog2(TCDM_BANK_SIZE/4), // WORD address width per TCDM bank (the word width is 32 bits) + + // DMA parameters + parameter int TCDM_ADD_WIDTH = ADDR_MEM_WIDTH + $clog2(NB_TCDM_BANKS) + 2, // BYTE address width TCDM + parameter int NB_OUTSND_BURSTS = 8, + parameter int MCHAN_BURST_LENGTH = 256, + + // peripheral and periph interconnect parameters + parameter int LOG_CLUSTER = 5, // unused + parameter int PE_ROUTING_LSB = 10, // LSB used as routing BIT in periph interco + parameter int PE_ROUTING_MSB = 13, // MSB used as routing BIT in periph interco + parameter int EVNT_WIDTH = 8, // size of the event bus + parameter int REMAP_ADDRESS = 0, // for cluster virtualization + + // WIDE DMA parameters + parameter int DMA_AXI_ID_WIDTH = 4, // + parameter int DMA_AXI_AW_WIDTH = 32, // DON'T CHANGE + parameter int DMA_AXI_DW_WIDTH = 512,// DON'T CHANGE + parameter int DMA_AXI_UW_WIDTH = 4 // +) +( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + input logic pmu_mem_pwdn_i, + + input logic [3:0] base_addr_i, + + input logic test_mode_i, + + input logic en_sa_boot_i, + + input logic [5:0] cluster_id_i, + + input logic fetch_en_i, + + output logic eoc_o, + + output logic busy_o, + + input logic [DC_SLICE_BUFFER_WIDTH-1:0] ext_events_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] ext_events_readpointer_o, + input logic [EVNT_WIDTH-1:0] ext_events_dataasync_i, + + input logic dma_pe_evt_ack_i, + output logic dma_pe_evt_valid_o, + + input logic dma_pe_irq_ack_i, + output logic dma_pe_irq_valid_o, + + input logic pf_evt_ack_i, + output logic pf_evt_valid_o, + + // AXI4 SLAVE + //*************************************** + // WRITE ADDRESS CHANNEL + input logic [AXI_ADDR_WIDTH-1:0] data_slave_aw_addr_i, + input axi_pkg::prot_t data_slave_aw_prot_i, + input axi_pkg::region_t data_slave_aw_region_i, + input axi_pkg::len_t data_slave_aw_len_i, + input axi_pkg::size_t data_slave_aw_size_i, + input axi_pkg::burst_t data_slave_aw_burst_i, + input logic data_slave_aw_lock_i, + input axi_pkg::atop_t data_slave_aw_atop_i, + input axi_pkg::cache_t data_slave_aw_cache_i, + input axi_pkg::qos_t data_slave_aw_qos_i, + input logic [AXI_ID_IN_WIDTH-1:0] data_slave_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_aw_user_i, + // used if ASYNC_INTF + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_aw_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_aw_readpointer_o, + // used if !ASYNC_INTF + input logic data_slave_aw_valid_i, + output logic data_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input logic [AXI_ADDR_WIDTH-1:0] data_slave_ar_addr_i, + input axi_pkg::prot_t data_slave_ar_prot_i, + input axi_pkg::region_t data_slave_ar_region_i, + input axi_pkg::len_t data_slave_ar_len_i, + input axi_pkg::size_t data_slave_ar_size_i, + input axi_pkg::burst_t data_slave_ar_burst_i, + input logic data_slave_ar_lock_i, + input axi_pkg::cache_t data_slave_ar_cache_i, + input axi_pkg::qos_t data_slave_ar_qos_i, + input logic [AXI_ID_IN_WIDTH-1:0] data_slave_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_ar_user_i, + // used if ASYNC_INTF + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_ar_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_ar_readpointer_o, + // used if !ASYNC_INTF + input logic data_slave_ar_valid_i, + output logic data_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input logic [AXI_DATA_S2C_WIDTH-1:0] data_slave_w_data_i, + input logic [AXI_STRB_S2C_WIDTH-1:0] data_slave_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_w_user_i, + input logic data_slave_w_last_i, + // used if ASYNC_INTF + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_w_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_w_readpointer_o, + // used if !ASYNC_INTF + input logic data_slave_w_valid_i, + output logic data_slave_w_ready_o, + + // READ DATA CHANNEL + output logic [AXI_DATA_S2C_WIDTH-1:0] data_slave_r_data_o, + output axi_pkg::resp_t data_slave_r_resp_o, + output logic data_slave_r_last_o, + output logic [AXI_ID_IN_WIDTH-1:0] data_slave_r_id_o, + output logic [AXI_USER_WIDTH-1:0] data_slave_r_user_o, + // used if ASYNC_INTF + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_r_writetoken_o, + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_r_readpointer_i, + // used if !ASYNC_INTF + output logic data_slave_r_valid_o, + input logic data_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output axi_pkg::resp_t data_slave_b_resp_o, + output logic [AXI_ID_IN_WIDTH-1:0] data_slave_b_id_o, + output logic [AXI_USER_WIDTH-1:0] data_slave_b_user_o, + // used if ASYNC_INTF + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_b_writetoken_o, + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_slave_b_readpointer_i, + // used if !ASYNC_INTF + output logic data_slave_b_valid_o, + input logic data_slave_b_ready_i, + + // AXI4 MASTER + //*************************************** + // WRITE ADDRESS CHANNEL + output logic [AXI_ADDR_WIDTH-1:0] data_master_aw_addr_o, + output axi_pkg::prot_t data_master_aw_prot_o, + output axi_pkg::region_t data_master_aw_region_o, + output axi_pkg::len_t data_master_aw_len_o, + output axi_pkg::size_t data_master_aw_size_o, + output axi_pkg::burst_t data_master_aw_burst_o, + output logic data_master_aw_lock_o, + output axi_pkg::atop_t data_master_aw_atop_o, + output axi_pkg::cache_t data_master_aw_cache_o, + output axi_pkg::qos_t data_master_aw_qos_o, + output logic [AXI_ID_OUT_WIDTH-1:0] data_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] data_master_aw_user_o, + // used if ASYNC_INTF + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_aw_writetoken_o, + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_aw_readpointer_i, + // used if !ASYNC_INTF + output logic data_master_aw_valid_o, + input logic data_master_aw_ready_i, + + // READ ADDRESS CHANNEL + output logic [AXI_ADDR_WIDTH-1:0] data_master_ar_addr_o, + output axi_pkg::prot_t data_master_ar_prot_o, + output axi_pkg::region_t data_master_ar_region_o, + output axi_pkg::len_t data_master_ar_len_o, + output axi_pkg::size_t data_master_ar_size_o, + output axi_pkg::burst_t data_master_ar_burst_o, + output logic data_master_ar_lock_o, + output axi_pkg::cache_t data_master_ar_cache_o, + output axi_pkg::qos_t data_master_ar_qos_o, + output logic [AXI_ID_OUT_WIDTH-1:0] data_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] data_master_ar_user_o, + // used if ASYNC_INTF + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_ar_writetoken_o, + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_ar_readpointer_i, + // used if !ASYNC_INTF + output logic data_master_ar_valid_o, + input logic data_master_ar_ready_i, + + // WRITE DATA CHANNEL + output logic [AXI_DATA_C2S_WIDTH-1:0] data_master_w_data_o, + output logic [AXI_STRB_C2S_WIDTH-1:0] data_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] data_master_w_user_o, + output logic data_master_w_last_o, + // used if ASYNC_INTF + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_w_writetoken_o, + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_w_readpointer_i, + // used if !ASYNC_INTF + output logic data_master_w_valid_o, + input logic data_master_w_ready_i, + + // READ DATA CHANNEL + input logic [AXI_DATA_C2S_WIDTH-1:0] data_master_r_data_i, + input axi_pkg::resp_t data_master_r_resp_i, + input logic data_master_r_last_i, + input logic [AXI_ID_OUT_WIDTH-1:0] data_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] data_master_r_user_i, + // used if ASYNC_INTF + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_r_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_r_readpointer_o, + // used if !ASYNC_INTF + input logic data_master_r_valid_i, + output logic data_master_r_ready_o, + + // WRITE RESPONSE CHANNEL + input axi_pkg::resp_t data_master_b_resp_i, + input logic [AXI_ID_OUT_WIDTH-1:0] data_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] data_master_b_user_i, + // used if ASYNC_INTF + input logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_b_writetoken_i, + output logic [DC_SLICE_BUFFER_WIDTH-1:0] data_master_b_readpointer_o, + // used if !ASYNC_INTF + input logic data_master_b_valid_i, + output logic data_master_b_ready_o, + + // AXI4 DMA MASTER + //*************************************** + // WRITE ADDRESS CHANNEL + output logic [DMA_AXI_AW_WIDTH-1:0] dma_aw_addr_o, + output axi_pkg::prot_t dma_aw_prot_o, + output axi_pkg::region_t dma_aw_region_o, + output axi_pkg::len_t dma_aw_len_o, + output axi_pkg::size_t dma_aw_size_o, + output axi_pkg::burst_t dma_aw_burst_o, + output logic dma_aw_lock_o, + output axi_pkg::atop_t dma_aw_atop_o, + output axi_pkg::cache_t dma_aw_cache_o, + output axi_pkg::qos_t dma_aw_qos_o, + output logic [DMA_AXI_ID_WIDTH-1:0] dma_aw_id_o, + output logic [DMA_AXI_UW_WIDTH-1:0] dma_aw_user_o, + output logic dma_aw_valid_o, + input logic dma_aw_ready_i, + + // READ ADDRESS CHANNEL + output logic [DMA_AXI_AW_WIDTH-1:0] dma_ar_addr_o, + output axi_pkg::prot_t dma_ar_prot_o, + output axi_pkg::region_t dma_ar_region_o, + output axi_pkg::len_t dma_ar_len_o, + output axi_pkg::size_t dma_ar_size_o, + output axi_pkg::burst_t dma_ar_burst_o, + output logic dma_ar_lock_o, + output axi_pkg::cache_t dma_ar_cache_o, + output axi_pkg::qos_t dma_ar_qos_o, + output logic [DMA_AXI_ID_WIDTH-1:0] dma_ar_id_o, + output logic [DMA_AXI_UW_WIDTH-1:0] dma_ar_user_o, + output logic dma_ar_valid_o, + input logic dma_ar_ready_i, + + // WRITE DATA CHANNEL + output logic [DMA_AXI_DW_WIDTH-1:0] dma_w_data_o, + output logic [DMA_AXI_DW_WIDTH/8-1:0] dma_w_strb_o, + output logic [DMA_AXI_UW_WIDTH-1:0] dma_w_user_o, + output logic dma_w_last_o, + output logic dma_w_valid_o, + input logic dma_w_ready_i, + + // READ DATA CHANNEL + input logic [DMA_AXI_DW_WIDTH-1:0] dma_r_data_i, + input axi_pkg::resp_t dma_r_resp_i, + input logic dma_r_last_i, + input logic [DMA_AXI_ID_WIDTH-1:0] dma_r_id_i, + input logic [DMA_AXI_UW_WIDTH-1:0] dma_r_user_i, + input logic dma_r_valid_i, + output logic dma_r_ready_o, + + // WRITE RESPONSE CHANNEL + input axi_pkg::resp_t dma_b_resp_i, + input logic [DMA_AXI_ID_WIDTH-1:0] dma_b_id_i, + input logic [DMA_AXI_UW_WIDTH-1:0] dma_b_user_i, + input logic dma_b_valid_i, + output logic dma_b_ready_o, + + // AXI4 NIC-HOST-Interconnect (NHI) SLAVE + //*************************************** + // WRITE ADDRESS CHANNEL + input logic [DMA_AXI_AW_WIDTH-1:0] nhi_aw_addr_i, + input axi_pkg::prot_t nhi_aw_prot_i, + input axi_pkg::region_t nhi_aw_region_i, + input axi_pkg::len_t nhi_aw_len_i, + input axi_pkg::size_t nhi_aw_size_i, + input axi_pkg::burst_t nhi_aw_burst_i, + input logic nhi_aw_lock_i, + input axi_pkg::atop_t nhi_aw_atop_i, + input axi_pkg::cache_t nhi_aw_cache_i, + input axi_pkg::qos_t nhi_aw_qos_i, + input logic [DMA_AXI_ID_WIDTH-1:0] nhi_aw_id_i, + input logic [DMA_AXI_UW_WIDTH-1:0] nhi_aw_user_i, + input logic nhi_aw_valid_i, + output logic nhi_aw_ready_o, + + // READ ADDRESS CHANNEL + input logic [DMA_AXI_AW_WIDTH-1:0] nhi_ar_addr_i, + input axi_pkg::prot_t nhi_ar_prot_i, + input axi_pkg::region_t nhi_ar_region_i, + input axi_pkg::len_t nhi_ar_len_i, + input axi_pkg::size_t nhi_ar_size_i, + input axi_pkg::burst_t nhi_ar_burst_i, + input logic nhi_ar_lock_i, + input axi_pkg::cache_t nhi_ar_cache_i, + input axi_pkg::qos_t nhi_ar_qos_i, + input logic [DMA_AXI_ID_WIDTH-1:0] nhi_ar_id_i, + input logic [DMA_AXI_UW_WIDTH-1:0] nhi_ar_user_i, + input logic nhi_ar_valid_i, + output logic nhi_ar_ready_o, + + // WRITE DATA CHANNEL + input logic [DMA_AXI_DW_WIDTH-1:0] nhi_w_data_i, + input logic [DMA_AXI_DW_WIDTH/8-1:0] nhi_w_strb_i, + input logic [DMA_AXI_UW_WIDTH-1:0] nhi_w_user_i, + input logic nhi_w_last_i, + input logic nhi_w_valid_i, + output logic nhi_w_ready_o, + + // READ DATA CHANNEL + output logic [DMA_AXI_DW_WIDTH-1:0] nhi_r_data_o, + output axi_pkg::resp_t nhi_r_resp_o, + output logic nhi_r_last_o, + output logic [DMA_AXI_ID_WIDTH-1:0] nhi_r_id_o, + output logic [DMA_AXI_UW_WIDTH-1:0] nhi_r_user_o, + output logic nhi_r_valid_o, + input logic nhi_r_ready_i, + + // WRITE RESPONSE CHANNEL + output axi_pkg::resp_t nhi_b_resp_o, + output logic [DMA_AXI_ID_WIDTH-1:0] nhi_b_id_o, + output logic [DMA_AXI_UW_WIDTH-1:0] nhi_b_user_o, + output logic nhi_b_valid_o, + input logic nhi_b_ready_i, + + // Instruction Cache Master Port + output pulp_cluster_cfg_pkg::addr_t icache_aw_addr_o, + output axi_pkg::prot_t icache_aw_prot_o, + output axi_pkg::region_t icache_aw_region_o, + output axi_pkg::len_t icache_aw_len_o, + output axi_pkg::size_t icache_aw_size_o, + output axi_pkg::burst_t icache_aw_burst_o, + output logic icache_aw_lock_o, + output axi_pkg::atop_t icache_aw_atop_o, + output axi_pkg::cache_t icache_aw_cache_o, + output axi_pkg::qos_t icache_aw_qos_o, + output pulp_cluster_cfg_pkg::id_icache_t icache_aw_id_o, + output pulp_cluster_cfg_pkg::user_t icache_aw_user_o, + output logic icache_aw_valid_o, + input logic icache_aw_ready_i, + + output pulp_cluster_cfg_pkg::addr_t icache_ar_addr_o, + output axi_pkg::prot_t icache_ar_prot_o, + output axi_pkg::region_t icache_ar_region_o, + output axi_pkg::len_t icache_ar_len_o, + output axi_pkg::size_t icache_ar_size_o, + output axi_pkg::burst_t icache_ar_burst_o, + output logic icache_ar_lock_o, + output axi_pkg::cache_t icache_ar_cache_o, + output axi_pkg::qos_t icache_ar_qos_o, + output pulp_cluster_cfg_pkg::id_icache_t icache_ar_id_o, + output pulp_cluster_cfg_pkg::user_t icache_ar_user_o, + output logic icache_ar_valid_o, + input logic icache_ar_ready_i, + + output pulp_cluster_cfg_pkg::data_icache_t icache_w_data_o, + output pulp_cluster_cfg_pkg::strb_icache_t icache_w_strb_o, + output pulp_cluster_cfg_pkg::user_t icache_w_user_o, + output logic icache_w_last_o, + output logic icache_w_valid_o, + input logic icache_w_ready_i, + + input pulp_cluster_cfg_pkg::data_icache_t icache_r_data_i, + input axi_pkg::resp_t icache_r_resp_i, + input logic icache_r_last_i, + input pulp_cluster_cfg_pkg::id_icache_t icache_r_id_i, + input pulp_cluster_cfg_pkg::user_t icache_r_user_i, + input logic icache_r_valid_i, + output logic icache_r_ready_o, + + input axi_pkg::resp_t icache_b_resp_i, + input pulp_cluster_cfg_pkg::id_icache_t icache_b_id_i, + input pulp_cluster_cfg_pkg::user_t icache_b_user_i, + input logic icache_b_valid_i, + output logic icache_b_ready_o, + + //task from scheduler + input logic task_valid_i, + output logic task_ready_o, + input pspin_cfg_pkg::handler_task_t task_descr_i, + + //feedback to scheduler + output logic feedback_valid_o, + input logic feedback_ready_i, + output pspin_cfg_pkg::feedback_descr_t feedback_o, + + //signal if the cluster is ready to accept tasks + output logic cluster_active_o, + + //commands out + input logic cmd_ready_i, + output logic cmd_valid_o, + output pspin_cfg_pkg::pspin_cmd_t cmd_o, + + //command response + input logic cmd_resp_valid_i, + input pspin_cfg_pkg::pspin_cmd_resp_t cmd_resp_i +); + + logic [NB_CORES-1:0] fetch_enable_reg_int; + logic [NB_CORES-1:0] fetch_en_int; + logic s_rst_n; + logic s_init_n; + logic [NB_CORES-1:0][31:0] boot_addr; + logic [NB_CORES-1:0] dbg_core_halt; + logic [NB_CORES-1:0] dbg_core_resume; + logic [NB_CORES-1:0] dbg_core_halted; + logic hwpe_sel; + logic hwpe_en; + + logic [NB_CORES-1:0][AXI_USER_WIDTH-1:0] tryx_axuser; + logic [NB_CORES-1:0] tryx_xresp_decerr; + logic [NB_CORES-1:0] tryx_xresp_slverr; + logic [NB_CORES-1:0] tryx_xresp_valid; + + logic s_cluster_periphs_busy; + logic s_axi_to_mem_busy; + logic s_per2axi_busy; + logic s_axi2per_busy; + logic s_dmac_busy; + logic s_cluster_cg_en; + logic [NB_CORES-1:0] s_dma_event; + logic [NB_CORES-1:0] s_dma_irq; + logic [NB_CORES-1:0][3:0] s_hwacc_events; + logic [NB_CORES-1:0][1:0] s_xne_evt; + logic s_xne_busy; + + logic [NB_CORES-1:0] clk_core_en; + logic clk_cluster; + + // CLK reset, and other control signals + + logic s_cluster_int_busy; + logic s_fregfile_disable; + + logic [NB_CORES-1:0] core_busy; + + logic s_incoming_req; + logic s_isolate_cluster; + logic s_events_async; + + logic s_events_valid; + logic s_events_ready; + logic [EVNT_WIDTH-1:0] s_events_data; + + // Signals Between CORE_ISLAND and INSTRUCTION CACHES + logic [NB_CORES-1:0] instr_req; + logic [NB_CORES-1:0][31:0] instr_addr; + logic [NB_CORES-1:0] instr_gnt; + logic [NB_CORES-1:0] instr_r_valid; + logic [NB_CORES-1:0][INSTR_RDATA_WIDTH-1:0] instr_r_rdata; + + logic [1:0] s_TCDM_arb_policy; + logic tcdm_sleep; + + logic s_dma_pe_event; + logic s_dma_pe_irq; + logic s_pf_event; + + logic[NB_CORES-1:0][4:0] irq_id; + logic[NB_CORES-1:0][4:0] irq_ack_id; + logic[NB_CORES-1:0] irq_req; + logic[NB_CORES-1:0] irq_ack; + + + /* asynchronous AXI interfaces at CLUSTER/SOC interface, driven iff `ASYNC_INTF` */ + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_S2C_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_WIDTH ( DC_SLICE_BUFFER_WIDTH ) + ) s_data_slave_async(); + + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .BUFFER_WIDTH ( DC_SLICE_BUFFER_WIDTH ) + ) s_data_master_async(); + + /* synchronously cut (no combinatorial paths) AXI interfaces, driven iff `!ASYNC_INTF` */ + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_S2C_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_data_slave_cut(); + + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_data_master_cut(); + + /* synchronous AXI interfaces at CLUSTER/SOC interface */ + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_S2C_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_data_slave(); + + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_data_master(); + + /* synchronous AXI interfaces internal to the cluster */ + // core per2axi -> ext + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_core_ext_bus(); + + // DMA -> ext + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_dma_ext_bus(); + + // WIDE DMA -> SoC + AXI_BUS #( + .AXI_ADDR_WIDTH ( DMA_AXI_AW_WIDTH ), + .AXI_DATA_WIDTH ( DMA_AXI_DW_WIDTH ), + .AXI_ID_WIDTH ( DMA_AXI_ID_WIDTH ), + .AXI_USER_WIDTH ( DMA_AXI_UW_WIDTH ) + ) s_wide_dma_soc(); + + // WIDE NHI -> TCDM (supprbanks) + AXI_BUS #( + .AXI_ADDR_WIDTH ( DMA_AXI_AW_WIDTH ), + .AXI_DATA_WIDTH ( DMA_AXI_DW_WIDTH ), + .AXI_ID_WIDTH ( DMA_AXI_ID_WIDTH ), + .AXI_USER_WIDTH ( DMA_AXI_UW_WIDTH ) + ) s_wide_nhi_superbanks(); + + // ext -> axi_to_mem + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_ext_tcdm_bus(); + + // cluster bus -> axi2per + AXI_BUS #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) s_ext_mperiph_bus(); + + /* logarithmic and peripheral interconnect interfaces */ + // wide dma -> superbanks a + WIDE_DMA_TCDM_BUS #( + .ADDR_WIDTH ( DMA_AXI_AW_WIDTH ), + .DATA_WIDTH ( DMA_AXI_DW_WIDTH ) + ) s_wide_dma_a_superbanks(); + + // NHI interconnect -> superbanks b + WIDE_DMA_TCDM_BUS #( + .ADDR_WIDTH ( DMA_AXI_AW_WIDTH ), + .DATA_WIDTH ( DMA_AXI_DW_WIDTH ) + ) s_wide_dma_b_superbanks(); + + + // ext -> log interconnect + XBAR_TCDM_BUS s_ext_xbar_bus[NB_EXT2MEM-1:0](); + + // periph interconnect -> slave peripherals + XBAR_PERIPH_BUS s_xbar_speriph_bus[NB_SPERIPHS-1:0](); + logic [NB_SPERIPHS-1:0][5:0] s_xbar_speriph_atop; + + // periph interconnect -> XNE + XBAR_PERIPH_BUS s_xne_cfg_bus(); + + // DMA -> log interconnect + XBAR_TCDM_BUS s_dma_xbar_bus[NB_DMAS-1:0](); + + // ext -> xbar periphs FIXME + XBAR_TCDM_BUS s_mperiph_xbar_bus[NB_MPERIPHS-1:0](); + + // periph demux + XBAR_TCDM_BUS s_mperiph_bus(); + XBAR_TCDM_BUS s_mperiph_demux_bus[1:0](); + + // cores & accelerators -> log interconnect + XBAR_TCDM_BUS s_core_xbar_bus[NB_CORES+NB_HWACC_PORTS-1:0](); + + // cores -> periph interconnect + XBAR_PERIPH_BUS s_core_periph_bus[NB_CORES-1:0](); + XBAR_PERIPH_BUS s_inter_core_fifo[NB_CORES-1:0](); + XBAR_PERIPH_BUS s_hpu_driver_bus[NB_CORES-1:0](); + logic [NB_CORES-1:0][5:0] s_core_periph_bus_atop, s_core_xbar_bus_atop; + + // cores -> tryx control + XBAR_PERIPH_BUS s_core_periph_tryx[NB_CORES-1:0](); + + // periph interconnect -> DMA + XBAR_PERIPH_BUS s_periph_dma_bus(); + + // debug + XBAR_TCDM_BUS s_debug_bus[NB_CORES-1:0](); + + /* other interfaces */ + // cores -> DMA ctrl + XBAR_TCDM_BUS s_core_dmactrl_bus[NB_CORES-1:0](); + + // cores -> event unit ctrl + XBAR_PERIPH_BUS s_core_euctrl_bus[NB_CORES-1:0](); + + // I$ ctrl unit <-> I$, L0, I$ interconnect + MP_PF_ICACHE_CTRL_UNIT_BUS IC_ctrl_unit_bus(); + + // log interconnect -> TCDM memory banks (SRAM) + TCDM_BANK_MEM_BUS s_tcdm_bus_sram[NB_TCDM_BANKS-1:0](); + + // cluster_scheduler -> dma_wrap + logic ext_dma_req_valid; + logic ext_dma_req_ready; + pspin_cfg_pkg::transf_descr_32_t ext_dma_req; + + // dma_wrap -> cluster_scheduler + logic ext_dma_rsp_valid; + + // cluster_schedulers -> hpu_drivers + logic [NB_CORES-1:0] hpu_task_valid; + logic [NB_CORES-1:0] hpu_task_ready; + pspin_cfg_pkg::hpu_handler_task_t hpu_task; + + // hpu_drivers -> cluster_schedulers + logic [NB_CORES-1:0] hpu_feedback_valid; + logic [NB_CORES-1:0] hpu_feedback_ready; + pspin_cfg_pkg::task_feedback_descr_t [NB_CORES-1:0] hpu_feedback; + + logic [NB_CORES-1:0] hpu_active; + + logic [NB_CORES-1:0] core_cmd_ready; + logic [NB_CORES-1:0] core_cmd_valid; + pspin_cfg_pkg::pspin_cmd_t [NB_CORES-1:0] core_cmd; + + // cores -> APU + cpu_marx_if #( + .WOP_CPU ( WOP_CPU ), + .WAPUTYPE ( WAPUTYPE ), + .NUSFLAGS_CPU ( NUSFLAGS_CPU ), + .NDSFLAGS_CPU ( NDSFLAGS_CPU ), + .NARGS_CPU ( NARGS_CPU ) + ) apu_cluster_bus [NB_CORES-1:0] (); + + /* reset generator */ + rstgen rstgen_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_mode_i( test_mode_i ), + .rst_no ( s_rst_n ), + .init_no ( s_init_n ) + ); + + /* fetch & busy genertion */ + assign s_cluster_int_busy = s_cluster_periphs_busy | s_per2axi_busy | s_axi2per_busy | s_axi_to_mem_busy | s_dmac_busy | s_xne_busy; + assign busy_o = s_cluster_int_busy | (|core_busy); + assign fetch_en_int = fetch_enable_reg_int; + + /* cluster bus and attached peripherals */ + cluster_bus_wrap #( + .NB_CORES ( NB_CORES ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_IN_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_ID_OUT_WIDTH ( AXI_ID_OUT_WIDTH ) + ) cluster_bus_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .test_en_i ( test_mode_i ), + .cluster_id_i ( cluster_id_i ), + .data_slave ( s_core_ext_bus ), + .dma_slave ( s_dma_ext_bus ), + .ext_slave ( s_data_slave ), + .tcdm_master ( s_ext_tcdm_bus ), + .periph_master ( s_ext_mperiph_bus ), + .ext_master ( s_data_master ) + ); + + logic [NB_EXT2MEM-1:0] s_ext_xbar_bus_req, s_ext_xbar_bus_gnt, + s_ext_xbar_bus_wen, + s_ext_xbar_bus_rvalid; + logic [NB_EXT2MEM-1:0][31:0] s_ext_xbar_bus_addr, + s_ext_xbar_bus_rdata, + s_ext_xbar_bus_wdata; + logic [NB_EXT2MEM-1:0][ 3:0] s_ext_xbar_bus_be; + logic [NB_EXT2MEM-1:0][ 5:0] s_ext_xbar_bus_atop; + + // Fall-through register on AW due to protocol violation by upstream (dependency on aw_ready for + // w_valid). + typedef logic [31:0] addr_t; + typedef logic [AXI_DATA_C2S_WIDTH-1:0] data_t; + typedef logic [AXI_ID_OUT_WIDTH-1:0] id_oup_t; + typedef logic [AXI_DATA_C2S_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_oup_t, user_t); + `AXI_TYPEDEF_W_CHAN_T (w_chan_t, data_t, strb_t, user_t); + `AXI_TYPEDEF_B_CHAN_T (b_chan_t, id_oup_t, user_t); + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_oup_t, user_t); + `AXI_TYPEDEF_R_CHAN_T (r_chan_t, data_t, id_oup_t, user_t); + `AXI_TYPEDEF_REQ_T (axi_req_t, aw_chan_t, w_chan_t, ar_chan_t); + `AXI_TYPEDEF_RESP_T (axi_resp_t, b_chan_t, r_chan_t); + axi_req_t ext_tcdm_req, ext_tcdm_req_buf; + axi_resp_t ext_tcdm_resp, ext_tcdm_resp_buf; + `AXI_ASSIGN_TO_REQ(ext_tcdm_req, s_ext_tcdm_bus); + `AXI_ASSIGN_FROM_RESP(s_ext_tcdm_bus, ext_tcdm_resp); + always_comb begin + ext_tcdm_req_buf.w = ext_tcdm_req.w; + ext_tcdm_req_buf.w_valid = ext_tcdm_req.w_valid; + ext_tcdm_resp.w_ready = ext_tcdm_resp_buf.w_ready; + ext_tcdm_req_buf.ar = ext_tcdm_req.ar; + ext_tcdm_req_buf.ar_valid = ext_tcdm_req.ar_valid; + ext_tcdm_resp.ar_ready = ext_tcdm_resp_buf.ar_ready; + ext_tcdm_resp.b = ext_tcdm_resp_buf.b; + ext_tcdm_resp.b_valid = ext_tcdm_resp_buf.b_valid; + ext_tcdm_req_buf.b_ready = ext_tcdm_req.b_ready; + ext_tcdm_resp.r = ext_tcdm_resp_buf.r; + ext_tcdm_resp.r_valid = ext_tcdm_resp_buf.r_valid; + ext_tcdm_req_buf.r_ready = ext_tcdm_req.r_ready; + end + fall_through_register #( + .T (aw_chan_t) + ) i_axi_to_mem_aw_ft_reg ( + .clk_i (clk_cluster), + .rst_ni, + .clr_i (1'b0), + .testmode_i (1'b0), + .valid_i (ext_tcdm_req.aw_valid), + .ready_o (ext_tcdm_resp.aw_ready), + .data_i (ext_tcdm_req.aw), + .valid_o (ext_tcdm_req_buf.aw_valid), + .ready_i (ext_tcdm_resp_buf.aw_ready), + .data_o (ext_tcdm_req_buf.aw) + ); + + axi_to_mem #( + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_resp_t ), + .AddrWidth ( 32 ), + .DataWidth ( AXI_DATA_C2S_WIDTH ), + .IdWidth ( AXI_ID_OUT_WIDTH ), + .NumBanks ( NB_EXT2MEM ) + ) i_axi_to_mem ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .busy_o ( s_axi_to_mem_busy ), + .axi_req_i ( ext_tcdm_req_buf ), + .axi_resp_o ( ext_tcdm_resp_buf ), + .mem_req_o ( s_ext_xbar_bus_req ), + .mem_gnt_i ( s_ext_xbar_bus_gnt ), + .mem_addr_o ( s_ext_xbar_bus_addr ), + .mem_wdata_o ( s_ext_xbar_bus_wdata ), + .mem_strb_o ( s_ext_xbar_bus_be ), + .mem_atop_o ( s_ext_xbar_bus_atop ), + .mem_we_o ( s_ext_xbar_bus_wen ), + .mem_rvalid_i ( s_ext_xbar_bus_rvalid ), + .mem_rdata_i ( s_ext_xbar_bus_rdata ) + ); + for (genvar i = 0; i < NB_EXT2MEM; i++) begin : gen_ext_xbar_bus + assign s_ext_xbar_bus[i].req = s_ext_xbar_bus_req[i]; + assign s_ext_xbar_bus_gnt[i] = s_ext_xbar_bus[i].gnt; + assign s_ext_xbar_bus[i].add = s_ext_xbar_bus_addr[i]; + assign s_ext_xbar_bus[i].wdata = s_ext_xbar_bus_wdata[i]; + assign s_ext_xbar_bus[i].be = s_ext_xbar_bus_be[i]; + assign s_ext_xbar_bus[i].wen = ~s_ext_xbar_bus_wen[i]; // active low + assign s_ext_xbar_bus_rvalid[i] = s_ext_xbar_bus[i].r_valid; + assign s_ext_xbar_bus_rdata[i] = s_ext_xbar_bus[i].r_rdata; + end + + axi2per_wrap #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_OUT_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) axi2per_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .test_en_i ( test_mode_i ), + .cluster_id_i ( cluster_id_i ), + .axi_slave ( s_ext_mperiph_bus ), + .periph_master ( s_mperiph_bus ), + .busy_o ( s_axi2per_busy ) + ); + + per_demux_wrap #( + .NB_MASTERS ( 2 ), + .ADDR_OFFSET ( 20 ) + ) per_demux_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .slave ( s_mperiph_bus ), + .masters ( s_mperiph_demux_bus ) + ); + + assign s_mperiph_xbar_bus[NB_MPERIPHS-1].req = s_mperiph_demux_bus[0].req; + assign s_mperiph_xbar_bus[NB_MPERIPHS-1].add = s_mperiph_demux_bus[0].add; + assign s_mperiph_xbar_bus[NB_MPERIPHS-1].wen = s_mperiph_demux_bus[0].wen; + assign s_mperiph_xbar_bus[NB_MPERIPHS-1].wdata = s_mperiph_demux_bus[0].wdata; + assign s_mperiph_xbar_bus[NB_MPERIPHS-1].be = s_mperiph_demux_bus[0].be; + + assign s_mperiph_demux_bus[0].gnt = s_mperiph_xbar_bus[NB_MPERIPHS-1].gnt; + assign s_mperiph_demux_bus[0].r_valid = s_mperiph_xbar_bus[NB_MPERIPHS-1].r_valid; + assign s_mperiph_demux_bus[0].r_opc = s_mperiph_xbar_bus[NB_MPERIPHS-1].r_opc; + assign s_mperiph_demux_bus[0].r_rdata = s_mperiph_xbar_bus[NB_MPERIPHS-1].r_rdata; + + per_demux_wrap #( + .NB_MASTERS ( NB_CORES ), + .ADDR_OFFSET ( 15 ) + ) debug_interconect_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .slave ( s_mperiph_demux_bus[1] ), + .masters ( s_debug_bus ) + ); + + per2axi_wrap #( + .NB_CORES ( NB_CORES ), + .PER_ADDR_WIDTH ( 32 ), + .PER_ID_WIDTH ( NB_CORES+NB_MPERIPHS ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ) + ) per2axi_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .test_en_i ( test_mode_i ), + .periph_slave ( s_xbar_speriph_bus[SPER_EXT_ID] ), + .periph_slave_atop_i ( s_xbar_speriph_atop[SPER_EXT_ID] ), + .axi_axuser_i ( tryx_axuser ), + .axi_xresp_decerr_o ( tryx_xresp_decerr ), + .axi_xresp_slverr_o ( tryx_xresp_slverr ), + .axi_xresp_valid_o ( tryx_xresp_valid ), + .axi_master ( s_core_ext_bus ), + .busy_o ( s_per2axi_busy ) + ); + + tryx_ctrl #( + .NB_CORES ( NB_CORES ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ) + ) tryx_ctrl_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .axi_axuser_o ( tryx_axuser ), + .axi_xresp_decerr_i ( tryx_xresp_decerr ), + .axi_xresp_slverr_i ( tryx_xresp_slverr ), + .axi_xresp_valid_i ( tryx_xresp_valid ), + .periph_data_slave ( s_core_periph_bus ), + .periph_data_master ( s_core_periph_tryx ) + ); + + /* cluster (log + periph) interconnect and attached peripherals */ + cluster_interconnect_wrap #( + .NB_CORES ( NB_CORES ), + .NB_HWACC_PORTS ( NB_HWACC_PORTS ), + .NB_DMAS ( NB_DMAS ), + .NB_EXT ( NB_EXT2MEM ), + .NB_MPERIPHS ( NB_MPERIPHS ), + .NB_TCDM_BANKS ( NB_TCDM_BANKS ), + .NB_SPERIPHS ( NB_SPERIPHS ), + .DATA_WIDTH ( DATA_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .BE_WIDTH ( BE_WIDTH ), + .TEST_SET_BIT ( TEST_SET_BIT ), + .ADDR_MEM_WIDTH ( ADDR_MEM_WIDTH ), + .LOG_CLUSTER ( LOG_CLUSTER ), + .PE_ROUTING_LSB ( PE_ROUTING_LSB ), + .PE_ROUTING_MSB ( PE_ROUTING_MSB ), + .CLUSTER_ALIAS ( CLUSTER_ALIAS ), + .CLUSTER_ALIAS_BASE ( CLUSTER_ALIAS_BASE ) + ) cluster_interconnect_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .core_tcdm_slave ( s_core_xbar_bus ), + .core_tcdm_slave_atop ( s_core_xbar_bus_atop ), + .core_periph_slave ( s_core_periph_tryx ), + .core_periph_slave_atop ( s_core_periph_bus_atop ), + .ext_slave ( s_ext_xbar_bus ), + .ext_slave_atop ( s_ext_xbar_bus_atop ), + .dma_slave ( s_dma_xbar_bus ), + .mperiph_slave ( s_mperiph_xbar_bus[NB_MPERIPHS-1:0] ), + .tcdm_sram_master ( s_tcdm_bus_sram ), + .speriph_master ( s_xbar_speriph_bus ), + .speriph_master_atop ( s_xbar_speriph_atop ), + .TCDM_arb_policy_i ( s_TCDM_arb_policy ), + .s_wide_dma_a_superbanks( s_wide_dma_a_superbanks ), + .s_wide_dma_b_superbanks( s_wide_dma_b_superbanks ) + ); + + logic [NB_CORES-1:0] s_no_req_pending; + + dmac_wrap #( + .NB_CORES ( NB_CORES ), + .NB_OUTSND_BURSTS ( NB_OUTSND_BURSTS ), + .MCHAN_BURST_LENGTH ( MCHAN_BURST_LENGTH ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_C2S_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ), + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), + .PE_ID_WIDTH ( NB_CORES + 1 ), + .TCDM_ADD_WIDTH ( TCDM_ADD_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .ADDR_WIDTH ( ADDR_WIDTH ), + .BE_WIDTH ( BE_WIDTH ), + .dma_transf_descr_t ( pspin_cfg_pkg::transf_descr_32_t ), + .DMA_AXI_AW_WIDTH ( DMA_AXI_AW_WIDTH ), + .DMA_AXI_DW_WIDTH ( DMA_AXI_DW_WIDTH ), + .DMA_AXI_ID_WIDTH ( DMA_AXI_ID_WIDTH ), + .DMA_AXI_UW_WIDTH ( DMA_AXI_UW_WIDTH ), + .TF_REQ_FIFO_DEPTH ( pspin_cfg_pkg::BUFFERED_HERS_PER_CLUSTER ) + ) dmac_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .cluster_id_i ( cluster_id_i ), + .test_mode_i ( test_mode_i ), + .ctrl_slave ( s_core_dmactrl_bus ), + .pe_ctrl_slave ( s_periph_dma_bus ), + .tcdm_master ( s_dma_xbar_bus ), + .ext_master ( s_dma_ext_bus ), + .s_wide_dma_soc ( s_wide_dma_soc ), + .s_wide_dma_superbanks ( s_wide_dma_a_superbanks ), + .term_event_o ( s_dma_event ), + .term_irq_o ( s_dma_irq ), + .term_event_pe_o ( s_dma_pe_event ), + .term_irq_pe_o ( s_dma_pe_irq ), + .busy_o ( s_dmac_busy ), + .ext_dma_req_valid_i ( ext_dma_req_valid ), + .ext_dma_req_ready_o ( ext_dma_req_ready ), + .ext_dma_req_i ( ext_dma_req ), + .ext_dma_rsp_valid_o ( ext_dma_rsp_valid ), + .no_req_pending_o ( s_no_req_pending ) + ); + + nhi_port_wrap #( + .DMA_AXI_AW_WIDTH ( DMA_AXI_AW_WIDTH ), + .DMA_AXI_DW_WIDTH ( DMA_AXI_DW_WIDTH ), + .DMA_AXI_ID_WIDTH ( DMA_AXI_ID_WIDTH ), + .DMA_AXI_UW_WIDTH ( DMA_AXI_UW_WIDTH ) + ) nhi_port_wrap_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .s_wide_dma_superbanks ( s_wide_dma_b_superbanks ), + .s_wide_dma_nhi ( s_wide_nhi_superbanks ) + ); + + cluster_peripherals #( + .NB_CORES ( NB_CORES ), + .NB_MPERIPHS ( NB_MPERIPHS ), + .NB_CACHE_BANKS ( NB_CACHE_BANKS ), + .NB_SPERIPHS ( NB_SPERIPHS ), + .NB_TCDM_BANKS ( NB_TCDM_BANKS ), + .NB_HWPE_PORTS ( 1 ), + .ROM_BOOT_ADDR ( ROM_BOOT_ADDR ), + .BOOT_ADDR ( BOOT_ADDR ), + .EVNT_WIDTH ( EVNT_WIDTH ) + ) cluster_peripherals_i ( + .clk_i ( clk_cluster ), + .rst_ni ( rst_ni ), + .ref_clk_i ( ref_clk_i ), + .test_mode_i ( test_mode_i ), + .busy_o ( s_cluster_periphs_busy ), + .dma_events_i ( s_dma_event ), + .dma_irq_i ( s_dma_irq ), + .en_sa_boot_i ( en_sa_boot_i ), + .fetch_en_i ( fetch_en_i ), + .boot_addr_o ( boot_addr ), + .core_busy_i ( core_busy ), + .core_clk_en_o ( clk_core_en ), + .fregfile_disable_o ( s_fregfile_disable ), + .speriph_slave ( s_xbar_speriph_bus[NB_SPERIPHS-2:0]), + .core_eu_direct_link ( s_core_euctrl_bus ), + .dma_cfg_master ( s_periph_dma_bus ), + .dma_pe_irq_i ( s_dma_pe_irq ), + .pf_event_o ( s_pf_event ), + .soc_periph_evt_ready_o ( s_events_ready ), + .soc_periph_evt_valid_i ( s_events_valid ), + .soc_periph_evt_data_i ( s_events_data ), + .dbg_core_halt_o ( dbg_core_halt ), + .dbg_core_halted_i ( dbg_core_halted ), + .dbg_core_resume_o ( dbg_core_resume ), + .eoc_o ( eoc_o ), + .cluster_cg_en_o ( s_cluster_cg_en ), + .fetch_enable_reg_o ( fetch_enable_reg_int ), + .irq_id_o ( irq_id ), + .irq_ack_id_i ( irq_ack_id ), + .irq_req_o ( irq_req ), + .irq_ack_i ( irq_ack ), + .TCDM_arb_policy_o ( s_TCDM_arb_policy ), + .hwce_cfg_master ( s_xne_cfg_bus ), + .hwacc_events_i ( s_hwacc_events ), + .hwpe_sel_o ( hwpe_sel ), + .hwpe_en_o ( hwpe_en ), + .IC_ctrl_unit_bus ( IC_ctrl_unit_bus ) + ); + + + /* Cluster scheduler */ + cluster_scheduler #( + .NUM_HERS_PER_CLUSTER (pspin_cfg_pkg::NUM_HERS_PER_CLUSTER), + .L1_PKT_BUFF_SIZE (pspin_cfg_pkg::L1_PKT_BUFF_SIZE), + .L1_CLUSTER_BASE (pspin_cfg_pkg::L1_CLUSTER_BASE), + .L1_CLUSTER_MEM_SIZE (pspin_cfg_pkg::L1_CLUSTER_MEM_SIZE), + .L1_RUNTIME_OFFSET (pspin_cfg_pkg::L1_RUNTIME_OFFSET) + ) i_cluster_scheduler ( + .rst_ni (rst_ni), + .clk_i (clk_cluster), + + .cluster_id_i (cluster_id_i), + + // from scheduler + .task_valid_i (task_valid_i), + .task_ready_o (task_ready_o), + .task_descr_i (task_descr_i), + + // to scheduler + .feedback_valid_o (feedback_valid_o), + .feedback_ready_i (feedback_ready_i), + .feedback_o (feedback_o), + + // to DMA + .dma_xfer_valid_o (ext_dma_req_valid), + .dma_xfer_ready_i (ext_dma_req_ready), + .dma_xfer_o (ext_dma_req), + + // from DMA + .dma_resp_i (ext_dma_rsp_valid), + + // to HPU drivers + .hpu_task_valid_o (hpu_task_valid), + .hpu_task_ready_i (hpu_task_ready), + .hpu_task_o (hpu_task), + + // from HPU drivers + .hpu_feedback_valid_i (hpu_feedback_valid), + .hpu_feedback_ready_o (hpu_feedback_ready), + .hpu_feedback_i (hpu_feedback), + + .hpu_active_i (hpu_active), + .cluster_active_o (cluster_active_o) + ); + + + /* cluster-local command unit */ + cluster_cmd #( + .NUM_CORES (NB_CORES) + ) i_cluster_cmd ( + .clk_i (clk_cluster), + .rst_ni (rst_ni), + + .cmd_ready_o (core_cmd_ready), + .cmd_valid_i (core_cmd_valid), + .cmd_i (core_cmd), + + .cmd_ready_i (cmd_ready_i), + .cmd_valid_o (cmd_valid_o), + .cmd_o (cmd_o) + ); + + /* cluster cores + core-coupled accelerators / shared execution units */ + localparam int N_PMP_ENTRIES = 16; + generate + for (genvar i=0; i 0) else $fatal(1, "NB_CORES not set!"); + end + // pragma translate_on + `endif + +endmodule diff --git a/hw/deps/pulp_cluster/rtl/virtual_stdout_demux.sv b/hw/deps/pulp_cluster/rtl/virtual_stdout_demux.sv new file mode 100644 index 0000000..ba7329b --- /dev/null +++ b/hw/deps/pulp_cluster/rtl/virtual_stdout_demux.sv @@ -0,0 +1,106 @@ +// Copyright 2019 ETH Zurich and 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. + +module virtual_stdout_demux #( + parameter int unsigned CoreId = 0 +) ( + input logic clk_i, + input logic rst_ni, + input logic [5:0] cluster_id_i, + XBAR_PERIPH_BUS.Slave periph_slv, + input logic [5:0] periph_slv_atop_i, + XBAR_PERIPH_BUS.Master periph_mst, + output logic [5:0] periph_mst_atop_o +); + + `ifndef TARGET_SYNTHESIS + `define VIRTUAL_STDOUT + `endif + + `ifndef VIRTUAL_STDOUT + // When synthesizing, feed signals through to real stdout device. + assign periph_mst.req = periph_slv.req; + assign periph_mst.add = periph_slv.add; + assign periph_mst.wen = periph_slv.wen; + assign periph_mst_atop_o = periph_slv_atop_i; + assign periph_mst.wdata = periph_slv.wdata; + assign periph_mst.be = periph_slv.be; + assign periph_slv.gnt = periph_mst.gnt; + assign periph_slv.r_valid = periph_mst.r_valid; + assign periph_slv.r_rdata = periph_mst.r_rdata; + assign periph_slv.r_opc = periph_mst.r_opc; + `else + // When not synthesizing, insert virtual stdout device that is close to the core for fast and + // interference-free printing. + + byte buffer [$]; + + function void flush(); + automatic string s; + for (int i_char = 0; i_char < buffer.size(); i_char++) begin + s = $sformatf("%s%c", s, buffer[i_char]); + end + if (s.len() > 0) begin + $display("[%01d,%01d] %s", cluster_id_i, CoreId, s); + end + buffer.delete(); + endfunction + + function void append(byte ch); + if (ch == 8'hA) begin + flush(); + end else begin + buffer.push_back(ch); + end + endfunction + + logic resp_inj_d, resp_inj_q; + always_comb begin + // Feed through by default. + periph_mst.req = periph_slv.req; + periph_mst.add = periph_slv.add; + periph_mst.wen = periph_slv.wen; + periph_mst_atop_o = periph_slv_atop_i; + periph_mst.wdata = periph_slv.wdata; + periph_mst.be = periph_slv.be; + periph_slv.gnt = periph_mst.gnt; + periph_slv.r_valid = periph_mst.r_valid; + periph_slv.r_rdata = periph_mst.r_rdata; + periph_slv.r_opc = periph_mst.r_opc; + resp_inj_d = resp_inj_q; + // Inject responses by stdout device. + if (resp_inj_q) begin + periph_slv.r_valid = 1'b1; + periph_slv.r_rdata = '0; + periph_slv.r_opc = 1'b0; + resp_inj_d = 1'b0; + end + // Intercept accesses to stdout device. + if (periph_slv.req && periph_slv.add[31:12] == 20'h1A104) begin + periph_mst.req = 1'b0; + periph_slv.gnt = 1'b1; + resp_inj_d = 1'b1; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + flush(); + resp_inj_q <= 1'b0; + end else begin + resp_inj_q <= resp_inj_d; + if (resp_inj_d) begin + append(periph_slv.wdata & 32'hFF); + end + end + end + `endif + +endmodule diff --git a/hw/deps/riscv/include/apu_core_package.sv b/hw/deps/riscv/include/apu_core_package.sv new file mode 100644 index 0000000..ddba25d --- /dev/null +++ b/hw/deps/riscv/include/apu_core_package.sv @@ -0,0 +1,77 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: APU-core package // +// Project Name: RISC-V // +// Language: SystemVerilog // +// // +// Description: core package of RISC-V core for shared APU // +// // +//////////////////////////////////////////////////////////////////////////////// + +package apu_core_package; + + ///////////////////////////////////////////////////////////////////////////// + // IMPORTANT!! // + ///////////////////////////////////////////////////////////////////////////// + // THESE PARAMETERS HAVE TO MATCH THE ones in ulpcluster/apu_package.sv // + ///////////////////////////////////////////////////////////////////////////// + + // by default set to 0 + parameter SHARED_INT_MULT = 0; + + ///////////////////////////////////////////////////////////////////////////// + // until here // + ///////////////////////////////////////////////////////////////////////////// + + // APU interface + parameter WAPUTYPE = 0; + parameter APU_NARGS_CPU = 3; + parameter APU_WOP_CPU = 6; + parameter APU_NDSFLAGS_CPU = 15; + parameter APU_NUSFLAGS_CPU = 5; + + // FP-general + parameter APU_FLAGS_FP = 2; + parameter APU_FLAGS_FPNEW = 3; + + // DSP-Mult + parameter PIPE_REG_DSP_MULT = 1; + parameter APU_FLAGS_DSP_MULT = 0; + + // Int-Mult + parameter APU_FLAGS_INT_MULT = 1; + + // Int-div + + // addsub + parameter PIPE_REG_ADDSUB = 1; + + // mult + parameter PIPE_REG_MULT = 1; + + // casts + parameter PIPE_REG_CAST = 1; + + // mac + parameter PIPE_REG_MAC = 2; + + // div + parameter PIPE_REG_DIV = 4; + + // sqrt + parameter PIPE_REG_SQRT = 5; + + // iter divsqrt + +endpackage // apu_core_package diff --git a/hw/deps/riscv/include/fpnew_pkg.sv b/hw/deps/riscv/include/fpnew_pkg.sv new file mode 100644 index 0000000..6065054 --- /dev/null +++ b/hw/deps/riscv/include/fpnew_pkg.sv @@ -0,0 +1,484 @@ +// Copyright 2019 ETH Zurich and 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. + +// Author: Stefan Mach + +package fpnew_pkg; + + // --------- + // FP TYPES + // --------- + // | Enumerator | Format | Width | EXP_BITS | MAN_BITS + // |:----------:|------------------|-------:|:--------:|:--------: + // | FP32 | IEEE binary32 | 32 bit | 8 | 23 + // | FP64 | IEEE binary64 | 64 bit | 11 | 52 + // | FP16 | IEEE binary16 | 16 bit | 5 | 10 + // | FP8 | binary8 | 8 bit | 5 | 2 + // | FP16ALT | binary16alt | 16 bit | 8 | 7 + // *NOTE:* Add new formats only at the end of the enumeration for backwards compatibilty! + + // Encoding for a format + typedef struct packed { + int unsigned exp_bits; + int unsigned man_bits; + } fp_encoding_t; + + localparam int unsigned NUM_FP_FORMATS = 5; // change me to add formats + localparam int unsigned FP_FORMAT_BITS = $clog2(NUM_FP_FORMATS); + + // FP formats + typedef enum logic [FP_FORMAT_BITS-1:0] { + FP32 = 'd0, + FP64 = 'd1, + FP16 = 'd2, + FP8 = 'd3, + FP16ALT = 'd4 + // add new formats here + } fp_format_e; + + // Encodings for supported FP formats + localparam fp_encoding_t [0:NUM_FP_FORMATS-1] FP_ENCODINGS = '{ + '{8, 23}, // IEEE binary32 (single) + '{11, 52}, // IEEE binary64 (double) + '{5, 10}, // IEEE binary16 (half) + '{5, 2}, // custom binary8 + '{8, 7} // custom binary16alt + // add new formats here + }; + + typedef logic [0:NUM_FP_FORMATS-1] fmt_logic_t; // Logic indexed by FP format (for masks) + typedef logic [0:NUM_FP_FORMATS-1][31:0] fmt_unsigned_t; // Unsigned indexed by FP format + + localparam fmt_logic_t CPK_FORMATS = 5'b11000; // FP32 and FP64 can provide CPK only + + // --------- + // INT TYPES + // --------- + // | Enumerator | Width | + // |:----------:|-------:| + // | INT8 | 8 bit | + // | INT16 | 16 bit | + // | INT32 | 32 bit | + // | INT64 | 64 bit | + // *NOTE:* Add new formats only at the end of the enumeration for backwards compatibilty! + + localparam int unsigned NUM_INT_FORMATS = 4; // change me to add formats + localparam int unsigned INT_FORMAT_BITS = $clog2(NUM_INT_FORMATS); + + // Int formats + typedef enum logic [INT_FORMAT_BITS-1:0] { + INT8, + INT16, + INT32, + INT64 + // add new formats here + } int_format_e; + + // Returns the width of an INT format by index + function automatic int unsigned int_width(int_format_e ifmt); + unique case (ifmt) + INT8: return 8; + INT16: return 16; + INT32: return 32; + INT64: return 64; + endcase + endfunction + + typedef logic [0:NUM_INT_FORMATS-1] ifmt_logic_t; // Logic indexed by INT format (for masks) + + // -------------- + // FP OPERATIONS + // -------------- + localparam int unsigned NUM_OPGROUPS = 4; + + // Each FP operation belongs to an operation group + typedef enum logic [1:0] { + ADDMUL, DIVSQRT, NONCOMP, CONV + } opgroup_e; + + localparam int unsigned OP_BITS = 4; + + typedef enum logic [OP_BITS-1:0] { + FMADD, FNMSUB, ADD, MUL, // ADDMUL operation group + DIV, SQRT, // DIVSQRT operation group + SGNJ, MINMAX, CMP, CLASSIFY, // NONCOMP operation group + F2F, F2I, I2F, CPKAB, CPKCD // CONV operation group + } operation_e; + + // ------------------- + // RISC-V FP-SPECIFIC + // ------------------- + // Rounding modes + typedef enum logic [2:0] { + RNE = 3'b000, + RTZ = 3'b001, + RDN = 3'b010, + RUP = 3'b011, + RMM = 3'b100, + DYN = 3'b111 + } roundmode_e; + + // Status flags + typedef struct packed { + logic NV; // Invalid + logic DZ; // Divide by zero + logic OF; // Overflow + logic UF; // Underflow + logic NX; // Inexact + } status_t; + + // Information about a floating point value + typedef struct packed { + logic is_normal; // is the value normal + logic is_subnormal; // is the value subnormal + logic is_zero; // is the value zero + logic is_inf; // is the value infinity + logic is_nan; // is the value NaN + logic is_signalling; // is the value a signalling NaN + logic is_quiet; // is the value a quiet NaN + logic is_boxed; // is the value properly NaN-boxed (RISC-V specific) + } fp_info_t; + + // Classification mask + typedef enum logic [9:0] { + NEGINF = 10'b00_0000_0001, + NEGNORM = 10'b00_0000_0010, + NEGSUBNORM = 10'b00_0000_0100, + NEGZERO = 10'b00_0000_1000, + POSZERO = 10'b00_0001_0000, + POSSUBNORM = 10'b00_0010_0000, + POSNORM = 10'b00_0100_0000, + POSINF = 10'b00_1000_0000, + SNAN = 10'b01_0000_0000, + QNAN = 10'b10_0000_0000 + } classmask_e; + + // ------------------ + // FPU configuration + // ------------------ + // Pipelining registers can be inserted (at elaboration time) into operational units + typedef enum logic [1:0] { + BEFORE, // registers are inserted at the inputs of the unit + AFTER, // registers are inserted at the outputs of the unit + INSIDE, // registers are inserted at predetermined (suboptimal) locations in the unit + DISTRIBUTED // registers are evenly distributed, INSIDE >= AFTER >= BEFORE + } pipe_config_t; + + // Arithmetic units can be arranged in parallel (per format), merged (multi-format) or not at all. + typedef enum logic [1:0] { + DISABLED, // arithmetic units are not generated + PARALLEL, // arithmetic units are generated in prallel slices, one for each format + MERGED // arithmetic units are contained within a merged unit holding multiple formats + } unit_type_t; + + // Array of unit types indexed by format + typedef unit_type_t [0:NUM_FP_FORMATS-1] fmt_unit_types_t; + + // Array of format-specific unit types by opgroup + typedef fmt_unit_types_t [0:NUM_OPGROUPS-1] opgrp_fmt_unit_types_t; + // same with unsigned + typedef fmt_unsigned_t [0:NUM_OPGROUPS-1] opgrp_fmt_unsigned_t; + + // FPU configuration: features + typedef struct packed { + int unsigned Width; + logic EnableVectors; + logic EnableNanBox; + fmt_logic_t FpFmtMask; + ifmt_logic_t IntFmtMask; + } fpu_features_t; + + localparam fpu_features_t RV64D = '{ + Width: 64, + EnableVectors: 1'b0, + EnableNanBox: 1'b1, + FpFmtMask: 5'b11000, + IntFmtMask: 4'b0011 + }; + + localparam fpu_features_t RV32D = '{ + Width: 64, + EnableVectors: 1'b1, + EnableNanBox: 1'b1, + FpFmtMask: 5'b11000, + IntFmtMask: 4'b0010 + }; + + localparam fpu_features_t RV32F = '{ + Width: 32, + EnableVectors: 1'b0, + EnableNanBox: 1'b1, + FpFmtMask: 5'b10000, + IntFmtMask: 4'b0010 + }; + + localparam fpu_features_t RV64D_Xsflt = '{ + Width: 64, + EnableVectors: 1'b1, + EnableNanBox: 1'b1, + FpFmtMask: 5'b11111, + IntFmtMask: 4'b1111 + }; + + localparam fpu_features_t RV32F_Xsflt = '{ + Width: 32, + EnableVectors: 1'b1, + EnableNanBox: 1'b1, + FpFmtMask: 5'b10111, + IntFmtMask: 4'b1110 + }; + + localparam fpu_features_t RV32F_Xf16alt_Xfvec = '{ + Width: 32, + EnableVectors: 1'b1, + EnableNanBox: 1'b1, + FpFmtMask: 5'b10001, + IntFmtMask: 4'b0110 + }; + + + // FPU configuraion: implementation + typedef struct packed { + opgrp_fmt_unsigned_t PipeRegs; + opgrp_fmt_unit_types_t UnitTypes; + pipe_config_t PipeConfig; + } fpu_implementation_t; + + localparam fpu_implementation_t DEFAULT_NOREGS = '{ + PipeRegs: '{default: 0}, + UnitTypes: '{'{default: PARALLEL}, // ADDMUL + '{default: MERGED}, // DIVSQRT + '{default: PARALLEL}, // NONCOMP + '{default: MERGED}}, // CONV + PipeConfig: BEFORE + }; + + localparam fpu_implementation_t DEFAULT_SNITCH = '{ + PipeRegs: '{default: 1}, + UnitTypes: '{'{default: PARALLEL}, // ADDMUL + '{default: DISABLED}, // DIVSQRT + '{default: PARALLEL}, // NONCOMP + '{default: MERGED}}, // CONV + PipeConfig: BEFORE + }; + + // ----------------------- + // Synthesis optimization + // ----------------------- + localparam logic DONT_CARE = 1'b1; // the value to assign as don't care + + // ------------------------- + // General helper functions + // ------------------------- + function automatic int minimum(int a, int b); + return (a < b) ? a : b; + endfunction + + function automatic int maximum(int a, int b); + return (a > b) ? a : b; + endfunction + + // ------------------------------------------- + // Helper functions for FP formats and values + // ------------------------------------------- + // Returns the width of a FP format + function automatic int unsigned fp_width(fp_format_e fmt); + return FP_ENCODINGS[fmt].exp_bits + FP_ENCODINGS[fmt].man_bits + 1; + endfunction + + // Returns the widest FP format present + function automatic int unsigned max_fp_width(fmt_logic_t cfg); + automatic int unsigned res = 0; + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) + if (cfg[i]) + res = unsigned'(maximum(res, fp_width(fp_format_e'(i)))); + return res; + endfunction + + // Returns the narrowest FP format present + function automatic int unsigned min_fp_width(fmt_logic_t cfg); + automatic int unsigned res = max_fp_width(cfg); + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) + if (cfg[i]) + res = unsigned'(minimum(res, fp_width(fp_format_e'(i)))); + return res; + endfunction + + // Returns the number of expoent bits for a format + function automatic int unsigned exp_bits(fp_format_e fmt); + return FP_ENCODINGS[fmt].exp_bits; + endfunction + + // Returns the number of mantissa bits for a format + function automatic int unsigned man_bits(fp_format_e fmt); + return FP_ENCODINGS[fmt].man_bits; + endfunction + + // Returns the bias value for a given format (as per IEEE 754-2008) + function automatic int unsigned bias(fp_format_e fmt); + return unsigned'(2**(FP_ENCODINGS[fmt].exp_bits-1)-1); // symmetrical bias + endfunction + + function automatic fp_encoding_t super_format(fmt_logic_t cfg); + automatic fp_encoding_t res; + res = '0; + for (int unsigned fmt = 0; fmt < NUM_FP_FORMATS; fmt++) + if (cfg[fmt]) begin // only active format + res.exp_bits = unsigned'(maximum(res.exp_bits, exp_bits(fp_format_e'(fmt)))); + res.man_bits = unsigned'(maximum(res.man_bits, man_bits(fp_format_e'(fmt)))); + end + return res; + endfunction + + // ------------------------------------------- + // Helper functions for INT formats and values + // ------------------------------------------- + // Returns the widest INT format present + function automatic int unsigned max_int_width(ifmt_logic_t cfg); + automatic int unsigned res = 0; + for (int ifmt = 0; ifmt < NUM_INT_FORMATS; ifmt++) begin + if (cfg[ifmt]) res = maximum(res, int_width(int_format_e'(ifmt))); + end + return res; + endfunction + + // -------------------------------------------------- + // Helper functions for operations and FPU structure + // -------------------------------------------------- + // Returns the operation group of the given operation + function automatic opgroup_e get_opgroup(operation_e op); + unique case (op) + FMADD, FNMSUB, ADD, MUL: return ADDMUL; + DIV, SQRT: return DIVSQRT; + SGNJ, MINMAX, CMP, CLASSIFY: return NONCOMP; + F2F, F2I, I2F, CPKAB, CPKCD: return CONV; + default: return NONCOMP; + endcase + endfunction + + // Returns the number of operands by operation group + function automatic int unsigned num_operands(opgroup_e grp); + unique case (grp) + ADDMUL: return 3; + DIVSQRT: return 2; + NONCOMP: return 2; + CONV: return 3; // vectorial casts use 3 operands + default: return 0; + endcase + endfunction + + // Returns the number of lanes according to width, format and vectors + function automatic int unsigned num_lanes(int unsigned width, fp_format_e fmt, logic vec); + return vec ? width / fp_width(fmt) : 1; // if no vectors, only one lane + endfunction + + // Returns the maximum number of lanes in the FPU according to width, format config and vectors + function automatic int unsigned max_num_lanes(int unsigned width, fmt_logic_t cfg, logic vec); + return vec ? width / min_fp_width(cfg) : 1; // if no vectors, only one lane + endfunction + + // Returns a mask of active FP formats that are present in lane lane_no of a multiformat slice + function automatic fmt_logic_t get_lane_formats(int unsigned width, + fmt_logic_t cfg, + int unsigned lane_no); + automatic fmt_logic_t res; + for (int unsigned fmt = 0; fmt < NUM_FP_FORMATS; fmt++) + // Mask active formats with the number of lanes for that format + res[fmt] = cfg[fmt] & (width / fp_width(fp_format_e'(fmt)) > lane_no); + return res; + endfunction + + // Returns a mask of active INT formats that are present in lane lane_no of a multiformat slice + function automatic ifmt_logic_t get_lane_int_formats(int unsigned width, + fmt_logic_t cfg, + ifmt_logic_t icfg, + int unsigned lane_no); + automatic ifmt_logic_t res; + automatic fmt_logic_t lanefmts; + res = '0; + lanefmts = get_lane_formats(width, cfg, lane_no); + + for (int unsigned ifmt = 0; ifmt < NUM_INT_FORMATS; ifmt++) + for (int unsigned fmt = 0; fmt < NUM_FP_FORMATS; fmt++) + // Mask active int formats with the width of the float formats + if ((fp_width(fp_format_e'(fmt)) == int_width(int_format_e'(ifmt)))) + res[ifmt] |= icfg[ifmt] && lanefmts[fmt]; + return res; + endfunction + + // Returns a mask of active FP formats that are present in lane lane_no of a CONV slice + function automatic fmt_logic_t get_conv_lane_formats(int unsigned width, + fmt_logic_t cfg, + int unsigned lane_no); + automatic fmt_logic_t res; + for (int unsigned fmt = 0; fmt < NUM_FP_FORMATS; fmt++) + // Mask active formats with the number of lanes for that format, CPK at least twice + res[fmt] = cfg[fmt] && ((width / fp_width(fp_format_e'(fmt)) > lane_no) || + (CPK_FORMATS[fmt] && (lane_no < 2))); + return res; + endfunction + + // Returns a mask of active INT formats that are present in lane lane_no of a CONV slice + function automatic ifmt_logic_t get_conv_lane_int_formats(int unsigned width, + fmt_logic_t cfg, + ifmt_logic_t icfg, + int unsigned lane_no); + automatic ifmt_logic_t res; + automatic fmt_logic_t lanefmts; + res = '0; + lanefmts = get_conv_lane_formats(width, cfg, lane_no); + + for (int unsigned ifmt = 0; ifmt < NUM_INT_FORMATS; ifmt++) + for (int unsigned fmt = 0; fmt < NUM_FP_FORMATS; fmt++) + // Mask active int formats with the width of the float formats + res[ifmt] |= icfg[ifmt] && lanefmts[fmt] && + (fp_width(fp_format_e'(fmt)) == int_width(int_format_e'(ifmt))); + return res; + endfunction + + // Return whether any active format is set as MERGED + function automatic logic any_enabled_multi(fmt_unit_types_t types, fmt_logic_t cfg); + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) + if (cfg[i] && types[i] == MERGED) + return 1'b1; + return 1'b0; + endfunction + + // Return whether the given format is the first active one set as MERGED + function automatic logic is_first_enabled_multi(fp_format_e fmt, + fmt_unit_types_t types, + fmt_logic_t cfg); + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) begin + if (cfg[i] && types[i] == MERGED) return (fp_format_e'(i) == fmt); + end + return 1'b0; + endfunction + + // Returns the first format that is active and is set as MERGED + function automatic fp_format_e get_first_enabled_multi(fmt_unit_types_t types, fmt_logic_t cfg); + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) + if (cfg[i] && types[i] == MERGED) + return fp_format_e'(i); + return fp_format_e'(0); + endfunction + + // Returns the largest number of regs that is active and is set as MERGED + function automatic int unsigned get_num_regs_multi(fmt_unsigned_t regs, + fmt_unit_types_t types, + fmt_logic_t cfg); + automatic int unsigned res = 0; + for (int unsigned i = 0; i < NUM_FP_FORMATS; i++) begin + if (cfg[i] && types[i] == MERGED) res = maximum(res, regs[i]); + end + return res; + endfunction + +endpackage diff --git a/hw/deps/riscv/include/riscv_defines.sv b/hw/deps/riscv/include/riscv_defines.sv new file mode 100644 index 0000000..b8556a5 --- /dev/null +++ b/hw/deps/riscv/include/riscv_defines.sv @@ -0,0 +1,675 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Matthias Baer - baermatt@student.ethz.ch // +// // +// Additional contributions by: // +// Sven Stucki - svstucki@student.ethz.ch // +// // +// // +// Design Name: RISC-V processor core // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Defines for various constants used by the processor core. // +// // +//////////////////////////////////////////////////////////////////////////////// + +package riscv_defines; + +//////////////////////////////////////////////// +// ___ ____ _ // +// / _ \ _ __ / ___|___ __| | ___ ___ // +// | | | | '_ \| | / _ \ / _` |/ _ \/ __| // +// | |_| | |_) | |__| (_) | (_| | __/\__ \ // +// \___/| .__/ \____\___/ \__,_|\___||___/ // +// |_| // +//////////////////////////////////////////////// + +parameter OPCODE_SYSTEM = 7'h73; +parameter OPCODE_FENCE = 7'h0f; +parameter OPCODE_OP = 7'h33; +parameter OPCODE_OPIMM = 7'h13; +parameter OPCODE_STORE = 7'h23; +parameter OPCODE_BSW = 7'h6b; +parameter OPCODE_LOAD = 7'h03; +parameter OPCODE_BRANCH = 7'h63; +parameter OPCODE_JALR = 7'h67; +parameter OPCODE_JAL = 7'h6f; +parameter OPCODE_AUIPC = 7'h17; +parameter OPCODE_LUI = 7'h37; +parameter OPCODE_OP_FP = 7'h53; +parameter OPCODE_OP_FMADD = 7'h43; +parameter OPCODE_OP_FNMADD = 7'h4f; +parameter OPCODE_OP_FMSUB = 7'h47; +parameter OPCODE_OP_FNMSUB = 7'h4b; +parameter OPCODE_STORE_FP = 7'h27; +parameter OPCODE_LOAD_FP = 7'h07; +parameter OPCODE_AMO = 7'h2F; + +// those opcodes are now used for PULP custom instructions +// parameter OPCODE_CUST0 = 7'h0b +// parameter OPCODE_CUST1 = 7'h2b + +// PULP custom +parameter OPCODE_LOAD_POST = 7'h0b; +parameter OPCODE_STORE_POST = 7'h2b; +parameter OPCODE_STORE_BUF = 7'b11_010_11; +parameter OPCODE_STORE_POST_BUF = 7'b11_101_11; +parameter OPCODE_PULP_OP = 7'h5b; +parameter OPCODE_VECOP = 7'h57; +parameter OPCODE_HWLOOP = 7'h7b; + +parameter REGC_S1 = 2'b10; +parameter REGC_S4 = 2'b00; +parameter REGC_RD = 2'b01; +parameter REGC_ZERO = 2'b11; + + +////////////////////////////////////////////////////////////////////////////// +// _ _ _ _ ___ _ _ // +// / \ | | | | | | / _ \ _ __ ___ _ __ __ _| |_(_) ___ _ __ ___ // +// / _ \ | | | | | | | | | | '_ \ / _ \ '__/ _` | __| |/ _ \| '_ \/ __| // +// / ___ \| |__| |_| | | |_| | |_) | __/ | | (_| | |_| | (_) | | | \__ \ // +// /_/ \_\_____\___/ \___/| .__/ \___|_| \__,_|\__|_|\___/|_| |_|___/ // +// |_| // +////////////////////////////////////////////////////////////////////////////// + +parameter ALU_OP_WIDTH = 7; + +parameter ALU_ADD = 7'b0011000; +parameter ALU_SUB = 7'b0011001; +parameter ALU_ADDU = 7'b0011010; +parameter ALU_SUBU = 7'b0011011; +parameter ALU_ADDR = 7'b0011100; +parameter ALU_SUBR = 7'b0011101; +parameter ALU_ADDUR = 7'b0011110; +parameter ALU_SUBUR = 7'b0011111; + +parameter ALU_XOR = 7'b0101111; +parameter ALU_OR = 7'b0101110; +parameter ALU_AND = 7'b0010101; + +// Shifts +parameter ALU_SRA = 7'b0100100; +parameter ALU_SRL = 7'b0100101; +parameter ALU_ROR = 7'b0100110; +parameter ALU_SLL = 7'b0100111; + +// bit manipulation +parameter ALU_BEXT = 7'b0101000; +parameter ALU_BEXTU = 7'b0101001; +parameter ALU_BINS = 7'b0101010; +parameter ALU_BCLR = 7'b0101011; +parameter ALU_BSET = 7'b0101100; +parameter ALU_BREV = 7'b1001001; + +// Bit counting +parameter ALU_FF1 = 7'b0110110; +parameter ALU_FL1 = 7'b0110111; +parameter ALU_CNT = 7'b0110100; +parameter ALU_CLB = 7'b0110101; + +// Sign-/zero-extensions +parameter ALU_EXTS = 7'b0111110; +parameter ALU_EXT = 7'b0111111; + +// Comparisons +parameter ALU_LTS = 7'b0000000; +parameter ALU_LTU = 7'b0000001; +parameter ALU_LES = 7'b0000100; +parameter ALU_LEU = 7'b0000101; +parameter ALU_GTS = 7'b0001000; +parameter ALU_GTU = 7'b0001001; +parameter ALU_GES = 7'b0001010; +parameter ALU_GEU = 7'b0001011; +parameter ALU_EQ = 7'b0001100; +parameter ALU_NE = 7'b0001101; + +// Set Lower Than operations +parameter ALU_SLTS = 7'b0000010; +parameter ALU_SLTU = 7'b0000011; +parameter ALU_SLETS = 7'b0000110; +parameter ALU_SLETU = 7'b0000111; + +// Absolute value +parameter ALU_ABS = 7'b0010100; +parameter ALU_CLIP = 7'b0010110; +parameter ALU_CLIPU = 7'b0010111; + +// Insert/extract +parameter ALU_INS = 7'b0101101; + +// min/max +parameter ALU_MIN = 7'b0010000; +parameter ALU_MINU = 7'b0010001; +parameter ALU_MAX = 7'b0010010; +parameter ALU_MAXU = 7'b0010011; + +// div/rem +parameter ALU_DIVU = 7'b0110000; // bit 0 is used for signed mode, bit 1 is used for remdiv +parameter ALU_DIV = 7'b0110001; // bit 0 is used for signed mode, bit 1 is used for remdiv +parameter ALU_REMU = 7'b0110010; // bit 0 is used for signed mode, bit 1 is used for remdiv +parameter ALU_REM = 7'b0110011; // bit 0 is used for signed mode, bit 1 is used for remdiv + +parameter ALU_SHUF = 7'b0111010; +parameter ALU_SHUF2 = 7'b0111011; +parameter ALU_PCKLO = 7'b0111000; +parameter ALU_PCKHI = 7'b0111001; + +// fpu +parameter ALU_FKEEP = 7'b1111111; // hack, to support fcvt.s.d +parameter ALU_FSGNJ = 7'b1000000; +parameter ALU_FSGNJN = 7'b1000001; +parameter ALU_FSGNJX = 7'b1000010; +parameter ALU_FEQ = 7'b1000011; +parameter ALU_FLT = 7'b1000100; +parameter ALU_FLE = 7'b1000101; +parameter ALU_FMAX = 7'b1000110; +parameter ALU_FMIN = 7'b1000111; +parameter ALU_FCLASS = 7'b1001000; + +parameter MUL_MAC32 = 3'b000; +parameter MUL_MSU32 = 3'b001; +parameter MUL_I = 3'b010; +parameter MUL_IR = 3'b011; +parameter MUL_DOT8 = 3'b100; +parameter MUL_DOT16 = 3'b101; +parameter MUL_H = 3'b110; + +// vector modes +parameter VEC_MODE32 = 2'b00; +parameter VEC_MODE16 = 2'b10; +parameter VEC_MODE8 = 2'b11; + + + // FSM state encoding + typedef enum logic [4:0] { RESET, BOOT_SET, SLEEP, WAIT_SLEEP, FIRST_FETCH, + DECODE, + IRQ_TAKEN_ID, IRQ_TAKEN_IF, IRQ_FLUSH, IRQ_FLUSH_ELW, ELW_EXE, + FLUSH_EX, FLUSH_WB, XRET_JUMP, + DBG_TAKEN_ID, DBG_TAKEN_IF, DBG_FLUSH, DBG_WAIT_BRANCH } ctrl_state_e; + + +///////////////////////////////////////////////////////// +// ____ ____ ____ _ _ // +// / ___/ ___| | _ \ ___ __ _(_)___| |_ ___ _ __ // +// | | \___ \ | |_) / _ \/ _` | / __| __/ _ \ '__| // +// | |___ ___) | | _ < __/ (_| | \__ \ || __/ | // +// \____|____/ |_| \_\___|\__, |_|___/\__\___|_| // +// |___/ // +///////////////////////////////////////////////////////// + +// CSRs mnemonics +// imported form IBEX, some regs may be still not implemented +typedef enum logic[11:0] { + // Machine information + CSR_MVENDORID = 12'hF11, + CSR_MARCHID = 12'hF12, + CSR_MIMPID = 12'hF13, + CSR_MHARTID = 12'hF14, + + // Machine trap setup + CSR_MSTATUS = 12'h300, + CSR_MISA = 12'h301, + CSR_MIE = 12'h304, + CSR_MTVEC = 12'h305, + CSR_MIE1 = 12'h7D0, + + // Machine trap handling + CSR_MSCRATCH = 12'h340, + CSR_MEPC = 12'h341, + CSR_MCAUSE = 12'h342, + CSR_MTVAL = 12'h343, + CSR_MIP = 12'h344, + CSR_MCOUNTEREN= 12'h306, + CSR_MIP1 = 12'h7D2, + + // User trap setup + CSR_USTATUS = 12'h000, + CSR_UTVEC = 12'h005, + + // User trap handling + CSR_UEPC = 12'h041, + CSR_UCAUSE = 12'h042, + + // Physical memory protection + CSR_PMPCFG0 = 12'h3A0, + CSR_PMPCFG1 = 12'h3A1, + CSR_PMPCFG2 = 12'h3A2, + CSR_PMPCFG3 = 12'h3A3, + CSR_PMPADDR0 = 12'h3B0, + CSR_PMPADDR1 = 12'h3B1, + CSR_PMPADDR2 = 12'h3B2, + CSR_PMPADDR3 = 12'h3B3, + CSR_PMPADDR4 = 12'h3B4, + CSR_PMPADDR5 = 12'h3B5, + CSR_PMPADDR6 = 12'h3B6, + CSR_PMPADDR7 = 12'h3B7, + CSR_PMPADDR8 = 12'h3B8, + CSR_PMPADDR9 = 12'h3B9, + CSR_PMPADDR10 = 12'h3BA, + CSR_PMPADDR11 = 12'h3BB, + CSR_PMPADDR12 = 12'h3BC, + CSR_PMPADDR13 = 12'h3BD, + CSR_PMPADDR14 = 12'h3BE, + CSR_PMPADDR15 = 12'h3BF, + + // Trigger + CSR_TSELECT = 12'h7A0, + CSR_TDATA1 = 12'h7A1, + CSR_TDATA2 = 12'h7A2, + CSR_TDATA3 = 12'h7A3, + CSR_MCONTEXT = 12'h7A8, + CSR_SCONTEXT = 12'h7AA, + + // Debug/trace + CSR_DCSR = 12'h7b0, + CSR_DPC = 12'h7b1, + + // Debug + CSR_DSCRATCH0 = 12'h7b2, + CSR_DSCRATCH1 = 12'h7b3, + + // Floating Point + CSR_FFLAGS = 12'h001, + CSR_FRM = 12'h002, + CSR_FCSR = 12'h003, + + // Hardware Performance Monitor + CSR_MCYCLE = 12'hb00, + CSR_MINSTRET = 12'hb02, + CSR_MHPMCOUNTER3 = 12'hb03, + CSR_MHPMCOUNTER4 = 12'hb04, + CSR_MHPMCOUNTER5 = 12'hb05, + CSR_MHPMCOUNTER6 = 12'hb06, + CSR_MHPMCOUNTER7 = 12'hb07, + CSR_MHPMCOUNTER8 = 12'hb08, + CSR_MHPMCOUNTER9 = 12'hb09, + CSR_MHPMCOUNTER10 = 12'hb0a, + CSR_MHPMCOUNTER11 = 12'hb0b, + CSR_MHPMCOUNTER12 = 12'hb0c, + CSR_MHPMCOUNTER13 = 12'hb0d, + CSR_MHPMCOUNTER14 = 12'hb0e, + CSR_MHPMCOUNTER15 = 12'hb0f, + CSR_MHPMCOUNTER16 = 12'hb10, + CSR_MHPMCOUNTER17 = 12'hb11, + CSR_MHPMCOUNTER18 = 12'hb12, + CSR_MHPMCOUNTER19 = 12'hb13, + CSR_MHPMCOUNTER20 = 12'hb14, + CSR_MHPMCOUNTER21 = 12'hb15, + CSR_MHPMCOUNTER22 = 12'hb16, + CSR_MHPMCOUNTER23 = 12'hb17, + CSR_MHPMCOUNTER24 = 12'hb18, + CSR_MHPMCOUNTER25 = 12'hb19, + CSR_MHPMCOUNTER26 = 12'hb1a, + CSR_MHPMCOUNTER27 = 12'hb1b, + CSR_MHPMCOUNTER28 = 12'hb1c, + CSR_MHPMCOUNTER29 = 12'hb1d, + CSR_MHPMCOUNTER30 = 12'hb1e, + CSR_MHPMCOUNTER31 = 12'hb1f, + + CSR_MCYCLEH = 12'hb80, + CSR_MINSTRETH = 12'hb82, + CSR_MHPMCOUNTER3H = 12'hb83, + CSR_MHPMCOUNTER4H = 12'hb84, + CSR_MHPMCOUNTER5H = 12'hb85, + CSR_MHPMCOUNTER6H = 12'hb86, + CSR_MHPMCOUNTER7H = 12'hb87, + CSR_MHPMCOUNTER8H = 12'hb88, + CSR_MHPMCOUNTER9H = 12'hb89, + CSR_MHPMCOUNTER10H = 12'hb8a, + CSR_MHPMCOUNTER11H = 12'hb8b, + CSR_MHPMCOUNTER12H = 12'hb8c, + CSR_MHPMCOUNTER13H = 12'hb8d, + CSR_MHPMCOUNTER14H = 12'hb8e, + CSR_MHPMCOUNTER15H = 12'hb8f, + CSR_MHPMCOUNTER16H = 12'hb90, + CSR_MHPMCOUNTER17H = 12'hb91, + CSR_MHPMCOUNTER18H = 12'hb92, + CSR_MHPMCOUNTER19H = 12'hb93, + CSR_MHPMCOUNTER20H = 12'hb94, + CSR_MHPMCOUNTER21H = 12'hb95, + CSR_MHPMCOUNTER22H = 12'hb96, + CSR_MHPMCOUNTER23H = 12'hb97, + CSR_MHPMCOUNTER24H = 12'hb98, + CSR_MHPMCOUNTER25H = 12'hb99, + CSR_MHPMCOUNTER26H = 12'hb9a, + CSR_MHPMCOUNTER27H = 12'hb9b, + CSR_MHPMCOUNTER28H = 12'hb9c, + CSR_MHPMCOUNTER29H = 12'hb9d, + CSR_MHPMCOUNTER30H = 12'hb9e, + CSR_MHPMCOUNTER31H = 12'hb9f, + + CSR_MCOUNTINHIBIT = 12'h320, + + CSR_MHPMEVENT3 = 12'h323, + CSR_MHPMEVENT4 = 12'h324, + CSR_MHPMEVENT5 = 12'h325, + CSR_MHPMEVENT6 = 12'h326, + CSR_MHPMEVENT7 = 12'h327, + CSR_MHPMEVENT8 = 12'h328, + CSR_MHPMEVENT9 = 12'h329, + CSR_MHPMEVENT10 = 12'h32a, + CSR_MHPMEVENT11 = 12'h32b, + CSR_MHPMEVENT12 = 12'h32c, + CSR_MHPMEVENT13 = 12'h32d, + CSR_MHPMEVENT14 = 12'h32e, + CSR_MHPMEVENT15 = 12'h32f, + CSR_MHPMEVENT16 = 12'h330, + CSR_MHPMEVENT17 = 12'h331, + CSR_MHPMEVENT18 = 12'h332, + CSR_MHPMEVENT19 = 12'h333, + CSR_MHPMEVENT20 = 12'h334, + CSR_MHPMEVENT21 = 12'h335, + CSR_MHPMEVENT22 = 12'h336, + CSR_MHPMEVENT23 = 12'h337, + CSR_MHPMEVENT24 = 12'h338, + CSR_MHPMEVENT25 = 12'h339, + CSR_MHPMEVENT26 = 12'h33a, + CSR_MHPMEVENT27 = 12'h33b, + CSR_MHPMEVENT28 = 12'h33c, + CSR_MHPMEVENT29 = 12'h33d, + CSR_MHPMEVENT30 = 12'h33e, + CSR_MHPMEVENT31 = 12'h33f + +} csr_num_e; + +// CSR operations +parameter CSR_OP_READ = 2'b00; +parameter CSR_OP_WRITE = 2'b01; +parameter CSR_OP_SET = 2'b10; +parameter CSR_OP_CLEAR = 2'b11; + +// CSR interrupt pending/enable bits +parameter int unsigned CSR_MSIX_BIT = 3; +parameter int unsigned CSR_MTIX_BIT = 7; +parameter int unsigned CSR_MEIX_BIT = 11; +parameter int unsigned CSR_MFIX_BIT_LOW = 16; +parameter int unsigned CSR_MFIX_BIT_HIGH = 31; + +// SPR for debugger, not accessible by CPU +parameter SP_DVR0 = 16'h3000; +parameter SP_DCR0 = 16'h3008; +parameter SP_DMR1 = 16'h3010; +parameter SP_DMR2 = 16'h3011; + +parameter SP_DVR_MSB = 8'h00; +parameter SP_DCR_MSB = 8'h01; +parameter SP_DMR_MSB = 8'h02; +parameter SP_DSR_MSB = 8'h04; + +// Privileged mode +typedef enum logic[1:0] { + PRIV_LVL_M = 2'b11, + PRIV_LVL_H = 2'b10, + PRIV_LVL_S = 2'b01, + PRIV_LVL_U = 2'b00 +} PrivLvl_t; + +/////////////////////////////////////////////// +// ___ ____ ____ _ // +// |_ _| _ \ / ___|| |_ __ _ __ _ ___ // +// | || | | | \___ \| __/ _` |/ _` |/ _ \ // +// | || |_| | ___) | || (_| | (_| | __/ // +// |___|____/ |____/ \__\__,_|\__, |\___| // +// |___/ // +/////////////////////////////////////////////// + +// forwarding operand mux +parameter SEL_REGFILE = 2'b00; +parameter SEL_FW_EX = 2'b01; +parameter SEL_FW_WB = 2'b10; + +// operand a selection +parameter OP_A_REGA_OR_FWD = 3'b000; +parameter OP_A_CURRPC = 3'b001; +parameter OP_A_IMM = 3'b010; +parameter OP_A_REGB_OR_FWD = 3'b011; +parameter OP_A_REGC_OR_FWD = 3'b100; + +// immediate a selection +parameter IMMA_Z = 1'b0; +parameter IMMA_ZERO = 1'b1; + +// operand b selection +parameter OP_B_REGB_OR_FWD = 3'b000; +parameter OP_B_REGC_OR_FWD = 3'b001; +parameter OP_B_IMM = 3'b010; +parameter OP_B_REGA_OR_FWD = 3'b011; +parameter OP_B_BMASK = 3'b100; + +// immediate b selection +parameter IMMB_I = 4'b0000; +parameter IMMB_S = 4'b0001; +parameter IMMB_U = 4'b0010; +parameter IMMB_PCINCR = 4'b0011; +parameter IMMB_S2 = 4'b0100; +parameter IMMB_S3 = 4'b0101; +parameter IMMB_VS = 4'b0110; +parameter IMMB_VU = 4'b0111; +parameter IMMB_SHUF = 4'b1000; +parameter IMMB_CLIP = 4'b1001; +parameter IMMB_BI = 4'b1011; + +// bit mask selection +parameter BMASK_A_ZERO = 1'b0; +parameter BMASK_A_S3 = 1'b1; + +parameter BMASK_B_S2 = 2'b00; +parameter BMASK_B_S3 = 2'b01; +parameter BMASK_B_ZERO = 2'b10; +parameter BMASK_B_ONE = 2'b11; + +parameter BMASK_A_REG = 1'b0; +parameter BMASK_A_IMM = 1'b1; +parameter BMASK_B_REG = 1'b0; +parameter BMASK_B_IMM = 1'b1; + + +// multiplication immediates +parameter MIMM_ZERO = 1'b0; +parameter MIMM_S3 = 1'b1; + +// operand c selection +parameter OP_C_REGC_OR_FWD = 2'b00; +parameter OP_C_REGB_OR_FWD = 2'b01; +parameter OP_C_JT = 2'b10; + +// branch types +parameter BRANCH_NONE = 2'b00; +parameter BRANCH_JAL = 2'b01; +parameter BRANCH_JALR = 2'b10; +parameter BRANCH_COND = 2'b11; // conditional branches + +// jump target mux +parameter JT_JAL = 2'b01; +parameter JT_JALR = 2'b10; +parameter JT_COND = 2'b11; + +// Atomic operations +parameter AMO_LR = 5'b00010; +parameter AMO_SC = 5'b00011; +parameter AMO_SWAP = 5'b00001; +parameter AMO_ADD = 5'b00000; +parameter AMO_XOR = 5'b00100; +parameter AMO_AND = 5'b01100; +parameter AMO_OR = 5'b01000; +parameter AMO_MIN = 5'b10000; +parameter AMO_MAX = 5'b10100; +parameter AMO_MINU = 5'b11000; +parameter AMO_MAXU = 5'b11100; + +/////////////////////////////////////////////// +// ___ _____ ____ _ // +// |_ _| ___| / ___|| |_ __ _ __ _ ___ // +// | || |_ \___ \| __/ _` |/ _` |/ _ \ // +// | || _| ___) | || (_| | (_| | __/ // +// |___|_| |____/ \__\__,_|\__, |\___| // +// |___/ // +/////////////////////////////////////////////// + +// PC mux selector defines +parameter PC_BOOT = 3'b000; +parameter PC_JUMP = 3'b010; +parameter PC_BRANCH = 3'b011; +parameter PC_EXCEPTION = 3'b100; +parameter PC_FENCEI = 3'b001; +parameter PC_MRET = 3'b101; +parameter PC_URET = 3'b110; +parameter PC_DRET = 3'b111; + +// Exception PC mux selector defines +parameter EXC_PC_EXCEPTION = 3'b000; +parameter EXC_PC_IRQ = 3'b001; + +parameter EXC_PC_DBD = 3'b010; + +// Exception Cause +parameter EXC_CAUSE_INSTR_FAULT = 6'h01; +parameter EXC_CAUSE_ILLEGAL_INSN = 6'h02; +parameter EXC_CAUSE_BREAKPOINT = 6'h03; +parameter EXC_CAUSE_LOAD_FAULT = 6'h05; +parameter EXC_CAUSE_STORE_FAULT = 6'h07; +parameter EXC_CAUSE_ECALL_UMODE = 6'h08; +parameter EXC_CAUSE_ECALL_MMODE = 6'h0B; + +parameter int unsigned IRQ_ID_BITS = 6; +parameter int unsigned IRQ_LINES_NUM = 51; // number of physical irq lines to core +// Interrupt lines struct +typedef struct packed { + logic irq_software; + logic irq_timer; + logic irq_external; + logic [15:0] irq_fast; +} Interrupts_t; + + +// Trap mux selector +parameter TRAP_MACHINE = 2'b00; +parameter TRAP_USER = 2'b01; + +// Debug Cause +parameter DBG_CAUSE_NONE = 3'h0; +parameter DBG_CAUSE_EBREAK = 3'h1; +parameter DBG_CAUSE_TRIGGER = 3'h2; +parameter DBG_CAUSE_HALTREQ = 3'h3; +parameter DBG_CAUSE_STEP = 3'h4; +parameter DBG_CAUSE_RSTHALTREQ = 3'h5; + +// Debug module +parameter DBG_SETS_W = 6; + +parameter DBG_SETS_IRQ = 5; +parameter DBG_SETS_ECALL = 4; +parameter DBG_SETS_EILL = 3; +parameter DBG_SETS_ELSU = 2; +parameter DBG_SETS_EBRK = 1; +parameter DBG_SETS_SSTE = 0; + +parameter DBG_CAUSE_HALT = 6'h1F; + +// Constants for the dcsr.xdebugver fields +typedef enum logic[3:0] { + XDEBUGVER_NO = 4'd0, // no external debug support + XDEBUGVER_STD = 4'd4, // external debug according to RISC-V debug spec + XDEBUGVER_NONSTD = 4'd15 // debug not conforming to RISC-V debug spec +} x_debug_ver_e; + + +///////////////////////////////////// +// THIS PART IS OBSOLETED BY FPNEW // +///////////////////////////////////// +// // private FPU +// parameter C_CMD = 4; +// parameter C_FPU_ADD_CMD = 4'h0; +// parameter C_FPU_SUB_CMD = 4'h1; +// parameter C_FPU_MUL_CMD = 4'h2; +// parameter C_FPU_DIV_CMD = 4'h3; +// parameter C_FPU_I2F_CMD = 4'h4; +// parameter C_FPU_F2I_CMD = 4'h5; +// parameter C_FPU_SQRT_CMD = 4'h6; +// parameter C_FPU_NOP_CMD = 4'h7; +// parameter C_FPU_FMADD_CMD = 4'h8; +// parameter C_FPU_FMSUB_CMD = 4'h9; +// parameter C_FPU_FNMADD_CMD = 4'hA; +// parameter C_FPU_FNMSUB_CMD = 4'hB; + +// Floating-point extensions configuration +parameter bit C_RVF = 1'b1; // Is F extension enabled +parameter bit C_RVD = 1'b0; // Is D extension enabled - NOT SUPPORTED CURRENTLY + +// Transprecision floating-point extensions configuration +parameter bit C_XF16 = 1'b0; // Is half-precision float extension (Xf16) enabled +parameter bit C_XF16ALT = 1'b0; // Is alternative half-precision float extension (Xf16alt) enabled +parameter bit C_XF8 = 1'b0; // Is quarter-precision float extension (Xf8) enabled +parameter bit C_XFVEC = 1'b0; // Is vectorial float extension (Xfvec) enabled + +// FPnew configuration +parameter C_FPNEW_OPBITS = fpnew_pkg::OP_BITS; +parameter C_FPNEW_FMTBITS = fpnew_pkg::FP_FORMAT_BITS; +parameter C_FPNEW_IFMTBITS = fpnew_pkg::INT_FORMAT_BITS; + +// Latency of FP operations: 0 = no pipe registers, 1 = 1 pipe register etc. +parameter int unsigned C_LAT_FP64 = 'd0; +parameter int unsigned C_LAT_FP32 = 'd0; +parameter int unsigned C_LAT_FP16 = 'd0; +parameter int unsigned C_LAT_FP16ALT = 'd0; +parameter int unsigned C_LAT_FP8 = 'd0; +parameter int unsigned C_LAT_DIVSQRT = 'd1; // divsqrt post-processing pipe +parameter int unsigned C_LAT_CONV = 'd0; +parameter int unsigned C_LAT_NONCOMP = 'd0; + +// General FPU-specific defines + +// Length of widest floating-point format = width of fp regfile +parameter C_FLEN = C_RVD ? 64 : // D ext. + C_RVF ? 32 : // F ext. + C_XF16 ? 16 : // Xf16 ext. + C_XF16ALT ? 16 : // Xf16alt ext. + C_XF8 ? 8 : // Xf8 ext. + 0; // Unused in case of no FP + +parameter C_FFLAG = 5; +parameter C_RM = 3; + +parameter C_PC = 5; + + + +///////////////////////////////////////////////////////// +// ____ ____ ____ // +// / ___/ ___| | _ \ // +// | | \___ \ | |_) | MAPPING // +// | |___ ___) | | _ < // +// \____|____/ |_| \_\ // +// // +///////////////////////////////////////////////////////// + +//Hardware Loop +parameter HWLoop0_START = 12'h7C0; //NON standard read/write (Machine CSRs). Old address 12'h7B0; +parameter HWLoop0_END = 12'h7C1; //NON standard read/write (Machine CSRs). Old address 12'h7B1; +parameter HWLoop0_COUNTER = 12'h7C2; //NON standard read/write (Machine CSRs). Old address 12'h7B2; +parameter HWLoop1_START = 12'h7C4; //NON standard read/write (Machine CSRs). Old address 12'h7B4; +parameter HWLoop1_END = 12'h7C5; //NON standard read/write (Machine CSRs). Old address 12'h7B5; +parameter HWLoop1_COUNTER = 12'h7C6; //NON standard read/write (Machine CSRs). Old address 12'h7B6; + +//Custom Hart and Priveledge +parameter UHARTID = 12'h014; //NON standard read/write (Machine CSRs) - User Hart ID +parameter PRIVLV = 12'hC10; //NON standard read/write (Machine CSRs) - Privilege Level +//Custom Floating Point +parameter FPREC = 12'h006; //NON standard read/write (Machine CSRs) - Floating Point + +//PMP Range +parameter CSR_PMPADDR_RANGE_X = CSR_PMPADDR0 | 12'b0000_0000_xxxx; +parameter CSR_PMPCFG_RANGE_X = CSR_PMPCFG0 | 12'b0000_0000_00xx; + +endpackage diff --git a/hw/deps/riscv/include/riscv_tracer_defines.sv b/hw/deps/riscv/include/riscv_tracer_defines.sv new file mode 100644 index 0000000..aac4b83 --- /dev/null +++ b/hw/deps/riscv/include/riscv_tracer_defines.sv @@ -0,0 +1,203 @@ +// Copyright 2018 ETH Zurich and 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. + + +package riscv_tracer_defines; +import riscv_defines::*; + +// settings +parameter bit SymbolicRegs = 0; // show abi names for registers + +// instruction masks (for tracer) +// parameter INSTR_CUSTOM0 = { 25'b?, OPCODE_CUST0 }; +// parameter INSTR_CUSTOM1 = { 25'b?, OPCODE_CUST1 }; +parameter INSTR_LUI = { 25'b?, OPCODE_LUI }; +parameter INSTR_AUIPC = { 25'b?, OPCODE_AUIPC }; +parameter INSTR_JAL = { 25'b?, OPCODE_JAL }; +parameter INSTR_JALR = { 17'b?, 3'b000, 5'b?, OPCODE_JALR }; +// BRANCH +parameter INSTR_BEQ = { 17'b?, 3'b000, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BNE = { 17'b?, 3'b001, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BLT = { 17'b?, 3'b100, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BGE = { 17'b?, 3'b101, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BLTU = { 17'b?, 3'b110, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BGEU = { 17'b?, 3'b111, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BEQIMM = { 17'b?, 3'b010, 5'b?, OPCODE_BRANCH }; +parameter INSTR_BNEIMM = { 17'b?, 3'b011, 5'b?, OPCODE_BRANCH }; +// OPIMM +parameter INSTR_ADDI = { 17'b?, 3'b000, 5'b?, OPCODE_OPIMM }; +parameter INSTR_SLTI = { 17'b?, 3'b010, 5'b?, OPCODE_OPIMM }; +parameter INSTR_SLTIU = { 17'b?, 3'b011, 5'b?, OPCODE_OPIMM }; +parameter INSTR_XORI = { 17'b?, 3'b100, 5'b?, OPCODE_OPIMM }; +parameter INSTR_ORI = { 17'b?, 3'b110, 5'b?, OPCODE_OPIMM }; +parameter INSTR_ANDI = { 17'b?, 3'b111, 5'b?, OPCODE_OPIMM }; +parameter INSTR_SLLI = { 7'b0000000, 10'b?, 3'b001, 5'b?, OPCODE_OPIMM }; +parameter INSTR_SRLI = { 7'b0000000, 10'b?, 3'b101, 5'b?, OPCODE_OPIMM }; +parameter INSTR_SRAI = { 7'b0100000, 10'b?, 3'b101, 5'b?, OPCODE_OPIMM }; +// OP +parameter INSTR_ADD = { 7'b0000000, 10'b?, 3'b000, 5'b?, OPCODE_OP }; +parameter INSTR_SUB = { 7'b0100000, 10'b?, 3'b000, 5'b?, OPCODE_OP }; +parameter INSTR_SLL = { 7'b0000000, 10'b?, 3'b001, 5'b?, OPCODE_OP }; +parameter INSTR_SLT = { 7'b0000000, 10'b?, 3'b010, 5'b?, OPCODE_OP }; +parameter INSTR_SLTU = { 7'b0000000, 10'b?, 3'b011, 5'b?, OPCODE_OP }; +parameter INSTR_XOR = { 7'b0000000, 10'b?, 3'b100, 5'b?, OPCODE_OP }; +parameter INSTR_SRL = { 7'b0000000, 10'b?, 3'b101, 5'b?, OPCODE_OP }; +parameter INSTR_SRA = { 7'b0100000, 10'b?, 3'b101, 5'b?, OPCODE_OP }; +parameter INSTR_OR = { 7'b0000000, 10'b?, 3'b110, 5'b?, OPCODE_OP }; +parameter INSTR_AND = { 7'b0000000, 10'b?, 3'b111, 5'b?, OPCODE_OP }; + + +parameter INSTR_FF1 = { 7'b0001000, 5'b0, 5'b?, 3'b000, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_FL1 = { 7'b0001000, 5'b0, 5'b?, 3'b001, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_CLB = { 7'b0001000, 5'b0, 5'b?, 3'b010, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_CNT = { 7'b0001000, 5'b0, 5'b?, 3'b011, 5'b?, OPCODE_OP }; // pulp specific + +parameter INSTR_EXTHS = { 7'b0001000, 10'b?, 3'b100, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_EXTHZ = { 7'b0001000, 10'b?, 3'b101, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_EXTBS = { 7'b0001000, 10'b?, 3'b110, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_EXTBZ = { 7'b0001000, 10'b?, 3'b111, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PAVG = { 7'b0000010, 10'b?, 3'b000, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PAVGU = { 7'b0000010, 10'b?, 3'b001, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PADDN = { 2'b00, 15'b?, 3'b010, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDUN = { 2'b10, 15'b?, 3'b010, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDRN = { 2'b00, 15'b?, 3'b110, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDURN = { 2'b10, 15'b?, 3'b110, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBN = { 2'b00, 15'b?, 3'b011, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBUN = { 2'b10, 15'b?, 3'b011, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBRN = { 2'b00, 15'b?, 3'b111, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBURN = { 2'b10, 15'b?, 3'b111, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDNR = { 2'b01, 15'b?, 3'b010, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDUNR = { 2'b11, 15'b?, 3'b010, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDRNR = { 2'b01, 15'b?, 3'b110, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PADDURNR = { 2'b11, 15'b?, 3'b110, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBNR = { 2'b01, 15'b?, 3'b011, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBUNR = { 2'b11, 15'b?, 3'b011, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBRNR = { 2'b01, 15'b?, 3'b111, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PSUBURNR = { 2'b11, 15'b?, 3'b111, 5'b?, OPCODE_PULP_OP }; // pulp specific + +parameter INSTR_PABS = { 7'b0001010, 10'b?, 3'b000, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PCLIP = { 7'b0001010, 10'b?, 3'b001, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PCLIPU = { 7'b0001010, 10'b?, 3'b010, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PCLIPR = { 7'b0001010, 10'b?, 3'b101, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PCLIPUR = { 7'b0001010, 10'b?, 3'b110, 5'b?, OPCODE_OP }; // pulp specific + +parameter INSTR_PSLET = { 7'b0000010, 10'b?, 3'b010, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PSLETU = { 7'b0000010, 10'b?, 3'b011, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PMIN = { 7'b0000010, 10'b?, 3'b100, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PMINU = { 7'b0000010, 10'b?, 3'b101, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PMAX = { 7'b0000010, 10'b?, 3'b110, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PMAXU = { 7'b0000010, 10'b?, 3'b111, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_ROR = { 7'b0000100, 10'b?, 3'b101, 5'b?, OPCODE_OP }; // pulp specific + +parameter INSTR_PBEXT = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBEXTU = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBINS = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBCLR = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b011, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBSET = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b100, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBREV = { 2'b11, 5'b?, 5'b?, 5'b?, 3'b101, 5'b?, OPCODE_OP }; // pulp specific + + +parameter INSTR_PBEXTR = { 2'b10, 5'b?, 5'b?, 5'b?, 3'b000, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBEXTUR = { 2'b10, 5'b?, 5'b?, 5'b?, 3'b001, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBINSR = { 2'b10, 5'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBCLRR = { 2'b10, 5'b?, 5'b?, 5'b?, 3'b011, 5'b?, OPCODE_OP }; // pulp specific +parameter INSTR_PBSETR = { 2'b10, 5'b?, 5'b?, 5'b?, 3'b100, 5'b?, OPCODE_OP }; // pulp specific + +// FENCE +parameter INSTR_FENCE = { 4'b0, 8'b?, 13'b0, OPCODE_FENCE }; +parameter INSTR_FENCEI = { 17'b0, 3'b001, 5'b0, OPCODE_FENCE }; +// SYSTEM +parameter INSTR_CSRRW = { 17'b?, 3'b001, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_CSRRS = { 17'b?, 3'b010, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_CSRRC = { 17'b?, 3'b011, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_CSRRWI = { 17'b?, 3'b101, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_CSRRSI = { 17'b?, 3'b110, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_CSRRCI = { 17'b?, 3'b111, 5'b?, OPCODE_SYSTEM }; +parameter INSTR_ECALL = { 12'b000000000000, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_EBREAK = { 12'b000000000001, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_URET = { 12'b000000000010, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_SRET = { 12'b000100000010, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_MRET = { 12'b001100000010, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_DRET = { 12'b011110110010, 13'b0, OPCODE_SYSTEM }; +parameter INSTR_WFI = { 12'b000100000101, 13'b0, OPCODE_SYSTEM }; + +// RV32M +parameter INSTR_DIV = { 7'b0000001, 10'b?, 3'b100, 5'b?, OPCODE_OP }; +parameter INSTR_DIVU = { 7'b0000001, 10'b?, 3'b101, 5'b?, OPCODE_OP }; +parameter INSTR_REM = { 7'b0000001, 10'b?, 3'b110, 5'b?, OPCODE_OP }; +parameter INSTR_REMU = { 7'b0000001, 10'b?, 3'b111, 5'b?, OPCODE_OP }; +parameter INSTR_PMUL = { 7'b0000001, 10'b?, 3'b000, 5'b?, OPCODE_OP }; +parameter INSTR_PMUH = { 7'b0000001, 10'b?, 3'b001, 5'b?, OPCODE_OP }; +parameter INSTR_PMULHSU = { 7'b0000001, 10'b?, 3'b010, 5'b?, OPCODE_OP }; +parameter INSTR_PMULHU = { 7'b0000001, 10'b?, 3'b011, 5'b?, OPCODE_OP }; +parameter INSTR_PMAC = { 7'b0100001, 10'b?, 3'b000, 5'b?, OPCODE_OP }; +parameter INSTR_PMSU = { 7'b0100001, 10'b?, 3'b001, 5'b?, OPCODE_OP }; + +//PULP MUL +parameter INSTR_PMULS = { 2'b10, 5'b? ,10'b?, 3'b000, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULHLSN = { 2'b11, 5'b?, 10'b?, 3'b000, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULRS = { 2'b10, 5'b? ,10'b?, 3'b100, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULRHLSN = { 2'b11, 5'b?, 10'b?, 3'b100, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULU = { 2'b00, 5'b? ,10'b?, 3'b000, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULUHLU = { 2'b01, 5'b? ,10'b?, 3'b000, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULRU = { 2'b00, 5'b? ,10'b?, 3'b100, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMULRUHLU = { 2'b01, 5'b? ,10'b?, 3'b100, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACS = { 2'b10, 5'b? ,10'b?, 3'b001, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACHLSN = { 2'b11, 5'b?, 10'b?, 3'b001, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACRS = { 2'b10, 5'b? ,10'b?, 3'b101, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACRHLSN = { 2'b11, 5'b?, 10'b?, 3'b101, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACU = { 2'b00, 5'b? ,10'b?, 3'b001, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACUHLU = { 2'b01, 5'b? ,10'b?, 3'b001, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACRU = { 2'b00, 5'b? ,10'b?, 3'b101, 5'b?, OPCODE_PULP_OP }; // pulp specific +parameter INSTR_PMACRUHLU = { 2'b01, 5'b? ,10'b?, 3'b101, 5'b?, OPCODE_PULP_OP }; // pulp specific + +// RV32F +parameter INSTR_FMADD = { 5'b?, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FMADD }; +parameter INSTR_FMSUB = { 5'b?, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FMSUB }; +parameter INSTR_FNMSUB = { 5'b?, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FNMSUB }; +parameter INSTR_FNMADD = { 5'b?, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FNMADD }; + +parameter INSTR_FADD = { 5'b00000, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FSUB = { 5'b00001, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FMUL = { 5'b00010, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FDIV = { 5'b00011, 2'b00, 10'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FSQRT = { 5'b01011, 2'b00, 5'b0, 5'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FSGNJS = { 5'b00100, 2'b00, 10'b?, 3'b000, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FSGNJNS = { 5'b00100, 2'b00, 10'b?, 3'b001, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FSGNJXS = { 5'b00100, 2'b00, 10'b?, 3'b010, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FMIN = { 5'b00101, 2'b00, 10'b?, 3'b000, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FMAX = { 5'b00101, 2'b00, 10'b?, 3'b001, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FCVTWS = { 5'b11000, 2'b00, 5'b0, 5'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FCVTWUS = { 5'b11000, 2'b00, 5'b1, 5'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FMVXS = { 5'b11100, 2'b00, 5'b0, 5'b?, 3'b000, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FEQS = { 5'b10100, 2'b00, 10'b?, 3'b010, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FLTS = { 5'b10100, 2'b00, 10'b?, 3'b001, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FLES = { 5'b10100, 2'b00, 10'b?, 3'b000, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FCLASS = { 5'b11100, 2'b00, 5'b0, 5'b?, 3'b001, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FCVTSW = { 5'b11010, 2'b00, 5'b0, 5'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FCVTSWU = { 5'b11010, 2'b00, 5'b1, 5'b?, 3'b?, 5'b?, OPCODE_OP_FP }; +parameter INSTR_FMVSX = { 5'b11110, 2'b00, 5'b0, 5'b?, 3'b000, 5'b?, OPCODE_OP_FP }; + +// RV32A +parameter INSTR_LR = { AMO_LR , 2'b?, 5'b0, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_SC = { AMO_SC , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOSWAP = { AMO_SWAP, 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOADD = { AMO_ADD , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOXOR = { AMO_XOR , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOAND = { AMO_AND , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOOR = { AMO_OR , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOMIN = { AMO_MIN , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOMAX = { AMO_MAX , 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOMINU = { AMO_MINU, 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; +parameter INSTR_AMOMAXU = { AMO_MAXU, 2'b?, 5'b?, 5'b?, 3'b010, 5'b?, OPCODE_AMO }; + +// to be used in tracer! + +endpackage diff --git a/hw/deps/riscv/riscv_L0_buffer.sv b/hw/deps/riscv/riscv_L0_buffer.sv new file mode 100644 index 0000000..4a2903a --- /dev/null +++ b/hw/deps/riscv/riscv_L0_buffer.sv @@ -0,0 +1,282 @@ +// Copyright 2018 ETH Zurich and 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. + +module riscv_L0_buffer +#( + parameter RDATA_IN_WIDTH = 128 +) +( + input logic clk, + input logic rst_n, + + input logic prefetch_i, + input logic [31:0] prefetch_addr_i, + + input logic branch_i, + input logic [31:0] branch_addr_i, + + input logic hwlp_i, + input logic [31:0] hwlp_addr_i, + + + output logic fetch_gnt_o, + output logic fetch_valid_o, + + output logic valid_o, + output logic [RDATA_IN_WIDTH/32-1:0][31:0] rdata_o, + output logic [31:0] addr_o, + + // goes to instruction memory / instruction cache + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [RDATA_IN_WIDTH/32-1:0][31:0] instr_rdata_i, + + output logic busy_o +); + + enum logic [2:0] { EMPTY, VALID_L0, WAIT_GNT, WAIT_RVALID, ABORTED_BRANCH, WAIT_HWLOOP } CS, NS; + + logic [3:0][31:0] L0_buffer; + logic [31:0] addr_q, instr_addr_int; + logic valid; + // logic fetch_gnt_int, send_rvalid_int; + // logic fetch_valid_int; + + ////////////////////////////////////////////////////////////////////////////// + // FSM + ////////////////////////////////////////////////////////////////////////////// + + always_comb + begin + NS = CS; + valid = 1'b0; + instr_req_o = 1'b0; + instr_addr_int = '0; + fetch_valid_o = 1'b0; + //fetch_gnt_int = 1'b0; + //send_rvalid_int = 1'b0; + + case(CS) + + // wait for the first branch request before fetching any instructions + EMPTY: + begin + if (branch_i) + instr_addr_int = branch_addr_i; + else if (hwlp_i) + instr_addr_int = hwlp_addr_i; + else + instr_addr_int = prefetch_addr_i; + + if (branch_i | hwlp_i | prefetch_i) // make the request to icache + begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end + end //~EMPTY + + WAIT_GNT: + begin + if (branch_i) + instr_addr_int = branch_addr_i; + else if (hwlp_i) + instr_addr_int = hwlp_addr_i; + else + instr_addr_int = addr_q; + + if (branch_i) + begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end + else + begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end + end //~WAIT_GNT + + + WAIT_RVALID: + begin + valid = instr_rvalid_i; + + if (branch_i) + instr_addr_int = branch_addr_i; + else if (hwlp_i) + instr_addr_int = hwlp_addr_i; + else + instr_addr_int = prefetch_addr_i; + + if (branch_i) + begin + if (instr_rvalid_i) + begin + fetch_valid_o = 1'b1; + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end else begin + NS = ABORTED_BRANCH; // TODO: THIS STATE IS IDENTICAL WITH THIS ONE + end + + end + else + begin + + if (instr_rvalid_i) + begin + fetch_valid_o = 1'b1; + + if (prefetch_i | hwlp_i) // we are receiving the last packet, then prefetch the next one + begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end + else // not the last chunk + begin + NS = VALID_L0; + end + end + end + end //~WAIT_RVALID + + VALID_L0: + begin + valid = 1'b1; + //fetch_valid_o = fetch_valid_int; + + if (branch_i) + instr_addr_int = branch_addr_i; + else if (hwlp_i) + instr_addr_int = hwlp_addr_i; + else + instr_addr_int = prefetch_addr_i; + + if (branch_i | hwlp_i | prefetch_i) + begin + + //if(instr_addr_int[31:4] != addr_q[31:4]) + //begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + //end + // else + // begin + // // Cache line is already in the L0 BUFFER, NO NEED TO prefetch + // instr_req_o = 1'b0; + // fetch_gnt_int = 1'b1; // Grant the Loop or the prefetcher + // send_rvalid_int = 1'b1; // data is ready! + // NS = VALID_L0; + // end + + end + end //~VALID_L0 + + ABORTED_BRANCH: + begin + + // prepare address even if we don't need it + // this removes the dependency for instr_addr_o on instr_rvalid_i + if (branch_i) + instr_addr_int = branch_addr_i; + else + instr_addr_int = addr_q; + + if (instr_rvalid_i) + begin + instr_req_o = 1'b1; + + if (instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end + end //~ABORTED_BRANCH + + default: + begin + NS = EMPTY; + end + endcase //~CS + end + + + ////////////////////////////////////////////////////////////////////////////// + // registers + ////////////////////////////////////////////////////////////////////////////// + + always_ff @(posedge clk, negedge rst_n) + begin + if (~rst_n) + begin + CS <= EMPTY; + L0_buffer <= '0; + addr_q <= '0; + //fetch_valid_int <= '0; + end + else + begin + CS <= NS; + + //fetch_valid_int <= send_rvalid_int; + + if (instr_rvalid_i) + begin + L0_buffer <= instr_rdata_i; + end + + if (branch_i | hwlp_i | prefetch_i) + addr_q <= instr_addr_int; + end + end + + + ////////////////////////////////////////////////////////////////////////////// + // output ports + ////////////////////////////////////////////////////////////////////////////// + + assign instr_addr_o = { instr_addr_int[31:4], 4'b0000 }; + + assign rdata_o = (instr_rvalid_i) ? instr_rdata_i : L0_buffer; + assign addr_o = addr_q; + + assign valid_o = valid & (~branch_i); + + assign busy_o = (CS != EMPTY) && (CS != VALID_L0) || instr_req_o; + + assign fetch_gnt_o = instr_gnt_i /*| fetch_gnt_int*/; + +endmodule \ No newline at end of file diff --git a/hw/deps/riscv/riscv_alu.sv b/hw/deps/riscv/riscv_alu.sv new file mode 100644 index 0000000..3ddbdc8 --- /dev/null +++ b/hw/deps/riscv/riscv_alu.sv @@ -0,0 +1,1155 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Matthias Baer - baermatt@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Andreas Traber - atraber@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: ALU // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Arithmetic logic unit of the pipelined processor // +// supports FP-comparisons, classifications if FPU is defined // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; + +module riscv_alu +#( + parameter SHARED_INT_DIV = 0, + parameter FPU = 0 +)( + input logic clk, + input logic rst_n, + input logic enable_i, + input logic [ALU_OP_WIDTH-1:0] operator_i, + input logic [31:0] operand_a_i, + input logic [31:0] operand_b_i, + input logic [31:0] operand_c_i, + + input logic [ 1:0] vector_mode_i, + input logic [ 4:0] bmask_a_i, + input logic [ 4:0] bmask_b_i, + input logic [ 1:0] imm_vec_ext_i, + + input logic is_clpx_i, + input logic is_subrot_i, + input logic [ 1:0] clpx_shift_i, + + output logic [31:0] result_o, + output logic comparison_result_o, + + output logic ready_o, + input logic ex_ready_i +); + + + logic [31:0] operand_a_rev; + logic [31:0] operand_a_neg; + logic [31:0] operand_a_neg_rev; + + assign operand_a_neg = ~operand_a_i; + + // bit reverse operand_a for left shifts and bit counting + generate + genvar k; + for(k = 0; k < 32; k++) + begin + assign operand_a_rev[k] = operand_a_i[31-k]; + end + endgenerate + + // bit reverse operand_a_neg for left shifts and bit counting + generate + genvar m; + for(m = 0; m < 32; m++) + begin + assign operand_a_neg_rev[m] = operand_a_neg[31-m]; + end + endgenerate + + logic [31:0] operand_b_neg; + + assign operand_b_neg = ~operand_b_i; + + + logic [5:0] div_shift; + logic div_valid; + logic [31:0] bmask; + + ////////////////////////////////////////////////////////////////////////////////////////// + // ____ _ _ _ _ _ _ _ _ // + // | _ \ __ _ _ __| |_(_) |_(_) ___ _ __ ___ __| | / \ __| | __| | ___ _ __ // + // | |_) / _` | '__| __| | __| |/ _ \| '_ \ / _ \/ _` | / _ \ / _` |/ _` |/ _ \ '__| // + // | __/ (_| | | | |_| | |_| | (_) | | | | __/ (_| | / ___ \ (_| | (_| | __/ | // + // |_| \__,_|_| \__|_|\__|_|\___/|_| |_|\___|\__,_| /_/ \_\__,_|\__,_|\___|_| // + // // + ////////////////////////////////////////////////////////////////////////////////////////// + + logic adder_op_b_negate; + logic [31:0] adder_op_a, adder_op_b; + logic [35:0] adder_in_a, adder_in_b; + logic [31:0] adder_result; + logic [36:0] adder_result_expanded; + + + assign adder_op_b_negate = (operator_i == ALU_SUB) || (operator_i == ALU_SUBR) || + (operator_i == ALU_SUBU) || (operator_i == ALU_SUBUR) || is_subrot_i; + + // prepare operand a + assign adder_op_a = (operator_i == ALU_ABS) ? operand_a_neg : ( is_subrot_i ? {operand_b_i[15:0], operand_a_i[31:16]} : operand_a_i ); + + // prepare operand b + assign adder_op_b = adder_op_b_negate ? ( is_subrot_i ? ~{operand_a_i[15:0], operand_b_i[31:16]} : operand_b_neg ) : operand_b_i; + + // prepare carry + always_comb + begin + adder_in_a[ 0] = 1'b1; + adder_in_a[ 8: 1] = adder_op_a[ 7: 0]; + adder_in_a[ 9] = 1'b1; + adder_in_a[17:10] = adder_op_a[15: 8]; + adder_in_a[ 18] = 1'b1; + adder_in_a[26:19] = adder_op_a[23:16]; + adder_in_a[ 27] = 1'b1; + adder_in_a[35:28] = adder_op_a[31:24]; + + adder_in_b[ 0] = 1'b0; + adder_in_b[ 8: 1] = adder_op_b[ 7: 0]; + adder_in_b[ 9] = 1'b0; + adder_in_b[17:10] = adder_op_b[15: 8]; + adder_in_b[ 18] = 1'b0; + adder_in_b[26:19] = adder_op_b[23:16]; + adder_in_b[ 27] = 1'b0; + adder_in_b[35:28] = adder_op_b[31:24]; + + if (adder_op_b_negate || (operator_i == ALU_ABS || operator_i == ALU_CLIP)) begin + // special case for subtractions and absolute number calculations + adder_in_b[0] = 1'b1; + + case (vector_mode_i) + VEC_MODE16: begin + adder_in_b[18] = 1'b1; + end + + VEC_MODE8: begin + adder_in_b[ 9] = 1'b1; + adder_in_b[18] = 1'b1; + adder_in_b[27] = 1'b1; + end + endcase + + end else begin + // take care of partitioning the adder for the addition case + case (vector_mode_i) + VEC_MODE16: begin + adder_in_a[18] = 1'b0; + end + + VEC_MODE8: begin + adder_in_a[ 9] = 1'b0; + adder_in_a[18] = 1'b0; + adder_in_a[27] = 1'b0; + end + endcase + end + end + + // actual adder + assign adder_result_expanded = $signed(adder_in_a) + $signed(adder_in_b); + assign adder_result = {adder_result_expanded[35:28], + adder_result_expanded[26:19], + adder_result_expanded[17:10], + adder_result_expanded[8:1]}; + + + // normalization stage + logic [31:0] adder_round_value; + logic [31:0] adder_round_result; + + assign adder_round_value = ((operator_i == ALU_ADDR) || (operator_i == ALU_SUBR) || + (operator_i == ALU_ADDUR) || (operator_i == ALU_SUBUR)) ? + {1'b0, bmask[31:1]} : '0; + assign adder_round_result = adder_result + adder_round_value; + + + //////////////////////////////////////// + // ____ _ _ ___ _____ _____ // + // / ___|| | | |_ _| ___|_ _| // + // \___ \| |_| || || |_ | | // + // ___) | _ || || _| | | // + // |____/|_| |_|___|_| |_| // + // // + //////////////////////////////////////// + + logic shift_left; // should we shift left + logic shift_use_round; + logic shift_arithmetic; + + logic [31:0] shift_amt_left; // amount of shift, if to the left + logic [31:0] shift_amt; // amount of shift, to the right + logic [31:0] shift_amt_int; // amount of shift, used for the actual shifters + logic [31:0] shift_amt_norm; // amount of shift, used for normalization + logic [31:0] shift_op_a; // input of the shifter + logic [31:0] shift_result; + logic [31:0] shift_right_result; + logic [31:0] shift_left_result; + logic [15:0] clpx_shift_ex; + + // shifter is also used for preparing operand for division + assign shift_amt = div_valid ? div_shift : operand_b_i; + + // by reversing the bits of the input, we also have to reverse the order of shift amounts + always_comb + begin + case(vector_mode_i) + VEC_MODE16: + begin + shift_amt_left[15: 0] = shift_amt[31:16]; + shift_amt_left[31:16] = shift_amt[15: 0]; + end + + VEC_MODE8: + begin + shift_amt_left[ 7: 0] = shift_amt[31:24]; + shift_amt_left[15: 8] = shift_amt[23:16]; + shift_amt_left[23:16] = shift_amt[15: 8]; + shift_amt_left[31:24] = shift_amt[ 7: 0]; + end + + default: // VEC_MODE32 + begin + shift_amt_left[31: 0] = shift_amt[31: 0]; + end + endcase + end + + // ALU_FL1 and ALU_CBL are used for the bit counting ops later + assign shift_left = (operator_i == ALU_SLL) || (operator_i == ALU_BINS) || + (operator_i == ALU_FL1) || (operator_i == ALU_CLB) || + (operator_i == ALU_DIV) || (operator_i == ALU_DIVU) || + (operator_i == ALU_REM) || (operator_i == ALU_REMU) || + (operator_i == ALU_BREV); + + assign shift_use_round = (operator_i == ALU_ADD) || (operator_i == ALU_SUB) || + (operator_i == ALU_ADDR) || (operator_i == ALU_SUBR) || + (operator_i == ALU_ADDU) || (operator_i == ALU_SUBU) || + (operator_i == ALU_ADDUR) || (operator_i == ALU_SUBUR); + + assign shift_arithmetic = (operator_i == ALU_SRA) || (operator_i == ALU_BEXT) || + (operator_i == ALU_ADD) || (operator_i == ALU_SUB) || + (operator_i == ALU_ADDR) || (operator_i == ALU_SUBR); + + // choose the bit reversed or the normal input for shift operand a + assign shift_op_a = shift_left ? operand_a_rev : + (shift_use_round ? adder_round_result : operand_a_i); + assign shift_amt_int = shift_use_round ? shift_amt_norm : + (shift_left ? shift_amt_left : shift_amt); + + assign shift_amt_norm = is_clpx_i ? {clpx_shift_ex,clpx_shift_ex} : {4{3'b000, bmask_b_i}}; + + assign clpx_shift_ex = $unsigned(clpx_shift_i); + + // right shifts, we let the synthesizer optimize this + logic [63:0] shift_op_a_32; + + assign shift_op_a_32 = (operator_i == ALU_ROR) ? {shift_op_a, shift_op_a} : $signed({ {32{shift_arithmetic & shift_op_a[31]}}, shift_op_a}); + + always_comb + begin + case(vector_mode_i) + VEC_MODE16: + begin + shift_right_result[31:16] = $signed( {shift_arithmetic & shift_op_a[31], shift_op_a[31:16] }) >>> shift_amt_int[19:16]; + shift_right_result[15: 0] = $signed( {shift_arithmetic & shift_op_a[15], shift_op_a[15: 0] }) >>> shift_amt_int[ 3: 0]; + end + + VEC_MODE8: + begin + shift_right_result[31:24] = $signed( {shift_arithmetic & shift_op_a[31], shift_op_a[31:24] }) >>> shift_amt_int[26:24]; + shift_right_result[23:16] = $signed( {shift_arithmetic & shift_op_a[23], shift_op_a[23:16] }) >>> shift_amt_int[18:16]; + shift_right_result[15: 8] = $signed( {shift_arithmetic & shift_op_a[15], shift_op_a[15: 8] }) >>> shift_amt_int[10: 8]; + shift_right_result[ 7: 0] = $signed( {shift_arithmetic & shift_op_a[ 7], shift_op_a[ 7: 0] }) >>> shift_amt_int[ 2: 0]; + end + + default: // VEC_MODE32 + begin + shift_right_result = shift_op_a_32 >> shift_amt_int[4:0]; + end + endcase; // case (vec_mode_i) + end + + // bit reverse the shift_right_result for left shifts + genvar j; + generate + for(j = 0; j < 32; j++) + begin + assign shift_left_result[j] = shift_right_result[31-j]; + end + endgenerate + + assign shift_result = shift_left ? shift_left_result : shift_right_result; + + + ////////////////////////////////////////////////////////////////// + // ____ ___ __ __ ____ _ ____ ___ ____ ___ _ _ // + // / ___/ _ \| \/ | _ \ / \ | _ \|_ _/ ___| / _ \| \ | | // + // | | | | | | |\/| | |_) / _ \ | |_) || |\___ \| | | | \| | // + // | |__| |_| | | | | __/ ___ \| _ < | | ___) | |_| | |\ | // + // \____\___/|_| |_|_| /_/ \_\_| \_\___|____/ \___/|_| \_| // + // // + ////////////////////////////////////////////////////////////////// + + logic [3:0] is_equal; + logic [3:0] is_greater; // handles both signed and unsigned forms + logic [3:0] f_is_greater; // for floats, only signed and *no vectors*, + // inverted for two negative numbers + + // 8-bit vector comparisons, basic building blocks + logic [3:0] cmp_signed; + logic [3:0] is_equal_vec; + logic [3:0] is_greater_vec; + logic [31:0] operand_b_eq; + logic is_equal_clip; + + + //second == comparator for CLIP instructions + always_comb + begin + operand_b_eq = operand_b_neg; + if(operator_i == ALU_CLIPU) + operand_b_eq = '0; + else + operand_b_eq = operand_b_neg; + end + assign is_equal_clip = operand_a_i == operand_b_eq; + + always_comb + begin + cmp_signed = 4'b0; + + unique case (operator_i) + ALU_GTS, + ALU_GES, + ALU_LTS, + ALU_LES, + ALU_SLTS, + ALU_SLETS, + ALU_MIN, + ALU_MAX, + ALU_ABS, + ALU_CLIP, + ALU_CLIPU, + ALU_FLE, + ALU_FLT, + ALU_FMAX, + ALU_FMIN: begin + case (vector_mode_i) + VEC_MODE8: cmp_signed[3:0] = 4'b1111; + VEC_MODE16: cmp_signed[3:0] = 4'b1010; + default: cmp_signed[3:0] = 4'b1000; + endcase + end + + default:; + endcase + end + + // generate vector equal and greater than signals, cmp_signed decides if the + // comparison is done signed or unsigned + genvar i; + generate + for(i = 0; i < 4; i++) + begin + assign is_equal_vec[i] = (operand_a_i[8*i+7:8*i] == operand_b_i[8*i+7:i*8]); + assign is_greater_vec[i] = $signed({operand_a_i[8*i+7] & cmp_signed[i], operand_a_i[8*i+7:8*i]}) + > + $signed({operand_b_i[8*i+7] & cmp_signed[i], operand_b_i[8*i+7:i*8]}); + end + endgenerate + + // generate the real equal and greater than signals that take the vector + // mode into account + always_comb + begin + // 32-bit mode + is_equal[3:0] = {4{is_equal_vec[3] & is_equal_vec[2] & is_equal_vec[1] & is_equal_vec[0]}}; + is_greater[3:0] = {4{is_greater_vec[3] | (is_equal_vec[3] & (is_greater_vec[2] + | (is_equal_vec[2] & (is_greater_vec[1] + | (is_equal_vec[1] & (is_greater_vec[0]))))))}}; + + case(vector_mode_i) + VEC_MODE16: + begin + is_equal[1:0] = {2{is_equal_vec[0] & is_equal_vec[1]}}; + is_equal[3:2] = {2{is_equal_vec[2] & is_equal_vec[3]}}; + is_greater[1:0] = {2{is_greater_vec[1] | (is_equal_vec[1] & is_greater_vec[0])}}; + is_greater[3:2] = {2{is_greater_vec[3] | (is_equal_vec[3] & is_greater_vec[2])}}; + end + + VEC_MODE8: + begin + is_equal[3:0] = is_equal_vec[3:0]; + is_greater[3:0] = is_greater_vec[3:0]; + end + + default:; // see default assignment + endcase + end + + // generate the floating point greater signal, inverted for two negative numbers + // (but not for identical numbers) + assign f_is_greater[3:0] = {4{is_greater[3] ^ (operand_a_i[31] & operand_b_i[31] & !is_equal[3])}}; + + // generate comparison result + logic [3:0] cmp_result; + logic f_is_qnan; + logic f_is_snan; + logic [3:0] f_is_nan; + + always_comb + begin + cmp_result = is_equal; + f_is_nan = {4{(f_is_qnan | f_is_snan)}}; + unique case (operator_i) + ALU_EQ: cmp_result = is_equal; + ALU_NE: cmp_result = ~is_equal; + ALU_GTS, ALU_GTU: cmp_result = is_greater; + ALU_GES, ALU_GEU: cmp_result = is_greater | is_equal; + ALU_LTS, ALU_SLTS, + ALU_LTU, ALU_SLTU: cmp_result = ~(is_greater | is_equal); + ALU_SLETS, + ALU_SLETU, + ALU_LES, ALU_LEU: cmp_result = ~is_greater; + ALU_FEQ: cmp_result = is_equal & ~f_is_nan; + ALU_FLE: cmp_result = ~f_is_greater & ~f_is_nan; + ALU_FLT: cmp_result = ~(f_is_greater | is_equal) & ~f_is_nan; + + default: ; + endcase + end + + assign comparison_result_o = cmp_result[3]; + + + // min/max/abs handling + logic [31:0] result_minmax; + logic [31:0] fp_canonical_nan; + logic [ 3:0] sel_minmax; + logic do_min; + logic minmax_is_fp_special; + logic [31:0] minmax_b; + + assign minmax_b = (operator_i == ALU_ABS) ? adder_result : operand_b_i; + + assign do_min = (operator_i == ALU_MIN) || (operator_i == ALU_MINU) || + (operator_i == ALU_CLIP) || (operator_i == ALU_CLIPU) || + (operator_i == ALU_FMIN); + + assign sel_minmax[3:0] = ((operator_i == ALU_FMIN || operator_i == ALU_FMAX) ? f_is_greater : is_greater) ^ {4{do_min}}; + + assign result_minmax[31:24] = (sel_minmax[3] == 1'b1) ? operand_a_i[31:24] : minmax_b[31:24]; + assign result_minmax[23:16] = (sel_minmax[2] == 1'b1) ? operand_a_i[23:16] : minmax_b[23:16]; + assign result_minmax[15: 8] = (sel_minmax[1] == 1'b1) ? operand_a_i[15: 8] : minmax_b[15: 8]; + assign result_minmax[ 7: 0] = (sel_minmax[0] == 1'b1) ? operand_a_i[ 7: 0] : minmax_b[ 7: 0]; + + ////////////////////////////////////////////////// + // Float classification + ////////////////////////////////////////////////// + logic [31:0] fclass_result; + + if (FPU == 1) begin + logic [7:0] fclass_exponent; + logic [22:0] fclass_mantiassa; + logic fclass_ninf; + logic fclass_pinf; + logic fclass_normal; + logic fclass_subnormal; + logic fclass_nzero; + logic fclass_pzero; + logic fclass_is_negative; + logic fclass_snan_a; + logic fclass_qnan_a; + logic fclass_snan_b; + logic fclass_qnan_b; + + assign fclass_exponent = operand_a_i[30:23]; + assign fclass_mantiassa = operand_a_i[22:0]; + assign fclass_is_negative = operand_a_i[31]; + + assign fclass_ninf = operand_a_i == 32'hFF800000; + assign fclass_pinf = operand_a_i == 32'h7F800000; + assign fclass_normal = fclass_exponent != 0 && fclass_exponent != 255; + assign fclass_subnormal = fclass_exponent == 0 && fclass_mantiassa != 0; + assign fclass_nzero = operand_a_i == 32'h80000000; + assign fclass_pzero = operand_a_i == 32'h00000000; + assign fclass_snan_a = operand_a_i[30:0] == 32'h7fa00000; + assign fclass_qnan_a = operand_a_i[30:0] == 32'h7fc00000; + assign fclass_snan_b = operand_b_i[30:0] == 32'h7fa00000; + assign fclass_qnan_b = operand_b_i[30:0] == 32'h7fc00000; + + assign fclass_result[31:0] = {{22{1'b0}}, + fclass_qnan_a, + fclass_snan_a, + fclass_pinf, + (fclass_normal && !fclass_is_negative), + (fclass_subnormal && !fclass_is_negative), + fclass_pzero, + fclass_nzero, + (fclass_subnormal && fclass_is_negative), + (fclass_normal && fclass_is_negative), + fclass_ninf}; + + + // float special cases + assign f_is_qnan = fclass_qnan_a | fclass_qnan_b; + assign f_is_snan = fclass_snan_a | fclass_snan_b; + + assign minmax_is_fp_special = (operator_i == ALU_FMIN || operator_i == ALU_FMAX) & (f_is_snan | f_is_qnan); + assign fp_canonical_nan = 32'h7fc00000; + end else begin // (FPU == 0) + assign minmax_is_fp_special = '0; + assign f_is_qnan = '0; + assign f_is_snan = '0; + assign fclass_result = '0; + assign fp_canonical_nan = '0; + end + + + ////////////////////////////////////////////////// + // Float sign injection + ////////////////////////////////////////////////// + logic [31:0] f_sign_inject_result; + + + always_comb + begin + if (FPU == 1) begin + f_sign_inject_result[30:0] = operand_a_i[30:0]; + f_sign_inject_result[31] = operand_a_i[31]; + + unique case(operator_i) + ALU_FKEEP: f_sign_inject_result[31] = operand_a_i[31]; + ALU_FSGNJ: f_sign_inject_result[31] = operand_b_i[31]; + ALU_FSGNJN: f_sign_inject_result[31] = !operand_b_i[31]; + ALU_FSGNJX: f_sign_inject_result[31] = operand_a_i[31] ^ operand_b_i[31]; + default: ; + endcase + end + else + f_sign_inject_result = '0; + end + + ////////////////////////////////////////////////// + // Clip + ////////////////////////////////////////////////// + logic [31:0] clip_result; // result of clip and clip + + always_comb + begin + clip_result = result_minmax; + if(operator_i == ALU_CLIPU) begin + if(operand_a_i[31] || is_equal_clip) begin + clip_result = '0; + end else begin + clip_result = result_minmax; + end + end else begin + //CLIP + if(adder_result_expanded[36] || is_equal_clip) begin + clip_result = operand_b_neg; + end else begin + clip_result = result_minmax; + end + end + + end + + ////////////////////////////////////////////////// + // ____ _ _ _ _ _____ _____ _ _____ // + // / ___|| | | | | | | ___| ___| | | ____| // + // \___ \| |_| | | | | |_ | |_ | | | _| // + // ___) | _ | |_| | _| | _| | |___| |___ // + // |____/|_| |_|\___/|_| |_| |_____|_____| // + // // + ////////////////////////////////////////////////// + + logic [ 3: 0][1:0] shuffle_byte_sel; // select byte in register: 31:24, 23:16, 15:8, 7:0 + logic [ 3: 0] shuffle_reg_sel; // select register: rD/rS2 or rS1 + logic [ 1: 0] shuffle_reg1_sel; // select register rD or rS2 for next stage + logic [ 1: 0] shuffle_reg0_sel; + logic [ 3: 0] shuffle_through; + + logic [31: 0] shuffle_r1, shuffle_r0; + logic [31: 0] shuffle_r1_in, shuffle_r0_in; + logic [31: 0] shuffle_result; + logic [31: 0] pack_result; + + + always_comb + begin + shuffle_reg_sel = '0; + shuffle_reg1_sel = 2'b01; + shuffle_reg0_sel = 2'b10; + shuffle_through = '1; + + unique case(operator_i) + ALU_EXT, ALU_EXTS: begin + if (operator_i == ALU_EXTS) + shuffle_reg1_sel = 2'b11; + + if (vector_mode_i == VEC_MODE8) begin + shuffle_reg_sel[3:1] = 3'b111; + shuffle_reg_sel[0] = 1'b0; + end else begin + shuffle_reg_sel[3:2] = 2'b11; + shuffle_reg_sel[1:0] = 2'b00; + end + end + + ALU_PCKLO: begin + shuffle_reg1_sel = 2'b00; + + if (vector_mode_i == VEC_MODE8) begin + shuffle_through = 4'b0011; + shuffle_reg_sel = 4'b0001; + end else begin + shuffle_reg_sel = 4'b0011; + end + end + + ALU_PCKHI: begin + shuffle_reg1_sel = 2'b00; + + if (vector_mode_i == VEC_MODE8) begin + shuffle_through = 4'b1100; + shuffle_reg_sel = 4'b0100; + end else begin + shuffle_reg_sel = 4'b0011; + end + end + + ALU_SHUF2: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_reg_sel[3] = ~operand_b_i[26]; + shuffle_reg_sel[2] = ~operand_b_i[18]; + shuffle_reg_sel[1] = ~operand_b_i[10]; + shuffle_reg_sel[0] = ~operand_b_i[ 2]; + end + + VEC_MODE16: begin + shuffle_reg_sel[3] = ~operand_b_i[17]; + shuffle_reg_sel[2] = ~operand_b_i[17]; + shuffle_reg_sel[1] = ~operand_b_i[ 1]; + shuffle_reg_sel[0] = ~operand_b_i[ 1]; + end + default:; + endcase + end + + ALU_INS: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_reg0_sel = 2'b00; + unique case (imm_vec_ext_i) + 2'b00: begin + shuffle_reg_sel[3:0] = 4'b1110; + end + 2'b01: begin + shuffle_reg_sel[3:0] = 4'b1101; + end + 2'b10: begin + shuffle_reg_sel[3:0] = 4'b1011; + end + 2'b11: begin + shuffle_reg_sel[3:0] = 4'b0111; + end + default:; + endcase + end + VEC_MODE16: begin + shuffle_reg0_sel = 2'b01; + shuffle_reg_sel[3] = ~imm_vec_ext_i[ 0]; + shuffle_reg_sel[2] = ~imm_vec_ext_i[ 0]; + shuffle_reg_sel[1] = imm_vec_ext_i[ 0]; + shuffle_reg_sel[0] = imm_vec_ext_i[ 0]; + end + default:; + endcase + end + + default:; + endcase + end + + always_comb + begin + shuffle_byte_sel = '0; + + // byte selector + unique case (operator_i) + ALU_EXTS, + ALU_EXT: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_byte_sel[3] = imm_vec_ext_i[1:0]; + shuffle_byte_sel[2] = imm_vec_ext_i[1:0]; + shuffle_byte_sel[1] = imm_vec_ext_i[1:0]; + shuffle_byte_sel[0] = imm_vec_ext_i[1:0]; + end + + VEC_MODE16: begin + shuffle_byte_sel[3] = {imm_vec_ext_i[0], 1'b1}; + shuffle_byte_sel[2] = {imm_vec_ext_i[0], 1'b1}; + shuffle_byte_sel[1] = {imm_vec_ext_i[0], 1'b1}; + shuffle_byte_sel[0] = {imm_vec_ext_i[0], 1'b0}; + end + + default:; + endcase + end + + ALU_PCKLO: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_byte_sel[3] = 2'b00; + shuffle_byte_sel[2] = 2'b00; + shuffle_byte_sel[1] = 2'b00; + shuffle_byte_sel[0] = 2'b00; + end + + VEC_MODE16: begin + shuffle_byte_sel[3] = 2'b01; + shuffle_byte_sel[2] = 2'b00; + shuffle_byte_sel[1] = 2'b01; + shuffle_byte_sel[0] = 2'b00; + end + + default:; + endcase + end + + ALU_PCKHI: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_byte_sel[3] = 2'b00; + shuffle_byte_sel[2] = 2'b00; + shuffle_byte_sel[1] = 2'b00; + shuffle_byte_sel[0] = 2'b00; + end + + VEC_MODE16: begin + shuffle_byte_sel[3] = 2'b11; + shuffle_byte_sel[2] = 2'b10; + shuffle_byte_sel[1] = 2'b11; + shuffle_byte_sel[0] = 2'b10; + end + + default:; + endcase + end + + ALU_SHUF2, + ALU_SHUF: begin + unique case (vector_mode_i) + VEC_MODE8: begin + shuffle_byte_sel[3] = operand_b_i[25:24]; + shuffle_byte_sel[2] = operand_b_i[17:16]; + shuffle_byte_sel[1] = operand_b_i[ 9: 8]; + shuffle_byte_sel[0] = operand_b_i[ 1: 0]; + end + + VEC_MODE16: begin + shuffle_byte_sel[3] = {operand_b_i[16], 1'b1}; + shuffle_byte_sel[2] = {operand_b_i[16], 1'b0}; + shuffle_byte_sel[1] = {operand_b_i[ 0], 1'b1}; + shuffle_byte_sel[0] = {operand_b_i[ 0], 1'b0}; + end + default:; + endcase + end + + ALU_INS: begin + shuffle_byte_sel[3] = 2'b11; + shuffle_byte_sel[2] = 2'b10; + shuffle_byte_sel[1] = 2'b01; + shuffle_byte_sel[0] = 2'b00; + end + + default:; + endcase + end + + assign shuffle_r0_in = shuffle_reg0_sel[1] ? + operand_a_i : + (shuffle_reg0_sel[0] ? {2{operand_a_i[15:0]}} : {4{operand_a_i[7:0]}}); + + assign shuffle_r1_in = shuffle_reg1_sel[1] ? + {{8{operand_a_i[31]}}, {8{operand_a_i[23]}}, {8{operand_a_i[15]}}, {8{operand_a_i[7]}}} : + (shuffle_reg1_sel[0] ? operand_c_i : operand_b_i); + + assign shuffle_r0[31:24] = shuffle_byte_sel[3][1] ? + (shuffle_byte_sel[3][0] ? shuffle_r0_in[31:24] : shuffle_r0_in[23:16]) : + (shuffle_byte_sel[3][0] ? shuffle_r0_in[15: 8] : shuffle_r0_in[ 7: 0]); + assign shuffle_r0[23:16] = shuffle_byte_sel[2][1] ? + (shuffle_byte_sel[2][0] ? shuffle_r0_in[31:24] : shuffle_r0_in[23:16]) : + (shuffle_byte_sel[2][0] ? shuffle_r0_in[15: 8] : shuffle_r0_in[ 7: 0]); + assign shuffle_r0[15: 8] = shuffle_byte_sel[1][1] ? + (shuffle_byte_sel[1][0] ? shuffle_r0_in[31:24] : shuffle_r0_in[23:16]) : + (shuffle_byte_sel[1][0] ? shuffle_r0_in[15: 8] : shuffle_r0_in[ 7: 0]); + assign shuffle_r0[ 7: 0] = shuffle_byte_sel[0][1] ? + (shuffle_byte_sel[0][0] ? shuffle_r0_in[31:24] : shuffle_r0_in[23:16]) : + (shuffle_byte_sel[0][0] ? shuffle_r0_in[15: 8] : shuffle_r0_in[ 7: 0]); + + assign shuffle_r1[31:24] = shuffle_byte_sel[3][1] ? + (shuffle_byte_sel[3][0] ? shuffle_r1_in[31:24] : shuffle_r1_in[23:16]) : + (shuffle_byte_sel[3][0] ? shuffle_r1_in[15: 8] : shuffle_r1_in[ 7: 0]); + assign shuffle_r1[23:16] = shuffle_byte_sel[2][1] ? + (shuffle_byte_sel[2][0] ? shuffle_r1_in[31:24] : shuffle_r1_in[23:16]) : + (shuffle_byte_sel[2][0] ? shuffle_r1_in[15: 8] : shuffle_r1_in[ 7: 0]); + assign shuffle_r1[15: 8] = shuffle_byte_sel[1][1] ? + (shuffle_byte_sel[1][0] ? shuffle_r1_in[31:24] : shuffle_r1_in[23:16]) : + (shuffle_byte_sel[1][0] ? shuffle_r1_in[15: 8] : shuffle_r1_in[ 7: 0]); + assign shuffle_r1[ 7: 0] = shuffle_byte_sel[0][1] ? + (shuffle_byte_sel[0][0] ? shuffle_r1_in[31:24] : shuffle_r1_in[23:16]) : + (shuffle_byte_sel[0][0] ? shuffle_r1_in[15: 8] : shuffle_r1_in[ 7: 0]); + + assign shuffle_result[31:24] = shuffle_reg_sel[3] ? shuffle_r1[31:24] : shuffle_r0[31:24]; + assign shuffle_result[23:16] = shuffle_reg_sel[2] ? shuffle_r1[23:16] : shuffle_r0[23:16]; + assign shuffle_result[15: 8] = shuffle_reg_sel[1] ? shuffle_r1[15: 8] : shuffle_r0[15: 8]; + assign shuffle_result[ 7: 0] = shuffle_reg_sel[0] ? shuffle_r1[ 7: 0] : shuffle_r0[ 7: 0]; + + assign pack_result[31:24] = shuffle_through[3] ? shuffle_result[31:24] : operand_c_i[31:24]; + assign pack_result[23:16] = shuffle_through[2] ? shuffle_result[23:16] : operand_c_i[23:16]; + assign pack_result[15: 8] = shuffle_through[1] ? shuffle_result[15: 8] : operand_c_i[15: 8]; + assign pack_result[ 7: 0] = shuffle_through[0] ? shuffle_result[ 7: 0] : operand_c_i[ 7: 0]; + + + ///////////////////////////////////////////////////////////////////// + // ____ _ _ ____ _ ___ // + // | __ )(_) |_ / ___|___ _ _ _ __ | |_ / _ \ _ __ ___ // + // | _ \| | __| | | / _ \| | | | '_ \| __| | | | | '_ \/ __| // + // | |_) | | |_ | |__| (_) | |_| | | | | |_ | |_| | |_) \__ \_ // + // |____/|_|\__| \____\___/ \__,_|_| |_|\__| \___/| .__/|___(_) // + // |_| // + ///////////////////////////////////////////////////////////////////// + + logic [31:0] ff_input; // either op_a_i or its bit reversed version + logic [5:0] cnt_result; // population count + logic [5:0] clb_result; // count leading bits + logic [4:0] ff1_result; // holds the index of the first '1' + logic ff_no_one; // if no ones are found + logic [4:0] fl1_result; // holds the index of the last '1' + logic [5:0] bitop_result; // result of all bitop operations muxed together + + riscv_popcnt alu_popcnt_i + ( + .in_i ( operand_a_i ), + .result_o ( cnt_result ) + ); + + always_comb + begin + ff_input = '0; + + case (operator_i) + ALU_FF1: ff_input = operand_a_i; + + ALU_DIVU, + ALU_REMU, + ALU_FL1: ff_input = operand_a_rev; + + ALU_DIV, + ALU_REM, + ALU_CLB: begin + if (operand_a_i[31]) + ff_input = operand_a_neg_rev; + else + ff_input = operand_a_rev; + end + endcase + end + + riscv_ff_one alu_ff_i + ( + .in_i ( ff_input ), + .first_one_o ( ff1_result ), + .no_ones_o ( ff_no_one ) + ); + + // special case if ff1_res is 0 (no 1 found), then we keep the 0 + // this is done in the result mux + assign fl1_result = 5'd31 - ff1_result; + assign clb_result = ff1_result - 5'd1; + + always_comb + begin + bitop_result = '0; + case (operator_i) + ALU_FF1: bitop_result = ff_no_one ? 6'd32 : {1'b0, ff1_result}; + ALU_FL1: bitop_result = ff_no_one ? 6'd32 : {1'b0, fl1_result}; + ALU_CNT: bitop_result = cnt_result; + ALU_CLB: begin + if (ff_no_one) begin + if (operand_a_i[31]) + bitop_result = 6'd31; + else + bitop_result = '0; + end else begin + bitop_result = clb_result; + end + end + default:; + endcase + end + + + //////////////////////////////////////////////// + // ____ _ _ __ __ _ // + // | __ )(_) |_ | \/ | __ _ _ __ (_)_ __ // + // | _ \| | __| | |\/| |/ _` | '_ \| | '_ \ // + // | |_) | | |_ | | | | (_| | | | | | |_) | // + // |____/|_|\__| |_| |_|\__,_|_| |_|_| .__/ // + // |_| // + //////////////////////////////////////////////// + + logic extract_is_signed; + logic extract_sign; + logic [31:0] bmask_first, bmask_inv; + logic [31:0] bextins_and; + logic [31:0] bextins_result, bclr_result, bset_result; + + + // construct bit mask for insert/extract/bclr/bset + // bmask looks like this 00..0011..1100..00 + assign bmask_first = {32'hFFFFFFFE} << bmask_a_i; + assign bmask = (~bmask_first) << bmask_b_i; + assign bmask_inv = ~bmask; + + assign bextins_and = (operator_i == ALU_BINS) ? operand_c_i : {32{extract_sign}}; + + assign extract_is_signed = (operator_i == ALU_BEXT); + assign extract_sign = extract_is_signed & shift_result[bmask_a_i]; + + assign bextins_result = (bmask & shift_result) | (bextins_and & bmask_inv); + + assign bclr_result = operand_a_i & bmask_inv; + assign bset_result = operand_a_i | bmask; + + ///////////////////////////////////////////////////////////////////////////////// + // ____ _____ _______ _____ ________ ________ _____ _____ ______ // + // | _ \_ _|__ __| | __ \| ____\ \ / / ____| __ \ / ____| ____| // + // | |_) || | | |______| |__) | |__ \ \ / /| |__ | |__) | (___ | |__ // + // | _ < | | | |______| _ /| __| \ \/ / | __| | _ / \___ \| __| // + // | |_) || |_ | | | | \ \| |____ \ / | |____| | \ \ ____) | |____ // + // |____/_____| |_| |_| \_\______| \/ |______|_| \_\_____/|______| // + // // + ///////////////////////////////////////////////////////////////////////////////// + + logic [31:0] radix_2_rev; + logic [31:0] radix_4_rev; + logic [31:0] radix_8_rev; + logic [31:0] reverse_result; + logic [1:0] radix_mux_sel; + + assign radix_mux_sel = bmask_a_i[1:0]; + + generate + // radix-2 bit reverse + for(j = 0; j < 32; j++) + begin + assign radix_2_rev[j] = shift_result[31-j]; + end + // radix-4 bit reverse + for(j = 0; j < 16; j++) + begin + assign radix_4_rev[2*j+1:2*j] = shift_result[31-j*2:31-j*2-1]; + end + // radix-8 bit reverse + for(j = 0; j < 10; j++) + begin + assign radix_8_rev[3*j+2:3*j] = shift_result[31-j*3:31-j*3-2]; + end + assign radix_8_rev[31:30] = 2'b0; + endgenerate + + always_comb + begin + reverse_result = '0; + + unique case (radix_mux_sel) + 2'b00: reverse_result = radix_2_rev; + 2'b01: reverse_result = radix_4_rev; + 2'b10: reverse_result = radix_8_rev; + + default: reverse_result = radix_2_rev; + endcase + end + + //////////////////////////////////////////////////// + // ____ _____ __ __ ____ _____ __ __ // + // | _ \_ _\ \ / / / / | _ \| ____| \/ | // + // | | | | | \ \ / / / / | |_) | _| | |\/| | // + // | |_| | | \ V / / / | _ <| |___| | | | // + // |____/___| \_/ /_/ |_| \_\_____|_| |_| // + // // + //////////////////////////////////////////////////// + + logic [31:0] result_div; + logic div_ready; + + if (SHARED_INT_DIV == 1) begin + + assign result_div = '0; + assign div_ready = '1; + assign div_valid = '0; + + end else begin : int_div + + logic div_signed; + logic div_op_a_signed; + logic div_op_b_signed; + logic [5:0] div_shift_int; + + assign div_signed = operator_i[0]; + + assign div_op_a_signed = operand_a_i[31] & div_signed; + assign div_op_b_signed = operand_b_i[31] & div_signed; + + assign div_shift_int = ff_no_one ? 6'd31 : clb_result; + assign div_shift = div_shift_int + (div_op_a_signed ? 6'd0 : 6'd1); + + assign div_valid = enable_i & ((operator_i == ALU_DIV) || (operator_i == ALU_DIVU) || + (operator_i == ALU_REM) || (operator_i == ALU_REMU)); + + + // inputs A and B are swapped + riscv_alu_div div_i + ( + .Clk_CI ( clk ), + .Rst_RBI ( rst_n ), + + // input IF + .OpA_DI ( operand_b_i ), + .OpB_DI ( shift_left_result ), + .OpBShift_DI ( div_shift ), + .OpBIsZero_SI ( (cnt_result == 0) ), + + .OpBSign_SI ( div_op_a_signed ), + .OpCode_SI ( operator_i[1:0] ), + + .Res_DO ( result_div ), + + // Hand-Shake + .InVld_SI ( div_valid ), + .OutRdy_SI ( ex_ready_i ), + .OutVld_SO ( div_ready ) + ); + end + + //////////////////////////////////////////////////////// + // ____ _ _ __ __ // + // | _ \ ___ ___ _ _| | |_ | \/ |_ ___ __ // + // | |_) / _ \/ __| | | | | __| | |\/| | | | \ \/ / // + // | _ < __/\__ \ |_| | | |_ | | | | |_| |> < // + // |_| \_\___||___/\__,_|_|\__| |_| |_|\__,_/_/\_\ // + // // + //////////////////////////////////////////////////////// + + always_comb + begin + result_o = '0; + + unique case (operator_i) + // Standard Operations + ALU_AND: result_o = operand_a_i & operand_b_i; + ALU_OR: result_o = operand_a_i | operand_b_i; + ALU_XOR: result_o = operand_a_i ^ operand_b_i; + + // Shift Operations + ALU_ADD, ALU_ADDR, ALU_ADDU, ALU_ADDUR, + ALU_SUB, ALU_SUBR, ALU_SUBU, ALU_SUBUR, + ALU_SLL, + ALU_SRL, ALU_SRA, + ALU_ROR: result_o = shift_result; + + // bit manipulation instructions + ALU_BINS, + ALU_BEXT, + ALU_BEXTU: result_o = bextins_result; + + ALU_BCLR: result_o = bclr_result; + ALU_BSET: result_o = bset_result; + + // Bit reverse instruction + ALU_BREV: result_o = reverse_result; + + // pack and shuffle operations + ALU_SHUF, ALU_SHUF2, + ALU_PCKLO, ALU_PCKHI, + ALU_EXT, ALU_EXTS, + ALU_INS: result_o = pack_result; + + // Min/Max/Ins + ALU_MIN, ALU_MINU, + ALU_MAX, ALU_MAXU, + ALU_FMIN, + ALU_FMAX: result_o = minmax_is_fp_special ? fp_canonical_nan : result_minmax; + + //Abs/Cplxconj , ABS is used to do 0 - A for Cplxconj + ALU_ABS: result_o = is_clpx_i ? {adder_result[31:16], operand_a_i[15:0]} : result_minmax; + + ALU_CLIP, ALU_CLIPU: result_o = clip_result; + + // Comparison Operations + ALU_EQ, ALU_NE, + ALU_GTU, ALU_GEU, + ALU_LTU, ALU_LEU, + ALU_GTS, ALU_GES, + ALU_LTS, ALU_LES: begin + result_o[31:24] = {8{cmp_result[3]}}; + result_o[23:16] = {8{cmp_result[2]}}; + result_o[15: 8] = {8{cmp_result[1]}}; + result_o[ 7: 0] = {8{cmp_result[0]}}; + end + // Non-vector comparisons + ALU_FEQ, ALU_FLT, + ALU_FLE, + ALU_SLTS, ALU_SLTU, + ALU_SLETS, ALU_SLETU: result_o = {31'b0, comparison_result_o}; + + ALU_FF1, ALU_FL1, ALU_CLB, ALU_CNT: result_o = {26'h0, bitop_result[5:0]}; + + // Division Unit Commands + ALU_DIV, ALU_DIVU, + ALU_REM, ALU_REMU: result_o = result_div; + + // fclass + ALU_FCLASS: result_o = fclass_result; + + // float sign injection + ALU_FSGNJ, ALU_FSGNJN, + ALU_FSGNJX, ALU_FKEEP: result_o = f_sign_inject_result; + + default: ; // default case to suppress unique warning + endcase + end + + assign ready_o = div_ready; + +endmodule diff --git a/hw/deps/riscv/riscv_alu_div.sv b/hw/deps/riscv/riscv_alu_div.sv new file mode 100644 index 0000000..6fc49f9 --- /dev/null +++ b/hw/deps/riscv/riscv_alu_div.sv @@ -0,0 +1,216 @@ +// Copyright 2018 ETH Zurich and 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. + +/////////////////////////////////////////////////////////////////////////////// +// File : Simple Serial Divider +// Ver : 1.0 +// Date : 15.03.2016 +/////////////////////////////////////////////////////////////////////////////// +// +// Description: this is a simple serial divider for signed integers (int32). +// +/////////////////////////////////////////////////////////////////////////////// +// +// Authors : Michael Schaffner (schaffner@iis.ee.ethz.ch) +// Andreas Traber (atraber@iis.ee.ethz.ch) +// +/////////////////////////////////////////////////////////////////////////////// + +module riscv_alu_div +#( + parameter C_WIDTH = 32, + parameter C_LOG_WIDTH = 6 +) +( + input logic Clk_CI, + input logic Rst_RBI, + // input IF + input logic [C_WIDTH-1:0] OpA_DI, + input logic [C_WIDTH-1:0] OpB_DI, + input logic [C_LOG_WIDTH-1:0] OpBShift_DI, + input logic OpBIsZero_SI, + // + input logic OpBSign_SI, // gate this to 0 in case of unsigned ops + input logic [1:0] OpCode_SI, // 0: udiv, 2: urem, 1: div, 3: rem + // handshake + input logic InVld_SI, + // output IF + input logic OutRdy_SI, + output logic OutVld_SO, + output logic [C_WIDTH-1:0] Res_DO + ); + + /////////////////////////////////////////////////////////////////////////////// + // signal declarations + /////////////////////////////////////////////////////////////////////////////// + + logic [C_WIDTH-1:0] ResReg_DP, ResReg_DN; + logic [C_WIDTH-1:0] ResReg_DP_rev; + logic [C_WIDTH-1:0] AReg_DP, AReg_DN; + logic [C_WIDTH-1:0] BReg_DP, BReg_DN; + + logic RemSel_SN, RemSel_SP; + logic CompInv_SN, CompInv_SP; + logic ResInv_SN, ResInv_SP; + + logic [C_WIDTH-1:0] AddMux_D; + logic [C_WIDTH-1:0] AddOut_D; + logic [C_WIDTH-1:0] AddTmp_D; + logic [C_WIDTH-1:0] BMux_D; + logic [C_WIDTH-1:0] OutMux_D; + + logic [C_LOG_WIDTH-1:0] Cnt_DP, Cnt_DN; + logic CntZero_S; + + logic ARegEn_S, BRegEn_S, ResRegEn_S, ABComp_S, PmSel_S, LoadEn_S; + + enum logic [1:0] {IDLE, DIVIDE, FINISH} State_SN, State_SP; + + + /////////////////////////////////////////////////////////////////////////////// + // datapath + /////////////////////////////////////////////////////////////////////////////// + + assign PmSel_S = LoadEn_S & ~(OpCode_SI[0] & (OpA_DI[$high(OpA_DI)] ^ OpBSign_SI)); + + // muxes + assign AddMux_D = (LoadEn_S) ? OpA_DI : BReg_DP; + + // attention: logical shift in case of negative operand B! + assign BMux_D = (LoadEn_S) ? OpB_DI : {CompInv_SP, (BReg_DP[$high(BReg_DP):1])}; + + assign ResReg_DP_rev = {<<{ResReg_DP}}; + assign OutMux_D = (RemSel_SP) ? AReg_DP : ResReg_DP_rev; + + // invert if necessary + assign Res_DO = (ResInv_SP) ? -$signed(OutMux_D) : OutMux_D; + + // main comparator + assign ABComp_S = ((AReg_DP == BReg_DP) | ((AReg_DP > BReg_DP) ^ CompInv_SP)) & ((|AReg_DP) | OpBIsZero_SI); + + // main adder + assign AddTmp_D = (LoadEn_S) ? 0 : AReg_DP; + assign AddOut_D = (PmSel_S) ? AddTmp_D + AddMux_D : AddTmp_D - $signed(AddMux_D); + + /////////////////////////////////////////////////////////////////////////////// + // counter + /////////////////////////////////////////////////////////////////////////////// + + assign Cnt_DN = (LoadEn_S) ? OpBShift_DI : + (~CntZero_S) ? Cnt_DP - 1 : Cnt_DP; + + assign CntZero_S = ~(|Cnt_DP); + + /////////////////////////////////////////////////////////////////////////////// + // FSM + /////////////////////////////////////////////////////////////////////////////// + + always_comb + begin : p_fsm + // default + State_SN = State_SP; + + OutVld_SO = 1'b0; + + LoadEn_S = 1'b0; + + ARegEn_S = 1'b0; + BRegEn_S = 1'b0; + ResRegEn_S = 1'b0; + + case (State_SP) + ///////////////////////////////// + IDLE: begin + OutVld_SO = 1'b1; + + if(InVld_SI) begin + OutVld_SO = 1'b0; + ARegEn_S = 1'b1; + BRegEn_S = 1'b1; + LoadEn_S = 1'b1; + State_SN = DIVIDE; + end + end + ///////////////////////////////// + DIVIDE: begin + + ARegEn_S = ABComp_S; + BRegEn_S = 1'b1; + ResRegEn_S = 1'b1; + + // calculation finished + // one more divide cycle (32nd divide cycle) + if (CntZero_S) begin + State_SN = FINISH; + end + end + ///////////////////////////////// + FINISH: begin + OutVld_SO = 1'b1; + + if(OutRdy_SI) begin + State_SN = IDLE; + end + end + ///////////////////////////////// + default : /* default */ ; + ///////////////////////////////// + endcase + end + + + /////////////////////////////////////////////////////////////////////////////// + // regs + /////////////////////////////////////////////////////////////////////////////// + + // get flags + assign RemSel_SN = (LoadEn_S) ? OpCode_SI[1] : RemSel_SP; + assign CompInv_SN = (LoadEn_S) ? OpBSign_SI : CompInv_SP; + assign ResInv_SN = (LoadEn_S) ? (~OpBIsZero_SI | OpCode_SI[1]) & OpCode_SI[0] & (OpA_DI[$high(OpA_DI)] ^ OpBSign_SI) : ResInv_SP; + + assign AReg_DN = (ARegEn_S) ? AddOut_D : AReg_DP; + assign BReg_DN = (BRegEn_S) ? BMux_D : BReg_DP; + assign ResReg_DN = (LoadEn_S) ? '0 : + (ResRegEn_S) ? {ABComp_S, ResReg_DP[$high(ResReg_DP):1]} : ResReg_DP; + + always_ff @(posedge Clk_CI or negedge Rst_RBI) begin : p_regs + if(~Rst_RBI) begin + State_SP <= IDLE; + AReg_DP <= '0; + BReg_DP <= '0; + ResReg_DP <= '0; + Cnt_DP <= '0; + RemSel_SP <= 1'b0; + CompInv_SP <= 1'b0; + ResInv_SP <= 1'b0; + end else begin + State_SP <= State_SN; + AReg_DP <= AReg_DN; + BReg_DP <= BReg_DN; + ResReg_DP <= ResReg_DN; + Cnt_DP <= Cnt_DN; + RemSel_SP <= RemSel_SN; + CompInv_SP <= CompInv_SN; + ResInv_SP <= ResInv_SN; + end + end + + /////////////////////////////////////////////////////////////////////////////// + // assertions + /////////////////////////////////////////////////////////////////////////////// + +`ifndef SYNTHESIS + initial + begin : p_assertions + assert (C_LOG_WIDTH == $clog2(C_WIDTH+1)) else $error("C_LOG_WIDTH must be $clog2(C_WIDTH+1)"); + end +`endif + +endmodule // serDiv diff --git a/hw/deps/riscv/riscv_apu_disp.sv b/hw/deps/riscv/riscv_apu_disp.sv new file mode 100644 index 0000000..b1ee545 --- /dev/null +++ b/hw/deps/riscv/riscv_apu_disp.sv @@ -0,0 +1,248 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Lukas Mueller - lukasmue@student.ethz.ch // +// // +// Additional contributions by: // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: Simple APU dispatcher // +// Project Name: PULP // +// Language: SystemVerilog // +// // +// Description: Dispatcher for sending instructions to the Marx // +// interconnect. // +//////////////////////////////////////////////////////////////////////////////// + +`include "apu_macros.sv" + +module riscv_apu_disp ( + input logic clk_i, + input logic rst_ni, + + // request input + input logic enable_i, + input logic [1:0] apu_lat_i, + input logic [5:0] apu_waddr_i, + + // response output + output logic [5:0] apu_waddr_o, + output logic apu_multicycle_o, + output logic apu_singlecycle_o, + + // active signal + output logic active_o, + + // stall signals + output logic stall_o, + + // dependency checks + input logic [2:0][5:0] read_regs_i, + input logic [2:0] read_regs_valid_i, + output logic read_dep_o, + + input logic [1:0][5:0] write_regs_i, + input logic [1:0] write_regs_valid_i, + output logic write_dep_o, + + // perf counter stuff + output logic perf_type_o, + output logic perf_cont_o, + + // apu-interconnect + // handshake signals + output logic apu_master_req_o, + output logic apu_master_ready_o, + input logic apu_master_gnt_i, + // response channel + input logic apu_master_valid_i + + ); + + logic [5:0] addr_req, addr_inflight, addr_waiting; + logic [5:0] addr_inflight_dn, addr_waiting_dn; + logic valid_req, valid_inflight, valid_waiting; + logic valid_inflight_dn, valid_waiting_dn; + logic returned_req, returned_inflight, returned_waiting; + + logic req_accepted; + logic active; + logic [1:0] apu_lat; + + + logic [2:0] read_deps_req, read_deps_inflight, read_deps_waiting; + logic [1:0] write_deps_req, write_deps_inflight, write_deps_waiting; + logic read_dep_req, read_dep_inflight, read_dep_waiting; + logic write_dep_req, write_dep_inflight, write_dep_waiting; + + logic stall_full, stall_type, stall_nack; + + // Generate request signal; do not generate request if stalled unless it's a nack stall + assign valid_req = enable_i & !(stall_full | stall_type); + assign addr_req = apu_waddr_i; + + assign req_accepted = valid_req & apu_master_gnt_i; + + // + // In-flight instructions + // + // Check whether the instructions have returned + assign returned_req = valid_req & apu_master_valid_i & !valid_inflight & !valid_waiting; + assign returned_inflight = valid_inflight & (apu_master_valid_i) & !valid_waiting; + assign returned_waiting = valid_waiting & (apu_master_valid_i); + + // Inflight and waiting registers + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + valid_inflight <= 1'b0; + valid_waiting <= 1'b0; + addr_inflight <= '0; + addr_waiting <= '0; + end else begin + valid_inflight <= valid_inflight_dn; + valid_waiting <= valid_waiting_dn; + addr_inflight <= addr_inflight_dn; + addr_waiting <= addr_waiting_dn; + end + end + + always_comb begin + valid_inflight_dn = valid_inflight; + valid_waiting_dn = valid_waiting; + addr_inflight_dn = addr_inflight; + addr_waiting_dn = addr_waiting; + + if (req_accepted & !returned_req) begin // this is a multicycle request + valid_inflight_dn = 1'b1; + addr_inflight_dn = addr_req; + if (valid_inflight & !(returned_inflight)) begin // we already have an inflight instruction! + valid_waiting_dn = 1'b1; + addr_waiting_dn = addr_inflight; + end + if (returned_waiting) begin // we have received a new request and waiting goes out of the pipe but will be refilled + valid_waiting_dn = 1'b1; + addr_waiting_dn = addr_inflight; + end + end // no new request + else if (returned_inflight) begin // multicycle request has returned + valid_inflight_dn = '0; + valid_waiting_dn = '0; + addr_inflight_dn = '0; + addr_waiting_dn = '0; + end + else if (returned_waiting) begin // multicycle request has returned + valid_waiting_dn = '0; + addr_waiting_dn = '0; + end + end + + // + // Active type + // + // Dispatcher is active when there is an unreturned instruction + assign active = valid_inflight | valid_waiting; + + // Store the latency type whenever there is a request + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + apu_lat <= '0; + end else begin + if(valid_req) begin + apu_lat <= apu_lat_i; + end + end + end + + // + // Dependency checks + // + // There is a dependency if the register is equal to one of the instructions + generate + for (genvar i = 0; i < 3; i++) begin + assign read_deps_req[i] = (read_regs_i[i] == addr_req) & read_regs_valid_i[i]; + assign read_deps_inflight[i] = (read_regs_i[i] == addr_inflight) & read_regs_valid_i[i]; + assign read_deps_waiting[i] = (read_regs_i[i] == addr_waiting) & read_regs_valid_i[i]; + end + endgenerate + + generate + for (genvar i = 0; i < 2; i++) begin + assign write_deps_req[i] = (write_regs_i[i] == addr_req) & write_regs_valid_i[i]; + assign write_deps_inflight[i] = (write_regs_i[i] == addr_inflight) & write_regs_valid_i[i]; + assign write_deps_waiting[i] = (write_regs_i[i] == addr_waiting) & write_regs_valid_i[i]; + end + endgenerate + + // Reduce the individual dependency signals into one read and one write dependency + assign read_dep_req = |read_deps_req & valid_req & !returned_req; + assign read_dep_inflight = |read_deps_inflight & valid_inflight & !returned_inflight; + assign read_dep_waiting = |read_deps_waiting & valid_waiting & !returned_waiting; + assign write_dep_req = |write_deps_req & valid_req & !returned_req; + assign write_dep_inflight = |write_deps_inflight & valid_inflight & !returned_inflight; + assign write_dep_waiting = |write_deps_waiting & valid_waiting & !returned_waiting; + + assign read_dep_o = read_dep_req | read_dep_inflight | read_dep_waiting; + assign write_dep_o = write_dep_req | write_dep_inflight | write_dep_waiting; + + // + // Stall signals + // + // Stall if we cannot store any more outstanding requests + assign stall_full = valid_inflight & valid_waiting; + // Stall if there is a type conflict. if apu is active we can only issue requests with a larger or equal latency + // than the latency of the inflight operation (apu_lat_i>=apu_lat). otherwise operations would overtake each other! + // so we stall if: (apu_lat_i = 1 & apu_lat = 2/3) | (apu_lat_i = 2 & apu_lat = 3) | (apu_lat_i = 3 (multicycle)) + assign stall_type = enable_i & active & ((apu_lat_i==2'h1) | ((apu_lat_i==2'h2) & (apu_lat==2'h3)) | (apu_lat_i==2'h3)); + assign stall_nack = valid_req & !apu_master_gnt_i; + assign stall_o = stall_full | stall_type | stall_nack; + + // + // Generate Apu_master request + // + assign apu_master_req_o = valid_req; + + // + // Use Apu_master response + // + assign apu_master_ready_o = 1'b1; + + // Determine write register based on where the instruction returned. + always_comb begin + apu_waddr_o = '0; + if(returned_req) + apu_waddr_o = addr_req; + if(returned_inflight) + apu_waddr_o = addr_inflight; + if(returned_waiting) + apu_waddr_o = addr_waiting; + end + + // Output active signal + assign active_o = active; + + // Performance counter signals + assign perf_type_o = stall_type; + assign perf_cont_o = stall_nack; + + assign apu_multicycle_o = (apu_lat == 2'h3); + assign apu_singlecycle_o = ~(valid_inflight | valid_waiting); + + // + // Assertions + // + +`ifndef VERILATOR + assert property ( + @(posedge clk_i) (apu_master_valid_i) |-> (valid_req | valid_inflight | valid_waiting)) + else $warning("[APU Dispatcher] instruction returned while no instruction is in-flight"); +`endif + +endmodule \ No newline at end of file diff --git a/hw/deps/riscv/riscv_compressed_decoder.sv b/hw/deps/riscv/riscv_compressed_decoder.sv new file mode 100644 index 0000000..50ecf56 --- /dev/null +++ b/hw/deps/riscv/riscv_compressed_decoder.sv @@ -0,0 +1,299 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Sven Stucki - svstucki@student.ethz.ch // +// // +// Additional contributions by: // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: Compressed instruction decoder // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Decodes RISC-V compressed instructions into their RV32 // +// equivalent. This module is fully combinatorial. // +// Float extensions added // +// // +//////////////////////////////////////////////////////////////////////////////// + + +import riscv_defines::*; + +module riscv_compressed_decoder +#( + parameter FPU = 0 +) +( + input logic [31:0] instr_i, + output logic [31:0] instr_o, + output logic is_compressed_o, + output logic illegal_instr_o +); + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // ____ _ ____ _ // + // / ___|___ _ __ ___ _ __ _ __ ___ ___ ___ ___ __| | | _ \ ___ ___ ___ __| | ___ _ __ // + // | | / _ \| '_ ` _ \| '_ \| '__/ _ \/ __/ __|/ _ \/ _` | | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| // + // | |__| (_) | | | | | | |_) | | | __/\__ \__ \ __/ (_| | | |_| | __/ (_| (_) | (_| | __/ | // + // \____\___/|_| |_| |_| .__/|_| \___||___/___/\___|\__,_| |____/ \___|\___\___/ \__,_|\___|_| // + // |_| // + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + generate + + always_comb + begin + illegal_instr_o = 1'b0; + instr_o = '0; + + unique case (instr_i[1:0]) + // C0 + 2'b00: begin + unique case (instr_i[15:13]) + 3'b000: begin + // c.addi4spn -> addi rd', x2, imm + instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], OPCODE_OPIMM}; + if (instr_i[12:5] == 8'b0) illegal_instr_o = 1'b1; + end + + 3'b001: begin + // c.fld -> fld rd', imm(rs1') + if (FPU==1) // instr_i[12:10]-> offset[5:3], instr_i[6:5]-> offset[7:6] + instr_o = {4'b0, instr_i[6:5], instr_i[12:10], 3'b000, 2'b01, instr_i[9:7], 3'b011, 2'b01, instr_i[4:2], OPCODE_LOAD_FP}; + else + illegal_instr_o = 1'b1; + end + + 3'b010: begin + // c.lw -> lw rd', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], OPCODE_LOAD}; + end + + 3'b011: begin + // c.flw -> flw rd', imm(rs1') + if (FPU==1) + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], OPCODE_LOAD_FP}; + else + illegal_instr_o = 1'b1; + end + + 3'b101: begin + // c.fsd -> fsd rs2', imm(rs1') + if (FPU==1) // instr_i[12:10] -> offset[5:3], instr_i[6:5] -> offset[7:6] + instr_o = {4'b0, instr_i[6:5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b011, instr_i[11:10], 3'b000, OPCODE_STORE_FP}; + else + illegal_instr_o = 1'b1; + end + + 3'b110: begin + // c.sw -> sw rs2', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, OPCODE_STORE}; + end + + 3'b111: begin + // c.fsw -> fsw rs2', imm(rs1') + if (FPU==1) + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, OPCODE_STORE_FP}; + else + illegal_instr_o = 1'b1; + end + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + + + // C1 + 2'b01: begin + unique case (instr_i[15:13]) + 3'b000: begin + // c.addi -> addi rd, rd, nzimm + // c.nop + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OPIMM}; + end + + 3'b001, 3'b101: begin + // 001: c.jal -> jal x1, imm + // 101: c.j -> jal x0, imm + instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], OPCODE_JAL}; + end + + 3'b010: begin + // c.li -> addi rd, x0, nzimm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], OPCODE_OPIMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b011: begin + // c.lui -> lui rd, imm + instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], OPCODE_LUI}; + + if (instr_i[11:7] == 5'h02) begin + // c.addi16sp -> addi x2, x2, nzimm + instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, OPCODE_OPIMM}; + end else if (instr_i[11:7] == 5'b0) begin + illegal_instr_o = 1'b1; + end + + if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1; + end + + 3'b100: begin + unique case (instr_i[11:10]) + 2'b00, + 2'b01: begin + // 00: c.srli -> srli rd, rd, shamt + // 01: c.srai -> srai rd, rd, shamt + instr_o = {1'b0, instr_i[10], 5'b0, instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], OPCODE_OPIMM}; + if (instr_i[12] == 1'b1) illegal_instr_o = 1'b1; + if (instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + end + + 2'b10: begin + // c.andi -> andi rd, rd, imm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OPIMM}; + end + + 2'b11: begin + unique case ({instr_i[12], instr_i[6:5]}) + 3'b000: begin + // c.sub -> sub rd', rd', rs2' + instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], OPCODE_OP}; + end + + 3'b001: begin + // c.xor -> xor rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], OPCODE_OP}; + end + + 3'b010: begin + // c.or -> or rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], OPCODE_OP}; + end + + 3'b011: begin + // c.and -> and rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OP}; + end + + 3'b100, + 3'b101, + 3'b110, + 3'b111: begin + // 100: c.subw + // 101: c.addw + illegal_instr_o = 1'b1; + end + endcase + end + endcase + end + + 3'b110, 3'b111: begin + // 0: c.beqz -> beq rs1', x0, imm + // 1: c.bnez -> bne rs1', x0, imm + instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], OPCODE_BRANCH}; + end + endcase + end + + // C2 + 2'b10: begin + unique case (instr_i[15:13]) + 3'b000: begin + // c.slli -> slli rd, rd, shamt + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], OPCODE_OPIMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + if (instr_i[12] == 1'b1 || instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b001: begin + // c.fldsp -> fld rd, imm(x2) + if (FPU==1) // instr_i[6:5] -> offset[4:3], instr_i[4:2] -> offset[8:6], instr_i[12] -> offset[5] + instr_o = {3'b0, instr_i[4:2], instr_i[12], instr_i[6:5], 3'b000, 5'h02, 3'b011, instr_i[11:7], OPCODE_LOAD_FP}; + else + illegal_instr_o = 1'b1; + end + + 3'b010: begin + // c.lwsp -> lw rd, imm(x2) + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], OPCODE_LOAD}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + end + + 3'b011: begin + // c.flwsp -> flw rd, imm(x2) + if (FPU==1) + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], OPCODE_LOAD_FP}; + else + illegal_instr_o = 1'b1; + end + + 3'b100: begin + if (instr_i[12] == 1'b0) begin + // c.mv -> add rd/rs1, x0, rs2 + instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], OPCODE_OP}; + + if (instr_i[6:2] == 5'b0) begin + // c.jr -> jalr x0, rd/rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, OPCODE_JALR}; + end + end else begin + // c.add -> add rd, rd, rs2 + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OP}; + + if (instr_i[11:7] == 5'b0) begin + // c.ebreak -> ebreak + instr_o = {32'h00_10_00_73}; + if (instr_i[6:2] != 5'b0) + illegal_instr_o = 1'b1; + end else if (instr_i[6:2] == 5'b0) begin + // c.jalr -> jalr x1, rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, OPCODE_JALR}; + end + end + end + + 3'b101: begin + // c.fsdsp -> fsd rs2, imm(x2) + if (FPU==1) // instr_i[12:10] -> offset[5:3], instr_i[9:7] -> offset[8:6] + instr_o = {3'b0, instr_i[9:7], instr_i[12], instr_i[6:2], 5'h02, 3'b011, instr_i[11:10], 3'b000, OPCODE_STORE_FP}; + else + illegal_instr_o = 1'b1; + end + 3'b110: begin + // c.swsp -> sw rs2, imm(x2) + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, OPCODE_STORE}; + end + + 3'b111: begin + // c.fswsp -> fsw rs2, imm(x2) + if (FPU==1) + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, OPCODE_STORE_FP}; + else + illegal_instr_o = 1'b1; + end + endcase + end + + default: begin + // 32 bit (or more) instruction + instr_o = instr_i; + end + endcase + end + + endgenerate + + assign is_compressed_o = (instr_i[1:0] != 2'b11); + +endmodule diff --git a/hw/deps/riscv/riscv_controller.sv b/hw/deps/riscv/riscv_controller.sv new file mode 100644 index 0000000..8813796 --- /dev/null +++ b/hw/deps/riscv/riscv_controller.sv @@ -0,0 +1,1138 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Matthias Baer - baermatt@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Andreas Traber - atraber@student.ethz.ch // +// Sven Stucki - svstucki@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// Robert Balas - balasr@iis.ee.ethz.ch // +// Andrea Bettati - andrea.bettati@studenti.unipr.it // +// // +// Design Name: Main controller // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Main CPU controller of the processor // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; + +module riscv_controller +#( + parameter FPU = 0 +) +( + input logic clk, + input logic rst_n, + + input logic fetch_enable_i, // Start the decoding + output logic ctrl_busy_o, // Core is busy processing instructions + output logic first_fetch_o, // Core is at the FIRST FETCH stage + output logic is_decoding_o, // Core is in decoding state + input logic is_fetch_failed_i, + + // decoder related signals + output logic deassert_we_o, // deassert write enable for next instruction + + input logic illegal_insn_i, // decoder encountered an invalid instruction + input logic ecall_insn_i, // ecall encountered an mret instruction + input logic mret_insn_i, // decoder encountered an mret instruction + input logic uret_insn_i, // decoder encountered an uret instruction + + input logic dret_insn_i, // decoder encountered an dret instruction + + input logic mret_dec_i, + input logic uret_dec_i, + input logic dret_dec_i, + + input logic pipe_flush_i, // decoder wants to do a pipe flush + input logic ebrk_insn_i, // decoder encountered an ebreak instruction + input logic fencei_insn_i, // decoder encountered an fence.i instruction + input logic csr_status_i, // decoder encountered an csr status instruction + input logic instr_multicycle_i, // true when multiple cycles are decoded + + output logic hwloop_mask_o, //prevent writes on the hwloop instructions in case interrupt are taken + + // from IF/ID pipeline + input logic instr_valid_i, // instruction coming from IF/ID pipeline is valid + + // from prefetcher + output logic instr_req_o, // Start fetching instructions + + // to prefetcher + output logic pc_set_o, // jump to address set by pc_mux + output logic [2:0] pc_mux_o, // Selector in the Fetch stage to select the rigth PC (normal, jump ...) + output logic [2:0] exc_pc_mux_o, // Selects target PC for exception + output logic [1:0] trap_addr_mux_o, // Selects trap address base + + // LSU + input logic data_req_ex_i, // data memory access is currently performed in EX stage + input logic data_we_ex_i, + input logic data_misaligned_i, + input logic data_load_event_i, + input logic data_err_i, + output logic data_err_ack_o, + + // from ALU + input logic mult_multicycle_i, // multiplier is taken multiple cycles and uses op c as storage + + // APU dependency checks + input logic apu_en_i, + input logic apu_read_dep_i, + input logic apu_write_dep_i, + + output logic apu_stall_o, + + // jump/branch signals + input logic branch_taken_ex_i, // branch taken signal from EX ALU + input logic [1:0] jump_in_id_i, // jump is being calculated in ALU + input logic [1:0] jump_in_dec_i, // jump is being calculated in ALU + + // Interrupt Controller Signals + input logic irq_pending_i, + input logic irq_req_ctrl_i, + input logic irq_sec_ctrl_i, + input logic [5:0] irq_id_ctrl_i, + input logic m_IE_i, // interrupt enable bit from CSR (M mode) + input logic u_IE_i, // interrupt enable bit from CSR (U mode) + input PrivLvl_t current_priv_lvl_i, + + output logic irq_ack_o, + output logic [5:0] irq_id_o, + + output logic [5:0] exc_cause_o, + output logic exc_ack_o, + output logic exc_kill_o, + + // Debug Signal + output logic debug_mode_o, + output logic [2:0] debug_cause_o, + output logic debug_csr_save_o, + input logic debug_req_i, + input logic debug_single_step_i, + input logic debug_ebreakm_i, + input logic debug_ebreaku_i, + input logic trigger_match_i, + + output logic csr_save_if_o, + output logic csr_save_id_o, + output logic csr_save_ex_o, + output logic [6:0] csr_cause_o, + output logic csr_irq_sec_o, + output logic csr_restore_mret_id_o, + output logic csr_restore_uret_id_o, + + output logic csr_restore_dret_id_o, + + output logic csr_save_cause_o, + + + // Regfile target + input logic regfile_we_id_i, // currently decoded we enable + input logic [5:0] regfile_alu_waddr_id_i, // currently decoded target address + + // Forwarding signals from regfile + input logic regfile_we_ex_i, // FW: write enable from EX stage + input logic [5:0] regfile_waddr_ex_i, // FW: write address from EX stage + input logic regfile_we_wb_i, // FW: write enable from WB stage + input logic regfile_alu_we_fw_i, // FW: ALU/MUL write enable from EX stage + + // forwarding signals + output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage + output logic [1:0] operand_b_fw_mux_sel_o, // regfile rb data selector form ID stage + output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage + + // forwarding detection signals + input logic reg_d_ex_is_reg_a_i, + input logic reg_d_ex_is_reg_b_i, + input logic reg_d_ex_is_reg_c_i, + input logic reg_d_wb_is_reg_a_i, + input logic reg_d_wb_is_reg_b_i, + input logic reg_d_wb_is_reg_c_i, + input logic reg_d_alu_is_reg_a_i, + input logic reg_d_alu_is_reg_b_i, + input logic reg_d_alu_is_reg_c_i, + + // stall signals + output logic halt_if_o, + output logic halt_id_o, + + output logic misaligned_stall_o, + output logic jr_stall_o, + output logic load_stall_o, + + input logic id_ready_i, // ID stage is ready + + input logic ex_valid_i, // EX stage is done + + input logic wb_ready_i, // WB stage is ready + + // Performance Counters + output logic perf_jump_o, // we are executing a jump instruction (j, jr, jal, jalr) + output logic perf_jr_stall_o, // stall due to jump-register-hazard + output logic perf_ld_stall_o, // stall due to load-use-hazard + output logic perf_pipeline_stall_o // stall due to elw extra cycles +); + + // FSM state encoding + ctrl_state_e ctrl_fsm_cs, ctrl_fsm_ns; + + logic jump_done, jump_done_q, jump_in_dec, branch_in_id; + logic boot_done, boot_done_q; + logic irq_enable_int; + logic data_err_q; + + logic debug_mode_q, debug_mode_n; + logic ebrk_force_debug_mode; + + logic illegal_insn_q, illegal_insn_n; + + logic instr_valid_irq_flush_n, instr_valid_irq_flush_q; + +`ifndef SYNTHESIS + // synopsys translate_off + // make sure we are called later so that we do not generate messages for + // glitches + always_ff @(negedge clk) + begin + // print warning in case of decoding errors + if (is_decoding_o && illegal_insn_i) begin + $display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, riscv_core.hart_id_i[3:0], + riscv_id_stage.pc_id_i); + end + end + // synopsys translate_on +`endif + + + //////////////////////////////////////////////////////////////////////////////////////////// + // ____ ___ ____ _____ ____ ___ _ _ _____ ____ ___ _ _ _____ ____ // + // / ___/ _ \| _ \| ____| / ___/ _ \| \ | |_ _| _ \ / _ \| | | | | ____| _ \ // + // | | | | | | |_) | _| | | | | | | \| | | | | |_) | | | | | | | | _| | |_) | // + // | |__| |_| | _ <| |___ | |__| |_| | |\ | | | | _ <| |_| | |___| |___| |___| _ < // + // \____\___/|_| \_\_____| \____\___/|_| \_| |_| |_| \_\\___/|_____|_____|_____|_| \_\ // + // // + //////////////////////////////////////////////////////////////////////////////////////////// + + always_comb + begin + // Default values + instr_req_o = 1'b1; + + exc_ack_o = 1'b0; + exc_kill_o = 1'b0; + data_err_ack_o = 1'b0; + + csr_save_if_o = 1'b0; + csr_save_id_o = 1'b0; + csr_save_ex_o = 1'b0; + csr_restore_mret_id_o = 1'b0; + csr_restore_uret_id_o = 1'b0; + + csr_restore_dret_id_o = 1'b0; + + csr_save_cause_o = 1'b0; + + exc_cause_o = '0; + exc_pc_mux_o = EXC_PC_IRQ; + trap_addr_mux_o = TRAP_MACHINE; + + csr_cause_o = '0; + csr_irq_sec_o = 1'b0; + + pc_mux_o = PC_BOOT; + pc_set_o = 1'b0; + jump_done = jump_done_q; + + ctrl_fsm_ns = ctrl_fsm_cs; + + ctrl_busy_o = 1'b1; + first_fetch_o = 1'b0; + + halt_if_o = 1'b0; + halt_id_o = 1'b0; + irq_ack_o = 1'b0; + irq_id_o = irq_id_ctrl_i[5:0]; + + boot_done = 1'b0; + jump_in_dec = jump_in_dec_i == BRANCH_JALR || jump_in_dec_i == BRANCH_JAL; + branch_in_id = jump_in_id_i == BRANCH_COND; + irq_enable_int = ((u_IE_i | irq_sec_ctrl_i) & current_priv_lvl_i == PRIV_LVL_U) | (m_IE_i & current_priv_lvl_i == PRIV_LVL_M); + + ebrk_force_debug_mode = (debug_ebreakm_i && current_priv_lvl_i == PRIV_LVL_M) || + (debug_ebreaku_i && current_priv_lvl_i == PRIV_LVL_U); + debug_csr_save_o = 1'b0; + debug_cause_o = DBG_CAUSE_EBREAK; + debug_mode_n = debug_mode_q; + + illegal_insn_n = illegal_insn_q; + // a trap towards the debug unit is generated when one of the + // following conditions are true: + // - ebreak instruction encountered + // - single-stepping mode enabled + // - illegal instruction exception and IIE bit is set + // - IRQ and INTE bit is set and no exception is currently running + // - Debuger requests halt + + perf_pipeline_stall_o = 1'b0; + + + //this signal goes to 1 only registered interrupt requests are killed by exc_kill_o + //so that the current instructions will have the deassert_we_o signal equal to 0 once the controller is back to DECODE + instr_valid_irq_flush_n = 1'b0; + + hwloop_mask_o = 1'b0; + + unique case (ctrl_fsm_cs) + // We were just reset, wait for fetch_enable + RESET: + begin + is_decoding_o = 1'b0; + instr_req_o = 1'b0; + if (fetch_enable_i == 1'b1) + begin + ctrl_fsm_ns = BOOT_SET; + end + end + + // copy boot address to instr fetch address + BOOT_SET: + begin + is_decoding_o = 1'b0; + instr_req_o = 1'b1; + pc_mux_o = PC_BOOT; + pc_set_o = 1'b1; + boot_done = 1'b1; + ctrl_fsm_ns = FIRST_FETCH; + end + + WAIT_SLEEP: + begin + is_decoding_o = 1'b0; + ctrl_busy_o = 1'b0; + instr_req_o = 1'b0; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = SLEEP; + end + + // instruction in if_stage is already valid + SLEEP: + begin + // we begin execution when an + // interrupt has arrived + is_decoding_o = 1'b0; + ctrl_busy_o = 1'b0; + instr_req_o = 1'b0; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + + // normal execution flow + // in debug mode or single step mode we leave immediately (wfi=nop) + if (irq_pending_i || (debug_req_i || debug_mode_q || debug_single_step_i || trigger_match_i)) begin + ctrl_fsm_ns = FIRST_FETCH; + end + + end + + FIRST_FETCH: + begin + is_decoding_o = 1'b0; + first_fetch_o = 1'b1; + // Stall because of IF miss + if ((id_ready_i == 1'b1) ) + begin + ctrl_fsm_ns = DECODE; + end + + // handle interrupts + if (irq_req_ctrl_i & irq_enable_int) begin + // This assumes that the pipeline is always flushed before + // going to sleep. + ctrl_fsm_ns = IRQ_TAKEN_IF; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + end + + if ((debug_req_i || trigger_match_i) & (~debug_mode_q)) + begin + ctrl_fsm_ns = DBG_TAKEN_IF; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + end + + end + + DECODE: + begin + + if (branch_taken_ex_i) + begin //taken branch + // there is a branch in the EX stage that is taken + + is_decoding_o = 1'b0; + + pc_mux_o = PC_BRANCH; + pc_set_o = 1'b1; + + // if we want to debug, flush the pipeline + // the current_pc_if will take the value of the next instruction to + // be executed (NPC) + + end //taken branch + + else if (data_err_i) + begin //data error + // the current LW or SW have been blocked by the PMP + + is_decoding_o = 1'b0; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + csr_save_ex_o = 1'b1; + csr_save_cause_o = 1'b1; + data_err_ack_o = 1'b1; + //no jump in this stage as we have to wait one cycle to go to Machine Mode + + csr_cause_o = data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT; + ctrl_fsm_ns = FLUSH_WB; + + end //data error + + else if (is_fetch_failed_i) + begin + + // the current instruction has been blocked by the PMP + + is_decoding_o = 1'b0; + halt_id_o = 1'b1; + halt_if_o = 1'b1; + csr_save_if_o = 1'b1; + csr_save_cause_o = 1'b1; + + //no jump in this stage as we have to wait one cycle to go to Machine Mode + + csr_cause_o = EXC_CAUSE_INSTR_FAULT; + ctrl_fsm_ns = FLUSH_WB; + + + end + // decode and execute instructions only if the current conditional + // branch in the EX stage is either not taken, or there is no + // conditional branch in the EX stage + else if (instr_valid_i || instr_valid_irq_flush_q) //valid block or replay after interrupt speculation + begin // now analyze the current instruction in the ID stage + + is_decoding_o = 1'b1; + + unique case(1'b1) + + //irq_req_ctrl_i comes from a FF in the interrupt controller + //irq_enable_int: check again irq_enable_int because xIE could have changed + //don't serve in debug mode + irq_req_ctrl_i & irq_enable_int & (~debug_req_i) & (~debug_mode_q): + begin + //Serving the external interrupt + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = IRQ_FLUSH; + hwloop_mask_o = 1'b1; + end + + + (debug_req_i || trigger_match_i) & (~debug_mode_q): + begin + //Serving the debug + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = DBG_FLUSH; + end + + + default: + begin + + exc_kill_o = irq_req_ctrl_i ? 1'b1 : 1'b0; + + if(illegal_insn_i) begin + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = FLUSH_EX; + illegal_insn_n = 1'b1; + end else begin + + //decoding block + unique case (1'b1) + + jump_in_dec: begin + // handle unconditional jumps + // we can jump directly since we know the address already + // we don't need to worry about conditional branches here as they + // will be evaluated in the EX stage + pc_mux_o = PC_JUMP; + // if there is a jr stall, wait for it to be gone + if ((~jr_stall_o) && (~jump_done_q)) begin + pc_set_o = 1'b1; + jump_done = 1'b1; + end + + end + ebrk_insn_i: begin + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + if (debug_mode_q) + // we got back to the park loop in the debug rom + ctrl_fsm_ns = DBG_FLUSH; + + else if (ebrk_force_debug_mode) + // debug module commands us to enter debug mode anyway + ctrl_fsm_ns = DBG_FLUSH; + + else begin + // otherwise just a normal ebreak exception + ctrl_fsm_ns = FLUSH_EX; + end + + end + pipe_flush_i: begin + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = FLUSH_EX; + end + ecall_insn_i: begin + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = FLUSH_EX; + end + fencei_insn_i: begin + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = FLUSH_EX; + end + mret_insn_i | uret_insn_i | dret_insn_i: begin + halt_if_o = 1'b1; + halt_id_o = 1'b1; + ctrl_fsm_ns = FLUSH_EX; + end + csr_status_i: begin + halt_if_o = 1'b1; + ctrl_fsm_ns = id_ready_i ? FLUSH_EX : DECODE; + end + data_load_event_i: begin + ctrl_fsm_ns = id_ready_i ? ELW_EXE : DECODE; + halt_if_o = 1'b1; + end + default:; + + endcase // unique case (1'b1) + end + + if (debug_single_step_i & ~debug_mode_q) begin + // prevent any more instructions from executing + halt_if_o = 1'b1; + + // we don't handle dret here because its should be illegal + // anyway in this context + + // illegal, ecall, ebrk and xrettransition to later to a DBG + // state since we need the return address which is + // determined later + + // TODO: handle ebrk_force_debug_mode plus single stepping over ebreak + if (id_ready_i) begin + // make sure the current instruction has been executed + unique case(1'b1) + illegal_insn_i | ecall_insn_i: + ctrl_fsm_ns = FLUSH_EX; // TODO: flush ex + (~ebrk_force_debug_mode & ebrk_insn_i): + ctrl_fsm_ns = FLUSH_EX; + mret_insn_i | uret_insn_i: + ctrl_fsm_ns = FLUSH_EX; + branch_in_id: + ctrl_fsm_ns = DBG_WAIT_BRANCH; + default: + // regular instruction + ctrl_fsm_ns = DBG_FLUSH; + endcase // unique case (1'b1) + end + end + + end //decoding block + endcase + end //valid block + else begin + is_decoding_o = 1'b0; + perf_pipeline_stall_o = data_load_event_i; + end + end + + + // flush the pipeline, insert NOP into EX stage + FLUSH_EX: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + if (data_err_i) + begin //data error + // the current LW or SW have been blocked by the PMP + csr_save_ex_o = 1'b1; + csr_save_cause_o = 1'b1; + data_err_ack_o = 1'b1; + //no jump in this stage as we have to wait one cycle to go to Machine Mode + csr_cause_o = data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT; + ctrl_fsm_ns = FLUSH_WB; + //putting illegal to 0 as if it was 1, the core is going to jump to the exception of the EX stage, + //so the illegal was never executed + illegal_insn_n = 1'b0; + end //data erro + else if (ex_valid_i) begin + //check done to prevent data harzard in the CSR registers + ctrl_fsm_ns = FLUSH_WB; + + if(illegal_insn_q) begin + csr_save_id_o = 1'b1; + csr_save_cause_o = 1'b1; + csr_cause_o = EXC_CAUSE_ILLEGAL_INSN; + end else begin + unique case (1'b1) + ebrk_insn_i: begin + csr_save_id_o = 1'b1; + csr_save_cause_o = 1'b1; + csr_cause_o = EXC_CAUSE_BREAKPOINT; + end + ecall_insn_i: begin + csr_save_id_o = 1'b1; + csr_save_cause_o = 1'b1; + csr_cause_o = current_priv_lvl_i == PRIV_LVL_U ? EXC_CAUSE_ECALL_UMODE : EXC_CAUSE_ECALL_MMODE; + end + default:; + endcase // unique case (1'b1) + end + + end + end + + + IRQ_FLUSH: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + if (data_err_i) + begin //data error + // the current LW or SW have been blocked by the PMP + csr_save_ex_o = 1'b1; + csr_save_cause_o = 1'b1; + data_err_ack_o = 1'b1; + //no jump in this stage as we have to wait one cycle to go to Machine Mode + csr_cause_o = data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT; + ctrl_fsm_ns = FLUSH_WB; + + end //data error + else begin + if(irq_pending_i & irq_enable_int) begin + ctrl_fsm_ns = IRQ_TAKEN_ID; + end else begin + // we can go back to decode in case the IRQ is not taken (no ELW REPLAY) + exc_kill_o = 1'b1; + instr_valid_irq_flush_n = 1'b1; + ctrl_fsm_ns = DECODE; + end + end + end + + IRQ_FLUSH_ELW: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + perf_pipeline_stall_o = data_load_event_i; + + if(irq_pending_i & irq_enable_int) begin + ctrl_fsm_ns = IRQ_TAKEN_ID; + end else begin + // we can go back to decode in case the IRQ is not taken (no ELW REPLAY) + exc_kill_o = 1'b1; + ctrl_fsm_ns = DECODE; + end + end + + ELW_EXE: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + + //if we are here, a elw is executing now in the EX stage + //or if an interrupt has been received + //the ID stage contains the PC_ID of the elw, therefore halt_id is set to invalid the instruction + //If an interrupt occurs, we replay the ELW + //No needs to check irq_int_req_i since in the EX stage there is only the elw, no CSR pendings + if(id_ready_i) + ctrl_fsm_ns = ((debug_req_i || trigger_match_i) & ~debug_mode_q) ? DBG_FLUSH : IRQ_FLUSH_ELW; + // if from the ELW EXE we go to IRQ_FLUSH_ELW, it is assumed that if there was an IRQ req together with the grant and IE was valid, then + // there must be no hazard due to xIE + else + ctrl_fsm_ns = ELW_EXE; + + perf_pipeline_stall_o = data_load_event_i; + end + + IRQ_TAKEN_ID: + begin + is_decoding_o = 1'b0; + + pc_set_o = 1'b1; + pc_mux_o = PC_EXCEPTION; + exc_pc_mux_o = EXC_PC_IRQ; + exc_cause_o = irq_id_ctrl_i; + csr_irq_sec_o = irq_sec_ctrl_i; + + // IRQs (standard plus extension) + irq_ack_o = 1'b1; + if(irq_sec_ctrl_i) + trap_addr_mux_o = TRAP_MACHINE; + else + trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; + + csr_save_cause_o = 1'b1; + csr_cause_o = {1'b1,irq_id_ctrl_i}; + csr_save_id_o = 1'b1; + exc_ack_o = 1'b1; + ctrl_fsm_ns = DECODE; + end + + + IRQ_TAKEN_IF: + begin + is_decoding_o = 1'b0; + + pc_set_o = 1'b1; + pc_mux_o = PC_EXCEPTION; + exc_pc_mux_o = EXC_PC_IRQ; + exc_cause_o = irq_id_ctrl_i; + csr_irq_sec_o = irq_sec_ctrl_i; + + // IRQs (standard plus extension) + irq_ack_o = 1'b1; + if(irq_sec_ctrl_i) + trap_addr_mux_o = TRAP_MACHINE; + else + trap_addr_mux_o = current_priv_lvl_i == PRIV_LVL_U ? TRAP_USER : TRAP_MACHINE; + + csr_save_cause_o = 1'b1; + csr_cause_o = {1'b1,irq_id_ctrl_i}; + csr_save_if_o = 1'b1; + exc_ack_o = 1'b1; + ctrl_fsm_ns = DECODE; + end + + + // flush the pipeline, insert NOP into EX and WB stage + FLUSH_WB: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + ctrl_fsm_ns = DECODE; + + if(data_err_q) begin + //data_error + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + trap_addr_mux_o = TRAP_MACHINE; + //little hack during testing + exc_pc_mux_o = EXC_PC_EXCEPTION; + exc_cause_o = data_we_ex_i ? EXC_CAUSE_LOAD_FAULT : EXC_CAUSE_STORE_FAULT; + + end + else if (is_fetch_failed_i) begin + //data_error + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + trap_addr_mux_o = TRAP_MACHINE; + exc_pc_mux_o = EXC_PC_EXCEPTION; + exc_cause_o = EXC_CAUSE_INSTR_FAULT; + + end + else begin + if(illegal_insn_q) begin + //exceptions + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + trap_addr_mux_o = TRAP_MACHINE; + exc_pc_mux_o = EXC_PC_EXCEPTION; + illegal_insn_n = 1'b0; + if (debug_single_step_i && ~debug_mode_q) + ctrl_fsm_ns = DBG_TAKEN_IF; + end else begin + unique case(1'b1) + ebrk_insn_i: begin + //ebreak + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + trap_addr_mux_o = TRAP_MACHINE; + exc_pc_mux_o = EXC_PC_EXCEPTION; + + if (debug_single_step_i && ~debug_mode_q) + ctrl_fsm_ns = DBG_TAKEN_IF; + end + ecall_insn_i: begin + //ecall + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + trap_addr_mux_o = TRAP_MACHINE; + exc_pc_mux_o = EXC_PC_EXCEPTION; + // TODO: why is this here, signal only needed for async exceptions + exc_cause_o = EXC_CAUSE_ECALL_MMODE; + + if (debug_single_step_i && ~debug_mode_q) + ctrl_fsm_ns = DBG_TAKEN_IF; + end + + mret_insn_i: begin + csr_restore_mret_id_o = 1'b1; + ctrl_fsm_ns = XRET_JUMP; + end + uret_insn_i: begin + csr_restore_uret_id_o = 1'b1; + ctrl_fsm_ns = XRET_JUMP; + end + dret_insn_i: begin + csr_restore_dret_id_o = 1'b1; + ctrl_fsm_ns = XRET_JUMP; + end + + csr_status_i: begin + + end + pipe_flush_i: begin + ctrl_fsm_ns = WAIT_SLEEP; + end + fencei_insn_i: begin + // we just jump to instruction after the fence.i since that + // forces the instruction cache to refetch + pc_mux_o = PC_FENCEI; + pc_set_o = 1'b1; + end + default:; + endcase + end + end + + end + + XRET_JUMP: + begin + is_decoding_o = 1'b0; + ctrl_fsm_ns = DECODE; + unique case(1'b1) + mret_dec_i: begin + //mret + pc_mux_o = PC_MRET; + pc_set_o = 1'b1; + end + uret_dec_i: begin + //uret + pc_mux_o = PC_URET; + pc_set_o = 1'b1; + end + dret_dec_i: begin + //dret + //TODO: is illegal when not in debug mode + pc_mux_o = PC_DRET; + pc_set_o = 1'b1; + debug_mode_n = 1'b0; + end + default:; + endcase + + if (debug_single_step_i && ~debug_mode_q) begin + ctrl_fsm_ns = DBG_TAKEN_IF; + end + end + + // a branch was in ID when a trying to go to debug rom wait until we can + // determine branch target address (for saving into dpc) before proceeding + DBG_WAIT_BRANCH: + begin + is_decoding_o = 1'b0; + halt_if_o = 1'b1; + + if (branch_taken_ex_i) begin + // there is a branch in the EX stage that is taken + pc_mux_o = PC_BRANCH; + pc_set_o = 1'b1; + end + + ctrl_fsm_ns = DBG_FLUSH; + end + + // We enter this state when we encounter + // 1. ebreak during debug mode + // 2. ebreak with forced entry into debug mode (ebreakm or ebreaku set). + // 3. halt request during decode + // Regular ebreak's go through FLUSH_EX and FLUSH_WB. + // For 1. we don't update dcsr and dpc while for 2. and 3. we do + // (debug-spec p.39). Critically dpc is set to the address of ebreak and + // not to the next instruction's (which is why we save the pc in id). + DBG_TAKEN_ID: + begin + is_decoding_o = 1'b0; + pc_set_o = 1'b1; + pc_mux_o = PC_EXCEPTION; + exc_pc_mux_o = EXC_PC_DBD; + if (((debug_req_i || trigger_match_i) && (~debug_mode_q)) || + (ebrk_insn_i && ebrk_force_debug_mode && (~debug_mode_q))) begin + csr_save_cause_o = 1'b1; + csr_save_id_o = 1'b1; + debug_csr_save_o = 1'b1; + if (debug_req_i) + debug_cause_o = DBG_CAUSE_HALTREQ; + if (ebrk_insn_i) + debug_cause_o = DBG_CAUSE_EBREAK; + if (trigger_match_i) + debug_cause_o = DBG_CAUSE_TRIGGER; + end + ctrl_fsm_ns = DECODE; + debug_mode_n = 1'b1; + end + + DBG_TAKEN_IF: + begin + is_decoding_o = 1'b0; + pc_set_o = 1'b1; + pc_mux_o = PC_EXCEPTION; + exc_pc_mux_o = EXC_PC_DBD; + csr_save_cause_o = 1'b1; + debug_csr_save_o = 1'b1; + if (debug_single_step_i) + debug_cause_o = DBG_CAUSE_STEP; + if (debug_req_i) + debug_cause_o = DBG_CAUSE_HALTREQ; + if (ebrk_insn_i) + debug_cause_o = DBG_CAUSE_EBREAK; + if (trigger_match_i) + debug_cause_o = DBG_CAUSE_TRIGGER; + csr_save_if_o = 1'b1; + ctrl_fsm_ns = DECODE; + debug_mode_n = 1'b1; + end + + DBG_FLUSH: + begin + is_decoding_o = 1'b0; + + halt_if_o = 1'b1; + halt_id_o = 1'b1; + + perf_pipeline_stall_o = data_load_event_i; + + if (data_err_i) + begin //data error + // the current LW or SW have been blocked by the PMP + csr_save_ex_o = 1'b1; + csr_save_cause_o = 1'b1; + data_err_ack_o = 1'b1; + //no jump in this stage as we have to wait one cycle to go to Machine Mode + csr_cause_o = data_we_ex_i ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT; + ctrl_fsm_ns = FLUSH_WB; + + end //data error + else begin + if(debug_mode_q) begin //ebreak in debug rom + ctrl_fsm_ns = DBG_TAKEN_ID; + end else if(data_load_event_i) begin + ctrl_fsm_ns = DBG_TAKEN_ID; + end else if (debug_single_step_i) begin + // save the next instruction when single stepping regular insn + ctrl_fsm_ns = DBG_TAKEN_IF; + end else begin + ctrl_fsm_ns = DBG_TAKEN_ID; + end + end + end + // Debug end + + default: begin + is_decoding_o = 1'b0; + instr_req_o = 1'b0; + ctrl_fsm_ns = RESET; + end + endcase + end + + ///////////////////////////////////////////////////////////// + // ____ _ _ _ ____ _ _ // + // / ___|| |_ __ _| | | / ___|___ _ __ | |_ _ __ ___ | | // + // \___ \| __/ _` | | | | | / _ \| '_ \| __| '__/ _ \| | // + // ___) | || (_| | | | | |__| (_) | | | | |_| | | (_) | | // + // |____/ \__\__,_|_|_| \____\___/|_| |_|\__|_| \___/|_| // + // // + ///////////////////////////////////////////////////////////// + always_comb + begin + load_stall_o = 1'b0; + jr_stall_o = 1'b0; + deassert_we_o = 1'b0; + + // deassert WE when the core is not decoding instructions + if (~is_decoding_o) + deassert_we_o = 1'b1; + + // deassert WE in case of illegal instruction + if (illegal_insn_i) + deassert_we_o = 1'b1; + + // Stall because of load operation + if ( + ( (data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) || + (wb_ready_i == 1'b0) && (regfile_we_wb_i == 1'b1) + ) && + ( (reg_d_ex_is_reg_a_i == 1'b1) || (reg_d_ex_is_reg_b_i == 1'b1) || (reg_d_ex_is_reg_c_i == 1'b1) || + (is_decoding_o && regfile_we_id_i && (regfile_waddr_ex_i == regfile_alu_waddr_id_i)) ) + ) + begin + deassert_we_o = 1'b1; + load_stall_o = 1'b1; + end + + // Stall because of jr path + // - always stall if a result is to be forwarded to the PC + // we don't care about in which state the ctrl_fsm is as we deassert_we + // anyway when we are not in DECODE + if ((jump_in_dec_i == BRANCH_JALR) && + (((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_a_i == 1'b1)) || + ((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_a_i == 1'b1)) || + ((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_a_i == 1'b1))) ) + begin + jr_stall_o = 1'b1; + deassert_we_o = 1'b1; + end + end + + + // stall because of misaligned data access + assign misaligned_stall_o = data_misaligned_i; + + // APU dependency stalls (data hazards) + assign apu_stall_o = apu_read_dep_i | (apu_write_dep_i & ~apu_en_i); + + // Forwarding control unit + always_comb + begin + // default assignements + operand_a_fw_mux_sel_o = SEL_REGFILE; + operand_b_fw_mux_sel_o = SEL_REGFILE; + operand_c_fw_mux_sel_o = SEL_REGFILE; + + // Forwarding WB -> ID + if (regfile_we_wb_i == 1'b1) + begin + if (reg_d_wb_is_reg_a_i == 1'b1) + operand_a_fw_mux_sel_o = SEL_FW_WB; + if (reg_d_wb_is_reg_b_i == 1'b1) + operand_b_fw_mux_sel_o = SEL_FW_WB; + if (reg_d_wb_is_reg_c_i == 1'b1) + operand_c_fw_mux_sel_o = SEL_FW_WB; + end + + // Forwarding EX -> ID + if (regfile_alu_we_fw_i == 1'b1) + begin + if (reg_d_alu_is_reg_a_i == 1'b1) + operand_a_fw_mux_sel_o = SEL_FW_EX; + if (reg_d_alu_is_reg_b_i == 1'b1) + operand_b_fw_mux_sel_o = SEL_FW_EX; + if (reg_d_alu_is_reg_c_i == 1'b1) + operand_c_fw_mux_sel_o = SEL_FW_EX; + end + + // for misaligned memory accesses + if (data_misaligned_i) + begin + operand_a_fw_mux_sel_o = SEL_FW_EX; + operand_b_fw_mux_sel_o = SEL_REGFILE; + end else if (mult_multicycle_i) begin + operand_c_fw_mux_sel_o = SEL_FW_EX; + end + end + + // update registers + always_ff @(posedge clk , negedge rst_n) + begin : UPDATE_REGS + if ( rst_n == 1'b0 ) + begin + ctrl_fsm_cs <= RESET; + jump_done_q <= 1'b0; + boot_done_q <= 1'b0; + data_err_q <= 1'b0; + + debug_mode_q <= 1'b0; + illegal_insn_q <= 1'b0; + + instr_valid_irq_flush_q <= 1'b0; + + end + else + begin + ctrl_fsm_cs <= ctrl_fsm_ns; + boot_done_q <= boot_done | (~boot_done & boot_done_q); + // clear when id is valid (no instruction incoming) + jump_done_q <= jump_done & (~id_ready_i); + + data_err_q <= data_err_i; + + debug_mode_q <= debug_mode_n; + + illegal_insn_q <= illegal_insn_n; + + instr_valid_irq_flush_q <= instr_valid_irq_flush_n; + end + end + + // Performance Counters + assign perf_jump_o = (jump_in_id_i == BRANCH_JAL || jump_in_id_i == BRANCH_JALR); + assign perf_jr_stall_o = jr_stall_o; + assign perf_ld_stall_o = load_stall_o; + + // debug mode + assign debug_mode_o = debug_mode_q; + + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + // make sure that taken branches do not happen back-to-back, as this is not + // possible without branch prediction in the IF stage + `ifndef VERILATOR + assert property ( + @(posedge clk) (branch_taken_ex_i) |=> (~branch_taken_ex_i) ) else $warning("Two branches back-to-back are taken"); + `endif +endmodule // controller diff --git a/hw/deps/riscv/riscv_core.sv b/hw/deps/riscv/riscv_core.sv new file mode 100644 index 0000000..ffaccf0 --- /dev/null +++ b/hw/deps/riscv/riscv_core.sv @@ -0,0 +1,1284 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Matthias Baer - baermatt@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Andreas Traber - atraber@student.ethz.ch // +// Sven Stucki - svstucki@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: Top level module // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Top level module of the RISC-V core. // +// added APU, FPU parameter to include the APU_dispatcher // +// and the FPU // +// // +//////////////////////////////////////////////////////////////////////////////// + +import apu_core_package::*; + +`include "riscv_config.sv" + +import riscv_defines::*; + +module riscv_core +#( + parameter PULP_HWLP = 0, + parameter INSTR_RDATA_WIDTH = 128, + parameter N_EXT_PERF_COUNTERS = 0, + parameter PULP_CLUSTER = 1, + parameter FPU = 0, + parameter PULP_ZFINX = 0, + parameter NUM_MHPMCOUNTERS = 1, + parameter SHARED_FP = 0, + parameter SHARED_DSP_MULT = 0, + parameter SHARED_INT_DIV = 0, + parameter SHARED_FP_DIVSQRT = 0, + parameter WAPUTYPE = 0, + parameter APU_NARGS_CPU = 3, + parameter APU_WOP_CPU = 6, + parameter APU_NDSFLAGS_CPU = 15, + parameter APU_NUSFLAGS_CPU = 5, + parameter N_PMP_ENTRIES = 16 +) +( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic clock_en_i, // enable clock, otherwise it is gated + input logic scan_cg_en_i, // enable all clock gates for testing + + // Core ID, Cluster ID, debug mode halt address and boot address are considered more or less static + input logic [31:0] boot_addr_i, + input logic [31:0] dm_halt_addr_i, + input logic [31:0] hart_id_i, + + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [INSTR_RDATA_WIDTH-1:0] instr_rdata_i, + + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + + output logic [5:0] data_atop_o, + output logic data_buffer_o, + output logic data_unaligned_o, + + // apu-interconnect + // handshake signals + output logic apu_master_req_o, + output logic apu_master_ready_o, + input logic apu_master_gnt_i, + // request channel + output logic [APU_NARGS_CPU-1:0][31:0] apu_master_operands_o, + output logic [APU_WOP_CPU-1:0] apu_master_op_o, + output logic [WAPUTYPE-1:0] apu_master_type_o, + output logic [APU_NDSFLAGS_CPU-1:0] apu_master_flags_o, + // response channel + input logic apu_master_valid_i, + input logic [31:0] apu_master_result_i, + input logic [APU_NUSFLAGS_CPU-1:0] apu_master_flags_i, + + // Interrupt inputs + output logic irq_ack_o, + output logic [5:0] irq_id_o, + + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [47:0] irq_fast_i, + + // Debug Interface + input logic debug_req_i, + + // CPU Control Signals + input logic fetch_enable_i, + output logic core_busy_o, + + // PMP coonfiguration + // NOTE: when pmp_conf_override_i is high, the pmp configuration is taken from the input + // (i.e., pmp_addr_i and pmp_cfg_i) instead of from the CS registers. + input logic pmp_conf_override_i, + input logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_i, + input logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_i +); + + // Unused parameters and signals (left in code for future design extensions) + localparam PULP_SECURE = 1; + localparam USE_PMP = 1; // if PULP_SECURE is 1, you can still not use the PMP + localparam A_EXTENSION = 1; + localparam FP_DIVSQRT = FPU; + //localparam SHARED_FP = 0; + //localparam SHARED_DSP_MULT = 0; + localparam SHARED_INT_MULT = 0; + //localparam SHARED_INT_DIV = 0; + //localparam SHARED_FP_DIVSQRT = 0; + localparam DEBUG_TRIGGER_EN = 1; + + // Unused signals related to above unused parameters + // Left in code (with their original _i, _o postfixes) for future design extensions; + // these used to be former inputs/outputs of RI5CY + + logic irq_sec_i; + logic sec_lvl_o; + + localparam N_HWLP = 2; + localparam N_HWLP_BITS = $clog2(N_HWLP); + localparam APU = ((SHARED_DSP_MULT==1) | (SHARED_INT_DIV==1) | (FPU==1)) ? 1 : 0; + + + // IF/ID signals + logic is_hwlp_id; + logic [N_HWLP-1:0] hwlp_dec_cnt_id; + logic instr_valid_id; + logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage + logic is_compressed_id; + logic is_fetch_failed_id; + logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage + logic [31:0] pc_if; // Program counter in IF stage + logic [31:0] pc_id; // Program counter in ID stage + + logic clear_instr_valid; + logic pc_set; + logic [2:0] pc_mux_id; // Mux selector for next PC + logic [2:0] exc_pc_mux_id; // Mux selector for exception PC + logic [5:0] m_exc_vec_pc_mux_id; // Mux selector for vectored IRQ PC + logic [5:0] u_exc_vec_pc_mux_id; // Mux selector for vectored IRQ PC + logic [5:0] exc_cause; + logic [1:0] trap_addr_mux; + + // ID performance counter signals + logic is_decoding; + + logic useincr_addr_ex; // Active when post increment + logic data_misaligned; + + logic mult_multicycle; + + // Jump and branch target and decision (EX->IF) + logic [31:0] jump_target_id, jump_target_ex; + logic branch_in_ex; + logic branch_decision; + + logic ctrl_busy; + logic if_busy; + logic lsu_busy; + logic apu_busy; + + logic [31:0] pc_ex; // PC of last executed branch or p.elw + + // ALU Control + logic alu_en_ex; + logic [ALU_OP_WIDTH-1:0] alu_operator_ex; + logic [31:0] alu_operand_a_ex; + logic [31:0] alu_operand_b_ex; + logic [31:0] alu_operand_c_ex; + logic [ 4:0] bmask_a_ex; + logic [ 4:0] bmask_b_ex; + logic [ 1:0] imm_vec_ext_ex; + logic [ 1:0] alu_vec_mode_ex; + logic alu_is_clpx_ex, alu_is_subrot_ex; + logic [ 1:0] alu_clpx_shift_ex; + + // Multiplier Control + logic [ 2:0] mult_operator_ex; + logic [31:0] mult_operand_a_ex; + logic [31:0] mult_operand_b_ex; + logic [31:0] mult_operand_c_ex; + logic mult_en_ex; + logic mult_sel_subword_ex; + logic [ 1:0] mult_signed_mode_ex; + logic [ 4:0] mult_imm_ex; + logic [31:0] mult_dot_op_a_ex; + logic [31:0] mult_dot_op_b_ex; + logic [31:0] mult_dot_op_c_ex; + logic [ 1:0] mult_dot_signed_ex; + logic mult_is_clpx_ex; + logic [ 1:0] mult_clpx_shift_ex; + logic mult_clpx_img_ex; + + // FPU + logic [C_PC-1:0] fprec_csr; + logic [C_RM-1:0] frm_csr; + logic [C_FFLAG-1:0] fflags; + logic [C_FFLAG-1:0] fflags_csr; + logic fflags_we; + + // APU + logic apu_en_ex; + logic [WAPUTYPE-1:0] apu_type_ex; + logic [APU_NDSFLAGS_CPU-1:0] apu_flags_ex; + logic [APU_WOP_CPU-1:0] apu_op_ex; + logic [1:0] apu_lat_ex; + logic [APU_NARGS_CPU-1:0][31:0] apu_operands_ex; + logic [5:0] apu_waddr_ex; + + logic [2:0][5:0] apu_read_regs; + logic [2:0] apu_read_regs_valid; + logic apu_read_dep; + logic [1:0][5:0] apu_write_regs; + logic [1:0] apu_write_regs_valid; + logic apu_write_dep; + + logic perf_apu_type; + logic perf_apu_cont; + logic perf_apu_dep; + logic perf_apu_wb; + + // Register Write Control + logic [5:0] regfile_waddr_ex; + logic regfile_we_ex; + logic [5:0] regfile_waddr_fw_wb_o; // From WB to ID + logic regfile_we_wb; + logic [31:0] regfile_wdata; + + logic [5:0] regfile_alu_waddr_ex; + logic regfile_alu_we_ex; + + logic [5:0] regfile_alu_waddr_fw; + logic regfile_alu_we_fw; + logic [31:0] regfile_alu_wdata_fw; + + // CSR control + logic csr_access_ex; + logic [1:0] csr_op_ex; + logic [23:0] mtvec, utvec; + logic [1:0] mtvec_mode; + logic [1:0] utvec_mode; + + logic csr_access; + logic [1:0] csr_op; + csr_num_e csr_addr; + csr_num_e csr_addr_int; + logic [31:0] csr_rdata; + logic [31:0] csr_wdata; + PrivLvl_t current_priv_lvl; + + // Stack Protection + logic stack_access; + logic [31:0] stack_base, + stack_limit; + + // Data Memory Control: From ID stage (id-ex pipe) <--> load store unit + logic data_we_ex; + logic [5:0] data_atop_ex; + logic data_buffer_ex; + logic [1:0] data_type_ex; + logic [1:0] data_sign_ext_ex; + logic [1:0] data_reg_offset_ex; + logic data_req_ex; + logic data_load_event_ex; + logic data_misaligned_ex; + + logic [31:0] lsu_rdata; + + // stall control + logic halt_if; + logic id_ready; + logic ex_ready; + + logic id_valid; + logic ex_valid; + logic wb_valid; + + logic lsu_ready_ex; + logic lsu_ready_wb; + + logic apu_ready_wb; + + // Signals between instruction core interface and pipe (if and id stages) + logic instr_req_int; // Id stage asserts a req to instruction core interface + + // Interrupts + logic m_irq_enable, u_irq_enable; + logic csr_irq_sec; + logic [31:0] mepc, uepc, depc; + + logic csr_save_cause; + logic csr_save_if; + logic csr_save_id; + logic csr_save_ex; + logic [6:0] csr_cause; + logic csr_restore_mret_id; + logic csr_restore_uret_id; + + logic csr_restore_dret_id; + + // debug mode and dcsr configuration + logic debug_mode; + logic [2:0] debug_cause; + logic debug_csr_save; + logic debug_single_step; + logic debug_ebreakm; + logic debug_ebreaku; + logic trigger_match; + + // Hardware loop controller signals + logic [N_HWLP-1:0] [31:0] hwlp_start; + logic [N_HWLP-1:0] [31:0] hwlp_end; + logic [N_HWLP-1:0] [31:0] hwlp_cnt; + + // used to write from CS registers to hardware loop registers + logic [N_HWLP_BITS-1:0] csr_hwlp_regid; + logic [2:0] csr_hwlp_we; + logic [31:0] csr_hwlp_data; + + // Performance Counters + logic perf_imiss; + logic perf_jump; + logic perf_jr_stall; + logic perf_ld_stall; + logic perf_pipeline_stall; + + //core busy signals + logic core_ctrl_firstfetch, core_busy_int, core_busy_q; + + //pmp signals (sent to PMP) + logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr; + logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg; + + //pmp signal (set by CS) + logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_cs; + logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_cs; + + logic data_req_pmp; + logic [31:0] data_addr_pmp; + logic data_gnt_pmp; + logic data_err_pmp; + logic data_err_ack; + logic instr_req_pmp; + logic instr_gnt_pmp; + logic [31:0] instr_addr_pmp; + logic instr_err_pmp; + + // interrupt signals + logic irq_pending; + logic [5:0] irq_id; + + //Simchecker signal + logic is_interrupt; + assign is_interrupt = (pc_mux_id == PC_EXCEPTION) && (exc_pc_mux_id == EXC_PC_IRQ); + assign m_exc_vec_pc_mux_id = (mtvec_mode == 2'b0) ? 6'h0 : exc_cause; + assign u_exc_vec_pc_mux_id = (utvec_mode == 2'b0) ? 6'h0 : exc_cause; + + // N_EXT_PERF_COUNTERS == 0 + assign ext_perf_counters_i = 'b0; + + // PULP_SECURE == 0 + assign irq_sec_i = 1'b0; + + // APU master signals + generate + if ( SHARED_FP ) begin + assign apu_master_type_o = apu_type_ex; + assign apu_master_flags_o = apu_flags_ex; + assign fflags_csr = apu_master_flags_i; + end + else begin + assign apu_master_type_o = '0; + assign apu_master_flags_o = '0; + assign fflags_csr = fflags; + end + endgenerate + +`ifdef APU_TRACE + + int apu_trace; + string fn; + string apu_waddr_trace; + + + // open/close output file for writing + initial + begin + wait(rst_ni == 1'b1); + // hart_id_i[10:5] and hart_id_i[3:0] mean cluster_id and core_id in PULP + $sformat(fn, "apu_trace_core_%h_%h.log", hart_id_i[10:5], hart_id_i[3:0]); + $display("[APU_TRACER] Output filename is: %s", fn); + apu_trace = $fopen(fn, "w"); + $fwrite(apu_trace, "time register \tresult\n"); + + while(1) begin + + @(negedge clk_i); + if (ex_stage_i.apu_valid == 1'b1) begin + if (ex_stage_i.apu_waddr>31) + $sformat(apu_waddr_trace, "f%d",ex_stage_i.apu_waddr[4:0]); + else + $sformat(apu_waddr_trace, "x%d",ex_stage_i.apu_waddr[4:0]); + $fwrite(apu_trace, "%t %s \t\t%h\n", $time, apu_waddr_trace, ex_stage_i.apu_result); + end + end + + end + + final + begin + $fclose(apu_trace); + end +`endif + + ////////////////////////////////////////////////////////////////////////////////////////////// + // ____ _ _ __ __ _ // + // / ___| | ___ ___| | __ | \/ | __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ // + // | | | |/ _ \ / __| |/ / | |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '_ ` _ \ / _ \ '_ \| __| // + // | |___| | (_) | (__| < | | | | (_| | | | | (_| | (_| | __/ | | | | | __/ | | | |_ // + // \____|_|\___/ \___|_|\_\ |_| |_|\__,_|_| |_|\__,_|\__, |\___|_| |_| |_|\___|_| |_|\__| // + // |___/ // + ////////////////////////////////////////////////////////////////////////////////////////////// + + logic clk; + + logic clock_en; + + + logic sleeping; + + + assign core_busy_o = core_ctrl_firstfetch ? 1'b1 : core_busy_q; + + // if we are sleeping on a barrier let's just wait on the instruction + // interface to finish loading instructions + assign core_busy_int = (PULP_CLUSTER & data_load_event_ex & data_req_o) ? (if_busy | apu_busy) : (if_busy | ctrl_busy | lsu_busy | apu_busy); + + assign clock_en = PULP_CLUSTER ? clock_en_i | core_busy_o : irq_pending | debug_req_i | core_busy_o; + + assign sleeping = ~core_busy_o; + + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if (rst_ni == 1'b0) begin + core_busy_q <= 1'b0; + end else begin + core_busy_q <= core_busy_int; + end + end + + // main clock gate of the core + // generates all clocks except the one for the debug unit which is + // independent + cluster_clock_gating core_clock_gate_i + ( + .clk_i ( clk_i ), + .en_i ( clock_en ), + .test_en_i ( scan_cg_en_i ), + .clk_o ( clk ) + ); + + ////////////////////////////////////////////////// + // ___ _____ ____ _____ _ ____ _____ // + // |_ _| ___| / ___|_ _|/ \ / ___| ____| // + // | || |_ \___ \ | | / _ \| | _| _| // + // | || _| ___) || |/ ___ \ |_| | |___ // + // |___|_| |____/ |_/_/ \_\____|_____| // + // // + ////////////////////////////////////////////////// + riscv_if_stage + #( + .N_HWLP ( N_HWLP ), + .RDATA_WIDTH ( INSTR_RDATA_WIDTH ), + .FPU ( FPU ) + ) + if_stage_i + ( + .clk ( clk ), + .rst_n ( rst_ni ), + + // boot address + .boot_addr_i ( boot_addr_i[31:1] ), + + // debug mode halt address + .dm_halt_addr_i ( dm_halt_addr_i[31:2] ), + + // trap vector location + .m_trap_base_addr_i ( mtvec ), + .u_trap_base_addr_i ( utvec ), + .trap_addr_mux_i ( trap_addr_mux ), + + // instruction request control + .req_i ( instr_req_int ), + + // instruction cache interface + .instr_req_o ( instr_req_pmp ), + .instr_addr_o ( instr_addr_pmp ), + .instr_gnt_i ( instr_gnt_pmp ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + .instr_err_pmp_i ( instr_err_pmp ), + + // outputs to ID stage + .hwlp_dec_cnt_id_o ( hwlp_dec_cnt_id ), + .is_hwlp_id_o ( is_hwlp_id ), + .instr_valid_id_o ( instr_valid_id ), + .instr_rdata_id_o ( instr_rdata_id ), + .is_compressed_id_o ( is_compressed_id ), + .illegal_c_insn_id_o ( illegal_c_insn_id ), + .pc_if_o ( pc_if ), + .pc_id_o ( pc_id ), + .is_fetch_failed_o ( is_fetch_failed_id ), + + // control signals + .clear_instr_valid_i ( clear_instr_valid ), + .pc_set_i ( pc_set ), + + .mepc_i ( mepc ), // exception return address + .uepc_i ( uepc ), // exception return address + + .depc_i ( depc ), // debug return address + + .pc_mux_i ( pc_mux_id ), // sel for pc multiplexer + .exc_pc_mux_i ( exc_pc_mux_id ), + .m_exc_vec_pc_mux_i ( m_exc_vec_pc_mux_id ), + .u_exc_vec_pc_mux_i ( u_exc_vec_pc_mux_id ), + + // from hwloop registers + .hwlp_start_i ( hwlp_start ), + .hwlp_end_i ( hwlp_end ), + .hwlp_cnt_i ( hwlp_cnt ), + + + // Jump targets + .jump_target_id_i ( jump_target_id ), + .jump_target_ex_i ( jump_target_ex ), + + // pipeline stalls + .halt_if_i ( halt_if ), + .id_ready_i ( id_ready ), + + .if_busy_o ( if_busy ), + .perf_imiss_o ( perf_imiss ) + ); + + + ///////////////////////////////////////////////// + // ___ ____ ____ _____ _ ____ _____ // + // |_ _| _ \ / ___|_ _|/ \ / ___| ____| // + // | || | | | \___ \ | | / _ \| | _| _| // + // | || |_| | ___) || |/ ___ \ |_| | |___ // + // |___|____/ |____/ |_/_/ \_\____|_____| // + // // + ///////////////////////////////////////////////// + riscv_id_stage + #( + .PULP_HWLP ( PULP_HWLP ), + .N_HWLP ( N_HWLP ), + .PULP_SECURE ( PULP_SECURE ), + .USE_PMP ( USE_PMP ), + .A_EXTENSION ( A_EXTENSION ), + .APU ( APU ), + .FPU ( FPU ), + .PULP_ZFINX ( PULP_ZFINX ), + .FP_DIVSQRT ( FP_DIVSQRT ), + .SHARED_FP ( SHARED_FP ), + .SHARED_DSP_MULT ( SHARED_DSP_MULT ), + .SHARED_INT_MULT ( SHARED_INT_MULT ), + .SHARED_INT_DIV ( SHARED_INT_DIV ), + .SHARED_FP_DIVSQRT ( SHARED_FP_DIVSQRT ), + .WAPUTYPE ( WAPUTYPE ), + .APU_NARGS_CPU ( APU_NARGS_CPU ), + .APU_WOP_CPU ( APU_WOP_CPU ), + .APU_NDSFLAGS_CPU ( APU_NDSFLAGS_CPU ), + .APU_NUSFLAGS_CPU ( APU_NUSFLAGS_CPU ), + .DEBUG_TRIGGER_EN ( DEBUG_TRIGGER_EN ) + ) + id_stage_i + ( + .clk ( clk ), + .rst_n ( rst_ni ), + + .scan_cg_en_i ( scan_cg_en_i ), + + // Processor Enable + .fetch_enable_i ( fetch_enable_i ), + .ctrl_busy_o ( ctrl_busy ), + .core_ctrl_firstfetch_o ( core_ctrl_firstfetch ), + .is_decoding_o ( is_decoding ), + + // Interface to instruction memory + .hwlp_dec_cnt_i ( hwlp_dec_cnt_id ), + .is_hwlp_i ( is_hwlp_id ), + .instr_valid_i ( instr_valid_id ), + .instr_rdata_i ( instr_rdata_id ), + .instr_req_o ( instr_req_int ), + + // Jumps and branches + .branch_in_ex_o ( branch_in_ex ), + .branch_decision_i ( branch_decision ), + .jump_target_o ( jump_target_id ), + + // IF and ID control signals + .clear_instr_valid_o ( clear_instr_valid ), + .pc_set_o ( pc_set ), + .pc_mux_o ( pc_mux_id ), + .exc_pc_mux_o ( exc_pc_mux_id ), + .exc_cause_o ( exc_cause ), + .trap_addr_mux_o ( trap_addr_mux ), + .illegal_c_insn_i ( illegal_c_insn_id ), + .is_compressed_i ( is_compressed_id ), + .is_fetch_failed_i ( is_fetch_failed_id ), + + .pc_if_i ( pc_if ), + .pc_id_i ( pc_id ), + + // Stalls + .halt_if_o ( halt_if ), + + .id_ready_o ( id_ready ), + .ex_ready_i ( ex_ready ), + .wb_ready_i ( lsu_ready_wb ), + + .id_valid_o ( id_valid ), + .ex_valid_i ( ex_valid ), + + // From the Pipeline ID/EX + .pc_ex_o ( pc_ex ), + + .alu_en_ex_o ( alu_en_ex ), + .alu_operator_ex_o ( alu_operator_ex ), + .alu_operand_a_ex_o ( alu_operand_a_ex ), + .alu_operand_b_ex_o ( alu_operand_b_ex ), + .alu_operand_c_ex_o ( alu_operand_c_ex ), + .bmask_a_ex_o ( bmask_a_ex ), + .bmask_b_ex_o ( bmask_b_ex ), + .imm_vec_ext_ex_o ( imm_vec_ext_ex ), + .alu_vec_mode_ex_o ( alu_vec_mode_ex ), + .alu_is_clpx_ex_o ( alu_is_clpx_ex ), + .alu_is_subrot_ex_o ( alu_is_subrot_ex ), + .alu_clpx_shift_ex_o ( alu_clpx_shift_ex ), + + .regfile_waddr_ex_o ( regfile_waddr_ex ), + .regfile_we_ex_o ( regfile_we_ex ), + + .regfile_alu_we_ex_o ( regfile_alu_we_ex ), + .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), + + // MUL + .mult_operator_ex_o ( mult_operator_ex ), // from ID to EX stage + .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage + .mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage + .mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage + .mult_operand_a_ex_o ( mult_operand_a_ex ), // from ID to EX stage + .mult_operand_b_ex_o ( mult_operand_b_ex ), // from ID to EX stage + .mult_operand_c_ex_o ( mult_operand_c_ex ), // from ID to EX stage + .mult_imm_ex_o ( mult_imm_ex ), // from ID to EX stage + + .mult_dot_op_a_ex_o ( mult_dot_op_a_ex ), // from ID to EX stage + .mult_dot_op_b_ex_o ( mult_dot_op_b_ex ), // from ID to EX stage + .mult_dot_op_c_ex_o ( mult_dot_op_c_ex ), // from ID to EX stage + .mult_dot_signed_ex_o ( mult_dot_signed_ex ), // from ID to EX stage + .mult_is_clpx_ex_o ( mult_is_clpx_ex ), // from ID to EX stage + .mult_clpx_shift_ex_o ( mult_clpx_shift_ex ), // from ID to EX stage + .mult_clpx_img_ex_o ( mult_clpx_img_ex ), // from ID to EX stage + + // FPU + .frm_i ( frm_csr ), + + // APU + .apu_en_ex_o ( apu_en_ex ), + .apu_type_ex_o ( apu_type_ex ), + .apu_op_ex_o ( apu_op_ex ), + .apu_lat_ex_o ( apu_lat_ex ), + .apu_operands_ex_o ( apu_operands_ex ), + .apu_flags_ex_o ( apu_flags_ex ), + .apu_waddr_ex_o ( apu_waddr_ex ), + + .apu_read_regs_o ( apu_read_regs ), + .apu_read_regs_valid_o ( apu_read_regs_valid ), + .apu_read_dep_i ( apu_read_dep ), + .apu_write_regs_o ( apu_write_regs ), + .apu_write_regs_valid_o ( apu_write_regs_valid ), + .apu_write_dep_i ( apu_write_dep ), + .apu_perf_dep_o ( perf_apu_dep ), + .apu_busy_i ( apu_busy ), + + // CSR ID/EX + .csr_access_ex_o ( csr_access_ex ), + .csr_op_ex_o ( csr_op_ex ), + .current_priv_lvl_i ( current_priv_lvl ), + .csr_irq_sec_o ( csr_irq_sec ), + .csr_cause_o ( csr_cause ), + .csr_save_if_o ( csr_save_if ), // control signal to save pc + .csr_save_id_o ( csr_save_id ), // control signal to save pc + .csr_save_ex_o ( csr_save_ex ), // control signal to save pc + .csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc + .csr_restore_uret_id_o ( csr_restore_uret_id ), // control signal to restore pc + + .csr_restore_dret_id_o ( csr_restore_dret_id ), // control signal to restore pc + + .csr_save_cause_o ( csr_save_cause ), + + // hardware loop signals to IF hwlp controller + .hwlp_start_o ( hwlp_start ), + .hwlp_end_o ( hwlp_end ), + .hwlp_cnt_o ( hwlp_cnt ), + + // hardware loop signals from CSR + .csr_hwlp_regid_i ( csr_hwlp_regid ), + .csr_hwlp_we_i ( csr_hwlp_we ), + .csr_hwlp_data_i ( csr_hwlp_data ), + + // LSU + .data_req_ex_o ( data_req_ex ), // to load store unit + .data_we_ex_o ( data_we_ex ), // to load store unit + .atop_ex_o ( data_atop_ex ), + .buffer_ex_o ( data_buffer_ex ), + .data_type_ex_o ( data_type_ex ), // to load store unit + .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit + .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit + .data_load_event_ex_o ( data_load_event_ex ), // to load store unit + + .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit + + .prepost_useincr_ex_o ( useincr_addr_ex ), + .data_misaligned_i ( data_misaligned ), + .data_err_i ( data_err_pmp ), + .data_err_ack_o ( data_err_ack ), + + + // Interrupt Signals + .irq_pending_i ( irq_pending ), // incoming interrupts + .irq_id_i ( irq_id ), + .irq_sec_i ( (PULP_SECURE) ? irq_sec_i : 1'b0 ), + .m_irq_enable_i ( m_irq_enable ), + .u_irq_enable_i ( u_irq_enable ), + .irq_ack_o ( irq_ack_o ), + .irq_id_o ( irq_id_o ), + + // Debug Signal + .debug_mode_o ( debug_mode ), + .debug_cause_o ( debug_cause ), + .debug_csr_save_o ( debug_csr_save ), + .debug_req_i ( debug_req_i ), + .debug_single_step_i ( debug_single_step ), + .debug_ebreakm_i ( debug_ebreakm ), + .debug_ebreaku_i ( debug_ebreaku ), + .trigger_match_i ( trigger_match ), + + // Forward Signals + .regfile_waddr_wb_i ( regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file + .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file + + .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ), + .regfile_alu_we_fw_i ( regfile_alu_we_fw ), + .regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ), + + // from ALU + .mult_multicycle_i ( mult_multicycle ), + + // Performance Counters + .perf_jump_o ( perf_jump ), + .perf_jr_stall_o ( perf_jr_stall ), + .perf_ld_stall_o ( perf_ld_stall ), + .perf_pipeline_stall_o ( perf_pipeline_stall ) + ); + + + ///////////////////////////////////////////////////// + // _______ __ ____ _____ _ ____ _____ // + // | ____\ \/ / / ___|_ _|/ \ / ___| ____| // + // | _| \ / \___ \ | | / _ \| | _| _| // + // | |___ / \ ___) || |/ ___ \ |_| | |___ // + // |_____/_/\_\ |____/ |_/_/ \_\____|_____| // + // // + ///////////////////////////////////////////////////// + riscv_ex_stage + #( + .FPU ( FPU ), + .FP_DIVSQRT ( FP_DIVSQRT ), + .SHARED_FP ( SHARED_FP ), + .SHARED_DSP_MULT ( SHARED_DSP_MULT ), + .SHARED_INT_DIV ( SHARED_INT_DIV ), + .APU_NARGS_CPU ( APU_NARGS_CPU ), + .APU_WOP_CPU ( APU_WOP_CPU ), + .APU_NDSFLAGS_CPU ( APU_NDSFLAGS_CPU ), + .APU_NUSFLAGS_CPU ( APU_NUSFLAGS_CPU ) + ) + ex_stage_i + ( + // Global signals: Clock and active low asynchronous reset + .clk ( clk ), + .rst_n ( rst_ni ), + + // Alu signals from ID stage + .alu_en_i ( alu_en_ex ), + .alu_operator_i ( alu_operator_ex ), // from ID/EX pipe registers + .alu_operand_a_i ( alu_operand_a_ex ), // from ID/EX pipe registers + .alu_operand_b_i ( alu_operand_b_ex ), // from ID/EX pipe registers + .alu_operand_c_i ( alu_operand_c_ex ), // from ID/EX pipe registers + .bmask_a_i ( bmask_a_ex ), // from ID/EX pipe registers + .bmask_b_i ( bmask_b_ex ), // from ID/EX pipe registers + .imm_vec_ext_i ( imm_vec_ext_ex ), // from ID/EX pipe registers + .alu_vec_mode_i ( alu_vec_mode_ex ), // from ID/EX pipe registers + .alu_is_clpx_i ( alu_is_clpx_ex ), // from ID/EX pipe registers + .alu_is_subrot_i ( alu_is_subrot_ex ), // from ID/Ex pipe registers + .alu_clpx_shift_i ( alu_clpx_shift_ex ), // from ID/EX pipe registers + + // Multipler + .mult_operator_i ( mult_operator_ex ), // from ID/EX pipe registers + .mult_operand_a_i ( mult_operand_a_ex ), // from ID/EX pipe registers + .mult_operand_b_i ( mult_operand_b_ex ), // from ID/EX pipe registers + .mult_operand_c_i ( mult_operand_c_ex ), // from ID/EX pipe registers + .mult_en_i ( mult_en_ex ), // from ID/EX pipe registers + .mult_sel_subword_i ( mult_sel_subword_ex ), // from ID/EX pipe registers + .mult_signed_mode_i ( mult_signed_mode_ex ), // from ID/EX pipe registers + .mult_imm_i ( mult_imm_ex ), // from ID/EX pipe registers + .mult_dot_op_a_i ( mult_dot_op_a_ex ), // from ID/EX pipe registers + .mult_dot_op_b_i ( mult_dot_op_b_ex ), // from ID/EX pipe registers + .mult_dot_op_c_i ( mult_dot_op_c_ex ), // from ID/EX pipe registers + .mult_dot_signed_i ( mult_dot_signed_ex ), // from ID/EX pipe registers + .mult_is_clpx_i ( mult_is_clpx_ex ), // from ID/EX pipe registers + .mult_clpx_shift_i ( mult_clpx_shift_ex ), // from ID/EX pipe registers + .mult_clpx_img_i ( mult_clpx_img_ex ), // from ID/EX pipe registers + + .mult_multicycle_o ( mult_multicycle ), // to ID/EX pipe registers + + // FPU + .fpu_prec_i ( fprec_csr ), + .fpu_fflags_o ( fflags ), + .fpu_fflags_we_o ( fflags_we ), + + // APU + .apu_en_i ( apu_en_ex ), + .apu_op_i ( apu_op_ex ), + .apu_lat_i ( apu_lat_ex ), + .apu_operands_i ( apu_operands_ex ), + .apu_waddr_i ( apu_waddr_ex ), + .apu_flags_i ( apu_flags_ex ), + + .apu_read_regs_i ( apu_read_regs ), + .apu_read_regs_valid_i ( apu_read_regs_valid ), + .apu_read_dep_o ( apu_read_dep ), + .apu_write_regs_i ( apu_write_regs ), + .apu_write_regs_valid_i ( apu_write_regs_valid ), + .apu_write_dep_o ( apu_write_dep ), + + .apu_perf_type_o ( perf_apu_type ), + .apu_perf_cont_o ( perf_apu_cont ), + .apu_perf_wb_o ( perf_apu_wb ), + .apu_ready_wb_o ( apu_ready_wb ), + .apu_busy_o ( apu_busy ), + + // apu-interconnect + // handshake signals + .apu_master_req_o ( apu_master_req_o ), + .apu_master_ready_o ( apu_master_ready_o ), + .apu_master_gnt_i ( apu_master_gnt_i ), + // request channel + .apu_master_operands_o ( apu_master_operands_o ), + .apu_master_op_o ( apu_master_op_o ), + // response channel + .apu_master_valid_i ( apu_master_valid_i ), + .apu_master_result_i ( apu_master_result_i ), + + .lsu_en_i ( data_req_ex ), + .lsu_rdata_i ( lsu_rdata ), + + // interface with CSRs + .csr_access_i ( csr_access_ex ), + .csr_rdata_i ( csr_rdata ), + + // From ID Stage: Regfile control signals + .branch_in_ex_i ( branch_in_ex ), + .regfile_alu_waddr_i ( regfile_alu_waddr_ex ), + .regfile_alu_we_i ( regfile_alu_we_ex ), + + .regfile_waddr_i ( regfile_waddr_ex ), + .regfile_we_i ( regfile_we_ex ), + + // Output of ex stage pipeline + .regfile_waddr_wb_o ( regfile_waddr_fw_wb_o ), + .regfile_we_wb_o ( regfile_we_wb ), + .regfile_wdata_wb_o ( regfile_wdata ), + + // To IF: Jump and branch target and decision + .jump_target_o ( jump_target_ex ), + .branch_decision_o ( branch_decision ), + + // To ID stage: Forwarding signals + .regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ), + .regfile_alu_we_fw_o ( regfile_alu_we_fw ), + .regfile_alu_wdata_fw_o ( regfile_alu_wdata_fw ), + + // stall control + .is_decoding_i ( is_decoding ), + .lsu_ready_ex_i ( lsu_ready_ex ), + .lsu_err_i ( data_err_pmp ), + + .ex_ready_o ( ex_ready ), + .ex_valid_o ( ex_valid ), + .wb_ready_i ( lsu_ready_wb ) + ); + + + //////////////////////////////////////////////////////////////////////////////////////// + // _ ___ _ ____ ____ _____ ___ ____ _____ _ _ _ _ ___ _____ // + // | | / _ \ / \ | _ \ / ___|_ _/ _ \| _ \| ____| | | | | \ | |_ _|_ _| // + // | | | | | |/ _ \ | | | | \___ \ | || | | | |_) | _| | | | | \| || | | | // + // | |__| |_| / ___ \| |_| | ___) || || |_| | _ <| |___ | |_| | |\ || | | | // + // |_____\___/_/ \_\____/ |____/ |_| \___/|_| \_\_____| \___/|_| \_|___| |_| // + // // + //////////////////////////////////////////////////////////////////////////////////////// + + riscv_load_store_unit load_store_unit_i + ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + + //output to data memory + .data_req_o ( data_req_pmp ), + .data_gnt_i ( data_gnt_pmp ), + .data_rvalid_i ( data_rvalid_i ), + .data_err_i ( data_err_pmp ), + + .data_addr_o ( data_addr_pmp ), + .data_we_o ( data_we_o ), + .data_atop_o ( data_atop_o ), + .data_be_o ( data_be_o ), + .data_buffer_o ( data_buffer_o ), + .data_wdata_o ( data_wdata_o ), + .data_rdata_i ( data_rdata_i ), + + // signal from ex stage + .data_we_ex_i ( data_we_ex ), + .data_atop_ex_i ( data_atop_ex ), + .data_buffer_ex_i ( data_buffer_ex ), + .data_type_ex_i ( data_type_ex ), + .data_wdata_ex_i ( alu_operand_c_ex ), + .data_reg_offset_ex_i ( data_reg_offset_ex ), + .data_sign_ext_ex_i ( data_sign_ext_ex ), // sign extension + + .data_rdata_ex_o ( lsu_rdata ), + .data_req_ex_i ( data_req_ex ), + .operand_a_ex_i ( alu_operand_a_ex ), + .operand_b_ex_i ( alu_operand_b_ex ), + .addr_useincr_ex_i ( useincr_addr_ex ), + + .data_misaligned_ex_i ( data_misaligned_ex ), // from ID/EX pipeline + .data_misaligned_o ( data_misaligned ), + + // control signals + .lsu_ready_ex_o ( lsu_ready_ex ), + .lsu_ready_wb_o ( lsu_ready_wb ), + + .ex_valid_i ( ex_valid ), + .busy_o ( lsu_busy ) + ); + + assign wb_valid = lsu_ready_wb & apu_ready_wb; + + + ////////////////////////////////////// + // ____ ____ ____ // + // / ___/ ___|| _ \ ___ // + // | | \___ \| |_) / __| // + // | |___ ___) | _ <\__ \ // + // \____|____/|_| \_\___/ // + // // + // Control and Status Registers // + ////////////////////////////////////// + + riscv_cs_registers + #( + .A_EXTENSION ( A_EXTENSION ), + .FPU ( FPU ), + .APU ( APU ), + .PULP_SECURE ( PULP_SECURE ), + .USE_PMP ( USE_PMP ), + .N_PMP_ENTRIES ( N_PMP_ENTRIES ), + .NUM_MHPMCOUNTERS ( NUM_MHPMCOUNTERS ), + .PULP_HWLP ( PULP_HWLP ), + .DEBUG_TRIGGER_EN ( DEBUG_TRIGGER_EN ) + ) + cs_registers_i + ( + .clk ( clk ), + .rst_n ( rst_ni ), + + // Hart ID from outside + .hart_id_i ( hart_id_i ), + .mtvec_o ( mtvec ), + .utvec_o ( utvec ), + .mtvec_mode_o ( mtvec_mode ), + .utvec_mode_o ( utvec_mode ), + // boot address + .boot_addr_i ( boot_addr_i[31:1] ), + // Interface to CSRs (SRAM like) + .csr_access_i ( csr_access ), + .csr_addr_i ( csr_addr ), + .csr_wdata_i ( csr_wdata ), + .csr_op_i ( csr_op ), + .csr_rdata_o ( csr_rdata ), + + .frm_o ( frm_csr ), + .fprec_o ( fprec_csr ), + .fflags_i ( fflags_csr ), + .fflags_we_i ( fflags_we ), + + // Interrupt related control signals + .m_irq_enable_o ( m_irq_enable ), + .u_irq_enable_o ( u_irq_enable ), + .csr_irq_sec_i ( csr_irq_sec ), + .sec_lvl_o ( sec_lvl_o ), + .mepc_o ( mepc ), + .uepc_o ( uepc ), + .irq_software_i ( irq_software_i ), + .irq_timer_i ( irq_timer_i ), + .irq_external_i ( irq_external_i ), + .irq_fast_i ( irq_fast_i ), + .irq_pending_o ( irq_pending ), // IRQ to ID/Controller + .irq_id_o ( irq_id ), + // debug + .debug_mode_i ( debug_mode ), + .debug_cause_i ( debug_cause ), + .debug_csr_save_i ( debug_csr_save ), + .depc_o ( depc ), + .debug_single_step_o ( debug_single_step ), + .debug_ebreakm_o ( debug_ebreakm ), + .debug_ebreaku_o ( debug_ebreaku ), + .trigger_match_o ( trigger_match ), + + .priv_lvl_o ( current_priv_lvl ), + + .pmp_addr_o ( pmp_addr_cs ), + .pmp_cfg_o ( pmp_cfg_cs ), + + .pc_if_i ( pc_if ), + .pc_id_i ( pc_id ), + .pc_ex_i ( pc_ex ), + + .csr_save_if_i ( csr_save_if ), + .csr_save_id_i ( csr_save_id ), + .csr_save_ex_i ( csr_save_ex ), + .csr_restore_mret_i ( csr_restore_mret_id ), + .csr_restore_uret_i ( csr_restore_uret_id ), + + .csr_restore_dret_i ( csr_restore_dret_id ), + + .csr_cause_i ( csr_cause ), + .csr_save_cause_i ( csr_save_cause ), + + // from hwloop registers + .hwlp_start_i ( hwlp_start ), + .hwlp_end_i ( hwlp_end ), + .hwlp_cnt_i ( hwlp_cnt ), + + .hwlp_regid_o ( csr_hwlp_regid ), + .hwlp_we_o ( csr_hwlp_we ), + .hwlp_data_o ( csr_hwlp_data ), + + .stack_base_o ( stack_base ), + .stack_limit_o ( stack_limit ), + + // performance counter related signals + .id_valid_i ( id_valid ), + .is_compressed_i ( is_compressed_id ), + .is_decoding_i ( is_decoding ), + + .imiss_i ( perf_imiss ), + .pc_set_i ( pc_set ), + .jump_i ( perf_jump ), + .branch_i ( branch_in_ex ), + .branch_taken_i ( branch_decision ), + .ld_stall_i ( perf_ld_stall ), + .jr_stall_i ( perf_jr_stall ), + .pipeline_stall_i ( perf_pipeline_stall ), + + .apu_typeconflict_i ( perf_apu_type ), + .apu_contention_i ( perf_apu_cont ), + .apu_dep_i ( perf_apu_dep ), + .apu_wb_i ( perf_apu_wb ), + + .mem_load_i ( data_req_o & data_gnt_i & (~data_we_o) ), + .mem_store_i ( data_req_o & data_gnt_i & data_we_o ) + + ); + + // CSR access + assign csr_access = csr_access_ex; + assign csr_addr = csr_addr_int; + assign csr_wdata = alu_operand_a_ex; + assign csr_op = csr_op_ex; + + assign csr_addr_int = csr_num_e'(csr_access_ex ? alu_operand_b_ex[11:0] : '0); + + + + /////////////////////////// + // ____ __ __ ____ // + // | _ \| \/ | _ \ // + // | |_) | |\/| | |_) | // + // | __/| | | | __/ // + // |_| |_| |_|_| // + // // + /////////////////////////// + + generate + if(PULP_SECURE && USE_PMP) begin : RISCY_PMP + riscv_pmp + #( + .N_PMP_ENTRIES(N_PMP_ENTRIES) + ) + pmp_unit_i + ( + .clk ( clk ), + .rst_n ( rst_ni ), + + .pmp_privil_mode_i ( current_priv_lvl ), + + .pmp_addr_i ( pmp_addr ), + .pmp_cfg_i ( pmp_cfg ), + + + .data_req_i ( data_req_pmp ), + .data_addr_i ( data_addr_pmp ), + .data_we_i ( data_we_o ), + .data_gnt_o ( data_gnt_pmp ), + + .data_req_o ( data_req_o ), + .data_gnt_i ( data_gnt_i ), + .data_addr_o ( data_addr_o ), + .data_err_o ( data_err_pmp ), + .data_err_ack_i ( data_err_ack ), + + .instr_req_i ( instr_req_pmp ), + .instr_addr_i ( instr_addr_pmp ), + .instr_gnt_o ( instr_gnt_pmp ), + + .instr_req_o ( instr_req_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_addr_o ( instr_addr_o ), + .instr_err_o ( instr_err_pmp ) + ); + end else begin + assign instr_req_o = instr_req_pmp; + assign instr_addr_o = instr_addr_pmp; + assign instr_gnt_pmp = instr_gnt_i; + assign instr_err_pmp = 1'b0; + + assign data_req_o = data_req_pmp; + assign data_addr_o = data_addr_pmp; + assign data_gnt_pmp = data_gnt_i; + assign data_err_pmp = 1'b0; + end + + + always_comb begin + pmp_addr = pmp_addr_cs; + pmp_cfg = pmp_cfg_cs; + + //external configuration has priority over CS + if (pmp_conf_override_i) begin + pmp_addr = pmp_addr_i; + pmp_cfg = pmp_cfg_i; + end + end + endgenerate + + +`ifdef TRACE_EXECUTION + + riscv_tracer riscv_tracer_i + ( + .clk ( clk_i ), // always-running clock for tracing + .rst_n ( rst_ni ), + + .fetch_enable ( fetch_enable_i ), + .hart_id_i ( hart_id_i ), + + .pc ( id_stage_i.pc_id_i ), + .instr ( id_stage_i.instr ), + .controller_state_i ( id_stage_i.controller_i.ctrl_fsm_cs ), + .compressed ( id_stage_i.is_compressed_i ), + .id_valid ( id_stage_i.id_valid_o ), + .is_decoding ( id_stage_i.is_decoding_o ), + .pipe_flush ( id_stage_i.controller_i.pipe_flush_i ), + .mret ( id_stage_i.controller_i.mret_insn_i ), + .uret ( id_stage_i.controller_i.uret_insn_i ), + .dret ( id_stage_i.controller_i.dret_insn_i ), + .ecall ( id_stage_i.controller_i.ecall_insn_i ), + .ebreak ( id_stage_i.controller_i.ebrk_insn_i ), + .fence ( id_stage_i.controller_i.fencei_insn_i), + .rs1_value ( id_stage_i.operand_a_fw_id ), + .rs2_value ( id_stage_i.operand_b_fw_id ), + .rs3_value ( id_stage_i.alu_operand_c ), + .rs2_value_vec ( id_stage_i.alu_operand_b ), + + .rs1_is_fp ( id_stage_i.regfile_fp_a ), + .rs2_is_fp ( id_stage_i.regfile_fp_b ), + .rs3_is_fp ( id_stage_i.regfile_fp_c ), + .rd_is_fp ( id_stage_i.regfile_fp_d ), + + .ex_valid ( ex_valid ), + .ex_reg_addr ( regfile_alu_waddr_fw ), + .ex_reg_we ( regfile_alu_we_fw ), + .ex_reg_wdata ( regfile_alu_wdata_fw ), + + .ex_data_addr ( data_addr_o ), + .ex_data_req ( data_req_o ), + .ex_data_gnt ( data_gnt_i ), + .ex_data_we ( data_we_o ), + .ex_data_wdata ( data_wdata_o ), + .data_misaligned ( data_misaligned ), + + .wb_bypass ( ex_stage_i.branch_in_ex_i ), + + .wb_valid ( wb_valid ), + .wb_reg_addr ( regfile_waddr_fw_wb_o ), + .wb_reg_we ( regfile_we_wb ), + .wb_reg_wdata ( regfile_wdata ), + + .imm_u_type ( id_stage_i.imm_u_type ), + .imm_uj_type ( id_stage_i.imm_uj_type ), + .imm_i_type ( id_stage_i.imm_i_type ), + .imm_iz_type ( id_stage_i.imm_iz_type[11:0] ), + .imm_z_type ( id_stage_i.imm_z_type ), + .imm_s_type ( id_stage_i.imm_s_type ), + .imm_sb_type ( id_stage_i.imm_sb_type ), + .imm_s2_type ( id_stage_i.imm_s2_type ), + .imm_s3_type ( id_stage_i.imm_s3_type ), + .imm_vs_type ( id_stage_i.imm_vs_type ), + .imm_vu_type ( id_stage_i.imm_vu_type ), + .imm_shuffle_type ( id_stage_i.imm_shuffle_type ), + .imm_clip_type ( id_stage_i.instr_rdata_i[11:7] ) + ); +`endif + +`ifdef PRINT_CORE_MEM_ACCESSES + always_comb begin + if (data_req_o && data_gnt_i) begin + if (data_we_o) begin + $display("Core %0d,%0d writes 0x%08x.", cluster_id_i, core_id_i, data_addr_o); + end else begin + $display("Core %0d,%0d reads 0x%08x.", cluster_id_i, core_id_i, data_addr_o); + end + end + end + `endif + +endmodule \ No newline at end of file diff --git a/hw/deps/riscv/riscv_cs_registers.sv b/hw/deps/riscv/riscv_cs_registers.sv new file mode 100644 index 0000000..57588a5 --- /dev/null +++ b/hw/deps/riscv/riscv_cs_registers.sv @@ -0,0 +1,1646 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Sven Stucki - svstucki@student.ethz.ch // +// // +// Additional contributions by: // +// Andreas Traber - atraber@iis.ee.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// Andrea Bettati - andrea.bettati@studenti.unipr.it // +// // +// Design Name: Control and Status Registers // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Control and Status Registers (CSRs) loosely following the // +// RiscV draft priviledged instruction set spec (v1.9) // +// Added Floating point support // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; + +`ifndef PULP_FPGA_EMUL + `ifdef SYNTHESIS + `define ASIC_SYNTHESIS + `endif +`endif + +module riscv_cs_registers +#( + parameter N_HWLP = 2, + parameter N_HWLP_BITS = $clog2(N_HWLP), + parameter APU = 0, + parameter A_EXTENSION = 0, + parameter FPU = 0, + parameter PULP_SECURE = 0, + parameter USE_PMP = 0, + parameter N_PMP_ENTRIES = 16, + parameter NUM_MHPMCOUNTERS = 1, + parameter PULP_HWLP = 0, + parameter DEBUG_TRIGGER_EN = 1 +) +( + // Clock and Reset + input logic clk, + input logic rst_n, + + // Hart ID + input logic [31:0] hart_id_i, + output logic [23:0] mtvec_o, + output logic [23:0] utvec_o, + output logic [1:0] mtvec_mode_o, + output logic [1:0] utvec_mode_o, + + // Used for boot address + input logic [30:0] boot_addr_i, + + // Interface to registers (SRAM like) + input logic csr_access_i, + input riscv_defines::csr_num_e csr_addr_i, + input logic [31:0] csr_wdata_i, + input logic [1:0] csr_op_i, + output logic [31:0] csr_rdata_o, + + output logic [2:0] frm_o, + output logic [C_PC-1:0] fprec_o, + input logic [C_FFLAG-1:0] fflags_i, + input logic fflags_we_i, + + // Interrupts + // IRQ lines from int_controller + input logic irq_software_i, + input logic irq_timer_i, + input logic irq_external_i, + input logic [47:0] irq_fast_i, + + output logic m_irq_enable_o, + output logic u_irq_enable_o, + // IRQ req to ID/controller + output logic irq_pending_o, //used to wake up the WFI and to signal interrupts to controller + output logic [5:0] irq_id_o, + + //csr_irq_sec_i is always 0 if PULP_SECURE is zero + input logic csr_irq_sec_i, + output logic sec_lvl_o, + output logic [31:0] mepc_o, + output logic [31:0] uepc_o, + + // debug + input logic debug_mode_i, + input logic [2:0] debug_cause_i, + input logic debug_csr_save_i, + output logic [31:0] depc_o, + output logic debug_single_step_o, + output logic debug_ebreakm_o, + output logic debug_ebreaku_o, + output logic trigger_match_o, + + + output logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_o, + output logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_o, + + output PrivLvl_t priv_lvl_o, + + input logic [31:0] pc_if_i, + input logic [31:0] pc_id_i, + input logic [31:0] pc_ex_i, + + input logic csr_save_if_i, + input logic csr_save_id_i, + input logic csr_save_ex_i, + + input logic csr_restore_mret_i, + input logic csr_restore_uret_i, + + input logic csr_restore_dret_i, + //coming from controller + input logic [6:0] csr_cause_i, + //coming from controller + input logic csr_save_cause_i, + // Hardware loops + input logic [N_HWLP-1:0] [31:0] hwlp_start_i, + input logic [N_HWLP-1:0] [31:0] hwlp_end_i, + input logic [N_HWLP-1:0] [31:0] hwlp_cnt_i, + + output logic [31:0] hwlp_data_o, + output logic [N_HWLP_BITS-1:0] hwlp_regid_o, + output logic [2:0] hwlp_we_o, + + // Stack Protection + output logic [31:0] stack_base_o, + output logic [31:0] stack_limit_o, + + // Performance Counters + input logic id_valid_i, // ID stage is done + input logic is_compressed_i, // compressed instruction in ID + input logic is_decoding_i, // controller is in DECODE state + + input logic imiss_i, // instruction fetch + input logic pc_set_i, // pc was set to a new value + input logic jump_i, // jump instruction seen (j, jr, jal, jalr) + input logic branch_i, // branch instruction seen (bf, bnf) + input logic branch_taken_i, // branch was taken + input logic ld_stall_i, // load use hazard + input logic jr_stall_i, // jump register use hazard + input logic pipeline_stall_i, // extra cycles from elw + + input logic apu_typeconflict_i, + input logic apu_contention_i, + input logic apu_dep_i, + input logic apu_wb_i, + + input logic mem_load_i, // load from memory in this cycle + input logic mem_store_i // store to memory in this cycle + +); + + localparam NUM_HPM_EVENTS = 16; + + localparam MTVEC_MODE = 2'b01; + + localparam MAX_N_PMP_ENTRIES = 16; + localparam MAX_N_PMP_CFG = 4; + localparam N_PMP_CFG = N_PMP_ENTRIES % 4 == 0 ? N_PMP_ENTRIES/4 : N_PMP_ENTRIES/4 + 1; + + + `define MSTATUS_UIE_BITS 0 + `define MSTATUS_SIE_BITS 1 + `define MSTATUS_MIE_BITS 3 + `define MSTATUS_UPIE_BITS 4 + `define MSTATUS_SPIE_BITS 5 + `define MSTATUS_MPIE_BITS 7 + `define MSTATUS_SPP_BITS 8 + `define MSTATUS_MPP_BITS 12:11 + `define MSTATUS_MPRV_BITS 17 + + // misa + localparam logic [1:0] MXL = 2'd1; // M-XLEN: XLEN in M-Mode for RV32 + localparam logic [31:0] MISA_VALUE = + (32'(A_EXTENSION) << 0) // A - Atomic Instructions extension + | (1 << 2) // C - Compressed extension + | (0 << 3) // D - Double precision floating-point extension + | (0 << 4) // E - RV32E base ISA + | (32'(FPU) << 5) // F - Single precision floating-point extension + | (1 << 8) // I - RV32I/64I/128I base ISA + | (1 << 12) // M - Integer Multiply/Divide extension + | (0 << 13) // N - User level interrupts supported + | (0 << 18) // S - Supervisor mode implemented + | (32'(PULP_SECURE) << 20) // U - User mode implemented + | (1 << 23) // X - Non-standard extensions present + | (32'(MXL) << 30); // M-XLEN + + typedef struct packed { + logic uie; + // logic sie; - unimplemented, hardwired to '0 + // logic hie; - unimplemented, hardwired to '0 + logic mie; + logic upie; + // logic spie; - unimplemented, hardwired to '0 + // logic hpie; - unimplemented, hardwired to '0 + logic mpie; + // logic spp; - unimplemented, hardwired to '0 + // logic[1:0] hpp; - unimplemented, hardwired to '0 + PrivLvl_t mpp; + logic mprv; + } Status_t; + + typedef struct packed{ + logic [31:28] xdebugver; + logic [27:16] zero2; + logic ebreakm; + logic zero1; + logic ebreaks; + logic ebreaku; + logic stepie; + logic stopcount; + logic stoptime; + logic [8:6] cause; + logic zero0; + logic mprven; + logic nmip; + logic step; + PrivLvl_t prv; + } Dcsr_t; + +`ifndef SYNTHESIS + initial + begin + $display("[CORE] Core settings: PULP_SECURE = %d, N_PMP_ENTRIES = %d, N_PMP_CFG %d",PULP_SECURE, N_PMP_ENTRIES, N_PMP_CFG); + end +`endif + + typedef struct packed { + logic [MAX_N_PMP_ENTRIES-1:0] [31:0] pmpaddr; + //logic [MAX_N_PMP_CFG-1:0] [31:0] pmpcfg_packed; + logic [MAX_N_PMP_ENTRIES-1:0] [ 7:0] pmpcfg; + } Pmp_t; + + typedef logic [MAX_N_PMP_CFG-1:0][31:0] pmpcfg_packed_t; + + // CSR update logic + logic [31:0] csr_wdata_int; + logic [31:0] csr_rdata_int; + logic csr_we_int; + logic [C_RM-1:0] frm_q, frm_n; + logic [C_FFLAG-1:0] fflags_q, fflags_n; + logic [C_PC-1:0] fprec_q, fprec_n; + + // Interrupt control signals + logic [31:0] mepc_q, mepc_n; + logic [31:0] uepc_q, uepc_n; + // Trigger + logic [31:0] tmatch_control_rdata; + logic [31:0] tmatch_value_rdata; + // Debug + Dcsr_t dcsr_q, dcsr_n; + logic [31:0] depc_q, depc_n; + logic [31:0] dscratch0_q, dscratch0_n; + logic [31:0] dscratch1_q, dscratch1_n; + logic [31:0] mscratch_q, mscratch_n; + + logic [31:0] exception_pc; + Status_t mstatus_q, mstatus_n; + logic [ 6:0] mcause_q, mcause_n; + logic [ 6:0] ucause_q, ucause_n; + logic [31:0] stack_base_q, stack_base_n, + stack_size_q, stack_size_n; + //not implemented yet + logic [23:0] mtvec_n, mtvec_q; + logic [23:0] utvec_n, utvec_q; + logic [ 1:0] mtvec_mode_n, mtvec_mode_q; + logic [ 1:0] utvec_mode_n, utvec_mode_q; + + Interrupts_t mip; + logic [31:0] mip1; + Interrupts_t mie_q, mie_n; + logic [31:0] mie1_q, mie1_n; + //machine enabled interrupt pending + Interrupts_t menip; + logic [31:0] menip1; + + logic is_irq; + PrivLvl_t priv_lvl_n, priv_lvl_q; + + Pmp_t pmp_reg_q; + Pmp_t pmp_reg_n; + pmpcfg_packed_t pmpcfg_packed_q; + pmpcfg_packed_t pmpcfg_packed_n; + + //clock gating for pmp regs + logic [MAX_N_PMP_ENTRIES-1:0] pmpaddr_we; + logic [MAX_N_PMP_ENTRIES-1:0] pmpcfg_we; + + // Performance Counter Signals + logic id_valid_q; + + + // performance counters + logic [31:0] [63:0] mhpmcounter_q; + logic [31:0] [63:0] mhpmcounter_n; + + // event enable + logic [31:0] [31:0] mhpmevent_q; + logic [31:0] [31:0] mhpmevent_n; + + // performance counter enable + logic [31:0] mcountinhibit_q; + logic [31:0] mcountinhibit_n; + + logic [NUM_HPM_EVENTS-1:0] hpm_events; // events for performance counters + + Interrupts_t irq_req; + logic [31:0] irq_req1; + + assign is_irq = csr_cause_i[6]; + + assign irq_req.irq_software = irq_software_i; + assign irq_req.irq_timer = irq_timer_i; + assign irq_req.irq_external = irq_external_i; + assign irq_req.irq_fast = irq_fast_i[15:0]; + assign irq_req1 = irq_fast_i[47:16]; + + // mip CSR is purely combintational + // must be able to re-enable the clock upon WFI + assign mip.irq_software = irq_req.irq_software; + assign mip.irq_timer = irq_req.irq_timer; + assign mip.irq_external = irq_req.irq_external; + assign mip.irq_fast = irq_req.irq_fast; + assign mip1 = irq_req1; + + // menip signal the controller + assign menip.irq_software = irq_req.irq_software & mie_q.irq_software; + assign menip.irq_timer = irq_req.irq_timer & mie_q.irq_timer; + assign menip.irq_external = irq_req.irq_external & mie_q.irq_external; + assign menip.irq_fast = irq_req.irq_fast & mie_q.irq_fast; + assign menip1 = irq_req1 & mie1_q; + + + + //////////////////////////////////////////// + // ____ ____ ____ ____ // + // / ___/ ___|| _ \ | _ \ ___ __ _ // + // | | \___ \| |_) | | |_) / _ \/ _` | // + // | |___ ___) | _ < | _ < __/ (_| | // + // \____|____/|_| \_\ |_| \_\___|\__, | // + // |___/ // + //////////////////////////////////////////// + + // NOTE!!!: Any new CSR register added in this file must also be + // added to the valid CSR register list riscv_decoder.v + + genvar j; + + +if(PULP_SECURE==1) begin + // read logic + always_comb + begin + casex (csr_addr_i) + // fcsr: Floating-Point Control and Status Register (frm + fflags). + CSR_FFLAGS : csr_rdata_int = (FPU == 1) ? {27'b0, fflags_q} : '0; + CSR_FRM : csr_rdata_int = (FPU == 1) ? {29'b0, frm_q} : '0; + CSR_FCSR : csr_rdata_int = (FPU == 1) ? {24'b0, frm_q, fflags_q} : '0; + FPREC : csr_rdata_int = (FPU == 1) ? {27'b0, fprec_q} : '0; // Optional precision control for FP DIV/SQRT Unit + + // mstatus + CSR_MSTATUS: csr_rdata_int = { + 14'b0, + mstatus_q.mprv, + 4'b0, + mstatus_q.mpp, + 3'b0, + mstatus_q.mpie, + 2'h0, + mstatus_q.upie, + mstatus_q.mie, + 2'h0, + mstatus_q.uie + }; + + // misa: machine isa register + CSR_MISA: csr_rdata_int = MISA_VALUE; + + // mie: machine interrupt enable + CSR_MIE: begin + csr_rdata_int = '0; + csr_rdata_int[CSR_MSIX_BIT] = mie_q.irq_software; + csr_rdata_int[CSR_MTIX_BIT] = mie_q.irq_timer; + csr_rdata_int[CSR_MEIX_BIT] = mie_q.irq_external; + csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mie_q.irq_fast; + end + + // mie1: machine interrupt enable for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIE1: csr_rdata_int = mie1_q; + + // mtvec: machine trap-handler base address + CSR_MTVEC: csr_rdata_int = {mtvec_q, 6'h0, mtvec_mode_q}; + // mscratch: machine scratch + CSR_MSCRATCH: csr_rdata_int = mscratch_q; + // mepc: exception program counter + CSR_MEPC: csr_rdata_int = mepc_q; + // mcause: exception cause + CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; + // mip: interrupt pending + CSR_MIP: begin + csr_rdata_int = '0; + csr_rdata_int[CSR_MSIX_BIT] = mip.irq_software; + csr_rdata_int[CSR_MTIX_BIT] = mip.irq_timer; + csr_rdata_int[CSR_MEIX_BIT] = mip.irq_external; + csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mip.irq_fast; + end + + // mip1: machine interrupt pending for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIP1: csr_rdata_int = mip1; + + // mhartid: unique hardware thread id + CSR_MHARTID: csr_rdata_int = hart_id_i; + + // unimplemented, read 0 CSRs + CSR_MVENDORID, + CSR_MARCHID, + CSR_MIMPID, + CSR_MTVAL, + CSR_MCOUNTEREN : + csr_rdata_int = 'b0; + + CSR_TSELECT, + CSR_TDATA3, + CSR_MCONTEXT, + CSR_SCONTEXT: + csr_rdata_int = 'b0; // Always read 0 + CSR_TDATA1: + csr_rdata_int = tmatch_control_rdata; + CSR_TDATA2: + csr_rdata_int = tmatch_value_rdata; + + CSR_DCSR: + csr_rdata_int = dcsr_q;// + CSR_DPC: + csr_rdata_int = depc_q; + CSR_DSCRATCH0: + csr_rdata_int = dscratch0_q;// + CSR_DSCRATCH1: + csr_rdata_int = dscratch1_q;// + + // Hardware Performance Monitor + CSR_MCYCLE, + CSR_MINSTRET, + CSR_MHPMCOUNTER3, + CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, + CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, + CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, + CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, + CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, + CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, + CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31: + csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][31:0]; + + CSR_MCYCLEH, + CSR_MINSTRETH, + CSR_MHPMCOUNTER3H, + CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, + CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, + CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, + CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, + CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, + CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, + CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H: + csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][63:32]; + + CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit_q; + + CSR_MHPMEVENT3, + CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, + CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, + CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, + CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, + CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, + CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, + CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: + csr_rdata_int = mhpmevent_q[csr_addr_i[4:0]]; + + // hardware loops (not official) + HWLoop0_START : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_start_i[0]; + HWLoop0_END : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_end_i[0] ; + HWLoop0_COUNTER: csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_cnt_i[0] ; + HWLoop1_START : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_start_i[1]; + HWLoop1_END : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_end_i[1] ; + HWLoop1_COUNTER: csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_cnt_i[1] ; + + // PMP config registers + CSR_PMPCFG0: csr_rdata_int = USE_PMP ? pmpcfg_packed_q[0] : '0; + CSR_PMPCFG1: csr_rdata_int = USE_PMP ? pmpcfg_packed_q[1] : '0; + CSR_PMPCFG2: csr_rdata_int = USE_PMP ? pmpcfg_packed_q[2] : '0; + CSR_PMPCFG3: csr_rdata_int = USE_PMP ? pmpcfg_packed_q[3] : '0; + + CSR_PMPADDR_RANGE_X : + csr_rdata_int = USE_PMP ? pmp_reg_q.pmpaddr[csr_addr_i[3:0]] : '0; + + /* USER CSR */ + // ustatus + CSR_USTATUS: csr_rdata_int = { + 27'b0, + mstatus_q.upie, + 3'h0, + mstatus_q.uie + }; + // utvec: user trap-handler base address + CSR_UTVEC: csr_rdata_int = {utvec_q, 6'h0, utvec_mode_q}; + // duplicated mhartid: unique hardware thread id (not official) + UHARTID: csr_rdata_int = hart_id_i; + // uepc: exception program counter + CSR_UEPC: csr_rdata_int = uepc_q; + // ucause: exception cause + CSR_UCAUSE: csr_rdata_int = {ucause_q[6], 25'h0, ucause_q[5:0]}; + + // current priv level (not official) + PRIVLV: csr_rdata_int = {30'h0, priv_lvl_q}; + + default: + csr_rdata_int = '0; + endcase + end +end else begin //PULP_SECURE == 0 + // read logic + always_comb + begin + + case (csr_addr_i) + // fcsr: Floating-Point Control and Status Register (frm + fflags). + CSR_FFLAGS : csr_rdata_int = (FPU == 1) ? {27'b0, fflags_q} : '0; + CSR_FRM : csr_rdata_int = (FPU == 1) ? {29'b0, frm_q} : '0; + CSR_FCSR : csr_rdata_int = (FPU == 1) ? {24'b0, frm_q, fflags_q} : '0; + FPREC : csr_rdata_int = (FPU == 1) ? {27'b0, fprec_q} : '0; // Optional precision control for FP DIV/SQRT Unit + // mstatus: always M-mode, contains IE bit + CSR_MSTATUS: csr_rdata_int = { + 14'b0, + mstatus_q.mprv, + 4'b0, + mstatus_q.mpp, + 3'b0, + mstatus_q.mpie, + 2'h0, + mstatus_q.upie, + mstatus_q.mie, + 2'h0, + mstatus_q.uie + }; + // misa: machine isa register + CSR_MISA: csr_rdata_int = MISA_VALUE; + // mie: machine interrupt enable + CSR_MIE: begin + csr_rdata_int = '0; + csr_rdata_int[CSR_MSIX_BIT] = mie_q.irq_software; + csr_rdata_int[CSR_MTIX_BIT] = mie_q.irq_timer; + csr_rdata_int[CSR_MEIX_BIT] = mie_q.irq_external; + csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mie_q.irq_fast; + end + + // mie1: machine interrupt enable for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIE1: csr_rdata_int = mie1_q; + // mtvec: machine trap-handler base address + CSR_MTVEC: csr_rdata_int = {mtvec_q, 6'h0, mtvec_mode_q}; + // mscratch: machine scratch + CSR_MSCRATCH: csr_rdata_int = mscratch_q; + // mepc: exception program counter + CSR_MEPC: csr_rdata_int = mepc_q; + // mcause: exception cause + CSR_MCAUSE: csr_rdata_int = {mcause_q[6], 25'b0, mcause_q[5:0]}; + // mip: interrupt pending + CSR_MIP: begin + csr_rdata_int = '0; + csr_rdata_int[CSR_MSIX_BIT] = mip.irq_software; + csr_rdata_int[CSR_MTIX_BIT] = mip.irq_timer; + csr_rdata_int[CSR_MEIX_BIT] = mip.irq_external; + csr_rdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = mip.irq_fast; + end + // mip1: machine interrupt pending for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIP1: csr_rdata_int = mip1; + // mhartid: unique hardware thread id + CSR_MHARTID: csr_rdata_int = hart_id_i; + + // unimplemented, read 0 CSRs + CSR_MVENDORID, + CSR_MARCHID, + CSR_MIMPID, + CSR_MTVAL, + CSR_MCOUNTEREN : + csr_rdata_int = 'b0; + + CSR_TSELECT, + CSR_TDATA3, + CSR_MCONTEXT, + CSR_SCONTEXT: + csr_rdata_int = 'b0; // Always read 0 + CSR_TDATA1: + csr_rdata_int = tmatch_control_rdata; + CSR_TDATA2: + csr_rdata_int = tmatch_value_rdata; + + CSR_DCSR: + csr_rdata_int = dcsr_q;// + CSR_DPC: + csr_rdata_int = depc_q; + CSR_DSCRATCH0: + csr_rdata_int = dscratch0_q;// + CSR_DSCRATCH1: + csr_rdata_int = dscratch1_q;// + + // Hardware Performance Monitor + CSR_MCYCLE, + CSR_MINSTRET, + CSR_MHPMCOUNTER3, + CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, + CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, + CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, + CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, + CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, + CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, + CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31: + csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][31:0]; + + CSR_MCYCLEH, + CSR_MINSTRETH, + CSR_MHPMCOUNTER3H, + CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, + CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, + CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, + CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, + CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, + CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, + CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H: + csr_rdata_int = mhpmcounter_q[csr_addr_i[4:0]][63:32]; + + CSR_MCOUNTINHIBIT: csr_rdata_int = mcountinhibit_q; + + CSR_MHPMEVENT3, + CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, + CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, + CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, + CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, + CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, + CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, + CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: + csr_rdata_int = mhpmevent_q[csr_addr_i[4:0]]; + + // hardware loops (not official) + HWLoop0_START : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_start_i[0] ; + HWLoop0_END : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_end_i[0] ; + HWLoop0_COUNTER : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_cnt_i[0] ; + HWLoop1_START : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_start_i[1] ; + HWLoop1_END : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_end_i[1] ; + HWLoop1_COUNTER : csr_rdata_int = !PULP_HWLP ? 'b0 : hwlp_cnt_i[1] ; + + /* USER CSR */ + // dublicated mhartid: unique hardware thread id (not official) + UHARTID: csr_rdata_int = hart_id_i; + // current priv level (not official) + PRIVLV: csr_rdata_int = {30'h0, priv_lvl_q}; + default: + csr_rdata_int = '0; + endcase + end +end //PULP_SECURE + +if(PULP_SECURE==1) begin + // write logic + always_comb + begin + fflags_n = fflags_q; + frm_n = frm_q; + fprec_n = fprec_q; + mscratch_n = mscratch_q; + mepc_n = mepc_q; + uepc_n = uepc_q; + depc_n = depc_q; + dcsr_n = dcsr_q; + dscratch0_n = dscratch0_q; + dscratch1_n = dscratch1_q; + + mstatus_n = mstatus_q; + mcause_n = mcause_q; + ucause_n = ucause_q; + hwlp_we_o = '0; + hwlp_regid_o = '0; + exception_pc = pc_id_i; + priv_lvl_n = priv_lvl_q; + mtvec_n = mtvec_q; + utvec_n = utvec_q; + mtvec_mode_n = mtvec_mode_q; + utvec_mode_n = utvec_mode_q; + pmp_reg_n.pmpaddr = pmp_reg_q.pmpaddr; + pmpcfg_packed_n = pmpcfg_packed_q; + pmpaddr_we = '0; + pmpcfg_we = '0; + + mie_n = mie_q; + mie1_n = mie1_q; + + if (FPU == 1) if (fflags_we_i) fflags_n = fflags_i | fflags_q; + + casex (csr_addr_i) + // fcsr: Floating-Point Control and Status Register (frm, fflags, fprec). + CSR_FFLAGS : if (csr_we_int) fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; + CSR_FRM : if (csr_we_int) frm_n = (FPU == 1) ? csr_wdata_int[C_RM-1:0] : '0; + CSR_FCSR : if (csr_we_int) begin + fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; + frm_n = (FPU == 1) ? csr_wdata_int[C_RM+C_FFLAG-1:C_FFLAG] : '0; + end + FPREC : if (csr_we_int) fprec_n = (FPU == 1) ? csr_wdata_int[C_PC-1:0] : '0; + + // mstatus: IE bit + CSR_MSTATUS: if (csr_we_int) begin + mstatus_n = '{ + uie: csr_wdata_int[`MSTATUS_UIE_BITS], + mie: csr_wdata_int[`MSTATUS_MIE_BITS], + upie: csr_wdata_int[`MSTATUS_UPIE_BITS], + mpie: csr_wdata_int[`MSTATUS_MPIE_BITS], + mpp: PrivLvl_t'(csr_wdata_int[`MSTATUS_MPP_BITS]), + mprv: csr_wdata_int[`MSTATUS_MPRV_BITS] + }; + end + // mie: machine interrupt enable + CSR_MIE: if (csr_we_int) begin + mie_n.irq_software = csr_wdata_int[CSR_MSIX_BIT]; + mie_n.irq_timer = csr_wdata_int[CSR_MTIX_BIT]; + mie_n.irq_external = csr_wdata_int[CSR_MEIX_BIT]; + mie_n.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW]; + end + // mie1: machine interrupt enable for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIE1: if (csr_we_int) begin + mie1_n = csr_wdata_int; + end + // mtvec: machine trap-handler base address + CSR_MTVEC: if (csr_we_int) begin + mtvec_n = csr_wdata_int[31:8]; + mtvec_mode_n = {1'b0, csr_wdata_int[0]}; // Only direct and vectored mode are supported + end + // mscratch: machine scratch + CSR_MSCRATCH: if (csr_we_int) begin + mscratch_n = csr_wdata_int; + end + // mepc: exception program counter + CSR_MEPC: if (csr_we_int) begin + mepc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment + end + // mcause + CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[5:0]}; + + // Debug + CSR_DCSR: + if (csr_we_int) + begin + dcsr_n = csr_wdata_int; + //31:28 xdebuger = 4 -> debug is implemented + dcsr_n.xdebugver=4'h4; + //privilege level: 0-> U;1-> S; 3->M. + dcsr_n.prv=priv_lvl_q; + //currently not supported: + dcsr_n.nmip=1'b0; //nmip + dcsr_n.mprven=1'b0; //mprven + dcsr_n.stopcount=1'b0; //stopcount + dcsr_n.stoptime=1'b0; //stoptime + end + CSR_DPC: + if (csr_we_int) + begin + depc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment + end + + CSR_DSCRATCH0: + if (csr_we_int) + begin + dscratch0_n = csr_wdata_int; + end + + CSR_DSCRATCH1: + if (csr_we_int) + begin + dscratch1_n = csr_wdata_int; + end + + // hardware loops + HWLoop0_START: if (csr_we_int) begin hwlp_we_o = 3'b001; hwlp_regid_o = 1'b0; end + HWLoop0_END: if (csr_we_int) begin hwlp_we_o = 3'b010; hwlp_regid_o = 1'b0; end + HWLoop0_COUNTER: if (csr_we_int) begin hwlp_we_o = 3'b100; hwlp_regid_o = 1'b0; end + HWLoop1_START: if (csr_we_int) begin hwlp_we_o = 3'b001; hwlp_regid_o = 1'b1; end + HWLoop1_END: if (csr_we_int) begin hwlp_we_o = 3'b010; hwlp_regid_o = 1'b1; end + HWLoop1_COUNTER: if (csr_we_int) begin hwlp_we_o = 3'b100; hwlp_regid_o = 1'b1; end + + + // PMP config registers + CSR_PMPCFG0: if (csr_we_int) begin pmpcfg_packed_n[0] = csr_wdata_int; pmpcfg_we[3:0] = 4'b1111; end + CSR_PMPCFG1: if (csr_we_int) begin pmpcfg_packed_n[1] = csr_wdata_int; pmpcfg_we[7:4] = 4'b1111; end + CSR_PMPCFG2: if (csr_we_int) begin pmpcfg_packed_n[2] = csr_wdata_int; pmpcfg_we[11:8] = 4'b1111; end + CSR_PMPCFG3: if (csr_we_int) begin pmpcfg_packed_n[3] = csr_wdata_int; pmpcfg_we[15:12] = 4'b1111; end + + CSR_PMPADDR_RANGE_X : + if (csr_we_int) begin pmp_reg_n.pmpaddr[csr_addr_i[3:0]] = csr_wdata_int; pmpaddr_we[csr_addr_i[3:0]] = 1'b1; end + + + /* USER CSR */ + // ucause: exception cause + CSR_USTATUS: if (csr_we_int) begin + mstatus_n = '{ + uie: csr_wdata_int[`MSTATUS_UIE_BITS], + mie: mstatus_q.mie, + upie: csr_wdata_int[`MSTATUS_UPIE_BITS], + mpie: mstatus_q.mpie, + mpp: mstatus_q.mpp, + mprv: mstatus_q.mprv + }; + end + // utvec: user trap-handler base address + CSR_UTVEC: if (csr_we_int) begin + utvec_n = csr_wdata_int[31:8]; + utvec_mode_n = {1'b0, csr_wdata_int[0]}; // Only direct and vectored mode are supported + end + // uepc: exception program counter + CSR_UEPC: if (csr_we_int) begin + uepc_n = csr_wdata_int; + end + // ucause: exception cause + CSR_UCAUSE: if (csr_we_int) ucause_n = {csr_wdata_int[31], csr_wdata_int[5:0]}; + endcase + + // exception controller gets priority over other writes + unique case (1'b1) + + csr_save_cause_i: begin + + unique case (1'b1) + csr_save_if_i: + exception_pc = pc_if_i; + csr_save_id_i: + exception_pc = pc_id_i; + csr_save_ex_i: + exception_pc = pc_ex_i; + default:; + endcase + + unique case (priv_lvl_q) + + PRIV_LVL_U: begin + if(~is_irq) begin + //Exceptions, Ecall U --> M + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = mstatus_q.uie; + mstatus_n.mie = 1'b0; + mstatus_n.mpp = PRIV_LVL_U; + // TODO: correctly handled? + if (debug_csr_save_i) + depc_n = exception_pc; + else + mepc_n = exception_pc; + mcause_n = csr_cause_i; + + end + else begin + if(~csr_irq_sec_i) begin + //U --> U + priv_lvl_n = PRIV_LVL_U; + mstatus_n.upie = mstatus_q.uie; + mstatus_n.uie = 1'b0; + // TODO: correctly handled? + if (debug_csr_save_i) + depc_n = exception_pc; + else + uepc_n = exception_pc; + ucause_n = csr_cause_i; + + end else begin + //U --> M + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = mstatus_q.uie; + mstatus_n.mie = 1'b0; + mstatus_n.mpp = PRIV_LVL_U; + // TODO: correctly handled? + if (debug_csr_save_i) + depc_n = exception_pc; + else + mepc_n = exception_pc; + mcause_n = csr_cause_i; + end + end + end //PRIV_LVL_U + + PRIV_LVL_M: begin + if (debug_csr_save_i) begin + // all interrupts are masked, don't update cause, epc, tval dpc + // and mpstatus + dcsr_n.prv = PRIV_LVL_M; + dcsr_n.cause = debug_cause_i; + depc_n = exception_pc; + end else begin + //Exceptions or Interrupts from PRIV_LVL_M always do M --> M + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = mstatus_q.mie; + mstatus_n.mie = 1'b0; + mstatus_n.mpp = PRIV_LVL_M; + mepc_n = exception_pc; + mcause_n = csr_cause_i; + end + end //PRIV_LVL_M + default:; + + endcase + + end //csr_save_cause_i + + csr_restore_uret_i: begin //URET + //mstatus_q.upp is implicitly 0, i.e PRIV_LVL_U + mstatus_n.uie = mstatus_q.upie; + priv_lvl_n = PRIV_LVL_U; + mstatus_n.upie = 1'b1; + end //csr_restore_uret_i + + csr_restore_mret_i: begin //MRET + unique case (mstatus_q.mpp) + PRIV_LVL_U: begin + mstatus_n.uie = mstatus_q.mpie; + priv_lvl_n = PRIV_LVL_U; + mstatus_n.mpie = 1'b1; + mstatus_n.mpp = PRIV_LVL_U; + end + PRIV_LVL_M: begin + mstatus_n.mie = mstatus_q.mpie; + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = 1'b1; + mstatus_n.mpp = PRIV_LVL_U; + end + default:; + endcase + end //csr_restore_mret_i + + + csr_restore_dret_i: begin //DRET + // restore to the recorded privilege level + // TODO: prevent illegal values, see riscv-debug p.44 + priv_lvl_n = dcsr_q.prv; + + end //csr_restore_dret_i + + default:; + endcase + end +end else begin //PULP_SECURE == 0 + // write logic + always_comb + begin + fflags_n = fflags_q; + frm_n = frm_q; + fprec_n = fprec_q; + mscratch_n = mscratch_q; + mepc_n = mepc_q; + uepc_n = 'b0; // Not used if PULP_SECURE == 0 + depc_n = depc_q; + dcsr_n = dcsr_q; + dscratch0_n = dscratch0_q; + dscratch1_n = dscratch1_q; + + mstatus_n = mstatus_q; + mcause_n = mcause_q; + ucause_n = '0; // Not used if PULP_SECURE == 0 + hwlp_we_o = '0; + hwlp_regid_o = '0; + exception_pc = pc_id_i; + priv_lvl_n = priv_lvl_q; + mtvec_n = mtvec_q; + utvec_n = '0; // Not used if PULP_SECURE == 0 + pmp_reg_n.pmpaddr = '0; // Not used if PULP_SECURE == 0 + pmpcfg_packed_n = '0; // Not used if PULP_SECURE == 0 + pmp_reg_n.pmpcfg = '0; // Not used if PULP_SECURE == 0 + pmpaddr_we = '0; + pmpcfg_we = '0; + + mie_n = mie_q; + mie1_n = mie1_q; + mtvec_mode_n = mtvec_mode_q; + utvec_mode_n = '0; // Not used if PULP_SECURE == 0 + + if (FPU == 1) if (fflags_we_i) fflags_n = fflags_i | fflags_q; + + case (csr_addr_i) + // fcsr: Floating-Point Control and Status Register (frm, fflags, fprec). + CSR_FFLAGS : if (csr_we_int) fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; + CSR_FRM : if (csr_we_int) frm_n = (FPU == 1) ? csr_wdata_int[C_RM-1:0] : '0; + CSR_FCSR : if (csr_we_int) begin + fflags_n = (FPU == 1) ? csr_wdata_int[C_FFLAG-1:0] : '0; + frm_n = (FPU == 1) ? csr_wdata_int[C_RM+C_FFLAG-1:C_FFLAG] : '0; + end + FPREC : if (csr_we_int) fprec_n = (FPU == 1) ? csr_wdata_int[C_PC-1:0] : '0; + + // mstatus: IE bit + CSR_MSTATUS: if (csr_we_int) begin + mstatus_n = '{ + uie: csr_wdata_int[`MSTATUS_UIE_BITS], + mie: csr_wdata_int[`MSTATUS_MIE_BITS], + upie: csr_wdata_int[`MSTATUS_UPIE_BITS], + mpie: csr_wdata_int[`MSTATUS_MPIE_BITS], + mpp: PrivLvl_t'(csr_wdata_int[`MSTATUS_MPP_BITS]), + mprv: csr_wdata_int[`MSTATUS_MPRV_BITS] + }; + end + // mie: machine interrupt enable + CSR_MIE: if(csr_we_int) begin + mie_n.irq_software = csr_wdata_int[CSR_MSIX_BIT]; + mie_n.irq_timer = csr_wdata_int[CSR_MTIX_BIT]; + mie_n.irq_external = csr_wdata_int[CSR_MEIX_BIT]; + mie_n.irq_fast = csr_wdata_int[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW]; + end + // mie1: machine interrupt enable for fast interrupt extension (irq_fast_i[47:16]) + CSR_MIE1: if (csr_we_int) begin + mie1_n = csr_wdata_int; + end + // mtvec: machine trap-handler base address + CSR_MTVEC: if (csr_we_int) begin + mtvec_n = csr_wdata_int[31:8]; + end + // mscratch: machine scratch + CSR_MSCRATCH: if (csr_we_int) begin + mscratch_n = csr_wdata_int; + end + // mepc: exception program counter + CSR_MEPC: if (csr_we_int) begin + mepc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment + end + // mcause + CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[5:0]}; + + CSR_DCSR: + if (csr_we_int) + begin + dcsr_n = csr_wdata_int; + //31:28 xdebuger = 4 -> debug is implemented + dcsr_n.xdebugver=4'h4; + //privilege level: 0-> U;1-> S; 3->M. + dcsr_n.prv=priv_lvl_q; + //currently not supported: + dcsr_n.nmip=1'b0; //nmip + dcsr_n.mprven=1'b0; //mprven + dcsr_n.stopcount=1'b0; //stopcount + dcsr_n.stoptime=1'b0; //stoptime + end + CSR_DPC: + if (csr_we_int) + begin + depc_n = csr_wdata_int & ~32'b1; // force 16-bit alignment + end + + CSR_DSCRATCH0: + if (csr_we_int) + begin + dscratch0_n = csr_wdata_int; + end + + CSR_DSCRATCH1: + if (csr_we_int) + begin + dscratch1_n = csr_wdata_int; + end + + // hardware loops + HWLoop0_START: if (csr_we_int) begin hwlp_we_o = 3'b001; hwlp_regid_o = 1'b0; end + HWLoop0_END: if (csr_we_int) begin hwlp_we_o = 3'b010; hwlp_regid_o = 1'b0; end + HWLoop0_COUNTER: if (csr_we_int) begin hwlp_we_o = 3'b100; hwlp_regid_o = 1'b0; end + HWLoop1_START: if (csr_we_int) begin hwlp_we_o = 3'b001; hwlp_regid_o = 1'b1; end + HWLoop1_END: if (csr_we_int) begin hwlp_we_o = 3'b010; hwlp_regid_o = 1'b1; end + HWLoop1_COUNTER: if (csr_we_int) begin hwlp_we_o = 3'b100; hwlp_regid_o = 1'b1; end + endcase + + // exception controller gets priority over other writes + unique case (1'b1) + + csr_save_cause_i: begin + unique case (1'b1) + csr_save_if_i: + exception_pc = pc_if_i; + csr_save_id_i: + exception_pc = pc_id_i; + default:; + endcase + + if (debug_csr_save_i) begin + // all interrupts are masked, don't update cause, epc, tval dpc and + // mpstatus + dcsr_n.prv = PRIV_LVL_M; + dcsr_n.cause = debug_cause_i; + depc_n = exception_pc; + end else begin + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = mstatus_q.mie; + mstatus_n.mie = 1'b0; + mstatus_n.mpp = PRIV_LVL_M; + mepc_n = exception_pc; + mcause_n = csr_cause_i; + end + end //csr_save_cause_i + + csr_restore_mret_i: begin //MRET + mstatus_n.mie = mstatus_q.mpie; + priv_lvl_n = PRIV_LVL_M; + mstatus_n.mpie = 1'b1; + mstatus_n.mpp = PRIV_LVL_M; + end //csr_restore_mret_i + + csr_restore_dret_i: begin //DRET + // restore to the recorded privilege level + // TODO: prevent illegal values, see riscv-debug p.44 + priv_lvl_n = dcsr_q.prv; + end //csr_restore_dret_i + + default:; + endcase + end +end //PULP_SECURE + + assign hwlp_data_o = csr_wdata_int; + + // CSR operation logic + always_comb + begin + csr_wdata_int = csr_wdata_i; + csr_we_int = 1'b1; + + unique case (csr_op_i) + CSR_OP_WRITE: csr_wdata_int = csr_wdata_i; + CSR_OP_SET: csr_wdata_int = csr_wdata_i | csr_rdata_o; + CSR_OP_CLEAR: csr_wdata_int = (~csr_wdata_i) & csr_rdata_o; + + CSR_OP_READ: begin + csr_wdata_int = csr_wdata_i; + csr_we_int = 1'b0; + end + + default:; + endcase + end + + assign csr_rdata_o = csr_rdata_int; + + // Interrupt Encoder: + // - sets correct id to request to ID + // - encodes priority order + always_comb + begin + + if (menip1[31]) irq_id_o = 6'd63; + else if (menip1[30]) irq_id_o = 6'd62; + else if (menip1[29]) irq_id_o = 6'd61; + else if (menip1[28]) irq_id_o = 6'd60; + else if (menip1[27]) irq_id_o = 6'd59; + else if (menip1[26]) irq_id_o = 6'd58; + else if (menip1[25]) irq_id_o = 6'd57; + else if (menip1[24]) irq_id_o = 6'd56; + else if (menip1[23]) irq_id_o = 6'd55; + else if (menip1[22]) irq_id_o = 6'd54; + else if (menip1[21]) irq_id_o = 6'd53; + else if (menip1[20]) irq_id_o = 6'd52; + else if (menip1[19]) irq_id_o = 6'd51; + else if (menip1[18]) irq_id_o = 6'd50; + else if (menip1[17]) irq_id_o = 6'd49; + else if (menip1[16]) irq_id_o = 6'd48; + else if (menip1[15]) irq_id_o = 6'd47; + else if (menip1[14]) irq_id_o = 6'd46; + else if (menip1[13]) irq_id_o = 6'd45; + else if (menip1[12]) irq_id_o = 6'd44; + else if (menip1[11]) irq_id_o = 6'd43; + else if (menip1[10]) irq_id_o = 6'd42; + else if (menip1[ 9]) irq_id_o = 6'd41; + else if (menip1[ 8]) irq_id_o = 6'd40; + else if (menip1[ 7]) irq_id_o = 6'd39; + else if (menip1[ 6]) irq_id_o = 6'd38; + else if (menip1[ 5]) irq_id_o = 6'd37; + else if (menip1[ 4]) irq_id_o = 6'd36; + else if (menip1[ 3]) irq_id_o = 6'd35; + else if (menip1[ 2]) irq_id_o = 6'd34; + else if (menip1[ 1]) irq_id_o = 6'd33; + else if (menip1[ 0]) irq_id_o = 6'd32; + else if (menip.irq_fast[15]) irq_id_o = 6'd31; + else if (menip.irq_fast[14]) irq_id_o = 6'd30; + else if (menip.irq_fast[13]) irq_id_o = 6'd29; + else if (menip.irq_fast[12]) irq_id_o = 6'd28; + else if (menip.irq_fast[11]) irq_id_o = 6'd27; + else if (menip.irq_fast[10]) irq_id_o = 6'd26; + else if (menip.irq_fast[ 9]) irq_id_o = 6'd25; + else if (menip.irq_fast[ 8]) irq_id_o = 6'd24; + else if (menip.irq_fast[ 7]) irq_id_o = 6'd23; + else if (menip.irq_fast[ 6]) irq_id_o = 6'd22; + else if (menip.irq_fast[ 5]) irq_id_o = 6'd21; + else if (menip.irq_fast[ 4]) irq_id_o = 6'd20; + else if (menip.irq_fast[ 3]) irq_id_o = 6'd19; + else if (menip.irq_fast[ 2]) irq_id_o = 6'd18; + else if (menip.irq_fast[ 1]) irq_id_o = 6'd17; + else if (menip.irq_fast[ 0]) irq_id_o = 6'd16; + else if (menip.irq_external) irq_id_o = CSR_MEIX_BIT; + else if (menip.irq_software) irq_id_o = CSR_MSIX_BIT; + else if (menip.irq_timer) irq_id_o = CSR_MTIX_BIT; + else irq_id_o = CSR_MTIX_BIT; + end + + + // directly output some registers + assign m_irq_enable_o = mstatus_q.mie & priv_lvl_q == PRIV_LVL_M; + assign u_irq_enable_o = mstatus_q.uie & priv_lvl_q == PRIV_LVL_U; + assign priv_lvl_o = priv_lvl_q; + assign sec_lvl_o = priv_lvl_q[0]; + assign frm_o = (FPU == 1) ? frm_q : '0; + assign fprec_o = (FPU == 1) ? fprec_q : '0; + + assign mtvec_o = mtvec_q; + assign utvec_o = utvec_q; + assign mtvec_mode_o = mtvec_mode_q; + assign utvec_mode_o = utvec_mode_q; + + assign mepc_o = mepc_q; + assign uepc_o = uepc_q; + + assign depc_o = depc_q; + + assign pmp_addr_o = pmp_reg_q.pmpaddr; + assign pmp_cfg_o = pmp_reg_q.pmpcfg; + + assign debug_single_step_o = dcsr_q.step; + assign debug_ebreakm_o = dcsr_q.ebreakm; + assign debug_ebreaku_o = dcsr_q.ebreaku; + + // Output interrupt pending to ID/Controller and to clock gating (WFI) + assign irq_pending_o = menip.irq_software | menip.irq_timer | menip.irq_external | (|menip.irq_fast) | (|menip1); + + generate + if (PULP_SECURE == 1) + begin + + for(j=0;j2) && (cnt_idx<(NUM_MHPMCOUNTERS+3))) + // add +1 if any event is enabled and active + mhpmcounter_n[cnt_idx] = mhpmcounter_q[cnt_idx] + + |(hpm_events & mhpmevent_q[cnt_idx][NUM_HPM_EVENTS-1:0]) ; + end + + // ------------------------ + // HPM Registers + // Counter Registers: mhpcounter_q[] + genvar cnt_gidx; + generate + for(cnt_gidx = 0; cnt_gidx < 32; cnt_gidx++) begin : g_mhpmcounter + // mcyclce is located at index 0 + // there is no counter at index 1 + // minstret is located at index 2 + // Programable HPM counters start at index 3 + + if( (cnt_gidx == 1) || (cnt_gidx >= (NUM_MHPMCOUNTERS+3) ) ) begin : g_non_implemented + always_ff @(posedge clk, negedge rst_n) begin + mhpmcounter_q[cnt_gidx] <= 'b0; + end + end else begin : g_implemented + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + mhpmcounter_q[cnt_gidx] <= 'b0; + end else begin + mhpmcounter_q[cnt_gidx] <= mhpmcounter_n[cnt_gidx]; + end + end + end + end + endgenerate + + // Event Register: mhpevent_q[] + genvar evt_gidx; + generate + for(evt_gidx = 0; evt_gidx < 32; evt_gidx++) begin : g_mhpmevent + // programable HPM events start at index3 + if( (evt_gidx < 3) || (evt_gidx >= (NUM_MHPMCOUNTERS+3) ) ) begin : g_non_implemented + always_ff @(posedge clk, negedge rst_n) begin + mhpmevent_q[evt_gidx] <= 'b0; + end + end else begin : g_implemented + if(NUM_HPM_EVENTS < 32) begin + always_ff @(posedge clk, negedge rst_n) begin + mhpmevent_q[evt_gidx][31:NUM_HPM_EVENTS] <= 'b0; + end + end else begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= 'b0; + end else begin + mhpmevent_q[evt_gidx][NUM_HPM_EVENTS-1:0] <= mhpmevent_n[evt_gidx][NUM_HPM_EVENTS-1:0]; + end + end + end + end + end + endgenerate + + // Inhibit Regsiter: mcountinhibit_q + // Note: implemented counters are disabled out of reset to save power + genvar inh_gidx; + generate + for(inh_gidx = 0; inh_gidx < 32; inh_gidx++) begin : g_mcountinhibit + if( (inh_gidx == 1) || (inh_gidx >= (NUM_MHPMCOUNTERS+3) ) ) begin : g_non_implemented + always_ff @(posedge clk, negedge rst_n) begin + mcountinhibit_q[inh_gidx] <= 'b1; // default disable + end + end else begin : g_implemented + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + mcountinhibit_q[inh_gidx] <= 'b1; // default disable + end else begin + mcountinhibit_q[inh_gidx] <= mcountinhibit_n[inh_gidx]; + end + end + end + end + endgenerate + + // capture valid for event match + always_ff @(posedge clk, negedge rst_n) + if (!rst_n) + id_valid_q <= 'b0; + else + id_valid_q <= id_valid_i; + + +endmodule + diff --git a/hw/deps/riscv/riscv_decoder.sv b/hw/deps/riscv/riscv_decoder.sv new file mode 100644 index 0000000..3a2bfff --- /dev/null +++ b/hw/deps/riscv/riscv_decoder.sv @@ -0,0 +1,2675 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer Andreas Traber - atraber@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Matthias Baer - baermatt@student.ethz.ch // +// Igor Loi - igor.loi@unibo.it // +// Sven Stucki - svstucki@student.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: Decoder // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Decoder // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "apu_macros.sv" + +import riscv_defines::*; + +module riscv_decoder +#( + parameter PULP_HWLP = 0, + parameter A_EXTENSION = 0, + parameter FPU = 0, + parameter FP_DIVSQRT = 0, + parameter PULP_SECURE = 0, + parameter USE_PMP = 0, + parameter SHARED_FP = 0, + parameter SHARED_DSP_MULT = 0, + parameter SHARED_INT_MULT = 0, + parameter SHARED_INT_DIV = 0, + parameter SHARED_FP_DIVSQRT = 0, + parameter WAPUTYPE = 0, + parameter APU_WOP_CPU = 6, + parameter DEBUG_TRIGGER_EN = 1 +) +( + // singals running to/from controller + input logic deassert_we_i, // deassert we, we are stalled or not active + input logic data_misaligned_i, // misaligned data load/store in progress + input logic mult_multicycle_i, // multiplier taking multiple cycles, using op c as storage + output logic instr_multicycle_o, // true when multiple cycles are decoded + + output logic illegal_insn_o, // illegal instruction encountered + output logic ebrk_insn_o, // trap instruction encountered + + output logic mret_insn_o, // return from exception instruction encountered (M) + output logic uret_insn_o, // return from exception instruction encountered (S) + output logic dret_insn_o, // return from debug (M) + + output logic mret_dec_o, // return from exception instruction encountered (M) without deassert + output logic uret_dec_o, // return from exception instruction encountered (S) without deassert + output logic dret_dec_o, // return from debug (M) without deassert + + output logic ecall_insn_o, // environment call (syscall) instruction encountered + output logic pipe_flush_o, // pipeline flush is requested + + output logic fencei_insn_o, // fence.i instruction + + output logic rega_used_o, // rs1 is used by current instruction + output logic regb_used_o, // rs2 is used by current instruction + output logic regc_used_o, // rs3 is used by current instruction + + output logic reg_fp_a_o, // fp reg a is used + output logic reg_fp_b_o, // fp reg b is used + output logic reg_fp_c_o, // fp reg c is used + output logic reg_fp_d_o, // fp reg d is used + + output logic [ 0:0] bmask_a_mux_o, // bit manipulation mask a mux + output logic [ 1:0] bmask_b_mux_o, // bit manipulation mask b mux + output logic alu_bmask_a_mux_sel_o, // bit manipulation mask a mux (reg or imm) + output logic alu_bmask_b_mux_sel_o, // bit manipulation mask b mux (reg or imm) + + // from IF/ID pipeline + input logic [31:0] instr_rdata_i, // instruction read from instr memory/cache + input logic illegal_c_insn_i, // compressed instruction decode failed + + // ALU signals + output logic alu_en_o, // ALU enable + output logic [ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection + output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero + output logic [2:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate + output logic [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target + output logic [1:0] alu_vec_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes + output logic scalar_replication_o, // scalar replication enable + output logic scalar_replication_c_o, // scalar replication enable for operand C + output logic [0:0] imm_a_mux_sel_o, // immediate selection for operand a + output logic [3:0] imm_b_mux_sel_o, // immediate selection for operand b + output logic [1:0] regc_mux_o, // register c selection: S3, RD or 0 + output logic is_clpx_o, // whether the instruction is complex (pulpv3) or not + output logic is_subrot_o, + + // MUL related control signals + output logic [2:0] mult_operator_o, // Multiplication operation selection + output logic mult_int_en_o, // perform integer multiplication + output logic mult_dot_en_o, // perform dot multiplication + output logic [0:0] mult_imm_mux_o, // Multiplication immediate mux selector + output logic mult_sel_subword_o, // Select subwords for 16x16 bit of multiplier + output logic [1:0] mult_signed_mode_o, // Multiplication in signed mode + output logic [1:0] mult_dot_signed_o, // Dot product in signed mode + + // FPU + input logic [C_RM-1:0] frm_i, // Rounding mode from float CSR + + output logic [C_FPNEW_FMTBITS-1:0] fpu_dst_fmt_o, // fpu destination format + output logic [C_FPNEW_FMTBITS-1:0] fpu_src_fmt_o, // fpu source format + output logic [C_FPNEW_IFMTBITS-1:0] fpu_int_fmt_o, // fpu integer format (for casts) + + // APU + output logic apu_en_o, + output logic [WAPUTYPE-1:0] apu_type_o, + output logic [APU_WOP_CPU-1:0] apu_op_o, + output logic [1:0] apu_lat_o, + output logic [WAPUTYPE-1:0] apu_flags_src_o, + output logic [2:0] fp_rnd_mode_o, + + // register file related signals + output logic regfile_mem_we_o, // write enable for regfile + output logic regfile_alu_we_o, // write enable for 2nd regfile port + output logic regfile_alu_we_dec_o, // write enable for 2nd regfile port without deassert + output logic regfile_alu_waddr_sel_o, // Select register write address for ALU/MUL operations + + // CSR manipulation + output logic csr_access_o, // access to CSR + output logic csr_status_o, // access to xstatus CSR + output logic [1:0] csr_op_o, // operation to perform on CSR + input PrivLvl_t current_priv_lvl_i, // The current privilege level + + // Stack protection + output logic stack_access_o, // memory access through the stack pointer + + // LD/ST unit signals + output logic data_req_o, // start transaction to data memory + output logic data_we_o, // data memory write enable + output logic prepost_useincr_o, // when not active bypass the alu result for address calculation + output logic [1:0] data_type_o, // data type on data memory: byte, half word or word + output logic [1:0] data_sign_extension_o, // sign extension on read data from data memory / NaN boxing + output logic [1:0] data_reg_offset_o, // offset in byte inside register for stores + output logic data_load_event_o, // data request is in the special event range + + // Atomic memory access + output logic [5:0] atop_o, // define atomic memory operation + output logic buffer_o, // define bufferable store + + // hwloop signals + output logic [2:0] hwloop_we_o, // write enable for hwloop regs + output logic hwloop_target_mux_sel_o, // selects immediate for hwloop target + output logic hwloop_start_mux_sel_o, // selects hwloop start address input + output logic hwloop_cnt_mux_sel_o, // selects hwloop counter input + + input logic debug_mode_i, // processor is in debug mode + + // jump/branches + output logic [1:0] jump_in_dec_o, // jump_in_id without deassert + output logic [1:0] jump_in_id_o, // jump is being calculated in ALU + output logic [1:0] jump_target_mux_sel_o // jump target selection +); + + // careful when modifying the following parameters! these types have to match the ones in the APU! + localparam APUTYPE_DSP_MULT = (SHARED_DSP_MULT) ? 0 : 0; + localparam APUTYPE_INT_MULT = (SHARED_INT_MULT) ? SHARED_DSP_MULT : 0; + localparam APUTYPE_INT_DIV = (SHARED_INT_DIV) ? SHARED_DSP_MULT + SHARED_INT_MULT : 0; + localparam APUTYPE_FP = (SHARED_FP) ? SHARED_DSP_MULT + SHARED_INT_MULT + SHARED_INT_DIV : 0; + localparam APUTYPE_ADDSUB = (SHARED_FP) ? ((SHARED_FP==1) ? APUTYPE_FP : APUTYPE_FP) : 0; + localparam APUTYPE_MULT = (SHARED_FP) ? ((SHARED_FP==1) ? APUTYPE_FP+1 : APUTYPE_FP) : 0; + localparam APUTYPE_CAST = (SHARED_FP) ? ((SHARED_FP==1) ? APUTYPE_FP+2 : APUTYPE_FP) : 0; + localparam APUTYPE_MAC = (SHARED_FP) ? ((SHARED_FP==1) ? APUTYPE_FP+3 : APUTYPE_FP) : 0; + // SHARED_FP_DIVSQRT is without effect unless FP_DIVSQRT is set. + // SHARED_FP_DIVSQRT==1, SHARED_FP==1 (old config): separate div and sqrt units + // SHARED_FP_DIVSQRT==1, SHARED_FP==2 (new config): divsqrt enabled within shared FPnew blocks + // SHARED_FP_DIVSQRT==2, SHARED_FP==1 (old config): merged div/sqrt unit + // SHARED_FP_DIVSQRT==2, SHARED_FP==2 (new config): separate shared divsqrt blocks (allows different share ratio) + localparam APUTYPE_DIV = (SHARED_FP_DIVSQRT==1) ? ((SHARED_FP==1) ? APUTYPE_FP+4 : APUTYPE_FP) : + ((SHARED_FP_DIVSQRT==2) ? ((SHARED_FP==1) ? APUTYPE_FP+4 : APUTYPE_FP+1) : 0); + localparam APUTYPE_SQRT = (SHARED_FP_DIVSQRT==1) ? ((SHARED_FP==1) ? APUTYPE_FP+5 : APUTYPE_FP) : + ((SHARED_FP_DIVSQRT==2) ? ((SHARED_FP==1) ? APUTYPE_FP+4 : APUTYPE_FP+1) : 0); + + // write enable/request control + logic regfile_mem_we; + logic regfile_alu_we; + logic data_req; + logic [2:0] hwloop_we; + logic csr_illegal; + logic [1:0] jump_in_id; + + logic [1:0] csr_op; + + logic mult_int_en; + logic mult_dot_en; + logic apu_en; + + // this instruction needs floating-point rounding-mode verification + logic check_fprm; + + logic [C_FPNEW_OPBITS-1:0] fpu_op; // fpu operation + logic fpu_op_mod; // fpu operation modifier + logic fpu_vec_op; // fpu vectorial operation + // unittypes for latencies to help us decode for APU + enum logic[1:0] {ADDMUL, DIVSQRT, NONCOMP, CONV} fp_op_group; + + + ///////////////////////////////////////////// + // ____ _ // + // | _ \ ___ ___ ___ __| | ___ _ __ // + // | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| // + // | |_| | __/ (_| (_) | (_| | __/ | // + // |____/ \___|\___\___/ \__,_|\___|_| // + // // + ///////////////////////////////////////////// + + always_comb + begin + jump_in_id = BRANCH_NONE; + jump_target_mux_sel_o = JT_JAL; + + alu_en_o = 1'b1; + alu_operator_o = ALU_SLTU; + alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + alu_op_c_mux_sel_o = OP_C_REGC_OR_FWD; + alu_vec_mode_o = VEC_MODE32; + scalar_replication_o = 1'b0; + scalar_replication_c_o = 1'b0; + regc_mux_o = REGC_ZERO; + imm_a_mux_sel_o = IMMA_ZERO; + imm_b_mux_sel_o = IMMB_I; + + mult_operator_o = MUL_I; + mult_int_en = 1'b0; + mult_dot_en = 1'b0; + mult_imm_mux_o = MIMM_ZERO; + mult_signed_mode_o = 2'b00; + mult_sel_subword_o = 1'b0; + mult_dot_signed_o = 2'b00; + + apu_en = 1'b0; + apu_type_o = '0; + apu_op_o = '0; + apu_lat_o = '0; + apu_flags_src_o = '0; + fp_rnd_mode_o = '0; + fpu_op = fpnew_pkg::SGNJ; + fpu_op_mod = 1'b0; + fpu_vec_op = 1'b0; + fpu_dst_fmt_o = fpnew_pkg::FP32; + fpu_src_fmt_o = fpnew_pkg::FP32; + fpu_int_fmt_o = fpnew_pkg::INT32; + check_fprm = 1'b0; + fp_op_group = ADDMUL; + + regfile_mem_we = 1'b0; + regfile_alu_we = 1'b0; + regfile_alu_waddr_sel_o = 1'b1; + + prepost_useincr_o = 1'b1; + + hwloop_we = 3'b0; + hwloop_target_mux_sel_o = 1'b0; + hwloop_start_mux_sel_o = 1'b0; + hwloop_cnt_mux_sel_o = 1'b0; + + csr_access_o = 1'b0; + csr_status_o = 1'b0; + csr_illegal = 1'b0; + csr_op = CSR_OP_READ; + mret_insn_o = 1'b0; + uret_insn_o = 1'b0; + + dret_insn_o = 1'b0; + + data_we_o = 1'b0; + data_type_o = 2'b00; + data_sign_extension_o = 2'b00; + data_reg_offset_o = 2'b00; + data_req = 1'b0; + data_load_event_o = 1'b0; + + atop_o = 6'b000000; + buffer_o = 1'b0; + + illegal_insn_o = 1'b0; + ebrk_insn_o = 1'b0; + ecall_insn_o = 1'b0; + pipe_flush_o = 1'b0; + + fencei_insn_o = 1'b0; + + rega_used_o = 1'b0; + regb_used_o = 1'b0; + regc_used_o = 1'b0; + reg_fp_a_o = 1'b0; + reg_fp_b_o = 1'b0; + reg_fp_c_o = 1'b0; + reg_fp_d_o = 1'b0; + + bmask_a_mux_o = BMASK_A_ZERO; + bmask_b_mux_o = BMASK_B_ZERO; + alu_bmask_a_mux_sel_o = BMASK_A_IMM; + alu_bmask_b_mux_sel_o = BMASK_B_IMM; + + instr_multicycle_o = 1'b0; + is_clpx_o = 1'b0; + is_subrot_o = 1'b0; + + mret_dec_o = 1'b0; + uret_dec_o = 1'b0; + dret_dec_o = 1'b0; + + unique case (instr_rdata_i[6:0]) + + ////////////////////////////////////// + // _ _ _ __ __ ____ ____ // + // | | | | | \/ | _ \/ ___| // + // _ | | | | | |\/| | |_) \___ \ // + // | |_| | |_| | | | | __/ ___) | // + // \___/ \___/|_| |_|_| |____/ // + // // + ////////////////////////////////////// + + OPCODE_JAL: begin // Jump and Link + jump_target_mux_sel_o = JT_JAL; + jump_in_id = BRANCH_JAL; + // Calculate and store PC+4 + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_PCINCR; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + // Calculate jump target (= PC + UJ imm) + end + + OPCODE_JALR: begin // Jump and Link Register + jump_target_mux_sel_o = JT_JALR; + jump_in_id = BRANCH_JALR; + // Calculate and store PC+4 + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_PCINCR; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + // Calculate jump target (= RS1 + I imm) + rega_used_o = 1'b1; + + if (instr_rdata_i[14:12] != 3'b0) begin + jump_in_id = BRANCH_NONE; + regfile_alu_we = 1'b0; + illegal_insn_o = 1'b1; + end + end + + OPCODE_BRANCH: begin // Branch + jump_target_mux_sel_o = JT_COND; + jump_in_id = BRANCH_COND; + alu_op_c_mux_sel_o = OP_C_JT; + rega_used_o = 1'b1; + regb_used_o = 1'b1; + + unique case (instr_rdata_i[14:12]) + 3'b000: alu_operator_o = ALU_EQ; + 3'b001: alu_operator_o = ALU_NE; + 3'b100: alu_operator_o = ALU_LTS; + 3'b101: alu_operator_o = ALU_GES; + 3'b110: alu_operator_o = ALU_LTU; + 3'b111: alu_operator_o = ALU_GEU; + 3'b010: begin + alu_operator_o = ALU_EQ; + regb_used_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_BI; + end + 3'b011: begin + alu_operator_o = ALU_NE; + regb_used_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_BI; + end + endcase + end + + + ////////////////////////////////// + // _ ____ ______ _____ // + // | | | _ \ / / ___|_ _| // + // | | | | | |/ /\___ \ | | // + // | |___| |_| / / ___) || | // + // |_____|____/_/ |____/ |_| // + // // + ////////////////////////////////// + + OPCODE_STORE, + OPCODE_STORE_BUF, + OPCODE_STORE_POST, + OPCODE_STORE_POST_BUF: begin + data_req = 1'b1; + data_we_o = 1'b1; + rega_used_o = 1'b1; + regb_used_o = 1'b1; + alu_operator_o = ALU_ADD; + instr_multicycle_o = 1'b1; + // pass write data through ALU operand c + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + + // post-increment setup + if (instr_rdata_i[6:0] == OPCODE_STORE_POST) begin + prepost_useincr_o = 1'b0; + regfile_alu_waddr_sel_o = 1'b0; + regfile_alu_we = 1'b1; + end + + if (instr_rdata_i[14] == 1'b0) begin + // offset from immediate + imm_b_mux_sel_o = IMMB_S; + alu_op_b_mux_sel_o = OP_B_IMM; + end else begin + // offset from register + regc_used_o = 1'b1; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + regc_mux_o = REGC_RD; + end + + // store size + unique case (instr_rdata_i[13:12]) + 2'b00: data_type_o = 2'b10; // SB + 2'b01: data_type_o = 2'b01; // SH + 2'b10: data_type_o = 2'b00; // SW + default: begin + data_req = 1'b0; + data_we_o = 1'b0; + illegal_insn_o = 1'b1; + end + endcase + + if (instr_rdata_i[6:0] == OPCODE_STORE_BUF + || instr_rdata_i[6:0] == OPCODE_STORE_POST_BUF) begin + buffer_o = 1'b1; + end + + stack_access_o = (instr_rdata_i[19:15] == 5'd2); + end + + OPCODE_LOAD, + OPCODE_LOAD_POST: begin + data_req = 1'b1; + regfile_mem_we = 1'b1; + rega_used_o = 1'b1; + data_type_o = 2'b00; + instr_multicycle_o = 1'b1; + // offset from immediate + alu_operator_o = ALU_ADD; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_I; + + // post-increment setup + if (instr_rdata_i[6:0] == OPCODE_LOAD_POST) begin + prepost_useincr_o = 1'b0; + regfile_alu_waddr_sel_o = 1'b0; + regfile_alu_we = 1'b1; + end + + // sign/zero extension + data_sign_extension_o = {1'b0,~instr_rdata_i[14]}; + + // load size + unique case (instr_rdata_i[13:12]) + 2'b00: data_type_o = 2'b10; // LB + 2'b01: data_type_o = 2'b01; // LH + 2'b10: data_type_o = 2'b00; // LW + default: data_type_o = 2'b00; // illegal or reg-reg + endcase + + // reg-reg load (different encoding) + if (instr_rdata_i[14:12] == 3'b111) begin + // offset from RS2 + regb_used_o = 1'b1; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + + // sign/zero extension + data_sign_extension_o = {1'b0, ~instr_rdata_i[30]}; + + // load size + unique case (instr_rdata_i[31:25]) + 7'b0000_000, + 7'b0100_000: data_type_o = 2'b10; // LB, LBU + 7'b0001_000, + 7'b0101_000: data_type_o = 2'b01; // LH, LHU + 7'b0010_000: data_type_o = 2'b00; // LW + default: begin + illegal_insn_o = 1'b1; + end + endcase + end + + // special p.elw (event load) + if (instr_rdata_i[14:12] == 3'b110) + data_load_event_o = 1'b1; + + if (instr_rdata_i[14:12] == 3'b011) begin + // LD -> RV64 only + illegal_insn_o = 1'b1; + end + + stack_access_o = (instr_rdata_i[19:15] == 5'd2); + end + + OPCODE_AMO: begin + if (A_EXTENSION) begin : decode_amo + if (instr_rdata_i[14:12] == 3'b010) begin // RV32A Extension (word) + data_req = 1'b1; + data_type_o = 2'b00; + rega_used_o = 1'b1; + regb_used_o = 1'b1; + regfile_mem_we = 1'b1; + prepost_useincr_o = 1'b0; // only use alu_operand_a as address (not a+b) + alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; + + data_sign_extension_o = 1'b1; + + // Apply AMO instruction at `atop_o`. + atop_o = {1'b1, instr_rdata_i[31:27]}; + + unique case (instr_rdata_i[31:27]) + AMO_LR: begin + data_we_o = 1'b0; + end + AMO_SC, + AMO_SWAP, + AMO_ADD, + AMO_XOR, + AMO_AND, + AMO_OR, + AMO_MIN, + AMO_MAX, + AMO_MINU, + AMO_MAXU: begin + data_we_o = 1'b1; + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; // pass write data through ALU operand c + end + default : illegal_insn_o = 1'b1; + endcase + end + else begin + illegal_insn_o = 1'b1; + end + end else begin : no_decode_amo + illegal_insn_o = 1'b1; + end + end + + + ////////////////////////// + // _ _ _ _ // + // / \ | | | | | | // + // / _ \ | | | | | | // + // / ___ \| |__| |_| | // + // /_/ \_\_____\___/ // + // // + ////////////////////////// + + OPCODE_LUI: begin // Load Upper Immediate + alu_op_a_mux_sel_o = OP_A_IMM; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_a_mux_sel_o = IMMA_ZERO; + imm_b_mux_sel_o = IMMB_U; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + end + + OPCODE_AUIPC: begin // Add Upper Immediate to PC + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_U; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + end + + OPCODE_OPIMM: begin // Register-Immediate ALU Operations + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_I; + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + + unique case (instr_rdata_i[14:12]) + 3'b000: alu_operator_o = ALU_ADD; // Add Immediate + 3'b010: alu_operator_o = ALU_SLTS; // Set to one if Lower Than Immediate + 3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned + 3'b100: alu_operator_o = ALU_XOR; // Exclusive Or with Immediate + 3'b110: alu_operator_o = ALU_OR; // Or with Immediate + 3'b111: alu_operator_o = ALU_AND; // And with Immediate + + 3'b001: begin + alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate + if (instr_rdata_i[31:25] != 7'b0) + illegal_insn_o = 1'b1; + end + + 3'b101: begin + if (instr_rdata_i[31:25] == 7'b0) + alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate + else if (instr_rdata_i[31:25] == 7'b010_0000) + alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate + else + illegal_insn_o = 1'b1; + end + + + endcase + end + + OPCODE_OP: begin // Register-Register ALU operation + + // PREFIX 11 + if (instr_rdata_i[31:30] == 2'b11) begin + + ////////////////////////////// + // IMMEDIATE BIT-MANIPULATION + ////////////////////////////// + + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + + // bit-manipulation instructions + bmask_a_mux_o = BMASK_A_S3; + bmask_b_mux_o = BMASK_B_S2; + alu_op_b_mux_sel_o = OP_B_IMM; + + unique case (instr_rdata_i[14:12]) + 3'b000: begin + alu_operator_o = ALU_BEXT; + imm_b_mux_sel_o = IMMB_S2; + bmask_b_mux_o = BMASK_B_ZERO; + end + 3'b001: begin + alu_operator_o = ALU_BEXTU; + imm_b_mux_sel_o = IMMB_S2; + bmask_b_mux_o = BMASK_B_ZERO; + end + 3'b010: begin + alu_operator_o = ALU_BINS; + imm_b_mux_sel_o = IMMB_S2; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + end + 3'b011: begin + alu_operator_o = ALU_BCLR; + end + 3'b100: begin + alu_operator_o = ALU_BSET; + end + 3'b101: begin + alu_operator_o = ALU_BREV; + // Enable write back to RD + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + // Extract the source register on operand a + imm_b_mux_sel_o = IMMB_S2; + // Map the radix to bmask_a immediate + alu_bmask_a_mux_sel_o = BMASK_A_IMM; + end + default: illegal_insn_o = 1'b1; + endcase + end + + // PREFIX 10 + else if (instr_rdata_i[31:30] == 2'b10) begin + + ////////////////////////////// + // REGISTER BIT-MANIPULATION + ////////////////////////////// + if (instr_rdata_i[29:25]==5'b00000) begin + + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + + bmask_a_mux_o = BMASK_A_S3; + bmask_b_mux_o = BMASK_B_S2; + alu_op_b_mux_sel_o = OP_B_IMM; + + unique case (instr_rdata_i[14:12]) + 3'b000: begin + alu_operator_o = ALU_BEXT; + imm_b_mux_sel_o = IMMB_S2; + bmask_b_mux_o = BMASK_B_ZERO; + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + regb_used_o = 1'b1; + end + 3'b001: begin + alu_operator_o = ALU_BEXTU; + imm_b_mux_sel_o = IMMB_S2; + bmask_b_mux_o = BMASK_B_ZERO; + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + regb_used_o = 1'b1; + end + 3'b010: begin + alu_operator_o = ALU_BINS; + imm_b_mux_sel_o = IMMB_S2; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + regb_used_o = 1'b1; + end + 3'b011: begin + alu_operator_o = ALU_BCLR; + //register variant + regb_used_o = 1'b1; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + end + 3'b100: begin + alu_operator_o = ALU_BSET; + //register variant + regb_used_o = 1'b1; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + end + default: illegal_insn_o = 1'b1; + endcase + + /////////////////////// + // VECTORIAL FLOAT OPS + /////////////////////// + end else begin + // Vectorial FP not available in 'old' shared FPU + if (FPU==1 && C_XFVEC && SHARED_FP!=1) begin + + // using APU instead of ALU + apu_en = 1'b1; + alu_en_o = 1'b0; + apu_flags_src_o = APU_FLAGS_FPNEW; + // by default, set all registers to FP registers and use 2 + rega_used_o = 1'b1; + regb_used_o = 1'b1; + reg_fp_a_o = 1'b1; + reg_fp_b_o = 1'b1; + reg_fp_d_o = 1'b1; + fpu_vec_op = 1'b1; + // replication bit comes from instruction (can change for some ops) + scalar_replication_o = instr_rdata_i[14]; + // by default we need to verify rm is legal but assume it is for now + check_fprm = 1'b1; + fp_rnd_mode_o = frm_i; // all vectorial ops have rm from fcsr + + // Decode Formats + unique case (instr_rdata_i[13:12]) + // FP32 + 2'b00: begin + fpu_dst_fmt_o = fpnew_pkg::FP32; + alu_vec_mode_o = VEC_MODE32; + end + // FP16ALT + 2'b01: begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + alu_vec_mode_o = VEC_MODE16; + end + // FP16 + 2'b10: begin + fpu_dst_fmt_o = fpnew_pkg::FP16; + alu_vec_mode_o = VEC_MODE16; + end + // FP8 + 2'b11: begin + fpu_dst_fmt_o = fpnew_pkg::FP8; + alu_vec_mode_o = VEC_MODE8; + end + endcase + + // By default, src=dst + fpu_src_fmt_o = fpu_dst_fmt_o; + + // decode vectorial FP instruction + unique case (instr_rdata_i[29:25]) inside + // vfadd.vfmt - Vectorial FP Addition + 5'b00001: begin + fpu_op = fpnew_pkg::ADD; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_ADDSUB; + // FPnew needs addition operands as operand B and C + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + scalar_replication_o = 1'b0; + scalar_replication_c_o = instr_rdata_i[14]; + end + // vfsub.vfmt - Vectorial FP Subtraction + 5'b00010: begin + fpu_op = fpnew_pkg::ADD; + fpu_op_mod = 1'b1; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_ADDSUB; + // FPnew needs addition operands as operand B and C + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + scalar_replication_o = 1'b0; + scalar_replication_c_o = instr_rdata_i[14]; + end + // vfmul.vfmt - Vectorial FP Multiplication + 5'b00011: begin + fpu_op = fpnew_pkg::MUL; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MULT; + end + // vfdiv.vfmt - Vectorial FP Division + 5'b00100: begin + if (FP_DIVSQRT) begin + fpu_op = fpnew_pkg::DIV; + fp_op_group = DIVSQRT; + apu_type_o = APUTYPE_DIV; + end else + illegal_insn_o = 1'b1; + end + // vfmin.vfmt - Vectorial FP Minimum + 5'b00101: begin + fpu_op = fpnew_pkg::MINMAX; + fp_rnd_mode_o = 3'b000; // min + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm + end + // vfmax.vfmt - Vectorial FP Maximum + 5'b00110: begin + fpu_op = fpnew_pkg::MINMAX; + fp_rnd_mode_o = 3'b001; // max + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm + end + // vfsqrt.vfmt - Vectorial FP Square Root + 5'b00111: begin + if (FP_DIVSQRT) begin + regb_used_o = 1'b0; + fpu_op = fpnew_pkg::SQRT; + fp_op_group = DIVSQRT; + apu_type_o = APUTYPE_SQRT; + // rs2 and R must be zero + if ((instr_rdata_i[24:20] != 5'b00000) || instr_rdata_i[14]) begin + illegal_insn_o = 1'b1; + end + end else + illegal_insn_o = 1'b1; + end + // vfmac.vfmt - Vectorial FP Multiply-Accumulate + 5'b01000: begin + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; // third operand is rd + reg_fp_c_o = 1'b1; + fpu_op = fpnew_pkg::FMADD; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MAC; + end + // vfmre.vfmt - Vectorial FP Multiply-Reduce + 5'b01001: begin + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; // third operand is rd + reg_fp_c_o = 1'b1; + fpu_op = fpnew_pkg::FMADD; + fpu_op_mod = 1'b1; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MAC; + end + // Moves, Conversions, Classifications + 5'b01100: begin + regb_used_o = 1'b0; + scalar_replication_o = 1'b0; + // Decode Operation in rs2 + unique case (instr_rdata_i[24:20]) inside + // vfmv.{x.vfmt/vfmt.x} - Vectorial FP Reg <-> GP Reg Moves + 5'b00000: begin + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit + fpu_op = fpnew_pkg::SGNJ; + fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + // GP reg to FP reg + if (instr_rdata_i[14]) begin + reg_fp_a_o = 1'b0; // go from integer regfile + fpu_op_mod = 1'b0; // nan-box result + end + // FP reg to GP reg + else begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op_mod = 1'b1; // sign-extend result + end + end + // vfclass.vfmt - Vectorial FP Classifications + 5'b00001: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CLASSIFY; + fp_rnd_mode_o = 3'b000; + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + // R must not be set + if (instr_rdata_i[14]) illegal_insn_o = 1'b1; + end + // vfcvt.{x.vfmt/vfmt.x} - Vectorial FP <-> Int Conversions + 5'b0001?: begin + fp_op_group = CONV; + fpu_op_mod = instr_rdata_i[14]; // signed/unsigned switch + apu_type_o = APUTYPE_CAST; + // Integer width matches FP width + unique case (instr_rdata_i[13:12]) + // FP32 + 2'b00 : fpu_int_fmt_o = fpnew_pkg::INT32; + // FP16[ALT] + 2'b01, + 2'b10: fpu_int_fmt_o = fpnew_pkg::INT16; + // FP8 + 2'b11: fpu_int_fmt_o = fpnew_pkg::INT8; + endcase + // Int to FP conversion + if (instr_rdata_i[20]) begin + reg_fp_a_o = 1'b0; // go from integer regfile + fpu_op = fpnew_pkg::I2F; + end + // FP to Int conversion + else begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::F2I; + end + end + // vfcvt.vfmt.vfmt - Vectorial FP <-> FP Conversions + 5'b001??: begin + fpu_op = fpnew_pkg::F2F; + fp_op_group = CONV; + apu_type_o = APUTYPE_CAST; + // check source format + unique case (instr_rdata_i[21:20]) + // Only process instruction if corresponding extension is active (static) + 2'b00: begin + fpu_src_fmt_o = fpnew_pkg::FP32; + if (~C_RVF) illegal_insn_o = 1'b1; + end + 2'b01: begin + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + if (~C_XF16ALT) illegal_insn_o = 1'b1; + end + 2'b10: begin + fpu_src_fmt_o = fpnew_pkg::FP16; + if (~C_XF16) illegal_insn_o = 1'b1; + end + 2'b11: begin + fpu_src_fmt_o = fpnew_pkg::FP8; + if (~C_XF8) illegal_insn_o = 1'b1; + end + endcase + // R must not be set + if (instr_rdata_i[14]) illegal_insn_o = 1'b1; + end + // others + default : illegal_insn_o = 1'b1; + endcase + end + // vfsgnj.vfmt - Vectorial FP Sign Injection + 5'b01101: begin + fpu_op = fpnew_pkg::SGNJ; + fp_rnd_mode_o = 3'b000; // sgnj + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfsgnjn.vfmt - Vectorial FP Negated Sign Injection + 5'b01110: begin + fpu_op = fpnew_pkg::SGNJ; + fp_rnd_mode_o = 3'b001; // sgnjn + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfsgnjx.vfmt - Vectorial FP Xored Sign Injection + 5'b01111: begin + fpu_op = fpnew_pkg::SGNJ; + fp_rnd_mode_o = 3'b010; // sgnjx + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfeq.vfmt - Vectorial FP Equals + 5'b10000: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fp_rnd_mode_o = 3'b010; // eq + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfne.vfmt - Vectorial FP Not Equals + 5'b10001: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fpu_op_mod = 1'b1; // invert output + fp_rnd_mode_o = 3'b010; // eq + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vflt.vfmt - Vectorial FP Less Than + 5'b10010: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fp_rnd_mode_o = 3'b001; // lt + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfge.vfmt - Vectorial FP Greater Than or Equals + 5'b10011: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fpu_op_mod = 1'b1; // invert output + fp_rnd_mode_o = 3'b001; // lt + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfle.vfmt - Vectorial FP Less Than or Equals + 5'b10100: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fp_rnd_mode_o = 3'b000; // le + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfgt.vfmt - Vectorial FP Greater Than + 5'b10101: begin + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::CMP; + fpu_op_mod = 1'b1; // invert output + fp_rnd_mode_o = 3'b000; // le + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; + end + // vfcpk{a-d}.vfmt.s/d + 5'b110??: begin + // vfcpk{{a/c}/{b/d}} selection in R bit + fpu_op_mod = instr_rdata_i[14]; + fp_op_group = CONV; + apu_type_o = APUTYPE_CAST; + scalar_replication_o = 1'b0; + + if (instr_rdata_i[25]) fpu_op = fpnew_pkg::CPKCD; // vfcpk{c/d} + else fpu_op = fpnew_pkg::CPKAB; // vfcpk{a/b} + + // vfcpk{a-d}.vfmt.d - from double + if (instr_rdata_i[26]) begin + fpu_src_fmt_o = fpnew_pkg::FP64; + if (~C_RVD) illegal_insn_o = 1'b1; + end + // vfcpk{a-d}.vfmt.s + else begin + fpu_src_fmt_o = fpnew_pkg::FP32; + if (~C_RVF) illegal_insn_o = 1'b1; + end + // Resolve legal vfcpk / format combinations (mostly static) + if (fpu_op == fpnew_pkg::CPKCD) begin // vfcpk{c/d} not possible unless FP8 and FLEN>=64 + if (~C_XF8 || ~C_RVD) illegal_insn_o = 1'b1; + end else begin + if (instr_rdata_i[14]) begin // vfcpkb + // vfcpkb not possible for FP32 + if (fpu_dst_fmt_o == fpnew_pkg::FP32) illegal_insn_o = 1'b1; + // vfcpkb not possible for FP16[ALT] if not RVD + if (~C_RVD && (fpu_dst_fmt_o != fpnew_pkg::FP8)) illegal_insn_o = 1'b1; + end + end + end + // Rest are illegal instructions + default: begin + illegal_insn_o = 1'b1; + end + endcase + + // check enabled formats (static) + // need RVD for F vectors + if ((~C_RVF || ~C_RVD) && fpu_dst_fmt_o == fpnew_pkg::FP32) illegal_insn_o = 1'b1; + // need RVF for F16 vectors + if ((~C_XF16 || ~C_RVF) && fpu_dst_fmt_o == fpnew_pkg::FP16) illegal_insn_o = 1'b1; + // need RVF for F16 vectors + if ((~C_XF16ALT || ~C_RVF) && fpu_dst_fmt_o == fpnew_pkg::FP16ALT) begin + illegal_insn_o = 1'b1; + end + // need F16 for F8 vectors + if ((~C_XF8 || (~C_XF16 && ~C_XF16ALT)) && fpu_dst_fmt_o == fpnew_pkg::FP8) begin + illegal_insn_o = 1'b1; + end + + // check rounding mode + if (check_fprm) begin + unique case (frm_i) inside + [3'b000:3'b100] : ; //legal rounding modes + default : illegal_insn_o = 1'b1; + endcase + end + + // Set latencies for FPnew from config. The C_LAT constants contain the number + // of pipeline registers. the APU takes the following values: + // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages + case (fp_op_group) + // ADDMUL has format dependent latency + ADDMUL : begin + unique case (fpu_dst_fmt_o) + fpnew_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; + fpnew_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; + fpnew_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; + fpnew_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; + default : ; + endcase + end + // DIVSQRT is iterative and takes more than 2 cycles + DIVSQRT : apu_lat_o = 2'h3; + // NONCOMP uses the same latency for all formats + NONCOMP : apu_lat_o = (C_LAT_NONCOMP<2) ? C_LAT_NONCOMP+1 : 2'h3; + // CONV uses the same latency for all formats + CONV : apu_lat_o = (C_LAT_CONV<2) ? C_LAT_CONV+1 : 2'h3; + endcase + + // Set FPnew OP and OPMOD as the APU op + apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; + end + // FPU!=1 or no Vectors or old shared unit + else begin + illegal_insn_o = 1'b1; + end + end // Vectorial Float Ops + + end // prefix 10 + + // PREFIX 00/01 + else begin + // non bit-manipulation instructions + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + + if (~instr_rdata_i[28]) regb_used_o = 1'b1; + + unique case ({instr_rdata_i[30:25], instr_rdata_i[14:12]}) + // RV32I ALU operations + {6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add + {6'b10_0000, 3'b000}: alu_operator_o = ALU_SUB; // Sub + {6'b00_0000, 3'b010}: alu_operator_o = ALU_SLTS; // Set Lower Than + {6'b00_0000, 3'b011}: alu_operator_o = ALU_SLTU; // Set Lower Than Unsigned + {6'b00_0000, 3'b100}: alu_operator_o = ALU_XOR; // Xor + {6'b00_0000, 3'b110}: alu_operator_o = ALU_OR; // Or + {6'b00_0000, 3'b111}: alu_operator_o = ALU_AND; // And + {6'b00_0000, 3'b001}: alu_operator_o = ALU_SLL; // Shift Left Logical + {6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical + {6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic + + // supported RV32M instructions + {6'b00_0001, 3'b000}: begin // mul + alu_en_o = 1'b0; + mult_int_en = 1'b1; + mult_operator_o = MUL_MAC32; + regc_mux_o = REGC_ZERO; + end + {6'b00_0001, 3'b001}: begin // mulh + alu_en_o = 1'b0; + regc_used_o = 1'b1; + regc_mux_o = REGC_ZERO; + mult_signed_mode_o = 2'b11; + mult_int_en = 1'b1; + mult_operator_o = MUL_H; + instr_multicycle_o = 1'b1; + end + {6'b00_0001, 3'b010}: begin // mulhsu + alu_en_o = 1'b0; + regc_used_o = 1'b1; + regc_mux_o = REGC_ZERO; + mult_signed_mode_o = 2'b01; + mult_int_en = 1'b1; + mult_operator_o = MUL_H; + instr_multicycle_o = 1'b1; + end + {6'b00_0001, 3'b011}: begin // mulhu + alu_en_o = 1'b0; + regc_used_o = 1'b1; + regc_mux_o = REGC_ZERO; + mult_signed_mode_o = 2'b00; + mult_int_en = 1'b1; + mult_operator_o = MUL_H; + instr_multicycle_o = 1'b1; + end + {6'b00_0001, 3'b100}: begin // div + alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + regc_mux_o = REGC_S1; + regc_used_o = 1'b1; + regb_used_o = 1'b1; + rega_used_o = 1'b0; + alu_operator_o = ALU_DIV; + instr_multicycle_o = 1'b1; + `USE_APU_INT_DIV + end + {6'b00_0001, 3'b101}: begin // divu + alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + regc_mux_o = REGC_S1; + regc_used_o = 1'b1; + regb_used_o = 1'b1; + rega_used_o = 1'b0; + alu_operator_o = ALU_DIVU; + instr_multicycle_o = 1'b1; + `USE_APU_INT_DIV + end + {6'b00_0001, 3'b110}: begin // rem + alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + regc_mux_o = REGC_S1; + regc_used_o = 1'b1; + regb_used_o = 1'b1; + rega_used_o = 1'b0; + alu_operator_o = ALU_REM; + instr_multicycle_o = 1'b1; + `USE_APU_INT_DIV + end + {6'b00_0001, 3'b111}: begin // remu + alu_op_a_mux_sel_o = OP_A_REGB_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + regc_mux_o = REGC_S1; + regc_used_o = 1'b1; + regb_used_o = 1'b1; + rega_used_o = 1'b0; + alu_operator_o = ALU_REMU; + instr_multicycle_o = 1'b1; + `USE_APU_INT_DIV + end + + // PULP specific instructions + {6'b10_0001, 3'b000}: begin // p.mac + alu_en_o = 1'b0; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + mult_int_en = 1'b1; + mult_operator_o = MUL_MAC32; + `USE_APU_INT_MULT + end + {6'b10_0001, 3'b001}: begin // p.msu + alu_en_o = 1'b0; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + mult_int_en = 1'b1; + mult_operator_o = MUL_MSU32; + `USE_APU_INT_MULT + end + {6'b00_0010, 3'b010}: alu_operator_o = ALU_SLETS; // Set Lower Equal Than p.slet + {6'b00_0010, 3'b011}: alu_operator_o = ALU_SLETU; // Set Lower Equal Than Unsigned p.sletu + {6'b00_0010, 3'b100}: begin alu_operator_o = ALU_MIN; end // Min p.min + {6'b00_0010, 3'b101}: begin alu_operator_o = ALU_MINU; end // Min Unsigned + {6'b00_0010, 3'b110}: begin alu_operator_o = ALU_MAX; end // Max + {6'b00_0010, 3'b111}: begin alu_operator_o = ALU_MAXU; end // Max Unsigned + {6'b00_0100, 3'b101}: begin alu_operator_o = ALU_ROR; end // Rotate Right + + // PULP specific instructions using only one source register + {6'b00_1000, 3'b000}: begin alu_operator_o = ALU_FF1; end // Find First 1 + {6'b00_1000, 3'b001}: begin alu_operator_o = ALU_FL1; end // Find Last 1 + {6'b00_1000, 3'b010}: begin alu_operator_o = ALU_CLB; end // Count Leading Bits + {6'b00_1000, 3'b011}: begin alu_operator_o = ALU_CNT; end // Count set bits (popcount) + {6'b00_1000, 3'b100}: begin alu_operator_o = ALU_EXTS; alu_vec_mode_o = VEC_MODE16; end // Sign-extend Half-word + {6'b00_1000, 3'b101}: begin alu_operator_o = ALU_EXT; alu_vec_mode_o = VEC_MODE16; end // Zero-extend Half-word + {6'b00_1000, 3'b110}: begin alu_operator_o = ALU_EXTS; alu_vec_mode_o = VEC_MODE8; end // Sign-extend Byte + {6'b00_1000, 3'b111}: begin alu_operator_o = ALU_EXT; alu_vec_mode_o = VEC_MODE8; end // Zero-extend Byte + + {6'b00_0010, 3'b000}: begin alu_operator_o = ALU_ABS; end // p.abs + + {6'b00_1010, 3'b001}: begin // p.clip + alu_operator_o = ALU_CLIP; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_CLIP; + end + + {6'b00_1010, 3'b010}: begin // p.clipu + alu_operator_o = ALU_CLIPU; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_CLIP; + end + + {6'b00_1010, 3'b101}: begin // p.clipr + alu_operator_o = ALU_CLIP; + regb_used_o = 1'b1; + end + + {6'b00_1010, 3'b110}: begin // p.clipur + alu_operator_o = ALU_CLIPU; + regb_used_o = 1'b1; + end + + default: begin + illegal_insn_o = 1'b1; + end + endcase + end + end + + //////////////////////////// + // ______ _____ _ _ // + // | ____| __ \| | | | // + // | |__ | |__) | | | | // + // | __| | ___/| | | | // + // | | | | | |__| | // + // |_| |_| \____/ // + // // + //////////////////////////// + + // floating point arithmetic + OPCODE_OP_FP: begin + if (FPU==1) begin + + // using APU instead of ALU + apu_en = 1'b1; + alu_en_o = 1'b0; + // Private and new shared FP use FPnew + apu_flags_src_o = (SHARED_FP==1) ? APU_FLAGS_FP : APU_FLAGS_FPNEW; + // by default, set all registers to FP registers and use 2 + rega_used_o = 1'b1; + regb_used_o = 1'b1; + reg_fp_a_o = 1'b1; + reg_fp_b_o = 1'b1; + reg_fp_d_o = 1'b1; + // by default we need to verify rm is legal but assume it is for now + check_fprm = 1'b1; + fp_rnd_mode_o = instr_rdata_i[14:12]; + + // Decode Formats (preliminary, can change for some ops) + unique case (instr_rdata_i[26:25]) + // FP32 + 2'b00: fpu_dst_fmt_o = fpnew_pkg::FP32; + // FP64 + 2'b01: fpu_dst_fmt_o = fpnew_pkg::FP64; + // FP16 or FP16ALT + 2'b10: begin + // FP16alt encoded in rm field + if (instr_rdata_i[14:12]==3'b101) fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + // this can still change to FP16ALT + else fpu_dst_fmt_o = fpnew_pkg::FP16; + end + // FP8 + 2'b11: fpu_dst_fmt_o = fpnew_pkg::FP8; + endcase + + // By default, src=dst + fpu_src_fmt_o = fpu_dst_fmt_o; + + // decode FP instruction + unique case (instr_rdata_i[31:27]) + // fadd.fmt - FP Addition + 5'b00000: begin + fpu_op = fpnew_pkg::ADD; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_ADDSUB; + apu_op_o = 2'b0; + apu_lat_o = (PIPE_REG_ADDSUB==1) ? 2'h2 : 2'h1; + // FPnew needs addition operands as operand B and C + if (SHARED_FP!=1) begin + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + end + end + // fsub.fmt - FP Subtraction + 5'b00001: begin + fpu_op = fpnew_pkg::ADD; + fpu_op_mod = 1'b1; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_ADDSUB; + apu_op_o = 2'b1; + apu_lat_o = (PIPE_REG_ADDSUB==1) ? 2'h2 : 2'h1; + if (SHARED_FP!=1) begin + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + end + end + // fmul.fmt - FP Multiplication + 5'b00010: begin + fpu_op = fpnew_pkg::MUL; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MULT; + apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; + end + // fdiv.fmt - FP Division + 5'b00011: begin + if (FP_DIVSQRT) begin + fpu_op = fpnew_pkg::DIV; + fp_op_group = DIVSQRT; + apu_type_o = APUTYPE_DIV; + apu_lat_o = 2'h3; + end else + illegal_insn_o = 1'b1; + end + // fsqrt.fmt - FP Square Root + 5'b01011: begin + if (FP_DIVSQRT) begin + regb_used_o = 1'b0; + fpu_op = fpnew_pkg::SQRT; + fp_op_group = DIVSQRT; + apu_type_o = APUTYPE_SQRT; + apu_op_o = 1'b1; + apu_lat_o = 2'h3; + // rs2 must be zero + if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; + end else + illegal_insn_o = 1'b1; + end + // fsgn{j[n]/jx}.fmt - FP Sign Injection + 5'b00100: begin + // old FPU needs ALU + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + case (instr_rdata_i[14:12]) + //fsgnj.s + 3'h0: alu_operator_o = ALU_FSGNJ; + //fsgnjn.s + 3'h1: alu_operator_o = ALU_FSGNJN; + //fsgnjx.s + 3'h2: alu_operator_o = ALU_FSGNJX; + // illegal instruction + default: illegal_insn_o = 1'b1; + endcase + // FPnew supports SGNJ + end else begin + fpu_op = fpnew_pkg::SGNJ; + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm, do the check here + if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010], [3'b100:3'b110]})) begin + illegal_insn_o = 1'b1; + end + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end else begin + fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; + end + end else begin + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010]})) illegal_insn_o = 1'b1; + end + end + end + // fmin/fmax.fmt - FP Minimum / Maximum + 5'b00101: begin + // old FPU needs ALU + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + case (instr_rdata_i[14:12]) + //fmin.s + 3'h0: alu_operator_o = ALU_FMIN; + //fmax.s + 3'h1: alu_operator_o = ALU_FMAX; + default: illegal_insn_o = 1'b1; + endcase + // FPnew supports MIN-MAX + end else begin + fpu_op = fpnew_pkg::MINMAX; + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm, do the check here + if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b001], [3'b100:3'b101]})) begin + illegal_insn_o = 1'b1; + end + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end else begin + fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; + end + end else begin + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b001]})) illegal_insn_o = 1'b1; + end + end + end + // fcvt.fmt.fmt - FP to FP Conversion + 5'b01000: begin + // old FPU has hacky fcvt.s.d + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + regb_used_o = 1'b0; + alu_operator_o = ALU_FKEEP; + // FPnew does proper casts + end else begin + regb_used_o = 1'b0; + fpu_op = fpnew_pkg::F2F; + fp_op_group = CONV; + apu_type_o = APUTYPE_CAST; + // bits [22:20] used, other bits must be 0 + if (instr_rdata_i[24:23]) illegal_insn_o = 1'b1; + // check source format + unique case (instr_rdata_i[22:20]) + // Only process instruction if corresponding extension is active (static) + 3'b000: begin + if (~C_RVF) illegal_insn_o = 1'b1; + fpu_src_fmt_o = fpnew_pkg::FP32; + end + 3'b001: begin + if (~C_RVD) illegal_insn_o = 1'b1; + fpu_src_fmt_o = fpnew_pkg::FP64; + end + 3'b010: begin + if (~C_XF16) illegal_insn_o = 1'b1; + fpu_src_fmt_o = fpnew_pkg::FP16; + end + 3'b110: begin + if (~C_XF16ALT) illegal_insn_o = 1'b1; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end + 3'b011: begin + if (~C_XF8) illegal_insn_o = 1'b1; + fpu_src_fmt_o = fpnew_pkg::FP8; + end + default: illegal_insn_o = 1'b1; + endcase + end + end + // fmulex.s.fmt - FP Expanding Multiplication to FP32 + 5'b01001: begin + fpu_op = fpnew_pkg::MUL; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MULT; + apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; + // set dst format to FP32 + fpu_dst_fmt_o = fpnew_pkg::FP32; + end + // fmacex.s.fmt - FP Expanding Multipy-Accumulate to FP32 + 5'b01010: begin + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; // third operand is rd + reg_fp_c_o = 1'b1; + fpu_op = fpnew_pkg::FMADD; + fp_op_group = ADDMUL; + apu_type_o = APUTYPE_MAC; + apu_lat_o = (PIPE_REG_MULT==1) ? 2'h2 : 2'h1; + // set dst format to FP32 + fpu_dst_fmt_o = fpnew_pkg::FP32; + end + // feq/flt/fle.fmt - FP Comparisons + 5'b10100: begin + // old FPU needs ALU + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + reg_fp_d_o = 1'b0; + case (instr_rdata_i[14:12]) + //fle.s + 3'h0: alu_operator_o = ALU_FLE; + //flt.s + 3'h1: alu_operator_o = ALU_FLT; + //feq.s + 3'h2: alu_operator_o = ALU_FEQ; + default: illegal_insn_o = 1'b1; + endcase + // FPnew supports comparisons + end else begin + fpu_op = fpnew_pkg::CMP; + fp_op_group = NONCOMP; + reg_fp_d_o = 1'b0; // go to integer regfile + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm, do the check here + if (C_XF16ALT) begin // FP16ALT instructions encoded in rm separately (static) + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010], [3'b100:3'b110]})) begin + illegal_insn_o = 1'b1; + end + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end else begin + fp_rnd_mode_o = {1'b0, instr_rdata_i[13:12]}; + end + end else begin + if (!(instr_rdata_i[14:12] inside {[3'b000:3'b010]})) illegal_insn_o = 1'b1; + end + end + end + // fcvt.ifmt.fmt - FP to Int Conversion + 5'b11000: begin + regb_used_o = 1'b0; + reg_fp_d_o = 1'b0; // go to integer regfile + fpu_op = fpnew_pkg::F2I; + fp_op_group = CONV; + fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch + apu_type_o = APUTYPE_CAST; + apu_op_o = 2'b1; + apu_lat_o = (PIPE_REG_CAST==1) ? 2'h2 : 2'h1; + + unique case (instr_rdata_i[26:25]) //fix for casting to different formats other than FP32 + 2'b00: begin + if (~C_RVF) illegal_insn_o = 1; + else fpu_src_fmt_o = fpnew_pkg::FP32; + end + 2'b01: begin + if (~C_RVD) illegal_insn_o = 1; + else fpu_src_fmt_o = fpnew_pkg::FP64; + end + 2'b10: begin + if (instr_rdata_i[14:12] == 3'b101) begin + if (~C_XF16ALT) illegal_insn_o = 1; + else fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end else if (~C_XF16) begin + illegal_insn_o = 1; + end else begin + fpu_src_fmt_o = fpnew_pkg::FP16; + end + end + 2'b11: begin + if (~C_XF8) illegal_insn_o = 1; + else fpu_src_fmt_o = fpnew_pkg::FP8; + end + endcase // unique case (instr_rdata_i[26:25]) + // bits [21:20] used, other bits must be 0 + if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. + end + // fcvt.fmt.ifmt - Int to FP Conversion + 5'b11010: begin + regb_used_o = 1'b0; + reg_fp_a_o = 1'b0; // go from integer regfile + fpu_op = fpnew_pkg::I2F; + fp_op_group = CONV; + fpu_op_mod = instr_rdata_i[20]; // signed/unsigned switch + apu_type_o = APUTYPE_CAST; + apu_op_o = 2'b0; + apu_lat_o = (PIPE_REG_CAST==1) ? 2'h2 : 2'h1; + // bits [21:20] used, other bits must be 0 + if (instr_rdata_i[24:21]) illegal_insn_o = 1'b1; // in RV32, no casts to L allowed. + end + // move and class + 5'b11100: begin + // old fpu maps this to ALU ops + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + case (instr_rdata_i[14:12]) + // fmv.x.s - move from floating point to gp register + 3'b000: begin + reg_fp_d_o = 1'b0; // go to integer regfile + alu_operator_o = ALU_ADD; + end + // fclass - classify float + 3'b001: begin + regb_used_o = 1'b0; + reg_fp_d_o = 1'b0; // go to integer regfile + alu_operator_o = ALU_FCLASS; + end + default: illegal_insn_o = 1'b1; + endcase + // FPnew does proper NaN-Boxing + end else begin + regb_used_o = 1'b0; + reg_fp_d_o = 1'b0; // go to integer regfile + fp_op_group = NONCOMP; + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm, do the check here + // fmv.x.fmt - FPR to GPR Move + if (instr_rdata_i[14:12] == 3'b000 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b100)) begin + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit + fpu_op = fpnew_pkg::SGNJ; // mapped to SGNJ-passthrough since no recoding + fpu_op_mod = 1'b1; // sign-extend result + fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end + // fclass.fmt - FP Classify + end else if (instr_rdata_i[14:12] == 3'b001 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b101)) begin + fpu_op = fpnew_pkg::CLASSIFY; + fp_rnd_mode_o = 3'b000; + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end + end else begin + illegal_insn_o = 1'b1; + end + // rs2 must be zero + if (instr_rdata_i[24:20]) illegal_insn_o = 1'b1; + end + end + // fmv.fmt.x - GPR to FPR Move + 5'b11110: begin + // old fpu maps this to ALU ops + if (SHARED_FP==1) begin + apu_en = 1'b0; + alu_en_o = 1'b1; + regfile_alu_we = 1'b1; + reg_fp_a_o = 1'b0; // go from integer regfile + alu_operator_o = ALU_ADD; + // FPnew does proper NaN-Boxing + end else begin + regb_used_o = 1'b0; + reg_fp_a_o = 1'b0; // go from integer regfile + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; // set rs2 = rs1 so we can map FMV to SGNJ in the unit + fpu_op = fpnew_pkg::SGNJ; // mapped to SGNJ-passthrough since no recoding + fpu_op_mod = 1'b0; // nan-box result + fp_op_group = NONCOMP; + fp_rnd_mode_o = 3'b011; // passthrough without checking nan-box + apu_type_o = APUTYPE_FP; // doesn't matter much as long as it's not div + check_fprm = 1'b0; // instruction encoded in rm, do the check here + if (instr_rdata_i[14:12] == 3'b000 || (C_XF16ALT && instr_rdata_i[14:12] == 3'b100)) begin + // FP16ALT uses special encoding here + if (instr_rdata_i[14]) begin + fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + fpu_src_fmt_o = fpnew_pkg::FP16ALT; + end + end else begin + illegal_insn_o = 1'b1; + end + // rs2 must be zero + if (instr_rdata_i[24:20] != 5'b00000) illegal_insn_o = 1'b1; + end + end + // Rest are illegal instructions + default: begin + illegal_insn_o = 1'b1; + end + endcase + + // check enabled formats (static) + if (~C_RVF && fpu_dst_fmt_o == fpnew_pkg::FP32) illegal_insn_o = 1'b1; + if ((~C_RVD || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP64) illegal_insn_o = 1'b1; + if ((~C_XF16 || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP16) illegal_insn_o = 1'b1; + if ((~C_XF16ALT || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP16ALT) begin + illegal_insn_o = 1'b1; + end + if ((~C_XF8 || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP8) illegal_insn_o = 1'b1; + + // check rounding mode + if (check_fprm) begin + unique case (instr_rdata_i[14:12]) inside + [3'b000:3'b100]: ; //legal rounding modes + 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 + if (~C_XF16ALT || fpu_dst_fmt_o != fpnew_pkg::FP16ALT) illegal_insn_o = 1'b1; + // actual rounding mode from frm csr + unique case (frm_i) inside + [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; + endcase + end + 3'b111: begin + // rounding mode from frm csr + unique case (frm_i) inside + [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; + endcase + end + default : illegal_insn_o = 1'b1; + endcase + end + + // Set latencies for FPnew from config. The C_LAT constants contain the number + // of pipeline registers. the APU takes the following values: + // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages + if (SHARED_FP!=1) begin + case (fp_op_group) + // ADDMUL has format dependent latency + ADDMUL : begin + unique case (fpu_dst_fmt_o) + fpnew_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; + fpnew_pkg::FP64 : apu_lat_o = (C_LAT_FP64<2) ? C_LAT_FP64+1 : 2'h3; + fpnew_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; + fpnew_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; + fpnew_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; + default : ; + endcase + end + // DIVSQRT is iterative and takes more than 2 cycles + DIVSQRT : apu_lat_o = 2'h3; + // NONCOMP uses the same latency for all formats + NONCOMP : apu_lat_o = (C_LAT_NONCOMP<2) ? C_LAT_NONCOMP+1 : 2'h3; + // CONV uses the same latency for all formats + CONV : apu_lat_o = (C_LAT_CONV<2) ? C_LAT_CONV+1 : 2'h3; + endcase + end + + // Set FPnew OP and OPMOD as the APU op + if (SHARED_FP!=1) apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; + + end + // FPU!=1 + else + illegal_insn_o = 1'b1; + end + + // floating point fused arithmetic + OPCODE_OP_FMADD, + OPCODE_OP_FMSUB, + OPCODE_OP_FNMSUB, + OPCODE_OP_FNMADD : begin + if (FPU==1) begin + // using APU instead of ALU + apu_en = 1'b1; + alu_en_o = 1'b0; + // Private and new shared FP use FPnew + apu_flags_src_o = (SHARED_FP==1) ? APU_FLAGS_FP : APU_FLAGS_FPNEW; + apu_type_o = APUTYPE_MAC; + apu_lat_o = (PIPE_REG_MAC>1) ? 2'h3 : 2'h2; + // all registers are FP registers and use three + rega_used_o = 1'b1; + regb_used_o = 1'b1; + regc_used_o = 1'b1; + regc_mux_o = REGC_S4; + reg_fp_a_o = 1'b1; + reg_fp_b_o = 1'b1; + reg_fp_c_o = 1'b1; + reg_fp_d_o = 1'b1; + fp_rnd_mode_o = instr_rdata_i[14:12]; + + // Decode Formats + unique case (instr_rdata_i[26:25]) + // FP32 + 2'b00 : fpu_dst_fmt_o = fpnew_pkg::FP32; + // FP64 + 2'b01 : fpu_dst_fmt_o = fpnew_pkg::FP64; + // FP16 or FP16ALT + 2'b10 : begin + // FP16alt encoded in rm field + if (instr_rdata_i[14:12]==3'b101) fpu_dst_fmt_o = fpnew_pkg::FP16ALT; + else fpu_dst_fmt_o = fpnew_pkg::FP16; + end + // FP8 + 2'b11 : fpu_dst_fmt_o = fpnew_pkg::FP8; + endcase + + // By default, src=dst + fpu_src_fmt_o = fpu_dst_fmt_o; + + // decode FP intstruction + unique case (instr_rdata_i[6:0]) + // fmadd.fmt - FP Fused multiply-add + OPCODE_OP_FMADD : begin + fpu_op = fpnew_pkg::FMADD; + apu_op_o = 2'b00; + end + // fmsub.fmt - FP Fused multiply-subtract + OPCODE_OP_FMSUB : begin + fpu_op = fpnew_pkg::FMADD; + fpu_op_mod = 1'b1; + apu_op_o = 2'b01; + end + // fnmsub.fmt - FP Negated fused multiply-subtract + OPCODE_OP_FNMSUB : begin + fpu_op = fpnew_pkg::FNMSUB; + apu_op_o = 2'b10; + end + // fnmadd.fmt - FP Negated fused multiply-add + OPCODE_OP_FNMADD : begin + fpu_op = fpnew_pkg::FNMSUB; + fpu_op_mod = 1'b1; + apu_op_o = 2'b11; + end + endcase + + // check enabled formats (static) + if (~C_RVF && fpu_dst_fmt_o == fpnew_pkg::FP32) illegal_insn_o = 1'b1; + if ((~C_RVD || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP64) illegal_insn_o = 1'b1; + if ((~C_XF16 || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP16) illegal_insn_o = 1'b1; + if ((~C_XF16ALT || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP16ALT) begin + illegal_insn_o = 1'b1; + end + if ((~C_XF8 || SHARED_FP==1) && fpu_dst_fmt_o == fpnew_pkg::FP8) illegal_insn_o = 1'b1; + + // check rounding mode + unique case (instr_rdata_i[14:12]) inside + [3'b000:3'b100]: ; //legal rounding modes + 3'b101: begin // Alternative Half-Precsision encded as fmt=10 and rm=101 + if (~C_XF16ALT || fpu_dst_fmt_o != fpnew_pkg::FP16ALT) illegal_insn_o = 1'b1; + // actual rounding mode from frm csr + unique case (frm_i) inside + [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; + endcase + end + 3'b111: begin + // rounding mode from frm csr + unique case (frm_i) inside + [3'b000:3'b100] : fp_rnd_mode_o = frm_i; //legal rounding modes + default : illegal_insn_o = 1'b1; + endcase + end + default : illegal_insn_o = 1'b1; + endcase + + // Set latencies for FPnew from config. The C_LAT constants contain the number + // of pipeline registers. the APU takes the following values: + // 1 = single cycle (no latency), 2 = one pipestage, 3 = two or more pipestages + if (SHARED_FP!=1) begin + // format dependent latency + unique case (fpu_dst_fmt_o) + fpnew_pkg::FP32 : apu_lat_o = (C_LAT_FP32<2) ? C_LAT_FP32+1 : 2'h3; + fpnew_pkg::FP64 : apu_lat_o = (C_LAT_FP64<2) ? C_LAT_FP64+1 : 2'h3; + fpnew_pkg::FP16 : apu_lat_o = (C_LAT_FP16<2) ? C_LAT_FP16+1 : 2'h3; + fpnew_pkg::FP16ALT : apu_lat_o = (C_LAT_FP16ALT<2) ? C_LAT_FP16ALT+1 : 2'h3; + fpnew_pkg::FP8 : apu_lat_o = (C_LAT_FP8<2) ? C_LAT_FP8+1 : 2'h3; + default : ; + endcase + end + + // Set FPnew OP and OPMOD as the APU op + if (SHARED_FP!=1) apu_op_o = {fpu_vec_op, fpu_op_mod, fpu_op}; + end + // FPU!=1 + else begin + illegal_insn_o = 1'b1; + end + end + + OPCODE_STORE_FP: begin + if (FPU==1) begin + data_req = 1'b1; + data_we_o = 1'b1; + rega_used_o = 1'b1; + regb_used_o = 1'b1; + alu_operator_o = ALU_ADD; + reg_fp_b_o = 1'b1; + instr_multicycle_o = 1'b1; + + // offset from immediate + imm_b_mux_sel_o = IMMB_S; + alu_op_b_mux_sel_o = OP_B_IMM; + + // pass write data through ALU operand c + alu_op_c_mux_sel_o = OP_C_REGB_OR_FWD; + + // Decode data type + unique case (instr_rdata_i[14:12]) + // fsb - FP8 store + 3'b000 : if (C_XF8) data_type_o = 2'b10; + else illegal_insn_o = 1'b1; + // fsh - FP16 store + 3'b001 : if (C_XF16 | C_XF16ALT) data_type_o = 2'b01; + else illegal_insn_o = 1'b1; + // fsw - FP32 store + 3'b010 : if (C_RVF) data_type_o = 2'b00; + else illegal_insn_o = 1'b1; + // fsd - FP64 store + 3'b011 : if (C_RVD) data_type_o = 2'b00; // 64bit stores unsupported! + else illegal_insn_o = 1'b1; + default: illegal_insn_o = 1'b1; + endcase + + // sanitize memory bus signals for illegal instr (not sure if needed??) + if (illegal_insn_o) begin + data_req = 1'b0; + data_we_o = 1'b0; + end + end + // FPU!=1 + else + illegal_insn_o = 1'b1; + end + + OPCODE_LOAD_FP: begin + if (FPU==1) begin + data_req = 1'b1; + regfile_mem_we = 1'b1; + reg_fp_d_o = 1'b1; + rega_used_o = 1'b1; + alu_operator_o = ALU_ADD; + instr_multicycle_o = 1'b1; + + // offset from immediate + imm_b_mux_sel_o = IMMB_I; + alu_op_b_mux_sel_o = OP_B_IMM; + + // NaN boxing + data_sign_extension_o = 2'b10; + + // Decode data type + unique case (instr_rdata_i[14:12]) + // flb - FP8 load + 3'b000 : if (C_XF8) data_type_o = 2'b10; + else illegal_insn_o = 1'b1; + // flh - FP16 load + 3'b001 : if (C_XF16 | C_XF16ALT) data_type_o = 2'b01; + else illegal_insn_o = 1'b1; + // flw - FP32 load + 3'b010 : if (C_RVF) data_type_o = 2'b00; + else illegal_insn_o = 1'b1; + // fld - FP64 load + 3'b011 : if (C_RVD) data_type_o = 2'b00; // 64bit loads unsupported! + else illegal_insn_o = 1'b1; + default: illegal_insn_o = 1'b1; + endcase + end + // FPU!=1 + else + illegal_insn_o = 1'b1; + end + + OPCODE_PULP_OP: begin // PULP specific ALU instructions with three source operands + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + regb_used_o = 1'b1; + + case (instr_rdata_i[13:12]) + 2'b00: begin // multiply with subword selection + alu_en_o = 1'b0; + + mult_sel_subword_o = instr_rdata_i[30]; + mult_signed_mode_o = {2{instr_rdata_i[31]}}; + + mult_imm_mux_o = MIMM_S3; + regc_mux_o = REGC_ZERO; + mult_int_en = 1'b1; + + if (instr_rdata_i[14]) + mult_operator_o = MUL_IR; + else + mult_operator_o = MUL_I; + + `USE_APU_INT_MULT + end + + 2'b01: begin // MAC with subword selection + alu_en_o = 1'b0; + + mult_sel_subword_o = instr_rdata_i[30]; + mult_signed_mode_o = {2{instr_rdata_i[31]}}; + + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + mult_imm_mux_o = MIMM_S3; + mult_int_en = 1'b1; + + if (instr_rdata_i[14]) + mult_operator_o = MUL_IR; + else + mult_operator_o = MUL_I; + + `USE_APU_INT_MULT + end + + 2'b10: begin // add with normalization and rounding + // decide between using unsigned and rounding, and combinations + // thereof + case ({instr_rdata_i[31],instr_rdata_i[14]}) + 2'b00: alu_operator_o = ALU_ADD; + 2'b01: alu_operator_o = ALU_ADDR; + 2'b10: alu_operator_o = ALU_ADDU; + 2'b11: alu_operator_o = ALU_ADDUR; + endcase + + bmask_a_mux_o = BMASK_A_ZERO; + bmask_b_mux_o = BMASK_B_S3; + + if (instr_rdata_i[30]) begin + //register variant + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + end + + end + + 2'b11: begin // sub with normalization and rounding + // decide between using unsigned and rounding, and combinations + // thereof + case ({instr_rdata_i[31],instr_rdata_i[14]}) + 2'b00: alu_operator_o = ALU_SUB; + 2'b01: alu_operator_o = ALU_SUBR; + 2'b10: alu_operator_o = ALU_SUBU; + 2'b11: alu_operator_o = ALU_SUBUR; + endcase + + bmask_a_mux_o = BMASK_A_ZERO; + bmask_b_mux_o = BMASK_B_S3; + + if (instr_rdata_i[30]) begin + //register variant + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + end + + end + endcase + end + + OPCODE_VECOP: begin + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + imm_b_mux_sel_o = IMMB_VS; + + // vector size + if (instr_rdata_i[12]) begin + alu_vec_mode_o = VEC_MODE8; + mult_operator_o = MUL_DOT8; + end else begin + alu_vec_mode_o = VEC_MODE16; + mult_operator_o = MUL_DOT16; + end + + // distinguish normal vector, sc and sci modes + if (instr_rdata_i[14]) begin + scalar_replication_o = 1'b1; + + if (instr_rdata_i[13]) begin + // immediate scalar replication, .sci + alu_op_b_mux_sel_o = OP_B_IMM; + end else begin + // register scalar replication, .sc + regb_used_o = 1'b1; + end + end else begin + // normal register use + regb_used_o = 1'b1; + end + + // now decode the instruction + unique case (instr_rdata_i[31:26]) + 6'b00000_0: begin alu_operator_o = ALU_ADD; imm_b_mux_sel_o = IMMB_VS; end // pv.add + 6'b00001_0: begin alu_operator_o = ALU_SUB; imm_b_mux_sel_o = IMMB_VS; end // pv.sub + 6'b00010_0: begin alu_operator_o = ALU_ADD; imm_b_mux_sel_o = IMMB_VS; bmask_b_mux_o = BMASK_B_ONE; end // pv.avg + 6'b00011_0: begin alu_operator_o = ALU_ADDU; imm_b_mux_sel_o = IMMB_VU; bmask_b_mux_o = BMASK_B_ONE; end // pv.avgu + 6'b00100_0: begin alu_operator_o = ALU_MIN; imm_b_mux_sel_o = IMMB_VS; end // pv.min + 6'b00101_0: begin alu_operator_o = ALU_MINU; imm_b_mux_sel_o = IMMB_VU; end // pv.minu + 6'b00110_0: begin alu_operator_o = ALU_MAX; imm_b_mux_sel_o = IMMB_VS; end // pv.max + 6'b00111_0: begin alu_operator_o = ALU_MAXU; imm_b_mux_sel_o = IMMB_VU; end // pv.maxu + 6'b01000_0: begin alu_operator_o = ALU_SRL; imm_b_mux_sel_o = IMMB_VS; end // pv.srl + 6'b01001_0: begin alu_operator_o = ALU_SRA; imm_b_mux_sel_o = IMMB_VS; end // pv.sra + 6'b01010_0: begin alu_operator_o = ALU_SLL; imm_b_mux_sel_o = IMMB_VS; end // pv.sll + 6'b01011_0: begin alu_operator_o = ALU_OR; imm_b_mux_sel_o = IMMB_VS; end // pv.or + 6'b01100_0: begin alu_operator_o = ALU_XOR; imm_b_mux_sel_o = IMMB_VS; end // pv.xor + 6'b01101_0: begin alu_operator_o = ALU_AND; imm_b_mux_sel_o = IMMB_VS; end // pv.and + 6'b01110_0: begin alu_operator_o = ALU_ABS; imm_b_mux_sel_o = IMMB_VS; end // pv.abs + + // shuffle/pack + 6'b11101_0, // pv.shuffleI1 + 6'b11110_0, // pv.shuffleI2 + 6'b11111_0, // pv.shuffleI3 + 6'b11000_0: begin // pv.shuffle, pv.shuffleI0 + alu_operator_o = ALU_SHUF; + imm_b_mux_sel_o = IMMB_SHUF; + regb_used_o = 1'b1; + scalar_replication_o = 1'b0; + end + 6'b11001_0: begin // pv.shuffle2 + alu_operator_o = ALU_SHUF2; + regb_used_o = 1'b1; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + scalar_replication_o = 1'b0; + end + 6'b11010_0: begin // pv.pack + alu_operator_o = instr_rdata_i[25] ? ALU_PCKHI : ALU_PCKLO; + regb_used_o = 1'b1; + end + 6'b11011_0: begin // pv.packhi + alu_operator_o = ALU_PCKHI; + regb_used_o = 1'b1; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + end + 6'b11100_0: begin // pv.packlo + alu_operator_o = ALU_PCKLO; + regb_used_o = 1'b1; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + end + + 6'b01111_0: begin // pv.extract + alu_operator_o = ALU_EXTS; + end + + 6'b10010_0: begin // pv.extractu + alu_operator_o = ALU_EXT; + end + + 6'b10110_0: begin // pv.insert + alu_operator_o = ALU_INS; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; + end + + 6'b10000_0: begin // pv.dotup + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b00; + imm_b_mux_sel_o = IMMB_VU; + `USE_APU_DSP_MULT + end + 6'b10001_0: begin // pv.dotusp + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b01; + `USE_APU_DSP_MULT + end + 6'b10011_0: begin // pv.dotsp + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b11; + `USE_APU_DSP_MULT + end + 6'b10100_0: begin // pv.sdotup + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b00; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + imm_b_mux_sel_o = IMMB_VU; + `USE_APU_DSP_MULT + end + 6'b10101_0: begin // pv.sdotusp + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b01; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + `USE_APU_DSP_MULT + end + 6'b10111_0: begin // pv.sdotsp + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b11; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + `USE_APU_DSP_MULT + end + + /* COMPLEX INSTRUCTIONS */ + + 6'b01010_1: begin // pc.clpxmul.h.{r,i}.{/,div2,div4,div8} + alu_en_o = 1'b0; + mult_dot_en = 1'b1; + mult_dot_signed_o = 2'b11; + is_clpx_o = 1'b1; + regc_used_o = 1'b1; + regc_mux_o = REGC_RD; + scalar_replication_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + regb_used_o = 1'b1; + `USE_APU_DSP_MULT + end + + 6'b01101_1: begin // pv.subrotmj.h.{/,div2,div4,div8} + alu_operator_o = ALU_SUB; + is_clpx_o = 1'b1; + scalar_replication_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + regb_used_o = 1'b1; + is_subrot_o = 1'b1; + end + + 6'b01011_1: begin // pv.cplxconj.h + alu_operator_o = ALU_ABS; + is_clpx_o = 1'b1; + scalar_replication_o = 1'b0; + regb_used_o = 1'b0; + end + + 6'b01110_1: begin // pv.add.h.{div2,div4,div8} + alu_operator_o = ALU_ADD; + is_clpx_o = 1'b1; + scalar_replication_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + regb_used_o = 1'b1; + end + + 6'b01100_1: begin // pv.sub.h.{div2,div4,div8} + alu_operator_o = ALU_SUB; + is_clpx_o = 1'b1; + scalar_replication_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + regb_used_o = 1'b1; + end + + // comparisons, always have bit 26 set + 6'b00000_1: begin alu_operator_o = ALU_EQ; imm_b_mux_sel_o = IMMB_VS; end // pv.cmpeq + 6'b00001_1: begin alu_operator_o = ALU_NE; imm_b_mux_sel_o = IMMB_VS; end // pv.cmpne + 6'b00010_1: begin alu_operator_o = ALU_GTS; imm_b_mux_sel_o = IMMB_VS; end // pv.cmpgt + 6'b00011_1: begin alu_operator_o = ALU_GES; imm_b_mux_sel_o = IMMB_VS; end // pv.cmpge + 6'b00100_1: begin alu_operator_o = ALU_LTS; imm_b_mux_sel_o = IMMB_VS; end // pv.cmplt + 6'b00101_1: begin alu_operator_o = ALU_LES; imm_b_mux_sel_o = IMMB_VS; end // pv.cmple + 6'b00110_1: begin alu_operator_o = ALU_GTU; imm_b_mux_sel_o = IMMB_VU; end // pv.cmpgtu + 6'b00111_1: begin alu_operator_o = ALU_GEU; imm_b_mux_sel_o = IMMB_VU; end // pv.cmpgeu + 6'b01000_1: begin alu_operator_o = ALU_LTU; imm_b_mux_sel_o = IMMB_VU; end // pv.cmpltu + 6'b01001_1: begin alu_operator_o = ALU_LEU; imm_b_mux_sel_o = IMMB_VU; end // pv.cmpleu + + default: illegal_insn_o = 1'b1; + endcase + end + + + //////////////////////////////////////////////// + // ____ ____ _____ ____ ___ _ _ // + // / ___|| _ \| ____/ ___|_ _| / \ | | // + // \___ \| |_) | _|| | | | / _ \ | | // + // ___) | __/| |__| |___ | | / ___ \| |___ // + // |____/|_| |_____\____|___/_/ \_\_____| // + // // + //////////////////////////////////////////////// + + OPCODE_FENCE: begin + unique case (instr_rdata_i[14:12]) + 3'b000: begin // FENCE (FENCE.I instead, a bit more conservative) + // flush pipeline + fencei_insn_o = 1'b1; + end + + 3'b001: begin // FENCE.I + // flush prefetch buffer, flush pipeline + fencei_insn_o = 1'b1; + end + + default: begin + illegal_insn_o = 1'b1; + end + endcase + end + + OPCODE_SYSTEM: begin + if (instr_rdata_i[14:12] == 3'b000) + begin + // non CSR related SYSTEM instructions + if ( {instr_rdata_i[19:15], instr_rdata_i[11:7]} == '0) + begin + unique case (instr_rdata_i[31:20]) + 12'h000: // ECALL + begin + // environment (system) call + ecall_insn_o = 1'b1; + end + + 12'h001: // ebreak + begin + // debugger trap + ebrk_insn_o = 1'b1; + end + + 12'h302: // mret + begin + illegal_insn_o = (PULP_SECURE) ? current_priv_lvl_i != PRIV_LVL_M : 1'b0; + mret_insn_o = ~illegal_insn_o; + mret_dec_o = 1'b1; + end + + 12'h002: // uret + begin + uret_insn_o = (PULP_SECURE) ? 1'b1 : 1'b0; + uret_dec_o = 1'b1; + end + + 12'h7b2: // dret + begin + illegal_insn_o = !debug_mode_i; + dret_insn_o = debug_mode_i; + dret_dec_o = 1'b1; + end + + 12'h105: // wfi + begin + // flush pipeline + pipe_flush_o = 1'b1; + end + + default: + begin + illegal_insn_o = 1'b1; + end + endcase + end else illegal_insn_o = 1'b1; + end + else + begin + // instruction to read/modify CSR + csr_access_o = 1'b1; + regfile_alu_we = 1'b1; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_a_mux_sel_o = IMMA_Z; + imm_b_mux_sel_o = IMMB_I; // CSR address is encoded in I imm + instr_multicycle_o = 1'b1; + + if (instr_rdata_i[14] == 1'b1) begin + // rs1 field is used as immediate + alu_op_a_mux_sel_o = OP_A_IMM; + end else begin + rega_used_o = 1'b1; + alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; + end + + // instr_rdata_i[19:14] = rs or immediate value + // if set or clear with rs==x0 or imm==0, + // then do not perform a write action + unique case (instr_rdata_i[13:12]) + 2'b01: csr_op = CSR_OP_WRITE; + 2'b10: csr_op = instr_rdata_i[19:15] == 5'b0 ? CSR_OP_READ : CSR_OP_SET; + 2'b11: csr_op = instr_rdata_i[19:15] == 5'b0 ? CSR_OP_READ : CSR_OP_CLEAR; + default: csr_illegal = 1'b1; + endcase + + if (instr_rdata_i[29:28] > current_priv_lvl_i) begin + // No access to higher privilege CSR + csr_illegal = 1'b1; + end + + // Determine if CSR access is illegal + casex(instr_rdata_i[31:20]) + // Floating point + CSR_FFLAGS, + CSR_FRM, + CSR_FCSR, + FPREC : + if(!FPU) csr_illegal = 1'b1; + + // Writes to read only CSRs results in illegal instruction + CSR_MVENDORID, + CSR_MARCHID, + CSR_MIMPID, + CSR_MHARTID : + if(csr_op != CSR_OP_READ) csr_illegal = 1'b1; + + // These are valid CSR registers + CSR_MSTATUS, + CSR_MISA, + CSR_MIE, + CSR_MIE1, + CSR_MTVEC, + CSR_MSCRATCH, + CSR_MEPC, + CSR_MCAUSE, + CSR_MTVAL, + CSR_MIP, + CSR_MIP1, + CSR_MVENDORID, + CSR_MARCHID, + CSR_MIMPID, + CSR_MHARTID, + CSR_MCOUNTEREN, + + UHARTID, + PRIVLV, + + // Hardware Performance Monitor + CSR_MCYCLE, + CSR_MINSTRET, + CSR_MHPMCOUNTER3, + CSR_MHPMCOUNTER4, CSR_MHPMCOUNTER5, CSR_MHPMCOUNTER6, CSR_MHPMCOUNTER7, + CSR_MHPMCOUNTER8, CSR_MHPMCOUNTER9, CSR_MHPMCOUNTER10, CSR_MHPMCOUNTER11, + CSR_MHPMCOUNTER12, CSR_MHPMCOUNTER13, CSR_MHPMCOUNTER14, CSR_MHPMCOUNTER15, + CSR_MHPMCOUNTER16, CSR_MHPMCOUNTER17, CSR_MHPMCOUNTER18, CSR_MHPMCOUNTER19, + CSR_MHPMCOUNTER20, CSR_MHPMCOUNTER21, CSR_MHPMCOUNTER22, CSR_MHPMCOUNTER23, + CSR_MHPMCOUNTER24, CSR_MHPMCOUNTER25, CSR_MHPMCOUNTER26, CSR_MHPMCOUNTER27, + CSR_MHPMCOUNTER28, CSR_MHPMCOUNTER29, CSR_MHPMCOUNTER30, CSR_MHPMCOUNTER31, + CSR_MCYCLEH, + CSR_MINSTRETH, + CSR_MHPMCOUNTER3H, + CSR_MHPMCOUNTER4H, CSR_MHPMCOUNTER5H, CSR_MHPMCOUNTER6H, CSR_MHPMCOUNTER7H, + CSR_MHPMCOUNTER8H, CSR_MHPMCOUNTER9H, CSR_MHPMCOUNTER10H, CSR_MHPMCOUNTER11H, + CSR_MHPMCOUNTER12H, CSR_MHPMCOUNTER13H, CSR_MHPMCOUNTER14H, CSR_MHPMCOUNTER15H, + CSR_MHPMCOUNTER16H, CSR_MHPMCOUNTER17H, CSR_MHPMCOUNTER18H, CSR_MHPMCOUNTER19H, + CSR_MHPMCOUNTER20H, CSR_MHPMCOUNTER21H, CSR_MHPMCOUNTER22H, CSR_MHPMCOUNTER23H, + CSR_MHPMCOUNTER24H, CSR_MHPMCOUNTER25H, CSR_MHPMCOUNTER26H, CSR_MHPMCOUNTER27H, + CSR_MHPMCOUNTER28H, CSR_MHPMCOUNTER29H, CSR_MHPMCOUNTER30H, CSR_MHPMCOUNTER31H, + CSR_MCOUNTINHIBIT, + CSR_MHPMEVENT3, + CSR_MHPMEVENT4, CSR_MHPMEVENT5, CSR_MHPMEVENT6, CSR_MHPMEVENT7, + CSR_MHPMEVENT8, CSR_MHPMEVENT9, CSR_MHPMEVENT10, CSR_MHPMEVENT11, + CSR_MHPMEVENT12, CSR_MHPMEVENT13, CSR_MHPMEVENT14, CSR_MHPMEVENT15, + CSR_MHPMEVENT16, CSR_MHPMEVENT17, CSR_MHPMEVENT18, CSR_MHPMEVENT19, + CSR_MHPMEVENT20, CSR_MHPMEVENT21, CSR_MHPMEVENT22, CSR_MHPMEVENT23, + CSR_MHPMEVENT24, CSR_MHPMEVENT25, CSR_MHPMEVENT26, CSR_MHPMEVENT27, + CSR_MHPMEVENT28, CSR_MHPMEVENT29, CSR_MHPMEVENT30, CSR_MHPMEVENT31: + ; // do nothing, not illegal + + // Debug register access + CSR_DCSR, + CSR_DPC, + CSR_DSCRATCH0, + CSR_DSCRATCH1 : + if(!debug_mode_i) csr_illegal = 1'b1; + + // Debug Trigger register access + CSR_TSELECT , + CSR_TDATA1 , + CSR_TDATA2 , + CSR_TDATA3 , + CSR_MCONTEXT , + CSR_SCONTEXT : + if(!debug_mode_i || DEBUG_TRIGGER_EN != 1) + csr_illegal = 1'b1; + + // Hardware Loop register access + HWLoop0_START, + HWLoop0_END, + HWLoop0_COUNTER, + HWLoop1_START, + HWLoop1_END, + HWLoop1_COUNTER : + if(!PULP_HWLP) csr_illegal = 1'b1; + + // PMP register access + CSR_PMPCFG_RANGE_X, + CSR_PMPADDR_RANGE_X : + if(!USE_PMP) csr_illegal = 1'b1; + + // User register access + CSR_USTATUS, + CSR_UTVEC, + CSR_UEPC, + CSR_UCAUSE : + if(!PULP_SECURE) csr_illegal = 1'b1; + + default : csr_illegal = 1'b1; + + endcase // casex (instr_rdata_i[31:20]) + + // set csr_status for specific CSR register access: + // Causes controller to enter FLUSH + if(~csr_illegal) + if (instr_rdata_i[31:20] == CSR_MSTATUS || + instr_rdata_i[31:20] == CSR_USTATUS || + instr_rdata_i[31:20] == CSR_UEPC || + // Debug registers + instr_rdata_i[31:20] == CSR_DCSR || + instr_rdata_i[31:20] == CSR_DPC || + instr_rdata_i[31:20] == CSR_DSCRATCH0 || + instr_rdata_i[31:20] == CSR_DSCRATCH1 ) + //access to xstatus + csr_status_o = 1'b1; + + illegal_insn_o = csr_illegal; + + end + + end + + + /////////////////////////////////////////////// + // _ ___ ___ ___ ___ ____ // + // | | | \ \ / / | / _ \ / _ \| _ \ // + // | |_| |\ \ /\ / /| | | | | | | | | |_) | // + // | _ | \ V V / | |__| |_| | |_| | __/ // + // |_| |_| \_/\_/ |_____\___/ \___/|_| // + // // + /////////////////////////////////////////////// + + OPCODE_HWLOOP: begin + if(PULP_HWLP) begin : HWLOOP_FEATURE_ENABLED + hwloop_target_mux_sel_o = 1'b0; + + unique case (instr_rdata_i[14:12]) + 3'b000: begin + // lp.starti: set start address to PC + I-type immediate + hwloop_we[0] = 1'b1; + hwloop_start_mux_sel_o = 1'b0; + end + + 3'b001: begin + // lp.endi: set end address to PC + I-type immediate + hwloop_we[1] = 1'b1; + end + + 3'b010: begin + // lp.count: initialize counter from rs1 + hwloop_we[2] = 1'b1; + hwloop_cnt_mux_sel_o = 1'b1; + rega_used_o = 1'b1; + end + + 3'b011: begin + // lp.counti: initialize counter from I-type immediate + hwloop_we[2] = 1'b1; + hwloop_cnt_mux_sel_o = 1'b0; + end + + 3'b100: begin + // lp.setup: initialize counter from rs1, set start address to + // next instruction and end address to PC + I-type immediate + hwloop_we = 3'b111; + hwloop_start_mux_sel_o = 1'b1; + hwloop_cnt_mux_sel_o = 1'b1; + rega_used_o = 1'b1; + end + + 3'b101: begin + // lp.setupi: initialize counter from immediate, set start address to + // next instruction and end address to PC + I-type immediate + hwloop_we = 3'b111; + hwloop_target_mux_sel_o = 1'b1; + hwloop_start_mux_sel_o = 1'b1; + hwloop_cnt_mux_sel_o = 1'b0; + end + + default: begin + illegal_insn_o = 1'b1; + end + endcase // case (instr_rdata_i[14:12]) + + end else begin // block: HWLOOP_FEATURE_ENABLED + illegal_insn_o = 1'b1; + end + end // case: OPCODE_HWLOOP + + default: begin + illegal_insn_o = 1'b1; + end + endcase + + // make sure invalid compressed instruction causes an exception + if (illegal_c_insn_i) begin + illegal_insn_o = 1'b1; + end + + // misaligned access was detected by the LSU + // TODO: this section should eventually be moved out of the decoder + if (data_misaligned_i == 1'b1) + begin + // only part of the pipeline is unstalled, make sure that the + // correct operands are sent to the AGU + alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_PCINCR; + + // if prepost increments are used, we do not write back the + // second address since the first calculated address was + // the correct one + regfile_alu_we = 1'b0; + + // if post increments are used, we must make sure that for + // the second memory access we do use the adder + prepost_useincr_o = 1'b1; + // we do not want to replicate operand_b + scalar_replication_o = 1'b0; + end else if (mult_multicycle_i) begin + alu_op_c_mux_sel_o = OP_C_REGC_OR_FWD; + end + end + + // deassert we signals (in case of stalls) + assign apu_en_o = (deassert_we_i) ? 1'b0 : apu_en; + assign mult_int_en_o = (deassert_we_i) ? 1'b0 : mult_int_en; + assign mult_dot_en_o = (deassert_we_i) ? 1'b0 : mult_dot_en; + assign regfile_mem_we_o = (deassert_we_i) ? 1'b0 : regfile_mem_we; + assign regfile_alu_we_o = (deassert_we_i) ? 1'b0 : regfile_alu_we; + assign data_req_o = (deassert_we_i) ? 1'b0 : data_req; + assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we; + assign csr_op_o = (deassert_we_i) ? CSR_OP_READ : csr_op; + assign jump_in_id_o = (deassert_we_i) ? BRANCH_NONE : jump_in_id; + + assign jump_in_dec_o = jump_in_id; + assign regfile_alu_we_dec_o = regfile_alu_we; + +endmodule // controller diff --git a/hw/deps/riscv/riscv_ex_stage.sv b/hw/deps/riscv/riscv_ex_stage.sv new file mode 100644 index 0000000..8afd4c8 --- /dev/null +++ b/hw/deps/riscv/riscv_ex_stage.sv @@ -0,0 +1,564 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Renzo Andri - andrire@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Sven Stucki - svstucki@student.ethz.ch // +// Andreas Traber - atraber@iis.ee.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: Execute stage // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Execution stage: Hosts ALU and MAC unit // +// ALU: computes additions/subtractions/comparisons // +// MULT: computes normal multiplications // +// APU_DISP: offloads instructions to the shared unit. // +// SHARED_DSP_MULT, SHARED_INT_DIV allow // +// to offload also dot-product, int-div, int-mult to the // +// shared unit. // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "apu_macros.sv" + +import apu_core_package::*; +import riscv_defines::*; + +module riscv_ex_stage +#( + parameter FPU = 0, + parameter FP_DIVSQRT = 0, + parameter SHARED_FP = 0, + parameter SHARED_DSP_MULT = 0, + parameter SHARED_INT_DIV = 0, + parameter APU_NARGS_CPU = 3, + parameter APU_WOP_CPU = 6, + parameter APU_NDSFLAGS_CPU = 15, + parameter APU_NUSFLAGS_CPU = 5 +) +( + input logic clk, + input logic rst_n, + + // ALU signals from ID stage + input logic [ALU_OP_WIDTH-1:0] alu_operator_i, + input logic [31:0] alu_operand_a_i, + input logic [31:0] alu_operand_b_i, + input logic [31:0] alu_operand_c_i, + input logic alu_en_i, + input logic [ 4:0] bmask_a_i, + input logic [ 4:0] bmask_b_i, + input logic [ 1:0] imm_vec_ext_i, + input logic [ 1:0] alu_vec_mode_i, + input logic alu_is_clpx_i, + input logic alu_is_subrot_i, + input logic [ 1:0] alu_clpx_shift_i, + + // Multiplier signals + input logic [ 2:0] mult_operator_i, + input logic [31:0] mult_operand_a_i, + input logic [31:0] mult_operand_b_i, + input logic [31:0] mult_operand_c_i, + input logic mult_en_i, + input logic mult_sel_subword_i, + input logic [ 1:0] mult_signed_mode_i, + input logic [ 4:0] mult_imm_i, + + input logic [31:0] mult_dot_op_a_i, + input logic [31:0] mult_dot_op_b_i, + input logic [31:0] mult_dot_op_c_i, + input logic [ 1:0] mult_dot_signed_i, + input logic mult_is_clpx_i, + input logic [ 1:0] mult_clpx_shift_i, + input logic mult_clpx_img_i, + + output logic mult_multicycle_o, + + // FPU signals + input logic [C_PC-1:0] fpu_prec_i, + output logic [C_FFLAG-1:0] fpu_fflags_o, + output logic fpu_fflags_we_o, + + // APU signals + input logic apu_en_i, + input logic [APU_WOP_CPU-1:0] apu_op_i, + input logic [1:0] apu_lat_i, + input logic [APU_NARGS_CPU-1:0][31:0] apu_operands_i, + input logic [5:0] apu_waddr_i, + input logic [APU_NDSFLAGS_CPU-1:0] apu_flags_i, + + input logic [2:0][5:0] apu_read_regs_i, + input logic [2:0] apu_read_regs_valid_i, + output logic apu_read_dep_o, + input logic [1:0][5:0] apu_write_regs_i, + input logic [1:0] apu_write_regs_valid_i, + output logic apu_write_dep_o, + + output logic apu_perf_type_o, + output logic apu_perf_cont_o, + output logic apu_perf_wb_o, + + output logic apu_busy_o, + output logic apu_ready_wb_o, + + // apu-interconnect + // handshake signals + output logic apu_master_req_o, + output logic apu_master_ready_o, + input logic apu_master_gnt_i, + // request channel + output logic [APU_NARGS_CPU-1:0][31:0] apu_master_operands_o, + output logic [APU_WOP_CPU-1:0] apu_master_op_o, + // response channel + input logic apu_master_valid_i, + input logic [31:0] apu_master_result_i, + + input logic lsu_en_i, + input logic [31:0] lsu_rdata_i, + + // input from ID stage + input logic branch_in_ex_i, + input logic [5:0] regfile_alu_waddr_i, + input logic regfile_alu_we_i, + + // directly passed through to WB stage, not used in EX + input logic regfile_we_i, + input logic [5:0] regfile_waddr_i, + + // CSR access + input logic csr_access_i, + input logic [31:0] csr_rdata_i, + + // Output of EX stage pipeline + output logic [5:0] regfile_waddr_wb_o, + output logic regfile_we_wb_o, + output logic [31:0] regfile_wdata_wb_o, + + // Forwarding ports : to ID stage + output logic [5:0] regfile_alu_waddr_fw_o, + output logic regfile_alu_we_fw_o, + output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL + + // To IF: Jump and branch target and decision + output logic [31:0] jump_target_o, + output logic branch_decision_o, + + // Stall Control + input logic is_decoding_i, // Used to mask data Dependency inside the APU dispatcher in case of an istruction non valid + input logic lsu_ready_ex_i, // EX part of LSU is done + input logic lsu_err_i, + + output logic ex_ready_o, // EX stage ready for new data + output logic ex_valid_o, // EX stage gets new data + input logic wb_ready_i // WB stage ready for new data +); + + logic [31:0] alu_result; + logic [31:0] mult_result; + logic alu_cmp_result; + + logic regfile_we_lsu; + logic [5:0] regfile_waddr_lsu; + + logic wb_contention; + logic wb_contention_lsu; + + logic alu_ready; + logic mult_ready; + logic fpu_ready; + + // APU signals + logic apu_valid; + logic [5:0] apu_waddr; + logic [31:0] apu_result; + logic apu_stall; + logic apu_active; + logic apu_singlecycle; + logic apu_multicycle; + logic apu_req; + logic apu_ready; + logic apu_gnt; + + // ALU write port mux + always_comb + begin + regfile_alu_wdata_fw_o = '0; + regfile_alu_waddr_fw_o = '0; + regfile_alu_we_fw_o = '0; + wb_contention = 1'b0; + + // APU single cycle operations, and multicycle operations (>2cycles) are written back on ALU port + if (apu_valid & (apu_singlecycle | apu_multicycle)) begin + regfile_alu_we_fw_o = 1'b1; + regfile_alu_waddr_fw_o = apu_waddr; + regfile_alu_wdata_fw_o = apu_result; + + if(regfile_alu_we_i & ~apu_en_i) begin + wb_contention = 1'b1; + end + end else begin + regfile_alu_we_fw_o = regfile_alu_we_i & ~apu_en_i; // private fpu incomplete? + regfile_alu_waddr_fw_o = regfile_alu_waddr_i; + if (alu_en_i) + regfile_alu_wdata_fw_o = alu_result; + if (mult_en_i) + regfile_alu_wdata_fw_o = mult_result; + if (csr_access_i) + regfile_alu_wdata_fw_o = csr_rdata_i; + end + end + + // LSU write port mux + always_comb + begin + regfile_we_wb_o = 1'b0; + regfile_waddr_wb_o = regfile_waddr_lsu; + regfile_wdata_wb_o = lsu_rdata_i; + wb_contention_lsu = 1'b0; + + if (regfile_we_lsu) begin + regfile_we_wb_o = 1'b1; + if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin + wb_contention_lsu = 1'b1; +// $error("%t, wb-contention", $time); + end + // APU two-cycle operations are written back on LSU port + end else if (apu_valid & (!apu_singlecycle & !apu_multicycle)) begin + regfile_we_wb_o = 1'b1; + regfile_waddr_wb_o = apu_waddr; + regfile_wdata_wb_o = apu_result; + end + end + + // branch handling + assign branch_decision_o = alu_cmp_result; + assign jump_target_o = alu_operand_c_i; + + + //////////////////////////// + // _ _ _ _ // + // / \ | | | | | | // + // / _ \ | | | | | | // + // / ___ \| |__| |_| | // + // /_/ \_\_____\___/ // + // // + //////////////////////////// + + riscv_alu + #( + .SHARED_INT_DIV( SHARED_INT_DIV ), + .FPU ( FPU ) + ) + alu_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + .enable_i ( alu_en_i ), + .operator_i ( alu_operator_i ), + .operand_a_i ( alu_operand_a_i ), + .operand_b_i ( alu_operand_b_i ), + .operand_c_i ( alu_operand_c_i ), + + .vector_mode_i ( alu_vec_mode_i ), + .bmask_a_i ( bmask_a_i ), + .bmask_b_i ( bmask_b_i ), + .imm_vec_ext_i ( imm_vec_ext_i ), + + .is_clpx_i ( alu_is_clpx_i ), + .clpx_shift_i ( alu_clpx_shift_i), + .is_subrot_i ( alu_is_subrot_i ), + + .result_o ( alu_result ), + .comparison_result_o ( alu_cmp_result ), + + .ready_o ( alu_ready ), + .ex_ready_i ( ex_ready_o ) + ); + + + //////////////////////////////////////////////////////////////// + // __ __ _ _ _ _____ ___ ____ _ ___ _____ ____ // + // | \/ | | | | | |_ _|_ _| _ \| | |_ _| ____| _ \ // + // | |\/| | | | | | | | | || |_) | | | || _| | |_) | // + // | | | | |_| | |___| | | || __/| |___ | || |___| _ < // + // |_| |_|\___/|_____|_| |___|_| |_____|___|_____|_| \_\ // + // // + //////////////////////////////////////////////////////////////// + + riscv_mult + #( + .SHARED_DSP_MULT(SHARED_DSP_MULT) + ) + mult_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .enable_i ( mult_en_i ), + .operator_i ( mult_operator_i ), + + .short_subword_i ( mult_sel_subword_i ), + .short_signed_i ( mult_signed_mode_i ), + + .op_a_i ( mult_operand_a_i ), + .op_b_i ( mult_operand_b_i ), + .op_c_i ( mult_operand_c_i ), + .imm_i ( mult_imm_i ), + + .dot_op_a_i ( mult_dot_op_a_i ), + .dot_op_b_i ( mult_dot_op_b_i ), + .dot_op_c_i ( mult_dot_op_c_i ), + .dot_signed_i ( mult_dot_signed_i ), + .is_clpx_i ( mult_is_clpx_i ), + .clpx_shift_i ( mult_clpx_shift_i ), + .clpx_img_i ( mult_clpx_img_i ), + + .result_o ( mult_result ), + + .multicycle_o ( mult_multicycle_o ), + .ready_o ( mult_ready ), + .ex_ready_i ( ex_ready_o ) + ); + + generate + if (FPU == 1) begin + //////////////////////////////////////////////////// + // _ ____ _ _ ____ ___ ____ ____ // + // / \ | _ \| | | | | _ \_ _/ ___|| _ \ // + // / _ \ | |_) | | | | | | | | |\___ \| |_) | // + // / ___ \| __/| |_| | | |_| | | ___) | __/ // + // /_/ \_\_| \___/ |____/___|____/|_| // + // // + //////////////////////////////////////////////////// + + riscv_apu_disp apu_disp_i + ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .enable_i ( apu_en_i ), + .apu_lat_i ( apu_lat_i ), + .apu_waddr_i ( apu_waddr_i ), + + .apu_waddr_o ( apu_waddr ), + .apu_multicycle_o ( apu_multicycle ), + .apu_singlecycle_o ( apu_singlecycle ), + + .active_o ( apu_active ), + .stall_o ( apu_stall ), + + .read_regs_i ( apu_read_regs_i ), + .read_regs_valid_i ( apu_read_regs_valid_i ), + .read_dep_o ( apu_read_dep_o ), + .write_regs_i ( apu_write_regs_i ), + .write_regs_valid_i ( apu_write_regs_valid_i ), + .write_dep_o ( apu_write_dep_o ), + + .perf_type_o ( apu_perf_type_o ), + .perf_cont_o ( apu_perf_cont_o ), + + // apu-interconnect + // handshake signals + .apu_master_req_o ( apu_req ), + .apu_master_ready_o ( apu_ready ), + .apu_master_gnt_i ( apu_gnt ), + // response channel + .apu_master_valid_i ( apu_valid ) + ); + + assign apu_perf_wb_o = wb_contention | wb_contention_lsu; + assign apu_ready_wb_o = ~(apu_active | apu_en_i | apu_stall) | apu_valid; + + if ( SHARED_FP ) begin + assign apu_master_req_o = apu_req; + assign apu_master_ready_o = apu_ready; + assign apu_gnt = apu_master_gnt_i; + assign apu_valid = apu_master_valid_i; + assign apu_master_operands_o = apu_operands_i; + assign apu_master_op_o = apu_op_i; + assign apu_result = apu_master_result_i; + assign fpu_fflags_we_o = apu_valid; + assign fpu_ready = 1'b1; + end + else begin + + ////////////////////////////// + // ______ _____ _ _ // + // | ____| __ \| | | | // + // | |__ | |__) | | | | // + // | __| | ___/| | | | // + // | | | | | |__| | // + // |_| |_| \____/ // + ////////////////////////////// + + + logic [C_FPNEW_OPBITS-1:0] fpu_op; + logic fpu_op_mod; + logic fpu_vec_op; + + logic [C_FPNEW_FMTBITS-1:0] fpu_dst_fmt; + logic [C_FPNEW_FMTBITS-1:0] fpu_src_fmt; + logic [C_FPNEW_IFMTBITS-1:0] fpu_int_fmt; + logic [C_RM-1:0] fp_rnd_mode; + + assign {fpu_vec_op, fpu_op_mod, fpu_op} = apu_op_i; + assign {fpu_int_fmt, fpu_src_fmt, fpu_dst_fmt, fp_rnd_mode} = apu_flags_i; + + localparam C_DIV = FP_DIVSQRT ? fpnew_pkg::MERGED : fpnew_pkg::DISABLED; + + logic FPU_ready_int; + + // ----------- + // FPU Config + // ----------- + // Features (enabled formats, vectors etc.) + localparam fpnew_pkg::fpu_features_t FPU_FEATURES = '{ + Width: C_FLEN, + EnableVectors: C_XFVEC, + EnableNanBox: 1'b0, + FpFmtMask: {C_RVF, C_RVD, C_XF16, C_XF8, C_XF16ALT}, + IntFmtMask: {C_XFVEC && C_XF8, C_XFVEC && (C_XF16 || C_XF16ALT), 1'b1, 1'b0} + }; + + // Implementation (number of registers etc) + localparam fpnew_pkg::fpu_implementation_t FPU_IMPLEMENTATION = '{ + PipeRegs: '{// FP32, FP64, FP16, FP8, FP16alt + '{C_LAT_FP32, C_LAT_FP64, C_LAT_FP16, C_LAT_FP8, C_LAT_FP16ALT}, // ADDMUL + '{default: C_LAT_DIVSQRT}, // DIVSQRT + '{default: C_LAT_NONCOMP}, // NONCOMP + '{default: C_LAT_CONV}}, // CONV + UnitTypes: '{'{default: fpnew_pkg::MERGED}, // ADDMUL + '{default: C_DIV}, // DIVSQRT + '{default: fpnew_pkg::PARALLEL}, // NONCOMP + '{default: fpnew_pkg::MERGED}}, // CONV + PipeConfig: fpnew_pkg::AFTER + }; + + //--------------- + // FPU instance + //--------------- + + fpnew_top #( + .Features ( FPU_FEATURES ), + .Implementation ( FPU_IMPLEMENTATION ), + .TagType ( logic ) + ) i_fpnew_bulk ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .operands_i ( apu_operands_i ), + .rnd_mode_i ( fpnew_pkg::roundmode_e'(fp_rnd_mode) ), + .op_i ( fpnew_pkg::operation_e'(fpu_op) ), + .op_mod_i ( fpu_op_mod ), + .src_fmt_i ( fpnew_pkg::fp_format_e'(fpu_src_fmt) ), + .dst_fmt_i ( fpnew_pkg::fp_format_e'(fpu_dst_fmt) ), + .int_fmt_i ( fpnew_pkg::int_format_e'(fpu_int_fmt) ), + .vectorial_op_i ( fpu_vec_op ), + .tag_i ( 1'b0 ), + .in_valid_i ( apu_req ), + .in_ready_o ( FPU_ready_int ), + .flush_i ( 1'b0 ), + .result_o ( apu_result ), + .status_o ( fpu_fflags_o ), + .tag_o ( /* unused */ ), + .out_valid_o ( apu_valid ), + .out_ready_i ( 1'b1 ), + .busy_o ( /* unused */ ) + ); + + assign fpu_fflags_we_o = apu_valid; + assign apu_master_req_o = '0; + assign apu_master_ready_o = 1'b1; + assign apu_master_operands_o[0] = '0; + assign apu_master_operands_o[1] = '0; + assign apu_master_operands_o[2] = '0; + assign apu_master_op_o = '0; + assign apu_gnt = 1'b1; + + assign fpu_ready = (FPU_ready_int & apu_req) | (~apu_req); + + end + + end + else begin + // default assignements for the case when no FPU/APU is attached. + assign apu_master_req_o = '0; + assign apu_master_ready_o = 1'b1; + assign apu_master_operands_o[0] = '0; + assign apu_master_operands_o[1] = '0; + assign apu_master_operands_o[2] = '0; + assign apu_master_op_o = '0; + assign apu_req = 1'b0; + assign apu_gnt = 1'b0; + assign apu_ready = 1'b0; + assign apu_result = 32'b0; + assign apu_valid = 1'b0; + assign apu_waddr = 6'b0; + assign apu_stall = 1'b0; + assign apu_active = 1'b0; + assign apu_ready_wb_o = 1'b1; + assign apu_perf_wb_o = 1'b0; + assign apu_perf_cont_o = 1'b0; + assign apu_perf_type_o = 1'b0; + assign apu_singlecycle = 1'b0; + assign apu_multicycle = 1'b0; + assign apu_read_dep_o = 1'b0; + assign apu_write_dep_o = 1'b0; + assign fpu_fflags_we_o = 1'b0; + assign fpu_fflags_o = '0; + // we need this because we want ex_ready_o to go high otherwise the + // pipeline can't progress + assign fpu_ready = 1'b1; + + end + endgenerate + + assign apu_busy_o = apu_active; + + /////////////////////////////////////// + // EX/WB Pipeline Register // + /////////////////////////////////////// + always_ff @(posedge clk, negedge rst_n) + begin : EX_WB_Pipeline_Register + if (~rst_n) + begin + regfile_waddr_lsu <= '0; + regfile_we_lsu <= 1'b0; + end + else + begin + if (ex_valid_o) // wb_ready_i is implied + begin + regfile_we_lsu <= regfile_we_i & ~lsu_err_i; + if (regfile_we_i & ~lsu_err_i ) begin + regfile_waddr_lsu <= regfile_waddr_i; + end + end else if (wb_ready_i) begin + // we are ready for a new instruction, but there is none available, + // so we just flush the current one out of the pipe + regfile_we_lsu <= 1'b0; + end + end + end + + // As valid always goes to the right and ready to the left, and we are able + // to finish branches without going to the WB stage, ex_valid does not + // depend on ex_ready. + assign ex_ready_o = (~apu_stall & alu_ready & mult_ready & lsu_ready_ex_i + & wb_ready_i & ~wb_contention & fpu_ready) | (branch_in_ex_i); + assign ex_valid_o = (apu_valid | alu_en_i | mult_en_i | csr_access_i | lsu_en_i) + & (alu_ready & mult_ready & lsu_ready_ex_i & wb_ready_i); + +endmodule diff --git a/hw/deps/riscv/riscv_ff_one.sv b/hw/deps/riscv/riscv_ff_one.sv new file mode 100644 index 0000000..8524e76 --- /dev/null +++ b/hw/deps/riscv/riscv_ff_one.sv @@ -0,0 +1,98 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Andreas Traber - atraber@student.ethz.ch // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: riscv_ff_one // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Find First One // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_ff_one +#( + parameter LEN = 32 +) +( + input logic [LEN-1:0] in_i, + + output logic [$clog2(LEN)-1:0] first_one_o, + output logic no_ones_o +); + + localparam NUM_LEVELS = $clog2(LEN); + + logic [LEN-1:0] [NUM_LEVELS-1:0] index_lut; + logic [2**NUM_LEVELS-1:0] sel_nodes; + logic [2**NUM_LEVELS-1:0] [NUM_LEVELS-1:0] index_nodes; + + + ////////////////////////////////////////////////////////////////////////////// + // generate tree structure + ////////////////////////////////////////////////////////////////////////////// + + generate + genvar j; + for (j = 0; j < LEN; j++) begin + assign index_lut[j] = $unsigned(j); + end + endgenerate + + generate + genvar k; + genvar l; + genvar level; + for (level = 0; level < NUM_LEVELS; level++) begin + //------------------------------------------------------------ + if (level < NUM_LEVELS-1) begin + for (l = 0; l < 2**level; l++) begin + assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1]; + assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ? + index_nodes[2**(level+1)-1+l*2] : index_nodes[2**(level+1)-1+l*2+1]; + end + end + //------------------------------------------------------------ + if (level == NUM_LEVELS-1) begin + for (k = 0; k < 2**level; k++) begin + // if two successive indices are still in the vector... + if (k * 2 < LEN-1) begin + assign sel_nodes[2**level-1+k] = in_i[k*2] | in_i[k*2+1]; + assign index_nodes[2**level-1+k] = (in_i[k*2] == 1'b1) ? index_lut[k*2] : index_lut[k*2+1]; + end + // if only the first index is still in the vector... + if (k * 2 == LEN-1) begin + assign sel_nodes[2**level-1+k] = in_i[k*2]; + assign index_nodes[2**level-1+k] = index_lut[k*2]; + end + // if index is out of range + if (k * 2 > LEN-1) begin + assign sel_nodes[2**level-1+k] = 1'b0; + assign index_nodes[2**level-1+k] = '0; + end + end + end + //------------------------------------------------------------ + end + endgenerate + + ////////////////////////////////////////////////////////////////////////////// + // connect output + ////////////////////////////////////////////////////////////////////////////// + + assign first_one_o = index_nodes[0]; + assign no_ones_o = ~sel_nodes[0]; + +endmodule diff --git a/hw/deps/riscv/riscv_hwloop_controller.sv b/hw/deps/riscv/riscv_hwloop_controller.sv new file mode 100644 index 0000000..bab8f0a --- /dev/null +++ b/hw/deps/riscv/riscv_hwloop_controller.sv @@ -0,0 +1,98 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: hwloop controller // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Hardware loop controller unit. This unit is responsible to // +// handle hardware loops. Tasks are: // +// a) compare PC to all stored end addresses // +// b) jump to the right start address if counter =/ 0 // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_hwloop_controller +#( + parameter N_REGS = 2 +) +( + // from id stage + input logic [31:0] current_pc_i, + + // from hwloop_regs + input logic [N_REGS-1:0] [31:0] hwlp_start_addr_i, + input logic [N_REGS-1:0] [31:0] hwlp_end_addr_i, + input logic [N_REGS-1:0] [31:0] hwlp_counter_i, + + // to hwloop_regs + output logic [N_REGS-1:0] hwlp_dec_cnt_o, + + // from pipeline stages + input logic [N_REGS-1:0] hwlp_dec_cnt_id_i, + + // to id stage + output logic hwlp_jump_o, + output logic [31:0] hwlp_targ_addr_o +); + + + logic [N_REGS-1:0] pc_is_end_addr; + + // end address detection + integer j; + + + // generate comparators. check for end address and the loop counter + genvar i; + generate + for (i = 0; i < N_REGS; i++) begin + always @(*) + begin + pc_is_end_addr[i] = 1'b0; + + if (current_pc_i == hwlp_end_addr_i[i]) begin + if (hwlp_counter_i[i][31:2] != 30'h0) begin + pc_is_end_addr[i] = 1'b1; + end else begin + // hwlp_counter_i[i][31:2] == 32'h0 + case (hwlp_counter_i[i][1:0]) + 2'b11: pc_is_end_addr[i] = 1'b1; + 2'b10: pc_is_end_addr[i] = ~hwlp_dec_cnt_id_i[i]; // only when there is nothing in flight + 2'b01, 2'b00: pc_is_end_addr[i] = 1'b0; + endcase + end + end + end + end + endgenerate + + // select corresponding start address and decrement counter + always_comb + begin + hwlp_targ_addr_o = '0; + hwlp_dec_cnt_o = '0; + + for (j = 0; j < N_REGS; j++) begin + if (pc_is_end_addr[j]) begin + hwlp_targ_addr_o = hwlp_start_addr_i[j]; + hwlp_dec_cnt_o[j] = 1'b1; + break; + end + end + end + + // output signal for ID stage + assign hwlp_jump_o = (|pc_is_end_addr); + +endmodule diff --git a/hw/deps/riscv/riscv_hwloop_regs.sv b/hw/deps/riscv/riscv_hwloop_regs.sv new file mode 100644 index 0000000..4f5b58b --- /dev/null +++ b/hw/deps/riscv/riscv_hwloop_regs.sv @@ -0,0 +1,134 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: hwloop regs // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Hardware loop registers // +// a) store start/end address of N=4 hardware loops // +// b) store init value of counter for each hardware loop // +// c) decrement counter if hwloop taken // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_hwloop_regs +#( + parameter N_REGS = 2, + parameter N_REG_BITS = $clog2(N_REGS) +) +( + input logic clk, + input logic rst_n, + + // from ex stage + input logic [31:0] hwlp_start_data_i, + input logic [31:0] hwlp_end_data_i, + input logic [31:0] hwlp_cnt_data_i, + input logic [2:0] hwlp_we_i, + input logic [N_REG_BITS-1:0] hwlp_regid_i, // selects the register set + + // from controller + input logic valid_i, + + // from hwloop controller + input logic [N_REGS-1:0] hwlp_dec_cnt_i, + + // to hwloop controller + output logic [N_REGS-1:0] [31:0] hwlp_start_addr_o, + output logic [N_REGS-1:0] [31:0] hwlp_end_addr_o, + output logic [N_REGS-1:0] [31:0] hwlp_counter_o +); + + + logic [N_REGS-1:0] [31:0] hwlp_start_q; + logic [N_REGS-1:0] [31:0] hwlp_end_q; + logic [N_REGS-1:0] [31:0] hwlp_counter_q, hwlp_counter_n; + + int unsigned i; + + + assign hwlp_start_addr_o = hwlp_start_q; + assign hwlp_end_addr_o = hwlp_end_q; + assign hwlp_counter_o = hwlp_counter_q; + + + ///////////////////////////////////////////////////////////////////////////////// + // HWLOOP start-address register // + ///////////////////////////////////////////////////////////////////////////////// + always_ff @(posedge clk, negedge rst_n) + begin : HWLOOP_REGS_START + if (rst_n == 1'b0) + begin + hwlp_start_q <= '{default: 32'b0}; + end + else if (hwlp_we_i[0] == 1'b1) + begin + hwlp_start_q[hwlp_regid_i] <= hwlp_start_data_i; + end + end + + + ///////////////////////////////////////////////////////////////////////////////// + // HWLOOP end-address register // + ///////////////////////////////////////////////////////////////////////////////// + always_ff @(posedge clk, negedge rst_n) + begin : HWLOOP_REGS_END + if (rst_n == 1'b0) + begin + hwlp_end_q <= '{default: 32'b0}; + end + else if (hwlp_we_i[1] == 1'b1) + begin + hwlp_end_q[hwlp_regid_i] <= hwlp_end_data_i; + end + end + + + ///////////////////////////////////////////////////////////////////////////////// + // HWLOOP counter register with decrement logic // + ///////////////////////////////////////////////////////////////////////////////// + genvar k; + for (k = 0; k < N_REGS; k++) begin + assign hwlp_counter_n[k] = hwlp_counter_q[k] - 1; + end + + always_ff @(posedge clk, negedge rst_n) + begin : HWLOOP_REGS_COUNTER + if (rst_n == 1'b0) + begin + hwlp_counter_q <= '{default: 32'b0}; + end + else + begin + for (i = 0; i < N_REGS; i++) + begin + if ((hwlp_we_i[2] == 1'b1) && (i == hwlp_regid_i)) begin + hwlp_counter_q[i] <= hwlp_cnt_data_i; + end else begin + if (hwlp_dec_cnt_i[i] && valid_i) + hwlp_counter_q[i] <= hwlp_counter_n[i]; + end + end + end + end + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + `ifndef VERILATOR + // do not decrement more than one counter at once + assert property ( + @(posedge clk) (valid_i) |-> ($countones(hwlp_dec_cnt_i) <= 1) ); + `endif +endmodule diff --git a/hw/deps/riscv/riscv_id_stage.sv b/hw/deps/riscv/riscv_id_stage.sv new file mode 100644 index 0000000..0c0df3b --- /dev/null +++ b/hw/deps/riscv/riscv_id_stage.sv @@ -0,0 +1,1676 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Renzo Andri - andrire@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Andreas Traber - atraber@student.ethz.ch // +// Sven Stucki - svstucki@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: Instruction Decode Stage // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Decode stage of the core. It decodes the instructions // +// and hosts the register file. // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; +import apu_core_package::*; + + +// Source/Destination register instruction index +`define REG_S1 19:15 +`define REG_S2 24:20 +`define REG_S4 31:27 +`define REG_D 11:07 + +module riscv_id_stage +#( + parameter PULP_HWLP = 0, + parameter N_HWLP = 2, + parameter N_HWLP_BITS = $clog2(N_HWLP), + parameter PULP_SECURE = 0, + parameter USE_PMP = 0, + parameter A_EXTENSION = 0, + parameter APU = 0, + parameter FPU = 0, + parameter PULP_ZFINX = 0, + parameter FP_DIVSQRT = 0, + parameter SHARED_FP = 0, + parameter SHARED_DSP_MULT = 0, + parameter SHARED_INT_MULT = 0, + parameter SHARED_INT_DIV = 0, + parameter SHARED_FP_DIVSQRT = 0, + parameter WAPUTYPE = 0, + parameter APU_NARGS_CPU = 3, + parameter APU_WOP_CPU = 6, + parameter APU_NDSFLAGS_CPU = 15, + parameter APU_NUSFLAGS_CPU = 5, + parameter DEBUG_TRIGGER_EN = 1 +) +( + input logic clk, + input logic rst_n, + + input logic scan_cg_en_i, + + input logic fetch_enable_i, + output logic ctrl_busy_o, + output logic core_ctrl_firstfetch_o, + output logic is_decoding_o, + + // Interface to IF stage + input logic [N_HWLP-1:0] hwlp_dec_cnt_i, + input logic is_hwlp_i, + input logic instr_valid_i, + input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage + output logic instr_req_o, + + + // Jumps and branches + output logic branch_in_ex_o, + input logic branch_decision_i, + output logic [31:0] jump_target_o, + + // IF and ID stage signals + output logic clear_instr_valid_o, + output logic pc_set_o, + output logic [2:0] pc_mux_o, + output logic [2:0] exc_pc_mux_o, + output logic [1:0] trap_addr_mux_o, + + input logic illegal_c_insn_i, + input logic is_compressed_i, + input logic is_fetch_failed_i, + + input logic [31:0] pc_if_i, + input logic [31:0] pc_id_i, + + // Stalls + output logic halt_if_o, // controller requests a halt of the IF stage + + output logic id_ready_o, // ID stage is ready for the next instruction + input logic ex_ready_i, // EX stage is ready for the next instruction + input logic wb_ready_i, // WB stage is ready for the next instruction + + output logic id_valid_o, // ID stage is done + input logic ex_valid_i, // EX stage is done + + // Pipeline ID/EX + output logic [31:0] pc_ex_o, + + output logic [31:0] alu_operand_a_ex_o, + output logic [31:0] alu_operand_b_ex_o, + output logic [31:0] alu_operand_c_ex_o, + output logic [ 4:0] bmask_a_ex_o, + output logic [ 4:0] bmask_b_ex_o, + output logic [ 1:0] imm_vec_ext_ex_o, + output logic [ 1:0] alu_vec_mode_ex_o, + + output logic [5:0] regfile_waddr_ex_o, + output logic regfile_we_ex_o, + + output logic [5:0] regfile_alu_waddr_ex_o, + output logic regfile_alu_we_ex_o, + + // ALU + output logic alu_en_ex_o, + output logic [ALU_OP_WIDTH-1:0] alu_operator_ex_o, + output logic alu_is_clpx_ex_o, + output logic alu_is_subrot_ex_o, + output logic [ 1:0] alu_clpx_shift_ex_o, + + + // MUL + output logic [ 2:0] mult_operator_ex_o, + output logic [31:0] mult_operand_a_ex_o, + output logic [31:0] mult_operand_b_ex_o, + output logic [31:0] mult_operand_c_ex_o, + output logic mult_en_ex_o, + output logic mult_sel_subword_ex_o, + output logic [ 1:0] mult_signed_mode_ex_o, + output logic [ 4:0] mult_imm_ex_o, + + output logic [31:0] mult_dot_op_a_ex_o, + output logic [31:0] mult_dot_op_b_ex_o, + output logic [31:0] mult_dot_op_c_ex_o, + output logic [ 1:0] mult_dot_signed_ex_o, + output logic mult_is_clpx_ex_o, + output logic [ 1:0] mult_clpx_shift_ex_o, + output logic mult_clpx_img_ex_o, + + // APU + output logic apu_en_ex_o, + output logic [WAPUTYPE-1:0] apu_type_ex_o, + output logic [APU_WOP_CPU-1:0] apu_op_ex_o, + output logic [1:0] apu_lat_ex_o, + output logic [APU_NARGS_CPU-1:0][31:0] apu_operands_ex_o, + output logic [APU_NDSFLAGS_CPU-1:0] apu_flags_ex_o, + output logic [5:0] apu_waddr_ex_o, + + output logic [2:0][5:0] apu_read_regs_o, + output logic [2:0] apu_read_regs_valid_o, + input logic apu_read_dep_i, + output logic [1:0][5:0] apu_write_regs_o, + output logic [1:0] apu_write_regs_valid_o, + input logic apu_write_dep_i, + output logic apu_perf_dep_o, + input logic apu_busy_i, + input logic [C_RM-1:0] frm_i, + + // CSR ID/EX + output logic csr_access_ex_o, + output logic [1:0] csr_op_ex_o, + input PrivLvl_t current_priv_lvl_i, + output logic csr_irq_sec_o, + output logic [6:0] csr_cause_o, + output logic csr_save_if_o, + output logic csr_save_id_o, + output logic csr_save_ex_o, + output logic csr_restore_mret_id_o, + output logic csr_restore_uret_id_o, + + output logic csr_restore_dret_id_o, + + // Stack protection + output logic stack_access_o, + + output logic csr_save_cause_o, + + // hwloop signals + output logic [N_HWLP-1:0] [31:0] hwlp_start_o, + output logic [N_HWLP-1:0] [31:0] hwlp_end_o, + output logic [N_HWLP-1:0] [31:0] hwlp_cnt_o, + + // hwloop signals from CS register + input logic [N_HWLP_BITS-1:0] csr_hwlp_regid_i, + input logic [2:0] csr_hwlp_we_i, + input logic [31:0] csr_hwlp_data_i, + + // Interface to load store unit + output logic data_req_ex_o, + output logic data_we_ex_o, + output logic [1:0] data_type_ex_o, + output logic [1:0] data_sign_ext_ex_o, + output logic [1:0] data_reg_offset_ex_o, + output logic data_load_event_ex_o, + + output logic data_misaligned_ex_o, + + output logic prepost_useincr_ex_o, + input logic data_misaligned_i, + input logic data_err_i, + output logic data_err_ack_o, + + output logic [5:0] atop_ex_o, + output logic buffer_ex_o, + + // Interrupt signals + input logic irq_pending_i, + input logic irq_sec_i, + input logic [5:0] irq_id_i, + input logic m_irq_enable_i, + input logic u_irq_enable_i, + output logic irq_ack_o, + output logic [5:0] irq_id_o, + output logic [5:0] exc_cause_o, + + // Debug Signal + output logic debug_mode_o, + output logic [2:0] debug_cause_o, + output logic debug_csr_save_o, + input logic debug_req_i, + input logic debug_single_step_i, + input logic debug_ebreakm_i, + input logic debug_ebreaku_i, + input logic trigger_match_i, + + // Forward Signals + input logic [5:0] regfile_waddr_wb_i, + input logic regfile_we_wb_i, + input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata + + input logic [5:0] regfile_alu_waddr_fw_i, + input logic regfile_alu_we_fw_i, + input logic [31:0] regfile_alu_wdata_fw_i, + + // from ALU + input logic mult_multicycle_i, // when we need multiple cycles in the multiplier and use op c as storage + + // Performance Counters + output logic perf_jump_o, // we are executing a jump instruction + output logic perf_jr_stall_o, // jump-register-hazard + output logic perf_ld_stall_o, // load-use-hazard + output logic perf_pipeline_stall_o //extra cycles from elw +); + + logic [31:0] instr; + + // Decoder/Controller ID stage internal signals + logic deassert_we; + + logic illegal_insn_dec; + logic ebrk_insn; + logic mret_insn_dec; + logic uret_insn_dec; + + logic dret_insn_dec; + + logic ecall_insn_dec; + logic pipe_flush_dec; + + logic fencei_insn_dec; + + logic rega_used_dec; + logic regb_used_dec; + logic regc_used_dec; + + logic branch_taken_ex; + logic [1:0] jump_in_id; + logic [1:0] jump_in_dec; + + logic misaligned_stall; + logic jr_stall; + logic load_stall; + logic csr_apu_stall; + logic instr_multicycle; + logic hwloop_mask; + logic halt_id; + + + // Immediate decoding and sign extension + logic [31:0] imm_i_type; + logic [31:0] imm_iz_type; + logic [31:0] imm_s_type; + logic [31:0] imm_sb_type; + logic [31:0] imm_u_type; + logic [31:0] imm_uj_type; + logic [31:0] imm_z_type; + logic [31:0] imm_s2_type; + logic [31:0] imm_bi_type; + logic [31:0] imm_s3_type; + logic [31:0] imm_vs_type; + logic [31:0] imm_vu_type; + logic [31:0] imm_shuffleb_type; + logic [31:0] imm_shuffleh_type; + logic [31:0] imm_shuffle_type; + logic [31:0] imm_clip_type; + + logic [31:0] imm_a; // contains the immediate for operand b + logic [31:0] imm_b; // contains the immediate for operand b + + logic [31:0] jump_target; // calculated jump target (-> EX -> IF) + + + + // Signals running between controller and exception controller + logic irq_req_ctrl, irq_sec_ctrl; + logic [5:0] irq_id_ctrl; + logic exc_ack, exc_kill;// handshake + + // Register file interface + logic [5:0] regfile_addr_ra_id; + logic [5:0] regfile_addr_rb_id; + logic [5:0] regfile_addr_rc_id; + + logic regfile_fp_a; + logic regfile_fp_b; + logic regfile_fp_c; + logic regfile_fp_d; + + logic fregfile_ena; // whether the fp register file is enabled/present + + logic [5:0] regfile_waddr_id; + logic [5:0] regfile_alu_waddr_id; + logic regfile_alu_we_id, regfile_alu_we_dec_id; + + logic [31:0] regfile_data_ra_id; + logic [31:0] regfile_data_rb_id; + logic [31:0] regfile_data_rc_id; + + // ALU Control + logic alu_en; + logic [ALU_OP_WIDTH-1:0] alu_operator; + logic [2:0] alu_op_a_mux_sel; + logic [2:0] alu_op_b_mux_sel; + logic [1:0] alu_op_c_mux_sel; + logic [1:0] regc_mux; + + logic [0:0] imm_a_mux_sel; + logic [3:0] imm_b_mux_sel; + logic [1:0] jump_target_mux_sel; + + // Multiplier Control + logic [2:0] mult_operator; // multiplication operation selection + logic mult_en; // multiplication is used instead of ALU + logic mult_int_en; // use integer multiplier + logic mult_sel_subword; // Select a subword when doing multiplications + logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers + logic mult_dot_en; // use dot product + logic [1:0] mult_dot_signed; // Signed mode dot products (can be mixed types) + + // FPU signals + logic [C_FPNEW_FMTBITS-1:0] fpu_src_fmt; + logic [C_FPNEW_FMTBITS-1:0] fpu_dst_fmt; + logic [C_FPNEW_IFMTBITS-1:0] fpu_int_fmt; + + // APU signals + logic apu_en; + logic [WAPUTYPE-1:0] apu_type; + logic [APU_WOP_CPU-1:0] apu_op; + logic [1:0] apu_lat; + logic [APU_NARGS_CPU-1:0][31:0] apu_operands; + logic [APU_NDSFLAGS_CPU-1:0] apu_flags; + logic [5:0] apu_waddr; + + logic [2:0][5:0] apu_read_regs; + logic [2:0] apu_read_regs_valid; + logic [1:0][5:0] apu_write_regs; + logic [1:0] apu_write_regs_valid; + + logic [WAPUTYPE-1:0] apu_flags_src; + logic apu_stall; + logic [2:0] fp_rnd_mode; + + // Register Write Control + logic regfile_we_id; + logic regfile_alu_waddr_mux_sel; + + // Data Memory Control + logic data_we_id; + logic [1:0] data_type_id; + logic [1:0] data_sign_ext_id; + logic [1:0] data_reg_offset_id; + logic data_req_id; + logic data_load_event_id; + + // Atomic memory instruction + logic [5:0] atop_id; + logic buffer_id; + + // hwloop signals + logic [N_HWLP_BITS-1:0] hwloop_regid, hwloop_regid_int; + logic [2:0] hwloop_we, hwloop_we_int, hwloop_we_masked; + logic hwloop_target_mux_sel; + logic hwloop_start_mux_sel; + logic hwloop_cnt_mux_sel; + + logic [31:0] hwloop_target; + logic [31:0] hwloop_start, hwloop_start_int; + logic [31:0] hwloop_end; + logic [31:0] hwloop_cnt, hwloop_cnt_int; + + logic hwloop_valid; + + // CSR control + logic csr_access; + logic [1:0] csr_op; + logic csr_status; + + logic prepost_useincr; + + // Forwarding + logic [1:0] operand_a_fw_mux_sel; + logic [1:0] operand_b_fw_mux_sel; + logic [1:0] operand_c_fw_mux_sel; + logic [31:0] operand_a_fw_id; + logic [31:0] operand_b_fw_id; + logic [31:0] operand_c_fw_id; + + logic [31:0] operand_b, operand_b_vec; + logic [31:0] operand_c, operand_c_vec; + + logic [31:0] alu_operand_a; + logic [31:0] alu_operand_b; + logic [31:0] alu_operand_c; + + // Immediates for ID + logic [0:0] bmask_a_mux; + logic [1:0] bmask_b_mux; + logic alu_bmask_a_mux_sel; + logic alu_bmask_b_mux_sel; + logic [0:0] mult_imm_mux; + + logic [ 4:0] bmask_a_id_imm; + logic [ 4:0] bmask_b_id_imm; + logic [ 4:0] bmask_a_id; + logic [ 4:0] bmask_b_id; + logic [ 1:0] imm_vec_ext_id; + logic [ 4:0] mult_imm_id; + + logic [ 1:0] alu_vec_mode; + logic scalar_replication; + logic scalar_replication_c; + + // Forwarding detection signals + logic reg_d_ex_is_reg_a_id; + logic reg_d_ex_is_reg_b_id; + logic reg_d_ex_is_reg_c_id; + logic reg_d_wb_is_reg_a_id; + logic reg_d_wb_is_reg_b_id; + logic reg_d_wb_is_reg_c_id; + logic reg_d_alu_is_reg_a_id; + logic reg_d_alu_is_reg_b_id; + logic reg_d_alu_is_reg_c_id; + + logic stack_access; + + logic is_clpx, is_subrot; + + logic mret_dec; + logic uret_dec; + logic dret_dec; + + assign instr = instr_rdata_i; + + // immediate extraction and sign extension + assign imm_i_type = { {20 {instr[31]}}, instr[31:20] }; + assign imm_iz_type = { 20'b0, instr[31:20] }; + assign imm_s_type = { {20 {instr[31]}}, instr[31:25], instr[11:7] }; + assign imm_sb_type = { {19 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 }; + assign imm_u_type = { instr[31:12], 12'b0 }; + assign imm_uj_type = { {12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 }; + + // immediate for CSR manipulatin (zero extended) + assign imm_z_type = { 27'b0, instr[`REG_S1] }; + + assign imm_s2_type = { 27'b0, instr[24:20] }; + assign imm_bi_type = { {27{instr[24]}}, instr[24:20] }; + assign imm_s3_type = { 27'b0, instr[29:25] }; + assign imm_vs_type = { {26 {instr[24]}}, instr[24:20], instr[25] }; + assign imm_vu_type = { 26'b0, instr[24:20], instr[25] }; + + // same format as rS2 for shuffle needs, expands immediate + assign imm_shuffleb_type = {6'b0, instr[28:27], 6'b0, instr[24:23], 6'b0, instr[22:21], 6'b0, instr[20], instr[25]}; + assign imm_shuffleh_type = {15'h0, instr[20], 15'h0, instr[25]}; + + // clipping immediate, uses a small barrel shifter to pre-process the + // immediate and an adder to subtract 1 + // The end result is a mask that has 1's set in the lower part + // TODO: check if this can be shared with the bit-manipulation unit + assign imm_clip_type = (32'h1 << instr[24:20]) - 1; + + //----------------------------------------------------------------------------- + //-- FPU Register file enable: + //-- Taken from Cluster Config Reg if FPU reg file exists, or always disabled + //----------------------------------------------------------------------------- + assign fregfile_ena = FPU && !PULP_ZFINX ? 1'b1 : 1'b0; + + //--------------------------------------------------------------------------- + // source register selection regfile_fp_x=1 <=> REG_x is a FP-register + //--------------------------------------------------------------------------- + assign regfile_addr_ra_id = {fregfile_ena & regfile_fp_a, instr[`REG_S1]}; + assign regfile_addr_rb_id = {fregfile_ena & regfile_fp_b, instr[`REG_S2]}; + + // register C mux + always_comb begin + unique case (regc_mux) + REGC_ZERO: regfile_addr_rc_id = '0; + REGC_RD: regfile_addr_rc_id = {fregfile_ena & regfile_fp_c, instr[`REG_D]}; + REGC_S1: regfile_addr_rc_id = {fregfile_ena & regfile_fp_c, instr[`REG_S1]}; + REGC_S4: regfile_addr_rc_id = {fregfile_ena & regfile_fp_c, instr[`REG_S4]}; + default: regfile_addr_rc_id = '0; + endcase + end + + //--------------------------------------------------------------------------- + // destination registers regfile_fp_d=1 <=> REG_D is a FP-register + //--------------------------------------------------------------------------- + assign regfile_waddr_id = {fregfile_ena & regfile_fp_d, instr[`REG_D]}; + + // Second Register Write Address Selection + // Used for prepost load/store and multiplier + assign regfile_alu_waddr_id = regfile_alu_waddr_mux_sel ? + regfile_waddr_id : regfile_addr_ra_id; + + // Forwarding control signals + assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_o == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_o == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_o == regfile_addr_rc_id) && (regc_used_dec == 1'b1) && (regfile_addr_rc_id != '0); + assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == regfile_addr_rc_id) && (regc_used_dec == 1'b1) && (regfile_addr_rc_id != '0); + assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == regfile_addr_rc_id) && (regc_used_dec == 1'b1) && (regfile_addr_rc_id != '0); + + + // kill instruction in the IF/ID stage by setting the instr_valid_id control + // signal to 0 for instructions that are done + assign clear_instr_valid_o = id_ready_o | halt_id | branch_taken_ex; + + assign branch_taken_ex = branch_in_ex_o & branch_decision_i; + + + assign mult_en = mult_int_en | mult_dot_en; + + /////////////////////////////////////////////// + // _ ___ ___ ___ ___ ____ // + // | | | \ \ / / | / _ \ / _ \| _ \ // + // | |_| |\ \ /\ / /| | | | | | | | | |_) | // + // | _ | \ V V / | |__| |_| | |_| | __/ // + // |_| |_| \_/\_/ |_____\___/ \___/|_| // + // // + /////////////////////////////////////////////// + + // hwloop register id + assign hwloop_regid_int = instr[7]; // rd contains hwloop register id + + // hwloop target mux + always_comb begin + case (hwloop_target_mux_sel) + 1'b0: hwloop_target = pc_id_i + {imm_iz_type[30:0], 1'b0}; + 1'b1: hwloop_target = pc_id_i + {imm_z_type[30:0], 1'b0}; + endcase + end + + // hwloop start mux + always_comb begin + case (hwloop_start_mux_sel) + 1'b0: hwloop_start_int = hwloop_target; // for PC + I imm + 1'b1: hwloop_start_int = pc_if_i; // for next PC + endcase + end + + + // hwloop cnt mux + always_comb begin : hwloop_cnt_mux + case (hwloop_cnt_mux_sel) + 1'b0: hwloop_cnt_int = imm_iz_type; + 1'b1: hwloop_cnt_int = operand_a_fw_id; + endcase; + end + + /* + when hwloop_mask is 1, the controller is about to take an interrupt + the xEPC is going to have the hwloop instruction PC, therefore, do not update the + hwloop registers to make clear that the instruction hasn't been executed. + Although it may not be a HW bugs causing uninteded behaviours, + it helps verifications processes when checking the hwloop regs + */ + assign hwloop_we_masked = hwloop_we_int & ~{3{hwloop_mask}} & {3{id_ready_o}}; + + // multiplex between access from instructions and access via CSR registers + assign hwloop_start = hwloop_we_masked[0] ? hwloop_start_int : csr_hwlp_data_i; + assign hwloop_end = hwloop_we_masked[1] ? hwloop_target : csr_hwlp_data_i; + assign hwloop_cnt = hwloop_we_masked[2] ? hwloop_cnt_int : csr_hwlp_data_i; + assign hwloop_regid = (|hwloop_we_masked) ? hwloop_regid_int : csr_hwlp_regid_i; + assign hwloop_we = (|hwloop_we_masked) ? hwloop_we_masked : csr_hwlp_we_i; + + + ////////////////////////////////////////////////////////////////// + // _ _____ _ // + // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // + // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // + // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // + // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // + // |_| |___/ // + ////////////////////////////////////////////////////////////////// + + always_comb begin : jump_target_mux + unique case (jump_target_mux_sel) + JT_JAL: jump_target = pc_id_i + imm_uj_type; + JT_COND: jump_target = pc_id_i + imm_sb_type; + + // JALR: Cannot forward RS1, since the path is too long + JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; + default: jump_target = regfile_data_ra_id + imm_i_type; + endcase + end + + assign jump_target_o = jump_target; + + + //////////////////////////////////////////////////////// + // ___ _ _ // + // / _ \ _ __ ___ _ __ __ _ _ __ __| | / \ // + // | | | | '_ \ / _ \ '__/ _` | '_ \ / _` | / _ \ // + // | |_| | |_) | __/ | | (_| | | | | (_| | / ___ \ // + // \___/| .__/ \___|_| \__,_|_| |_|\__,_| /_/ \_\ // + // |_| // + //////////////////////////////////////////////////////// + + // ALU_Op_a Mux + always_comb begin : alu_operand_a_mux + case (alu_op_a_mux_sel) + OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; + OP_A_REGB_OR_FWD: alu_operand_a = operand_b_fw_id; + OP_A_REGC_OR_FWD: alu_operand_a = operand_c_fw_id; + OP_A_CURRPC: alu_operand_a = pc_id_i; + OP_A_IMM: alu_operand_a = imm_a; + default: alu_operand_a = operand_a_fw_id; + endcase; // case (alu_op_a_mux_sel) + end + + always_comb begin : immediate_a_mux + unique case (imm_a_mux_sel) + IMMA_Z: imm_a = imm_z_type; + IMMA_ZERO: imm_a = '0; + default: imm_a = '0; + endcase + end + + // Operand a forwarding mux + always_comb begin : operand_a_fw_mux + case (operand_a_fw_mux_sel) + SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; + default: operand_a_fw_id = regfile_data_ra_id; + endcase; // case (operand_a_fw_mux_sel) + end + + ////////////////////////////////////////////////////// + // ___ _ ____ // + // / _ \ _ __ ___ _ __ __ _ _ __ __| | | __ ) // + // | | | | '_ \ / _ \ '__/ _` | '_ \ / _` | | _ \ // + // | |_| | |_) | __/ | | (_| | | | | (_| | | |_) | // + // \___/| .__/ \___|_| \__,_|_| |_|\__,_| |____/ // + // |_| // + ////////////////////////////////////////////////////// + + // Immediate Mux for operand B + // TODO: check if sign-extension stuff works well here, maybe able to save + // some area here + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMMB_I: imm_b = imm_i_type; + IMMB_S: imm_b = imm_s_type; + IMMB_U: imm_b = imm_u_type; + IMMB_PCINCR: imm_b = (is_compressed_i && (~data_misaligned_i)) ? 32'h2 : 32'h4; + IMMB_S2: imm_b = imm_s2_type; + IMMB_BI: imm_b = imm_bi_type; + IMMB_S3: imm_b = imm_s3_type; + IMMB_VS: imm_b = imm_vs_type; + IMMB_VU: imm_b = imm_vu_type; + IMMB_SHUF: imm_b = imm_shuffle_type; + IMMB_CLIP: imm_b = {1'b0, imm_clip_type[31:1]}; + default: imm_b = imm_i_type; + endcase + end + + // ALU_Op_b Mux + always_comb begin : alu_operand_b_mux + case (alu_op_b_mux_sel) + OP_B_REGA_OR_FWD: operand_b = operand_a_fw_id; + OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; + OP_B_REGC_OR_FWD: operand_b = operand_c_fw_id; + OP_B_IMM: operand_b = imm_b; + OP_B_BMASK: operand_b = $unsigned(operand_b_fw_id[4:0]); + default: operand_b = operand_b_fw_id; + endcase // case (alu_op_b_mux_sel) + end + + + // scalar replication for operand B and shuffle type + always_comb begin + if (alu_vec_mode == VEC_MODE8) begin + operand_b_vec = {4{operand_b[7:0]}}; + imm_shuffle_type = imm_shuffleb_type; + end else begin + operand_b_vec = {2{operand_b[15:0]}}; + imm_shuffle_type = imm_shuffleh_type; + end + end + + // choose normal or scalar replicated version of operand b + assign alu_operand_b = (scalar_replication == 1'b1) ? operand_b_vec : operand_b; + + + // Operand b forwarding mux + always_comb begin : operand_b_fw_mux + case (operand_b_fw_mux_sel) + SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; + default: operand_b_fw_id = regfile_data_rb_id; + endcase; // case (operand_b_fw_mux_sel) + end + + + ////////////////////////////////////////////////////// + // ___ _ ____ // + // / _ \ _ __ ___ _ __ __ _ _ __ __| | / ___| // + // | | | | '_ \ / _ \ '__/ _` | '_ \ / _` | | | // + // | |_| | |_) | __/ | | (_| | | | | (_| | | |___ // + // \___/| .__/ \___|_| \__,_|_| |_|\__,_| \____| // + // |_| // + ////////////////////////////////////////////////////// + + // ALU OP C Mux + always_comb begin : alu_operand_c_mux + case (alu_op_c_mux_sel) + OP_C_REGC_OR_FWD: operand_c = operand_c_fw_id; + OP_C_REGB_OR_FWD: operand_c = operand_b_fw_id; + OP_C_JT: operand_c = jump_target; + default: operand_c = operand_c_fw_id; + endcase // case (alu_op_c_mux_sel) + end + + + // scalar replication for operand C and shuffle type + always_comb begin + if (alu_vec_mode == VEC_MODE8) begin + operand_c_vec = {4{operand_c[7:0]}}; + end else begin + operand_c_vec = {2{operand_c[15:0]}}; + end + end + + // choose normal or scalar replicated version of operand b + assign alu_operand_c = (scalar_replication_c == 1'b1) ? operand_c_vec : operand_c; + + + // Operand c forwarding mux + always_comb begin : operand_c_fw_mux + case (operand_c_fw_mux_sel) + SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; + default: operand_c_fw_id = regfile_data_rc_id; + endcase; // case (operand_c_fw_mux_sel) + end + + + /////////////////////////////////////////////////////////////////////////// + // ___ _ _ _ ___ ____ // + // |_ _|_ __ ___ _ __ ___ ___ __| (_) __ _| |_ ___ ___ |_ _| _ \ // + // | || '_ ` _ \| '_ ` _ \ / _ \/ _` | |/ _` | __/ _ \/ __| | || | | | // + // | || | | | | | | | | | | __/ (_| | | (_| | || __/\__ \ | || |_| | // + // |___|_| |_| |_|_| |_| |_|\___|\__,_|_|\__,_|\__\___||___/ |___|____/ // + // // + /////////////////////////////////////////////////////////////////////////// + + always_comb begin + unique case (bmask_a_mux) + BMASK_A_ZERO: bmask_a_id_imm = '0; + BMASK_A_S3: bmask_a_id_imm = imm_s3_type[4:0]; + default: bmask_a_id_imm = '0; + endcase + end + always_comb begin + unique case (bmask_b_mux) + BMASK_B_ZERO: bmask_b_id_imm = '0; + BMASK_B_ONE: bmask_b_id_imm = 5'd1; + BMASK_B_S2: bmask_b_id_imm = imm_s2_type[4:0]; + BMASK_B_S3: bmask_b_id_imm = imm_s3_type[4:0]; + default: bmask_b_id_imm = '0; + endcase + end + + always_comb begin + unique case (alu_bmask_a_mux_sel) + BMASK_A_IMM: bmask_a_id = bmask_a_id_imm; + BMASK_A_REG: bmask_a_id = operand_b_fw_id[9:5]; + default: bmask_a_id = bmask_a_id_imm; + endcase + end + always_comb begin + unique case (alu_bmask_b_mux_sel) + BMASK_B_IMM: bmask_b_id = bmask_b_id_imm; + BMASK_B_REG: bmask_b_id = operand_b_fw_id[4:0]; + default: bmask_b_id = bmask_b_id_imm; + endcase + end + + assign imm_vec_ext_id = imm_vu_type[1:0]; + + + always_comb begin + unique case (mult_imm_mux) + MIMM_ZERO: mult_imm_id = '0; + MIMM_S3: mult_imm_id = imm_s3_type[4:0]; + default: mult_imm_id = '0; + endcase + end + + ///////////////////////////// + // APU operand assignment // + ///////////////////////////// + // read regs + generate + if (APU == 1) begin : apu_op_preparation + + if (APU_NARGS_CPU >= 1) + assign apu_operands[0] = alu_operand_a; + if (APU_NARGS_CPU >= 2) + assign apu_operands[1] = alu_operand_b; + if (APU_NARGS_CPU >= 3) + assign apu_operands[2] = alu_operand_c; + + // write reg + assign apu_waddr = regfile_alu_waddr_id; + + // flags + always_comb begin + unique case (apu_flags_src) + APU_FLAGS_INT_MULT: + apu_flags = {7'h0 , mult_imm_id, mult_signed_mode, mult_sel_subword}; + APU_FLAGS_DSP_MULT: + apu_flags = {13'h0, mult_dot_signed}; + APU_FLAGS_FP: + if (FPU == 1) + apu_flags = fp_rnd_mode; + else + apu_flags = '0; + APU_FLAGS_FPNEW: + if (FPU == 1) + apu_flags = {fpu_int_fmt, fpu_src_fmt, fpu_dst_fmt, fp_rnd_mode}; + else + apu_flags = '0; + default: + apu_flags = '0; + endcase + end + + // dependency checks + always_comb begin + unique case (alu_op_a_mux_sel) + OP_A_REGA_OR_FWD: begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid [0] = 1'b1; + end // OP_A_REGA_OR_FWD: + OP_A_REGB_OR_FWD: begin + apu_read_regs[0] = regfile_addr_rb_id; + apu_read_regs_valid[0] = 1'b1; + end + default: begin + apu_read_regs[0] = regfile_addr_ra_id; + apu_read_regs_valid [0] = 1'b0; + end + endcase + end + + always_comb begin + unique case (alu_op_b_mux_sel) + OP_B_REGA_OR_FWD: begin + apu_read_regs[1] = regfile_addr_ra_id; + apu_read_regs_valid[1] = 1'b1; + end + OP_B_REGB_OR_FWD: begin + apu_read_regs[1] = regfile_addr_rb_id; + apu_read_regs_valid[1] = 1'b1; + end + OP_B_REGC_OR_FWD: begin + apu_read_regs[1] = regfile_addr_rc_id; + apu_read_regs_valid[1] = 1'b1; + end + default: begin + apu_read_regs[1] = regfile_addr_rb_id; + apu_read_regs_valid [1] = 1'b0; + end + endcase + end + + always_comb begin + unique case (alu_op_c_mux_sel) + OP_C_REGB_OR_FWD: begin + apu_read_regs[2] = regfile_addr_rb_id; + apu_read_regs_valid[2] = 1'b1; + end + OP_C_REGC_OR_FWD: begin + apu_read_regs[2] = regfile_addr_rc_id; + apu_read_regs_valid[2] = 1'b1; + end + default: begin + apu_read_regs[2] = regfile_addr_rc_id; + apu_read_regs_valid [2] = 1'b0; + end + endcase + end + + assign apu_write_regs[0] = regfile_alu_waddr_id; + assign apu_write_regs_valid [0] = regfile_alu_we_id; + + assign apu_write_regs[1] = regfile_waddr_id; + assign apu_write_regs_valid[1] = regfile_we_id; + + assign apu_read_regs_o = apu_read_regs; + assign apu_read_regs_valid_o = apu_read_regs_valid; + + assign apu_write_regs_o = apu_write_regs; + assign apu_write_regs_valid_o = apu_write_regs_valid; + end else begin + for (genvar i=0; i= C_RM+2*C_FPNEW_FMTBITS+C_FPNEW_IFMTBITS) + else $error("[apu] APU_NDSFLAGS_CPU APU flagbits is smaller than %0d", C_RM+2*C_FPNEW_FMTBITS+C_FPNEW_IFMTBITS); + end + end +`endif + + + ///////////////////////////////////////////////////////// + // ____ _____ ____ ___ ____ _____ _____ ____ ____ // + // | _ \| ____/ ___|_ _/ ___|_ _| ____| _ \/ ___| // + // | |_) | _|| | _ | |\___ \ | | | _| | |_) \___ \ // + // | _ <| |__| |_| || | ___) || | | |___| _ < ___) | // + // |_| \_\_____\____|___|____/ |_| |_____|_| \_\____/ // + // // + ///////////////////////////////////////////////////////// + riscv_register_file + #( + .ADDR_WIDTH(6), + .FPU(FPU) + ) + registers_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .test_en_i ( scan_cg_en_i ), + + .fregfile_disable_i ( 1'b0 ), + + // Read port a + .raddr_a_i ( regfile_addr_ra_id ), + .rdata_a_o ( regfile_data_ra_id ), + + // Read port b + .raddr_b_i ( regfile_addr_rb_id ), + .rdata_b_o ( regfile_data_rb_id ), + + // Read port c + .raddr_c_i ( regfile_addr_rc_id ), + .rdata_c_o ( regfile_data_rc_id ), + + // Write port a + .waddr_a_i ( regfile_waddr_wb_i ), + .wdata_a_i ( regfile_wdata_wb_i ), + .we_a_i ( regfile_we_wb_i ), + + // Write port b + .waddr_b_i ( regfile_alu_waddr_fw_i ), + .wdata_b_i ( regfile_alu_wdata_fw_i ), + .we_b_i ( regfile_alu_we_fw_i ) + ); + + + + + /////////////////////////////////////////////// + // ____ _____ ____ ___ ____ _____ ____ // + // | _ \| ____/ ___/ _ \| _ \| ____| _ \ // + // | | | | _|| | | | | | | | | _| | |_) | // + // | |_| | |__| |__| |_| | |_| | |___| _ < // + // |____/|_____\____\___/|____/|_____|_| \_\ // + // // + /////////////////////////////////////////////// + + riscv_decoder + #( + .PULP_HWLP ( PULP_HWLP ), + .A_EXTENSION ( A_EXTENSION ), + .FPU ( FPU ), + .FP_DIVSQRT ( FP_DIVSQRT ), + .PULP_SECURE ( PULP_SECURE ), + .USE_PMP ( USE_PMP ), + .SHARED_FP ( SHARED_FP ), + .SHARED_DSP_MULT ( SHARED_DSP_MULT ), + .SHARED_INT_MULT ( SHARED_INT_MULT ), + .SHARED_INT_DIV ( SHARED_INT_DIV ), + .SHARED_FP_DIVSQRT ( SHARED_FP_DIVSQRT ), + .WAPUTYPE ( WAPUTYPE ), + .APU_WOP_CPU ( APU_WOP_CPU ), + .DEBUG_TRIGGER_EN ( DEBUG_TRIGGER_EN ) + ) + decoder_i + ( + // controller related signals + .deassert_we_i ( deassert_we ), + .data_misaligned_i ( data_misaligned_i ), + .mult_multicycle_i ( mult_multicycle_i ), + .instr_multicycle_o ( instr_multicycle ), + + .illegal_insn_o ( illegal_insn_dec ), + .ebrk_insn_o ( ebrk_insn ), + + .mret_insn_o ( mret_insn_dec ), + .uret_insn_o ( uret_insn_dec ), + .dret_insn_o ( dret_insn_dec ), + + .mret_dec_o ( mret_dec ), + .uret_dec_o ( uret_dec ), + .dret_dec_o ( dret_dec ), + + .ecall_insn_o ( ecall_insn_dec ), + .pipe_flush_o ( pipe_flush_dec ), + + .fencei_insn_o ( fencei_insn_dec ), + + .rega_used_o ( rega_used_dec ), + .regb_used_o ( regb_used_dec ), + .regc_used_o ( regc_used_dec ), + + .reg_fp_a_o ( regfile_fp_a ), + .reg_fp_b_o ( regfile_fp_b ), + .reg_fp_c_o ( regfile_fp_c ), + .reg_fp_d_o ( regfile_fp_d ), + + .bmask_a_mux_o ( bmask_a_mux ), + .bmask_b_mux_o ( bmask_b_mux ), + .alu_bmask_a_mux_sel_o ( alu_bmask_a_mux_sel ), + .alu_bmask_b_mux_sel_o ( alu_bmask_b_mux_sel ), + + // from IF/ID pipeline + .instr_rdata_i ( instr ), + .illegal_c_insn_i ( illegal_c_insn_i ), + + // ALU signals + .alu_en_o ( alu_en ), + .alu_operator_o ( alu_operator ), + .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), + .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), + .alu_op_c_mux_sel_o ( alu_op_c_mux_sel ), + .alu_vec_mode_o ( alu_vec_mode ), + .scalar_replication_o ( scalar_replication ), + .scalar_replication_c_o ( scalar_replication_c ), + .imm_a_mux_sel_o ( imm_a_mux_sel ), + .imm_b_mux_sel_o ( imm_b_mux_sel ), + .regc_mux_o ( regc_mux ), + .is_clpx_o ( is_clpx ), + .is_subrot_o ( is_subrot ), + + // MUL signals + .mult_operator_o ( mult_operator ), + .mult_int_en_o ( mult_int_en ), + .mult_sel_subword_o ( mult_sel_subword ), + .mult_signed_mode_o ( mult_signed_mode ), + .mult_imm_mux_o ( mult_imm_mux ), + .mult_dot_en_o ( mult_dot_en ), + .mult_dot_signed_o ( mult_dot_signed ), + + // FPU / APU signals + .frm_i ( frm_i ), + .fpu_src_fmt_o ( fpu_src_fmt ), + .fpu_dst_fmt_o ( fpu_dst_fmt ), + .fpu_int_fmt_o ( fpu_int_fmt ), + .apu_en_o ( apu_en ), + .apu_type_o ( apu_type ), + .apu_op_o ( apu_op ), + .apu_lat_o ( apu_lat ), + .apu_flags_src_o ( apu_flags_src ), + .fp_rnd_mode_o ( fp_rnd_mode ), + + // Register file control signals + .regfile_mem_we_o ( regfile_we_id ), + .regfile_alu_we_o ( regfile_alu_we_id ), + .regfile_alu_we_dec_o ( regfile_alu_we_dec_id ), + .regfile_alu_waddr_sel_o ( regfile_alu_waddr_mux_sel ), + + // CSR control signals + .csr_access_o ( csr_access ), + .csr_status_o ( csr_status ), + .csr_op_o ( csr_op ), + .current_priv_lvl_i ( current_priv_lvl_i ), + + // Stack protection + .stack_access_o ( stack_access ), + + // Data bus interface + .data_req_o ( data_req_id ), + .data_we_o ( data_we_id ), + .prepost_useincr_o ( prepost_useincr ), + .data_type_o ( data_type_id ), + .data_sign_extension_o ( data_sign_ext_id ), + .data_reg_offset_o ( data_reg_offset_id ), + .data_load_event_o ( data_load_event_id ), + + // Atomic memory access + .atop_o ( atop_id ), + .buffer_o ( buffer_id ), + + // hwloop signals + .hwloop_we_o ( hwloop_we_int ), + .hwloop_target_mux_sel_o ( hwloop_target_mux_sel ), + .hwloop_start_mux_sel_o ( hwloop_start_mux_sel ), + .hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ), + + // debug mode + .debug_mode_i ( debug_mode_o ), + + // jump/branches + .jump_in_dec_o ( jump_in_dec ), + .jump_in_id_o ( jump_in_id ), + .jump_target_mux_sel_o ( jump_target_mux_sel ) + + ); + + //////////////////////////////////////////////////////////////////// + // ____ ___ _ _ _____ ____ ___ _ _ _____ ____ // + // / ___/ _ \| \ | |_ _| _ \ / _ \| | | | | ____| _ \ // + // | | | | | | \| | | | | |_) | | | | | | | | _| | |_) | // + // | |__| |_| | |\ | | | | _ <| |_| | |___| |___| |___| _ < // + // \____\___/|_| \_| |_| |_| \_\\___/|_____|_____|_____|_| \_\ // + // // + //////////////////////////////////////////////////////////////////// + + riscv_controller + #( + .FPU ( FPU ) + ) + controller_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .fetch_enable_i ( fetch_enable_i ), + .ctrl_busy_o ( ctrl_busy_o ), + .first_fetch_o ( core_ctrl_firstfetch_o ), + .is_decoding_o ( is_decoding_o ), + .is_fetch_failed_i ( is_fetch_failed_i ), + + // decoder related signals + .deassert_we_o ( deassert_we ), + + .illegal_insn_i ( illegal_insn_dec ), + .ecall_insn_i ( ecall_insn_dec ), + .mret_insn_i ( mret_insn_dec ), + .uret_insn_i ( uret_insn_dec ), + + .dret_insn_i ( dret_insn_dec ), + + .mret_dec_i ( mret_dec ), + .uret_dec_i ( uret_dec ), + .dret_dec_i ( dret_dec ), + + + .pipe_flush_i ( pipe_flush_dec ), + .ebrk_insn_i ( ebrk_insn ), + .fencei_insn_i ( fencei_insn_dec ), + .csr_status_i ( csr_status ), + .instr_multicycle_i ( instr_multicycle ), + + .hwloop_mask_o ( hwloop_mask ), + + // from IF/ID pipeline + .instr_valid_i ( instr_valid_i ), + + // from prefetcher + .instr_req_o ( instr_req_o ), + + // to prefetcher + .pc_set_o ( pc_set_o ), + .pc_mux_o ( pc_mux_o ), + .exc_pc_mux_o ( exc_pc_mux_o ), + .exc_cause_o ( exc_cause_o ), + .trap_addr_mux_o ( trap_addr_mux_o ), + + // LSU + .data_req_ex_i ( data_req_ex_o ), + .data_we_ex_i ( data_we_ex_o ), + .data_misaligned_i ( data_misaligned_i ), + .data_load_event_i ( data_load_event_id ), + .data_err_i ( data_err_i ), + .data_err_ack_o ( data_err_ack_o ), + + // ALU + .mult_multicycle_i ( mult_multicycle_i ), + + // APU + .apu_en_i ( apu_en ), + .apu_read_dep_i ( apu_read_dep_i ), + .apu_write_dep_i ( apu_write_dep_i ), + + .apu_stall_o ( apu_stall ), + + // jump/branch control + .branch_taken_ex_i ( branch_taken_ex ), + .jump_in_id_i ( jump_in_id ), + .jump_in_dec_i ( jump_in_dec ), + + // Interrupt Controller Signals + .irq_pending_i ( irq_pending_i ), + .irq_req_ctrl_i ( irq_req_ctrl ), + .irq_sec_ctrl_i ( irq_sec_ctrl ), + .irq_id_ctrl_i ( irq_id_ctrl ), + .m_IE_i ( m_irq_enable_i ), + .u_IE_i ( u_irq_enable_i ), + .current_priv_lvl_i ( current_priv_lvl_i ), + + .irq_ack_o ( irq_ack_o ), + .irq_id_o ( irq_id_o ), + + .exc_ack_o ( exc_ack ), + .exc_kill_o ( exc_kill ), + + // Debug Signal + .debug_mode_o ( debug_mode_o ), + .debug_cause_o ( debug_cause_o ), + .debug_csr_save_o ( debug_csr_save_o ), + .debug_req_i ( debug_req_i ), + .debug_single_step_i ( debug_single_step_i ), + .debug_ebreakm_i ( debug_ebreakm_i ), + .debug_ebreaku_i ( debug_ebreaku_i ), + .trigger_match_i ( trigger_match_i ), + + // CSR Controller Signals + .csr_save_cause_o ( csr_save_cause_o ), + .csr_cause_o ( csr_cause_o ), + .csr_save_if_o ( csr_save_if_o ), + .csr_save_id_o ( csr_save_id_o ), + .csr_save_ex_o ( csr_save_ex_o ), + .csr_restore_mret_id_o ( csr_restore_mret_id_o ), + .csr_restore_uret_id_o ( csr_restore_uret_id_o ), + + .csr_restore_dret_id_o ( csr_restore_dret_id_o ), + + .csr_irq_sec_o ( csr_irq_sec_o ), + + // Write targets from ID + .regfile_we_id_i ( regfile_alu_we_dec_id ), + .regfile_alu_waddr_id_i ( regfile_alu_waddr_id ), + + // Forwarding signals from regfile + .regfile_we_ex_i ( regfile_we_ex_o ), + .regfile_waddr_ex_i ( regfile_waddr_ex_o ), + .regfile_we_wb_i ( regfile_we_wb_i ), + + // regfile port 2 + .regfile_alu_we_fw_i ( regfile_alu_we_fw_i ), + + // Forwarding detection signals + .reg_d_ex_is_reg_a_i ( reg_d_ex_is_reg_a_id ), + .reg_d_ex_is_reg_b_i ( reg_d_ex_is_reg_b_id ), + .reg_d_ex_is_reg_c_i ( reg_d_ex_is_reg_c_id ), + .reg_d_wb_is_reg_a_i ( reg_d_wb_is_reg_a_id ), + .reg_d_wb_is_reg_b_i ( reg_d_wb_is_reg_b_id ), + .reg_d_wb_is_reg_c_i ( reg_d_wb_is_reg_c_id ), + .reg_d_alu_is_reg_a_i ( reg_d_alu_is_reg_a_id ), + .reg_d_alu_is_reg_b_i ( reg_d_alu_is_reg_b_id ), + .reg_d_alu_is_reg_c_i ( reg_d_alu_is_reg_c_id ), + + // Forwarding signals + .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), + .operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ), + .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), + + // Stall signals + .halt_if_o ( halt_if_o ), + .halt_id_o ( halt_id ), + + .misaligned_stall_o ( misaligned_stall ), + .jr_stall_o ( jr_stall ), + .load_stall_o ( load_stall ), + + .id_ready_i ( id_ready_o ), + + .ex_valid_i ( ex_valid_i ), + + .wb_ready_i ( wb_ready_i ), + + // Performance Counters + .perf_jump_o ( perf_jump_o ), + .perf_jr_stall_o ( perf_jr_stall_o ), + .perf_ld_stall_o ( perf_ld_stall_o ), + .perf_pipeline_stall_o ( perf_pipeline_stall_o ) + ); + + +//////////////////////////////////////////////////////////////////////// +// _____ _ _____ _ _ _ // +// |_ _| | | / __ \ | | | | | // +// | | _ __ | |_ | / \/ ___ _ __ | |_ _ __ ___ | | | ___ _ __ // +// | || '_ \| __| | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| // +// _| || | | | |_ _ | \__/\ (_) | | | | |_| | | (_) | | | __/ | // +// \___/_| |_|\__(_) \____/\___/|_| |_|\__|_| \___/|_|_|\___|_| // +// // +//////////////////////////////////////////////////////////////////////// + + riscv_int_controller + #( + .PULP_SECURE(PULP_SECURE) + ) + int_controller_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + // to controller + .irq_req_ctrl_o ( irq_req_ctrl ), + .irq_sec_ctrl_o ( irq_sec_ctrl ), + .irq_id_ctrl_o ( irq_id_ctrl ), + + .ctrl_ack_i ( exc_ack ), + .ctrl_kill_i ( exc_kill ), + + // Interrupt signals + .irq_pending_i ( irq_pending_i ), + .irq_sec_i ( irq_sec_i ), + .irq_id_i ( irq_id_i ), + + .m_IE_i ( m_irq_enable_i ), + .u_IE_i ( u_irq_enable_i ), + .current_priv_lvl_i ( current_priv_lvl_i ) + + ); + + + ////////////////////////////////////////////////////////////////////////// + // ____ ___ _ _ _____ ____ ___ _ _ _____ ____ // + // / ___/ _ \| \ | |_ _| _ \ / _ \| | | | | ____| _ \ // + // HWLOOP-| | | | | | \| | | | | |_) | | | | | | | | _| | |_) | // + // | |__| |_| | |\ | | | | _ <| |_| | |___| |___| |___| _ < // + // \____\___/|_| \_| |_| |_| \_\\___/|_____|_____|_____|_| \_\ // + // // + ////////////////////////////////////////////////////////////////////////// + + riscv_hwloop_regs + #( + .N_REGS ( N_HWLP ) + ) + hwloop_regs_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + // from ID + .hwlp_start_data_i ( hwloop_start ), + .hwlp_end_data_i ( hwloop_end ), + .hwlp_cnt_data_i ( hwloop_cnt ), + .hwlp_we_i ( hwloop_we ), + .hwlp_regid_i ( hwloop_regid ), + + // from controller + .valid_i ( hwloop_valid ), + + // to hwloop controller + .hwlp_start_addr_o ( hwlp_start_o ), + .hwlp_end_addr_o ( hwlp_end_o ), + .hwlp_counter_o ( hwlp_cnt_o ), + + // from hwloop controller + .hwlp_dec_cnt_i ( hwlp_dec_cnt_i ) + ); + + assign hwloop_valid = instr_valid_i & clear_instr_valid_o & is_hwlp_i; + + + ///////////////////////////////////////////////////////////////////////////////// + // ___ ____ _______ __ ____ ___ ____ _____ _ ___ _ _ _____ // + // |_ _| _ \ | ____\ \/ / | _ \_ _| _ \| ____| | |_ _| \ | | ____| // + // | || | | |_____| _| \ / | |_) | || |_) | _| | | | || \| | _| // + // | || |_| |_____| |___ / \ | __/| || __/| |___| |___ | || |\ | |___ // + // |___|____/ |_____/_/\_\ |_| |___|_| |_____|_____|___|_| \_|_____| // + // // + ///////////////////////////////////////////////////////////////////////////////// + + always_ff @(posedge clk, negedge rst_n) + begin : ID_EX_PIPE_REGISTERS + if (rst_n == 1'b0) + begin + alu_en_ex_o <= '0; + alu_operator_ex_o <= ALU_SLTU; + alu_operand_a_ex_o <= '0; + alu_operand_b_ex_o <= '0; + alu_operand_c_ex_o <= '0; + bmask_a_ex_o <= '0; + bmask_b_ex_o <= '0; + imm_vec_ext_ex_o <= '0; + alu_vec_mode_ex_o <= '0; + alu_clpx_shift_ex_o <= 2'b0; + alu_is_clpx_ex_o <= 1'b0; + alu_is_subrot_ex_o <= 1'b0; + + mult_operator_ex_o <= '0; + mult_operand_a_ex_o <= '0; + mult_operand_b_ex_o <= '0; + mult_operand_c_ex_o <= '0; + mult_en_ex_o <= 1'b0; + mult_sel_subword_ex_o <= 1'b0; + mult_signed_mode_ex_o <= 2'b00; + mult_imm_ex_o <= '0; + + mult_dot_op_a_ex_o <= '0; + mult_dot_op_b_ex_o <= '0; + mult_dot_op_c_ex_o <= '0; + mult_dot_signed_ex_o <= '0; + mult_is_clpx_ex_o <= 1'b0; + mult_clpx_shift_ex_o <= 2'b0; + mult_clpx_img_ex_o <= 1'b0; + + apu_en_ex_o <= '0; + apu_type_ex_o <= '0; + apu_op_ex_o <= '0; + apu_lat_ex_o <= '0; + apu_operands_ex_o[0] <= '0; + apu_operands_ex_o[1] <= '0; + apu_operands_ex_o[2] <= '0; + apu_flags_ex_o <= '0; + apu_waddr_ex_o <= '0; + + + regfile_waddr_ex_o <= 6'b0; + regfile_we_ex_o <= 1'b0; + + regfile_alu_waddr_ex_o <= 6'b0; + regfile_alu_we_ex_o <= 1'b0; + prepost_useincr_ex_o <= 1'b0; + + csr_access_ex_o <= 1'b0; + csr_op_ex_o <= CSR_OP_READ; + + data_we_ex_o <= 1'b0; + data_type_ex_o <= 2'b0; + data_sign_ext_ex_o <= 2'b0; + data_reg_offset_ex_o <= 2'b0; + data_req_ex_o <= 1'b0; + data_load_event_ex_o <= 1'b0; + atop_ex_o <= 5'b0; + buffer_ex_o <= 1'b0; + + data_misaligned_ex_o <= 1'b0; + stack_access_o <= 1'b0; + + pc_ex_o <= '0; + + branch_in_ex_o <= 1'b0; + + end + else if (data_misaligned_i) begin + // misaligned data access case + if (ex_ready_i) + begin // misaligned access case, only unstall alu operands + + // if we are using post increments, then we have to use the + // original value of the register for the second memory access + // => keep it stalled + if (prepost_useincr_ex_o == 1'b1) + begin + alu_operand_a_ex_o <= alu_operand_a; + end + + alu_operand_b_ex_o <= alu_operand_b; + regfile_alu_we_ex_o <= regfile_alu_we_id; + prepost_useincr_ex_o <= prepost_useincr; + + data_misaligned_ex_o <= 1'b1; + stack_access_o <= stack_access; + end + end else if (mult_multicycle_i) begin + mult_operand_c_ex_o <= alu_operand_c; + end + else begin + // normal pipeline unstall case + + if (id_valid_o) + begin // unstall the whole pipeline + + alu_en_ex_o <= alu_en | branch_taken_ex; + if (alu_en | branch_taken_ex) + begin + //this prevents divisions or multicycle instructions to keep the EX stage busy + alu_operator_ex_o <= branch_taken_ex ? ALU_SLTU : alu_operator; + if(~branch_taken_ex) begin + alu_operand_a_ex_o <= alu_operand_a; + alu_operand_b_ex_o <= alu_operand_b; + alu_operand_c_ex_o <= alu_operand_c; + bmask_a_ex_o <= bmask_a_id; + bmask_b_ex_o <= bmask_b_id; + imm_vec_ext_ex_o <= imm_vec_ext_id; + alu_vec_mode_ex_o <= alu_vec_mode; + alu_is_clpx_ex_o <= is_clpx; + alu_clpx_shift_ex_o <= instr[14:13]; + alu_is_subrot_ex_o <= is_subrot; + end + end + + mult_en_ex_o <= mult_en; + if (mult_int_en) begin + mult_operator_ex_o <= mult_operator; + mult_sel_subword_ex_o <= mult_sel_subword; + mult_signed_mode_ex_o <= mult_signed_mode; + mult_operand_a_ex_o <= alu_operand_a; + mult_operand_b_ex_o <= alu_operand_b; + mult_operand_c_ex_o <= alu_operand_c; + mult_imm_ex_o <= mult_imm_id; + end + if (mult_dot_en) begin + mult_operator_ex_o <= mult_operator; + mult_dot_signed_ex_o <= mult_dot_signed; + mult_dot_op_a_ex_o <= alu_operand_a; + mult_dot_op_b_ex_o <= alu_operand_b; + mult_dot_op_c_ex_o <= alu_operand_c; + mult_is_clpx_ex_o <= is_clpx; + mult_clpx_shift_ex_o <= instr[14:13]; + mult_clpx_img_ex_o <= instr[25]; + end + + // APU pipeline + apu_en_ex_o <= apu_en; + if (apu_en) begin + apu_type_ex_o <= apu_type; + apu_op_ex_o <= apu_op; + apu_lat_ex_o <= apu_lat; + apu_operands_ex_o <= apu_operands; + apu_flags_ex_o <= apu_flags; + apu_waddr_ex_o <= apu_waddr; + end + + regfile_we_ex_o <= regfile_we_id; + if (regfile_we_id) begin + regfile_waddr_ex_o <= regfile_waddr_id; + end + + regfile_alu_we_ex_o <= regfile_alu_we_id; + if (regfile_alu_we_id) begin + regfile_alu_waddr_ex_o <= regfile_alu_waddr_id; + end + + prepost_useincr_ex_o <= prepost_useincr; + + csr_access_ex_o <= csr_access; + csr_op_ex_o <= csr_op; + + data_req_ex_o <= data_req_id; + if (data_req_id) + begin // only needed for LSU when there is an active request + data_we_ex_o <= data_we_id; + data_type_ex_o <= data_type_id; + data_sign_ext_ex_o <= data_sign_ext_id; + data_reg_offset_ex_o <= data_reg_offset_id; + data_load_event_ex_o <= data_load_event_id; + atop_ex_o <= atop_id; + buffer_ex_o <= buffer_id; + end else begin + data_load_event_ex_o <= 1'b0; + end + + data_misaligned_ex_o <= 1'b0; + stack_access_o <= stack_access; + + if ((jump_in_id == BRANCH_COND) || data_req_id) begin + pc_ex_o <= pc_id_i; + end + + branch_in_ex_o <= jump_in_id == BRANCH_COND; + end else if(ex_ready_i) begin + // EX stage is ready but we don't have a new instruction for it, + // so we set all write enables to 0, but unstall the pipe + + regfile_we_ex_o <= 1'b0; + + regfile_alu_we_ex_o <= 1'b0; + + csr_op_ex_o <= CSR_OP_READ; + + data_req_ex_o <= 1'b0; + + data_load_event_ex_o <= 1'b0; + + data_misaligned_ex_o <= 1'b0; + stack_access_o <= stack_access; + + branch_in_ex_o <= 1'b0; + + apu_en_ex_o <= 1'b0; + + alu_operator_ex_o <= ALU_SLTU; + + mult_en_ex_o <= 1'b0; + + alu_en_ex_o <= 1'b1; + + end else if (csr_access_ex_o) begin + //In the EX stage there was a CSR access, to avoid multiple + //writes to the RF, disable regfile_alu_we_ex_o. + //Not doing it can overwrite the RF file with the currennt CSR value rather than the old one + regfile_alu_we_ex_o <= 1'b0; + end + end + end + + + // stall control + assign id_ready_o = ((~misaligned_stall) & (~jr_stall) & (~load_stall) & (~apu_stall) & (~csr_apu_stall) & ex_ready_i); + assign id_valid_o = (~halt_id) & id_ready_o; + + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + `ifndef VERILATOR + // make sure that branch decision is valid when jumping + assert property ( + @(posedge clk) (branch_in_ex_o) |-> (branch_decision_i !== 1'bx) ) else begin $display("%t, Branch decision is X in module %m", $time); $stop; end + + // the instruction delivered to the ID stage should always be valid + assert property ( + @(posedge clk) (instr_valid_i & (~illegal_c_insn_i)) |-> (!$isunknown(instr_rdata_i)) ) else $display("Instruction is valid, but has at least one X"); + `endif +endmodule diff --git a/hw/deps/riscv/riscv_if_stage.sv b/hw/deps/riscv/riscv_if_stage.sv new file mode 100644 index 0000000..cef7739 --- /dev/null +++ b/hw/deps/riscv/riscv_if_stage.sv @@ -0,0 +1,428 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Renzo Andri - andrire@student.ethz.ch // +// // +// Additional contributions by: // +// Igor Loi - igor.loi@unibo.it // +// Andreas Traber - atraber@student.ethz.ch // +// Sven Stucki - svstucki@student.ethz.ch // +// // +// Design Name: Instruction Fetch Stage // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Instruction fetch unit: Selection of the next PC, and // +// buffering (sampling) of the read instruction // +// // +//////////////////////////////////////////////////////////////////////////////// + + +import riscv_defines::*; + +module riscv_if_stage +#( + parameter N_HWLP = 2, + parameter RDATA_WIDTH = 32, + parameter FPU = 0 +) +( + input logic clk, + input logic rst_n, + + // Used to calculate the exception offsets + input logic [23:0] m_trap_base_addr_i, + input logic [23:0] u_trap_base_addr_i, + input logic [1:0] trap_addr_mux_i, + // Boot address + input logic [30:0] boot_addr_i, + + // Debug mode halt address + input logic [29:0] dm_halt_addr_i, + + // instruction request control + input logic req_i, + + // instruction cache interface + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [RDATA_WIDTH-1:0] instr_rdata_i, + input logic instr_err_pmp_i, + + // Output of IF Pipeline stage + output logic [N_HWLP-1:0] hwlp_dec_cnt_id_o, // currently served instruction was the target of a hwlp + output logic is_hwlp_id_o, // currently served instruction was the target of a hwlp + output logic instr_valid_id_o, // instruction in IF/ID pipeline is valid + output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding + output logic is_compressed_id_o, // compressed decoder thinks this is a compressed instruction + output logic illegal_c_insn_id_o, // compressed decoder thinks this is an invalid instruction + output logic [31:0] pc_if_o, + output logic [31:0] pc_id_o, + output logic is_fetch_failed_o, + + // Forwarding ports - control signals + input logic clear_instr_valid_i, // clear instruction valid bit in IF/ID pipe + input logic pc_set_i, // set the program counter to a new value + input logic [31:0] mepc_i, // address used to restore PC when the interrupt/exception is served + input logic [31:0] uepc_i, // address used to restore PC when the interrupt/exception is served + + input logic [31:0] depc_i, // address used to restore PC when the debug is served + + input logic [2:0] pc_mux_i, // sel for pc multiplexer + input logic [2:0] exc_pc_mux_i, // selects ISR address + input logic [5:0] m_exc_vec_pc_mux_i, // selects ISR address for vectorized interrupt lines + input logic [5:0] u_exc_vec_pc_mux_i, // selects ISR address for vectorized interrupt lines + + // jump and branch target and decision + input logic [31:0] jump_target_id_i, // jump target address + input logic [31:0] jump_target_ex_i, // jump target address + + // from hwloop controller + input logic [N_HWLP-1:0] [31:0] hwlp_start_i, // hardware loop start addresses + input logic [N_HWLP-1:0] [31:0] hwlp_end_i, // hardware loop end addresses + input logic [N_HWLP-1:0] [31:0] hwlp_cnt_i, // hardware loop counters + + // pipeline stall + input logic halt_if_i, + input logic id_ready_i, + + // misc signals + output logic if_busy_o, // is the IF stage busy fetching instructions? + output logic perf_imiss_o // Instruction Fetch Miss +); + + localparam IGNORE_CAUSE_MSB = 0; // Ignore the MSB of the exception code (effectively mapping the top 32 and bottom 32 IRQs on top of each other) + + // offset FSM + enum logic[0:0] {WAIT, IDLE } offset_fsm_cs, offset_fsm_ns; + + logic if_valid, if_ready; + logic valid; + + // prefetch buffer related signals + logic prefetch_busy; + logic branch_req; + logic [31:0] fetch_addr_n; + + logic fetch_valid; + logic fetch_ready; + logic [31:0] fetch_rdata; + logic [31:0] fetch_addr; + logic is_hwlp_id_q, fetch_is_hwlp; + + logic [31:0] exc_pc; + + // hardware loop related signals + logic hwlp_jump, hwlp_branch; + logic [31:0] hwlp_target; + logic [N_HWLP-1:0] hwlp_dec_cnt, hwlp_dec_cnt_if; + + logic [23:0] trap_base_addr; + logic [5:0] exc_vec_pc_mux; + logic fetch_failed; + + + // exception PC selection mux + always_comb + begin : EXC_PC_MUX + unique case (trap_addr_mux_i) + TRAP_MACHINE: trap_base_addr = m_trap_base_addr_i; + TRAP_USER: trap_base_addr = u_trap_base_addr_i; + default: trap_base_addr = m_trap_base_addr_i; + endcase + + unique case (trap_addr_mux_i) + TRAP_MACHINE: exc_vec_pc_mux = m_exc_vec_pc_mux_i; + TRAP_USER: exc_vec_pc_mux = u_exc_vec_pc_mux_i; + default: exc_vec_pc_mux = m_exc_vec_pc_mux_i; + endcase + + unique case (exc_pc_mux_i) + EXC_PC_EXCEPTION: exc_pc = { trap_base_addr, 8'h0 }; //1.10 all the exceptions go to base address + EXC_PC_IRQ: exc_pc = { trap_base_addr, 1'b0,IGNORE_CAUSE_MSB ? {1'b0, exc_vec_pc_mux[4:0]} : exc_vec_pc_mux[5:0], 2'b0 }; // interrupts are vectored + EXC_PC_DBD: exc_pc = { dm_halt_addr_i, 2'b0 }; + default: exc_pc = { trap_base_addr, 8'h0 }; + endcase + end + + // fetch address selection + always_comb + begin + fetch_addr_n = '0; + + unique case (pc_mux_i) + PC_BOOT: fetch_addr_n = {boot_addr_i, 1'b0}; + PC_JUMP: fetch_addr_n = jump_target_id_i; + PC_BRANCH: fetch_addr_n = jump_target_ex_i; + PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler + PC_MRET: fetch_addr_n = mepc_i; // PC is restored when returning from IRQ/exception + PC_URET: fetch_addr_n = uepc_i; // PC is restored when returning from IRQ/exception + PC_DRET: fetch_addr_n = depc_i; // + PC_FENCEI: fetch_addr_n = pc_id_o + 4; // jump to next instr forces prefetch buffer reload + default:; + endcase + end + + generate + if (RDATA_WIDTH == 32) begin : prefetch_32 + // prefetch buffer, caches a fixed number of instructions + riscv_prefetch_buffer prefetch_buffer_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .req_i ( req_i ), + + .branch_i ( branch_req ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .hwloop_i ( hwlp_jump ), + .hwloop_target_i ( hwlp_target ), + .hwlp_branch_o ( hwlp_branch ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + .is_hwlp_o ( fetch_is_hwlp ), + + // goes to instruction memory / instruction cache + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_err_pmp_i ( instr_err_pmp_i ), + .fetch_failed_o ( fetch_failed ), + .instr_rdata_i ( instr_rdata_i ), + + // Prefetch Buffer Status + .busy_o ( prefetch_busy ) + ); + end else if (RDATA_WIDTH == 128) begin : prefetch_128 + // prefetch buffer, caches a fixed number of instructions + riscv_prefetch_L0_buffer prefetch_buffer_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .req_i ( 1'b1 ), + + .branch_i ( branch_req ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .hwloop_i ( hwlp_jump ), + .hwloop_target_i ( hwlp_target ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + .is_hwlp_o ( fetch_is_hwlp ), + + // goes to instruction memory / instruction cache + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + + // Prefetch Buffer Status + .busy_o ( prefetch_busy ) + ); + + assign hwlp_branch = 1'b0; + assign fetch_failed = 1'b0; + + end + endgenerate + + // offset FSM state + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) begin + offset_fsm_cs <= IDLE; + end else begin + offset_fsm_cs <= offset_fsm_ns; + end + end + + // offset FSM state transition logic + always_comb + begin + offset_fsm_ns = offset_fsm_cs; + + fetch_ready = 1'b0; + branch_req = 1'b0; + valid = 1'b0; + + unique case (offset_fsm_cs) + // no valid instruction data for ID stage + // assume aligned + IDLE: begin + if (req_i) begin + branch_req = 1'b1; + offset_fsm_ns = WAIT; + end + end + + // serving aligned 32 bit or 16 bit instruction, we don't know yet + WAIT: begin + if (fetch_valid) begin + valid = 1'b1; // an instruction is ready for ID stage + + if (req_i && if_valid) begin + fetch_ready = 1'b1; + offset_fsm_ns = WAIT; + end + end + end + + default: begin + offset_fsm_ns = IDLE; + end + endcase + + + // take care of jumps and branches + if (pc_set_i) begin + valid = 1'b0; + + // switch to new PC from ID stage + branch_req = 1'b1; + offset_fsm_ns = WAIT; + end + else begin + if(hwlp_branch) + valid = 1'b0; + end + end + + // Hardware Loops + riscv_hwloop_controller + #( + .N_REGS ( N_HWLP ) + ) + hwloop_controller_i + ( + .current_pc_i ( fetch_addr ), + + .hwlp_jump_o ( hwlp_jump ), + .hwlp_targ_addr_o ( hwlp_target ), + + // from hwloop_regs + .hwlp_start_addr_i ( hwlp_start_i ), + .hwlp_end_addr_i ( hwlp_end_i ), + .hwlp_counter_i ( hwlp_cnt_i ), + + // to hwloop_regs + .hwlp_dec_cnt_o ( hwlp_dec_cnt ), + .hwlp_dec_cnt_id_i ( hwlp_dec_cnt_id_o & {N_HWLP{is_hwlp_id_o}} ) + ); + + + assign pc_if_o = fetch_addr; + + assign if_busy_o = prefetch_busy; + + assign perf_imiss_o = (~fetch_valid) | branch_req; + + + // compressed instruction decoding, or more precisely compressed instruction + // expander + // + // since it does not matter where we decompress instructions, we do it here + // to ease timing closure + logic [31:0] instr_decompressed; + logic illegal_c_insn; + logic instr_compressed_int; + + riscv_compressed_decoder + #( + .FPU(FPU) + ) + compressed_decoder_i + ( + .instr_i ( fetch_rdata ), + .instr_o ( instr_decompressed ), + .is_compressed_o ( instr_compressed_int ), + .illegal_instr_o ( illegal_c_insn ) + ); + + // prefetch -> IF registers + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) + begin + hwlp_dec_cnt_if <= '0; + end + else + begin + if (hwlp_jump) + hwlp_dec_cnt_if <= hwlp_dec_cnt; + end + end + + // IF-ID pipeline registers, frozen when the ID stage is stalled + always_ff @(posedge clk, negedge rst_n) + begin : IF_ID_PIPE_REGISTERS + if (rst_n == 1'b0) + begin + instr_valid_id_o <= 1'b0; + instr_rdata_id_o <= '0; + illegal_c_insn_id_o <= 1'b0; + is_compressed_id_o <= 1'b0; + pc_id_o <= '0; + is_hwlp_id_q <= 1'b0; + hwlp_dec_cnt_id_o <= '0; + is_fetch_failed_o <= 1'b0; + + end + else + begin + + if (if_valid) + begin + instr_valid_id_o <= 1'b1; + instr_rdata_id_o <= instr_decompressed; + illegal_c_insn_id_o <= illegal_c_insn; + is_compressed_id_o <= instr_compressed_int; + pc_id_o <= pc_if_o; + is_hwlp_id_q <= fetch_is_hwlp; + is_fetch_failed_o <= 1'b0; + + if (fetch_is_hwlp) + hwlp_dec_cnt_id_o <= hwlp_dec_cnt_if; + + end else if (clear_instr_valid_i) begin + instr_valid_id_o <= 1'b0; + is_fetch_failed_o <= fetch_failed; + end + + end + end + + assign is_hwlp_id_o = is_hwlp_id_q & instr_valid_id_o; + + assign if_ready = valid & id_ready_i; + assign if_valid = (~halt_if_i) & if_ready; + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + `ifndef VERILATOR + // there should never be a grant when there is no request + assert property ( + @(posedge clk) (instr_gnt_i) |-> (instr_req_o) ) + else $warning("There was a grant without a request"); + `endif +endmodule diff --git a/hw/deps/riscv/riscv_int_controller.sv b/hw/deps/riscv/riscv_int_controller.sv new file mode 100644 index 0000000..b7fea15 --- /dev/null +++ b/hw/deps/riscv/riscv_int_controller.sv @@ -0,0 +1,126 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// // +// Design Name: Interrupt Controller // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Interrupt Controller of the pipelined processor // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; + +module riscv_int_controller +#( + parameter PULP_SECURE = 0 +) +( + input logic clk, + input logic rst_n, + + // irq_req for controller + output logic irq_req_ctrl_o, + output logic irq_sec_ctrl_o, + output logic [5:0] irq_id_ctrl_o, + + // handshake signals to controller + input logic ctrl_ack_i, + input logic ctrl_kill_i, + + // external interrupt lines + input logic irq_pending_i, // level-triggered interrupt inputs + input logic irq_sec_i, // interrupt secure bit from EU + input logic [5:0] irq_id_i, // interrupt id [0,1,....31] + + input logic m_IE_i, // interrupt enable bit from CSR (M mode) + input logic u_IE_i, // interrupt enable bit from CSR (U mode) + input PrivLvl_t current_priv_lvl_i + +); + + enum logic [1:0] { IDLE, IRQ_PENDING, IRQ_DONE} exc_ctrl_cs; + + logic irq_enable_ext; + logic [5:0] irq_id_q; + logic irq_sec_q; + +if(PULP_SECURE) + assign irq_enable_ext = ((u_IE_i | irq_sec_i) & current_priv_lvl_i == PRIV_LVL_U) | (m_IE_i & current_priv_lvl_i == PRIV_LVL_M); +else + assign irq_enable_ext = m_IE_i; + + assign irq_req_ctrl_o = exc_ctrl_cs == IRQ_PENDING; + assign irq_sec_ctrl_o = irq_sec_q; + assign irq_id_ctrl_o = irq_id_q; + + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) begin + + irq_id_q <= '0; + irq_sec_q <= 1'b0; + exc_ctrl_cs <= IDLE; + + end else begin + + unique case (exc_ctrl_cs) + + IDLE: + begin + if(irq_enable_ext & irq_pending_i) begin + exc_ctrl_cs <= IRQ_PENDING; + irq_id_q <= irq_id_i; + irq_sec_q <= irq_sec_i; + end + end + + IRQ_PENDING: + begin + unique case(1'b1) + ctrl_ack_i: + exc_ctrl_cs <= IRQ_DONE; + ctrl_kill_i: + exc_ctrl_cs <= IDLE; + default: + exc_ctrl_cs <= IRQ_PENDING; + endcase + end + + IRQ_DONE: + begin + irq_sec_q <= 1'b0; + exc_ctrl_cs <= IDLE; + end + + endcase + + end + end + + +`ifndef SYNTHESIS + // synopsys translate_off + // evaluate at falling edge to avoid duplicates during glitches + // Removed this message as it pollutes too much the output and makes tests fail + //always_ff @(negedge clk) + //begin + // if (rst_n && exc_ctrl_cs == IRQ_DONE) + // $display("%t: Entering interrupt service routine. [%m]", $time); + //end + // synopsys translate_on +`endif + +endmodule diff --git a/hw/deps/riscv/riscv_load_store_unit.sv b/hw/deps/riscv/riscv_load_store_unit.sv new file mode 100644 index 0000000..0c387b7 --- /dev/null +++ b/hw/deps/riscv/riscv_load_store_unit.sv @@ -0,0 +1,337 @@ +// Copyright 2018 ETH Zurich and 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. + +module riscv_load_store_unit ( + input logic clk_i, + input logic rst_ni, + + // output to data memory + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + input logic data_err_i, + + output logic [31:0] data_addr_o, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic data_buffer_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + + // signals from ex stage + input logic data_we_ex_i, // write enable -> from ex stage + input logic [1:0] data_type_ex_i, // Data type word, halfword, byte -> from ex stage + input logic [31:0] data_wdata_ex_i, // data to write to memory -> from ex stage + input logic [1:0] data_reg_offset_ex_i, // offset inside register for stores -> from ex stage + input logic [1:0] data_sign_ext_ex_i, // sign extension -> from ex stage + + output logic [31:0] data_rdata_ex_o, // requested data -> to ex stage + input logic data_req_ex_i, // data request -> from ex stage + input logic [31:0] operand_a_ex_i, // operand a from RF for address -> from ex stage + input logic [31:0] operand_b_ex_i, // operand b from RF for address -> from ex stage + input logic addr_useincr_ex_i, // use a + b or just a for address -> from ex stage + + input logic data_misaligned_ex_i, // misaligned access in last ld/st -> from ID/EX pipeline + output logic data_misaligned_o, // misaligned access was detected -> to controller + + input logic [5:0] data_atop_ex_i, // atomic instructions signal -> from ex stage + input logic data_buffer_ex_i, + output logic [5:0] data_atop_o, // atomic instruction signal -> core output + + // exception signals + output logic load_err_o, + output logic store_err_o, + + // stall signal + output logic lsu_ready_ex_o, // LSU ready for new data in EX stage + output logic lsu_ready_wb_o, // LSU ready for new data in WB stage + + input logic ex_valid_i, + output logic busy_o +); + + // Calculate shift amount for strobe and data for unaligned accesses. + logic [1:0] shamt; + always_comb begin + shamt = operand_a_ex_i[1:0]; + if (addr_useincr_ex_i) begin + shamt += operand_b_ex_i[1:0]; + end + end + + // Compute byte enable. + always_comb begin + if (data_type_ex_i[1]) begin // writing a single byte + data_be_o = 1'b1; + end else if (data_type_ex_i[0]) begin // writing a half word + data_be_o = 2'b11; + end else begin // writing a full word + data_be_o = 4'b1111; + end + data_be_o <<= shamt; + // Write or read the other part of the word during the second access of an unaligned access. + // FIXME: will not work for 16 bit accesses + if (data_misaligned_ex_i) begin + data_be_o = ~data_be_o; + end + end + + // Latch properties of request to reconstruct response. + logic [3:0] mask_d, mask_q; + logic [1:0] shamt_d, shamt_q; + logic [1:0] type_d, type_q; + logic [1:0] sign_ext_d, sign_ext_q; + logic we_d, we_q; + always_comb begin + mask_d = mask_q; + shamt_d = shamt_q; + sign_ext_d = sign_ext_q; + type_d = type_q; + we_d = we_q; + if (data_req_o && data_gnt_i) begin + mask_d = data_be_o; + shamt_d = shamt; + sign_ext_d = data_sign_ext_ex_i; + type_d = data_type_ex_i; + we_d = data_we_ex_i; + end + end + + // Rotate write data to the left by the shift amount. + always_comb begin + case (shamt) + 2'd0: data_wdata_o = data_wdata_ex_i; + 2'd1: data_wdata_o = {data_wdata_ex_i[23:0], data_wdata_ex_i[31:24]}; + 2'd2: data_wdata_o = {data_wdata_ex_i[15:0], data_wdata_ex_i[31:16]}; + 2'd3: data_wdata_o = {data_wdata_ex_i[ 7:0], data_wdata_ex_i[31: 8]}; + endcase + end + + // Identify responses to misaligned accesses. + enum logic [1:0] { + RespRegular, // response to regular, non-misaligned request + RespMisaligned, // response to first request of a misaligned access -> misaligned response + RespAligned // response to second request of a misaligned access -> aligned response + } resp_state_d, resp_state_q; + always_comb begin + resp_state_d = resp_state_q; + if (data_req_o && data_gnt_i && data_misaligned_o) begin + // When we request misaligned data, the next response is misaligned. + resp_state_d = RespMisaligned; + end else if (data_rvalid_i) begin + // A response to the first request of a misaligned access means the next response is to the + // second request. + resp_state_d = (resp_state_q == RespMisaligned) ? RespAligned : RespRegular; + end + end + + // Reconstruct read data from read response. + logic [31:0] rdata_d, rdata_q; + always_comb begin + rdata_d = rdata_q; + if (data_rvalid_i) begin + // Mask response with byte enable from request. + rdata_d = data_rdata_i & {{8{mask_q[3]}}, {8{mask_q[2]}}, {8{mask_q[1]}}, {8{mask_q[0]}}}; + // Reconstruct misaligned response. + case (resp_state_q) + RespRegular, + RespMisaligned: begin + rdata_d = rdata_d >> 8*shamt_q; + end + RespAligned: begin + rdata_d = (rdata_d << 8*(4 - shamt_q)) | rdata_q; + end + endcase + if (sign_ext_q == 2'b00) begin + // Zero-extend. + if (type_q[1]) begin // single byte + rdata_d = {{24{1'b0}}, rdata_d[ 7:0]}; + end else if (type_q[0]) begin // half word + rdata_d = {{16{1'b0}}, rdata_d[15:0]}; + end + end else if (sign_ext_q == 2'b10) begin + // One-extend. + if (type_q[1]) begin // single byte + rdata_d = {{24{1'b1}}, rdata_d[ 7:0]}; + end else if (type_q[0]) begin // half word + rdata_d = {{16{1'b1}}, rdata_d[15:0]}; + end + end else begin + // Sign-extend. + if (type_q[1]) begin // single byte + rdata_d = {{24{rdata_d[ 7]}}, rdata_d[ 7:0]}; + end else if (type_q[0]) begin // half word + rdata_d = {{16{rdata_d[15]}}, rdata_d[15:0]}; + end + end + end + end + + enum logic [1:0] { + Idle, WaitRValid, WaitRValidExStall, IdleExStall + } state_d, state_q; + + // Main LSU FSM + always_comb begin + state_d = state_q; + data_req_o = 1'b0; + lsu_ready_ex_o = 1'b1; + lsu_ready_wb_o = 1'b1; + + case (state_q) + Idle: begin + // Start here and stay in Idle until request was granted. + data_req_o = data_req_ex_i; + if (data_req_ex_i) begin + lsu_ready_ex_o = 1'b0; + if (data_gnt_i) begin + lsu_ready_ex_o = 1'b1; + if (ex_valid_i) begin + state_d = WaitRValid; + end else begin + state_d = WaitRValidExStall; + end + end + end + end + + WaitRValid: begin + // Wait for rvalid in WB stage and send a new request if there is any. + lsu_ready_wb_o = 1'b0; + if (data_rvalid_i) begin + // We don't have to wait for anything here as we are the only stall source for the WB + // stage. + lsu_ready_wb_o = 1'b1; + data_req_o = data_req_ex_i; + if (data_req_ex_i) begin + lsu_ready_ex_o = 1'b0; + if (data_gnt_i) begin + lsu_ready_ex_o = 1'b1; + if (ex_valid_i) begin + state_d = WaitRValid; + end else begin + state_d = WaitRValidExStall; + end + end else begin + state_d = Idle; + end + end else begin + if (data_rvalid_i) begin + // No request, so go to Idle + state_d = Idle; + end + end + end + end + + WaitRValidExStall: begin + // Wait for rvalid while still in EX stage. We end up here when there was an EX stall, so + // in this cycle we just wait and don't send new requests. + data_req_o = 1'b0; + if (data_rvalid_i) begin + if (ex_valid_i) begin + // We are done and can go back to Idle. The data is safely stored already. + state_d = Idle; + end else begin + // We have to wait until ex_stall is deasserted. + state_d = IdleExStall; + end + end else begin + // We didn't yet receive the rvalid, so we check the ex_stall signal. If we are no longer + // stalled we can change to the "normal" WaitRValid state. + if (ex_valid_i) begin + state_d = WaitRValid; + end + end + end + + IdleExStall: begin + // Wait for us to be unstalled and then change back to Idle state. + if (ex_valid_i) begin + state_d = Idle; + end + end + + default: state_d = Idle; + endcase + end + + // Check for misaligned accesses that need a second memory access. If one is detected, this is + // signaled with data_misaligned_o to the controller, which selectively stalls the pipeline. + always_comb begin + data_misaligned_o = 1'b0; + if (data_req_ex_i && !data_misaligned_ex_i) begin + data_misaligned_o = + (data_type_ex_i == 2'b00 && data_addr_o[1:0] != 2'b00) // misaligned word + || (data_type_ex_i == 2'b01 && data_addr_o[1:0] == 2'b11); // misaligned half word + end + end + + // Generate address from operands. + always_comb begin + data_addr_o = operand_a_ex_i; + if (addr_useincr_ex_i) begin + data_addr_o += operand_b_ex_i; + if (data_misaligned_ex_i) begin + data_addr_o &= 32'hFFFF_FFFC; + end + end + end + + assign busy_o = (state_q == WaitRValid) || (state_q == WaitRValidExStall) + || (state_q == IdleExStall) || (data_req_o); + + // Output to register file + assign data_rdata_ex_o = data_rvalid_i ? rdata_d : rdata_q; + + // Output to data interface + assign data_we_o = data_we_ex_i; + assign data_atop_o = data_atop_ex_i; + assign data_buffer_o = data_buffer_ex_i; + + assign load_err_o = data_gnt_i && data_err_i && ~data_we_o; + assign store_err_o = data_gnt_i && data_err_i && data_we_o; + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + mask_q <= '0; + rdata_q <= '0; + resp_state_q <= RespRegular; + shamt_q <= '0; + sign_ext_q <= '0; + state_q <= Idle; + type_q <= '0; + we_q <= 1'b0; + end else begin + mask_q <= mask_d; + rdata_q <= rdata_d; + resp_state_q <= resp_state_d; + shamt_q <= shamt_d; + sign_ext_q <= sign_ext_d; + state_q <= state_d; + type_q <= type_d; + we_q <= we_d; + end + end + + // Assertions + `ifndef VERILATOR + // Make sure there is no new request when the old one is not yet completely done. + assert property (@(posedge clk_i) state_q == WaitRValid && data_gnt_i |-> data_rvalid_i) + else $warning("It should not be possible to get a grant without an rvalid for the last request!"); + + assert property (@(posedge clk_i) state_q == Idle |-> !data_rvalid_i) + else $warning("There should be no rvalid when the LSU is idle!"); + + // Assert that the address does not contain X when request is sent. + assert property (@(posedge clk_i) data_req_o |-> !$isunknown(data_addr_o)) + else $error("There has been a data request but the address is unknown!"); + `endif +endmodule diff --git a/hw/deps/riscv/riscv_mult.sv b/hw/deps/riscv/riscv_mult.sv new file mode 100644 index 0000000..653392c --- /dev/null +++ b/hw/deps/riscv/riscv_mult.sv @@ -0,0 +1,365 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Matthias Baer - baermatt@student.ethz.ch // +// // +// Additional contributions by: // +// Andreas Traber - atraber@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: Subword multiplier and MAC // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Advanced MAC unit for PULP. // +// added parameter SHARED_DSP_MULT to offload dot-product // +// instructions to the shared unit // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; + +module riscv_mult +#( + parameter SHARED_DSP_MULT = 1 + ) +( + input logic clk, + input logic rst_n, + + input logic enable_i, + input logic [ 2:0] operator_i, + + // integer and short multiplier + input logic short_subword_i, + input logic [ 1:0] short_signed_i, + + input logic [31:0] op_a_i, + input logic [31:0] op_b_i, + input logic [31:0] op_c_i, + + input logic [ 4:0] imm_i, + + + // dot multiplier + input logic [ 1:0] dot_signed_i, + input logic [31:0] dot_op_a_i, + input logic [31:0] dot_op_b_i, + input logic [31:0] dot_op_c_i, + input logic is_clpx_i, + input logic [ 1:0] clpx_shift_i, + input logic clpx_img_i, + + output logic [31:0] result_o, + + output logic multicycle_o, + output logic ready_o, + input logic ex_ready_i +); + + /////////////////////////////////////////////////////////////// + // ___ _ _ _____ ___ ___ ___ ___ __ __ _ _ _ _____ // + // |_ _| \| |_ _| __/ __| __| _ \ | \/ | | | | ||_ _| // + // | || . | | | | _| (_ | _|| / | |\/| | |_| | |__| | // + // |___|_|\_| |_| |___\___|___|_|_\ |_| |_|\___/|____|_| // + // // + /////////////////////////////////////////////////////////////// + + logic [16:0] short_op_a; + logic [16:0] short_op_b; + logic [32:0] short_op_c; + logic [33:0] short_mul; + logic [33:0] short_mac; + logic [31:0] short_round, short_round_tmp; + logic [33:0] short_result; + + logic short_mac_msb1; + logic short_mac_msb0; + + logic [ 4:0] short_imm; + logic [ 1:0] short_subword; + logic [ 1:0] short_signed; + logic short_shift_arith; + logic [ 4:0] mulh_imm; + logic [ 1:0] mulh_subword; + logic [ 1:0] mulh_signed; + logic mulh_shift_arith; + logic mulh_carry_q; + logic mulh_active; + logic mulh_save; + logic mulh_clearcarry; + logic mulh_ready; + + enum logic [2:0] {IDLE, STEP0, STEP1, STEP2, FINISH} mulh_CS, mulh_NS; + + // prepare the rounding value + assign short_round_tmp = (32'h00000001) << imm_i; + assign short_round = (operator_i == MUL_IR) ? {1'b0, short_round_tmp[31:1]} : '0; + + // perform subword selection and sign extensions + assign short_op_a[15:0] = short_subword[0] ? op_a_i[31:16] : op_a_i[15:0]; + assign short_op_b[15:0] = short_subword[1] ? op_b_i[31:16] : op_b_i[15:0]; + + assign short_op_a[16] = short_signed[0] & short_op_a[15]; + assign short_op_b[16] = short_signed[1] & short_op_b[15]; + + assign short_op_c = mulh_active ? $signed({mulh_carry_q, op_c_i}) : $signed(op_c_i); + + assign short_mul = $signed(short_op_a) * $signed(short_op_b); + assign short_mac = $signed(short_op_c) + $signed(short_mul) + $signed(short_round); + + //we use only short_signed_i[0] as it cannot be short_signed_i[1] 1 and short_signed_i[0] 0 + assign short_result = $signed({short_shift_arith & short_mac_msb1, short_shift_arith & short_mac_msb0, short_mac[31:0]}) >>> short_imm; + + // choose between normal short multiplication operation and mulh operation + assign short_imm = mulh_active ? mulh_imm : imm_i; + assign short_subword = mulh_active ? mulh_subword : {2{short_subword_i}}; + assign short_signed = mulh_active ? mulh_signed : short_signed_i; + assign short_shift_arith = mulh_active ? mulh_shift_arith : short_signed_i[0]; + + assign short_mac_msb1 = mulh_active ? short_mac[33] : short_mac[31]; + assign short_mac_msb0 = mulh_active ? short_mac[32] : short_mac[31]; + + + always_comb + begin + mulh_NS = mulh_CS; + mulh_imm = 5'd0; + mulh_subword = 2'b00; + mulh_signed = 2'b00; + mulh_shift_arith = 1'b0; + mulh_ready = 1'b0; + mulh_active = 1'b1; + mulh_save = 1'b0; + mulh_clearcarry = 1'b0; + multicycle_o = 1'b0; + + case (mulh_CS) + IDLE: begin + mulh_active = 1'b0; + mulh_ready = 1'b1; + mulh_save = 1'b0; + if ((operator_i == MUL_H) && enable_i) begin + mulh_ready = 1'b0; + mulh_NS = STEP0; + end + end + + STEP0: begin + multicycle_o = 1'b1; + mulh_imm = 5'd16; + mulh_active = 1'b1; + //AL*BL never overflows + mulh_save = 1'b0; + mulh_NS = STEP1; + //Here always a 32'b unsigned result (no carry) + end + + STEP1: begin + multicycle_o = 1'b1; + //AL*BH is signed iff B is signed + mulh_signed = {short_signed_i[1], 1'b0}; + mulh_subword = 2'b10; + mulh_save = 1'b1; + mulh_shift_arith = 1'b1; + mulh_NS = STEP2; + //Here signed 32'b + unsigned 32'b result. + //Result is a signed 33'b + //Store the carry as it will be used as sign extension, we do + //not shift + end + + STEP2: begin + multicycle_o = 1'b1; + //AH*BL is signed iff A is signed + mulh_signed = {1'b0, short_signed_i[0]}; + mulh_subword = 2'b01; + mulh_imm = 5'd16; + mulh_save = 1'b1; + mulh_clearcarry = 1'b1; + mulh_shift_arith = 1'b1; + mulh_NS = FINISH; + //Here signed 32'b + signed 33'b result. + //Result is a signed 34'b + //We do not store the carries as the bits 34:33 are shifted back, so we clear it + end + + FINISH: begin + mulh_signed = short_signed_i; + mulh_subword = 2'b11; + mulh_ready = 1'b1; + if (ex_ready_i) + mulh_NS = IDLE; + end + endcase + end + + always_ff @(posedge clk, negedge rst_n) + begin + if (~rst_n) + begin + mulh_CS <= IDLE; + mulh_carry_q <= 1'b0; + end else begin + mulh_CS <= mulh_NS; + + if (mulh_save) + mulh_carry_q <= ~mulh_clearcarry & short_mac[32]; + else if (ex_ready_i) // clear carry when we are going to the next instruction + mulh_carry_q <= 1'b0; + end + end + + // 32x32 = 32-bit multiplier + logic [31:0] int_op_a_msu; + logic [31:0] int_op_b_msu; + logic [31:0] int_result; + + logic int_is_msu; + + assign int_is_msu = (operator_i == MUL_MSU32); // TODO: think about using a separate signal here, could prevent some switching + + assign int_op_a_msu = op_a_i ^ {32{int_is_msu}}; + assign int_op_b_msu = op_b_i & {32{int_is_msu}}; + + assign int_result = $signed(op_c_i) + $signed(int_op_b_msu) + $signed(int_op_a_msu) * $signed(op_b_i); + + /////////////////////////////////////////////// + // ___ ___ _____ __ __ _ _ _ _____ // + // | \ / _ \_ _| | \/ | | | | ||_ _| // + // | |) | (_) || | | |\/| | |_| | |__| | // + // |___/ \___/ |_| |_| |_|\___/|____|_| // + // // + /////////////////////////////////////////////// + + logic [31:0] dot_char_result; + logic [32:0] dot_short_result; + logic [31:0] accumulator; + logic [15:0] clpx_shift_result; + + generate + if (SHARED_DSP_MULT == 0) begin + + logic [3:0][ 8:0] dot_char_op_a; + logic [3:0][ 8:0] dot_char_op_b; + logic [3:0][17:0] dot_char_mul; + + logic [1:0][16:0] dot_short_op_a; + logic [1:0][16:0] dot_short_op_b; + logic [1:0][33:0] dot_short_mul; + logic [16:0] dot_short_op_a_1_neg; //to compute -rA[31:16]*rB[31:16] -> (!rA[31:16] + 1)*rB[31:16] = !rA[31:16]*rB[31:16] + rB[31:16] + logic [31:0] dot_short_op_b_ext; + + assign dot_char_op_a[0] = {dot_signed_i[1] & dot_op_a_i[ 7], dot_op_a_i[ 7: 0]}; + assign dot_char_op_a[1] = {dot_signed_i[1] & dot_op_a_i[15], dot_op_a_i[15: 8]}; + assign dot_char_op_a[2] = {dot_signed_i[1] & dot_op_a_i[23], dot_op_a_i[23:16]}; + assign dot_char_op_a[3] = {dot_signed_i[1] & dot_op_a_i[31], dot_op_a_i[31:24]}; + + assign dot_char_op_b[0] = {dot_signed_i[0] & dot_op_b_i[ 7], dot_op_b_i[ 7: 0]}; + assign dot_char_op_b[1] = {dot_signed_i[0] & dot_op_b_i[15], dot_op_b_i[15: 8]}; + assign dot_char_op_b[2] = {dot_signed_i[0] & dot_op_b_i[23], dot_op_b_i[23:16]}; + assign dot_char_op_b[3] = {dot_signed_i[0] & dot_op_b_i[31], dot_op_b_i[31:24]}; + + assign dot_char_mul[0] = $signed(dot_char_op_a[0]) * $signed(dot_char_op_b[0]); + assign dot_char_mul[1] = $signed(dot_char_op_a[1]) * $signed(dot_char_op_b[1]); + assign dot_char_mul[2] = $signed(dot_char_op_a[2]) * $signed(dot_char_op_b[2]); + assign dot_char_mul[3] = $signed(dot_char_op_a[3]) * $signed(dot_char_op_b[3]); + + assign dot_char_result = $signed(dot_char_mul[0]) + $signed(dot_char_mul[1]) + + $signed(dot_char_mul[2]) + $signed(dot_char_mul[3]) + + $signed(dot_op_c_i); + + + assign dot_short_op_a[0] = {dot_signed_i[1] & dot_op_a_i[15], dot_op_a_i[15: 0]}; + assign dot_short_op_a[1] = {dot_signed_i[1] & dot_op_a_i[31], dot_op_a_i[31:16]}; + assign dot_short_op_a_1_neg = dot_short_op_a[1] ^ {17{(is_clpx_i & ~clpx_img_i)}}; //negates whether clpx_img_i is 0 or 1, only REAL PART needs to be negated + + assign dot_short_op_b[0] = (is_clpx_i & clpx_img_i) ? {dot_signed_i[0] & dot_op_b_i[31], dot_op_b_i[31:16]} : {dot_signed_i[0] & dot_op_b_i[15], dot_op_b_i[15: 0]}; + assign dot_short_op_b[1] = (is_clpx_i & clpx_img_i) ? {dot_signed_i[0] & dot_op_b_i[15], dot_op_b_i[15: 0]} : {dot_signed_i[0] & dot_op_b_i[31], dot_op_b_i[31:16]}; + + assign dot_short_mul[0] = $signed(dot_short_op_a[0]) * $signed(dot_short_op_b[0]); + assign dot_short_mul[1] = $signed(dot_short_op_a_1_neg) * $signed(dot_short_op_b[1]); + + assign dot_short_op_b_ext = $signed(dot_short_op_b[1]); + assign accumulator = is_clpx_i ? dot_short_op_b_ext & {32{~clpx_img_i}} : $signed(dot_op_c_i); + + assign dot_short_result = $signed(dot_short_mul[0][31:0]) + $signed(dot_short_mul[1][31:0]) + $signed(accumulator); + assign clpx_shift_result = $signed(dot_short_result[31:15])>>>clpx_shift_i; + + end else begin + assign dot_char_result = '0; + assign dot_short_result = '0; + end + endgenerate + + //////////////////////////////////////////////////////// + // ____ _ _ __ __ // + // | _ \ ___ ___ _ _| | |_ | \/ |_ ___ __ // + // | |_) / _ \/ __| | | | | __| | |\/| | | | \ \/ / // + // | _ < __/\__ \ |_| | | |_ | | | | |_| |> < // + // |_| \_\___||___/\__,_|_|\__| |_| |_|\__,_/_/\_\ // + // // + //////////////////////////////////////////////////////// + + always_comb + begin + result_o = '0; + + unique case (operator_i) + MUL_MAC32, MUL_MSU32: result_o = int_result[31:0]; + + MUL_I, MUL_IR, MUL_H: result_o = short_result[31:0]; + + MUL_DOT8: result_o = dot_char_result[31:0]; + MUL_DOT16: begin + if(is_clpx_i) begin + if(clpx_img_i) begin + result_o[31:16] = clpx_shift_result; + result_o[15:0] = dot_op_c_i[15:0]; + end else begin + result_o[15:0] = clpx_shift_result; + result_o[31:16] = dot_op_c_i[31:16]; + end + end else begin + result_o = dot_short_result[31:0]; + end + end + + default: ; // default case to suppress unique warning + endcase + end + + assign ready_o = mulh_ready; + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + + // check multiplication result for mulh + `ifndef VERILATOR + assert property ( + @(posedge clk) ((mulh_CS == FINISH) && (operator_i == MUL_H) && (short_signed_i == 2'b11)) + |-> + (result_o == (($signed({{32{op_a_i[31]}}, op_a_i}) * $signed({{32{op_b_i[31]}}, op_b_i})) >>> 32) ) ); + + // check multiplication result for mulhsu + assert property ( + @(posedge clk) ((mulh_CS == FINISH) && (operator_i == MUL_H) && (short_signed_i == 2'b01)) + |-> + (result_o == (($signed({{32{op_a_i[31]}}, op_a_i}) * {32'b0, op_b_i}) >> 32) ) ); + + // check multiplication result for mulhu + assert property ( + @(posedge clk) ((mulh_CS == FINISH) && (operator_i == MUL_H) && (short_signed_i == 2'b00)) + |-> + (result_o == (({32'b0, op_a_i} * {32'b0, op_b_i}) >> 32) ) ); + `endif +endmodule diff --git a/hw/deps/riscv/riscv_pmp.sv b/hw/deps/riscv/riscv_pmp.sv new file mode 100644 index 0000000..c8622d5 --- /dev/null +++ b/hw/deps/riscv/riscv_pmp.sv @@ -0,0 +1,810 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: BASIC MPU // +// Project Name: RISCV // +// Language: SystemVerilog // +// // +// Description: BASIC MPU: it suppoerts NA4, DIS, NAPOT and TOR // +// NAPOT can be configured from 8B to 4GB // +// Number of RULES is parametric, and TOR and NAPOT can be // +// disabled. // +// // +//////////////////////////////////////////////////////////////////////////////// + + + +`define RULE_0 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xxxxxxx0 +`define RULE_1 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xxxxxx01 +`define RULE_2 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xxxxx011 +`define RULE_3 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xxxx0111 +`define RULE_4 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xxx01111 +`define RULE_5 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_xx011111 +`define RULE_6 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_x0111111 +`define RULE_7 32'bxxxxxxxx_xxxxxxxx_xxxxxxxx_01111111 +`define RULE_8 32'bxxxxxxxx_xxxxxxxx_xxxxxxx0_11111111 +`define RULE_9 32'bxxxxxxxx_xxxxxxxx_xxxxxx01_11111111 +`define RULE_10 32'bxxxxxxxx_xxxxxxxx_xxxxx011_11111111 +`define RULE_11 32'bxxxxxxxx_xxxxxxxx_xxxx0111_11111111 +`define RULE_12 32'bxxxxxxxx_xxxxxxxx_xxx01111_11111111 +`define RULE_13 32'bxxxxxxxx_xxxxxxxx_xx011111_11111111 +`define RULE_14 32'bxxxxxxxx_xxxxxxxx_x0111111_11111111 +`define RULE_15 32'bxxxxxxxx_xxxxxxxx_01111111_11111111 +`define RULE_16 32'bxxxxxxxx_xxxxxxx0_11111111_11111111 +`define RULE_17 32'bxxxxxxxx_xxxxxx01_11111111_11111111 +`define RULE_18 32'bxxxxxxxx_xxxxx011_11111111_11111111 +`define RULE_19 32'bxxxxxxxx_xxxx0111_11111111_11111111 +`define RULE_20 32'bxxxxxxxx_xxx01111_11111111_11111111 +`define RULE_21 32'bxxxxxxxx_xx011111_11111111_11111111 +`define RULE_22 32'bxxxxxxxx_x0111111_11111111_11111111 +`define RULE_23 32'bxxxxxxxx_01111111_11111111_11111111 +`define RULE_24 32'bxxxxxxx0_11111111_11111111_11111111 +`define RULE_25 32'bxxxxxx01_11111111_11111111_11111111 +`define RULE_26 32'bxxxxx011_11111111_11111111_11111111 +`define RULE_27 32'bxxxx0111_11111111_11111111_11111111 +`define RULE_28 32'bxxx01111_11111111_11111111_11111111 +`define RULE_29 32'bxx011111_11111111_11111111_11111111 +`define RULE_30 32'bx0111111_11111111_11111111_11111111 +`define RULE_31 32'b01111111_11111111_11111111_11111111 + + + +`define EN_NAPOT_RULE_8B /* 0 */ +`define EN_NAPOT_RULE_16B /* 1 */ +`define EN_NAPOT_RULE_32B /* 2 */ +`define EN_NAPOT_RULE_64B /* 3 */ +`define EN_NAPOT_RULE_128B /* 4 */ +`define EN_NAPOT_RULE_256B /* 5 */ +`define EN_NAPOT_RULE_512B /* 6 */ +`define EN_NAPOT_RULE_1KB /* 7 */ +`define EN_NAPOT_RULE_2KB /* 8 */ +`define EN_NAPOT_RULE_4KB /* 9 */ +`define EN_NAPOT_RULE_8KB /* 10 */ +`define EN_NAPOT_RULE_16KB /* 11 */ +`define EN_NAPOT_RULE_32KB /* 12 */ +`define EN_NAPOT_RULE_64KB /* 13 */ +`define EN_NAPOT_RULE_128KB /* 14 */ +`define EN_NAPOT_RULE_256KB /* 15 */ +`define EN_NAPOT_RULE_512KB /* 16 */ +`define EN_NAPOT_RULE_1MB /* 17 */ +`define EN_NAPOT_RULE_2MB /* 18 */ +`define EN_NAPOT_RULE_4MB /* 19 */ +`define EN_NAPOT_RULE_8MB /* 20 */ +`define EN_NAPOT_RULE_16MB /* 21 */ +`define EN_NAPOT_RULE_32MB /* 22 */ +`define EN_NAPOT_RULE_64MB /* 23 */ +`define EN_NAPOT_RULE_128MB /* 24 */ +`define EN_NAPOT_RULE_256MB /* 25 */ +`define EN_NAPOT_RULE_512MB /* 26 */ +`define EN_NAPOT_RULE_1GB /* 27 */ +`define EN_NAPOT_RULE_2GB /* 28 */ +`define EN_NAPOT_RULE_4GB /* 29 */ +`define EN_NAPOT_RULE_8GB /* 30 */ +`define EN_NAPOT_RULE_16GB /* 31 */ + + +`define ENABLE_NAPOT +`define ENABLE_TOR + +//`define DEBUG_RULE + +import riscv_defines::*; + +module riscv_pmp +#( + parameter N_PMP_ENTRIES = 16 +) +( + input logic clk, + input logic rst_n, + + input PrivLvl_t pmp_privil_mode_i, + + input logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_i, + input logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_i, + + + // data side : if TO pipeline + input logic data_req_i, + input logic [31:0] data_addr_i, + input logic data_we_i, + output logic data_gnt_o, + // if to Memory + output logic data_req_o, + input logic data_gnt_i, + output logic [31:0] data_addr_o, + output logic data_err_o, + input logic data_err_ack_i, + + + // fetch side : if TO pipeline + input logic instr_req_i, + input logic [31:0] instr_addr_i, + output logic instr_gnt_o, + // fetch to PF buffer + output logic instr_req_o, + input logic instr_gnt_i, + output logic [31:0] instr_addr_o, + output logic instr_err_o +); + + + logic [N_PMP_ENTRIES-1:0] EN_rule; + logic [N_PMP_ENTRIES-1:0] R_rule; + logic [N_PMP_ENTRIES-1:0] W_rule; + logic [N_PMP_ENTRIES-1:0] X_rule; + logic [N_PMP_ENTRIES-1:0][1:0] MODE_rule; + logic [N_PMP_ENTRIES-1:0][1:0] WIRI_rule; + logic [N_PMP_ENTRIES-1:0][1:0] LOCK_rule; + logic [N_PMP_ENTRIES-1:0][31:0] mask_addr; + + logic [N_PMP_ENTRIES-1:0][31:0] start_addr; + logic [N_PMP_ENTRIES-1:0][31:0] stop_addr; + logic [N_PMP_ENTRIES-1:0] data_match_region; + logic [N_PMP_ENTRIES-1:0] instr_match_region; + logic data_err_int; + genvar i; + int unsigned j,k; + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ██████╗ ██╗ ██╗██╗ ███████╗ ███████╗██╗ ██╗██████╗ █████╗ ███╗ ██╗███████╗██╗ ██████╗ ███╗ ██╗ // + // ██╔══██╗██║ ██║██║ ██╔════╝ ██╔════╝╚██╗██╔╝██╔══██╗██╔══██╗████╗ ██║██╔════╝██║██╔═══██╗████╗ ██║ // + // ██████╔╝██║ ██║██║ █████╗ █████╗ ╚███╔╝ ██████╔╝███████║██╔██╗ ██║███████╗██║██║ ██║██╔██╗ ██║ // + // ██╔══██╗██║ ██║██║ ██╔══╝ ██╔══╝ ██╔██╗ ██╔═══╝ ██╔══██║██║╚██╗██║╚════██║██║██║ ██║██║╚██╗██║ // + // ██║ ██║╚██████╔╝███████╗███████╗ ███████╗██╔╝ ██╗██║ ██║ ██║██║ ╚████║███████║██║╚██████╔╝██║ ╚████║ // + // ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝ // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + generate + for(i=0;i %8h", i , start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end +`endif + + + 2'b10: + begin : NA4_MODE + EN_rule[i] = 1'b1; + stop_addr[i] = pmp_addr_i[i]; + start_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NA4[%d] %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + +`ifdef ENABLE_NAPOT + 2'b11: + begin : NAPOT_MODE + EN_rule[i] = 1'b1; + mask_addr[i] = 32'hFFFF_FFFF; + stop_addr[i] = pmp_addr_i[i]; + start_addr[i] = pmp_addr_i[i]; + + + + casex(pmp_addr_i[i]) + + `ifdef EN_NAPOT_RULE_8B + `RULE_0: + begin: BYTE_ALIGN_8B + mask_addr[i] = 32'hFFFF_FFFE; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_8B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_16B + `RULE_1: + begin: BYTE_ALIGN_16B + mask_addr[i] = 32'hFFFF_FFFC; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_16B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_32B + `RULE_2: + begin: BYTE_ALIGN_32B + mask_addr[i] = 32'hFFFF_FFF8; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_32B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_64B + `RULE_3: + begin: BYTE_ALIGN_64B + mask_addr[i] = 32'hFFFF_FFF0; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_64B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + + `ifdef EN_NAPOT_RULE_128B + `RULE_4: + begin: BYTE_ALIGN_128B + mask_addr[i] = 32'hFFFF_FFE0; + start_addr[i] = pmp_addr_i[i] & 32'hFFFF_FFE0; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_128B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_256B + `RULE_5: + begin: BYTE_ALIGN_256B + mask_addr[i] = 32'hFFFF_FFC0; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_256B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_512B + `RULE_6: + begin: BYTE_ALIGN_512B + mask_addr[i] = 32'hFFFF_FF80; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_512B: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_1KB + `RULE_7: + begin: BYTE_ALIGN_1KB + mask_addr[i] = 32'hFFFF_FF00; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_1KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + + `ifdef EN_NAPOT_RULE_2KB + `RULE_8: + begin: BYTE_ALIGN_2KB + mask_addr[i] = 32'hFFFF_FE00; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_2K: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_4KB + `RULE_9: + begin: BYTE_ALIGN_4KB + mask_addr[i] = 32'hFFFF_FC00; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_4KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_8KB + `RULE_10: + begin: BYTE_ALIGN_8KB + mask_addr[i] = 32'hFFFF_F800; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_8KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_16KB + `RULE_11: + begin: BYTE_ALIGN_16KB + mask_addr[i] = 32'hFFFF_F000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_16KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + + `ifdef EN_NAPOT_RULE_32KB + `RULE_12: + begin: BYTE_ALIGN_32KB + mask_addr[i] = 32'hFFFF_E000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_32KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_64KB + `RULE_13: + begin: BYTE_ALIGN_64KB + mask_addr[i] = 32'hFFFF_C000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_64KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_128KB + `RULE_14: + begin: BYTE_ALIGN_128KB + mask_addr[i] = 32'hFFFF_8000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_128KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_256KB + `RULE_15: + begin: BYTE_ALIGN_256KB + mask_addr[i] = 32'hFFFF_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_256KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + + `ifdef EN_NAPOT_RULE_512KB + `RULE_16: + begin: BYTE_ALIGN_512KB + mask_addr[i] = 32'hFFFE_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_512KB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_1MB + `RULE_17: + begin: BYTE_ALIGN_1MB + mask_addr[i] = 32'hFFFC_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_1MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_2MB + `RULE_18: + begin: BYTE_ALIGN_2MB + mask_addr[i] = 32'hFFF8_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_2MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_4MB + `RULE_19: + begin: BYTE_ALIGN_4MB + mask_addr[i] = 32'hFFF0_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_4MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + `ifdef EN_NAPOT_RULE_8MB + `RULE_20: + begin: BYTE_ALIGN_8MB + mask_addr[i] = 32'hFFE0_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_8MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_16MB + `RULE_21: + begin: BYTE_ALIGN_16MB + mask_addr[i] = 32'hFFC0_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_16MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_32MB + `RULE_22: + begin: BYTE_ALIGN_32MB + mask_addr[i] = 32'hFF80_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_32MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + `ifdef EN_NAPOT_RULE_64MB + `RULE_23: + begin: BYTE_ALIGN_64MB + mask_addr[i] = 32'hFF00_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + `ifdef DEBUG_RULE $display(" NAPOT[%d] --> BYTE_ALIGN_64MB: %8h<-- addr --> %8h", i, start_addr[i]<<2, stop_addr[i]<<2 ); `endif + end + `endif + + + + `ifdef EN_NAPOT_RULE_128MB + `RULE_24: + begin: BYTE_ALIGN_128MB + mask_addr[i] = 32'hFE00_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + `ifdef EN_NAPOT_RULE_256MB + `RULE_25: + begin: BYTE_ALIGN_256MB + mask_addr[i] = 32'hFC00_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + `ifdef EN_NAPOT_RULE_512MB + `RULE_26: + begin: BYTE_ALIGN_512MB + mask_addr[i] = 32'hF800_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + `ifdef EN_NAPOT_RULE_1GB + `RULE_27: + begin: BYTE_ALIGN_1GB + mask_addr[i] = 32'hF000_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + + + + `ifdef EN_NAPOT_RULE_2GB + `RULE_28: + begin: BYTE_ALIGN_2GB + mask_addr[i] = 32'hE000_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + + `ifdef EN_NAPOT_RULE_4GB + `RULE_29: + begin: BYTE_ALIGN_4GB + mask_addr[i] = 32'hC000_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + + `ifdef EN_NAPOT_RULE_8GB + `RULE_30: + begin: BYTE_ALIGN_8GB + mask_addr[i] = 32'h8000_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + + `ifdef EN_NAPOT_RULE_16GB + `RULE_31: + begin: BYTE_ALIGN_16GB + mask_addr[i] = 32'h0000_0000; + start_addr[i] = pmp_addr_i[i] & mask_addr[i]; + stop_addr[i] = pmp_addr_i[i]; + end + `endif + default: + begin: INVALID_RULE + EN_rule[i] = 1'b0; + start_addr[i] = '0; + stop_addr[i] = '0; + end + + endcase + + + end +`endif + + default: + begin: DEFAULT_DISABLED + EN_rule[i] = 1'b0; + start_addr[i] = '0; + stop_addr[i] = '0; + end + + endcase + end + end + endgenerate + + + /////////////////////////////////////////////////////////////////////////////////////////////// + // ██████╗ ██╗ ██╗██╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗███████╗ // + // ██╔══██╗██║ ██║██║ ██╔════╝ ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝██╔════╝ // + // ██████╔╝██║ ██║██║ █████╗ ██║ ███████║█████╗ ██║ █████╔╝ ███████╗ // + // ██╔══██╗██║ ██║██║ ██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ╚════██║ // + // ██║ ██║╚██████╔╝███████╗███████╗███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗███████║ // + // ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ // + /////////////////////////////////////////////////////////////////////////////////////////////// + + + + + always_comb + begin + for(j=0;j= start_addr[j]) && ( data_addr_i[31:2] < stop_addr[j]) ) + begin + data_match_region[j] = 1'b1; + `ifdef DEBUG_RULE $display("HIT on TOR RULE %d: [%8h] <= data_addr_i [%8h] <= [%8h], RULE=%2h, X=%b, W=%b, R=%d", j, (start_addr[j])>>2 , data_addr_i , (stop_addr[j])>>2, pmp_cfg_i[j][4:3], X_rule[j], W_rule[j], R_rule[j]); `endif + end + else + begin + data_match_region[j] = 1'b0; + end + end + `endif + + 2'b10: + begin : NA4_CHECK_DATA + if ( data_addr_i[31:2] == start_addr[j][29:0] ) + begin + data_match_region[j] = 1'b1; + `ifdef DEBUG_RULE $display("HIT on NA4 RULE %d: [%8h] == [%8h] , RULE=%2h, X=%b, W=%b, R=%d", j, (start_addr[j])>>2 , data_addr_i , pmp_cfg_i[j][4:3], X_rule[j], W_rule[j], R_rule[j]); `endif + end + else + begin + data_match_region[j] = 1'b0; + end + end + + `ifdef ENABLE_NAPOT + 2'b11: + begin : NAPOT_CHECK_DATA + //$display("Checking NAPOT RULE [%d]: %8h, == %8h", j, data_addr_i[31:2] & mask_addr[j][29:0], start_addr[j][29:0]); + if ( (data_addr_i[31:2] & mask_addr[j][31:2]) == start_addr[j][31:2] ) + begin + data_match_region[j] = 1'b1; + end + else + begin + data_match_region[j] = 1'b0; + //$display("NO MACHING NAPOT: %8h, == %8h", (data_addr_i[31:2] & mask_addr[j][29:0]), start_addr[j][29:0]); + end + end + `endif + + default: + begin + data_match_region[j] = 1'b0; + end + endcase // MODE_rule[j] + + end + else + begin + data_match_region[j] = 1'b0; + end + + end + end + + assign data_addr_o = data_addr_i; + + always_comb + begin + if(pmp_privil_mode_i == PRIV_LVL_M) + begin + data_req_o = data_req_i; + data_gnt_o = data_gnt_i; + data_err_int = 1'b0; + + end + else + begin + if(|data_match_region == 1'b0) + begin + data_req_o = 1'b0; + data_err_int = data_req_i; + data_gnt_o = 1'b0; + end + else + begin + data_req_o = data_req_i; + data_err_int = 1'b0; + data_gnt_o = data_gnt_i; + end + end + end + + + enum logic {IDLE, GIVE_ERROR} data_err_state_q, data_err_state_n; + + always_comb + begin + data_err_o = 1'b0; + data_err_state_n = data_err_state_q; + unique case(data_err_state_q) + + IDLE: + begin + if(data_err_int) + data_err_state_n = GIVE_ERROR; + end + + GIVE_ERROR: + begin + data_err_o = 1'b1; + if(data_err_ack_i) + data_err_state_n = IDLE; + end + + default: ; + endcase + end + + + always_ff @(posedge clk or negedge rst_n) begin + if(~rst_n) begin + data_err_state_q <= IDLE; + end else begin + data_err_state_q <= data_err_state_n; + end + end + + + always_comb + begin + for(k=0;k= start_addr[k]) && ( instr_addr_i[31:2] < stop_addr[k]) ) + begin + instr_match_region[k] = 1'b1; + `ifdef DEBUG_RULE $display("HIT on TOR RULE %d: [%8h] <= data_addr_i [%8h] <= [%8h], RULE=%2h, X=%b, W=%b, R=%d", k, (start_addr[k])>>2 , data_addr_i , (stop_addr[k])>>2, pmp_cfg_i[k][4:3], X_rule[k], W_rule[k], R_rule[k]); `endif + end + else + begin + instr_match_region[k] = 1'b0; + end + end + `endif + + 2'b10: + begin : NA4_CHECK + if ( instr_addr_i[31:2] == start_addr[k][29:0] ) + begin + instr_match_region[k] = 1'b1; + `ifdef DEBUG_RULE $display("HIT on NA4 RULE %d: [%8h] == [%8h] , RULE=%2h, X=%b, W=%b, R=%d", k, (start_addr[k])>>2 , data_addr_i , pmp_cfg_i[k][4:3], X_rule[k], W_rule[k], R_rule[k]); `endif + end + else + begin + instr_match_region[k] = 1'b0; + end + end + + `ifdef ENABLE_NAPOT + 2'b11: + begin + if ( (instr_addr_i[31:2] & mask_addr[k][31:2]) == start_addr[k][31:2] ) + begin + instr_match_region[k] = 1'b1; + end + else + begin + instr_match_region[k] = 1'b0; + end + end + `endif + + default: + begin + instr_match_region[k] = 1'b0; + end + endcase // MODE_rule[i] + +/* if ( ( instr_addr_i[31:2] >= start_addr[k]) && ( instr_addr_i[31:2] <= stop_addr[k]) ) + begin + instr_match_region[k] = 1'b1; + end + else + begin + instr_match_region[k] = 1'b0; + end*/ + end + else + begin + instr_match_region[k] = 1'b0; + end + + + end + end + + assign instr_addr_o = instr_addr_i; + + always_comb + begin + if(pmp_privil_mode_i == PRIV_LVL_M) + begin + instr_req_o = instr_req_i; + instr_gnt_o = instr_gnt_i; + instr_err_o = 1'b0; + + end + else + begin + if(|instr_match_region == 1'b0) + begin + instr_req_o = 1'b0; + instr_err_o = instr_req_i; + instr_gnt_o = 1'b0; + end + else + begin + instr_req_o = instr_req_i; + instr_err_o = 1'b0; + instr_gnt_o = instr_gnt_i; + end + end + end + + +endmodule diff --git a/hw/deps/riscv/riscv_popcnt.sv b/hw/deps/riscv/riscv_popcnt.sv new file mode 100644 index 0000000..69c7ee6 --- /dev/null +++ b/hw/deps/riscv/riscv_popcnt.sv @@ -0,0 +1,63 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Andreas Traber - atraber@student.ethz.ch // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: riscv_popcnt // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Count the number of '1's in a word // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_popcnt +( + input logic [31:0] in_i, + output logic [5: 0] result_o +); + + logic [15:0][1:0] cnt_l1; + logic [ 7:0][2:0] cnt_l2; + logic [ 3:0][3:0] cnt_l3; + logic [ 1:0][4:0] cnt_l4; + + genvar l, m, n, p; + generate for(l = 0; l < 16; l++) + begin + assign cnt_l1[l] = {1'b0, in_i[2*l]} + {1'b0, in_i[2*l + 1]}; + end + endgenerate + + generate for(m = 0; m < 8; m++) + begin + assign cnt_l2[m] = {1'b0, cnt_l1[2*m]} + {1'b0, cnt_l1[2*m + 1]}; + end + endgenerate + + generate for(n = 0; n < 4; n++) + begin + assign cnt_l3[n] = {1'b0, cnt_l2[2*n]} + {1'b0, cnt_l2[2*n + 1]}; + end + endgenerate + + generate for(p = 0; p < 2; p++) + begin + assign cnt_l4[p] = {1'b0, cnt_l3[2*p]} + {1'b0, cnt_l3[2*p + 1]}; + end + endgenerate + + assign result_o = {1'b0, cnt_l4[0]} + {1'b0, cnt_l4[1]}; + +endmodule diff --git a/hw/deps/riscv/riscv_prefetch_L0_buffer.sv b/hw/deps/riscv/riscv_prefetch_L0_buffer.sv new file mode 100644 index 0000000..b2f2f44 --- /dev/null +++ b/hw/deps/riscv/riscv_prefetch_L0_buffer.sv @@ -0,0 +1,579 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Igor Loi - igor.loi@unibo.it // +// // +// Additional contributions by: // +// Andreas Traber - atraber@iis.ee.ethz.ch // +// // +// Design Name: Prefetcher Buffer for 128 bit memory interface // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Prefetch Buffer that caches instructions. This cuts overly // +// long critical paths to the instruction cache // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_prefetch_L0_buffer +#( + parameter RDATA_IN_WIDTH = 128 +) +( + input logic clk, + input logic rst_n, + + input logic req_i, + + input logic branch_i, + input logic [31:0] addr_i, + + input logic hwloop_i, + input logic [31:0] hwloop_target_i, + + input logic ready_i, + output logic valid_o, + output logic [31:0] rdata_o, + output logic [31:0] addr_o, + output logic is_hwlp_o, // is set when the currently served data is from a hwloop + + // goes to instruction memory / instruction cache + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [RDATA_IN_WIDTH/32-1:0][31:0] instr_rdata_i, + + // Prefetch Buffer Status + output logic busy_o +); + + logic busy_L0; + + enum logic [3:0] { IDLE, BRANCHED, + HWLP_WAIT_GNT, HWLP_GRANTED, HWLP_GRANTED_WAIT, HWLP_FETCH_DONE, + NOT_VALID, NOT_VALID_GRANTED, NOT_VALID_CROSS, NOT_VALID_CROSS_GRANTED, + VALID, VALID_CROSS, VALID_GRANTED, VALID_FETCH_DONE } CS, NS; + + logic do_fetch; + logic do_hwlp, do_hwlp_int; + logic use_last; + logic save_rdata_last; + logic use_hwlp; + logic save_rdata_hwlp; + logic valid; + + logic hwlp_is_crossword; + logic is_crossword; + logic next_is_crossword; + logic next_valid; + logic next_upper_compressed; + logic fetch_possible; + logic upper_is_compressed; + + logic [31:0] addr_q, addr_n, addr_int, addr_aligned_next, addr_real_next; + logic is_hwlp_q, is_hwlp_n; + + logic [31:0] rdata_last_q; + + logic valid_L0; + logic [RDATA_IN_WIDTH/32-1:0][31:0] rdata_L0; + logic [31:0] addr_L0; + + logic fetch_valid; + logic fetch_gnt; + + // prepared data for output + logic [31:0] rdata, rdata_unaligned; + + logic aligned_is_compressed, unaligned_is_compressed; + logic hwlp_aligned_is_compressed, hwlp_unaligned_is_compressed; + + + riscv_L0_buffer + #( + .RDATA_IN_WIDTH ( RDATA_IN_WIDTH ) + ) + L0_buffer_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .prefetch_i ( do_fetch ), + .prefetch_addr_i ( addr_real_next ), //addr_aligned_next + + .branch_i ( branch_i ), + .branch_addr_i ( addr_i ), + + .hwlp_i ( do_hwlp | do_hwlp_int ), + .hwlp_addr_i ( hwloop_target_i ), + + .fetch_gnt_o ( fetch_gnt ), + .fetch_valid_o ( fetch_valid ), + + .valid_o ( valid_L0 ), + .rdata_o ( rdata_L0 ), + .addr_o ( addr_L0 ), + + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + + .busy_o ( busy_L0 ) + ); + + + assign rdata = (use_last || use_hwlp) ? rdata_last_q : rdata_L0[addr_o[3:2]]; + + // the lower part of rdata_unaligned is always the higher part of rdata + assign rdata_unaligned[15:0] = rdata[31:16]; + + always_comb + begin + // rdata_unaligned[31:16] = '0; Not Needed + + case(addr_o[3:2]) + 2'b00: begin rdata_unaligned[31:16] = rdata_L0[1][15:0]; end + 2'b01: begin rdata_unaligned[31:16] = rdata_L0[2][15:0]; end + 2'b10: begin rdata_unaligned[31:16] = rdata_L0[3][15:0]; end + 2'b11: begin rdata_unaligned[31:16] = rdata_L0[0][15:0]; end + endcase // addr_o + end + + + assign unaligned_is_compressed = rdata[17:16] != 2'b11; + assign aligned_is_compressed = rdata[1:0] != 2'b11; + assign upper_is_compressed = rdata_L0[3][17:16] != 2'b11; + assign is_crossword = (addr_o[3:1] == 3'b111) && (~upper_is_compressed); + assign next_is_crossword = ((addr_o[3:1] == 3'b110) && (aligned_is_compressed) && (~upper_is_compressed)) || ((addr_o[3:1] == 3'b101) && (~unaligned_is_compressed) && (~upper_is_compressed)); + assign next_upper_compressed = ((addr_o[3:1] == 3'b110) && (aligned_is_compressed) && upper_is_compressed) || ((addr_o[3:1] == 3'b101) && (~unaligned_is_compressed) && upper_is_compressed); + assign next_valid = ((addr_o[3:2] != 2'b11) || next_upper_compressed) && (~next_is_crossword) && valid; + + //addr_o[3:2] == 2'b11;// ((addr_o[3:1] == 3'b101) & (~upper_is_compressed)) | addr_o[3:2] == 2'b11; // + assign fetch_possible = (addr_o[3:2] == 2'b11 ); + + assign addr_aligned_next = { addr_o[31:2], 2'b00 } + 32'h4; + assign addr_real_next = (next_is_crossword) ? { addr_o[31:4], 4'b0000 } + 32'h16 : { addr_o[31:2], 2'b00 } + 32'h4; + + assign hwlp_unaligned_is_compressed = rdata_L0[2][17:16] != 2'b11; + assign hwlp_aligned_is_compressed = rdata_L0[3][1:0] != 2'b11; + assign hwlp_is_crossword = (hwloop_target_i[3:1] == 3'b111) && (~upper_is_compressed); + + always_comb + begin + addr_int = addr_o; + + // advance address when pipeline is unstalled + if (ready_i) begin + + if (addr_o[1]) begin + // unaligned case + // always move to next entry in the FIFO + + if (unaligned_is_compressed) begin + addr_int = { addr_aligned_next[31:2], 2'b00}; + end else begin + addr_int = { addr_aligned_next[31:2], 2'b10}; + end + + end else begin + // aligned case + + if (aligned_is_compressed) begin + // just increase address, do not move to next entry in the FIFO + addr_int = { addr_o[31:2], 2'b10 }; + end else begin + // move to next entry in the FIFO + addr_int = { addr_aligned_next[31:2], 2'b00 }; + end + end + + end + end + + always_comb + begin + NS = CS; + do_fetch = 1'b0; + do_hwlp = 1'b0; + do_hwlp_int = 1'b0; + use_last = 1'b0; + use_hwlp = 1'b0; + save_rdata_last = 1'b0; + save_rdata_hwlp = 1'b0; + valid = 1'b0; + addr_n = addr_int; + is_hwlp_n = is_hwlp_q; + + if (ready_i) + is_hwlp_n = 1'b0; + + case (CS) + IDLE: begin + // wait here for something to happen + end + + BRANCHED: begin + valid = 1'b0; + do_fetch = fetch_possible; + + if (fetch_valid && (~is_crossword)) + valid = 1'b1; + + if (ready_i) begin + if (hwloop_i) begin + addr_n = addr_o; // keep the old address for now + NS = HWLP_WAIT_GNT; + end else begin + if (next_valid) begin + if (fetch_gnt) begin + save_rdata_last = 1'b1; + NS = VALID_GRANTED; + end else + NS = VALID; + end else if (next_is_crossword) begin + if (fetch_gnt) begin + save_rdata_last = 1'b1; + NS = NOT_VALID_CROSS_GRANTED; + end else begin + NS = NOT_VALID_CROSS; + end + end else begin + if (fetch_gnt) + NS = NOT_VALID_GRANTED; + else + NS = NOT_VALID; + end + end + end else begin + if (fetch_valid) begin + if (is_crossword) begin + save_rdata_last = 1'b1; + if (fetch_gnt) + NS = NOT_VALID_CROSS_GRANTED; + else + NS = NOT_VALID_CROSS; + end else begin + if (fetch_gnt) begin + save_rdata_last = 1'b1; + NS = VALID_GRANTED; + end else + NS = VALID; + end + end + end + end + + NOT_VALID: begin + do_fetch = 1'b1; + + if (fetch_gnt) + NS = NOT_VALID_GRANTED; + end + + NOT_VALID_GRANTED: begin + valid = fetch_valid; + do_hwlp = hwloop_i; + + if (fetch_valid) + NS = VALID; + end + + NOT_VALID_CROSS: + begin + do_fetch = 1'b1; + + if (fetch_gnt) + begin + save_rdata_last = 1'b1; + NS = NOT_VALID_CROSS_GRANTED; + end + end + + NOT_VALID_CROSS_GRANTED: + begin + valid = fetch_valid; + use_last = 1'b1; + do_hwlp = hwloop_i; + + if (fetch_valid) + begin + if (ready_i) + NS = VALID; + else + NS = VALID_CROSS; + end + end + + VALID: begin + valid = 1'b1; + do_fetch = fetch_possible; // fetch_possible = addr_o[3:2] == 2'b11;// + do_hwlp = hwloop_i; + + if (ready_i) + begin + if (next_is_crossword) + begin + do_fetch = 1'b1; + + if (fetch_gnt) + begin + save_rdata_last = 1'b1; + NS = NOT_VALID_CROSS_GRANTED; + end + else // not fetching + begin + NS = NOT_VALID_CROSS; + end + end + else // Next is not crossword + if (~next_valid) + begin + if (fetch_gnt) + NS = NOT_VALID_GRANTED; + else + NS = NOT_VALID; + end + else // Next is valid + begin + if (fetch_gnt) + begin + if (next_upper_compressed) + begin + save_rdata_last = 1'b1; + NS = VALID_GRANTED; + end + end + end + end + else // NOT ready + begin + if (fetch_gnt) + begin + save_rdata_last = 1'b1; + NS = VALID_GRANTED; + end + end + end + + VALID_CROSS: begin + valid = 1'b1; + use_last = 1'b1; + do_hwlp = hwloop_i; + + if (ready_i) + NS = VALID; + end + + VALID_GRANTED: begin + valid = 1'b1; + use_last = 1'b1; + do_hwlp = hwloop_i; + + if (ready_i) begin + if (fetch_valid) begin + if (next_is_crossword) + NS = VALID_CROSS; + else if(next_upper_compressed) + NS = VALID_FETCH_DONE; + else + NS = VALID; + end else begin + if (next_is_crossword) + NS = NOT_VALID_CROSS_GRANTED; + else if (next_upper_compressed) + NS = VALID_GRANTED; + else + NS = NOT_VALID_GRANTED; + end + end else begin + if (fetch_valid) + NS = VALID_FETCH_DONE; + end + end + + VALID_FETCH_DONE: begin + valid = 1'b1; + use_last = 1'b1; + do_hwlp = hwloop_i; + + if (ready_i) begin + if (next_is_crossword) + NS = VALID_CROSS; + else if (next_upper_compressed) + NS = VALID_FETCH_DONE; + else + NS = VALID; + end + end + + HWLP_WAIT_GNT: begin + do_hwlp_int = 1'b1; + + if (fetch_gnt) begin + is_hwlp_n = 1'b1; + addr_n = hwloop_target_i; + NS = BRANCHED; + end + end + + HWLP_GRANTED: begin + valid = 1'b1; + use_hwlp = 1'b1; + + if (ready_i) begin + addr_n = hwloop_target_i; + + if (fetch_valid) begin + is_hwlp_n = 1'b1; + + if (hwlp_is_crossword) begin + NS = NOT_VALID_CROSS; + end else begin + NS = VALID; + end + end else begin + NS = HWLP_GRANTED_WAIT; + end + end else begin + if (fetch_valid) + NS = HWLP_FETCH_DONE; + end + end + + HWLP_GRANTED_WAIT: begin + use_hwlp = 1'b1; + + if (fetch_valid) begin + is_hwlp_n = 1'b1; + + if ( (addr_L0[3:1] == 3'b111) && (~upper_is_compressed)) begin + NS = NOT_VALID_CROSS; + end else begin + NS = VALID; + end + end + end + + HWLP_FETCH_DONE: begin + valid = 1'b1; + use_hwlp = 1'b1; + + if (ready_i) begin + is_hwlp_n = 1'b1; + addr_n = hwloop_target_i; + + if (hwlp_is_crossword) begin + NS = NOT_VALID_CROSS; + end else begin + NS = VALID; + end + end + end + endcase + + // branches always have priority + if (branch_i) begin + is_hwlp_n = 1'b0; + addr_n = addr_i; + NS = BRANCHED; + + end else if (hwloop_i) begin + if (do_hwlp) begin + if (ready_i) begin + if (fetch_gnt) begin + is_hwlp_n = 1'b1; + addr_n = hwloop_target_i; + NS = BRANCHED; + end else begin + addr_n = addr_o; // keep the old address for now + NS = HWLP_WAIT_GNT; + end + end else begin + if (fetch_gnt) begin + save_rdata_hwlp = 1'b1; + NS = HWLP_GRANTED; + end + end + end + end + end + + + ////////////////////////////////////////////////////////////////////////////// + // registers + ////////////////////////////////////////////////////////////////////////////// + + always_ff @(posedge clk, negedge rst_n) + begin + if (~rst_n) + begin + addr_q <= '0; + is_hwlp_q <= 1'b0; + CS <= IDLE; + rdata_last_q <= '0; + end + else + begin + addr_q <= addr_n; + is_hwlp_q <= is_hwlp_n; + + CS <= NS; + + if (save_rdata_hwlp) + rdata_last_q <= rdata_o; + else if(save_rdata_last) + begin + //rdata_last_q <= rdata_L0[3]; + if(ready_i) + begin + rdata_last_q <= rdata_L0[3];//rdata; + end + else + begin + rdata_last_q <= rdata;//rdata; + end + end + end + end + + ////////////////////////////////////////////////////////////////////////////// + // output ports + ////////////////////////////////////////////////////////////////////////////// + + assign rdata_o = ((~addr_o[1]) || use_hwlp) ? rdata : rdata_unaligned; + assign valid_o = valid & (~branch_i); + + assign addr_o = addr_q; + + assign is_hwlp_o = is_hwlp_q & (~branch_i); + + assign busy_o = busy_L0; + + + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + `ifndef VERILATOR + // there should never be a ready_i without valid_o + assert property ( + @(posedge clk) (ready_i) |-> (valid_o) ) else $warning("IF Stage is ready without prefetcher having valid data"); + + // never is_crossword while also next_is_crossword + assert property ( + @(posedge clk) (next_is_crossword) |-> (~is_crossword) ) else $warning("Cannot have two crossword accesses back-to-back"); + assert property ( + @(posedge clk) (is_crossword) |-> (~next_is_crossword) ) else $warning("Cannot have two crossword accesses back-to-back"); + `endif +endmodule // prefetch_L0_buffer + diff --git a/hw/deps/riscv/riscv_register_file.sv b/hw/deps/riscv/riscv_register_file.sv new file mode 100644 index 0000000..24881fc --- /dev/null +++ b/hw/deps/riscv/riscv_register_file.sv @@ -0,0 +1,189 @@ +// Copyright 2018 ETH Zurich and 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Francesco Conti - f.conti@unibo.it // +// // +// Additional contributions by: // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// // +// Design Name: RISC-V register file // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Register file with 31x 32 bit wide registers. Register 0 // +// is fixed to 0. This register file is based on flip-flops. // +// Also supports the fp-register file now if FPU=1 // +// // +//////////////////////////////////////////////////////////////////////////////// + +module riscv_register_file +#( + parameter ADDR_WIDTH = 5, + parameter DATA_WIDTH = 32, + parameter FPU = 0 +) +( + // Clock and Reset + input logic clk, + input logic rst_n, + + input logic test_en_i, + + input logic fregfile_disable_i, + + //Read port R1 + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [DATA_WIDTH-1:0] rdata_a_o, + + //Read port R2 + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [DATA_WIDTH-1:0] rdata_b_o, + + //Read port R3 + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [DATA_WIDTH-1:0] rdata_c_o, + + // Write port W1 + input logic [ADDR_WIDTH-1:0] waddr_a_i, + input logic [DATA_WIDTH-1:0] wdata_a_i, + input logic we_a_i, + + // Write port W2 + input logic [ADDR_WIDTH-1:0] waddr_b_i, + input logic [DATA_WIDTH-1:0] wdata_b_i, + input logic we_b_i +); + + // number of integer registers + localparam NUM_WORDS = 2**(ADDR_WIDTH-1); + // number of floating point registers + localparam NUM_FP_WORDS = 2**(ADDR_WIDTH-1); + localparam NUM_TOT_WORDS = FPU ? NUM_WORDS + NUM_FP_WORDS : NUM_WORDS; + + // integer register file + logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] mem; + + // fp register file + logic [NUM_FP_WORDS-1:0][DATA_WIDTH-1:0] mem_fp; + + // mask bit for fpregfile selection (top bit of address) + logic fregfile_ena; + + // masked write addresses + logic [ADDR_WIDTH-1:0] waddr_a; + logic [ADDR_WIDTH-1:0] waddr_b; + + // write enable signals for all registers + logic [NUM_TOT_WORDS-1:0] we_a_dec; + logic [NUM_TOT_WORDS-1:0] we_b_dec; + + + //----------------------------------------------------------------------------- + //-- FPU Register file enable: + //-- Taken from Cluster Config Reg if FPU reg file exists, or always enabled (safe default) + //----------------------------------------------------------------------------- + assign fregfile_ena = FPU ? ~fregfile_disable_i : '1; + + + //----------------------------------------------------------------------------- + //-- READ : Read address decoder RAD + //----------------------------------------------------------------------------- + if (FPU == 1) begin + assign rdata_a_o = (fregfile_ena & raddr_a_i[5]) ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = (fregfile_ena & raddr_b_i[5]) ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = (fregfile_ena & raddr_c_i[5]) ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end else begin + assign rdata_a_o = mem[raddr_a_i[4:0]]; + assign rdata_b_o = mem[raddr_b_i[4:0]]; + assign rdata_c_o = mem[raddr_c_i[4:0]]; + end + + //----------------------------------------------------------------------------- + //-- WRITE : Write Address Decoder (WAD), combinatorial process + //----------------------------------------------------------------------------- + + // Mask top bit of write address to disable fp regfile + assign waddr_a = {(fregfile_ena & waddr_a_i[5]), waddr_a_i[4:0]}; + assign waddr_b = {(fregfile_ena & waddr_b_i[5]), waddr_b_i[4:0]}; + + always_comb + begin : we_a_decoder + for (int i = 0; i < NUM_TOT_WORDS; i++) begin + if (waddr_a == i) + we_a_dec[i] = we_a_i; + else + we_a_dec[i] = 1'b0; + end + end + + always_comb + begin : we_b_decoder + for (int i=0; i 0) else $fatal(1, "Address width must be non-zero!"); + assert (DataWidth > 0) else $fatal(1, "Data width must be non-zero!"); + assert (Depth > 0) else $fatal(1, "Depth must be non-zero!"); + end + `endif + // pragma translate_on + +endmodule diff --git a/hw/deps/riscv/riscv_tracer.sv b/hw/deps/riscv/riscv_tracer.sv new file mode 100644 index 0000000..087c452 --- /dev/null +++ b/hw/deps/riscv/riscv_tracer.sv @@ -0,0 +1,1192 @@ +// Copyright (c) 2019-2020 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// Salvatore Di Girolamo - digirols@inf.ethz.ch // +// // +// Design Name: RISC-V Tracer // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Traces the executed instructions // +// // +//////////////////////////////////////////////////////////////////////////////// + +import riscv_defines::*; +import riscv_tracer_defines::*; + +// Source/Destination register instruction index +`define REG_S1 19:15 +`define REG_S2 24:20 +`define REG_S3 29:25 +`define REG_S4 31:27 +`define REG_D 11:07 + +module riscv_tracer ( + // Clock and Reset + input logic clk, + input logic rst_n, + + input logic fetch_enable, + input logic [31:0] hart_id_i, + + input logic [31:0] pc, + input logic [31:0] instr, + input ctrl_state_e controller_state_i, + + input logic compressed, + input logic id_valid, + input logic is_decoding, + input logic pipe_flush, + input logic mret, + input logic uret, + input logic dret, + input logic ecall, + input logic ebreak, + input logic fence, + + input logic [31:0] rs1_value, + input logic [31:0] rs2_value, + input logic [31:0] rs3_value, + + input logic [31:0] rs2_value_vec, + + input logic rd_is_fp, + input logic rs1_is_fp, + input logic rs2_is_fp, + input logic rs3_is_fp, + + input logic ex_valid, + input logic [ 5:0] ex_reg_addr, + input logic ex_reg_we, + input logic [31:0] ex_reg_wdata, + + input logic ex_data_req, + input logic ex_data_gnt, + input logic ex_data_we, + input logic [31:0] ex_data_addr, + input logic [31:0] ex_data_wdata, + input logic data_misaligned, + + input logic wb_bypass, + + input logic wb_valid, + input logic [ 5:0] wb_reg_addr, + input logic wb_reg_we, + input logic [31:0] wb_reg_wdata, + + input logic [31:0] imm_u_type, + input logic [31:0] imm_uj_type, + input logic [31:0] imm_i_type, + input logic [11:0] imm_iz_type, + input logic [31:0] imm_z_type, + input logic [31:0] imm_s_type, + input logic [31:0] imm_sb_type, + input logic [31:0] imm_s2_type, + input logic [31:0] imm_s3_type, + input logic [31:0] imm_vs_type, + input logic [31:0] imm_vu_type, + input logic [31:0] imm_shuffle_type, + input logic [ 4:0] imm_clip_type +); + + `define ADDREG(REQ_QUEUE, R, ADDR, VAL) R.addr = ADDR; R.value = VAL; REQ_QUEUE.push_back(R); + + typedef enum logic [1:0] {Init, Running} state_t; + + typedef struct packed { + logic [ 5:0] addr; + logic [31:0] value; + } reg_t; + + typedef struct packed { + logic [31:0] addr; + logic we; + logic [ 3:0] be; + logic [31:0] wdata; + logic [31:0] rdata; + } mem_acc_t; + + class instr_trace_t; + time simtime; + integer cycles; + logic [31:0] pc; + logic [31:0] instr; + reg_t regs_read[$]; + reg_t regs_write[$]; + mem_acc_t mem_access[$]; + logic run_ex; + string str; + + function new(); + str = ""; + endfunction + + endclass + + integer f; + string fn; + integer cycles; + logic [5:0] rd, rs1, rs2, rs3, rs4; + + state_t state; + + // TODO: this is super ugly but verilator currently does not + // support complex data types as function argurments. :-( + instr_trace_t current_instr; + + instr_trace_t instr_ex[$]; + instr_trace_t instr_wb[$]; + instr_trace_t instr_ex_misaligned[$]; + instr_trace_t to_print[$]; + + assign rd = {rd_is_fp, instr[`REG_D]}; + assign rs1 = {rs1_is_fp, instr[`REG_S1]}; + assign rs2 = {rs2_is_fp, instr[`REG_S2]}; + assign rs3 = {rs3_is_fp, instr[`REG_S3]}; + assign rs4 = {rs3_is_fp, instr[`REG_S4]}; + + function void printMnemonic(input string mnemonic); + begin + current_instr.str = mnemonic; + end + endfunction // printMnemonic + + function void printRInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, x%0d", mnemonic, rd, rs1, rs2); + end + endfunction // printRInstr + + function void printAddNInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, x%0d, 0x%0d", mnemonic, rd, rs1, rs2, $unsigned(imm_s3_type[4:0])); + end + endfunction // printAddNInstr + + function void printR1Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d", mnemonic, rd, rs1); + end + endfunction // printR1Instr + + function void printR3Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rd, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, x%0d", mnemonic, rd, rs1, rs2); + end + endfunction // printR3Instr + + function void printF3Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs4, rs3_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s f%0d, f%0d, f%0d, f%0d", mnemonic, rd-32, rs1-32, rs2-32, rs4-32); + end + endfunction // printF3Instr + + function void printF2Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s f%0d, f%0d, f%0d", mnemonic, rd-32, rs1-32, rs2-32); + end + endfunction // printF2Instr + + function void printF2IInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, f%0d, f%0d", mnemonic, rd, rs1-32, rs2-32); + end + endfunction // printF2IInstr + + function void printFInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s f%0d, f%0d", mnemonic, rd-32, rs1-32); + end + endfunction // printFInstr + + function void printFIInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, f%0d", mnemonic, rd, rs1-32); + end + endfunction // printFIInstr + + function void printIFInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s f%0d, x%0d", mnemonic, rd-32, rs1); + end + endfunction // printIFInstr + + function void printClipInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $unsigned(imm_clip_type)); + end + endfunction // printClipInstr + + function void printIInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $signed(imm_i_type)); + end + endfunction // printIInstr + + function void printIuInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, 0x%0x", mnemonic, rd, rs1, imm_i_type); + end + endfunction // printIuInstr + + function void printUInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, {imm_u_type[31:12], 12'h000}); + end + endfunction // printUInstr + + function void printUJInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, %0d", mnemonic, rd, $signed(imm_uj_type)); + end + endfunction // printUJInstr + + function void printSBInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rs1, rs2, $signed(imm_sb_type)); + end + endfunction // printSBInstr + + function void printSBallInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, %0d", mnemonic, rs1, $signed(imm_sb_type)); + end + endfunction // printSBallInstr + + function void printCSRInstr(input string mnemonic); + logic [11:0] csr; + reg_t r; + begin + csr = instr[31:20]; + + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + + if (instr[14] == 1'b0) begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, x%0d, 0x%h", mnemonic, rd, rs1, csr); + end else begin + current_instr.str = $sformatf("%-16s x%0d, 0x%h, 0x%h", mnemonic, rd, imm_z_type, csr); + end + end + endfunction // printCSRInstr + + function void printBit1Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d, %0d", mnemonic, rd, rs1, imm_s3_type, imm_s2_type); + end + endfunction // printBit1Instr + + function void printBitRevInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d, %0d", mnemonic, rd, rs1, imm_s2_type, imm_s3_type); + end + endfunction // printBitRevInstr + + function void printBit2Instr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rd, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + current_instr.str = $sformatf("%-16s x%0d, x%0d, %0d, %0d", mnemonic, rd, rs1, imm_s3_type, imm_s2_type); + end + endfunction // printBit2Instr + + function void printAtomicInstr(input string mnemonic); + reg_t r; + begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + if (instr[31:27] == AMO_LR) begin + // Do not print rs2 for load-reserved + current_instr.str = $sformatf("%-16s x%0d, (x%0d)", mnemonic, rd, rs1); + end else begin + current_instr.str = $sformatf("%-16s x%0d, x%0d, (x%0d)", mnemonic, rd, rs2, rs1); + end + end + endfunction // printAtomicInstr + + function void printStoreBuffInstr(); + string mnemonic; + reg_t r; + begin + + case (instr[13:12]) + 2'b00: mnemonic = "bsb"; + 2'b01: mnemonic = "bsh"; + 2'b10: mnemonic = "bsw"; + 2'b11: begin + printMnemonic("INVALID"); + return; + end + endcase + + if (instr[14] == 1'b0) begin + // regular store + if (instr[6:0] != OPCODE_STORE_POST_BUF) begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, $signed(imm_s_type), rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, %0d(x%0d!)", mnemonic, rs2, $signed(imm_s_type), rs1); + end + end else begin + // reg-reg store + if (instr[6:0] != OPCODE_STORE_POST_BUF) begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs3, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("p.%-14s x%0d, x%0d(x%0d)", mnemonic, rs2, rs3, rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs3, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, x%0d(x%0d!)", mnemonic, rs2, rs3, rs1); + end + end + end + endfunction // printStoreBuffInstr + + function void printStoreInstr(); + string mnemonic; + reg_t r; + begin + + case (instr[13:12]) + 2'b00: mnemonic = "sb"; + 2'b01: mnemonic = "sh"; + 2'b10: mnemonic = "sw"; + 2'b11: begin + printMnemonic("INVALID"); + return; + end + endcase + + if (instr[14] == 1'b0) begin + // regular store + if (instr[6:0] != OPCODE_STORE_POST) begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, $signed(imm_s_type), rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, %0d(x%0d!)", mnemonic, rs2, $signed(imm_s_type), rs1); + end + end else begin + // reg-reg store + if (instr[6:0] != OPCODE_STORE_POST) begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs3, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("p.%-14s x%0d, x%0d(x%0d)", mnemonic, rs2, rs3, rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs3, rs3_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, x%0d(x%0d!)", mnemonic, rs2, rs3, rs1); + end + end + end + endfunction // printStoreInstr + + function void printHwloopInstr(); + string mnemonic; + reg_t r; + begin + // set mnemonic + case (instr[14:12]) + 3'b000: mnemonic = "lp.starti"; + 3'b001: mnemonic = "lp.endi"; + 3'b010: mnemonic = "lp.count"; + 3'b011: mnemonic = "lp.counti"; + 3'b100: mnemonic = "lp.setup"; + 3'b101: mnemonic = "lp.setupi"; + 3'b111: begin + printMnemonic("INVALID"); + return; + end + endcase + + // decode and print instruction + case (instr[14:12]) + // lp.starti and lp.endi + 3'b000, + 3'b001: current_instr.str = $sformatf("%-16s 0x%0d, 0x%0h", mnemonic, rd, imm_iz_type); + // lp.count + 3'b010: begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s 0x%0d, x%0d", mnemonic, rd, rs1); + end + // lp.counti + 3'b011: current_instr.str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, imm_iz_type); + // lp.setup + 3'b100: begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s 0x%0d, x%0d, 0x%0h", mnemonic, rd, rs1, imm_iz_type); + end + // lp.setupi + 3'b101: begin + current_instr.str = $sformatf("%-16s 0x%0d, 0x%0h, 0x%0h", mnemonic, rd, imm_iz_type, rs1); + end + endcase + end + endfunction // printHwloopInstr + + function void printLoadInstr(); + string mnemonic; + logic [2:0] size; + reg_t r; + begin + // detect reg-reg load and find size + size = instr[14:12]; + if (instr[14:12] == 3'b111) + size = instr[30:28]; + + case (size) + 3'b000: mnemonic = "lb"; + 3'b001: mnemonic = "lh"; + 3'b010: mnemonic = "lw"; + 3'b100: mnemonic = "lbu"; + 3'b101: mnemonic = "lhu"; + 3'b110: mnemonic = "p.elw"; + 3'b011, + 3'b111: begin + printMnemonic("INVALID"); + return; + end + endcase + + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + + if (instr[14:12] != 3'b111) begin + // regular load + if (instr[6:0] != OPCODE_LOAD_POST) begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rd, $signed(imm_i_type), rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, %0d(x%0d!)", mnemonic, rd, $signed(imm_i_type), rs1); + end + end else begin + // reg-reg load + if (instr[6:0] != OPCODE_LOAD_POST) begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + current_instr.str = $sformatf("%-16s x%0d, x%0d(x%0d)", mnemonic, rd, rs2, rs1); + end else begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rs1, 32'hDEADBEEF); + current_instr.str = $sformatf("p.%-14s x%0d, x%0d(x%0d!)", mnemonic, rd, rs2, rs1); + end + end + end + endfunction //printLoadInstr + + function void printMulInstr(); + string mnemonic; + string str_suf; + string str_imm; + string str_asm; + reg_t r; + begin + + // always read rs1 and rs2 and write rd + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + + if (instr[12]) begin + `ADDREG(current_instr.regs_read, r, rd, rs3_value); + end + + case ({instr[31:30], instr[14]}) + 3'b000: str_suf = "u"; + 3'b001: str_suf = "uR"; + 3'b010: str_suf = "hhu"; + 3'b011: str_suf = "hhuR"; + 3'b100: str_suf = "s"; + 3'b101: str_suf = "sR"; + 3'b110: str_suf = "hhs"; + 3'b111: str_suf = "hhsR"; + endcase + + if (instr[12]) + mnemonic = "p.mac"; + else + mnemonic = "p.mul"; + + if (imm_s3_type[4:0] != 5'b00000) + str_asm = $sformatf("%s%sN", mnemonic, str_suf); + else + str_asm = $sformatf("%s%s", mnemonic, str_suf); + + if (instr[29:25] != 5'b00000) + current_instr.str = $sformatf("%-16s x%0d, x%0d, x%0d, %0d", str_asm, rd, rs1, rs2, $unsigned(imm_s3_type[4:0])); + else + current_instr.str = $sformatf("%-16s x%0d, x%0d, x%0d", str_asm, rd, rs1, rs2); + end + endfunction // printMulInstr + + function void printVecInstr(); + string mnemonic; + string str_asm; + string str_args; + string str_hb; + string str_sci; + string str_imm; + reg_t r; + begin + + // always read rs1 and write rd + `ADDREG(current_instr.regs_read, r, rs1, rs1_value); + `ADDREG(current_instr.regs_write, r, rd, 32'hDEADBEEF); + + case (instr[14:13]) + 2'b00: str_sci = ""; + 2'b10: str_sci = ".sc"; + 2'b11: str_sci = ".sci"; + endcase + + if (instr[12]) + str_hb = ".b"; + else + str_hb = ".h"; + + // set mnemonic + case (instr[31:26]) + 6'b000000: begin mnemonic = "pv.add"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000010: begin mnemonic = "pv.sub"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000100: begin mnemonic = "pv.avg"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000110: begin mnemonic = "pv.avgu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b001000: begin mnemonic = "pv.min"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b001010: begin mnemonic = "pv.minu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b001100: begin mnemonic = "pv.max"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b001110: begin mnemonic = "pv.maxu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b010000: begin mnemonic = "pv.srl"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b010010: begin mnemonic = "pv.sra"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b010100: begin mnemonic = "pv.sll"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b010110: begin mnemonic = "pv.or"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b011000: begin mnemonic = "pv.xor"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b011010: begin mnemonic = "pv.and"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b011100: begin mnemonic = "pv.abs"; str_imm = $sformatf("0x%0d", imm_vs_type); end + + 6'b011110: begin mnemonic = "pv.extract"; str_imm = $sformatf("0x%0d", imm_vs_type); str_sci = ""; end + 6'b100100: begin mnemonic = "pv.extractu"; str_imm = $sformatf("0x%0d", imm_vu_type); str_sci = ""; end + 6'b101100: begin mnemonic = "pv.insert"; str_imm = $sformatf("0x%0d", imm_vs_type); end + + // shuffle/pack + 6'b110000: begin + if (instr[14:12] == 3'b001) begin + mnemonic = "pv.shuffle"; + end else begin + mnemonic = "pv.shufflei0"; + str_imm = $sformatf("0x%0d", imm_shuffle_type); + end + end + 6'b111010: begin mnemonic = "pv.shufflei1"; str_imm = $sformatf("0x%0d", imm_shuffle_type); end + 6'b111100: begin mnemonic = "pv.shufflei2"; str_imm = $sformatf("0x%0d", imm_shuffle_type); end + 6'b111110: begin mnemonic = "pv.shufflei3"; str_imm = $sformatf("0x%0d", imm_shuffle_type); end + + 6'b110010: begin mnemonic = "pv.shuffle2"; end + + 6'b110100: begin mnemonic = instr[25] ? "pv.pack.h" : "pv.pack"; end + 6'b110110: begin mnemonic = "pv.packhi"; end + 6'b111000: begin mnemonic = "pv.packlo"; end + + // comparisons + 6'b000001: begin mnemonic = "pv.cmpeq"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000011: begin mnemonic = "pv.cmpne"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000101: begin mnemonic = "pv.cmpgt"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b000111: begin mnemonic = "pv.cmpge"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b001001: begin mnemonic = "pv.cmplt"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b001011: begin mnemonic = "pv.cmple"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b001101: begin mnemonic = "pv.cmpgtu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b001111: begin mnemonic = "pv.cmpgeu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b010001: begin mnemonic = "pv.cmpltu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b010011: begin mnemonic = "pv.cmpleu"; str_imm = $sformatf("0x%0d", imm_vu_type); end + + // dotproducts + 6'b100000: begin mnemonic = "pv.dotup"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b100010: begin mnemonic = "pv.dotusp"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b100110: begin mnemonic = "pv.dotsp"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b101000: begin mnemonic = "pv.sdotup"; str_imm = $sformatf("0x%0d", imm_vu_type); end + 6'b101010: begin mnemonic = "pv.sdotusp"; str_imm = $sformatf("0x%0d", imm_vs_type); end + 6'b101110: begin mnemonic = "pv.sdotsp"; str_imm = $sformatf("0x%0d", imm_vs_type); end + + 6'b010101: begin + unique case (instr[14:13]) + 2'b00: mnemonic = instr[25] ? "pv.clpxmul.r" : "pv.clpxmul.i"; + 2'b01: mnemonic = instr[25] ? "pv.clpxmul.r.div2" : "pv.clpxmul.i.div2"; + 2'b10: mnemonic = instr[25] ? "pv.clpxmul.r.div4" : "pv.clpxmul.i.div4"; + 2'b11: mnemonic = instr[25] ? "pv.clpxmul.r.div8" : "pv.clpxmul.i.div8"; + endcase + str_sci = ""; + end + + 6'b011011: begin + unique case (instr[14:13]) + 2'b00: mnemonic = "pv.subrotmj"; + 2'b01: mnemonic = "pv.subrotmj.div2"; + 2'b10: mnemonic = "pv.subrotmj.div4"; + 2'b11: mnemonic = "pv.subrotmj.div8"; + endcase + str_sci = ""; + end + + 6'b010111: begin mnemonic = "pv.cplxconj"; end + + 6'b011101: begin + unique case (instr[14:13]) + 2'b01: mnemonic = "pv.add.div2"; + 2'b10: mnemonic = "pv.add.div4"; + 2'b11: mnemonic = "pv.add.div8"; + endcase + str_sci = ""; + end + + 6'b011001: begin + unique case (instr[14:13]) + 2'b01: mnemonic = "pv.sub.div2"; + 2'b10: mnemonic = "pv.sub.div4"; + 2'b11: mnemonic = "pv.sub.div8"; + endcase + str_sci = ""; + end + + default: begin + printMnemonic("INVALID"); + return; + end + endcase + + if (str_sci == "") begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value); + str_args = $sformatf("x%0d, x%0d, x%0d", rd, rs1, rs2); + end else if (str_sci == ".sc") begin + `ADDREG(current_instr.regs_read, r, rs2, rs2_value_vec); + str_args = $sformatf("x%0d, x%0d, x%0d", rd, rs1, rs2); + end else if (str_sci == ".sci") begin + str_args = $sformatf("x%0d, x%0d, %s", rd, rs1, str_imm); + end + + str_asm = $sformatf("%s%s%s", mnemonic, str_sci, str_hb); + + current_instr.str = $sformatf("%-16s %s", str_asm, str_args); + end + endfunction // printVecInstr + + + function string regAddrToStr(input logic [5:0] addr); + begin + // TODO: use this function to also format the arguments to the + // instructions + if (SymbolicRegs) begin // format according to RISC-V ABI + if (addr >= 42) + return $sformatf(" f%0d", addr-32); + else if (addr > 32) + return $sformatf(" f%0d", addr-32); + else begin + if (addr == 0) + return $sformatf("zero"); + else if (addr == 1) + return $sformatf(" ra"); + else if (addr == 2) + return $sformatf(" sp"); + else if (addr == 3) + return $sformatf(" gp"); + else if (addr == 4) + return $sformatf(" tp"); + else if (addr >= 5 && addr <= 7) + return $sformatf(" t%0d", addr-5); + else if (addr >= 8 && addr <= 9) + return $sformatf(" s%0d", addr-8); + else if (addr >= 10 && addr <= 17) + return $sformatf(" a%0d", addr-10); + else if (addr >= 18 && addr <= 25) + return $sformatf(" s%0d", addr-16); + else if (addr >= 26 && addr <= 27) + return $sformatf(" s%0d", addr-16); + else if (addr >= 28 && addr <= 31) + return $sformatf(" t%0d", addr-25); + else + return $sformatf("UNKNOWN %0d", addr); + end + end else begin + if (addr >= 42) + return $sformatf("f%0d", addr-32); + else if (addr > 32) + return $sformatf(" f%0d", addr-32); + else if (addr < 10) + return $sformatf(" x%0d", addr); + else + return $sformatf("x%0d", addr); + end + end + endfunction + + function void printInstrTrace(); + instr_trace_t trace; + mem_acc_t mem_acc; + if (to_print.size() > 0) begin + trace = to_print.pop_front(); + + $fwrite(f, "%21d %15d %h %h %-36s", trace.simtime, + trace.cycles, + trace.pc, + trace.instr, + trace.str); + + foreach(trace.regs_write[i]) begin + if (trace.regs_write[i].addr != 0) + $fwrite(f, " %s=%08x", regAddrToStr(trace.regs_write[i].addr), trace.regs_write[i].value); + end + + foreach(trace.regs_read[i]) begin + if (trace.regs_read[i].addr != 0) + $fwrite(f, " %s:%08x", regAddrToStr(trace.regs_read[i].addr), trace.regs_read[i].value); + end + + if (trace.mem_access.size() > 0) begin + mem_acc = trace.mem_access.pop_front(); + + $fwrite(f, " PA:%08x", mem_acc.addr); + end + + $fwrite(f, "\n"); + $fflush(); + + end + endfunction + + + function void progressID(); + + // special case for WFI because we don't wait for unstalling there + if ( (id_valid || pipe_flush || mret || uret || ecall || ebreak || dret || fence) && is_decoding) + begin + current_instr = new (); + + current_instr.simtime = $time; + current_instr.cycles = cycles; + current_instr.pc = pc; + current_instr.instr = instr; + current_instr.run_ex = 0; + //$display("LOG: %08x time: %0d \n", current_instr.pc, cycles); + + // use casex instead of case inside due to ModelSim bug + casex (instr) + // Aliases + 32'h00_00_00_13: printMnemonic("nop"); + // Regular opcodes + INSTR_LUI: printUInstr("lui"); + INSTR_AUIPC: printUInstr("auipc"); + INSTR_JAL: printUJInstr("jal"); + INSTR_JALR: printIInstr("jalr"); + // BRANCH + INSTR_BEQ: printSBInstr("beq"); + INSTR_BNE: printSBInstr("bne"); + INSTR_BLT: printSBInstr("blt"); + INSTR_BGE: printSBInstr("bge"); + INSTR_BLTU: printSBInstr("bltu"); + INSTR_BGEU: printSBInstr("bgeu"); + INSTR_BEQIMM: printSBallInstr("p.beqimm"); + INSTR_BNEIMM: printSBallInstr("p.bneimm"); + // OPIMM + INSTR_ADDI: printIInstr("addi"); + INSTR_SLTI: printIInstr("slti"); + INSTR_SLTIU: printIInstr("sltiu"); + INSTR_XORI: printIInstr("xori"); + INSTR_ORI: printIInstr("ori"); + INSTR_ANDI: printIInstr("andi"); + INSTR_SLLI: printIuInstr("slli"); + INSTR_SRLI: printIuInstr("srli"); + INSTR_SRAI: printIuInstr("srai"); + // OP + INSTR_ADD: printRInstr("add"); + INSTR_SUB: printRInstr("sub"); + INSTR_SLL: printRInstr("sll"); + INSTR_SLT: printRInstr("slt"); + INSTR_SLTU: printRInstr("sltu"); + INSTR_XOR: printRInstr("xor"); + INSTR_SRL: printRInstr("srl"); + INSTR_SRA: printRInstr("sra"); + INSTR_OR: printRInstr("or"); + INSTR_AND: printRInstr("and"); + INSTR_EXTHS: printRInstr("p.exths"); + INSTR_EXTHZ: printRInstr("p.exthz"); + INSTR_EXTBS: printRInstr("p.extbs"); + INSTR_EXTBZ: printRInstr("p.extbz"); + INSTR_PAVG: printRInstr("p.avg"); + INSTR_PAVGU: printRInstr("p.avgu"); + + INSTR_PADDN: printAddNInstr("p.addN"); + INSTR_PADDUN: printAddNInstr("p.adduN"); + INSTR_PADDRN: printAddNInstr("p.addRN"); + INSTR_PADDURN: printAddNInstr("p.adduRN"); + INSTR_PSUBN: printAddNInstr("p.subN"); + INSTR_PSUBUN: printAddNInstr("p.subuN"); + INSTR_PSUBRN: printAddNInstr("p.subRN"); + INSTR_PSUBURN: printAddNInstr("p.subuRN"); + + INSTR_PADDNR: printR3Instr("p.addNr"); + INSTR_PADDUNR: printR3Instr("p.adduNr"); + INSTR_PADDRNR: printR3Instr("p.addRNr"); + INSTR_PADDURNR: printR3Instr("p.adduRNr"); + INSTR_PSUBNR: printR3Instr("p.subNr"); + INSTR_PSUBUNR: printR3Instr("p.subuNr"); + INSTR_PSUBRNR: printR3Instr("p.subRNr"); + INSTR_PSUBURNR: printR3Instr("p.subuRNr"); + + INSTR_PSLET: printRInstr("p.slet"); + INSTR_PSLETU: printRInstr("p.sletu"); + INSTR_PMIN: printRInstr("p.min"); + INSTR_PMINU: printRInstr("p.minu"); + INSTR_PMAX: printRInstr("p.max"); + INSTR_PMAXU: printRInstr("p.maxu"); + INSTR_PABS: printR1Instr("p.abs"); + INSTR_PCLIP: printClipInstr("p.clip"); + INSTR_PCLIPU: printClipInstr("p.clipu"); + INSTR_PBEXT: printBit1Instr("p.extract"); + INSTR_PBEXTU: printBit1Instr("p.extractu"); + INSTR_PBINS: printBit2Instr("p.insert"); + INSTR_PBCLR: printBit1Instr("p.bclr"); + INSTR_PBSET: printBit1Instr("p.bset"); + INSTR_PBREV: printBitRevInstr("p.bitrev"); + + INSTR_PCLIPR: printRInstr("p.clipr"); + INSTR_PCLIPUR: printRInstr("p.clipur"); + INSTR_PBEXTR: printRInstr("p.extractr"); + INSTR_PBEXTUR: printRInstr("p.extractur"); + INSTR_PBINSR: printR3Instr("p.insertr"); + INSTR_PBCLRR: printRInstr("p.bclrr"); + INSTR_PBSETR: printRInstr("p.bsetr"); + + INSTR_FF1: printR1Instr("p.ff1"); + INSTR_FL1: printR1Instr("p.fl1"); + INSTR_CLB: printR1Instr("p.clb"); + INSTR_CNT: printR1Instr("p.cnt"); + INSTR_ROR: printRInstr("p.ror"); + + // FENCE + INSTR_FENCE: printMnemonic("fence"); + INSTR_FENCEI: printMnemonic("fencei"); + // SYSTEM (CSR manipulation) + INSTR_CSRRW: printCSRInstr("csrrw"); + INSTR_CSRRS: printCSRInstr("csrrs"); + INSTR_CSRRC: printCSRInstr("csrrc"); + INSTR_CSRRWI: printCSRInstr("csrrwi"); + INSTR_CSRRSI: printCSRInstr("csrrsi"); + INSTR_CSRRCI: printCSRInstr("csrrci"); + // SYSTEM (others) + INSTR_ECALL: printMnemonic("ecall"); + INSTR_EBREAK: printMnemonic("ebreak"); + INSTR_URET: printMnemonic("uret"); + INSTR_MRET: printMnemonic("mret"); + INSTR_WFI: printMnemonic("wfi"); + + INSTR_DRET: printMnemonic("dret"); + + // RV32M + INSTR_PMUL: printRInstr("mul"); + INSTR_PMUH: printRInstr("mulh"); + INSTR_PMULHSU: printRInstr("mulhsu"); + INSTR_PMULHU: printRInstr("mulhu"); + INSTR_DIV: printRInstr("div"); + INSTR_DIVU: printRInstr("divu"); + INSTR_REM: printRInstr("rem"); + INSTR_REMU: printRInstr("remu"); + // PULP MULTIPLIER + INSTR_PMAC: printR3Instr("p.mac"); + INSTR_PMSU: printR3Instr("p.msu"); + INSTR_PMULS : printMulInstr(); + INSTR_PMULHLSN : printMulInstr(); + INSTR_PMULRS : printMulInstr(); + INSTR_PMULRHLSN : printMulInstr(); + INSTR_PMULU : printMulInstr(); + INSTR_PMULUHLU : printMulInstr(); + INSTR_PMULRU : printMulInstr(); + INSTR_PMULRUHLU : printMulInstr(); + INSTR_PMACS : printMulInstr(); + INSTR_PMACHLSN : printMulInstr(); + INSTR_PMACRS : printMulInstr(); + INSTR_PMACRHLSN : printMulInstr(); + INSTR_PMACU : printMulInstr(); + INSTR_PMACUHLU : printMulInstr(); + INSTR_PMACRU : printMulInstr(); + INSTR_PMACRUHLU : printMulInstr(); + + // FP-OP + INSTR_FMADD: printF3Instr("fmadd.s"); + INSTR_FMSUB: printF3Instr("fmsub.s"); + INSTR_FNMADD: printF3Instr("fnmadd.s"); + INSTR_FNMSUB: printF3Instr("fnmsub.s"); + INSTR_FADD: printF2Instr("fadd.s"); + INSTR_FSUB: printF2Instr("fsub.s"); + INSTR_FMUL: printF2Instr("fmul.s"); + INSTR_FDIV: printF2Instr("fdiv.s"); + INSTR_FSQRT: printFInstr("fsqrt.s"); + INSTR_FSGNJS: printF2Instr("fsgnj.s"); + INSTR_FSGNJNS: printF2Instr("fsgnjn.s"); + INSTR_FSGNJXS: printF2Instr("fsgnjx.s"); + INSTR_FMIN: printF2Instr("fmin.s"); + INSTR_FMAX: printF2Instr("fmax.s"); + INSTR_FCVTWS: printFIInstr("fcvt.w.s"); + INSTR_FCVTWUS: printFIInstr("fcvt.wu.s"); + INSTR_FMVXS: printFIInstr("fmv.x.s"); + INSTR_FEQS: printF2IInstr("feq.s"); + INSTR_FLTS: printF2IInstr("flt.s"); + INSTR_FLES: printF2IInstr("fle.s"); + INSTR_FCLASS: printFIInstr("fclass.s"); + INSTR_FCVTSW: printIFInstr("fcvt.s.w"); + INSTR_FCVTSWU: printIFInstr("fcvt.s.wu"); + INSTR_FMVSX: printIFInstr("fmv.s.x"); + + // RV32A + INSTR_LR: printAtomicInstr("lr.w"); + INSTR_SC: printAtomicInstr("sc.w"); + INSTR_AMOSWAP: printAtomicInstr("amoswap.w"); + INSTR_AMOADD: printAtomicInstr("amoadd.w"); + INSTR_AMOXOR: printAtomicInstr("amoxor.w"); + INSTR_AMOAND: printAtomicInstr("amoand.w"); + INSTR_AMOOR: printAtomicInstr("amoor.w"); + INSTR_AMOMIN: printAtomicInstr("amomin.w"); + INSTR_AMOMAX: printAtomicInstr("amomax.w"); + INSTR_AMOMINU: printAtomicInstr("amominu.w"); + INSTR_AMOMAXU: printAtomicInstr("amomaxu.w"); + + // opcodes with custom decoding + {25'b?, OPCODE_LOAD}: printLoadInstr(); + {25'b?, OPCODE_LOAD_FP}: printLoadInstr(); + {25'b?, OPCODE_LOAD_POST}: printLoadInstr(); + {25'b?, OPCODE_STORE}: printStoreInstr(); + {25'b?, OPCODE_STORE_FP}: printStoreInstr(); + {25'b?, OPCODE_STORE_POST}: printStoreInstr(); + {25'b?, OPCODE_STORE_BUF}: printStoreBuffInstr(); + {25'b?, OPCODE_STORE_POST_BUF}: printStoreBuffInstr(); + {25'b?, OPCODE_HWLOOP}: printHwloopInstr(); + {25'b?, OPCODE_VECOP}: printVecInstr(); + default: printMnemonic("INVALID"); + endcase // unique case (instr) + + instr_ex.push_back(current_instr); + end + endfunction + + function void progressEX(); + instr_trace_t trace; + instr_trace_t trace_pop; + mem_acc_t mem_acc; + + if (instr_ex.size() > 0) begin + trace = instr_ex.pop_front(); + + //$display("EX: %08x time: %0d \n", trace.pc, cycles); + + foreach(trace.regs_write[i]) begin + if ((trace.regs_write[i].addr == ex_reg_addr) && ex_reg_we) begin + trace.regs_write[i].value = ex_reg_wdata; + end + end + + if (ex_data_req && ex_data_gnt) begin + mem_acc.addr = ex_data_addr; + mem_acc.we = ex_data_we; + + if (mem_acc.we) begin + mem_acc.wdata = ex_data_wdata; + end else begin + mem_acc.wdata = 32'hDEADBEEF; + end + + trace.mem_access.push_back(mem_acc); + end + + if (ex_valid || wb_bypass) begin + if(ex_data_req && data_misaligned) begin + instr_ex_misaligned.push_back(trace); + end else begin + instr_wb.push_back(trace); + end + + // NOTE: verilator seems to not like pop_front as standalone (i.e., without assignment) statement. + //trace_pop = instr_ex.pop_front(); + end else begin + // NOTE: we don't have a front() method (?) and instr_ex[0] has not queue semantic. Verilator + // maps queue operations to std::deque, so pushing/popping have O(1) complexity + instr_ex.push_front(trace); + end + end + endfunction + + function void progressEXMisaligned(); + instr_trace_t trace; + instr_trace_t trace_pop; + + if (instr_ex_misaligned.size() > 0) begin + trace = instr_ex_misaligned.pop_front(); + //$display("EXM: %08x time: %0d \n", trace.pc, cycles); + if (ex_valid || wb_bypass) begin + instr_wb.push_back(trace); + // NOTE: verilator seems to not like pop_front as standalone (i.e., without assignment) statement. + //trace_pop = instr_ex_misaligned.pop_front(); + end else begin + instr_ex_misaligned.push_front(trace); + end + end + endfunction + + function void progressWB(); + instr_trace_t trace; + instr_trace_t trace_pop; + if (instr_wb.size() > 0) begin + trace = instr_wb.pop_front(); + foreach(trace.regs_write[i]) begin + //$display("WB: %0d; wb_reg_addr: %08x; wb_reg_wdata: %08x\n", trace.instr, wb_reg_addr, wb_reg_wdata); + //$display("WB: %08x time: %0d \n", trace.pc, cycles); + + if ((trace.regs_write[i].addr == wb_reg_addr) && wb_reg_we) begin + trace.regs_write[i].value = wb_reg_wdata; + end + end + + if (wb_valid) begin + to_print.push_back(trace); + // NOTE: verilator seems to not like pop_front as standalone (i.e., without assignment) statement. + //trace_pop = instr_wb.pop_front(); + end else begin + instr_wb.push_front(trace); + end + end + endfunction + + // cycle counter + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) + cycles <= 0; + else + cycles <= cycles + 1; + end + + always_ff @(posedge clk, negedge rst_n) begin + if (rst_n == 1'b0) begin + state <= Init; + f = 0; + end else begin + state <= Running; + if (f == 0) begin + $sformat(fn, "trace_core_%h_%h.log", hart_id_i[10:5], hart_id_i[3:0]); + // $display("[TRACER] Output filename is: %s", fn); + f = $fopen(fn, "w"); + $fwrite(f, " Time Cycles PC Instr Mnemonic\n"); + end + end + end + + final + begin + $fclose(f); + end + + // log execution + always @(negedge clk) + begin + + if (state == Running) begin + //we run the stages in reverse order because we don't want the same instr being + //processed by the multiple stages in the same cycle. + progressWB(); + progressEXMisaligned(); + progressEX(); + progressID(); + + printInstrTrace(); + end + end // always @ (posedge clk) + +endmodule diff --git a/hw/deps/riscv/verilator-model/cluster_clock_gating.sv b/hw/deps/riscv/verilator-model/cluster_clock_gating.sv new file mode 100644 index 0000000..d486555 --- /dev/null +++ b/hw/deps/riscv/verilator-model/cluster_clock_gating.sv @@ -0,0 +1,34 @@ +// Copyright 2017 ETH Zurich and 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. + +module cluster_clock_gating +( + input logic clk_i, + input logic en_i, + input logic test_en_i, + output logic clk_o + ); + +`ifdef PULP_FPGA_EMUL + // no clock gates in FPGA flow + assign clk_o = clk_i; +`else + logic clk_en; + + always_latch + begin + if (clk_i == 1'b0) + clk_en <= en_i | test_en_i; + end + + assign clk_o = clk_i & clk_en; +`endif + +endmodule // cluster_clock_gating diff --git a/hw/deps/scm/latch_scm/register_file_1w_multi_port_read.sv b/hw/deps/scm/latch_scm/register_file_1w_multi_port_read.sv new file mode 100644 index 0000000..9d93525 --- /dev/null +++ b/hw/deps/scm/latch_scm/register_file_1w_multi_port_read.sv @@ -0,0 +1,173 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +module register_file_1w_multi_port_read +#( + parameter ADDR_WIDTH = 5, + parameter DATA_WIDTH = 32, + + parameter N_READ = 2, + parameter N_WRITE = 1 +) +( + input logic clk, + input logic rst_n, + input logic test_en_i, + + // Read port + input logic [N_READ-1:0] ReadEnable, + input logic [N_READ-1:0][ADDR_WIDTH-1:0] ReadAddr, + output logic [N_READ-1:0][DATA_WIDTH-1:0] ReadData, + + // Write port + input logic WriteEnable, + input logic [ADDR_WIDTH-1:0] WriteAddr, + input logic [DATA_WIDTH-1:0] WriteData +); + + localparam NUM_WORDS = 2**ADDR_WIDTH; + + // Read address register, located at the input of the address decoder + logic [N_READ-1:0][ADDR_WIDTH-1:0] RAddrRegxDP; + logic [N_READ-1:0][NUM_WORDS-1:0] RAddrOneHotxD; + + logic [DATA_WIDTH-1:0] MemContentxDP[NUM_WORDS]; + + logic [NUM_WORDS-1:0] WAddrOneHotxD; + logic [NUM_WORDS-1:0] ClocksxC; + logic [DATA_WIDTH-1:0] WDataIntxD; + + logic clk_int; + + int unsigned i; + int unsigned k; + + genvar x; + genvar z; + + cluster_clock_gating CG_WE_GLOBAL + ( + .clk_o ( clk_int ), + .en_i ( WriteEnable ), + .test_en_i ( test_en_i ), + .clk_i ( clk ) + ); + + //----------------------------------------------------------------------------- + //-- READ : Read address register + //----------------------------------------------------------------------------- + + generate + for(z=0; z + +// Description: Functional module of a generic SRAM +// +// Parameters: +// - NumWords: Number of words in the macro. Address width can be calculated with: +// `AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1` +// The module issues a warning if there is a request on an address which is +// not in range. +// - DataWidth: Width of the ports `wdata_i` and `rdata_o`. +// - ByteWidth: Width of a byte, the byte enable signal `be_i` can be calculated with the +// ceiling division `ceil(DataWidth, ByteWidth)`. +// - NumPorts: Number of read and write ports. Each is a full port. Ports with a higher +// index read and write after the ones with lower indices. +// - Latency: Read latency, the read data is available this many cycles after a request. +// - SimInit: Macro simulation initialization. Values are: +// "zeros": Each bit gets initialized with 1'b0. +// "ones": Each bit gets initialized with 1'b1. +// "random": Each bit gets random initialized with 1'b0 or 1'b1. +// "none": Each bit gets initialized with 1'bx. (default) +// - PrintSimCfg: Prints at the beginning of the simulation a `Hello` message with +// the instantiated parameters and signal widths. +// +// Ports: +// - `clk_i`: Clock +// - `rst_ni`: Asynchronous reset, active low +// - `req_i`: Request, active high +// - `we_i`: Write request, active high +// - `addr_i`: Request address +// - `wdata_i`: Write data, has to be valid on request +// - `be_i`: Byte enable, active high +// - `rdata_o`: Read data, valid `Latency` cycles after a request with `we_i` low. +// +// Behaviour: +// - Address collision: When Ports are making a write access onto the same address, +// the write operation will start at the port with the lowest address +// index, each port will overwrite the changes made by the previous ports +// according how the respective `be_i` signal is set. +// - Read data on write: This implementation will not produce a read data output on the signal +// `rdata_o` when `req_i` and `we_i` are asserted. The output data is stable +// on write requests. + +module tc_sram #( + parameter int unsigned NumWords = 32'd1024, // Number of Words in data array + parameter int unsigned DataWidth = 32'd128, // Data signal width + parameter int unsigned ByteWidth = 32'd8, // Width of a data byte + parameter int unsigned NumPorts = 32'd2, // Number of read and write ports + parameter int unsigned Latency = 32'd1, // Latency when the read data is available + parameter SimInit = "none", // Simulation initialization + parameter bit PrintSimCfg = 1'b0, // Print configuration + // DEPENDENT PARAMETERS, DO NOT OVERWRITE! + parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1, + parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth, // ceil_div + parameter type addr_t = logic [AddrWidth-1:0], + parameter type data_t = logic [DataWidth-1:0], + parameter type be_t = logic [BeWidth-1:0] +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + // input ports + input logic [NumPorts-1:0] req_i, // request + input logic [NumPorts-1:0] we_i, // write enable + input addr_t [NumPorts-1:0] addr_i, // request address + input data_t [NumPorts-1:0] wdata_i, // write data + input be_t [NumPorts-1:0] be_i, // write byte enable + // output ports + output data_t [NumPorts-1:0] rdata_o // read data +); + + // memory array + data_t sram [NumWords-1:0]; + // hold the read address when no read access is made + addr_t [NumPorts-1:0] r_addr_q; + + // SRAM simulation initialization + data_t [NumWords-1:0] init_val; + initial begin : proc_sram_init + for (int unsigned i = 0; i < NumWords; i++) begin + for (int unsigned j = 0; j < DataWidth; j++) begin + case (SimInit) + "zeros": init_val[i][j] = 1'b0; + "ones": init_val[i][j] = 1'b1; + "random": init_val[i][j] = $urandom(); + default: init_val[i][j] = 1'bx; + endcase + end + end + end + + // set the read output if requested + // The read data at the highest array index is set combinational. + // It gets then delayed for a number of cycles until it gets available at the output at + // array index 0. + + // read data output assignment + data_t [NumPorts-1:0][Latency-1:0] rdata_q, rdata_d; + if (Latency == 32'd0) begin : gen_no_read_lat + for (genvar i = 0; i < NumPorts; i++) begin : gen_port + assign rdata_o[i] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]]; + end + end else begin : gen_read_lat + + always_comb begin + for (int unsigned i = 0; i < NumPorts; i++) begin + rdata_o[i] = rdata_q[i][0]; + for (int unsigned j = 0; j < (Latency-1); j++) begin + rdata_d[i][j] = rdata_q[i][j+1]; + end + rdata_d[i][Latency-1] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]]; + end + end + end + + /* verilator lint_on BLKLOOPINIT */ + // write memory array + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + for (int i = 0; i < NumPorts; i++) begin + r_addr_q[i] <= {AddrWidth{1'b0}}; + // initialize the read output register for each port + if (Latency != 32'd0) begin + for (int unsigned j = 0; j < Latency; j++) begin + rdata_q[i][j] <= init_val[{AddrWidth{1'b0}}]; + end + end + end + end else begin + // read value latch happens before new data is written to the sram + for (int unsigned i = 0; i < NumPorts; i++) begin + if (Latency != 0) begin + for (int unsigned j = 0; j < Latency; j++) begin + rdata_q[i][j] <= rdata_d[i][j]; + end + end + end + // there is a request for the SRAM, latch the required register + for (int unsigned i = 0; i < NumPorts; i++) begin + if (req_i[i]) begin + if (we_i[i]) begin + // update value when write is set at clock + for (int unsigned j = 0; j < DataWidth; j++) begin + if (be_i[i][j/ByteWidth]) begin + sram[addr_i[i]][j] = wdata_i[i][j]; + end + end + end else begin + // otherwise update read address for subsequent non request cycles + r_addr_q[i] <= addr_i[i]; + end + end // if req_i + end // for ports + end // if !rst_ni + end + /* verilator lint_on BLKLOOPINIT */ + +// Validate parameters. +// pragma translate_off +`ifndef VERILATOR +`ifndef TARGET_SYNTHESYS + initial begin: p_assertions + assert ($bits(addr_i) == NumPorts * AddrWidth) else $fatal(1, "AddrWidth problem on `addr_i`"); + assert ($bits(wdata_i) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `wdata_i`"); + assert ($bits(be_i) == NumPorts * BeWidth) else $fatal(1, "BeWidth problem on `be_i`" ); + assert ($bits(rdata_o) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `rdata_o`"); + assert (NumWords >= 32'd1) else $fatal(1, "NumWords has to be > 0"); + assert (DataWidth >= 32'd1) else $fatal(1, "DataWidth has to be > 0"); + assert (ByteWidth >= 32'd1) else $fatal(1, "ByteWidth has to be > 0"); + assert (NumPorts >= 32'd1) else $fatal(1, "The number of ports must be at least 1!"); + end + initial begin: p_sim_hello + if (PrintSimCfg) begin + $display("#################################################################################"); + $display("tc_sram functional instantiated with the configuration:" ); + $display("Instance: %m" ); + $display("Number of ports (dec): %0d", NumPorts ); + $display("Number of words (dec): %0d", NumWords ); + $display("Address width (dec): %0d", AddrWidth ); + $display("Data width (dec): %0d", DataWidth ); + $display("Byte width (dec): %0d", ByteWidth ); + $display("Byte enable width (dec): %0d", BeWidth ); + $display("Latency Cycles (dec): %0d", Latency ); + $display("Simulation init (str): %0s", SimInit ); + $display("#################################################################################"); + end + end + for (genvar i = 0; i < NumPorts; i++) begin : gen_assertions + assert property ( @(posedge clk_i) disable iff (!rst_ni) + (req_i[i] |-> (addr_i[i] < NumWords))) else + $warning("Request address %0h not mapped, port %0d, expect random write or read behavior!", + addr_i[i], i); + end + +`endif +`endif +// pragma translate_on +endmodule diff --git a/hw/deps/timer_unit/rtl/timer_unit.sv b/hw/deps/timer_unit/rtl/timer_unit.sv new file mode 100644 index 0000000..07f19df --- /dev/null +++ b/hw/deps/timer_unit/rtl/timer_unit.sv @@ -0,0 +1,579 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +// Davide Rossi + +`define CFG_REG_LO 6'h0 +`define CFG_REG_HI 6'h4 +`define TIMER_VAL_LO 6'h8 +`define TIMER_VAL_HI 6'hC +`define TIMER_CMP_LO 6'h10 +`define TIMER_CMP_HI 6'h14 +`define TIMER_START_LO 6'h18 +`define TIMER_START_HI 6'h1C +`define TIMER_RESET_LO 6'h20 +`define TIMER_RESET_HI 6'h24 + + +`define ENABLE_BIT 'd0 +`define RESET_BIT 'd1 +`define IRQ_BIT 'd2 +`define IEM_BIT 'd3 +`define CMP_CLR_BIT 'd4 +`define ONE_SHOT_BIT 'd5 +`define PRESCALER_EN_BIT 'd6 +`define REF_CLK_EN_BIT 'd7 +`define PRESCALER_START_BIT 'd8 +`define PRESCALER_STOP_BIT 'd15 +`define MODE_64_BIT 'd31 + +module timer_unit + #( + parameter ID_WIDTH = 5 + ) + ( + input logic clk_i, + input logic rst_ni, + + input logic ref_clk_i, + + input logic req_i, + input logic [31:0] addr_i, + input logic wen_i, + input logic [31:0] wdata_i, + input logic [3:0] be_i, + input logic [ID_WIDTH-1:0] id_i, + output logic gnt_o, + + output logic r_valid_o, + output logic r_opc_o, + output logic [ID_WIDTH-1:0] r_id_o, + output logic [31:0] r_rdata_o, + + input logic event_lo_i, + input logic event_hi_i, + + output logic irq_lo_o, + output logic irq_hi_o, + + output logic busy_o + ); + + logic s_req,s_wen; + logic [31:0] s_addr; + + logic s_write_counter_lo, s_write_counter_hi; + logic s_start_timer_lo,s_start_timer_hi,s_reset_timer_lo,s_reset_timer_hi; + + logic s_ref_clk0, s_ref_clk1, s_ref_clk2, s_ref_clk3, s_ref_clk_edge, s_ref_clk_edge_del; + + logic [31:0] s_counter_val_lo, s_counter_val_hi; + + logic [31:0] s_cfg_lo, s_cfg_lo_reg; + logic [31:0] s_cfg_hi, s_cfg_hi_reg; + logic [31:0] s_timer_val_lo; + logic [31:0] s_timer_val_hi; + logic [31:0] s_timer_cmp_lo, s_timer_cmp_lo_reg; + logic [31:0] s_timer_cmp_hi, s_timer_cmp_hi_reg; + + logic s_enable_count_lo,s_enable_count_hi,s_enable_count_prescaler_lo,s_enable_count_prescaler_hi; + logic s_reset_count_lo,s_reset_count_hi,s_reset_count_prescaler_lo,s_reset_count_prescaler_hi; + logic s_target_reached_lo,s_target_reached_hi,s_target_reached_prescaler_lo, s_target_reached_prescaler_hi; + logic s_clear_reset_lo, s_clear_reset_hi; + + enum logic [1:0] { TRANS_IDLE, TRANS_RUN } CS, NS; + + //********************************************************** + //*************** FSM FOR GNT AND R_VALID ****************** + //********************************************************** + assign r_opc_o = 1'b0; + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + CS <= TRANS_IDLE; + else + CS <= NS; + end + + always_comb + begin + + gnt_o = 1'b1; + r_valid_o = 1'b0; + + case(CS) + + TRANS_IDLE: + begin + if (req_i == 1'b1) + NS = TRANS_RUN; + else + NS = TRANS_IDLE; + end + + TRANS_RUN: + begin + r_valid_o = 1'b1; + if (req_i == 1'b1) + NS = TRANS_RUN; + else + NS = TRANS_IDLE; + end + + default: + NS = TRANS_IDLE; + + endcase + + end + + //********************************************************** + //*************** DELAYED ADDR, REQ, WEN ******************* + //********************************************************** + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(rst_ni == 1'b0) + begin + s_req <= 0; + s_wen <= 0; + s_addr <= 0; + r_id_o <= 0; + end + else + begin + s_req <= req_i; + s_wen <= wen_i; + s_addr <= addr_i; + r_id_o <= id_i; + end + end + + //********************************************************** + //*************** PERIPHS INTERFACE ************************ + //********************************************************** + + // register write logic + always_comb + begin + + s_cfg_lo = s_cfg_lo_reg; + s_cfg_hi = s_cfg_hi_reg; + s_timer_cmp_lo = s_timer_cmp_lo_reg; + s_timer_cmp_hi = s_timer_cmp_hi_reg; + s_write_counter_lo = 1'b0; + s_write_counter_hi = 1'b0; + s_start_timer_lo = 1'b0; + s_start_timer_hi = 1'b0; + s_reset_timer_lo = 1'b0; + s_reset_timer_hi = 1'b0; + + // APERIPH BUS: LOWER PRIORITY + if (req_i && ~wen_i) + begin + + case (addr_i[5:0]) + + `CFG_REG_LO: + s_cfg_lo = wdata_i; + + `CFG_REG_HI: + s_cfg_hi = wdata_i; + + `TIMER_VAL_LO: + s_write_counter_lo = 1'b1; + + `TIMER_VAL_HI: + s_write_counter_hi = 1'b1; + + `TIMER_CMP_LO: + s_timer_cmp_lo = wdata_i; + + `TIMER_CMP_HI: + s_timer_cmp_hi = wdata_i; + + `TIMER_START_LO: + s_start_timer_lo = 1'b1; + + `TIMER_START_HI: + s_start_timer_hi = 1'b1; + + `TIMER_RESET_LO: + s_reset_timer_lo = 1'b1; + + `TIMER_RESET_HI: + s_reset_timer_hi = 1'b1; + + endcase + end + + // INPUT EVENTS: HIGHER PRIORITY + if ( ((event_lo_i == 1) && (s_cfg_lo[`IEM_BIT] == 1'b1)) | s_start_timer_lo == 1 ) + s_cfg_lo[`ENABLE_BIT] = 1; + else + begin + if ( s_cfg_lo_reg[`MODE_64_BIT] == 1'b0 ) // 32 BIT MODE + begin + if ( ( s_cfg_lo[`ONE_SHOT_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) ) // ONE SHOT FEATURE: DISABLES TIMER ONCE THE TARGET IS REACHED + s_cfg_lo[`ENABLE_BIT] = 0; + end + else + begin + if ( ( s_cfg_lo[`ONE_SHOT_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) // ONE SHOT FEATURE: DISABLES TIMER ONCE LOW COUNTER REACHES 0xFFFFFFFF and HI COUNTER TARGET IS REACHED + s_cfg_lo[`ENABLE_BIT] = 0; + end + end + + // INPUT EVENTS: HIGHER PRIORITY + if ( ((event_hi_i == 1) && (s_cfg_hi[`IEM_BIT] == 1'b1)) | s_start_timer_hi == 1 ) + s_cfg_hi[`ENABLE_BIT] = 1; + else + begin + if ( ( s_cfg_hi_reg[`MODE_64_BIT] == 1'b0 ) && ( s_cfg_hi[`ONE_SHOT_BIT] == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) // ONE SHOT FEATURE: DISABLES TIMER ONCE THE TARGET IS REACHED IN 32 BIT MODE + s_cfg_hi[`ENABLE_BIT] = 0; + else begin + if ( ( s_cfg_lo[`ONE_SHOT_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) + s_cfg_hi[`ENABLE_BIT] = 0; + end + end + + // RESET LO + if (s_reset_count_lo == 1'b1) + s_cfg_lo[`RESET_BIT] = 1'b0; + + // RESET HI + if (s_reset_count_hi == 1'b1) + s_cfg_hi[`RESET_BIT] = 1'b0; + + end + + // sequential part + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(~rst_ni) + begin + s_cfg_lo_reg <= 0; + s_cfg_hi_reg <= 0; + s_timer_cmp_lo_reg <= 0; + s_timer_cmp_hi_reg <= 0; + end + else + begin + s_cfg_lo_reg <= s_cfg_lo; + s_cfg_hi_reg <= s_cfg_hi; + s_timer_cmp_lo_reg <= s_timer_cmp_lo; + s_timer_cmp_hi_reg <= s_timer_cmp_hi; + end + end + + // APB register read logic + always_comb + begin + r_rdata_o = 'b0; + + if (s_req && s_wen) + begin + + case (s_addr[5:0]) + + `CFG_REG_LO: + r_rdata_o = s_cfg_lo_reg; + + `CFG_REG_HI: + r_rdata_o = s_cfg_hi_reg; + + `TIMER_VAL_LO: + r_rdata_o = s_timer_val_lo; + + `TIMER_VAL_HI: + r_rdata_o = s_timer_val_hi; + + `TIMER_CMP_LO: + r_rdata_o = s_timer_cmp_lo_reg; + + `TIMER_CMP_HI: + r_rdata_o = s_timer_cmp_hi_reg; + + endcase + + end + + end + + //********************************************************** + //*************** CONTROL ********************************** + //********************************************************** + + // RESET COUNT SIGNAL GENERATION + always_comb + begin + s_reset_count_lo = 1'b0; + s_reset_count_hi = 1'b0; + s_reset_count_prescaler_lo = 1'b0; + s_reset_count_prescaler_hi = 1'b0; + + if ( s_cfg_lo_reg[`RESET_BIT] == 1'b1 | s_reset_timer_lo == 1'b1 ) + begin + s_reset_count_lo = 1'b1; + s_reset_count_prescaler_lo = 1'b1; + end + else + begin + if ( s_cfg_lo_reg[`MODE_64_BIT] == 1'b0 ) // 32-bit mode + begin + if ( ( s_cfg_lo_reg[`CMP_CLR_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) ) // if compare and clear feature is enabled the counter is resetted when the target is reached + begin + s_reset_count_lo = 1; + end + end + else // 64-bit mode + begin + if ( ( s_cfg_lo_reg[`CMP_CLR_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) // if compare and clear feature is enabled the counter is resetted when the target is reached + begin + s_reset_count_lo = 1; + end + end + end + + if ( s_cfg_hi_reg[`RESET_BIT] == 1'b1 | s_reset_timer_hi == 1'b1 ) + begin + s_reset_count_hi = 1'b1; + s_reset_count_prescaler_hi = 1'b1; + end + else + begin + if ( s_cfg_lo_reg[`MODE_64_BIT] == 1'b0 ) // 32-bit mode + begin + if ( ( s_cfg_hi_reg[`CMP_CLR_BIT] == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) // if compare and clear feature is enabled the counter is resetted when the target is reached + begin + s_reset_count_hi = 1; + end + end + else // 64-bit mode + begin + if ( ( s_cfg_lo_reg[`CMP_CLR_BIT] == 1'b1 ) && ( s_target_reached_lo == 1'b1 ) && ( s_target_reached_hi == 1'b1 ) ) // if compare and clear feature is enabled the counter is resetted when the target is reached + begin + s_reset_count_hi = 1; + end + end + end + + if ( ( s_cfg_lo_reg[`PRESCALER_EN_BIT] ) && ( s_target_reached_prescaler_lo == 1'b1 ) ) + begin + s_reset_count_prescaler_lo = 1'b1; + end + + if ( ( s_cfg_hi_reg[`PRESCALER_EN_BIT] ) && ( s_target_reached_prescaler_hi == 1'b1 ) ) + begin + s_reset_count_prescaler_hi = 1'b1; + end + + end + + // ENABLE SIGNALS GENERATION + always_comb + begin + s_enable_count_lo = 1'b0; + s_enable_count_hi = 1'b0; + s_enable_count_prescaler_lo = 1'b0; + s_enable_count_prescaler_hi = 1'b0; + + // 32 bit mode lo counter + if ( s_cfg_lo_reg[`ENABLE_BIT] == 1'b1 ) + begin + if ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b0 && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b0 ) // prescaler disabled, ref clock disabled + begin + s_enable_count_lo = 1'b1; + end + else + if ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b0 && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler disabled, ref clock enabled + begin + s_enable_count_lo = s_ref_clk_edge; + end + else + if ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b1 && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler enabled, ref clock enabled + begin + s_enable_count_prescaler_lo = s_ref_clk_edge; + s_enable_count_lo = s_target_reached_prescaler_lo; + end + else // prescaler enabled, ref clock disabled + begin + s_enable_count_prescaler_lo = 1'b1; + s_enable_count_lo = s_target_reached_prescaler_lo; + end + end + + // 32 bit mode hi counter + if ( s_cfg_hi_reg[`ENABLE_BIT] == 1'b1 ) // counter hi enabled + begin + if ( s_cfg_hi_reg[`PRESCALER_EN_BIT] == 1'b0 && s_cfg_hi_reg[`REF_CLK_EN_BIT] == 1'b0 ) // prescaler disabled, ref clock disabled + begin + s_enable_count_hi = 1'b1; + end + else + if ( s_cfg_hi_reg[`PRESCALER_EN_BIT] == 1'b0 && s_cfg_hi_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler disabled, ref clock enabled + begin + s_enable_count_hi = s_ref_clk_edge; + end + else + if ( s_cfg_hi_reg[`PRESCALER_EN_BIT] == 1'b1 && s_cfg_hi_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler enabled, ref clock enabled + begin + s_enable_count_prescaler_hi = s_ref_clk_edge; + s_enable_count_hi = s_target_reached_prescaler_hi; + end + else // prescaler enabled, ref clock disabled + begin + s_enable_count_prescaler_hi = 1'b1; + s_enable_count_hi = s_target_reached_prescaler_hi; + end + end + + // 64-bit mode + if ( ( s_cfg_lo_reg[`ENABLE_BIT] == 1'b1 ) && ( s_cfg_lo_reg[`MODE_64_BIT] == 1'b1 ) ) // timer enabled, 64-bit mode + begin + if ( ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b0 ) && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b0 ) // prescaler disabled, ref clock disabled + begin + s_enable_count_lo = 1'b1; + s_enable_count_hi = ( s_timer_val_lo == 32'hFFFFFFFF ); + end + else if ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b0 && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler disabled, ref clock enabled + begin + s_enable_count_lo = s_ref_clk_edge; + s_enable_count_hi = s_ref_clk_edge_del && ( s_timer_val_lo == 32'hFFFFFFFF ); + end + else if ( s_cfg_lo_reg[`PRESCALER_EN_BIT] == 1'b1 && s_cfg_lo_reg[`REF_CLK_EN_BIT] == 1'b1 ) // prescaler enabled, ref clock enabled + begin + s_enable_count_prescaler_lo = s_ref_clk_edge; + s_enable_count_lo = s_target_reached_prescaler_lo; + s_enable_count_hi = s_target_reached_prescaler_lo && s_ref_clk_edge_del && ( s_timer_val_lo == 32'hFFFFFFFF ); + end + else // prescaler enabled, ref clock disabled + begin + s_enable_count_prescaler_lo = 1'b1; + s_enable_count_lo = s_target_reached_prescaler_lo; + s_enable_count_hi = s_target_reached_prescaler_lo && ( s_timer_val_lo == 32'hFFFFFFFF ); + end + end + end + + // IRQ SIGNALS GENERATION + always_comb + begin + irq_lo_o = 1'b0; + irq_hi_o = 1'b0; + + if ( s_cfg_lo_reg[`MODE_64_BIT] == 1'b0 ) + begin + irq_lo_o = s_target_reached_lo & s_cfg_lo_reg[`IRQ_BIT]; + irq_hi_o = s_target_reached_hi & s_cfg_hi_reg[`IRQ_BIT]; + end + else + begin + irq_lo_o = s_target_reached_lo & s_target_reached_hi & s_cfg_lo_reg[`IRQ_BIT]; + end + end + + //********************************************************** + //*************** EDGE DETECTOR FOR REF CLOCK ************** + //********************************************************** + + always_ff @(posedge clk_i, negedge rst_ni) + begin + if(~rst_ni) + begin + s_ref_clk0 <= 1'b0; + s_ref_clk1 <= 1'b0; + s_ref_clk2 <= 1'b0; + s_ref_clk3 <= 1'b0; + end + else + begin + s_ref_clk0 <= ref_clk_i; + s_ref_clk1 <= s_ref_clk0; + s_ref_clk2 <= s_ref_clk1; + s_ref_clk3 <= s_ref_clk2; + end + end + + assign s_ref_clk_edge = ( ( s_ref_clk1 == 1'b1 ) & ( s_ref_clk2 == 1'b0 ) ) ? 1'b1 : 1'b0; + assign s_ref_clk_edge_del = ( ( s_ref_clk2 == 1'b1 ) & ( s_ref_clk3 == 1'b0 ) ) ? 1'b1 : 1'b0; + + //********************************************************** + //*************** COUNTERS ********************************* + //********************************************************** + + timer_unit_counter_presc prescaler_lo_i + ( + .clk_i(clk_i), + .rst_ni(rst_ni), + + .write_counter_i(1'b0), + .counter_value_i(32'h0000_0000), + + .enable_count_i(s_enable_count_prescaler_lo), + .reset_count_i(s_reset_count_prescaler_lo), + .compare_value_i({24'd0,s_cfg_lo_reg[`PRESCALER_STOP_BIT:`PRESCALER_START_BIT]}), + + .counter_value_o(), + .target_reached_o(s_target_reached_prescaler_lo) + ); + + timer_unit_counter_presc prescaler_hi_i + ( + .clk_i(clk_i), + .rst_ni(rst_ni), + + .write_counter_i(1'b0), + .counter_value_i(32'h0000_0000), + + .enable_count_i(s_enable_count_prescaler_hi), + .reset_count_i(s_reset_count_prescaler_hi), + .compare_value_i({24'd0,s_cfg_hi_reg[`PRESCALER_STOP_BIT:`PRESCALER_START_BIT]}), + + .counter_value_o(), + .target_reached_o(s_target_reached_prescaler_hi) + ); + + timer_unit_counter counter_lo_i + ( + .clk_i(clk_i), + .rst_ni(rst_ni), + + .write_counter_i(s_write_counter_lo), + .counter_value_i(wdata_i), + + .enable_count_i(s_enable_count_lo), + .reset_count_i(s_reset_count_lo), + .compare_value_i(s_timer_cmp_lo_reg), + + .counter_value_o(s_timer_val_lo), + .target_reached_o(s_target_reached_lo) + ); + + timer_unit_counter counter_hi_i + ( + .clk_i(clk_i), + .rst_ni(rst_ni), + + .write_counter_i(s_write_counter_hi), + .counter_value_i(wdata_i), + + .enable_count_i(s_enable_count_hi), + .reset_count_i(s_reset_count_hi), + .compare_value_i(s_timer_cmp_hi_reg), + + .counter_value_o(s_timer_val_hi), + .target_reached_o(s_target_reached_hi) + ); + + assign busy_o = s_cfg_hi_reg[`ENABLE_BIT] | s_cfg_lo_reg[`ENABLE_BIT]; + +endmodule diff --git a/hw/deps/timer_unit/rtl/timer_unit_counter.sv b/hw/deps/timer_unit/rtl/timer_unit_counter.sv new file mode 100644 index 0000000..6592d7f --- /dev/null +++ b/hw/deps/timer_unit/rtl/timer_unit_counter.sv @@ -0,0 +1,73 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +// Davide Rossi + +module timer_unit_counter + ( + input logic clk_i, + input logic rst_ni, + + input logic write_counter_i, + input logic [31:0] counter_value_i, + + input logic reset_count_i, + input logic enable_count_i, + input logic [31:0] compare_value_i, + + output logic [31:0] counter_value_o, + output logic target_reached_o + ); + + logic [31:0] s_count, s_count_reg; + + // COUNTER + always_comb + begin + s_count = s_count_reg; + + // start counting + if ( reset_count_i == 1 ) + s_count = 0; + else + begin + if (write_counter_i == 1) // OVERWRITE COUNTER + s_count = counter_value_i; + else + begin + if ( enable_count_i == 1 ) // the counter is increased if counter is enabled and there is a tick + s_count = s_count_reg + 1; + end + end + end + + always_ff@(posedge clk_i, negedge rst_ni) + begin + if (rst_ni == 0) + s_count_reg <= 0; + else + s_count_reg <= s_count; + end + + // COMPARATOR + always_ff@(posedge clk_i, negedge rst_ni) + begin + if (rst_ni == 0) + target_reached_o <= 1'b0; + else + if ( s_count == compare_value_i ) + target_reached_o <= 1'b1; + else + target_reached_o <= 1'b0; + end + + assign counter_value_o = s_count_reg; + +endmodule diff --git a/hw/deps/timer_unit/rtl/timer_unit_counter_presc.sv b/hw/deps/timer_unit/rtl/timer_unit_counter_presc.sv new file mode 100644 index 0000000..099da6b --- /dev/null +++ b/hw/deps/timer_unit/rtl/timer_unit_counter_presc.sv @@ -0,0 +1,73 @@ +// Copyright 2014-2018 ETH Zurich and 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. + +// Davide Rossi + +module timer_unit_counter_presc + ( + input logic clk_i, + input logic rst_ni, + + input logic write_counter_i, + input logic [31:0] counter_value_i, + + input logic reset_count_i, + input logic enable_count_i, + input logic [31:0] compare_value_i, + + output logic [31:0] counter_value_o, + output logic target_reached_o + ); + + logic [31:0] s_count, s_count_reg; + + // COUNTER + always_comb + begin + s_count = s_count_reg; + + // start counting + if ( reset_count_i == 1 || target_reached_o==1) + s_count = 0; + else + begin + if (write_counter_i == 1) // OVERWRITE COUNTER + s_count = counter_value_i; + else + begin + if ( enable_count_i == 1 ) + s_count = s_count_reg + 1; + end + end + end + + always_ff@(posedge clk_i, negedge rst_ni) + begin + if (rst_ni == 0) + s_count_reg <= 0; + else + s_count_reg <= s_count; + end + + // COMPARATOR + always_ff@(posedge clk_i, negedge rst_ni) + begin + if (rst_ni == 0) + target_reached_o <= 1'b0; + else + if ( s_count == compare_value_i ) + target_reached_o <= 1'b1; + else + target_reached_o <= 1'b0; + end + + assign counter_value_o = s_count_reg; + +endmodule diff --git a/hw/src/apb/apb_bus.sv b/hw/src/apb/apb_bus.sv new file mode 100644 index 0000000..d908873 --- /dev/null +++ b/hw/src/apb/apb_bus.sv @@ -0,0 +1,128 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +// Imported from WIP in axi repo; TODO: unify APB modules and depend on the updated apb repo + +// APB Bus with Single Master and Multiple Slave Interfaces +// Each slave is accessible at exactly one address segment, and the address ranges of no two slaves +// may overlap. If the input address of this bus is not in any slave address segment, the bus +// responds with slverr; otherwise, this bus feeds all signals through to the slave. The slaves see +// offset-compensated addresses, e.g., if this bus gets ADDR_BEGIN[i] as input address, slave i will +// get address 0. +module apb_bus #( + // Number of slaves. + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0, + parameter int unsigned N_SLV = 0, + // Address ranges of the slaves. Slave i is mapped in the inclusive interval from ADDR_BEGIN[i] to + // ADDR_END[i]. + parameter logic [N_SLV-1:0][ADDR_WIDTH-1:0] ADDR_BEGIN = '0, + parameter logic [N_SLV-1:0][ADDR_WIDTH-1:0] ADDR_END = '0, + // Dependent parameters, do not change! + parameter int unsigned STRB_WIDTH = DATA_WIDTH/8 +) ( + // Input + input logic [ADDR_WIDTH-1:0] paddr_i, + input logic [2:0] pprot_i, + input logic psel_i, + input logic penable_i, + input logic pwrite_i, + input logic [DATA_WIDTH-1:0] pwdata_i, + input logic [STRB_WIDTH-1:0] pstrb_i, + output logic pready_o, + output logic [DATA_WIDTH-1:0] prdata_o, + output logic pslverr_o, + + // Outputs + output logic [N_SLV-1:0][ADDR_WIDTH-1:0] paddr_o, + output logic [N_SLV-1:0] [2:0] pprot_o, + output logic [N_SLV-1:0] psel_o, + output logic [N_SLV-1:0] penable_o, + output logic [N_SLV-1:0] pwrite_o, + output logic [N_SLV-1:0][DATA_WIDTH-1:0] pwdata_o, + output logic [N_SLV-1:0][STRB_WIDTH-1:0] pstrb_o, + input logic [N_SLV-1:0] pready_i, + input logic [N_SLV-1:0][DATA_WIDTH-1:0] prdata_i, + input logic [N_SLV-1:0] pslverr_i +); + + logic [$clog2(N_SLV)-1:0] sel_idx; + logic dec_err; + + for (genvar i = 0; i < N_SLV; i++) begin: gen_oup_demux + assign paddr_o[i] = paddr_i - ADDR_BEGIN[i]; + assign pprot_o[i] = pprot_i; + assign psel_o[i] = psel_i & (paddr_i >= ADDR_BEGIN[i] && paddr_i <= ADDR_END[i]); + assign penable_o[i] = penable_i; + assign pwrite_o[i] = pwrite_i; + assign pwdata_o[i] = pwdata_i; + assign pstrb_o[i] = pstrb_i; + end + + assign dec_err = psel_i & ~(|psel_o); + + if (N_SLV > 1) begin: gen_sel_idx_onehot + onehot_to_bin #(.ONEHOT_WIDTH(N_SLV)) i_sel_idx ( + .onehot (psel_o), + .bin (sel_idx) + ); + end else begin: gen_sel_idx_zero + assign sel_idx = 1'b0; + end + + always_comb begin + if (psel_i) begin + if (dec_err) begin + pready_o = 1'b1; + prdata_o = '0; + pslverr_o = 1'b1; + end else begin + pready_o = pready_i[sel_idx]; + prdata_o = prdata_i[sel_idx]; + pslverr_o = pslverr_i[sel_idx]; + end + end else begin // !psel_i + pready_o = 1'b0; + prdata_o = '0; + pslverr_o = 1'b0; + end + end + + // Validate parameters. + // pragma translate_off + `ifndef VERILATOR + initial begin: p_assertions + assert (N_SLV >= 1) else $fatal(1, "The number of slave ports must be at least 1!"); + assert (ADDR_WIDTH >= 1) else $fatal(1, "The addr width must be at least 1!"); + assert (DATA_WIDTH >= 1) else $fatal(1, "The data width must be at least 1!"); + end + for (genvar i = 0; i < N_SLV; i++) begin: gen_assert_addr_outer + initial begin + assert (ADDR_BEGIN[i] <= ADDR_END[i]) + else $fatal(1, "Invalid address range for slave %0d", i); + end + for (genvar j = 0; j < N_SLV; j++) begin: gen_assert_addr_inner + initial begin + if (i != j) begin + if (ADDR_BEGIN[j] >= ADDR_BEGIN[i]) begin + assert (ADDR_BEGIN[j] > ADDR_END[i]) + else $fatal("Address range of slaves %0d and %0d overlap!", i, j); + end else begin + assert (ADDR_END[j] < ADDR_BEGIN[i]) + else $fatal("Address range of slaves %0d and %0d overlap!", i, j); + end + end + end + end + end + `endif + // pragma translate_on + +endmodule diff --git a/hw/src/apb/apb_bus_wrap.sv b/hw/src/apb/apb_bus_wrap.sv new file mode 100644 index 0000000..47ada15 --- /dev/null +++ b/hw/src/apb/apb_bus_wrap.sv @@ -0,0 +1,82 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +// TODO: put into updated apb repo + +module apb_bus_wrap #( + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0, + parameter int unsigned N_SLV = 0, + // Address ranges of the slaves. Slave i is mapped in the inclusive interval from ADDR_BEGIN[i] to + // ADDR_END[i]. + parameter logic [N_SLV-1:0][ADDR_WIDTH-1:0] ADDR_BEGIN = '0, + parameter logic [N_SLV-1:0][ADDR_WIDTH-1:0] ADDR_END = '0, + // Dependent parameters, do not change! + parameter int unsigned STRB_WIDTH = DATA_WIDTH/8 +) ( + APB_BUS.Slave inp, + APB_BUS.Master oup[N_SLV-1:0] +); + + logic [N_SLV-1:0][ADDR_WIDTH-1:0] paddr; + logic [N_SLV-1:0] [2:0] pprot; + logic [N_SLV-1:0] psel; + logic [N_SLV-1:0] penable; + logic [N_SLV-1:0] pwrite; + logic [N_SLV-1:0][DATA_WIDTH-1:0] pwdata; + logic [N_SLV-1:0][STRB_WIDTH-1:0] pstrb; + logic [N_SLV-1:0] pready; + logic [N_SLV-1:0][DATA_WIDTH-1:0] prdata; + logic [N_SLV-1:0] pslverr; + + apb_bus #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_SLV (N_SLV), + .ADDR_BEGIN (ADDR_BEGIN), + .ADDR_END (ADDR_END) + ) i_apb_bus ( + .paddr_i (inp.paddr), + .pprot_i ('0), // TODO: connect after upgrade to APBv2 + .psel_i (inp.psel), + .penable_i (inp.penable), + .pwrite_i (inp.pwrite), + .pwdata_i (inp.pwdata), + .pstrb_i ('1), // TODO: connect after upgrade to APBv2 + .pready_o (inp.pready), + .prdata_o (inp.prdata), + .pslverr_o (inp.pslverr), + + .paddr_o (paddr), + .pprot_o (), // TODO: connect after upgrade to APBv2 + .psel_o (psel), + .penable_o (penable), + .pwrite_o (pwrite), + .pwdata_o (pwdata), + .pstrb_o (), // TODO: connect after upgrade to APBv2 + .pready_i (pready), + .prdata_i (prdata), + .pslverr_i (pslverr) + ); + + for (genvar i = 0; i < N_SLV; i++) begin: gen_bind_oup + assign oup[i].paddr = paddr[i]; + //assign oup[i].pprot = pprot[i]; // TODO: connect after upgrade to APBv2 + assign oup[i].psel = psel[i]; + assign oup[i].penable = penable[i]; + assign oup[i].pwrite = pwrite[i]; + assign oup[i].pwdata = pwdata[i]; + //assign oup[i].pstrb = pstrb[i]; // TODO: connect after upgrade to APBv2 + assign pready[i] = oup[i].pready; + assign prdata[i] = oup[i].prdata; + assign pslverr[i] = oup[i].pslverr; + end + +endmodule diff --git a/hw/src/apb/apb_ro_regs.sv b/hw/src/apb/apb_ro_regs.sv new file mode 100644 index 0000000..e454a0b --- /dev/null +++ b/hw/src/apb/apb_ro_regs.sv @@ -0,0 +1,56 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +// Imported from WIP in axi repo; TODO: unify APB modules and depend on the updated apb repo + +// APB Read-Only Registers +// TODO: Module specification + +module apb_ro_regs #( + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0, + parameter int unsigned N_REGS = 0 +) ( + APB_BUS.Slave apb, + input logic [N_REGS-1:0][DATA_WIDTH-1:0] reg_i +); + + localparam WORD_OFF = $clog2(DATA_WIDTH/8); + + always_comb begin + apb.prdata = 'x; + apb.pslverr = 1'b0; + if (apb.psel) begin + if (apb.pwrite) begin + // Error response to writes + apb.pslverr = 1'b1; + end else begin + automatic logic [ADDR_WIDTH-WORD_OFF-1:0] word_addr = apb.paddr >> WORD_OFF; + if (word_addr >= N_REGS) begin + // Error response to reads out of range + apb.pslverr = 1'b1; + end else begin + apb.prdata = reg_i[word_addr]; + end + end + end + end + assign apb.pready = apb.psel & apb.penable; + + // Validate parameters. + // pragma translate_off + `ifndef VERILATOR + initial begin: p_assertions + assert (N_REGS >= 1) else $fatal(1, "The number of registers must be at least 1!"); + end + `endif + // pragma translate_on + +endmodule diff --git a/hw/src/apb/apb_rw_regs.sv b/hw/src/apb/apb_rw_regs.sv new file mode 100644 index 0000000..7d9d40e --- /dev/null +++ b/hw/src/apb/apb_rw_regs.sv @@ -0,0 +1,82 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +// Imported from WIP in axi repo; TODO: unify APB modules and depend on the updated apb repo + +// APB Read-Write Registers +// TODO: Module specification + +module apb_rw_regs #( + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0, + parameter int unsigned N_REGS = 0 +) ( + input logic clk_i, + input logic rst_ni, + + // APB Interface + APB_BUS.Slave apb, + + // Register Interface + input logic [N_REGS-1:0][DATA_WIDTH-1:0] init_i, + output logic [N_REGS-1:0][DATA_WIDTH-1:0] q_o +); + + localparam int unsigned STRB_WIDTH = DATA_WIDTH/8; + localparam int unsigned WORD_OFF = $clog2(STRB_WIDTH); + + logic [N_REGS-1:0][DATA_WIDTH-1:0] reg_d, reg_q; + + always_comb begin + reg_d = reg_q; + apb.prdata = 'x; + apb.pslverr = 1'b0; + if (apb.psel) begin + automatic logic [ADDR_WIDTH-WORD_OFF-1:0] word_addr = apb.paddr >> WORD_OFF; + if (word_addr >= N_REGS) begin + // Error response to accesses that are out of range + apb.pslverr = 1'b1; + end else begin + if (apb.pwrite) begin + reg_d[word_addr] = apb.pwdata; + // TODO: handle after upgrade to APBv2 + //for (int i = 0; i < STRB_WIDTH; i++) begin + // if (apb.pstrb[i]) begin + // reg_d[word_addr][i*8 +: 8] = apb.pwdata[i*8 +: 8]; + // end + //end + end else begin + apb.prdata = reg_q[word_addr]; + end + end + end + end + assign apb.pready = apb.psel & apb.penable; + + assign q_o = reg_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + reg_q <= init_i; + end else begin + reg_q <= reg_d; + end + end + + // Validate parameters. + // pragma translate_off + `ifndef VERILATOR + initial begin: p_assertions + assert (N_REGS >= 1) else $fatal(1, "The number of registers must be at least 1!"); + end + `endif + // pragma translate_on + +endmodule diff --git a/hw/src/apb/apb_stdout.sv b/hw/src/apb/apb_stdout.sv new file mode 100644 index 0000000..3e44ae7 --- /dev/null +++ b/hw/src/apb/apb_stdout.sv @@ -0,0 +1,70 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +module apb_stdout #( + parameter int unsigned N_CORES = 0, + parameter int unsigned N_CLUSTERS = 0, + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0 +) ( + input logic clk_i, + input logic rst_ni, + APB_BUS.Slave apb +); + `ifndef VERILATOR + byte buffer [N_CLUSTERS-1:0][N_CORES-1:0][$]; + + function void flush(int unsigned i_cl, int unsigned i_core); + automatic string s; + for (int i_char = 0; i_char < buffer[i_cl][i_core].size(); i_char++) begin + s = $sformatf("%s%c", s, buffer[i_cl][i_core][i_char]); + end + if (s.len() > 0) begin + $display("[%01d,%01d] %s", i_cl, i_core, s); + end + buffer[i_cl][i_core] = {}; + endfunction + + function void append(int unsigned i_cl, int unsigned i_core, byte ch); + if (ch == 8'hA) begin + flush(i_cl, i_core); + end else begin + buffer[i_cl][i_core].push_back(ch); + end + endfunction + + always_ff @(posedge clk_i or negedge rst_ni) begin + int unsigned cl_idx, core_idx; + byte data; + if (!rst_ni) begin + for (int i_cl = 0; i_cl < N_CLUSTERS; i_cl++) begin + for (int i_core = 0; i_core < N_CORES; i_core++) begin + flush(i_cl, i_core); + end + end + end else begin + if (apb.psel && apb.penable && apb.pwrite) begin + cl_idx = (apb.paddr >> 7) & 32'hF; + core_idx = (apb.paddr >> 3) & 32'hF; + if (cl_idx < N_CLUSTERS && core_idx < N_CORES) begin + data = apb.pwdata & 32'hFF; + append(cl_idx, core_idx, data); + end + end + end + end + `endif + + assign apb.prdata = '0; + assign apb.pslverr = 1'b0; + assign apb.pready = 1'b1; + + +endmodule diff --git a/hw/src/cmds/cluster_cmd.sv b/hw/src/cmds/cluster_cmd.sv new file mode 100644 index 0000000..08500e9 --- /dev/null +++ b/hw/src/cmds/cluster_cmd.sv @@ -0,0 +1,50 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +module cluster_cmd #( + parameter int unsigned NUM_CORES = 8 +) ( + input logic clk_i, + input logic rst_ni, + + //from hpu drivers (commands) + output logic [NUM_CORES-1:0] cmd_ready_o, + input logic [NUM_CORES-1:0] cmd_valid_i, + input pspin_cmd_t [NUM_CORES-1:0] cmd_i, + + //to uncluster + input logic cmd_ready_i, + output logic cmd_valid_o, + output pspin_cmd_t cmd_o +); + + rr_arb_tree #( + .NumIn (NUM_CORES), + .DataType (pspin_cmd_t), + .ExtPrio (0), + .AxiVldRdy (1), + .LockIn (1) + ) i_cluster_cmd_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .rr_i ('0), + .req_i (cmd_valid_i), + .gnt_o (cmd_ready_o), + .data_i (cmd_i), + .gnt_i (cmd_ready_i), + .req_o (cmd_valid_o), + .data_o (cmd_o), + .idx_o () + ); + +endmodule diff --git a/hw/src/cmds/cmd_unit.sv b/hw/src/cmds/cmd_unit.sv new file mode 100644 index 0000000..2e698c7 --- /dev/null +++ b/hw/src/cmds/cmd_unit.sv @@ -0,0 +1,212 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +module cmd_unit #( + parameter int unsigned NUM_CLUSTERS = 4, + parameter int unsigned NUM_CMD_INTERFACES = 2, + parameter int unsigned INTF_RESP_BUFF_SIZE = 8 +) ( + input logic clk_i, + input logic rst_ni, + + output logic [NUM_CLUSTERS-1:0] cmd_ready_o, + input logic [NUM_CLUSTERS-1:0] cmd_valid_i, + input pspin_cmd_t [NUM_CLUSTERS-1:0] cmd_i, + + output logic cmd_resp_valid_o, + output pspin_cmd_resp_t cmd_resp_o, + + input logic [NUM_CMD_INTERFACES-1:0] intf_ready_i, + output logic [NUM_CMD_INTERFACES-1:0] intf_valid_o, + output pspin_cmd_t [NUM_CMD_INTERFACES-1:0] intf_cmd_o, + + input logic [NUM_CMD_INTERFACES-1:0] intf_cmd_resp_valid_i, + input pspin_cmd_resp_t [NUM_CMD_INTERFACES-1:0] intf_cmd_resp_i +); + + /* spill registers from clusters */ + logic [NUM_CLUSTERS-1:0] cluster_cmd_ready; + logic [NUM_CLUSTERS-1:0] cluster_cmd_valid; + pspin_cmd_t [NUM_CLUSTERS-1:0] cluster_cmd; + + for (genvar i=0; i=8 + parameter int unsigned CUT_N_WORDS = 16384, // must be a power of 2 + parameter int unsigned N_PAR_CUTS_MUL = 4 +) ( + input logic clk_i, + input logic rst_ni, + AXI_BUS.Slave slv_a, + AXI_BUS.Slave slv_b +); + + // Properties of one memory cut, keep synchronized with instantiated macro. + //localparam int unsigned CUT_DW = 64; // [bit], must be a power of 2 and >=8 + //localparam int unsigned CUT_N_WORDS = 16384; // must be a power of 2 + localparam int unsigned CUT_N_BITS = CUT_DW * CUT_N_WORDS; + + // Derived properties of memory array + localparam int unsigned N_PAR_CUTS = N_PAR_CUTS_MUL * AXI_DW / CUT_DW; + localparam int unsigned PAR_CUTS_N_BYTES = N_PAR_CUTS * CUT_N_BITS / 8; + localparam int unsigned N_SER_CUTS = N_BYTES / PAR_CUTS_N_BYTES; + + localparam int unsigned MEM_ADDR_WIDTH = $clog2(CUT_N_WORDS * N_SER_CUTS); + typedef logic [N_PAR_CUTS-1:0][MEM_ADDR_WIDTH-1:0] mem_addr_t; + typedef logic [N_PAR_CUTS-1:0][CUT_DW-1:0] mem_data_t; + typedef logic [N_PAR_CUTS-1:0][CUT_DW/8-1:0] mem_strb_t; + typedef logic [N_PAR_CUTS-1:0] mem_logic_t; + + mem_logic_t mem_req, + mem_wen; + mem_addr_t mem_addr; + mem_data_t mem_wdata, + mem_rdata; + mem_strb_t mem_be; + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) internal_a (); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) internal_b (); + + axi_buf_intf #( + .AW_DEPTH (32'd2), + .W_DEPTH (32'd1), + .ADDR_WIDTH (AXI_AW), + .DATA_WIDTH (AXI_DW), + .ID_WIDTH (AXI_IW), + .USER_WIDTH (AXI_UW) + ) i_axi_a_buf ( + .clk_i, + .rst_ni, + .slv (slv_a), + .mst (internal_a) + ); + + axi_buf_intf #( + .AW_DEPTH (32'd2), + .W_DEPTH (32'd1), + .ADDR_WIDTH (AXI_AW), + .DATA_WIDTH (AXI_DW), + .ID_WIDTH (AXI_IW), + .USER_WIDTH (AXI_UW) + ) i_axi_b_buf ( + .clk_i, + .rst_ni, + .slv (slv_b), + .mst (internal_b) + ); + + axi_to_mem_banked_2p_intf #( + .AXI_ID_WIDTH (AXI_IW), + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_DW), + .AXI_USER_WIDTH (AXI_UW), + .MEM_NUM_BANKS (N_PAR_CUTS), + .MEM_ADDR_WIDTH (MEM_ADDR_WIDTH), + .MEM_DATA_WIDTH (CUT_DW), + .MEM_LATENCY (1), + .TOPOLOGY (tcdm_interconnect_pkg::LIC) + ) i_axi_to_mem_banked ( + .clk_i, + .rst_ni, + .test_i (1'b0), + .slv_a (internal_a), + .slv_b (internal_b), + .mem_req_o (mem_req), + .mem_gnt_i ({N_PAR_CUTS{1'b1}}), + .mem_add_o (mem_addr), + .mem_wen_o (mem_wen), + .mem_wdata_o (mem_wdata), + .mem_be_o (mem_be), + .mem_atop_o (/* unused */), + .mem_rdata_i (mem_rdata), + .axi_to_mem_busy_a_o (/* unused */), + .axi_to_mem_busy_b_o (/* unused */) + ); + + // Interface from memory array to memory cuts + localparam int unsigned WORD_IDX_OFF = 0; // output of `axi_to_mem_banked` is word-addressed + localparam int unsigned WORD_IDX_WIDTH = $clog2(CUT_N_WORDS); + localparam int unsigned ROW_IDX_OFF = WORD_IDX_OFF + WORD_IDX_WIDTH; + localparam int unsigned ROW_IDX_WIDTH = $clog2(N_SER_CUTS); + + // Types for memory cuts + typedef logic [$clog2(CUT_N_WORDS)-1:0] cut_addr_t; + typedef logic [CUT_DW-1:0] cut_data_t; + + logic [N_PAR_CUTS-1:0][N_SER_CUTS-1:0] cut_req; + cut_addr_t [N_PAR_CUTS-1:0] cut_addr_d, cut_addr_q; + cut_data_t [N_PAR_CUTS-1:0][N_SER_CUTS-1:0] cut_rdata; + logic [N_PAR_CUTS-1:0][ROW_IDX_WIDTH-1:0] row_idx_d, row_idx_q; + + for (genvar iCol = 0; iCol < N_PAR_CUTS; iCol++) begin : gen_cols + assign cut_addr_d[iCol] + = mem_req[iCol] ? mem_addr[iCol][WORD_IDX_OFF+:WORD_IDX_WIDTH] : cut_addr_q[iCol]; + + if (ROW_IDX_WIDTH > 0) begin : gen_row_idx + assign row_idx_d[iCol] + = mem_req[iCol] ? mem_addr[iCol][ROW_IDX_OFF+:ROW_IDX_WIDTH] : row_idx_q[iCol]; + always_comb begin + cut_req[iCol] = '0; + cut_req[iCol][row_idx_d[iCol]] = mem_req[iCol]; + end + assign mem_rdata[iCol] = cut_rdata[iCol][row_idx_q[iCol]]; + + end else begin : gen_no_row_idx + assign cut_req[iCol][0] = mem_req[iCol]; + assign mem_rdata[iCol] = cut_rdata[iCol][0]; + end + + for (genvar iRow = 0; iRow < N_SER_CUTS; iRow++) begin : gen_rows + sram #( + .DATA_WIDTH (CUT_DW), + .N_WORDS (CUT_N_WORDS) + ) i_mem_cut ( + .clk_i, + .rst_ni, + .req_i (cut_req[iCol][iRow]), + .we_i (mem_wen[iCol]), + .addr_i (cut_addr_d[iCol]), + .wdata_i (mem_wdata[iCol]), + .be_i (mem_be[iCol]), + .rdata_o (cut_rdata[iCol][iRow]) + ); + end + end + + `FFARN(cut_addr_q, cut_addr_d, '0, clk_i, rst_ni) + `FFARN(row_idx_q, row_idx_d, '0, clk_i, rst_ni) + + // Validate parameters and properties. + // pragma translate_off + initial begin + assert (AXI_AW > 0); + assert (AXI_AW % (2**$clog2(AXI_AW)) == 0); + assert (AXI_DW > 0); + assert (AXI_DW % (2**$clog2(AXI_DW)) == 0); + assert (N_BYTES > 0); + assert (N_BYTES % (2**$clog2(N_BYTES)) == 0); + assert (CUT_DW % (2**$clog2(CUT_DW)) == 0); + assert (CUT_DW >= 8); + assert (AXI_DW >= CUT_DW); + assert (CUT_N_WORDS % 2**$clog2(CUT_N_WORDS) == 0); + assert (N_BYTES % PAR_CUTS_N_BYTES == 0); + end + // pragma translate_on + +endmodule diff --git a/hw/src/memories/prog_mem.sv b/hw/src/memories/prog_mem.sv new file mode 100644 index 0000000..6397202 --- /dev/null +++ b/hw/src/memories/prog_mem.sv @@ -0,0 +1,163 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +`include "axi/typedef.svh" +`include "common_cells/registers.svh" + +/// Program memory shared by all clusters, with an additional port for the host to deploy handler +/// code. +module prog_mem #( + parameter int unsigned NumClusters = 0, + parameter int unsigned NumBytes = 0, + parameter int unsigned AddrWidth = 0, + parameter int unsigned DataWidth = 0, + parameter int unsigned IdWidth = 0, + parameter int unsigned UserWidth = 0, + parameter type req_t = logic, + parameter type resp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input req_t [NumClusters-1:0] cl_req_i, + output resp_t [NumClusters-1:0] cl_resp_o, + input req_t host_req_i, + output resp_t host_resp_o +); + + // Types of input and output channels. + typedef logic [AddrWidth-1:0] addr_t; + typedef logic [DataWidth-1:0] data_t; + typedef logic [IdWidth-1:0] id_t; + typedef logic [DataWidth/8-1:0] strb_t; + typedef logic [UserWidth-1:0] user_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_t, data_t, id_t, user_t) + + // Slave ports of multiplexer. + localparam int unsigned NumSlvPorts = NumClusters + 1; + req_t [NumSlvPorts-1:0] req; + resp_t [NumSlvPorts-1:0] resp; + for (genvar i = 0; i < NumSlvPorts; i++) begin : gen_bind_slv_ports + if (i < NumClusters) begin : gen_bind_cluster + assign req[i] = cl_req_i[i]; + assign cl_resp_o[i] = resp[i]; + end else begin : gen_bind_host + assign req[i] = host_req_i; + assign host_resp_o = resp[i]; + end + end + + // Types of master ports of multiplexer. + parameter int unsigned MuxIdWidth = IdWidth + cf_math_pkg::idx_width(NumSlvPorts); + typedef logic [MuxIdWidth-1:0] mux_id_t; + `AXI_TYPEDEF_AW_CHAN_T(mux_aw_t, addr_t, mux_id_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(mux_b_t, mux_id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(mux_ar_t, addr_t, mux_id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(mux_r_t, data_t, mux_id_t, user_t) + `AXI_TYPEDEF_REQ_T(mux_req_t, mux_aw_t, w_t, mux_ar_t) + `AXI_TYPEDEF_RESP_T(mux_resp_t, mux_b_t, mux_r_t) + mux_req_t mux_req; + mux_resp_t mux_resp; + // Instantiation of multiplexer. + axi_mux #( + .SlvAxiIDWidth (IdWidth), + .slv_aw_chan_t (aw_t), + .mst_aw_chan_t (mux_aw_t), + .w_chan_t (w_t), + .slv_b_chan_t (b_t), + .mst_b_chan_t (mux_b_t), + .slv_ar_chan_t (ar_t), + .mst_ar_chan_t (mux_ar_t), + .slv_r_chan_t (r_t), + .mst_r_chan_t (mux_r_t), + .slv_req_t (req_t), + .slv_resp_t (resp_t), + .mst_req_t (mux_req_t), + .mst_resp_t (mux_resp_t), + .NoSlvPorts (NumSlvPorts), + .MaxWTrans (1), + .FallThrough (1'b0), + .SpillAw (1'b0), + .SpillW (1'b0), + .SpillB (1'b0), + .SpillAr (1'b0), + .SpillR (1'b0) + ) i_mux ( + .clk_i, + .rst_ni, + .test_i (1'b0), + .slv_reqs_i (req), + .slv_resps_o (resp), + .mst_req_o (mux_req), + .mst_resp_i (mux_resp) + ); + + // AXI-to-memory converter + logic mem_req, + mem_req_q, + mem_we; + addr_t axi_to_mem_addr; + data_t mem_rdata, + mem_wdata; + strb_t mem_strb; + axi_to_mem #( + .axi_req_t (mux_req_t), + .axi_resp_t (mux_resp_t), + .AddrWidth (AddrWidth), + .DataWidth (DataWidth), + .IdWidth (MuxIdWidth), + .NumBanks (1), + .BufDepth (1) + ) i_axi_to_mem ( + .clk_i, + .rst_ni, + .busy_o (/* unused */), + .axi_req_i (mux_req), + .axi_resp_o (mux_resp), + .mem_req_o (mem_req), + .mem_gnt_i (1'b1), + .mem_addr_o (axi_to_mem_addr), + .mem_wdata_o (mem_wdata), + .mem_strb_o (mem_strb), + .mem_atop_o (/* unsupported */), + .mem_we_o (mem_we), + .mem_rvalid_i (mem_req_q), + .mem_rdata_i (mem_rdata) + ); + `FFARN(mem_req_q, mem_req, 1'b0, clk_i, rst_ni) + + // Truncation of addresses into SRAM + localparam int unsigned NumWords = NumBytes / (DataWidth / 8); + localparam int unsigned ByteOffset = $clog2(DataWidth / 8); + localparam int unsigned MemAddrWidth = cf_math_pkg::idx_width(NumWords); + typedef logic [MemAddrWidth-1:0] mem_addr_t; + mem_addr_t mem_addr; + assign mem_addr = axi_to_mem_addr[ByteOffset+:MemAddrWidth]; + + // SRAM macro + sram #( + .DATA_WIDTH (DataWidth), + .N_WORDS (NumWords) + ) i_sram ( + .clk_i, + .rst_ni, + .req_i (mem_req), + .we_i (mem_we), + .addr_i (mem_addr), + .wdata_i (mem_wdata), + .be_i (mem_strb), + .rdata_o (mem_rdata) + ); + +endmodule diff --git a/hw/src/memories/sram.sv b/hw/src/memories/sram.sv new file mode 100644 index 0000000..a42154b --- /dev/null +++ b/hw/src/memories/sram.sv @@ -0,0 +1,52 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +// TODO: Replace behavior with instantiation of cuts. + +module sram #( + parameter int unsigned DATA_WIDTH = 0, // [bit] + parameter int unsigned N_WORDS = 0, + parameter SimInit = "none", + // Dependent parameters, do not override! + parameter int unsigned N_BYTES = DATA_WIDTH/8, + parameter type addr_t = logic[$clog2(N_WORDS)-1:0], + parameter type data_t = logic[DATA_WIDTH-1:0], + parameter type strb_t = logic[N_BYTES-1:0] +) ( + input logic clk_i, + input logic rst_ni, + input logic req_i, + input logic we_i, + input addr_t addr_i, + input data_t wdata_i, + input strb_t be_i, + output data_t rdata_o +); + + tc_sram #( + .NumWords ( N_WORDS ), + .DataWidth ( DATA_WIDTH ), + .ByteWidth ( 8 ), + .NumPorts ( 1 ), + .Latency ( 1 ), + .SimInit ( SimInit ), + .PrintSimCfg ( 1'b0 ) + ) i_tc_sram ( + .clk_i, + .rst_ni, + .req_i, + .we_i, + .addr_i, + .wdata_i, + .be_i, + .rdata_o + ); + +endmodule diff --git a/hw/src/pkt_scheduler/cluster_rb.sv b/hw/src/pkt_scheduler/cluster_rb.sv new file mode 100644 index 0000000..2e7c719 --- /dev/null +++ b/hw/src/pkt_scheduler/cluster_rb.sv @@ -0,0 +1,190 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +/* + An allocator which manages memory as a ring-buffer. All allocations requests + are always served from the tail_ptr. It allocates only contiguous memory regions, so + an allocation cannot wrap around: + - if head_ptr =< tail_ptr, the available space is max(mem_region_end - tail_ptr, head_ptr). + - if head_ptr > tail_ptr, the available space is head_ptr - tail_ptr. + + Free are not treated as FIFO pops, but they came with their own memory index, i.e., the index + at which the memory region to free starts, and size. A memory index to free is not necesserly + equal to the head_ptr but can be samewhere in between head_ptr and tail_ptr. The head_ptr is + moved forward only when there is a consecutive free memory region in front of it. +*/ + +module cluster_rb #( + parameter int unsigned BuffMemLength = 1, + parameter int unsigned MemSlotSize = 64, //[B] + + //derived parameters + parameter type elem_size_t = logic [$clog2(BuffMemLength):0], + parameter type elem_idx_t = logic [$clog2(BuffMemLength)-1:0], + parameter int unsigned NumSlots = BuffMemLength / MemSlotSize +) ( + + input logic clk_i, + input logic rst_ni, + + input logic alloc_valid_i, + output logic alloc_ready_o, + input elem_size_t alloc_size_i, //[B] + output elem_idx_t alloc_index_o, //[B] + + input logic free_valid_i, + input elem_idx_t free_index_i, //[B] + input elem_size_t free_size_i, //[B] + + output elem_size_t free_space_o //[B] +); + + /* we take the minimum allocatable unit as parameter, this is MemSlotSize. + Internally, we represent memory as a sequence of blocks of size MemSlotSize. + */ + typedef logic [$clog2(NumSlots)-1:0] slot_ptr_t; + typedef logic [$clog2(NumSlots):0] slot_size_t; + + logic [NumSlots-1:0] bitmap_d; + logic [NumSlots-1:0] bitmap_q; + + slot_ptr_t head_ptr_d, head_ptr_q; + slot_ptr_t tail_ptr_d, tail_ptr_q; + + slot_ptr_t push_idx, pop_idx; + slot_size_t push_size, pop_size; + + logic [NumSlots*2-1:0] bitmap_to_shift; + logic [NumSlots-1:0] bitmap_shifted; + + logic push_en, pop_en; + + slot_ptr_t head_ptr_incr_lzc; + slot_size_t head_ptr_incr; + slot_size_t head_ptr_incr_max; + slot_size_t head_ptr_incr_real; + logic no_head_ptr_incr; + + slot_size_t padding; + logic data_fits; + + logic equal_full, equal_empty; + + slot_size_t free_slots, free_slots_to_end, free_slots_to_head; + + //the idea is to store the status of the memory blocks in a bitmap. + for (genvar i=0; i= push_idx && i < push_idx + push_size) || (pop_en && i >= pop_idx && i < pop_idx + pop_size)); + end + + //the bitmap is shifted right by head_ptr_q, so to let lzc count the number of consecutive free blocks and use + //that information to update head_ptr_q. + + assign head_ptr_incr_max = (tail_ptr_q >= head_ptr_q) ? tail_ptr_q - head_ptr_q : tail_ptr_q + NumSlots - head_ptr_q; + assign head_ptr_incr = head_ptr_incr_lzc + no_head_ptr_incr; + assign head_ptr_incr_real = (head_ptr_incr_max > head_ptr_incr) ? head_ptr_incr : head_ptr_incr_max; + + assign bitmap_to_shift = { bitmap_q, bitmap_q } ; // input is the 512 bit bitmap + assign bitmap_shifted = bitmap_to_shift[head_ptr_q +: NumSlots]; + + //get increment of head_ptr; + lzc #( + .WIDTH (NumSlots) + ) i_lzc_head_ptr_incr ( + .in_i (bitmap_shifted), + .cnt_o (head_ptr_incr_lzc), + .empty_o (no_head_ptr_incr) + ); + + + assign push_en = data_fits && alloc_valid_i; + assign pop_en = free_valid_i; + + assign pop_idx = free_index_i / MemSlotSize; + assign push_idx = tail_ptr_q + padding; + + assign push_size = (alloc_size_i + MemSlotSize - 1) / MemSlotSize; + assign pop_size = (free_size_i + MemSlotSize - 1) / MemSlotSize; + + assign alloc_ready_o = push_en; + assign alloc_index_o = push_idx * MemSlotSize; + + assign equal_full = (head_ptr_q == tail_ptr_q && bitmap_q > 0); + assign equal_empty = (head_ptr_q == tail_ptr_q && bitmap_q == 0); + + //meaningful only if tail_ptr_q >= head_ptr_q + assign free_slots_to_end = NumSlots - tail_ptr_q; + assign free_slots_to_head = head_ptr_q; + + assign free_space_o = free_slots * MemSlotSize; + + //determine number of consecutive slots available + always_comb begin + free_slots = 0; + if (!equal_full) begin + if (head_ptr_q <= tail_ptr_q) begin + free_slots = (free_slots_to_end > free_slots_to_head) ? free_slots_to_end : free_slots_to_head; + end + else begin + free_slots = head_ptr_q - tail_ptr_q; + end + end + end + + always_comb begin + head_ptr_d = head_ptr_q + head_ptr_incr_real; + tail_ptr_d = (push_en) ? tail_ptr_q + padding + push_size : tail_ptr_q; + + //if everything is quiet and the buffer is empty, reset the pointers to zero + //so to regain the full space. + if (!push_en && !pop_en && equal_empty) begin + head_ptr_d = '0; + tail_ptr_d = '0; + end + end + + //check if data fits + always_comb begin + data_fits = 1'b0; + padding = '0; + + if (!equal_full) begin + if (head_ptr_q <= tail_ptr_q) begin + if (NumSlots - tail_ptr_q >= push_size) begin + // |<- start | <- pop | <-push [data fits here] | <- end + data_fits = 1'b1; + end + else if (push_size < head_ptr_q) begin //FIXME: this should be <= ? + // |<- start [data fits here] | <- pop | <-push | <- end + //push doesn't fit there, we start from 0 + data_fits = 1'b1; + padding = NumSlots - tail_ptr_q; + end + end + else if (tail_ptr_q - head_ptr_q >= push_size) begin + // |<- start | <- push [data fits here] | <-pop | <- end + data_fits = 1'b1; + end + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + bitmap_q <= '0; + head_ptr_q <= '0; + tail_ptr_q <= '0; + end else begin + bitmap_q <= bitmap_d; + head_ptr_q <= head_ptr_d; + tail_ptr_q <= tail_ptr_d; + end + end + +endmodule diff --git a/hw/src/pkt_scheduler/cluster_scheduler.sv b/hw/src/pkt_scheduler/cluster_scheduler.sv new file mode 100644 index 0000000..8a8c424 --- /dev/null +++ b/hw/src/pkt_scheduler/cluster_scheduler.sv @@ -0,0 +1,298 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +module cluster_scheduler #( + parameter int NUM_HERS_PER_CLUSTER = 64, + parameter int L1_PKT_BUFF_SIZE = 512, + parameter int L1_CLUSTER_BASE = 0, + parameter int L1_CLUSTER_MEM_SIZE = 0, + parameter int L1_RUNTIME_OFFSET = 0, + parameter int TASKS_FIFO_DEPTH = 1 +) ( + + input logic clk_i, + input logic rst_ni, + + input logic [5:0] cluster_id_i, + + //task from scheduler + input logic task_valid_i, + output logic task_ready_o, + input handler_task_t task_descr_i, + + //feedback to scheduler + output logic feedback_valid_o, + input logic feedback_ready_i, + output feedback_descr_t feedback_o, + + //dma request to DMA engine + output logic dma_xfer_valid_o, + input logic dma_xfer_ready_i, + output transf_descr_32_t dma_xfer_o, + + //dma response from DMA engine + input logic dma_resp_i, + + //task_descr_t to HPU + output logic [NUM_CORES-1:0] hpu_task_valid_o, + input logic [NUM_CORES-1:0] hpu_task_ready_i, + output hpu_handler_task_t hpu_task_o, + + //feedback from HPUs + input logic [NUM_CORES-1:0] hpu_feedback_valid_i, + output logic [NUM_CORES-1:0] hpu_feedback_ready_o, + input task_feedback_descr_t [NUM_CORES-1:0] hpu_feedback_i, + + //activation signal from HPUs + input logic [NUM_CORES-1:0] hpu_active_i, + + //activation signal out + output logic cluster_active_o +); + + localparam int unsigned PktBuffMemSlotSize = 64; + typedef logic [$clog2(L1_PKT_BUFF_SIZE):0] pkt_buf_size_t; + typedef logic [$clog2(L1_PKT_BUFF_SIZE)-1:0] pkt_buf_idx_t; + + logic [$clog2(NUM_HERS_PER_CLUSTER):0] to_pop_d; + logic [$clog2(NUM_HERS_PER_CLUSTER):0] to_pop_q; + + //tasks which DMA xfers are still in-flight + logic dma_req_empty; + logic dma_req_full; + //set if a request has been popped (i.e., dma resp recvd + assigned to core) + logic dma_req_pop, dma_req_pop_nz; + hpu_handler_task_t ready_task; + hpu_handler_task_t new_task; + + //true if we can issue a DMA transfer a + logic can_issue_dma; + + logic [31:0] l1_pkt_base_addr; + logic [31:0] l1_pkt_ptr; + + //free HPUs + logic [$clog2(NUM_CORES)-1:0] free_hpu_idx; + logic no_free_hpu; + + //L1 packet buffer + pkt_buf_idx_t free_pkt_idx; + pkt_buf_idx_t feedback_pkt_idx; + pkt_buf_size_t pkt_buff_free_space; + + //true if the HER allocator is ready + logic pkt_alloc_ready; //unused in synthesis + + //internal state + typedef enum logic {Ready, WaitDMA} state_t; + state_t state_d, state_q; + + transf_descr_32_t dma_xfer, dma_xfer_q, dma_xfer_d; + + // buffer the tasks in a fifo + fifo_v3 #( + .dtype (hpu_handler_task_t), + .DEPTH (NUM_HERS_PER_CLUSTER) + ) i_dma_request_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i(1'b0), + .full_o (dma_req_full), + .empty_o (dma_req_empty), + .usage_o (), + .data_i (new_task), + .push_i (task_valid_i && task_ready_o), + .data_o (ready_task), + .pop_i (dma_req_pop) + ); + + //idle HPUs + lzc #( + .WIDTH (NUM_CORES) + ) i_lzc_free_hpus ( + .in_i (hpu_task_ready_i), + .cnt_o (free_hpu_idx), + .empty_o (no_free_hpu) + ); + + // Packet buffer allocator + cluster_rb #( + .BuffMemLength (L1_PKT_BUFF_SIZE), + .MemSlotSize (PktBuffMemSlotSize) + ) i_her_alloc ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .alloc_valid_i (task_valid_i && task_ready_o), + .alloc_ready_o (pkt_alloc_ready), + .alloc_size_i (task_descr_i.pkt_size[$clog2(L1_PKT_BUFF_SIZE):0]), + .alloc_index_o (free_pkt_idx), + + .free_valid_i (feedback_valid_o && feedback_ready_i), + .free_index_i (feedback_pkt_idx), + .free_size_i (hpu_feedback_arb_i.feedback_descr.pkt_size[$clog2(L1_PKT_BUFF_SIZE):0]), + + .free_space_o (pkt_buff_free_space) + ); + + // HPU feedbacks to cluster feedback arbiter + task_feedback_descr_t hpu_feedback_arb_i; + rr_arb_tree #( + .NumIn (NUM_CORES), + .DataType (task_feedback_descr_t), + .ExtPrio (0), + .AxiVldRdy (1), + .LockIn (1) + ) i_hpu_feedback_rr_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .rr_i ('0), + .req_i (hpu_feedback_valid_i), + .gnt_o (hpu_feedback_ready_o), + .data_i (hpu_feedback_i), + .gnt_i (feedback_ready_i), + .req_o (feedback_valid_o), + .data_o (hpu_feedback_arb_i), + .idx_o () + ); + + assign cluster_active_o = (~hpu_active_i == '0); + + assign l1_pkt_base_addr = (L1_CLUSTER_BASE + cluster_id_i * L1_CLUSTER_MEM_SIZE) + L1_PKT_BUFF_OFFSET; + assign l1_pkt_ptr = l1_pkt_base_addr + free_pkt_idx; + assign feedback_pkt_idx = hpu_feedback_arb_i.pkt_ptr - l1_pkt_base_addr; + + /*** Accepting tasks and starting DMA xfers ***/ + + //define a new task + assign new_task.handler_task = task_descr_i; + assign new_task.pkt_ptr = l1_pkt_ptr; + + //define DMA xfer + assign can_issue_dma = task_valid_i && task_ready_o && task_descr_i.pkt_size != '0; + + assign dma_xfer.num_bytes = task_descr_i.pkt_size; + assign dma_xfer.src_addr = task_descr_i.pkt_addr; + assign dma_xfer.dst_addr = l1_pkt_ptr; + + assign dma_xfer.decouple = 1'b1; + assign dma_xfer.deburst = 1'b0; + assign dma_xfer.serialize = 1'b0; // TODO: connect me! + + assign dma_xfer_d = (state_q == Ready) ? dma_xfer : dma_xfer_q; + assign dma_xfer_o = (state_q == Ready) ? dma_xfer : dma_xfer_q; + assign dma_xfer_valid_o = (state_d == Ready && can_issue_dma) || (state_q == WaitDMA); + + //we are ready to accept new tasks if + // - we are in Ready state AND + // - we can buffer the new DMA xfer AND + // - we have an HER in L1 where we can copy the L2 HER + //This is a bit redundant because we expect the scheduler to not forward + //us tasks if we are at capacity. + assign task_ready_o = (state_q == Ready) && (!dma_req_full) && (pkt_buff_free_space >= task_descr_i.pkt_size); + + always_comb begin + state_d = state_q; + + case (state_q) + Ready: begin + //we don't issue a DMA transfer for zero-byte task (e.g., header, completion) + if (can_issue_dma) begin + state_d = (dma_xfer_ready_i) ? Ready : WaitDMA; + end + end + + WaitDMA: begin + if (dma_xfer_ready_i) begin + state_d = Ready; + end + end + endcase + end + + /*** Other side of the FIFO: popping and assigning to free HPUs ***/ + + //we pop if there is a free HPU and if there is a completed xfer + assign dma_req_pop = !dma_req_empty && !no_free_hpu && (to_pop_q > 0 || ready_task.handler_task.pkt_size == 0); + + //this gets asserted if we are popping an entry associated with an actual DMA transfer. + assign dma_req_pop_nz = !dma_req_empty && !no_free_hpu && to_pop_q > 0 && ready_task.handler_task.pkt_size > 0; + + //ready hput tasks goes to all HPUs' outputs but only one will be enabled + assign hpu_task_o = ready_task; + for (genvar i = 0; i < NUM_CORES; i++) begin : gen_hpu_task + assign hpu_task_valid_o[i] = dma_req_pop & (i == free_hpu_idx); + end + + /*** Feedback forwarding ***/ + assign feedback_o = hpu_feedback_arb_i.feedback_descr; + + + /*** Internal state ***/ + + //count how many DMA xfers can be popped. + //+1 if we get a DMA completion but do not pop at this cycle (e.g., no free HPU) + //-1 if we can pop at this cycle but did not get a DMA completion + //+0 if we get a DMA completion and also pop in this cycle + always_comb begin + case ({dma_resp_i, dma_req_pop_nz}) + 2'b10 : to_pop_d = to_pop_q + 1; + 2'b01 : to_pop_d = to_pop_q - 1; + default : to_pop_d = to_pop_q; + endcase + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + to_pop_q <= '0; + state_q <= Ready; + dma_xfer_q <= '0; + end else begin + to_pop_q <= to_pop_d; + state_q <= state_d; + dma_xfer_q <= dma_xfer_d; + end + end + + `ifndef VERILATOR + // pragma translate_off + initial begin + forever begin + @(posedge clk_i); + if (task_valid_i && task_ready_o) begin + $display("%0d CLUSTER %0d got task (msg_id: %0d; size: %0d; addr: %0d)!", $time, cluster_id_i, task_descr_i.msgid, task_descr_i.pkt_size, task_descr_i.pkt_addr); + + if (dma_xfer_valid_o && dma_xfer_ready_i && dma_xfer.src_addr[5:0] != '0) begin + $display("WARNING: source address of DMA transfer is not 512-bit aligned: this will negatively impact performance!"); + end + if (dma_xfer_valid_o && dma_xfer_ready_i && dma_xfer.dst_addr[5:0] != '0) begin + $display("WARNING: destination address of DMA transfer is not 512-bit aligned: this will negatively impact performance!"); + end + end + end + end + + initial begin : p_assertions + + assert property (@(posedge clk_i) (dma_req_pop) |-> (!dma_req_empty)) else + $fatal(1, "We cannot pop from an empty queue!"); + + assert property (@(posedge clk_i) (task_valid_i && task_ready_o) |-> (pkt_buff_free_space >= task_descr_i.pkt_size)) else + $fatal(1, "We received a packet that cannot store!"); + + end + // pragma translate_on + `endif + +endmodule \ No newline at end of file diff --git a/hw/src/pkt_scheduler/fifo_engine.sv b/hw/src/pkt_scheduler/fifo_engine.sv new file mode 100644 index 0000000..116bd7f --- /dev/null +++ b/hw/src/pkt_scheduler/fifo_engine.sv @@ -0,0 +1,221 @@ +// Copyright (c) 2020 ETH Zurich and 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 does not work if we are pushing and popping at the same time +// from a queue of size 0 +module fifo_engine #( + //dynamic cells + parameter int NUM_CELLS = 64, + parameter int NUM_FIFO = 16, + parameter int NUM_STATIC_CELLS_PER_FIFO = 4, + parameter type elem_t = logic, + + //do not touch! + parameter int TOT_STATIC_CELLS = NUM_STATIC_CELLS_PER_FIFO * NUM_FIFO, + parameter int TOT_CELLS = TOT_STATIC_CELLS + NUM_CELLS, + parameter type fifo_id_t = logic [$clog2(NUM_FIFO)-1:0], + parameter type cell_id_t = logic [$clog2(TOT_CELLS)-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + //push interface + input elem_t new_el_i, + input logic push_i, + input fifo_id_t fifo_push_id_i, + + //pop interface + input logic pop_i, + input fifo_id_t fifo_pop_id_i, + output elem_t data_o, + + //output interface + output logic empty_o, + output logic [NUM_FIFO-1:0] fifo_full_o +); + + typedef struct packed { + cell_id_t next; + logic is_last; + } cell_t; + + localparam int unsigned ELEM_SIZE = $bits(elem_t); + localparam int unsigned ELEM_SIZE_B = $bits(elem_t)/8; + + cell_t [TOT_CELLS-1:0] cells_q; + cell_t [TOT_CELLS-1:0] cells_d; + + logic [TOT_CELLS-1:0] free_cells_d; + logic [TOT_CELLS-1:0] free_cells_q; + + cell_id_t [NUM_FIFO-1:0] fifo_head_d; + cell_id_t [NUM_FIFO-1:0] fifo_head_q; + + cell_id_t [NUM_FIFO-1:0] fifo_last_d; + cell_id_t [NUM_FIFO-1:0] fifo_last_q; + + logic [NUM_FIFO-1:0] fifo_empty_q; + logic [NUM_FIFO-1:0] fifo_empty_d; + + logic [NUM_FIFO-1:0][$clog2(NUM_STATIC_CELLS_PER_FIFO):0] fifo_static_occup_q; + logic [NUM_FIFO-1:0][$clog2(NUM_STATIC_CELLS_PER_FIFO):0] fifo_static_occup_d; + + cell_id_t free_dynamic_cell_idx; + cell_id_t free_static_cell_idx, free_static_cell_idx_lzc; + cell_id_t push_cell_idx, pop_cell_idx; + logic no_free_dynamic_cells, no_free_static_cells; + logic pushing_to_static; + logic popping_from_static; + + // free dynamic slots + assign free_dynamic_cell_idx[$clog2(TOT_CELLS)-1:$clog2(NUM_CELLS)] = '0; + lzc #( + .WIDTH (NUM_CELLS) + ) i_lzc_dynamic_free_slots ( + .in_i (~(free_cells_q[NUM_CELLS-1:0])), + .cnt_o (free_dynamic_cell_idx[$clog2(NUM_CELLS)-1:0]), + .empty_o (no_free_dynamic_cells) + ); + + // free static slots + assign free_static_cell_idx = free_static_cell_idx_lzc + NUM_CELLS; + assign free_static_cell_idx_lzc[$clog2(TOT_CELLS)-1:$clog2(TOT_STATIC_CELLS)] = '0; + lzc #( + .WIDTH (TOT_STATIC_CELLS) + ) i_lzc_static_free_slots ( + .in_i (~(free_cells_q[TOT_CELLS-1:NUM_CELLS])), + .cnt_o (free_static_cell_idx_lzc[$clog2(TOT_STATIC_CELLS)-1:0]), + .empty_o (no_free_static_cells) + ); + + //memory for storing FIFO entries + elem_t fifo_data_ignored; + tc_sram #( + .NumWords (TOT_CELLS), + .DataWidth (ELEM_SIZE), + .NumPorts (2) + ) i_fifo_data ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .req_i ({push_i, 1'b1}), + .we_i ({push_i, 1'b0}), + .addr_i ({push_cell_idx, pop_cell_idx}), + .wdata_i ({new_el_i, {ELEM_SIZE{1'b0}}}), + .be_i ({{ELEM_SIZE_B{1'b1}}, {ELEM_SIZE_B{1'b0}}}), + .rdata_o ({fifo_data_ignored, data_o}) + ); + + //output + assign empty_o = (free_cells_q == '0); + + for (genvar i=0; i= NUM_CELLS); + + assign pop_cell_idx = fifo_head_q[fifo_pop_id_i]; + + always_comb begin + free_cells_d = free_cells_q; + + if (push_i) begin + free_cells_d[push_cell_idx] = 1'b1; + end + + if (pop_i) begin + free_cells_d[fifo_head_q[fifo_pop_id_i]] = 1'b0; + end + end + + //static cells occupation + always_comb begin + fifo_static_occup_d = fifo_static_occup_q; + + if (push_i && pop_i && fifo_push_id_i == fifo_pop_id_i) begin + //special case: we are pushing and popping from the same MPQ + case ({pushing_to_static, popping_from_static}) + 2'b10: fifo_static_occup_d[fifo_push_id_i] = fifo_static_occup_q[fifo_push_id_i] + 1; + 2'b01: fifo_static_occup_d[fifo_push_id_i] = fifo_static_occup_q[fifo_push_id_i] - 1; + endcase + end else begin + //we are popping/pushing on different MPQs or we are either popping or pushing + //to the same MPQ. + if (push_i && pushing_to_static) begin + fifo_static_occup_d[fifo_push_id_i] = fifo_static_occup_q[fifo_push_id_i] + 1; + end + + if (pop_i && popping_from_static) begin + fifo_static_occup_d[fifo_pop_id_i] = fifo_static_occup_q[fifo_pop_id_i] - 1; + end + end + end + + //pointers + always_comb begin + fifo_last_d = fifo_last_q; + fifo_head_d = fifo_head_q; + cells_d = cells_q; + fifo_empty_d = fifo_empty_q; + + if (push_i && pop_i && fifo_push_id_i == fifo_pop_id_i && cells_q[fifo_head_q[fifo_push_id_i]].is_last) begin + fifo_head_d[fifo_pop_id_i] = push_cell_idx; + fifo_last_d[fifo_push_id_i] = push_cell_idx; + + cells_d[push_cell_idx].is_last = 1'b1; + + end else begin + if (push_i) begin + + fifo_last_d[fifo_push_id_i] = push_cell_idx; + cells_d[push_cell_idx].is_last = 1'b1; + + if (fifo_empty_q[fifo_push_id_i]) begin + fifo_head_d[fifo_push_id_i] = push_cell_idx; + fifo_empty_d[fifo_push_id_i] = 1'b0; + end else begin + cells_d[fifo_last_q[fifo_push_id_i]].next = push_cell_idx; + cells_d[fifo_last_q[fifo_push_id_i]].is_last = 1'b0; + end + end + + if (pop_i) begin + fifo_head_d[fifo_pop_id_i] = cells_q[fifo_head_q[fifo_pop_id_i]].next; + fifo_empty_d[fifo_pop_id_i] = cells_q[fifo_head_q[fifo_pop_id_i]].is_last; + end + end + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + cells_q <= '0; + free_cells_q <= '0; + fifo_head_q <= '0; + fifo_last_q <= '0; + fifo_empty_q <= '1; + fifo_static_occup_q <= '0; + end else begin + cells_q <= cells_d; + free_cells_q <= free_cells_d; + fifo_head_q <= fifo_head_d; + fifo_last_q <= fifo_last_d; + fifo_empty_q <= fifo_empty_d; + fifo_static_occup_q <= fifo_static_occup_d; + end + end +endmodule diff --git a/hw/src/pkt_scheduler/hpu_driver.sv b/hw/src/pkt_scheduler/hpu_driver.sv new file mode 100644 index 0000000..6c738b9 --- /dev/null +++ b/hw/src/pkt_scheduler/hpu_driver.sv @@ -0,0 +1,884 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +module hpu_driver #( + parameter int C_CORE_ID = 0, + parameter int L1_PKT_BUFF_SIZE = 512, + parameter int NUM_CLUSTERS = 4, + parameter int NUM_SCRATCHPADS = 1, + parameter int NUM_HERS_PER_CLUSTER = 1, + parameter int L1_CLUSTER_BASE = 0, + parameter int L1_CLUSTER_MEM_SIZE = 0, + parameter int L1_RUNTIME_OFFSET = 0, + parameter int L1_SCRATCHPAD_SIZE = 4096, + parameter int NUM_CMDS = 4, + parameter int N_PMP_ENTRIES = 16 +) ( + input logic clk_i, + input logic rst_ni, + + input logic [5:0] cluster_id_i, + + //task in + input logic hpu_task_valid_i, + output logic hpu_task_ready_o, + input hpu_handler_task_t hpu_task_i, + + //feedback out + output logic hpu_feedback_valid_o, + input logic hpu_feedback_ready_i, + output task_feedback_descr_t hpu_feedback_o, + + //high if we are ready to accept tasks + output logic hpu_active_o, + + //core interface + XBAR_PERIPH_BUS.Slave hpu_driver_slave_i, + + //high if this core has no pending DMA requests + input logic no_dma_req_pending_i, + + //command out + input logic cmd_ready_i, + output logic cmd_valid_o, + output pspin_cmd_t cmd_o, + + //command completion notification in + input logic cmd_resp_valid_i, + input pspin_cmd_resp_t cmd_resp_i, + + //PMP configuration + output logic pmp_conf_override_o, + output logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_o, + output logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_o +); + + logic no_pending_cmd; + + //request destination: 0: task_frontend; 1: cmd_frontend; + logic [1:0] add_type_d; + logic [1:0] add_type_q; + assign add_type_d = hpu_driver_slave_i.add[8:7]; + + //word idx (max 32 words per add_type) + //logic [4:0] add_idx; + //assign add_idx = hpu_driver_slave_i.add[6:2]; + + //tf: task frontend; cf: cmd frontend + logic [3:0] frontend_req; + logic [3:0] frontend_gnt; + logic [3:0] frontend_r_valid; + logic [3:0][31:0] frontend_r_rdata; + + logic can_send_feedback; + logic cmd_resp_valid; + logic disable_commands; + + //NOTE: frontends 2 and 3 are unused (reserved for future extensions) + for (genvar i=0; i<4; i++) begin + assign frontend_req[i] = hpu_driver_slave_i.req && (add_type_d == i); + end + + for (genvar i=2; i<4; i++) begin + assign frontend_gnt[i] = 1'b0; + assign frontend_r_valid[i] = 1'b0; + assign frontend_r_rdata[i] = '0; + end + + assign hpu_driver_slave_i.gnt = frontend_gnt[add_type_d]; + + //we need to remember which output to pick because this will (eventually) + //be valid at the next cycle. + assign hpu_driver_slave_i.r_rdata = frontend_r_rdata[add_type_q]; + assign hpu_driver_slave_i.r_valid = frontend_r_valid[add_type_q]; + + assign can_send_feedback = no_dma_req_pending_i && no_pending_cmd; + + assign cmd_resp_valid = cmd_resp_valid_i && cmd_resp_i.cmd_id.cluster_id == cluster_id_i && cmd_resp_i.cmd_id.core_id == C_CORE_ID; + + task_frontend #( + .C_CORE_ID (C_CORE_ID), + .L1_PKT_BUFF_SIZE (L1_PKT_BUFF_SIZE), + .NUM_CLUSTERS (NUM_CLUSTERS), + .NUM_SCRATCHPADS (NUM_SCRATCHPADS), + .NUM_HERS_PER_CLUSTER (NUM_HERS_PER_CLUSTER), + .L1_CLUSTER_BASE (L1_CLUSTER_BASE), + .L1_CLUSTER_MEM_SIZE (L1_CLUSTER_MEM_SIZE), + .L1_RUNTIME_OFFSET (L1_RUNTIME_OFFSET), + .L1_SCRATCHPAD_SIZE (L1_SCRATCHPAD_SIZE), + .N_PMP_ENTRIES (N_PMP_ENTRIES) + ) i_task_frontend ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .cluster_id_i (cluster_id_i), + .hpu_task_valid_i (hpu_task_valid_i), + .hpu_task_ready_o (hpu_task_ready_o), + .hpu_task_i (hpu_task_i), + .hpu_feedback_valid_o (hpu_feedback_valid_o), + .hpu_feedback_ready_i (hpu_feedback_ready_i), + .hpu_feedback_o (hpu_feedback_o), + .hpu_active_o (hpu_active_o), + .req_i (frontend_req[0]), + .add_i (hpu_driver_slave_i.add), + .wen_ni (hpu_driver_slave_i.wen), + .wdata_i (hpu_driver_slave_i.wdata), + .be_i (hpu_driver_slave_i.be), + .gnt_o (frontend_gnt[0]), + .r_rdata_o (frontend_r_rdata[0]), + .r_valid_o (frontend_r_valid[0]), + .can_send_feedback_i (can_send_feedback), + .pmp_conf_override_o (pmp_conf_override_o), + .pmp_cfg_o (pmp_cfg_o), + .pmp_addr_o (pmp_addr_o), + .disable_commands_o (disable_commands) + ); + + cmd_frontend #( + .C_CORE_ID (C_CORE_ID), + .NUM_CMDS (NUM_CMDS), + .NUM_BUFFERED_CMD (NUM_CMDS) + ) i_cmd_frontend ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .cluster_id_i (cluster_id_i), + .req_i (frontend_req[1]), + .add_i (hpu_driver_slave_i.add), + .wen_ni (hpu_driver_slave_i.wen), + .wdata_i (hpu_driver_slave_i.wdata), + .be_i (hpu_driver_slave_i.be), + .gnt_o (frontend_gnt[1]), + .r_rdata_o (frontend_r_rdata[1]), + .r_valid_o (frontend_r_valid[1]), + + .cmd_resp_valid_i (cmd_resp_valid), + .cmd_resp_i (cmd_resp_i), + + .disabled_i (disable_commands), + .no_pending_cmd_o (no_pending_cmd), + + .cmd_ready_i (cmd_ready_i), + .cmd_valid_o (cmd_valid_o), + .cmd_o (cmd_o) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + add_type_q <= '0; + end else begin + add_type_q <= add_type_d; + end + end + +endmodule + + +module task_frontend #( + parameter int C_CORE_ID = 0, + parameter int L1_PKT_BUFF_SIZE = 512, + parameter int NUM_CLUSTERS = 4, + parameter int NUM_SCRATCHPADS = 1, + parameter int NUM_HERS_PER_CLUSTER = 1, + parameter int L1_CLUSTER_BASE = 0, + parameter int L1_CLUSTER_MEM_SIZE = 0, + parameter int L1_RUNTIME_OFFSET = 0, + parameter int L1_SCRATCHPAD_SIZE = 4096, + parameter int N_PMP_ENTRIES = 16 +) ( + input logic clk_i, + input logic rst_ni, + + input logic [5:0] cluster_id_i, + + //task in + input logic hpu_task_valid_i, + output logic hpu_task_ready_o, + input hpu_handler_task_t hpu_task_i, + + //feedback out + output logic hpu_feedback_valid_o, + input logic hpu_feedback_ready_i, + output task_feedback_descr_t hpu_feedback_o, + + output logic hpu_active_o, + + input logic req_i, + input logic [31:0] add_i, + input logic wen_ni, + input logic [31:0] wdata_i, + input logic [3:0] be_i, + output logic gnt_o, + output logic [31:0] r_rdata_o, + output logic r_valid_o, + + output logic disable_commands_o, + input logic can_send_feedback_i, + + output logic pmp_conf_override_o, + output logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_o, + output logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_o +); + + typedef enum logic [1:0] {Init, Idle, Running, SendingFeedback} state_t; + state_t state_d, state_q; + + hpu_handler_task_t current_task_q, current_task_d; + + logic trigger_feedback; + + logic valid_d, valid_q; + logic [31:0] rdata_d, rdata_q; + + logic [$clog2(NUM_SCRATCHPADS)-1:0] scratchpad_id; + logic [$clog2(NUM_CLUSTERS)-1:0] home_cluster_id; + + logic [31:0] l1_pkt_base_addr; // in this cluster + logic [NUM_CLUSTERS-1:0][31:0] l1_scratchpad_addr; //in the home cluster + + logic [31:0] l1_base_addr; + logic [31:0] l1_home_base_addr; + logic [31:0] l1_pkt_addr; + + logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_q; + logic [N_PMP_ENTRIES-1:0] [31:0] pmp_addr_d; + logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_q; + logic [N_PMP_ENTRIES-1:0] [7:0] pmp_cfg_d; + + + logic [31:0] handler_error_code; + logic handler_error; + + //buffer feedback waiting for command to complete + //NOTE: only one feedback at time can be buffered with this implementation! + task_feedback_descr_t hpu_feedback; + logic feedback_buff_full, feedback_buff_empty; + logic feedback_buff_push; + fifo_v3 #( + .dtype (task_feedback_descr_t), + .DEPTH (1) + ) i_hpu_cmd_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i(1'b0), + .full_o (feedback_buff_full), + .empty_o (feedback_buff_empty), + .usage_o (), + .data_i (hpu_feedback), + .push_i (feedback_buff_push), + .data_o (hpu_feedback_o), + .pop_i (hpu_feedback_ready_i && hpu_feedback_valid_o) + ); + + assign feedback_buff_push = !feedback_buff_full && (trigger_feedback || state_q==SendingFeedback); + assign disable_commands_o = !feedback_buff_empty; + + assign r_rdata_o = rdata_q; + assign r_valid_o = valid_q; + + //this way of determining addresses is super ugly but don't know how to make it nicer + assign scratchpad_id = current_task_q.handler_task.msgid[$clog2(NUM_CLUSTERS)+$clog2(NUM_SCRATCHPADS)-1:$clog2(NUM_CLUSTERS)]; + assign home_cluster_id = current_task_q.handler_task.msgid[$clog2(NUM_CLUSTERS)-1:0]; + assign l1_base_addr = (L1_CLUSTER_BASE + cluster_id_i * L1_CLUSTER_MEM_SIZE); + assign l1_pkt_base_addr = l1_base_addr + L1_RUNTIME_OFFSET; + assign l1_pkt_addr = current_task_q.pkt_ptr; + + for (genvar i=0; i= 4 && add_idx <= 10 && ~wen_ni) begin //command definition (words) + cmd_d.descr.words[add_idx - 4] = wdata_i; + end + end + end + + //assigning ID to command when issued + always_comb begin + cmd_d.cmd_id.local_cmd_id = cmd_q.cmd_id.local_cmd_id; + + case (state_q) + WaitingID: begin + if (cmd_resp_valid_i) begin + cmd_d.cmd_id.local_cmd_id = cmd_resp_i.cmd_id.local_cmd_id; + end + end + default: begin + if (assign_id) begin + cmd_d.cmd_id.local_cmd_id = cmd_idx; + end + end + endcase + end + + //command issuing + always_comb begin + rdata_d = rdata_q; + + case (state_q) + Ready: begin + if (cmd_issued) begin + rdata_d = cmd_idx; + end + + if (test_issued) begin + rdata_d = (wt_cmd_finished) ? 32'h0000_0001 : '0; + end + end + + Waiting: begin + if (cmd_resp_valid_i) begin + rdata_d = cmd_resp_i.cmd_id.local_cmd_id; + end + end + endcase + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + state_q <= Ready; + free_cmd_ids_q <= '0; + wt_cmd_idx_q <= '0; + rvalid_q <= 1'b0; + rdata_q <= '0; + cmd_q <= '0; + end else begin + state_q <= state_d; + free_cmd_ids_q <= free_cmd_ids_d; + wt_cmd_idx_q <= wt_cmd_idx_d; + rvalid_q <= rvalid_d; + rdata_q <= rdata_d; + cmd_q <= cmd_d; + end + end +endmodule diff --git a/hw/src/pkt_scheduler/mpq_engine.sv b/hw/src/pkt_scheduler/mpq_engine.sv new file mode 100644 index 0000000..95c7af7 --- /dev/null +++ b/hw/src/pkt_scheduler/mpq_engine.sv @@ -0,0 +1,538 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +module mpq_engine #( + parameter int NUM_HER_SLOTS = 64, + parameter int NUM_MPQ = 8 +) +( + input logic clk_i, + input logic rst_ni, + + //from pkt gen + output logic her_ready_o, + input logic her_valid_i, + input her_descr_t her_i, + + //termination signal + input logic eos_i, + + //mpq ready signal + output logic [NUM_MPQ-1:0] mpq_full_o, + + //from feedback engine + output logic feedback_ready_o, + input logic feedback_valid_i, + input feedback_descr_t feedback_i, + + //to scheduler + input logic task_ready_i, + output logic task_valid_o, + output handler_task_t task_o, + + //to pktgen + input logic nic_feedback_ready_i, + output logic nic_feedback_valid_o, + output feedback_descr_t nic_feedback_o +); + typedef struct packed { + mem_addr_t pkt_addr; + mem_size_t pkt_size; + } mpq_pkt_t; + + localparam int unsigned MPQ_META_LEN = $bits(mpq_meta_t); + localparam int unsigned MPQ_META_LEN_B = MPQ_META_LEN/8; + + // MPQ engine state. This is mainly to handle the case in which + // task_ready_i is not asserted and enable pipelining between + // reading from MPQ meta memory and defining output task + typedef enum logic [2:0] {Idle, Ready, Stalled} mpqeng_state_t; + mpqeng_state_t state_q, state_d; + + // MPQ state. I don't think we can move this too to memory :( + mpq_t [NUM_MPQ-1:0] mpq_q; + mpq_t [NUM_MPQ-1:0] mpq_d; + + // Flag saying if an MPQ is ready or not + logic [NUM_MPQ-1:0] mpq_valid; + + // Flag saying if an MPQ is being used or not + logic [NUM_MPQ-1:0] mpq_busy; + + // ID of the MPQ for which we received a new HER + logic [$clog2(NUM_MPQ)-1:0] newher_mpq_idx; + + // ID of the MPQ which we are sending a task from + logic [$clog2(NUM_MPQ)-1:0] tasksent_mpq_idx; + + // ID of the MPQ for which we received a task + logic [$clog2(NUM_MPQ)-1:0] feedback_mpq_idx; + + // aribitrate ready MPQs + logic [$clog2(NUM_MPQ)-1:0] mpq_arb_idx; + + // Next packet to schedule for each MPQ + mpq_pkt_t mpq_head; + + // New packet to push in the fifo_engine + mpq_pkt_t new_pkt; + + // We store the handler_task in order to use it in case we get stalled + handler_task_t task_q, task_d, new_task; + + // We use these registers to rember info about the currently selected MPQ. + // We need to way one cycle to get the output from memory and use that, + // toghether with these info, to build the output. + mpq_state_t mpq_out_state_d, mpq_out_state_q; + logic [$clog2(NUM_MPQ)-1:0] selected_mpq_d; + logic [$clog2(NUM_MPQ)-1:0] selected_mpq_q; + + // push/pop drivers for FIFO engine + logic fifo_push, fifo_pop; + + // flag saying if the FIFO engine is empty of full + // NOTE: fifo_empty is only used in assertions + logic fifo_empty; + logic [NUM_MPQ-1:0] fifo_full; + + // Updated MPQs from the FSMs output + mpq_t newher_mpq_fsm_s, tasksent_mpq_fsm_s, feedback_mpq_fsm_s; + + // Flags saying if the FSMs' output is valid + logic newher_mpq_fsm_update, tasksent_mpq_fsm_update, feedback_mpq_fsm_update; + + // True if we are writing to the MPQ meta memory + logic mpqmeta_write; + + // True if we are reading from MPQ meta memory + logic mpqmeta_read; + + // Flag used in the defintion of the output task (ugly). + logic new_task_triggers_feedback_q, new_task_triggers_feedback_d; + + // Read output of the MPQ meta memory + mpq_meta_t mpqmeta_read_mpq; + mpq_meta_t mpqmeta_read_mpq_ignored; + + // ready/valid for arbiter + logic arb_ready, arb_valid; + + assign mpq_full_o = fifo_full; + + // define the MPQ indices for the different events + assign newher_mpq_idx = her_i.msgid[$clog2(NUM_MPQ)-1:0]; + assign tasksent_mpq_idx = mpq_arb_idx; //this one comes one cycle before task_o! + assign feedback_mpq_idx = feedback_i.msgid[$clog2(NUM_MPQ)-1:0]; + + // Here we store the packets that are queued for each MPQ + assign new_pkt.pkt_addr = her_i.her_addr; + assign new_pkt.pkt_size = her_i.xfer_size; + + assign fifo_push = her_ready_o && her_valid_i; + + // Note: this is quite ugly, should be fixed. + assign fifo_pop = (arb_ready && arb_valid && ( + (mpq_q[tasksent_mpq_idx].state == Payload && mpq_d[tasksent_mpq_idx].state == Payload) || /* pop payload packets but not the eom */ + (mpq_q[tasksent_mpq_idx].state == Payload && mpq_d[tasksent_mpq_idx].state == PayloadDraining && !mpq_d[tasksent_mpq_idx].has_completion) || /* pop eom already if there is no completion handler */ + (mpq_q[tasksent_mpq_idx].state == Completion) /* pop EOM when the completion is sent */ + )); + + fifo_engine #( + .NUM_CELLS(NUM_HER_SLOTS), + .NUM_STATIC_CELLS_PER_FIFO(NUM_MPQ_STATIC_CELLS), + .NUM_FIFO(NUM_MPQ), + .elem_t(mpq_pkt_t) + ) i_fifo_engine ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .new_el_i (new_pkt), + .push_i (fifo_push), + .fifo_push_id_i (newher_mpq_idx), + .pop_i (fifo_pop), + .fifo_pop_id_i (tasksent_mpq_idx), + .data_o (mpq_head), + .empty_o (fifo_empty), + .fifo_full_o (fifo_full) + ); + + // MPQ metadata memory + assign mpqmeta_write = her_valid_i && her_ready_o && !mpq_busy[newher_mpq_idx]; + assign mpqmeta_read = arb_ready && arb_valid; + + tc_sram #( + .NumWords (NUM_MPQ), + .DataWidth (MPQ_META_LEN), + .NumPorts (2) + ) i_mpq_meta_mem ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .req_i ({mpqmeta_write, mpqmeta_read}), + .we_i ({mpqmeta_write, 1'b0}), + .addr_i ({newher_mpq_idx, tasksent_mpq_idx}), + .wdata_i ({her_i.mpq_meta, {MPQ_META_LEN{1'b0}}}), + .be_i ({{MPQ_META_LEN_B{1'b1}}, {MPQ_META_LEN_B{1'b0}}}), + .rdata_o ({mpqmeta_read_mpq_ignored, mpqmeta_read_mpq}) + ); + + // Select a ready MPQ + rr_arb_tree #( + .NumIn (NUM_MPQ), + .DataWidth (0), + .ExtPrio (0), + .AxiVldRdy (1), + .LockIn (1) + ) i_mpq_rr_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .rr_i ('0), + .req_i (mpq_valid), + .gnt_o (), + .data_i (), + .gnt_i (arb_ready), + .req_o (arb_valid), + .data_o (), + .idx_o (mpq_arb_idx) + ); + + // Define state + always_comb begin + state_d = state_q; + arb_ready = 1'b0; + + case (state_q) + Idle: begin + if (arb_valid == 1'b1) begin + state_d = Ready; + arb_ready = 1'b1; + end + end + Ready: begin + if (task_ready_i == 1'b0) begin + state_d = Stalled; + end else begin + state_d = (arb_valid == 1'b1) ? Ready : Idle; + arb_ready = (arb_valid == 1'b1); + end + end + Stalled: begin + if (task_ready_i == 1'b1) begin + state_d = (arb_valid == 1'b1) ? Ready : Idle; + arb_ready = (arb_valid == 1'b1); //to pipeline next memory read + end + end + endcase + end + + // Define output + // we delay mpq_arb_idx because the the memory read output will be + // ready at the next cycle + + assign task_valid_o = (state_q == Ready || state_q == Stalled); + + //this seems overworked.. + assign task_o = (state_q==Ready) ? new_task : task_q; + assign task_d = (state_q==Ready) ? new_task : task_q; + + assign mpq_out_state_d = (arb_ready && arb_valid) ? mpq_q[tasksent_mpq_idx].state : mpq_out_state_q; + assign selected_mpq_d = (arb_ready && arb_valid) ? tasksent_mpq_idx : selected_mpq_q; + assign new_task_triggers_feedback_d = (arb_ready && arb_valid) ? fifo_pop : new_task_triggers_feedback_q; + + always_comb begin + case (mpq_out_state_q) + Header: begin + new_task.handler_fun = mpqmeta_read_mpq.hh_addr; + new_task.handler_fun_size = mpqmeta_read_mpq.hh_size; + new_task.pkt_addr = mpq_head.pkt_addr; + new_task.pkt_size = mpq_head.pkt_size; + new_task.trigger_feedback = new_task_triggers_feedback_q; + end + + Payload: begin + new_task.handler_fun = mpqmeta_read_mpq.ph_addr; + new_task.handler_fun_size = mpqmeta_read_mpq.ph_size; + new_task.pkt_addr = mpq_head.pkt_addr; + new_task.pkt_size = mpq_head.pkt_size; + new_task.trigger_feedback = new_task_triggers_feedback_q; + end + + Completion: begin + new_task.handler_fun = mpqmeta_read_mpq.th_addr; + new_task.handler_fun_size = mpqmeta_read_mpq.th_size; + new_task.pkt_addr = mpq_head.pkt_addr; + new_task.pkt_size = mpq_head.pkt_size; + new_task.trigger_feedback = new_task_triggers_feedback_q; + end + + default: begin + new_task.handler_fun = '0; + new_task.handler_fun_size = '0; + new_task.pkt_addr = '0; + new_task.pkt_size = '0; + new_task.trigger_feedback = 1'b0; + end + endcase + end + + assign new_task.msgid = selected_mpq_q; + assign new_task.handler_mem_addr = mpqmeta_read_mpq.handler_mem_addr; + assign new_task.handler_mem_size = mpqmeta_read_mpq.handler_mem_size; + assign new_task.host_mem_addr = mpqmeta_read_mpq.host_mem_addr; + assign new_task.host_mem_size = mpqmeta_read_mpq.host_mem_size; + + for (genvar i = 0; i< pspin_cfg_pkg::NUM_CLUSTERS; i++) begin: gen_task_scratchpad + assign new_task.scratchpad_addr[i] = mpqmeta_read_mpq.scratchpad_addr[i]; + assign new_task.scratchpad_size[i] = mpqmeta_read_mpq.scratchpad_size[i]; + end + + // Update MPQ state + // This unit might have to process at most three MPQs at the same time: + // - the MPQ for which we get a new HER, + // - the MPQ for which we get a completion feedback, + // - the MPQ that gets selected to send a new task. + // For this reason, we keep three mpq_fsm. It can happen that two or all FSM + // will be fed with the same MPQ (e.g., getting a new HER and a completion feedback + // for the same MPQ in the same cycle). In that case, the FSM will produce the same + // output state, so it does not matter which output gets written. + mpq_fsm #( + ) i_newher_mpq_fsm ( + .her_new_i (her_valid_i && her_ready_o), + .task_sent_i (arb_valid && arb_ready && tasksent_mpq_idx == newher_mpq_idx), + .feedback_i (feedback_valid_i && feedback_ready_o && feedback_mpq_idx == newher_mpq_idx), + + .her_new_has_hh_i (her_i.mpq_meta.hh_addr != '0), + .her_new_has_th_i (her_i.mpq_meta.th_addr != '0), + .her_new_is_eom_i (her_i.eom), + + .mpq_q (mpq_q[newher_mpq_idx]), + .mpq_o (newher_mpq_fsm_s), + + .update_o (newher_mpq_fsm_update) + ); + + mpq_fsm #( + ) i_tasksent_mpq_fsm ( + .her_new_i (her_valid_i && her_ready_o && newher_mpq_idx == tasksent_mpq_idx), + .task_sent_i (arb_valid && arb_ready), + .feedback_i (feedback_valid_i && feedback_ready_o && feedback_mpq_idx == tasksent_mpq_idx), + + .her_new_has_hh_i (her_i.mpq_meta.hh_addr != '0), + .her_new_has_th_i (her_i.mpq_meta.th_addr != '0), + .her_new_is_eom_i (her_i.eom), + + .mpq_q (mpq_q[tasksent_mpq_idx]), + .mpq_o (tasksent_mpq_fsm_s), + + .update_o (tasksent_mpq_fsm_update) + ); + + mpq_fsm #( + ) i_feedback_mpq_fsm ( + .her_new_i (her_valid_i && her_ready_o && newher_mpq_idx == feedback_mpq_idx), + .task_sent_i (arb_valid && arb_ready && feedback_mpq_idx == tasksent_mpq_idx), + .feedback_i (feedback_valid_i && feedback_ready_o), + + .her_new_has_hh_i (her_i.mpq_meta.hh_addr != '0), + .her_new_has_th_i (her_i.mpq_meta.th_addr != '0), + .her_new_is_eom_i (her_i.eom), + + .mpq_q (mpq_q[feedback_mpq_idx]), + .mpq_o (feedback_mpq_fsm_s), + + .update_o (feedback_mpq_fsm_update) + ); + + always_comb begin + mpq_d = mpq_q; + + if (newher_mpq_fsm_update) begin + mpq_d[newher_mpq_idx] = newher_mpq_fsm_s; + end + + if (tasksent_mpq_fsm_update) begin + mpq_d[tasksent_mpq_idx] = tasksent_mpq_fsm_s; + end + + if (feedback_mpq_fsm_update) begin + mpq_d[feedback_mpq_idx] = feedback_mpq_fsm_s; + end + end + + // Define valid/busy MPQs + for (genvar i=0; i 0) || + (mpq_q[i].state == Completion)); + assign mpq_busy[i] = (mpq_q[i].state != Free); + end + + // Define ready signal on the HER input interface. We can + // get a new HER if the MPQ to which the HER will go has space. + assign her_ready_o = !fifo_full[newher_mpq_idx]; //((~fifo_full) != '0); + + // Forward the feedback to the NIC inbound engine + assign feedback_ready_o = nic_feedback_ready_i; + assign nic_feedback_valid_o = feedback_valid_i && feedback_i.trigger_feedback == 1'b1; + assign nic_feedback_o = feedback_i; + + // Sequential + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + mpq_q <= '0; + selected_mpq_q <= '0; + state_q <= Idle; + mpq_out_state_q <= Free; + task_q <= '0; + new_task_triggers_feedback_q <= 1'b0; + end else begin + mpq_q <= mpq_d; + selected_mpq_q <= selected_mpq_d; + state_q <= state_d; + mpq_out_state_q <= mpq_out_state_d; + task_q <= task_d; + new_task_triggers_feedback_q <= new_task_triggers_feedback_d; + end + end + + // Simulation only + // pragma translate_off + `ifndef VERILATOR + initial begin + forever begin + @(posedge clk_i); + if (feedback_ready_o && feedback_valid_i) begin + $display("%0d MPQ engine got feedback for msg id %0d", $time, feedback_i.msgid); + end + + if (her_ready_o && her_valid_i) begin + $display("%0d MPQ engine got new packet for msg id %0d", $time, her_i.msgid); + end + + end + end + + // Assertions + nonempty : assert property( + @(posedge clk_i) (mpq_busy=='0 && eos_i) |-> (fifo_empty)) + else $fatal (1, "Termination detected but there still are packets to process!"); + + for (genvar i=0; i (~(mpq_d[i].length) != '0)) + else $fatal (1, "MPQ length is negative!"); + + negativeinflight: assert property( + @(posedge clk_i) (mpq_q[i].in_flight == '0) |-> (~(mpq_d[i].in_flight) != '0)) + else $fatal (1, "MPQ in_flight is negative!"); + end + `endif + // pragma translate_on + + +endmodule + +module mpq_fsm #( +) ( + + // events + input logic her_new_i, // got a new HER + input logic task_sent_i, // got selected for sending a task + input logic feedback_i, // got a completion feedback + + //info on the new HER, if any (used only if her_new_i is asserted) + input logic her_new_has_hh_i, // Asserted if the new HER as a header handler + input logic her_new_has_th_i, // Asserted if the new HER as a completion handler + input logic her_new_is_eom_i, // Asserted if the new HER is flagged as EOM + + input mpq_t mpq_q, // current state + output mpq_t mpq_o, // new state + + output logic update_o // asserted if mpq_o is valid +); + + logic pushing_her, popping_her; + assign pushing_her = her_new_i; + assign popping_her = (task_sent_i && mpq_q.state == Payload); + + assign update_o = her_new_i || task_sent_i || feedback_i; + + //update MPQ length + always_comb begin + case ({pushing_her, popping_her}) + 2'b10 : mpq_o.length = mpq_q.length + 1; + 2'b01 : mpq_o.length = mpq_q.length - 1; + default : mpq_o.length = mpq_q.length; + endcase + end + + always_comb begin + case ({task_sent_i, feedback_i}) + 2'b10 : mpq_o.in_flight = mpq_q.in_flight + 1; + 2'b01 : mpq_o.in_flight = mpq_q.in_flight - 1; + default : mpq_o.in_flight = mpq_q.in_flight; + endcase + end + + assign mpq_o.eom_seen = mpq_q.eom_seen || (her_new_i && her_new_is_eom_i); + + //update state + always_comb begin //H-P-C case + + mpq_o.state = mpq_q.state; + mpq_o.has_completion = mpq_q.has_completion; + + case (mpq_q.state) + Free: begin + if (her_new_i) begin + mpq_o.state = (her_new_has_hh_i) ? Header : Payload; + mpq_o.has_completion = her_new_has_th_i; + end + end + + Header: begin + if (task_sent_i) begin + mpq_o.state = HeaderRunning; + end + end + + HeaderRunning: begin + if (feedback_i) begin + mpq_o.state = Payload; + end + end + + Payload: begin + if (task_sent_i && mpq_q.eom_seen && mpq_q.length == 1) begin + mpq_o.state = PayloadDraining; + end + end + + PayloadDraining: begin + if (feedback_i && mpq_q.in_flight == 1) begin + mpq_o.state = (mpq_q.has_completion) ? Completion : Free; + end + end + + Completion: begin + if (task_sent_i) begin + mpq_o.state = CompletionRunning; + end + end + + CompletionRunning: begin + if (feedback_i) begin + mpq_o.state = Free; + end + end + endcase + end +endmodule diff --git a/hw/src/pkt_scheduler/scheduler.sv b/hw/src/pkt_scheduler/scheduler.sv new file mode 100644 index 0000000..0dd522a --- /dev/null +++ b/hw/src/pkt_scheduler/scheduler.sv @@ -0,0 +1,293 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +/** + NOTE: this module needs to be revisioned because by introducing a packet buffer in L1 we don't have + the concept of "packet slots" anymore. The cluster_occup_i signal should be signal the available space + instead of the number of available packet slots. +**/ + +module scheduler #( + parameter int NUM_CLUSTERS = 4, + parameter int NUM_HERS_PER_CLUSTER = 64 +) ( + input logic clk_i, + input logic rst_ni, + + //input IF from MPQ engine + input logic task_valid_i, + output logic task_ready_o, + input handler_task_t task_descr_i, + + //output IF to cluster schedulers + output logic [NUM_CLUSTERS-1:0] cluster_task_valid_o, + input logic [NUM_CLUSTERS-1:0] cluster_task_ready_i, + output handler_task_t [NUM_CLUSTERS-1:0] cluster_task_descr_o, + + //input IF from clusters for the feedbacks + input logic [NUM_CLUSTERS-1:0] cluster_feedback_valid_i, + output logic [NUM_CLUSTERS-1:0] cluster_feedback_ready_o, + input feedback_descr_t [NUM_CLUSTERS-1:0] cluster_feedback_i, + + //output IF to pktgen for feedbacks + output logic pktgen_feedback_valid_o, + input logic pktgen_feedback_ready_i, + output feedback_descr_t pktgen_feedback_o + +); + + ///////////////////////// + /// Cluster interface /// + ///////////////////////// + + // We use these registers to cut the combinatorial network from + // the uncluster (outside a cluster) to inside a cluster. This helps + // defining domains and to close timings separately. It also reduces + // paths lengths. + logic [NUM_CLUSTERS-1:0] cluster_task_valid_od; + logic [NUM_CLUSTERS-1:0] cluster_task_ready_id; + handler_task_t [NUM_CLUSTERS-1:0] cluster_task_descr_od; + + logic [NUM_CLUSTERS-1:0] cluster_feedback_valid_iq; + logic [NUM_CLUSTERS-1:0] cluster_feedback_ready_oq; + feedback_descr_t [NUM_CLUSTERS-1:0] cluster_feedback_iq; + + for (genvar i=0; i= MAX_OCC) ? 1'b1 : 1'b0; + assign can_use_home_cluster = (no_cluster_avail || (cluster_occup_q[home_cluster_id] < MAX_OCC && cluster_task_ready_id[home_cluster_id])); + assign sel_cluster_id = (can_use_home_cluster) ? home_cluster_id : c_occup_min; + assign cluster_id_d = (state_q == ServePacket) ? sel_cluster_id : cluster_id_q; + + //task is put on all the output interfaces. Only the selected cluster ID will have + //cluster_valid_o[i] set. + for (genvar i = 0; i < NUM_CLUSTERS; i++) begin : gen_cluster_task + assign cluster_task_descr_od[i] = (state_q == ServePacket) ? task_descr_i : task_q; + assign cluster_task_valid_od[i] = (cluster_id_d == i) && serving_cluster; + end + + always_comb begin + int i; + state_d = state_q; + task_ready_o = 1'b0; + serving_cluster = 1'b0; + + case (state_q) + ServePacket: begin + serving_cluster = 1'b0; + + if (task_valid_i && !no_cluster_avail) begin + task_ready_o = 1'b1; //signal that we recvd the data + state_d = (cluster_task_ready_id[cluster_id_d]) ? ServePacket : WaitTransfer; + serving_cluster = 1'b1; + end + end + WaitTransfer: begin + serving_cluster = 1'b1; + if ((cluster_task_ready_id[cluster_id_q])) begin + state_d = ServePacket; + end + end + default: begin + state_d = ServePacket; + end + + endcase + end + + argmin4 #( + .VALUE_WIDTH ($clog2(NUM_HERS_PER_CLUSTER)+1) + ) i_argmin4 ( + .values_i(cluster_occup_q), + .enabled_i(cluster_task_ready_id), + .argmin_o(c_occup_min) + ); + + /** sequential part **/ + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + state_q <= ServePacket; + cluster_id_q <= '0; + task_q <= '0; + cluster_occup_q <= '0; + end else begin + state_q <= state_d; + cluster_id_q <= cluster_id_d; + task_q <= task_d; + cluster_occup_q <= cluster_occup_d; + end + end + + /** simulation **/ + /* + initial begin + forever begin + @(posedge clk_i); + if (task_valid_i && task_ready_o) begin + $display("[sched] msg_id: %0d; cluster_id: %0d; occupation: %0d; no_cluster_avail: %0d", task_descr_i.msgid, cluster_id_d, cluster_occup_iq[cluster_id_d], no_cluster_avail); + end + end + end + */ + + // pragma translate_off + `ifndef VERILATOR + initial begin + static int start_time = 0; + forever begin + @(posedge clk_i); + if (task_valid_i && task_ready_o && start_time == 0) begin + start_time = $stime; + end + + if (task_valid_i && task_ready_o) begin + $display("%0d INFO TASK %0d %0d", $stime, task_descr_i.msgid, ($stime - start_time)); + end + + if (pktgen_feedback_valid_o && pktgen_feedback_ready_i) begin + $display("%0d INFO FEEDBACK %0d %0d", $stime, pktgen_feedback_o.msgid, ($stime - start_time)); + end + end + end + `endif + // pragma translate_on + + ///////////////////////////////////////////////////// + /// Arbitrating feedbacks from cluster schedulers /// + ///////////////////////////////////////////////////// + + //logic [$clog2(NUM_CLUSTERS)-1:0] cluster_idx_arb; + rr_arb_tree #( + .NumIn (NUM_CLUSTERS), + .DataType (feedback_descr_t), + .ExtPrio (0), + .AxiVldRdy (1), + .LockIn (1) + ) i_rr_arb_tree ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .rr_i ('0), + .req_i (cluster_feedback_valid_iq), + .gnt_o (cluster_feedback_ready_oq), + .data_i (cluster_feedback_iq), + .gnt_i (pktgen_feedback_ready_i), + .req_o (pktgen_feedback_valid_o), + .data_o (pktgen_feedback_o), + .idx_o () + ); + +endmodule + +module argmin4 #( + VALUE_WIDTH = 64 +) +( + input logic [3:0][VALUE_WIDTH-1:0] values_i, + input logic [3:0] enabled_i, + output logic [1:0] argmin_o +); + logic [1:0] min_l0; + logic [1:0] min_l1; + + logic [3:0][VALUE_WIDTH-1:0] values; + + assign values[0] = (enabled_i[0]) ? values_i[0] : {VALUE_WIDTH{1'b1}}; + assign values[1] = (enabled_i[1]) ? values_i[1] : {VALUE_WIDTH{1'b1}}; + assign values[2] = (enabled_i[2]) ? values_i[2] : {VALUE_WIDTH{1'b1}}; + assign values[3] = (enabled_i[3]) ? values_i[3] : {VALUE_WIDTH{1'b1}}; + + assign min_l0[1:0] = (values[0] <= values[1]) ? 2'b00 : 2'b01; + assign min_l1[1:0] = (values[2] <= values[3]) ? 2'b10 : 2'b11; + assign argmin_o[1:0] = (values[min_l0] <= values[min_l1]) ? min_l0 : min_l1; +endmodule \ No newline at end of file diff --git a/hw/src/pspin.sv b/hw/src/pspin.sv new file mode 100644 index 0000000..308136b --- /dev/null +++ b/hw/src/pspin.sv @@ -0,0 +1,865 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +module pspin #( + parameter int unsigned N_CLUSTERS = 0, + parameter int N_MPQ = 0 +) ( + // Clocks and Resets + input logic clk_i, + input logic rst_ni, + + // Cluster Control + input logic [N_CLUSTERS-1:0] cl_fetch_en_i, + output logic [N_CLUSTERS-1:0] cl_eoc_o, + output logic [N_CLUSTERS-1:0] cl_busy_o, + + AXI_BUS.Slave axi_ni_slv, //NIC inbound slave port: to inject packets + AXI_BUS.Slave axi_no_slv, //NIC outbound slave port: to read data to send out + AXI_BUS.Master axi_host_mst, // Host master port: to write to host memory + AXI_BUS.Slave axi_host_slv, // Host slave port: to let the host write to L2 prog mem and L2 handler mem + + //from pktgen + output logic her_ready_o, + input logic her_valid_i, + input pspin_cfg_pkg::her_descr_t her_i, + + //termination signal + input logic eos_i, + + //MPQ full signal + output logic [N_MPQ-1:0] mpq_full_o, + + //to pktgen + input logic nic_feedback_ready_i, + output logic nic_feedback_valid_o, + output pspin_cfg_pkg::feedback_descr_t nic_feedback_o, + + output logic pspin_active_o, + + input logic nic_cmd_ready_i, + output logic nic_cmd_valid_o, + output pspin_cfg_pkg::pspin_cmd_t nic_cmd_o, + + input logic nic_cmd_resp_valid_i, + input pspin_cfg_pkg::pspin_cmd_resp_t nic_cmd_resp_i +); + + import pspin_cfg_pkg::AXI_AW; + import pspin_cfg_pkg::HOST_AXI_AW; + import pspin_cfg_pkg::addr_t; + import pspin_cfg_pkg::AXI_WIDE_DW; + import pspin_cfg_pkg::data_t; + import pspin_cfg_pkg::strb_t; + import pspin_cfg_pkg::AXI_IW; + import pspin_cfg_pkg::id_t; + import pspin_cfg_pkg::AXI_UW; + import pspin_cfg_pkg::user_t; + import pspin_cfg_pkg::aw_t; + import pspin_cfg_pkg::w_t; + import pspin_cfg_pkg::b_t; + import pspin_cfg_pkg::ar_t; + import pspin_cfg_pkg::r_t; + import pspin_cfg_pkg::req_t; + import pspin_cfg_pkg::resp_t; + import pspin_cfg_pkg::host_req_t; + import pspin_cfg_pkg::host_resp_t; + import pspin_cfg_pkg::PKT_MEM_SIZE; + import pspin_cfg_pkg::HND_MEM_SIZE; + import pspin_cfg_pkg::L1_CLUSTER_BASE; + import pspin_cfg_pkg::L1_CLUSTER_MEM_SIZE; + localparam int unsigned L2_SIZE = pulp_cluster_cfg_pkg::L2_SIZE; + + // Interface from NIC inbound + req_t ni_req; + resp_t ni_resp; + `AXI_ASSIGN_TO_REQ(ni_req, axi_ni_slv) + `AXI_ASSIGN_FROM_RESP(axi_ni_slv, ni_resp) + + // Interface from NIC outbound + req_t no_req; + resp_t no_resp; + `AXI_ASSIGN_TO_REQ(no_req, axi_no_slv) + `AXI_ASSIGN_FROM_RESP(axi_no_slv, no_resp) + + // Interface to Host + host_req_t host_mst_req; + host_resp_t host_mst_resp; + `AXI_ASSIGN_FROM_REQ(axi_host_mst, host_mst_req) + `AXI_ASSIGN_TO_RESP(host_mst_resp, axi_host_mst) + + host_req_t host_mst_soc_dma_req, host_mst_hdir_req; + host_resp_t host_mst_soc_dma_resp, host_mst_hdir_resp; + + // Interface from Host + req_t host_slv_req; + resp_t host_slv_resp; + `AXI_ASSIGN_TO_REQ(host_slv_req, axi_host_slv) + `AXI_ASSIGN_FROM_RESP(axi_host_slv, host_slv_resp) + + // Interface from NHI interconnect to cluster noc + req_t nhi_req; + resp_t nhi_resp; + + // Interfaces to Clusters + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_SLV), + .AXI_USER_WIDTH (AXI_UW) + ) cl_inp[N_CLUSTERS-1:0](); + pulp_cluster_cfg_pkg::req_slv_t [N_CLUSTERS-1:0] cl_inp_req; + pulp_cluster_cfg_pkg::resp_slv_t [N_CLUSTERS-1:0] cl_inp_resp; + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_assign_cl_inp + `AXI_ASSIGN_FROM_REQ(cl_inp[i], cl_inp_req[i]) + `AXI_ASSIGN_TO_RESP(cl_inp_resp[i], cl_inp[i]) + end + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_SLV), + .AXI_USER_WIDTH (AXI_UW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) cl_inp_async[N_CLUSTERS-1:0](); + + // Interfaces from Clusters + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_MST), + .AXI_USER_WIDTH (AXI_UW) + ) cl_oup[N_CLUSTERS-1:0](); + pulp_cluster_cfg_pkg::req_mst_t [N_CLUSTERS-1:0] cl_oup_req; + pulp_cluster_cfg_pkg::resp_mst_t [N_CLUSTERS-1:0] cl_oup_resp; + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_assign_cl_oup + `AXI_ASSIGN_TO_REQ(cl_oup_req[i], cl_oup[i]) + `AXI_ASSIGN_FROM_RESP(cl_oup[i], cl_oup_resp[i]) + end + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_MST), + .AXI_USER_WIDTH (AXI_UW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) cl_oup_async[N_CLUSTERS-1:0](); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .AXI_USER_WIDTH (AXI_UW) + ) cl_dma[N_CLUSTERS-1:0](); + pulp_cluster_cfg_pkg::req_dma_t [N_CLUSTERS-1:0] cl_dma_req; + pulp_cluster_cfg_pkg::resp_dma_t [N_CLUSTERS-1:0] cl_dma_resp; + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_assign_cl_dma + `AXI_ASSIGN_TO_REQ(cl_dma_req[i], cl_dma[i]) + `AXI_ASSIGN_FROM_RESP(cl_dma[i], cl_dma_resp[i]) + end + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .AXI_USER_WIDTH (AXI_UW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) cl_dma_async[N_CLUSTERS-1:0](); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .AXI_USER_WIDTH (AXI_UW) + ) cl_nhi[N_CLUSTERS-1:0](); + pulp_cluster_cfg_pkg::req_dma_t [N_CLUSTERS-1:0] cl_nhi_req; + pulp_cluster_cfg_pkg::resp_dma_t [N_CLUSTERS-1:0] cl_nhi_resp; + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_assign_cl_nhi + `AXI_ASSIGN_FROM_REQ(cl_nhi[i], cl_nhi_req[i]) + `AXI_ASSIGN_TO_RESP(cl_nhi_resp[i], cl_nhi[i]) + end + /* We are not using async clusters, can we remove their definition? */ + /* + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_DW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .AXI_USER_WIDTH (AXI_UW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) cl_nhi_async[N_CLUSTERS-1:0](); + */ + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW_ICACHE), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_ICACHE), + .AXI_USER_WIDTH (AXI_UW) + ) cl_icache[N_CLUSTERS-1:0](); + + pulp_cluster_cfg_pkg::req_icache_t [N_CLUSTERS-1:0] cl_icache_req; + pulp_cluster_cfg_pkg::resp_icache_t [N_CLUSTERS-1:0] cl_icache_resp; + + pulp_cluster_cfg_pkg::req_icache_t host_slv_downsized_req; + pulp_cluster_cfg_pkg::resp_icache_t host_slv_downsized_resp; + + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_assign_cl_icache + `AXI_ASSIGN_TO_REQ(cl_icache_req[i], cl_icache[i]) + `AXI_ASSIGN_FROM_RESP(cl_icache[i], cl_icache_resp[i]) + end + AXI_BUS_ASYNC #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW_ICACHE), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_ICACHE), + .AXI_USER_WIDTH (AXI_UW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) cl_icache_async[N_CLUSTERS-1:0](); + + // Interfaces to L2 Memory + req_t pe_l2_req, dma_l2_req, l2_hnd_req_a, l2_hnd_req_b, l2_pkt_req_a, l2_pkt_req_b; + resp_t pe_l2_resp, dma_l2_resp, l2_hnd_resp_a, l2_hnd_resp_b, l2_pkt_resp_a, l2_pkt_resp_b; + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) l2_hnd_mst_a(), l2_pkt_mst_a(), l2_hnd_mst_b(), l2_pkt_mst_b(); + + `AXI_ASSIGN_FROM_REQ(l2_hnd_mst_a, l2_hnd_req_a) + `AXI_ASSIGN_TO_RESP(l2_hnd_resp_a, l2_hnd_mst_a) + + `AXI_ASSIGN_FROM_REQ(l2_hnd_mst_b, l2_hnd_req_b) + `AXI_ASSIGN_TO_RESP(l2_hnd_resp_b, l2_hnd_mst_b) + + `AXI_ASSIGN_FROM_REQ(l2_pkt_mst_a, l2_pkt_req_a) + `AXI_ASSIGN_TO_RESP(l2_pkt_resp_a, l2_pkt_mst_a) + + `AXI_ASSIGN_FROM_REQ(l2_pkt_mst_b, l2_pkt_req_b) + `AXI_ASSIGN_TO_RESP(l2_pkt_resp_b, l2_pkt_mst_b) + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) l2_hnd_mst_wo_atomics(); + + req_t host_l2_prog_req; + resp_t host_l2_prog_resp; + + // Interface from eDMA to NHI + req_t nhi_mst_edma_req; + resp_t nhi_mst_edma_resp; + + // Interfaces to Peripherals + localparam int unsigned AXI_DW_PERIPHS = 64; + typedef logic [AXI_DW_PERIPHS-1:0] periph_data_t; + typedef logic [AXI_DW_PERIPHS/8-1:0] periph_strb_t; + `AXI_TYPEDEF_W_CHAN_T(periph_w_t, periph_data_t, periph_strb_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(periph_r_t, periph_data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(periph_req_t, aw_t, periph_w_t, ar_t) + `AXI_TYPEDEF_RESP_T(periph_resp_t, b_t, periph_r_t) + periph_req_t periph_req; + periph_resp_t periph_resp; + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_DW_PERIPHS), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) periph_mst(); + `AXI_ASSIGN_FROM_REQ(periph_mst, periph_req) + `AXI_ASSIGN_TO_RESP(periph_resp, periph_mst) + + // mpq_engine -> scheduler + logic mpqengine_scheduler_valid; + logic mpqengine_scheduler_ready; + pspin_cfg_pkg::handler_task_t mpqengine_scheduler_task; + + // scheduler -> mpq_engine + logic scheduler_mpqengine_valid; + logic scheduler_mpqengine_ready; + pspin_cfg_pkg::feedback_descr_t scheduler_mpqengine_feedback; + + // scheduler -> cluster_schedulers + logic [N_CLUSTERS-1:0] sched_loc_valid; + logic [N_CLUSTERS-1:0] sched_loc_ready; + pspin_cfg_pkg::handler_task_t [N_CLUSTERS-1:0] sched_loc_task; + + // cluster_schedulers -> scheduler + logic [N_CLUSTERS-1:0] loc_sched_valid; + logic [N_CLUSTERS-1:0] loc_sched_ready; + pspin_cfg_pkg::feedback_descr_t [N_CLUSTERS-1:0] loc_sched_feedback; + + logic [N_CLUSTERS-1:0] cluster_active_q; + logic [N_CLUSTERS-1:0] cluster_active_d; + + logic [N_CLUSTERS-1:0] cluster_cmd_ready; + logic [N_CLUSTERS-1:0] cluster_cmd_valid; + pspin_cfg_pkg::pspin_cmd_t [N_CLUSTERS-1:0] cluster_cmd; + + logic cluster_cmd_resp_valid; + pspin_cfg_pkg::pspin_cmd_resp_t cluster_cmd_resp; + + // CMD unit <-> soc-level DMA + logic edma_cmd_ready; + logic edma_cmd_valid; + pspin_cfg_pkg::pspin_cmd_t edma_cmd; + logic edma_resp_valid; + pspin_cfg_pkg::pspin_cmd_resp_t edma_resp; + + // CMD unit <-> HostDirect unit + logic hdir_cmd_valid; + logic hdir_cmd_ready; + pspin_cfg_pkg::pspin_cmd_t hdir_cmd; + logic hdir_resp_valid; + pspin_cfg_pkg::pspin_cmd_resp_t hdir_resp; + + assign pspin_active_o = (~cluster_active_q == '0); + + mpq_engine #( + .NUM_HER_SLOTS (pspin_cfg_pkg::NUM_MPQ_CELLS), + .NUM_MPQ (N_MPQ) + ) i_mpq_engine ( + .rst_ni (rst_ni), + .clk_i (clk_i), + + .her_ready_o (her_ready_o), + .her_valid_i (her_valid_i), + .her_i (her_i), + + .eos_i (eos_i), + + .mpq_full_o (mpq_full_o), + + .nic_feedback_ready_i (nic_feedback_ready_i), + .nic_feedback_valid_o (nic_feedback_valid_o), + .nic_feedback_o (nic_feedback_o), + + .feedback_ready_o (scheduler_mpqengine_ready), + .feedback_valid_i (scheduler_mpqengine_valid), + .feedback_i (scheduler_mpqengine_feedback), + + .task_ready_i (mpqengine_scheduler_ready), + .task_valid_o (mpqengine_scheduler_valid), + .task_o (mpqengine_scheduler_task) + + ); + + scheduler #( + .NUM_CLUSTERS (N_CLUSTERS), + .NUM_HERS_PER_CLUSTER (pspin_cfg_pkg::NUM_HERS_PER_CLUSTER) + ) i_scheduler ( + .rst_ni (rst_ni), + .clk_i (clk_i), + + //from MPQ engine + .task_valid_i (mpqengine_scheduler_valid), + .task_ready_o (mpqengine_scheduler_ready), + .task_descr_i (mpqengine_scheduler_task), + + // to MPQ engine (TODO: change names) + .pktgen_feedback_valid_o (scheduler_mpqengine_valid), + .pktgen_feedback_ready_i (scheduler_mpqengine_ready), + .pktgen_feedback_o (scheduler_mpqengine_feedback), + + // to cluster_schedulers + .cluster_task_valid_o (sched_loc_valid), + .cluster_task_ready_i (sched_loc_ready), + .cluster_task_descr_o (sched_loc_task), + + // from cluster schedulers + .cluster_feedback_valid_i (loc_sched_valid), + .cluster_feedback_ready_o (loc_sched_ready), + .cluster_feedback_i (loc_sched_feedback) + ); + + soc_dma_wrap #( + .DmaAxiIdWidth (AXI_IW), + .DmaDataWidth (AXI_WIDE_DW), + .DmaUserWidth (AXI_UW), + .AxiAxReqDepth (pspin_cfg_pkg::SOC_DMA_AXI_REQ_DEPTH), + .TfReqFifoDepth (pspin_cfg_pkg::SOC_DMA_REQ_FIFO_DEPT), + .axi_nhi_req_t (req_t), + .axi_nhi_res_t (resp_t), + .axi_host_req_t (host_req_t), + .axi_host_res_t (host_resp_t) + ) i_soc_dma_wrap ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .cmd_req_valid_i (edma_cmd_valid), + .cmd_req_ready_o (edma_cmd_ready), + .cmd_req_i (edma_cmd), + + .cmd_resp_valid_o (edma_resp_valid), + .cmd_resp_o (edma_resp), + + //AXI wide port 1 (to NHI) + .nhi_req_o (nhi_mst_edma_req), + .nhi_resp_i (nhi_mst_edma_resp), + //AXI wide port 2 (to HOST) + .host_req_o (host_mst_soc_dma_req), + .host_resp_i (host_mst_soc_dma_resp) + ); + + host_direct #( + .AXI_AW (HOST_AXI_AW), + .AXI_DW (AXI_WIDE_DW), + .CMD_IMM_DATA_SIZE (AXI_WIDE_DW), + .axi_host_aw_t (pspin_cfg_pkg::aw_host_t), + .axi_host_ar_t (pspin_cfg_pkg::ar_host_t), + .axi_host_w_t (pspin_cfg_pkg::w_t), + .axi_host_r_t (pspin_cfg_pkg::r_t), + .axi_host_b_t (pspin_cfg_pkg::b_t), + .axi_host_req_t (host_req_t), + .axi_host_res_t (host_resp_t), + .cmd_req_t (pspin_cfg_pkg::pspin_cmd_t), + .cmd_res_t (pspin_cfg_pkg::pspin_cmd_resp_t), + .cmd_id_t (pspin_cfg_pkg::pspin_cmd_id_t) + ) i_host_direct ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .cmd_req_valid_i (hdir_cmd_valid), + .cmd_req_ready_o (hdir_cmd_ready), + .cmd_req_i (hdir_cmd), + + .cmd_resp_valid_o (hdir_resp_valid), + .cmd_resp_o (hdir_resp), + + .host_req_o (host_mst_hdir_req), + .host_resp_i (host_mst_hdir_resp) + ); + + host_mst_mux #( + .AddrWidth (HOST_AXI_AW), + .DataWidth (AXI_WIDE_DW), + .IdWidth (AXI_IW), + .UserWidth (AXI_UW), + .req_t (host_req_t), + .resp_t (host_resp_t) + ) i_mux_host_mst ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .dma_req_i (host_mst_soc_dma_req), + .dma_resp_o (host_mst_soc_dma_resp), + + .hdir_req_i (host_mst_hdir_req), + .hdir_resp_o (host_mst_hdir_resp), + + .host_req_o (host_mst_req), + .host_resp_i (host_mst_resp) + ); + + cmd_unit #( + .NUM_CLUSTERS (N_CLUSTERS), + .NUM_CMD_INTERFACES (pspin_cfg_pkg::NUM_CMD_INTERFACES) + ) i_cmd_unit ( + .rst_ni (rst_ni), + .clk_i (clk_i), + + //commands from clusters + .cmd_ready_o (cluster_cmd_ready), + .cmd_valid_i (cluster_cmd_valid), + .cmd_i (cluster_cmd), + + //command responses to clusters + .cmd_resp_valid_o (cluster_cmd_resp_valid), + .cmd_resp_o (cluster_cmd_resp), + + //command interfaces requests + .intf_ready_i ({edma_cmd_ready, nic_cmd_ready_i, hdir_cmd_ready}), + .intf_valid_o ({edma_cmd_valid, nic_cmd_valid_o, hdir_cmd_valid}), + .intf_cmd_o ({edma_cmd, nic_cmd_o, hdir_cmd}), + + //command interfaces responses + .intf_cmd_resp_valid_i ({edma_resp_valid, nic_cmd_resp_valid_i, hdir_resp_valid}), + .intf_cmd_resp_i ({edma_resp, nic_cmd_resp_i, hdir_resp}) + ); + + for (genvar i = 0; i < N_CLUSTERS; i++) begin: gen_clusters + logic [5:0] cluster_id; + assign cluster_id = i; + + if (pulp_cluster_cfg_pkg::ASYNC) begin : gen_cluster_async + axi_slice_dc_slave_wrap #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_USER_WIDTH (AXI_UW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_SLV), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) i_dc_slice_cl_inp ( + .clk_i, + .rst_ni, + .test_cgbypass_i (1'b0), + .isolate_i (1'b0), + .axi_slave (cl_inp[i]), + .axi_master_async (cl_inp_async[i]) + ); + pulp_cluster_async i_cluster ( + .clk_i, + .rst_ni, + .ref_clk_i (clk_i), + .cluster_id_i (cluster_id), + .fetch_en_i (cl_fetch_en_i[i]), + .eoc_o (cl_eoc_o[i]), + .busy_o (cl_busy_o[i]), + .slv (cl_inp_async[i]), + .mst (cl_oup_async[i]), + .dma (cl_dma_async[i]), + .icache (cl_icache_async[i]) + ); + axi_slice_dc_master_wrap #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DW), + .AXI_USER_WIDTH (AXI_UW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_IW_MST), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) i_dc_slice_cl_oup ( + .clk_i, + .rst_ni, + .test_cgbypass_i (1'b0), + .clock_down_i (1'b0), + .isolate_i (1'b0), + .incoming_req_o (), + .axi_slave_async (cl_oup_async[i]), + .axi_master (cl_oup[i]) + ); + axi_slice_dc_master_wrap #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_DW), + .AXI_USER_WIDTH (AXI_UW), + .AXI_ID_WIDTH (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .BUFFER_WIDTH (pulp_cluster_cfg_pkg::DC_BUF_W) + ) i_dc_slice_cl_dma ( + .clk_i, + .rst_ni, + .test_cgbypass_i (1'b0), + .clock_down_i (1'b0), + .isolate_i (1'b0), + .incoming_req_o (), + .axi_slave_async (cl_dma_async[i]), + .axi_master (cl_dma[i]) + ); + + end else begin : gen_cluster_sync + pulp_cluster_sync i_cluster ( + .clk_i, + .rst_ni, + .ref_clk_i (clk_i), + .cluster_id_i (cluster_id), + .fetch_en_i (cl_fetch_en_i[i]), + .eoc_o (cl_eoc_o[i]), + .busy_o (cl_busy_o[i]), + .slv (cl_inp[i]), + .mst (cl_oup[i]), + .dma (cl_dma[i]), + .icache (cl_icache[i]), + .nhi (cl_nhi[i]), + + .task_valid_i (sched_loc_valid[i]), + .task_ready_o (sched_loc_ready[i]), + .task_descr_i (sched_loc_task[i]), + .feedback_valid_o (loc_sched_valid[i]), + .feedback_ready_i (loc_sched_ready[i]), + .feedback_o (loc_sched_feedback[i]), + .cluster_active_o (cluster_active_d[i]), + .cmd_ready_i (cluster_cmd_ready[i]), + .cmd_valid_o (cluster_cmd_valid[i]), + .cmd_o (cluster_cmd[i]), + .cmd_resp_valid_i (cluster_cmd_resp_valid), + .cmd_resp_i (cluster_cmd_resp) + ); + end + end + + /// Address map + // Clusters + addr_t [N_CLUSTERS-1:0] cl_start_addr, cl_end_addr; + for (genvar i = 0; i < N_CLUSTERS; i++) begin : gen_map_clusters + assign cl_start_addr[i] = L1_CLUSTER_BASE + i * L1_CLUSTER_MEM_SIZE; + assign cl_end_addr[i] = L1_CLUSTER_BASE + (i+1) * L1_CLUSTER_MEM_SIZE; + end + // L2 + addr_t l2_hnd_start_addr, l2_hnd_end_addr, + l2_pkt_start_addr, l2_pkt_end_addr, + l2_prog_start_addr, l2_prog_end_addr, + l2_start_addr, l2_end_addr; + assign l2_hnd_start_addr = 32'h1C00_0000; + assign l2_hnd_end_addr = l2_hnd_start_addr + addr_t'(HND_MEM_SIZE); + + assign l2_pkt_start_addr = l2_hnd_end_addr; + assign l2_pkt_end_addr = l2_pkt_start_addr + addr_t'(PKT_MEM_SIZE); + + assign l2_prog_start_addr = 32'h1D00_0000; + assign l2_prog_end_addr = l2_prog_start_addr + 32'h0000_8000; + + assign l2_start_addr = l2_hnd_start_addr; + assign l2_end_addr = l2_pkt_end_addr; + + // Peripherals + addr_t periph_start_addr, periph_end_addr; + assign periph_start_addr = 32'h1A10_0000; + assign periph_end_addr = periph_start_addr + addr_t'(32*1024); + + prog_mem #( + .NumClusters (N_CLUSTERS), + .NumBytes (32*1024), + .AddrWidth (AXI_AW), + .DataWidth (pulp_cluster_cfg_pkg::AXI_DW_ICACHE), + .IdWidth (pulp_cluster_cfg_pkg::AXI_IW_ICACHE), + .UserWidth (AXI_UW), + .req_t (pulp_cluster_cfg_pkg::req_icache_t), + .resp_t (pulp_cluster_cfg_pkg::resp_icache_t) + ) i_prog_mem ( + .clk_i, + .rst_ni, + .cl_req_i ( cl_icache_req ), + .cl_resp_o ( cl_icache_resp ), + .host_req_i ( host_slv_downsized_req ), + .host_resp_o ( host_slv_downsized_resp ) + ); + + pe_noc #( + .NumClusters (N_CLUSTERS), + .AddrWidth (AXI_AW), + .ClDataWidth (pulp_cluster_cfg_pkg::AXI_DW), + .ClOupIdWidth (pulp_cluster_cfg_pkg::AXI_IW_MST), + .ClInpIdWidth (pulp_cluster_cfg_pkg::AXI_IW_SLV), + .L2DataWidth (AXI_WIDE_DW), + .L2IdWidth (AXI_IW), + .PeriphDataWidth (AXI_DW_PERIPHS), + .PeriphIdWidth (AXI_IW), + .UserWidth (AXI_UW), + .cl_oup_req_t (pulp_cluster_cfg_pkg::req_mst_t), + .cl_oup_resp_t (pulp_cluster_cfg_pkg::resp_mst_t), + .cl_inp_req_t (pulp_cluster_cfg_pkg::req_slv_t), + .cl_inp_resp_t (pulp_cluster_cfg_pkg::resp_slv_t), + .l2_req_t (req_t), + .l2_resp_t (resp_t), + .periph_req_t (periph_req_t), + .periph_resp_t (periph_resp_t) + ) i_pe_noc ( + .clk_i, + .rst_ni, + .cl_start_addr_i (cl_start_addr), + .cl_end_addr_i (cl_end_addr), + .l2_start_addr_i (l2_start_addr), + .l2_end_addr_i (l2_end_addr), + .periph_start_addr_i (periph_start_addr), + .periph_end_addr_i (periph_end_addr), + .from_cl_req_i (cl_oup_req), + .from_cl_resp_o (cl_oup_resp), + .to_cl_req_o (cl_inp_req), + .to_cl_resp_i (cl_inp_resp), + .l2_req_o (pe_l2_req), + .l2_resp_i (pe_l2_resp), + .periph_req_o (periph_req), + .periph_resp_i (periph_resp) + ); + + dma_noc #( + .NumClusters (N_CLUSTERS), + .AddrWidth (AXI_AW), + .DataWidth (AXI_WIDE_DW), + .DMAIdWidth (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .L2IdWidth (AXI_IW), + .UserWidth (AXI_UW), + .dma_req_t (pulp_cluster_cfg_pkg::req_dma_t), + .dma_resp_t (pulp_cluster_cfg_pkg::resp_dma_t), + .l2_req_t (req_t), + .l2_resp_t (resp_t) + ) i_dma_noc ( + .clk_i, + .rst_ni, + .l2_start_addr_i(l2_start_addr), + .l2_end_addr_i (l2_end_addr), + .dma_req_i (cl_dma_req), + .dma_resp_o (cl_dma_resp), + .l2_req_o (dma_l2_req), + .l2_resp_i (dma_l2_resp) + ); + + cluster_noc #( + .NumClusters (N_CLUSTERS), + .AddrWidth (AXI_AW), + .DataWidth (AXI_WIDE_DW), + .UserWidth (AXI_UW), + .NHIIdWidth (AXI_IW), + .ClIdWidth (pulp_cluster_cfg_pkg::AXI_DMA_IW), + .nhi_req_t (req_t), + .nhi_resp_t (resp_t), + .cl_req_t (pulp_cluster_cfg_pkg::req_dma_t), + .cl_resp_t (pulp_cluster_cfg_pkg::resp_dma_t) + ) i_cluster_noc ( + .clk_i, + .rst_ni, + .cl_start_addr_i (cl_start_addr), + .cl_end_addr_i (cl_end_addr), + .cl_req_o (cl_nhi_req), + .cl_resp_i (cl_nhi_resp), + .nhi_req_i (nhi_req), + .nhi_resp_o (nhi_resp) + ); + + l2_xbar #( + .AddrWidth (AXI_AW), + .DataWidth (AXI_WIDE_DW), + .IdWidth (AXI_IW), + .UserWidth (AXI_UW), + .req_t (req_t), + .resp_t (resp_t) + ) i_l2_xbar ( + .clk_i, + .rst_ni, + .l2_hnd_start_addr_i (l2_hnd_start_addr), + .l2_hnd_end_addr_i (l2_hnd_end_addr), + .l2_pkt_start_addr_i (l2_pkt_start_addr), + .l2_pkt_end_addr_i (l2_pkt_end_addr), + .pe_req_i (pe_l2_req), + .pe_resp_o (pe_l2_resp), + .dma_req_i (dma_l2_req), + .dma_resp_o (dma_l2_resp), + .l2_hnd_req_o (l2_hnd_req_a), + .l2_hnd_resp_i (l2_hnd_resp_a), + .l2_pkt_req_o (l2_pkt_req_a), + .l2_pkt_resp_i (l2_pkt_resp_a) + ); + + nhi_xbar #( + .AddrWidth (AXI_AW), + .DataWidth (AXI_WIDE_DW), + .IdWidth (AXI_IW), + .UserWidth (AXI_UW), + .req_t (req_t), + .resp_t (resp_t) + ) i_nhi_xbar ( + .clk_i, + .rst_ni, + .l2_hnd_start_addr_i ( l2_hnd_start_addr ), + .l2_hnd_end_addr_i ( l2_hnd_end_addr ), + .l2_pkt_start_addr_i ( l2_pkt_start_addr ), + .l2_pkt_end_addr_i ( l2_pkt_end_addr ), + .l2_prog_start_addr_i ( l2_prog_start_addr ), + .l2_prog_end_addr_i ( l2_prog_end_addr ), + .l1_start_addr_i ( cl_start_addr[0] ), + .l1_end_addr_i ( cl_end_addr[N_CLUSTERS-1] ), + .host_req_i ( host_slv_req ), + .host_resp_o ( host_slv_resp ), + .ni_req_i ( ni_req ), + .ni_resp_o ( ni_resp ), + .no_req_i ( no_req ), + .no_resp_o ( no_resp ), + .edma_req_i ( nhi_mst_edma_req ), + .edma_resp_o ( nhi_mst_edma_resp ), + .l2_hnd_req_o ( l2_hnd_req_b ), + .l2_hnd_resp_i ( l2_hnd_resp_b ), + .l2_pkt_req_o ( l2_pkt_req_b ), + .l2_pkt_resp_i ( l2_pkt_resp_b ), + .l2_prog_req_o ( host_l2_prog_req ), + .l2_prog_resp_i ( host_l2_prog_resp ), + .cluster_req_o ( nhi_req ), + .cluster_resp_i ( nhi_resp ) + ); + + axi_dw_downsizer #( + .AxiMaxReads ( 4 ), // Number of outstanding reads + .AxiSlvPortDataWidth ( pspin_cfg_pkg::AXI_WIDE_DW ), // Data width of the slv port + .AxiMstPortDataWidth ( pulp_cluster_cfg_pkg::AXI_DW_ICACHE ), // Data width of the mst port + .AxiAddrWidth ( pulp_cluster_cfg_pkg::AXI_AW ), // Address width + .AxiIdWidth ( pspin_cfg_pkg::AXI_IW ), // ID width + .aw_chan_t ( pspin_cfg_pkg::aw_t ), // AW Channel Type + .mst_w_chan_t ( pulp_cluster_cfg_pkg::w_icache_t ), // W Channel Type for the mst port + .slv_w_chan_t ( pspin_cfg_pkg::w_t ), // W Channel Type for the slv port + .b_chan_t ( pspin_cfg_pkg::b_t ), // B Channel Type + .ar_chan_t ( pspin_cfg_pkg::ar_t ), // AR Channel Type + .mst_r_chan_t ( pulp_cluster_cfg_pkg::r_icache_t ), // R Channel Type for the mst port + .slv_r_chan_t ( pspin_cfg_pkg::r_t ), // R Channel Type for the slv port + .axi_mst_req_t ( pulp_cluster_cfg_pkg::req_icache_t ), // AXI Request Type for mst ports + .axi_mst_resp_t ( pulp_cluster_cfg_pkg::resp_icache_t ), // AXI Response Type for mst ports + .axi_slv_req_t ( pspin_cfg_pkg::req_t ), // AXI Request Type for slv ports + .axi_slv_resp_t ( pspin_cfg_pkg::resp_t ) // AXI Response Type for slv ports + ) i_dw_downsizer_host_l2_prog ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .slv_req_i ( host_l2_prog_req ), + .slv_resp_o ( host_l2_prog_resp ), + .mst_req_o ( host_slv_downsized_req ), + .mst_resp_i ( host_slv_downsized_resp ) + ); + + axi_riscv_atomics_wrap #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW), + .AXI_MAX_READ_TXNS (4), + .AXI_MAX_WRITE_TXNS (4), + .RISCV_WORD_WIDTH (32) + ) i_atomics ( + .clk_i, + .rst_ni, + .slv (l2_hnd_mst_a), + .mst (l2_hnd_mst_wo_atomics) + ); + + l2_mem #( + .AXI_AW (AXI_AW), + .AXI_DW (AXI_WIDE_DW), + .AXI_UW (AXI_UW), + .AXI_IW (AXI_IW), + .N_BYTES (HND_MEM_SIZE), + .CUT_DW (64), + .CUT_N_WORDS (16384), + .N_PAR_CUTS_MUL (4) + ) i_l2_hnd_mem ( + .clk_i, + .rst_ni, + .slv_a (l2_hnd_mst_wo_atomics), + .slv_b (l2_hnd_mst_b) + ); + + l2_mem #( + .AXI_AW (AXI_AW), + .AXI_DW (AXI_WIDE_DW), + .AXI_UW (AXI_UW), + .AXI_IW (AXI_IW), + .N_BYTES (PKT_MEM_SIZE), + .CUT_DW (512), + .CUT_N_WORDS (2048), + .N_PAR_CUTS_MUL (32) + ) i_l2_pkt_mem ( + .clk_i, + .rst_ni, + .slv_a (l2_pkt_mst_a), + .slv_b (l2_pkt_mst_b) + ); + + soc_peripherals #( + .AXI_AW (AXI_AW), + .AXI_IW (AXI_IW), + .AXI_UW (AXI_UW), + .N_CORES (pulp_cluster_cfg_pkg::N_CORES), + .N_CLUSTERS (N_CLUSTERS) + ) i_periphs ( + .clk_i, + .rst_ni, + .test_en_i ('0), + .axi (periph_mst) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + cluster_active_q <= '0; + end else begin + cluster_active_q <= cluster_active_d; + end + end + +endmodule diff --git a/hw/src/pspin_cfg_pkg.sv b/hw/src/pspin_cfg_pkg.sv new file mode 100644 index 0000000..2816854 --- /dev/null +++ b/hw/src/pspin_cfg_pkg.sv @@ -0,0 +1,322 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +package automatic pspin_cfg_pkg; + + localparam int unsigned HOST_AXI_AW = 64; + + // Interface parameters + localparam int unsigned AXI_AW = pulp_cluster_cfg_pkg::AXI_AW; + localparam int unsigned AXI_WIDE_DW = 512; // [bit], must be a power of 2 + localparam int unsigned AXI_IW = 6; + localparam int unsigned AXI_UW = pulp_cluster_cfg_pkg::AXI_UW; + + localparam int unsigned PKT_MEM_SIZE = pulp_cluster_cfg_pkg::L2_SIZE / 2; + localparam int unsigned HND_MEM_SIZE = pulp_cluster_cfg_pkg::L2_SIZE / 2; + + localparam int unsigned SOC_DMA_AXI_REQ_DEPTH = 12; + localparam int unsigned SOC_DMA_REQ_FIFO_DEPT = 64; //tune me! + + /* + localparam longint unsigned PCIE_START_ADDR = 64'h1000_0000_0000_0000; + localparam longint unsigned PCIE_END_ADDR = 64'h1FFF_FFFF_FFFF_FFFF; + localparam int unsigned NHI_START_ADDR = 32'h1000_0000; + localparam int unsigned NHI_END_ADDR = 32'hFF00_0000; + */ + + localparam int unsigned C_SIZE_WIDTH = AXI_AW; + localparam int unsigned C_MSGID_WIDTH = 10; + localparam int unsigned C_ADDR_WIDTH = AXI_AW; + localparam int unsigned C_HOST_ADDR_WIDTH = HOST_AXI_AW; + localparam int unsigned NUM_CLUSTERS = 4; + localparam int unsigned NUM_CORES = 8; + + //MPQ engine + localparam int unsigned NUM_MPQ = 1024; + localparam int unsigned NUM_MPQ_CELLS = 128; + localparam int unsigned NUM_MPQ_STATIC_CELLS = 1; //per MPQ + + localparam int unsigned HER_FLAGS_IS_HDR_IDX = 4; + localparam int unsigned HER_FLAGS_IS_CMPL_IDX = 5; + + localparam int unsigned L1_CLUSTER_BASE = 32'h1000_0000; + localparam int unsigned L1_CLUSTER_MEM_SIZE = 32'h0040_0000; //address space reserved to a cluster is 4 MiB + + //this is the actual L1 memory size + localparam int unsigned L1_CLUSTER_ACTUAL_MEM_SIZE = 32'h0010_0000; // 1 MiB + + //L1_RUNTIME_OFFSET + L1_RUNTIME_SIZE < L1_SIZE + + localparam int unsigned L1_RUNTIME_OFFSET = 32'h0000_0400; // 1 KiB reserved at the beginning. + localparam int unsigned L1_RUNTIME_SIZE = 32'h0000_4000; // 16 KiB + + localparam int unsigned L1_PKT_BUFF_OFFSET = L1_RUNTIME_OFFSET + L1_RUNTIME_SIZE; + localparam int unsigned L1_PKT_BUFF_SIZE = 32'h0001_0000; // 64 KiB + + localparam int unsigned L1_SCRATCHPAD_OFFSET = L1_PKT_BUFF_OFFSET + L1_PKT_BUFF_SIZE; + localparam int unsigned L1_SCRATCHPAD_SIZE = L1_CLUSTER_ACTUAL_MEM_SIZE - L1_PKT_BUFF_OFFSET; + + //number of HERs that can be buffered (allows to overlap DMA transfer to running handlers) + localparam int unsigned BUFFERED_HERS_PER_CLUSTER = 12; + + // the number of HERs in a cluster is the number of buffer ones + the ones running + localparam int unsigned NUM_HERS_PER_CLUSTER = BUFFERED_HERS_PER_CLUSTER + NUM_CORES; + + //number of messages per cluster + localparam int unsigned NUM_MSG_PER_CLUSTER = NUM_MPQ / NUM_CLUSTERS; + + //max number of commands that an HPU can keep in flight + localparam int unsigned NUM_HPU_CMDS = 4; + + //Number of command interfaces (NIC outbound, soc-level DMA) and IDs + //NOTE: the IDs need to be consistent with the inputs of the cmd unit. + localparam int unsigned NUM_CMD_INTERFACES = 3; + localparam int unsigned CMD_HOSTDIRECT_ID = 0; + localparam int unsigned CMD_NIC_OUTBOUND_ID = 1; + localparam int unsigned CMD_EDMA_ID = 2; + + + // Interface types + typedef logic [AXI_AW-1:0] addr_t; + typedef logic [AXI_WIDE_DW-1:0] data_t; + typedef logic [AXI_WIDE_DW/8-1:0] strb_t; + typedef logic [AXI_IW-1:0] id_t; + typedef logic [AXI_UW-1:0] user_t; + typedef logic [HOST_AXI_AW-1:0] host_addr_t; + `AXI_TYPEDEF_AW_CHAN_T(aw_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(req_t, aw_t, w_t, ar_t) + `AXI_TYPEDEF_RESP_T(resp_t, b_t, r_t) + + `AXI_TYPEDEF_AW_CHAN_T(aw_host_t, host_addr_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_host_t, host_addr_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(host_req_t, aw_host_t, w_t, ar_host_t) + `AXI_TYPEDEF_RESP_T(host_resp_t, b_t, r_t) + + typedef logic [$clog2(NUM_HERS_PER_CLUSTER):0] cluster_occup_t; + typedef logic [31:0] pkt_ptr_t; + + typedef logic [C_ADDR_WIDTH-1:0] mem_addr_t; + typedef logic [C_SIZE_WIDTH-1:0] mem_size_t; + + + // feedback descriptor + typedef struct packed { + logic [C_ADDR_WIDTH-1:0] pkt_addr; + mem_size_t pkt_size; + logic [C_MSGID_WIDTH-1:0] msgid; + logic trigger_feedback; + } feedback_descr_t; + + typedef struct packed { + + //handler memory + mem_addr_t handler_mem_addr; + mem_size_t handler_mem_size; + + //host memory + host_addr_t host_mem_addr; + mem_size_t host_mem_size; + + //header handler + mem_addr_t hh_addr; + mem_size_t hh_size; + + //payload handler + mem_addr_t ph_addr; + mem_size_t ph_size; + + //completion (aka tail) handler + mem_addr_t th_addr; + mem_size_t th_size; + + //L1 scratchpads + mem_addr_t [NUM_CLUSTERS-1:0] scratchpad_addr; + mem_size_t [NUM_CLUSTERS-1:0] scratchpad_size; + + } mpq_meta_t; + + typedef struct packed { + + logic [C_MSGID_WIDTH-1:0] msgid; + + logic eom; + + //full her descriptor + mem_addr_t her_addr; + mem_size_t her_size; + mem_size_t xfer_size; + + mpq_meta_t mpq_meta; + } her_descr_t; + + //typedef enum logic [1:0] {HeaderHandler, PayloadHandler, CompletionHandler} her_task_type_t; + // job descriptor + typedef struct packed { + + logic [C_MSGID_WIDTH-1:0] msgid; + + mem_addr_t handler_fun; + mem_size_t handler_fun_size; + + mem_addr_t handler_mem_addr; + mem_size_t handler_mem_size; + + host_addr_t host_mem_addr; + mem_size_t host_mem_size; + + mem_addr_t pkt_addr; + mem_size_t pkt_size; + + logic trigger_feedback; + + mem_addr_t [NUM_CLUSTERS-1:0] scratchpad_addr; + mem_size_t [NUM_CLUSTERS-1:0] scratchpad_size; + + } handler_task_t; + + // DMA transfer descriptor + typedef struct packed { + logic [31:0] num_bytes; + logic [31:0] dst_addr_high; + logic [31:0] dst_addr_low; + logic [31:0] src_addr_high; + logic [31:0] src_addr_low; + logic deburst; + logic decouple; + logic serialize; + } transf_descr_t; + + // DMA transfer descriptor + typedef struct packed { + logic [31:0] num_bytes; + logic [31:0] dst_addr; + logic [31:0] src_addr; + logic deburst; + logic decouple; + logic serialize; + } transf_descr_32_t; + + // DMA transfer descriptor + typedef struct packed { + logic [31:0] num_bytes; + logic [65:0] dst_addr; + logic [65:0] src_addr; + logic deburst; + logic decouple; + logic serialize; + } transf_descr_soc_t; + + // Task descriptor (sent by the local scheduler to the HPU driver) + typedef struct packed { + handler_task_t handler_task; + pkt_ptr_t pkt_ptr; + } hpu_handler_task_t; + + // Task feedback descriptor (sent by the HPU driver to the local scheduler) + typedef struct packed { + feedback_descr_t feedback_descr; + pkt_ptr_t pkt_ptr; + } task_feedback_descr_t; + + + // a bit ugly but they are shared between the mpq_engine and the mpq_fsm, so not sure + // how to share these two types differertly (except for passing both of them as parameters, which + // would be ugly as well) + typedef enum logic [2:0] {Free, Header, HeaderRunning, Payload, PayloadDraining, Completion, CompletionRunning} mpq_state_t; + typedef struct packed { + mpq_state_t state; + logic [$clog2(NUM_MPQ_CELLS):0] length; + logic [$clog2(NUM_MPQ_CELLS):0] in_flight; + logic has_completion; + logic eom_seen; + } mpq_t; + + /* commands */ + + // network ID (e.g., IP address) + typedef logic [31:0] nid_t; + + // flow ID (e.g., (srcport, dstport) or matching bits) + typedef logic [31:0] fid_t; + + // memory type + typedef enum logic [1:0] {HostMem, NicMem} mem_type_t; + + // userptr + typedef logic [63:0] user_ptr_t; + + //NIC put/send command (224 b, padded to 76 B) + typedef struct packed { + logic [383:0] unused; // 384b + user_ptr_t user_ptr; // 64b + mem_size_t length; // 32b + host_addr_t src_addr; // 64b + fid_t fid; // 32b unused + nid_t nid; // 32b + } nic_cmd_t; + + // Host <-> PsPIN DMA command (193 b, padded to 76 B) + typedef struct packed { + logic [414:0] unused; // 415b + user_ptr_t user_ptr; // 64b + logic nic_to_host;// 1 + mem_size_t length; // 32b + mem_addr_t nic_addr; // 32b + host_addr_t host_addr; // 64b + } host_dma_cmd_t; + + // PsPIN <-> Host with immediate data (586 b, padded to 76 B) + typedef struct packed { + logic [AXI_WIDE_DW-1:0] imm_data; // 512b + logic [21:0] unused; // 22b + logic [$clog2(AXI_WIDE_DW)-1:0] imm_data_size; // 9b + logic nic_to_host; // 1b + host_addr_t host_addr; // 64b + } host_direct_cmd_t; + + typedef union packed { + logic [18:0][31:0] words; //TODO: determine this size programatically (max(sizeof(nic_cmd_t), sizeof(host_dma_cmd_t)))/32 + nic_cmd_t nic_cmd; + host_dma_cmd_t host_dma_cmd; + host_direct_cmd_t host_direct_cmd; + } pspin_cmd_descr_t; + + typedef enum logic [1:0] {HostMemCpy, NICSend, HostDirect} pspin_cmd_type_t; + typedef logic [$clog2(NUM_CMD_INTERFACES)-1:0] pspin_cmd_intf_id_t; + + typedef struct packed { + logic [$clog2(NUM_CLUSTERS)-1:0] cluster_id; + logic [$clog2(NUM_CORES)-1:0] core_id; + logic [$clog2(NUM_HPU_CMDS)-1:0] local_cmd_id; + } pspin_cmd_id_t; + + typedef struct packed { + pspin_cmd_intf_id_t intf_id; + pspin_cmd_id_t cmd_id; + pspin_cmd_type_t cmd_type; + pspin_cmd_descr_t descr; + + logic generate_event; + } pspin_cmd_t; + + typedef struct packed { + pspin_cmd_id_t cmd_id; + logic [AXI_WIDE_DW-1:0] imm_data; + } pspin_cmd_resp_t; + + +endpackage diff --git a/hw/src/pspin_verilator.sv b/hw/src/pspin_verilator.sv new file mode 100644 index 0000000..93880ae --- /dev/null +++ b/hw/src/pspin_verilator.sv @@ -0,0 +1,696 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import pspin_cfg_pkg::*; + +package automatic pspin_io; + + typedef logic [pspin_cfg_pkg::HOST_AXI_AW-1:0] wide_addr_t; + typedef logic [pspin_cfg_pkg::AXI_AW-1:0] addr_t; + typedef logic [pspin_cfg_pkg::AXI_WIDE_DW-1:0] data_t; + typedef logic [pspin_cfg_pkg::AXI_WIDE_DW/8-1:0] strb_t; + typedef logic [pspin_cfg_pkg::AXI_IW-1:0] id_t; + typedef logic [pspin_cfg_pkg::AXI_UW-1:0] user_t; + +endpackage + +module pspin_verilator #( +) ( + /** Clocks and Resets **/ + input logic clk_i, + input logic rst_ni, + + // asserted when HPUs are ready + output logic pspin_active_o, + + // termination signal + input logic eos_i, + + // MPQ full signal + output logic [NUM_MPQ-1:0] mpq_full_o, + + + /** NIC inbound engine AXI slave port **/ + // WRITE ADDRESS CHANNEL + input pspin_io::addr_t ni_slave_aw_addr_i, + input axi_pkg::prot_t ni_slave_aw_prot_i, + input axi_pkg::region_t ni_slave_aw_region_i, + input axi_pkg::len_t ni_slave_aw_len_i, + input axi_pkg::size_t ni_slave_aw_size_i, + input axi_pkg::burst_t ni_slave_aw_burst_i, + input logic ni_slave_aw_lock_i, + input axi_pkg::atop_t ni_slave_aw_atop_i, + input axi_pkg::cache_t ni_slave_aw_cache_i, + input axi_pkg::qos_t ni_slave_aw_qos_i, + input pspin_io::id_t ni_slave_aw_id_i, + input pspin_io::user_t ni_slave_aw_user_i, + input logic ni_slave_aw_valid_i, + output logic ni_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input pspin_io::addr_t ni_slave_ar_addr_i, + input axi_pkg::prot_t ni_slave_ar_prot_i, + input axi_pkg::region_t ni_slave_ar_region_i, + input axi_pkg::len_t ni_slave_ar_len_i, + input axi_pkg::size_t ni_slave_ar_size_i, + input axi_pkg::burst_t ni_slave_ar_burst_i, + input logic ni_slave_ar_lock_i, + input axi_pkg::cache_t ni_slave_ar_cache_i, + input axi_pkg::qos_t ni_slave_ar_qos_i, + input pspin_io::id_t ni_slave_ar_id_i, + input pspin_io::user_t ni_slave_ar_user_i, + input logic ni_slave_ar_valid_i, + output logic ni_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input pspin_io::data_t ni_slave_w_data_i, + input pspin_io::strb_t ni_slave_w_strb_i, + input pspin_io::user_t ni_slave_w_user_i, + input logic ni_slave_w_last_i, + input logic ni_slave_w_valid_i, + output logic ni_slave_w_ready_o, + + // READ DATA CHANNEL + output pspin_io::data_t ni_slave_r_data_o, + output axi_pkg::resp_t ni_slave_r_resp_o, + output logic ni_slave_r_last_o, + output pspin_io::id_t ni_slave_r_id_o, + output pspin_io::user_t ni_slave_r_user_o, + output logic ni_slave_r_valid_o, + input logic ni_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output axi_pkg::resp_t ni_slave_b_resp_o, + output pspin_io::id_t ni_slave_b_id_o, + output pspin_io::user_t ni_slave_b_user_o, + output logic ni_slave_b_valid_o, + input logic ni_slave_b_ready_i, + + + /** NIC outbound engine AXI slave port **/ + // WRITE ADDRESS CHANNEL + input pspin_io::addr_t no_slave_aw_addr_i, + input axi_pkg::prot_t no_slave_aw_prot_i, + input axi_pkg::region_t no_slave_aw_region_i, + input axi_pkg::len_t no_slave_aw_len_i, + input axi_pkg::size_t no_slave_aw_size_i, + input axi_pkg::burst_t no_slave_aw_burst_i, + input logic no_slave_aw_lock_i, + input axi_pkg::atop_t no_slave_aw_atop_i, + input axi_pkg::cache_t no_slave_aw_cache_i, + input axi_pkg::qos_t no_slave_aw_qos_i, + input pspin_io::id_t no_slave_aw_id_i, + input pspin_io::user_t no_slave_aw_user_i, + input logic no_slave_aw_valid_i, + output logic no_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input pspin_io::addr_t no_slave_ar_addr_i, + input axi_pkg::prot_t no_slave_ar_prot_i, + input axi_pkg::region_t no_slave_ar_region_i, + input axi_pkg::len_t no_slave_ar_len_i, + input axi_pkg::size_t no_slave_ar_size_i, + input axi_pkg::burst_t no_slave_ar_burst_i, + input logic no_slave_ar_lock_i, + input axi_pkg::cache_t no_slave_ar_cache_i, + input axi_pkg::qos_t no_slave_ar_qos_i, + input pspin_io::id_t no_slave_ar_id_i, + input pspin_io::user_t no_slave_ar_user_i, + input logic no_slave_ar_valid_i, + output logic no_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input pspin_io::data_t no_slave_w_data_i, + input pspin_io::strb_t no_slave_w_strb_i, + input pspin_io::user_t no_slave_w_user_i, + input logic no_slave_w_last_i, + input logic no_slave_w_valid_i, + output logic no_slave_w_ready_o, + + // READ DATA CHANNEL + output pspin_io::data_t no_slave_r_data_o, + output axi_pkg::resp_t no_slave_r_resp_o, + output logic no_slave_r_last_o, + output pspin_io::id_t no_slave_r_id_o, + output pspin_io::user_t no_slave_r_user_o, + output logic no_slave_r_valid_o, + input logic no_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output axi_pkg::resp_t no_slave_b_resp_o, + output pspin_io::id_t no_slave_b_id_o, + output pspin_io::user_t no_slave_b_user_o, + output logic no_slave_b_valid_o, + input logic no_slave_b_ready_i, + + + /** host AXI slave port **/ + // WRITE ADDRESS CHANNEL + input pspin_io::addr_t host_slave_aw_addr_i, + input axi_pkg::prot_t host_slave_aw_prot_i, + input axi_pkg::region_t host_slave_aw_region_i, + input axi_pkg::len_t host_slave_aw_len_i, + input axi_pkg::size_t host_slave_aw_size_i, + input axi_pkg::burst_t host_slave_aw_burst_i, + input logic host_slave_aw_lock_i, + input axi_pkg::atop_t host_slave_aw_atop_i, + input axi_pkg::cache_t host_slave_aw_cache_i, + input axi_pkg::qos_t host_slave_aw_qos_i, + input pspin_io::id_t host_slave_aw_id_i, + input pspin_io::user_t host_slave_aw_user_i, + input logic host_slave_aw_valid_i, + output logic host_slave_aw_ready_o, + + // READ ADDRESS CHANNEL + input pspin_io::addr_t host_slave_ar_addr_i, + input axi_pkg::prot_t host_slave_ar_prot_i, + input axi_pkg::region_t host_slave_ar_region_i, + input axi_pkg::len_t host_slave_ar_len_i, + input axi_pkg::size_t host_slave_ar_size_i, + input axi_pkg::burst_t host_slave_ar_burst_i, + input logic host_slave_ar_lock_i, + input axi_pkg::cache_t host_slave_ar_cache_i, + input axi_pkg::qos_t host_slave_ar_qos_i, + input pspin_io::id_t host_slave_ar_id_i, + input pspin_io::user_t host_slave_ar_user_i, + input logic host_slave_ar_valid_i, + output logic host_slave_ar_ready_o, + + // WRITE DATA CHANNEL + input pspin_io::data_t host_slave_w_data_i, + input pspin_io::strb_t host_slave_w_strb_i, + input pspin_io::user_t host_slave_w_user_i, + input logic host_slave_w_last_i, + input logic host_slave_w_valid_i, + output logic host_slave_w_ready_o, + + // READ DATA CHANNEL + output pspin_io::data_t host_slave_r_data_o, + output axi_pkg::resp_t host_slave_r_resp_o, + output logic host_slave_r_last_o, + output pspin_io::id_t host_slave_r_id_o, + output pspin_io::user_t host_slave_r_user_o, + output logic host_slave_r_valid_o, + input logic host_slave_r_ready_i, + + // WRITE RESPONSE CHANNEL + output axi_pkg::resp_t host_slave_b_resp_o, + output pspin_io::id_t host_slave_b_id_o, + output pspin_io::user_t host_slave_b_user_o, + output logic host_slave_b_valid_o, + input logic host_slave_b_ready_i, + + + /** host AXI master port **/ + // WRITE ADDRESS CHANNEL + output pspin_io::wide_addr_t host_master_aw_addr_o, + output axi_pkg::prot_t host_master_aw_prot_o, + output axi_pkg::region_t host_master_aw_region_o, + output axi_pkg::len_t host_master_aw_len_o, + output axi_pkg::size_t host_master_aw_size_o, + output axi_pkg::burst_t host_master_aw_burst_o, + output logic host_master_aw_lock_o, + output axi_pkg::atop_t host_master_aw_atop_o, + output axi_pkg::cache_t host_master_aw_cache_o, + output axi_pkg::qos_t host_master_aw_qos_o, + output pspin_io::id_t host_master_aw_id_o, + output pspin_io::user_t host_master_aw_user_o, + output logic host_master_aw_valid_o, + input logic host_master_aw_ready_i, + + // READ ADDRESS CHANNEL + output pspin_io::wide_addr_t host_master_ar_addr_o, + output axi_pkg::prot_t host_master_ar_prot_o, + output axi_pkg::region_t host_master_ar_region_o, + output axi_pkg::len_t host_master_ar_len_o, + output axi_pkg::size_t host_master_ar_size_o, + output axi_pkg::burst_t host_master_ar_burst_o, + output logic host_master_ar_lock_o, + output axi_pkg::cache_t host_master_ar_cache_o, + output axi_pkg::qos_t host_master_ar_qos_o, + output pspin_io::id_t host_master_ar_id_o, + output pspin_io::user_t host_master_ar_user_o, + output logic host_master_ar_valid_o, + input logic host_master_ar_ready_i, + + // WRITE DATA CHANNEL + output pspin_io::data_t host_master_w_data_o, + output pspin_io::strb_t host_master_w_strb_o, + output pspin_io::user_t host_master_w_user_o, + output logic host_master_w_last_o, + output logic host_master_w_valid_o, + input logic host_master_w_ready_i, + + // READ DATA CHANNEL + input pspin_io::data_t host_master_r_data_i, + input axi_pkg::resp_t host_master_r_resp_i, + input logic host_master_r_last_i, + input pspin_io::id_t host_master_r_id_i, + input pspin_io::user_t host_master_r_user_i, + input logic host_master_r_valid_i, + output logic host_master_r_ready_o, + + // WRITE RESPONSE CHANNEL + input axi_pkg::resp_t host_master_b_resp_i, + input pspin_io::id_t host_master_b_id_i, + input pspin_io::user_t host_master_b_user_i, + input logic host_master_b_valid_i, + output logic host_master_b_ready_o, + + + /** NIC inbound engine/packet generator control **/ + //from pktgen + output logic her_ready_o, + input logic her_valid_i, + input logic [C_MSGID_WIDTH-1:0] her_msgid_i, + input logic her_is_eom_i, + input mem_addr_t her_addr_i, + input mem_size_t her_size_i, + input mem_size_t her_xfer_size_i, + input mem_addr_t her_meta_handler_mem_addr_i, + input mem_size_t her_meta_handler_mem_size_i, + input host_addr_t her_meta_host_mem_addr_i, + input mem_size_t her_meta_host_mem_size_i, + input mem_addr_t her_meta_hh_addr_i, + input mem_size_t her_meta_hh_size_i, + input mem_addr_t her_meta_ph_addr_i, + input mem_size_t her_meta_ph_size_i, + input mem_addr_t her_meta_th_addr_i, + input mem_size_t her_meta_th_size_i, + input mem_addr_t her_meta_scratchpad_0_addr_i, + input mem_size_t her_meta_scratchpad_0_size_i, + input mem_addr_t her_meta_scratchpad_1_addr_i, + input mem_size_t her_meta_scratchpad_1_size_i, + input mem_addr_t her_meta_scratchpad_2_addr_i, + input mem_size_t her_meta_scratchpad_2_size_i, + input mem_addr_t her_meta_scratchpad_3_addr_i, + input mem_size_t her_meta_scratchpad_3_size_i, + + // to pktgen + input logic feedback_ready_i, + output logic feedback_valid_o, + output mem_addr_t feedback_her_addr_o, + output mem_size_t feedback_her_size_o, + output logic [C_MSGID_WIDTH-1:0] feedback_msgid_o, + + + /** NIC outbound engine or NIC command unit **/ + input logic nic_cmd_req_ready_i, + output logic nic_cmd_req_valid_o, + output pspin_cmd_id_t nic_cmd_req_id_o, + output nid_t nic_cmd_req_nid_o, + output fid_t nic_cmd_req_fid_o, + output host_addr_t nic_cmd_req_src_addr_o, + output mem_size_t nic_cmd_req_length_o, + output user_ptr_t nic_cmd_req_user_ptr_o, + + input logic nic_cmd_resp_valid_i, + input pspin_cmd_id_t nic_cmd_resp_id_i +); + + import pulp_cluster_cfg_pkg::N_TCDM_BANKS; + import pulp_cluster_cfg_pkg::TCDM_WORDS_PER_BANK; + import pspin_cfg_pkg::NUM_CLUSTERS; + + import "DPI-C" function string get_slm_path(); + +/* + export "DPI-C" function fill_l2_prog_mem; + export "DPI-C" function fill_l2_handler_mem; +*/ + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) axi_ni (); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) axi_no (); + + AXI_BUS #( + .AXI_ADDR_WIDTH (HOST_AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) axi_host_mst (); + + AXI_BUS #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_WIDE_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW) + ) axi_host_slv (); + + logic [pspin_cfg_pkg::NUM_CLUSTERS-1:0] cl_fetch_en; + logic [pspin_cfg_pkg::NUM_CLUSTERS-1:0] cl_eoc; + logic [pspin_cfg_pkg::NUM_CLUSTERS-1:0] cl_busy; + + + her_descr_t her_descr; + feedback_descr_t feedback; + pspin_cmd_t nic_cmd_req; + pspin_cmd_resp_t nic_cmd_resp; + + pspin #( + .N_CLUSTERS (pspin_cfg_pkg::NUM_CLUSTERS), + .N_MPQ (pspin_cfg_pkg::NUM_MPQ) + ) i_pspin ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .cl_fetch_en_i (cl_fetch_en), + .cl_eoc_o (cl_eoc), + .cl_busy_o (cl_busy), + + .mpq_full_o (mpq_full_o), + + .axi_ni_slv (axi_ni), + .axi_no_slv (axi_no), + .axi_host_mst (axi_host_mst), + .axi_host_slv (axi_host_slv), + + .her_ready_o (her_ready_o), + .her_valid_i (her_valid_i), + .her_i (her_descr), + .eos_i (eos_i), + .nic_feedback_ready_i (feedback_ready_i), + .nic_feedback_valid_o (feedback_valid_o), + .nic_feedback_o (feedback), + .pspin_active_o (pspin_active_o), + .nic_cmd_ready_i (nic_cmd_req_ready_i), + .nic_cmd_valid_o (nic_cmd_req_valid_o), + .nic_cmd_o (nic_cmd_req), + .nic_cmd_resp_valid_i (nic_cmd_resp_valid_i), + .nic_cmd_resp_i (nic_cmd_resp) + ); + + + //TODO: move number of rows and number of cols in configuration file! + for (genvar iRow = 0; iRow < 1; iRow++) begin: gen_fill_l2_hnd_rows + for (genvar iCol = 0; iCol < 32; iCol++) begin: gen_fill_l2_hnd_cols + initial begin + //$readmemh($sformatf("../sim_files/slm_files/l2_hnd_%01d_%01d.slm", iRow, iCol), + //$display($sformatf(get_l2_handler_slm_path(), iRow, iCol)); + $readmemh({get_slm_path(), $sformatf("l2_hnd_%01d_%01d.slm", iRow, iCol)}, + i_pspin.i_l2_hnd_mem.gen_cols[iCol].gen_rows[iRow].i_mem_cut.i_tc_sram.sram); + end + end + end + + for (genvar iCluster = 0; iCluster < NUM_CLUSTERS; iCluster++) begin: gen_fill_tcdm_cluster + for (genvar iBank = 0; iBank < N_TCDM_BANKS; iBank++) begin: gen_fill_tcdm_bank + initial begin + for (int iWord = 0; iWord < TCDM_WORDS_PER_BANK; iWord++) begin + i_pspin.gen_clusters[iCluster].gen_cluster_sync.i_cluster.i_ooc.i_bound.gen_tcdm_banks[iBank].i_mem.i_tc_sram.sram[iWord] = '0; + end + end + end + end + + initial begin + //$readmemh("../sim_files/slm_files/prog_mem_stim.slm", i_pspin.i_prog_mem.i_sram.i_tc_sram.sram); + $readmemh({get_slm_path(), "prog_mem_stim.slm"}, i_pspin.i_prog_mem.i_sram.i_tc_sram.sram); + end + + // Wait for termination + always_ff @(posedge clk_i, negedge rst_ni) begin + if (i_pspin.i_mpq_engine.mpq_busy == '0 && i_pspin.i_mpq_engine.eos_i && i_pspin.i_mpq_engine.fifo_empty) begin + $finish; + end + end + + /* enable instruction fetch signal */ + assign cl_fetch_en = (rst_ni) ? 4'b1111 : '0; + + // Connecting axi_ni + assign axi_ni.aw_addr = ni_slave_aw_addr_i; + assign axi_ni.aw_prot = ni_slave_aw_prot_i; + assign axi_ni.aw_region = ni_slave_aw_region_i; + assign axi_ni.aw_len = ni_slave_aw_len_i; + assign axi_ni.aw_size = ni_slave_aw_size_i; + assign axi_ni.aw_burst = ni_slave_aw_burst_i; + assign axi_ni.aw_lock = ni_slave_aw_lock_i; + assign axi_ni.aw_atop = ni_slave_aw_atop_i; + assign axi_ni.aw_cache = ni_slave_aw_cache_i; + assign axi_ni.aw_qos = ni_slave_aw_qos_i; + assign axi_ni.aw_id = ni_slave_aw_id_i; + assign axi_ni.aw_user = ni_slave_aw_user_i; + assign axi_ni.aw_valid = ni_slave_aw_valid_i; + assign ni_slave_aw_ready_o = axi_ni.aw_ready; + + assign axi_ni.ar_addr = ni_slave_ar_addr_i; + assign axi_ni.ar_prot = ni_slave_ar_prot_i; + assign axi_ni.ar_region = ni_slave_ar_region_i; + assign axi_ni.ar_len = ni_slave_ar_len_i; + assign axi_ni.ar_size = ni_slave_ar_size_i; + assign axi_ni.ar_burst = ni_slave_ar_burst_i; + assign axi_ni.ar_lock = ni_slave_ar_lock_i; + assign axi_ni.ar_cache = ni_slave_ar_cache_i; + assign axi_ni.ar_qos = ni_slave_ar_qos_i; + assign axi_ni.ar_id = ni_slave_ar_id_i; + assign axi_ni.ar_user = ni_slave_ar_user_i; + assign axi_ni.ar_valid = ni_slave_ar_valid_i; + assign ni_slave_ar_ready_o = axi_ni.ar_ready; + + assign axi_ni.w_data = ni_slave_w_data_i; + assign axi_ni.w_strb = ni_slave_w_strb_i; + assign axi_ni.w_user = ni_slave_w_user_i; + assign axi_ni.w_last = ni_slave_w_last_i; + assign axi_ni.w_valid = ni_slave_w_valid_i; + assign ni_slave_w_ready_o = axi_ni.w_ready; + + assign ni_slave_r_data_o = axi_ni.r_data; + assign ni_slave_r_resp_o = axi_ni.r_resp; + assign ni_slave_r_last_o = axi_ni.r_last; + assign ni_slave_r_id_o = axi_ni.r_id; + assign ni_slave_r_user_o = axi_ni.r_user; + assign ni_slave_r_valid_o = axi_ni.r_valid; + assign axi_ni.r_ready = ni_slave_r_ready_i; + + assign ni_slave_b_resp_o = axi_ni.b_resp; + assign ni_slave_b_id_o = axi_ni.b_id; + assign ni_slave_b_user_o = axi_ni.b_user; + assign ni_slave_b_valid_o = axi_ni.b_valid; + assign axi_ni.b_ready = ni_slave_b_ready_i; + + + // Connecting axi_no + assign axi_no.aw_addr = no_slave_aw_addr_i; + assign axi_no.aw_prot = no_slave_aw_prot_i; + assign axi_no.aw_region = no_slave_aw_region_i; + assign axi_no.aw_len = no_slave_aw_len_i; + assign axi_no.aw_size = no_slave_aw_size_i; + assign axi_no.aw_burst = no_slave_aw_burst_i; + assign axi_no.aw_lock = no_slave_aw_lock_i; + assign axi_no.aw_atop = no_slave_aw_atop_i; + assign axi_no.aw_cache = no_slave_aw_cache_i; + assign axi_no.aw_qos = no_slave_aw_qos_i; + assign axi_no.aw_id = no_slave_aw_id_i; + assign axi_no.aw_user = no_slave_aw_user_i; + assign axi_no.aw_valid = no_slave_aw_valid_i; + assign no_slave_aw_ready_o = axi_no.aw_ready; + + assign axi_no.ar_addr = no_slave_ar_addr_i; + assign axi_no.ar_prot = no_slave_ar_prot_i; + assign axi_no.ar_region = no_slave_ar_region_i; + assign axi_no.ar_len = no_slave_ar_len_i; + assign axi_no.ar_size = no_slave_ar_size_i; + assign axi_no.ar_burst = no_slave_ar_burst_i; + assign axi_no.ar_lock = no_slave_ar_lock_i; + assign axi_no.ar_cache = no_slave_ar_cache_i; + assign axi_no.ar_qos = no_slave_ar_qos_i; + assign axi_no.ar_id = no_slave_ar_id_i; + assign axi_no.ar_user = no_slave_ar_user_i; + assign axi_no.ar_valid = no_slave_ar_valid_i; + assign no_slave_ar_ready_o = axi_no.ar_ready; + + assign axi_no.w_data = no_slave_w_data_i; + assign axi_no.w_strb = no_slave_w_strb_i; + assign axi_no.w_user = no_slave_w_user_i; + assign axi_no.w_last = no_slave_w_last_i; + assign axi_no.w_valid = no_slave_w_valid_i; + assign no_slave_w_ready_o = axi_no.w_ready; + + assign no_slave_r_data_o = axi_no.r_data; + assign no_slave_r_resp_o = axi_no.r_resp; + assign no_slave_r_last_o = axi_no.r_last; + assign no_slave_r_id_o = axi_no.r_id; + assign no_slave_r_user_o = axi_no.r_user; + assign no_slave_r_valid_o = axi_no.r_valid; + assign axi_no.r_ready = no_slave_r_ready_i; + + assign no_slave_b_resp_o = axi_no.b_resp; + assign no_slave_b_id_o = axi_no.b_id; + assign no_slave_b_user_o = axi_no.b_user; + assign no_slave_b_valid_o = axi_no.b_valid; + assign axi_no.b_ready = no_slave_b_ready_i; + + + // Connecting axi_host_slv + assign axi_host_slv.aw_addr = host_slave_aw_addr_i; + assign axi_host_slv.aw_prot = host_slave_aw_prot_i; + assign axi_host_slv.aw_region = host_slave_aw_region_i; + assign axi_host_slv.aw_len = host_slave_aw_len_i; + assign axi_host_slv.aw_size = host_slave_aw_size_i; + assign axi_host_slv.aw_burst = host_slave_aw_burst_i; + assign axi_host_slv.aw_lock = host_slave_aw_lock_i; + assign axi_host_slv.aw_atop = host_slave_aw_atop_i; + assign axi_host_slv.aw_cache = host_slave_aw_cache_i; + assign axi_host_slv.aw_qos = host_slave_aw_qos_i; + assign axi_host_slv.aw_id = host_slave_aw_id_i; + assign axi_host_slv.aw_user = host_slave_aw_user_i; + assign axi_host_slv.aw_valid = host_slave_aw_valid_i; + assign host_slave_aw_ready_o = axi_host_slv.aw_ready; + + assign axi_host_slv.ar_addr = host_slave_ar_addr_i; + assign axi_host_slv.ar_prot = host_slave_ar_prot_i; + assign axi_host_slv.ar_region = host_slave_ar_region_i; + assign axi_host_slv.ar_len = host_slave_ar_len_i; + assign axi_host_slv.ar_size = host_slave_ar_size_i; + assign axi_host_slv.ar_burst = host_slave_ar_burst_i; + assign axi_host_slv.ar_lock = host_slave_ar_lock_i; + assign axi_host_slv.ar_cache = host_slave_ar_cache_i; + assign axi_host_slv.ar_qos = host_slave_ar_qos_i; + assign axi_host_slv.ar_id = host_slave_ar_id_i; + assign axi_host_slv.ar_user = host_slave_ar_user_i; + assign axi_host_slv.ar_valid = host_slave_ar_valid_i; + assign host_slave_ar_ready_o = axi_host_slv.ar_ready; + + assign axi_host_slv.w_data = host_slave_w_data_i; + assign axi_host_slv.w_strb = host_slave_w_strb_i; + assign axi_host_slv.w_user = host_slave_w_user_i; + assign axi_host_slv.w_last = host_slave_w_last_i; + assign axi_host_slv.w_valid = host_slave_w_valid_i; + assign host_slave_w_ready_o = axi_host_slv.w_ready; + + assign host_slave_r_data_o = axi_host_slv.r_data; + assign host_slave_r_resp_o = axi_host_slv.r_resp; + assign host_slave_r_last_o = axi_host_slv.r_last; + assign host_slave_r_id_o = axi_host_slv.r_id; + assign host_slave_r_user_o = axi_host_slv.r_user; + assign host_slave_r_valid_o = axi_host_slv.r_valid; + assign axi_host_slv.r_ready = host_slave_r_ready_i; + + assign host_slave_b_resp_o = axi_host_slv.b_resp; + assign host_slave_b_id_o = axi_host_slv.b_id; + assign host_slave_b_user_o = axi_host_slv.b_user; + assign host_slave_b_valid_o = axi_host_slv.b_valid; + assign axi_host_slv.b_ready = host_slave_b_ready_i; + + // Connecting axi_host_mst + assign host_master_aw_addr_o = axi_host_mst.aw_addr; + assign host_master_aw_prot_o = axi_host_mst.aw_prot; + assign host_master_aw_region_o = axi_host_mst.aw_region; + assign host_master_aw_len_o = axi_host_mst.aw_len; + assign host_master_aw_size_o = axi_host_mst.aw_size; + assign host_master_aw_burst_o = axi_host_mst.aw_burst; + assign host_master_aw_lock_o = axi_host_mst.aw_lock; + assign host_master_aw_atop_o = axi_host_mst.aw_atop; + assign host_master_aw_cache_o = axi_host_mst.aw_cache; + assign host_master_aw_qos_o = axi_host_mst.aw_qos; + assign host_master_aw_id_o = axi_host_mst.aw_id; + assign host_master_aw_user_o = axi_host_mst.aw_user; + assign host_master_aw_valid_o = axi_host_mst.aw_valid; + assign axi_host_mst.aw_ready = host_master_aw_ready_i; + + assign host_master_ar_addr_o = axi_host_mst.ar_addr; + assign host_master_ar_prot_o = axi_host_mst.ar_prot; + assign host_master_ar_region_o = axi_host_mst.ar_region; + assign host_master_ar_len_o = axi_host_mst.ar_len; + assign host_master_ar_size_o = axi_host_mst.ar_size; + assign host_master_ar_burst_o = axi_host_mst.ar_burst; + assign host_master_ar_lock_o = axi_host_mst.ar_lock; + assign host_master_ar_cache_o = axi_host_mst.ar_cache; + assign host_master_ar_qos_o = axi_host_mst.ar_qos; + assign host_master_ar_id_o = axi_host_mst.ar_id; + assign host_master_ar_user_o = axi_host_mst.ar_user; + assign host_master_ar_valid_o = axi_host_mst.ar_valid; + assign axi_host_mst.ar_ready = host_master_ar_ready_i; + + assign host_master_w_data_o = axi_host_mst.w_data; + assign host_master_w_strb_o = axi_host_mst.w_strb; + assign host_master_w_user_o = axi_host_mst.w_user; + assign host_master_w_last_o = axi_host_mst.w_last; + assign host_master_w_valid_o = axi_host_mst.w_valid; + assign axi_host_mst.w_ready = host_master_w_ready_i; + + assign axi_host_mst.r_data = host_master_r_data_i; + assign axi_host_mst.r_resp = host_master_r_resp_i; + assign axi_host_mst.r_last = host_master_r_last_i; + assign axi_host_mst.r_id = host_master_r_id_i; + assign axi_host_mst.r_user = host_master_r_user_i; + assign axi_host_mst.r_valid = host_master_r_valid_i; + assign host_master_r_ready_o = axi_host_mst.r_ready; + + assign axi_host_mst.b_resp = host_master_b_resp_i; + assign axi_host_mst.b_id = host_master_b_id_i; + assign axi_host_mst.b_user = host_master_b_user_i; + assign axi_host_mst.b_valid = host_master_b_valid_i; + assign host_master_b_ready_o = axi_host_mst.b_ready; + + // Connecting her_descr + assign her_descr.msgid = her_msgid_i; + assign her_descr.eom = her_is_eom_i; + assign her_descr.her_addr = her_addr_i; + assign her_descr.her_size = her_size_i; + assign her_descr.xfer_size = her_xfer_size_i; + assign her_descr.mpq_meta.handler_mem_addr = her_meta_handler_mem_addr_i; + assign her_descr.mpq_meta.handler_mem_size = her_meta_handler_mem_size_i; + assign her_descr.mpq_meta.host_mem_addr = her_meta_host_mem_addr_i; + assign her_descr.mpq_meta.host_mem_size = her_meta_host_mem_size_i; + assign her_descr.mpq_meta.hh_addr = her_meta_hh_addr_i; + assign her_descr.mpq_meta.hh_size = her_meta_hh_size_i; + assign her_descr.mpq_meta.ph_addr = her_meta_ph_addr_i; + assign her_descr.mpq_meta.ph_size = her_meta_ph_size_i; + assign her_descr.mpq_meta.th_addr = her_meta_th_addr_i; + assign her_descr.mpq_meta.th_size = her_meta_th_size_i; + assign her_descr.mpq_meta.scratchpad_addr[0] = her_meta_scratchpad_0_addr_i; + assign her_descr.mpq_meta.scratchpad_addr[1] = her_meta_scratchpad_1_addr_i; + assign her_descr.mpq_meta.scratchpad_addr[2] = her_meta_scratchpad_2_addr_i; + assign her_descr.mpq_meta.scratchpad_addr[3] = her_meta_scratchpad_3_addr_i; + assign her_descr.mpq_meta.scratchpad_size[0] = her_meta_scratchpad_0_size_i; + assign her_descr.mpq_meta.scratchpad_size[1] = her_meta_scratchpad_1_size_i; + assign her_descr.mpq_meta.scratchpad_size[2] = her_meta_scratchpad_2_size_i; + assign her_descr.mpq_meta.scratchpad_size[3] = her_meta_scratchpad_3_size_i; + + // Connecting feedback + assign feedback_her_addr_o = feedback.pkt_addr; + assign feedback_her_size_o = feedback.pkt_size; + assign feedback_msgid_o = feedback.msgid; + + // Connecting NIC command request + assign nic_cmd_req_id_o = nic_cmd_req.cmd_id; + assign nic_cmd_req_nid_o = nic_cmd_req.descr.nic_cmd.nid; + assign nic_cmd_req_fid_o = nic_cmd_req.descr.nic_cmd.fid; + assign nic_cmd_req_src_addr_o = nic_cmd_req.descr.nic_cmd.src_addr; + assign nic_cmd_req_length_o = nic_cmd_req.descr.nic_cmd.length; + assign nic_cmd_req_user_ptr_o = nic_cmd_req.descr.nic_cmd.user_ptr; + + // Connecting NIC command response + assign nic_cmd_resp.cmd_id = nic_cmd_resp_id_i; + + + // Observe SoC bus for errors. + for (genvar iCluster = 0; iCluster < NUM_CLUSTERS; iCluster++) begin: gen_assert_cluster + assert property (@(posedge i_pspin.clk_i) i_pspin.rst_ni && i_pspin.cl_oup[iCluster].r_valid + |-> !i_pspin.cl_oup[iCluster].r_resp[1]) + else $warning("R resp error at cl_oup[%01d]", iCluster); + + assert property (@(posedge i_pspin.clk_i) i_pspin.rst_ni && i_pspin.cl_oup[iCluster].b_valid + |-> !i_pspin.cl_oup[iCluster].b_resp[1]) + else $warning("B resp error at cl_oup[%01d]", iCluster); + end + +endmodule diff --git a/hw/src/pulp_cluster_cfg_pkg.sv b/hw/src/pulp_cluster_cfg_pkg.sv new file mode 100644 index 0000000..c1bf424 --- /dev/null +++ b/hw/src/pulp_cluster_cfg_pkg.sv @@ -0,0 +1,88 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +`include "axi/typedef.svh" + +// Configuration package for PULP cluster OOC stub +package automatic pulp_cluster_cfg_pkg; + // -- Decoupling of cluster clock domain + localparam bit ASYNC = 1'b0; + localparam int unsigned DC_BUF_W = 8; + // -- Cores + localparam int unsigned N_CORES = 8; // must be a power of 2 and <= 8 + // -- AXI + localparam int unsigned AXI_AW = 32; // [bit] + localparam int unsigned AXI_DW = 64; // [bit] + localparam int unsigned AXI_IW_MST = 6; // [bit] + localparam int unsigned AXI_IW_SLV = 4; // [bit] + localparam int unsigned AXI_UW = 4; // [bit] + // -- DMA + localparam int unsigned AXI_DMA_DW = 512; // [bit]; do not change + localparam int unsigned AXI_DMA_IW = 4; // [bit]; do not change + localparam int unsigned DMA_MAX_BURST_SIZE = 2048; // [B], must be a power of 2 + // Maximum number of beats in a DMA burst on the SoC bus + localparam int unsigned DMA_MAX_BURST_LEN = DMA_MAX_BURST_SIZE / (AXI_DW/8); + // Maximum number of transactions the DMA can have in flight + localparam int unsigned DMA_MAX_N_TXNS = N_CORES; + localparam int unsigned N_DMAS = 4; // larger values seem to break the cluster + // -- Instruction Cache + localparam int unsigned ICACHE_SIZE = 4096; // [B], must be a power of 2 + localparam int unsigned AXI_DW_ICACHE = 64; // [bit]; do not change, seems to break instruction cache + localparam int unsigned AXI_IW_ICACHE = 6; // [bit]; do not change, seems to break instruction cache + // -- TCDM + localparam int unsigned N_TCDM_BANKS = 8*N_CORES; // must be a power of 2 + localparam int unsigned TCDM_SIZE = 1024*1024; // [B], must be a power of 2 + localparam int unsigned TCDM_WORDS_PER_BANK = (TCDM_SIZE / 4) / N_TCDM_BANKS; + // -- L2 Memory (not inside cluster) + localparam int unsigned L2_SIZE = 8192*1024; // [B], must be a power of 2 + + typedef logic [AXI_AW-1:0] addr_t; + typedef logic [5:0] cluster_id_t; + typedef logic [AXI_DW-1:0] data_t; + typedef logic [AXI_DMA_DW-1:0] data_dma_t; + typedef logic [AXI_DW_ICACHE-1:0] data_icache_t; + typedef logic [DC_BUF_W-1:0] dc_buf_t; + typedef logic [AXI_IW_MST-1:0] id_mst_t; + typedef logic [AXI_IW_SLV-1:0] id_slv_t; + typedef logic [AXI_DMA_IW-1:0] id_dma_t; + typedef logic [AXI_IW_ICACHE-1:0] id_icache_t; + typedef logic [AXI_DW/8-1:0] strb_t; + typedef logic [AXI_DMA_DW/8-1:0] strb_dma_t; + typedef logic [AXI_DW_ICACHE/8-1:0] strb_icache_t; + typedef logic [AXI_UW-1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_mst_t, addr_t, id_mst_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(aw_slv_t, addr_t, id_slv_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(aw_dma_t, addr_t, id_dma_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(aw_icache_t, addr_t, id_icache_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_dma_t, data_dma_t, strb_dma_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_icache_t, data_icache_t, strb_icache_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_mst_t, id_mst_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_slv_t, id_slv_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_dma_t, id_dma_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_icache_t, id_icache_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_mst_t, addr_t, id_mst_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_slv_t, addr_t, id_slv_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_dma_t, addr_t, id_dma_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_icache_t, addr_t, id_icache_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_mst_t, data_t, id_mst_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_slv_t, data_t, id_slv_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_dma_t, data_dma_t, id_dma_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_icache_t, data_icache_t, id_icache_t, user_t) + `AXI_TYPEDEF_REQ_T(req_mst_t, aw_mst_t, w_t, ar_mst_t) + `AXI_TYPEDEF_REQ_T(req_slv_t, aw_slv_t, w_t, ar_slv_t) + `AXI_TYPEDEF_REQ_T(req_dma_t, aw_dma_t, w_dma_t, ar_dma_t) + `AXI_TYPEDEF_REQ_T(req_icache_t, aw_icache_t, w_icache_t, ar_icache_t) + `AXI_TYPEDEF_RESP_T(resp_mst_t, b_mst_t, r_mst_t) + `AXI_TYPEDEF_RESP_T(resp_slv_t, b_slv_t, r_slv_t) + `AXI_TYPEDEF_RESP_T(resp_dma_t, b_dma_t, r_dma_t) + `AXI_TYPEDEF_RESP_T(resp_icache_t, b_icache_t, r_icache_t) +endpackage diff --git a/hw/src/pulp_cluster_ooc.sv b/hw/src/pulp_cluster_ooc.sv new file mode 100644 index 0000000..8a7c6f4 --- /dev/null +++ b/hw/src/pulp_cluster_ooc.sv @@ -0,0 +1,1213 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +import axi_pkg::*; +import pulp_cluster_cfg_pkg::*; + +// Stub of PULP Cluster for out-of-context synthesis +module pulp_cluster_ooc ( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + input cluster_id_t cluster_id_i, + input logic fetch_en_i, + output logic eoc_o, + output logic busy_o, + + // Slave Port + // AW + input addr_t slv_aw_addr_i, + input prot_t slv_aw_prot_i, + input region_t slv_aw_region_i, + input len_t slv_aw_len_i, + input size_t slv_aw_size_i, + input burst_t slv_aw_burst_i, + input logic slv_aw_lock_i, + input atop_t slv_aw_atop_i, + input cache_t slv_aw_cache_i, + input qos_t slv_aw_qos_i, + input id_slv_t slv_aw_id_i, + input user_t slv_aw_user_i, + // used if ASYNC_INTF + input dc_buf_t slv_aw_writetoken_i, + output dc_buf_t slv_aw_readpointer_o, + // used if !ASYNC_INTF + input logic slv_aw_valid_i, + output logic slv_aw_ready_o, + // AR + input addr_t slv_ar_addr_i, + input prot_t slv_ar_prot_i, + input region_t slv_ar_region_i, + input len_t slv_ar_len_i, + input size_t slv_ar_size_i, + input burst_t slv_ar_burst_i, + input logic slv_ar_lock_i, + input cache_t slv_ar_cache_i, + input qos_t slv_ar_qos_i, + input id_slv_t slv_ar_id_i, + input user_t slv_ar_user_i, + // used if ASYNC_INTF + input dc_buf_t slv_ar_writetoken_i, + output dc_buf_t slv_ar_readpointer_o, + // used if !ASYNC_INTF + input logic slv_ar_valid_i, + output logic slv_ar_ready_o, + // W + input data_t slv_w_data_i, + input strb_t slv_w_strb_i, + input user_t slv_w_user_i, + input logic slv_w_last_i, + // used if ASYNC_INTF + input dc_buf_t slv_w_writetoken_i, + output dc_buf_t slv_w_readpointer_o, + // used if !ASYNC_INTF + input logic slv_w_valid_i, + output logic slv_w_ready_o, + // R + output data_t slv_r_data_o, + output resp_t slv_r_resp_o, + output logic slv_r_last_o, + output id_slv_t slv_r_id_o, + output user_t slv_r_user_o, + // used if ASYNC_INTF + output dc_buf_t slv_r_writetoken_o, + input dc_buf_t slv_r_readpointer_i, + // used if !ASYNC_INTF + output logic slv_r_valid_o, + input logic slv_r_ready_i, + // B + output resp_t slv_b_resp_o, + output id_slv_t slv_b_id_o, + output user_t slv_b_user_o, + // used if ASYNC_INTF + output dc_buf_t slv_b_writetoken_o, + input dc_buf_t slv_b_readpointer_i, + // used if !ASYNC_INTF + output logic slv_b_valid_o, + input logic slv_b_ready_i, + + // Master Port + // AW + output addr_t mst_aw_addr_o, + output prot_t mst_aw_prot_o, + output region_t mst_aw_region_o, + output len_t mst_aw_len_o, + output size_t mst_aw_size_o, + output burst_t mst_aw_burst_o, + output logic mst_aw_lock_o, + output atop_t mst_aw_atop_o, + output cache_t mst_aw_cache_o, + output qos_t mst_aw_qos_o, + output id_mst_t mst_aw_id_o, + output user_t mst_aw_user_o, + // used if ASYNC_INTF + output dc_buf_t mst_aw_writetoken_o, + input dc_buf_t mst_aw_readpointer_i, + // used if !ASYNC_INTF + output logic mst_aw_valid_o, + input logic mst_aw_ready_i, + // AR + output addr_t mst_ar_addr_o, + output prot_t mst_ar_prot_o, + output region_t mst_ar_region_o, + output len_t mst_ar_len_o, + output size_t mst_ar_size_o, + output burst_t mst_ar_burst_o, + output logic mst_ar_lock_o, + output cache_t mst_ar_cache_o, + output qos_t mst_ar_qos_o, + output id_mst_t mst_ar_id_o, + output user_t mst_ar_user_o, + // used if ASYNC_INTF + output dc_buf_t mst_ar_writetoken_o, + input dc_buf_t mst_ar_readpointer_i, + // used if !ASYNC_INTF + output logic mst_ar_valid_o, + input logic mst_ar_ready_i, + // W + output data_t mst_w_data_o, + output strb_t mst_w_strb_o, + output user_t mst_w_user_o, + output logic mst_w_last_o, + // used if ASYNC_INTF + output dc_buf_t mst_w_writetoken_o, + input dc_buf_t mst_w_readpointer_i, + // used if !ASYNC_INTF + output logic mst_w_valid_o, + input logic mst_w_ready_i, + // R + input data_t mst_r_data_i, + input resp_t mst_r_resp_i, + input logic mst_r_last_i, + input id_mst_t mst_r_id_i, + input user_t mst_r_user_i, + // used if ASYNC_INTF + input dc_buf_t mst_r_writetoken_i, + output dc_buf_t mst_r_readpointer_o, + // used if !ASYNC_INTF + input logic mst_r_valid_i, + output logic mst_r_ready_o, + // B + input resp_t mst_b_resp_i, + input id_mst_t mst_b_id_i, + input user_t mst_b_user_i, + // used if ASYNC_INTF + input dc_buf_t mst_b_writetoken_i, + output dc_buf_t mst_b_readpointer_o, + // used if !ASYNC_INTF + input logic mst_b_valid_i, + output logic mst_b_ready_o, + + // AXI4 DMA MASTER + // WRITE ADDRESS CHANNEL + output addr_t dma_aw_addr_o, + output prot_t dma_aw_prot_o, + output region_t dma_aw_region_o, + output len_t dma_aw_len_o, + output size_t dma_aw_size_o, + output burst_t dma_aw_burst_o, + output logic dma_aw_lock_o, + output atop_t dma_aw_atop_o, + output cache_t dma_aw_cache_o, + output qos_t dma_aw_qos_o, + output id_dma_t dma_aw_id_o, + output user_t dma_aw_user_o, + output logic dma_aw_valid_o, + input logic dma_aw_ready_i, + + // READ ADDRESS CHANNEL + output addr_t dma_ar_addr_o, + output prot_t dma_ar_prot_o, + output region_t dma_ar_region_o, + output len_t dma_ar_len_o, + output size_t dma_ar_size_o, + output burst_t dma_ar_burst_o, + output logic dma_ar_lock_o, + output cache_t dma_ar_cache_o, + output qos_t dma_ar_qos_o, + output id_dma_t dma_ar_id_o, + output user_t dma_ar_user_o, + output logic dma_ar_valid_o, + input logic dma_ar_ready_i, + + // WRITE DATA CHANNEL + output data_dma_t dma_w_data_o, + output strb_dma_t dma_w_strb_o, + output user_t dma_w_user_o, + output logic dma_w_last_o, + output logic dma_w_valid_o, + input logic dma_w_ready_i, + + // READ DATA CHANNEL + input data_dma_t dma_r_data_i, + input resp_t dma_r_resp_i, + input logic dma_r_last_i, + input id_dma_t dma_r_id_i, + input user_t dma_r_user_i, + input logic dma_r_valid_i, + output logic dma_r_ready_o, + + // WRITE RESPONSE CHANNEL + input resp_t dma_b_resp_i, + input id_dma_t dma_b_id_i, + input user_t dma_b_user_i, + input logic dma_b_valid_i, + output logic dma_b_ready_o, + + //AXI4 NHI SLAVE + // WRITE ADDRESS CHANNEL + input addr_t nhi_aw_addr_i, + input prot_t nhi_aw_prot_i, + input region_t nhi_aw_region_i, + input len_t nhi_aw_len_i, + input size_t nhi_aw_size_i, + input burst_t nhi_aw_burst_i, + input logic nhi_aw_lock_i, + input atop_t nhi_aw_atop_i, + input cache_t nhi_aw_cache_i, + input qos_t nhi_aw_qos_i, + input id_dma_t nhi_aw_id_i, + input user_t nhi_aw_user_i, + input logic nhi_aw_valid_i, + output logic nhi_aw_ready_o, + + // READ ADDRESS CHANNEL + input addr_t nhi_ar_addr_i, + input prot_t nhi_ar_prot_i, + input region_t nhi_ar_region_i, + input len_t nhi_ar_len_i, + input size_t nhi_ar_size_i, + input burst_t nhi_ar_burst_i, + input logic nhi_ar_lock_i, + input cache_t nhi_ar_cache_i, + input qos_t nhi_ar_qos_i, + input id_dma_t nhi_ar_id_i, + input user_t nhi_ar_user_i, + input logic nhi_ar_valid_i, + output logic nhi_ar_ready_o, + + // WRITE DATA CHANNEL + input data_dma_t nhi_w_data_i, + input strb_dma_t nhi_w_strb_i, + input user_t nhi_w_user_i, + input logic nhi_w_last_i, + input logic nhi_w_valid_i, + output logic nhi_w_ready_o, + + // READ DATA CHANNEL + output data_dma_t nhi_r_data_o, + output resp_t nhi_r_resp_o, + output logic nhi_r_last_o, + output id_dma_t nhi_r_id_o, + output user_t nhi_r_user_o, + output logic nhi_r_valid_o, + input logic nhi_r_ready_i, + + // WRITE RESPONSE CHANNEL + output resp_t nhi_b_resp_o, + output id_dma_t nhi_b_id_o, + output user_t nhi_b_user_o, + output logic nhi_b_valid_o, + input logic nhi_b_ready_i, + + // Instruction Cache Master Port + output addr_t icache_aw_addr_o, + output prot_t icache_aw_prot_o, + output region_t icache_aw_region_o, + output len_t icache_aw_len_o, + output size_t icache_aw_size_o, + output burst_t icache_aw_burst_o, + output logic icache_aw_lock_o, + output atop_t icache_aw_atop_o, + output cache_t icache_aw_cache_o, + output qos_t icache_aw_qos_o, + output id_icache_t icache_aw_id_o, + output user_t icache_aw_user_o, + output logic icache_aw_valid_o, + input logic icache_aw_ready_i, + + output addr_t icache_ar_addr_o, + output prot_t icache_ar_prot_o, + output region_t icache_ar_region_o, + output len_t icache_ar_len_o, + output size_t icache_ar_size_o, + output burst_t icache_ar_burst_o, + output logic icache_ar_lock_o, + output cache_t icache_ar_cache_o, + output qos_t icache_ar_qos_o, + output id_icache_t icache_ar_id_o, + output user_t icache_ar_user_o, + output logic icache_ar_valid_o, + input logic icache_ar_ready_i, + + output data_icache_t icache_w_data_o, + output strb_icache_t icache_w_strb_o, + output user_t icache_w_user_o, + output logic icache_w_last_o, + output logic icache_w_valid_o, + input logic icache_w_ready_i, + + input data_icache_t icache_r_data_i, + input resp_t icache_r_resp_i, + input logic icache_r_last_i, + input id_icache_t icache_r_id_i, + input user_t icache_r_user_i, + input logic icache_r_valid_i, + output logic icache_r_ready_o, + + input resp_t icache_b_resp_i, + input id_icache_t icache_b_id_i, + input user_t icache_b_user_i, + input logic icache_b_valid_i, + output logic icache_b_ready_o, + + input logic task_valid_i, + output logic task_ready_o, + input pspin_cfg_pkg::handler_task_t task_descr_i, + + output logic feedback_valid_o, + input logic feedback_ready_i, + output pspin_cfg_pkg::feedback_descr_t feedback_o, + + output logic cluster_active_o, + + input logic cmd_ready_i, + output logic cmd_valid_o, + output pspin_cfg_pkg::pspin_cmd_t cmd_o, + + input logic cmd_resp_valid_i, + input pspin_cfg_pkg::pspin_cmd_resp_t cmd_resp_i +); + + pulp_cluster #( + .ASYNC_INTF (ASYNC), + .NB_CORES (N_CORES), + .NB_HWACC_PORTS (0), + .NB_DMAS (N_DMAS), + .CLUSTER_ALIAS (1'b1), + .CLUSTER_ALIAS_BASE (12'h1B0), + .TCDM_SIZE (TCDM_SIZE), + .NB_TCDM_BANKS (N_TCDM_BANKS), + .XNE_PRESENT (1'b0), + // I$ Parameters + .NB_CACHE_BANKS (4), + .CACHE_SIZE (ICACHE_SIZE), + .L2_SIZE (L2_SIZE), + // Core Parameters + .DEM_PER_BEFORE_TCDM_TS (1'b0), + .ROM_BOOT_ADDR (32'h1A00_0000), + .BOOT_ADDR (32'h1D00_0080), + // AXI Parameters + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_C2S_WIDTH (AXI_DW), + .AXI_DATA_S2C_WIDTH (AXI_DW), + .AXI_USER_WIDTH (AXI_UW), + .AXI_ID_IN_WIDTH (AXI_IW_SLV), + .AXI_ID_OUT_WIDTH (AXI_IW_MST), + .DC_SLICE_BUFFER_WIDTH (DC_BUF_W), + // TCDM and Interconnect Parameters + .DATA_WIDTH (32), + .ADDR_WIDTH (32), + .TEST_SET_BIT (20), + // DMA Parameters + .NB_OUTSND_BURSTS (DMA_MAX_N_TXNS), + .MCHAN_BURST_LENGTH (DMA_MAX_BURST_SIZE) + ) i_bound ( + .clk_i, + .rst_ni, + .ref_clk_i, + + .pmu_mem_pwdn_i (1'b0), + .base_addr_i ('0), + .test_mode_i ('0), + .en_sa_boot_i ('0), + + .cluster_id_i, + + .fetch_en_i, + .eoc_o, + .busy_o, + + .ext_events_writetoken_i ('0), + .ext_events_readpointer_o (), + .ext_events_dataasync_i ('0), + .dma_pe_evt_ack_i ('0), + .dma_pe_evt_valid_o (), + .dma_pe_irq_ack_i ('0), + .dma_pe_irq_valid_o (), + .pf_evt_ack_i ('0), + .pf_evt_valid_o (), + + .data_slave_aw_addr_i (slv_aw_addr_i), + .data_slave_aw_prot_i (slv_aw_prot_i), + .data_slave_aw_region_i (slv_aw_region_i), + .data_slave_aw_len_i (slv_aw_len_i), + .data_slave_aw_size_i (slv_aw_size_i), + .data_slave_aw_burst_i (slv_aw_burst_i), + .data_slave_aw_lock_i (slv_aw_lock_i), + .data_slave_aw_atop_i (slv_aw_atop_i), + .data_slave_aw_cache_i (slv_aw_cache_i), + .data_slave_aw_qos_i (slv_aw_qos_i), + .data_slave_aw_id_i (slv_aw_id_i), + .data_slave_aw_user_i (slv_aw_user_i), + .data_slave_aw_writetoken_i (slv_aw_writetoken_i), + .data_slave_aw_readpointer_o (slv_aw_readpointer_o), + .data_slave_aw_valid_i (slv_aw_valid_i), + .data_slave_aw_ready_o (slv_aw_ready_o), + .data_slave_ar_addr_i (slv_ar_addr_i), + .data_slave_ar_prot_i (slv_ar_prot_i), + .data_slave_ar_region_i (slv_ar_region_i), + .data_slave_ar_len_i (slv_ar_len_i), + .data_slave_ar_size_i (slv_ar_size_i), + .data_slave_ar_burst_i (slv_ar_burst_i), + .data_slave_ar_lock_i (slv_ar_lock_i), + .data_slave_ar_cache_i (slv_ar_cache_i), + .data_slave_ar_qos_i (slv_ar_qos_i), + .data_slave_ar_id_i (slv_ar_id_i), + .data_slave_ar_user_i (slv_ar_user_i), + .data_slave_ar_writetoken_i (slv_ar_writetoken_i), + .data_slave_ar_readpointer_o (slv_ar_readpointer_o), + .data_slave_ar_valid_i (slv_ar_valid_i), + .data_slave_ar_ready_o (slv_ar_ready_o), + .data_slave_w_data_i (slv_w_data_i), + .data_slave_w_strb_i (slv_w_strb_i), + .data_slave_w_user_i (slv_w_user_i), + .data_slave_w_last_i (slv_w_last_i), + .data_slave_w_writetoken_i (slv_w_writetoken_i), + .data_slave_w_readpointer_o (slv_w_readpointer_o), + .data_slave_w_valid_i (slv_w_valid_i), + .data_slave_w_ready_o (slv_w_ready_o), + .data_slave_r_data_o (slv_r_data_o), + .data_slave_r_resp_o (slv_r_resp_o), + .data_slave_r_last_o (slv_r_last_o), + .data_slave_r_id_o (slv_r_id_o), + .data_slave_r_user_o (slv_r_user_o), + .data_slave_r_writetoken_o (slv_r_writetoken_o), + .data_slave_r_readpointer_i (slv_r_readpointer_i), + .data_slave_r_valid_o (slv_r_valid_o), + .data_slave_r_ready_i (slv_r_ready_i), + .data_slave_b_resp_o (slv_b_resp_o), + .data_slave_b_id_o (slv_b_id_o), + .data_slave_b_user_o (slv_b_user_o), + .data_slave_b_writetoken_o (slv_b_writetoken_o), + .data_slave_b_readpointer_i (slv_b_readpointer_i), + .data_slave_b_valid_o (slv_b_valid_o), + .data_slave_b_ready_i (slv_b_ready_i), + + .data_master_aw_addr_o (mst_aw_addr_o), + .data_master_aw_prot_o (mst_aw_prot_o), + .data_master_aw_region_o (mst_aw_region_o), + .data_master_aw_len_o (mst_aw_len_o), + .data_master_aw_size_o (mst_aw_size_o), + .data_master_aw_burst_o (mst_aw_burst_o), + .data_master_aw_lock_o (mst_aw_lock_o), + .data_master_aw_atop_o (mst_aw_atop_o), + .data_master_aw_cache_o (), + .data_master_aw_qos_o (mst_aw_qos_o), + .data_master_aw_id_o (mst_aw_id_o), + .data_master_aw_user_o (mst_aw_user_o), + .data_master_aw_writetoken_o (mst_aw_writetoken_o), + .data_master_aw_readpointer_i (mst_aw_readpointer_i), + .data_master_aw_valid_o (mst_aw_valid_o), + .data_master_aw_ready_i (mst_aw_ready_i), + .data_master_ar_addr_o (mst_ar_addr_o), + .data_master_ar_prot_o (mst_ar_prot_o), + .data_master_ar_region_o (mst_ar_region_o), + .data_master_ar_len_o (mst_ar_len_o), + .data_master_ar_size_o (mst_ar_size_o), + .data_master_ar_burst_o (mst_ar_burst_o), + .data_master_ar_lock_o (mst_ar_lock_o), + .data_master_ar_cache_o (), + .data_master_ar_qos_o (mst_ar_qos_o), + .data_master_ar_id_o (mst_ar_id_o), + .data_master_ar_user_o (mst_ar_user_o), + .data_master_ar_writetoken_o (mst_ar_writetoken_o), + .data_master_ar_readpointer_i (mst_ar_readpointer_i), + .data_master_ar_valid_o (mst_ar_valid_o), + .data_master_ar_ready_i (mst_ar_ready_i), + .data_master_w_data_o (mst_w_data_o), + .data_master_w_strb_o (mst_w_strb_o), + .data_master_w_user_o (mst_w_user_o), + .data_master_w_last_o (mst_w_last_o), + .data_master_w_writetoken_o (mst_w_writetoken_o), + .data_master_w_readpointer_i (mst_w_readpointer_i), + .data_master_w_valid_o (mst_w_valid_o), + .data_master_w_ready_i (mst_w_ready_i), + .data_master_r_data_i (mst_r_data_i), + .data_master_r_resp_i (mst_r_resp_i), + .data_master_r_last_i (mst_r_last_i), + .data_master_r_id_i (mst_r_id_i), + .data_master_r_user_i (mst_r_user_i), + .data_master_r_writetoken_i (mst_r_writetoken_i), + .data_master_r_readpointer_o (mst_r_readpointer_o), + .data_master_r_valid_i (mst_r_valid_i), + .data_master_r_ready_o (mst_r_ready_o), + .data_master_b_resp_i (mst_b_resp_i), + .data_master_b_id_i (mst_b_id_i), + .data_master_b_user_i (mst_b_user_i), + .data_master_b_writetoken_i (mst_b_writetoken_i), + .data_master_b_readpointer_o (mst_b_readpointer_o), + .data_master_b_valid_i (mst_b_valid_i), + .data_master_b_ready_o (mst_b_ready_o), + + .dma_aw_addr_o, + .dma_aw_prot_o, + .dma_aw_region_o, + .dma_aw_len_o, + .dma_aw_size_o, + .dma_aw_burst_o, + .dma_aw_lock_o, + .dma_aw_atop_o, + .dma_aw_cache_o (), + .dma_aw_qos_o, + .dma_aw_id_o, + .dma_aw_user_o, + .dma_aw_valid_o, + .dma_aw_ready_i, + .dma_ar_addr_o, + .dma_ar_prot_o, + .dma_ar_region_o, + .dma_ar_len_o, + .dma_ar_size_o, + .dma_ar_burst_o, + .dma_ar_lock_o, + .dma_ar_cache_o (), + .dma_ar_qos_o, + .dma_ar_id_o, + .dma_ar_user_o, + .dma_ar_valid_o, + .dma_ar_ready_i, + .dma_w_data_o, + .dma_w_strb_o, + .dma_w_user_o, + .dma_w_last_o, + .dma_w_valid_o, + .dma_w_ready_i, + .dma_r_data_i, + .dma_r_resp_i, + .dma_r_last_i, + .dma_r_id_i, + .dma_r_user_i, + .dma_r_valid_i, + .dma_r_ready_o, + .dma_b_resp_i, + .dma_b_id_i, + .dma_b_user_i, + .dma_b_valid_i, + .dma_b_ready_o, + + .nhi_aw_addr_i, + .nhi_aw_prot_i, + .nhi_aw_region_i, + .nhi_aw_len_i, + .nhi_aw_size_i, + .nhi_aw_burst_i, + .nhi_aw_lock_i, + .nhi_aw_atop_i, + .nhi_aw_cache_i, + .nhi_aw_qos_i, + .nhi_aw_id_i, + .nhi_aw_user_i, + .nhi_aw_valid_i, + .nhi_aw_ready_o, + .nhi_ar_addr_i, + .nhi_ar_prot_i, + .nhi_ar_region_i, + .nhi_ar_len_i, + .nhi_ar_size_i, + .nhi_ar_burst_i, + .nhi_ar_lock_i, + .nhi_ar_cache_i, + .nhi_ar_qos_i, + .nhi_ar_id_i, + .nhi_ar_user_i, + .nhi_ar_valid_i, + .nhi_ar_ready_o, + .nhi_w_data_i, + .nhi_w_strb_i, + .nhi_w_user_i, + .nhi_w_last_i, + .nhi_w_valid_i, + .nhi_w_ready_o, + .nhi_r_data_o, + .nhi_r_resp_o, + .nhi_r_last_o, + .nhi_r_id_o, + .nhi_r_user_o, + .nhi_r_valid_o, + .nhi_r_ready_i, + .nhi_b_resp_o, + .nhi_b_id_o, + .nhi_b_user_o, + .nhi_b_valid_o, + .nhi_b_ready_i, + + .icache_aw_addr_o, + .icache_aw_prot_o, + .icache_aw_region_o, + .icache_aw_len_o, + .icache_aw_size_o, + .icache_aw_burst_o, + .icache_aw_lock_o, + .icache_aw_atop_o, + .icache_aw_cache_o, + .icache_aw_qos_o, + .icache_aw_id_o, + .icache_aw_user_o, + .icache_aw_valid_o, + .icache_aw_ready_i, + .icache_ar_addr_o, + .icache_ar_prot_o, + .icache_ar_region_o, + .icache_ar_len_o, + .icache_ar_size_o, + .icache_ar_burst_o, + .icache_ar_lock_o, + .icache_ar_cache_o, + .icache_ar_qos_o, + .icache_ar_id_o, + .icache_ar_user_o, + .icache_ar_valid_o, + .icache_ar_ready_i, + .icache_w_data_o, + .icache_w_strb_o, + .icache_w_user_o, + .icache_w_last_o, + .icache_w_valid_o, + .icache_w_ready_i, + .icache_r_data_i, + .icache_r_resp_i, + .icache_r_last_i, + .icache_r_id_i, + .icache_r_user_i, + .icache_r_valid_i, + .icache_r_ready_o, + .icache_b_resp_i, + .icache_b_id_i, + .icache_b_user_i, + .icache_b_valid_i, + .icache_b_ready_o, + + .task_valid_i (task_valid_i), + .task_ready_o (task_ready_o), + .task_descr_i (task_descr_i), + .feedback_valid_o (feedback_valid_o), + .feedback_ready_i (feedback_ready_i), + .feedback_o (feedback_o), + .cluster_active_o (cluster_active_o), + .cmd_ready_i (cmd_ready_i), + .cmd_valid_o (cmd_valid_o), + .cmd_o (cmd_o), + .cmd_resp_valid_i (cmd_resp_valid_i), + .cmd_resp_i (cmd_resp_i) + ); + // Make all reads and writes from cluster modifiable. + // TODO: This might be undesired for transactions from cores to peripherals, better modify the + // DMA and I$ to issue modifiable transactions. + assign mst_ar_cache_o = 4'b0010; + assign mst_aw_cache_o = 4'b0010; + assign dma_ar_cache_o = 4'b0010; + assign dma_aw_cache_o = 4'b0010; + +endmodule + + +// Interface wrapper for OOC-synthesized synchronous PULP cluster +module pulp_cluster_sync ( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + input cluster_id_t cluster_id_i, + input logic fetch_en_i, + output logic eoc_o, + output logic busy_o, + AXI_BUS.Slave slv, + AXI_BUS.Master mst, + AXI_BUS.Master dma, + AXI_BUS.Master icache, + AXI_BUS.Slave nhi, + + input logic task_valid_i, + output logic task_ready_o, + input pspin_cfg_pkg::handler_task_t task_descr_i, + output logic feedback_valid_o, + input logic feedback_ready_i, + output pspin_cfg_pkg::feedback_descr_t feedback_o, + output logic cluster_active_o, + input logic cmd_ready_i, + output logic cmd_valid_o, + output pspin_cfg_pkg::pspin_cmd_t cmd_o, + input logic cmd_resp_valid_i, + input pspin_cfg_pkg::pspin_cmd_resp_t cmd_resp_i +); + + pulp_cluster_ooc i_ooc ( + .clk_i, + .rst_ni, + .ref_clk_i, + .cluster_id_i, + .fetch_en_i, + .eoc_o, + .busy_o, + + .slv_aw_addr_i (slv.aw_addr), + .slv_aw_prot_i (slv.aw_prot), + .slv_aw_region_i (slv.aw_region), + .slv_aw_len_i (slv.aw_len), + .slv_aw_size_i (slv.aw_size), + .slv_aw_burst_i (slv.aw_burst), + .slv_aw_lock_i (slv.aw_lock), + .slv_aw_atop_i (slv.aw_atop), + .slv_aw_cache_i (slv.aw_cache), + .slv_aw_qos_i (slv.aw_qos), + .slv_aw_id_i (slv.aw_id), + .slv_aw_user_i (slv.aw_user), + .slv_aw_valid_i (slv.aw_valid), + .slv_aw_ready_o (slv.aw_ready), + .slv_aw_writetoken_i (), + .slv_aw_readpointer_o (), + .slv_ar_addr_i (slv.ar_addr), + .slv_ar_prot_i (slv.ar_prot), + .slv_ar_region_i (slv.ar_region), + .slv_ar_len_i (slv.ar_len), + .slv_ar_size_i (slv.ar_size), + .slv_ar_burst_i (slv.ar_burst), + .slv_ar_lock_i (slv.ar_lock), + .slv_ar_cache_i (slv.ar_cache), + .slv_ar_qos_i (slv.ar_qos), + .slv_ar_id_i (slv.ar_id), + .slv_ar_user_i (slv.ar_user), + .slv_ar_valid_i (slv.ar_valid), + .slv_ar_ready_o (slv.ar_ready), + .slv_ar_writetoken_i (), + .slv_ar_readpointer_o (), + .slv_w_data_i (slv.w_data), + .slv_w_strb_i (slv.w_strb), + .slv_w_user_i (slv.w_user), + .slv_w_last_i (slv.w_last), + .slv_w_valid_i (slv.w_valid), + .slv_w_ready_o (slv.w_ready), + .slv_w_writetoken_i (), + .slv_w_readpointer_o (), + .slv_r_data_o (slv.r_data), + .slv_r_resp_o (slv.r_resp), + .slv_r_last_o (slv.r_last), + .slv_r_id_o (slv.r_id), + .slv_r_user_o (slv.r_user), + .slv_r_valid_o (slv.r_valid), + .slv_r_ready_i (slv.r_ready), + .slv_r_writetoken_o (), + .slv_r_readpointer_i (), + .slv_b_resp_o (slv.b_resp), + .slv_b_id_o (slv.b_id), + .slv_b_user_o (slv.b_user), + .slv_b_valid_o (slv.b_valid), + .slv_b_ready_i (slv.b_ready), + .slv_b_writetoken_o (), + .slv_b_readpointer_i (), + + .mst_aw_addr_o (mst.aw_addr), + .mst_aw_prot_o (mst.aw_prot), + .mst_aw_region_o (mst.aw_region), + .mst_aw_len_o (mst.aw_len), + .mst_aw_size_o (mst.aw_size), + .mst_aw_burst_o (mst.aw_burst), + .mst_aw_lock_o (mst.aw_lock), + .mst_aw_atop_o (mst.aw_atop), + .mst_aw_cache_o (mst.aw_cache), + .mst_aw_qos_o (mst.aw_qos), + .mst_aw_id_o (mst.aw_id), + .mst_aw_user_o (mst.aw_user), + .mst_aw_valid_o (mst.aw_valid), + .mst_aw_ready_i (mst.aw_ready), + .mst_aw_writetoken_o (), + .mst_aw_readpointer_i (), + .mst_ar_addr_o (mst.ar_addr), + .mst_ar_prot_o (mst.ar_prot), + .mst_ar_region_o (mst.ar_region), + .mst_ar_len_o (mst.ar_len), + .mst_ar_size_o (mst.ar_size), + .mst_ar_burst_o (mst.ar_burst), + .mst_ar_lock_o (mst.ar_lock), + .mst_ar_cache_o (mst.ar_cache), + .mst_ar_qos_o (mst.ar_qos), + .mst_ar_id_o (mst.ar_id), + .mst_ar_user_o (mst.ar_user), + .mst_ar_valid_o (mst.ar_valid), + .mst_ar_ready_i (mst.ar_ready), + .mst_ar_writetoken_o (), + .mst_ar_readpointer_i (), + .mst_w_data_o (mst.w_data), + .mst_w_strb_o (mst.w_strb), + .mst_w_user_o (mst.w_user), + .mst_w_last_o (mst.w_last), + .mst_w_valid_o (mst.w_valid), + .mst_w_ready_i (mst.w_ready), + .mst_w_writetoken_o (), + .mst_w_readpointer_i (), + .mst_r_data_i (mst.r_data), + .mst_r_resp_i (mst.r_resp), + .mst_r_last_i (mst.r_last), + .mst_r_id_i (mst.r_id), + .mst_r_user_i (mst.r_user), + .mst_r_valid_i (mst.r_valid), + .mst_r_ready_o (mst.r_ready), + .mst_r_writetoken_i (), + .mst_r_readpointer_o (), + .mst_b_resp_i (mst.b_resp), + .mst_b_id_i (mst.b_id), + .mst_b_user_i (mst.b_user), + .mst_b_valid_i (mst.b_valid), + .mst_b_ready_o (mst.b_ready), + .mst_b_writetoken_i (), + .mst_b_readpointer_o (), + + .dma_aw_addr_o (dma.aw_addr), + .dma_aw_prot_o (dma.aw_prot), + .dma_aw_region_o (dma.aw_region), + .dma_aw_len_o (dma.aw_len), + .dma_aw_size_o (dma.aw_size), + .dma_aw_burst_o (dma.aw_burst), + .dma_aw_lock_o (dma.aw_lock), + .dma_aw_atop_o (dma.aw_atop), + .dma_aw_cache_o (dma.aw_cache), + .dma_aw_qos_o (dma.aw_qos), + .dma_aw_id_o (dma.aw_id), + .dma_aw_user_o (dma.aw_user), + .dma_aw_valid_o (dma.aw_valid), + .dma_aw_ready_i (dma.aw_ready), + .dma_ar_addr_o (dma.ar_addr), + .dma_ar_prot_o (dma.ar_prot), + .dma_ar_region_o (dma.ar_region), + .dma_ar_len_o (dma.ar_len), + .dma_ar_size_o (dma.ar_size), + .dma_ar_burst_o (dma.ar_burst), + .dma_ar_lock_o (dma.ar_lock), + .dma_ar_cache_o (dma.ar_cache), + .dma_ar_qos_o (dma.ar_qos), + .dma_ar_id_o (dma.ar_id), + .dma_ar_user_o (dma.ar_user), + .dma_ar_valid_o (dma.ar_valid), + .dma_ar_ready_i (dma.ar_ready), + .dma_w_data_o (dma.w_data), + .dma_w_strb_o (dma.w_strb), + .dma_w_user_o (dma.w_user), + .dma_w_last_o (dma.w_last), + .dma_w_valid_o (dma.w_valid), + .dma_w_ready_i (dma.w_ready), + .dma_r_data_i (dma.r_data), + .dma_r_resp_i (dma.r_resp), + .dma_r_last_i (dma.r_last), + .dma_r_id_i (dma.r_id), + .dma_r_user_i (dma.r_user), + .dma_r_valid_i (dma.r_valid), + .dma_r_ready_o (dma.r_ready), + .dma_b_resp_i (dma.b_resp), + .dma_b_id_i (dma.b_id), + .dma_b_user_i (dma.b_user), + .dma_b_valid_i (dma.b_valid), + .dma_b_ready_o (dma.b_ready), + + .nhi_aw_addr_i (nhi.aw_addr), + .nhi_aw_prot_i (nhi.aw_prot), + .nhi_aw_region_i (nhi.aw_region), + .nhi_aw_len_i (nhi.aw_len), + .nhi_aw_size_i (nhi.aw_size), + .nhi_aw_burst_i (nhi.aw_burst), + .nhi_aw_lock_i (nhi.aw_lock), + .nhi_aw_atop_i (nhi.aw_atop), + .nhi_aw_cache_i (nhi.aw_cache), + .nhi_aw_qos_i (nhi.aw_qos), + .nhi_aw_id_i (nhi.aw_id), + .nhi_aw_user_i (nhi.aw_user), + .nhi_aw_valid_i (nhi.aw_valid), + .nhi_aw_ready_o (nhi.aw_ready), + .nhi_ar_addr_i (nhi.ar_addr), + .nhi_ar_prot_i (nhi.ar_prot), + .nhi_ar_region_i (nhi.ar_region), + .nhi_ar_len_i (nhi.ar_len), + .nhi_ar_size_i (nhi.ar_size), + .nhi_ar_burst_i (nhi.ar_burst), + .nhi_ar_lock_i (nhi.ar_lock), + .nhi_ar_cache_i (nhi.ar_cache), + .nhi_ar_qos_i (nhi.ar_qos), + .nhi_ar_id_i (nhi.ar_id), + .nhi_ar_user_i (nhi.ar_user), + .nhi_ar_valid_i (nhi.ar_valid), + .nhi_ar_ready_o (nhi.ar_ready), + .nhi_w_data_i (nhi.w_data), + .nhi_w_strb_i (nhi.w_strb), + .nhi_w_user_i (nhi.w_user), + .nhi_w_last_i (nhi.w_last), + .nhi_w_valid_i (nhi.w_valid), + .nhi_w_ready_o (nhi.w_ready), + .nhi_r_data_o (nhi.r_data), + .nhi_r_resp_o (nhi.r_resp), + .nhi_r_last_o (nhi.r_last), + .nhi_r_id_o (nhi.r_id), + .nhi_r_user_o (nhi.r_user), + .nhi_r_valid_o (nhi.r_valid), + .nhi_r_ready_i (nhi.r_ready), + .nhi_b_resp_o (nhi.b_resp), + .nhi_b_id_o (nhi.b_id), + .nhi_b_user_o (nhi.b_user), + .nhi_b_valid_o (nhi.b_valid), + .nhi_b_ready_i (nhi.b_ready), + + .icache_aw_addr_o (icache.aw_addr), + .icache_aw_prot_o (icache.aw_prot), + .icache_aw_region_o (icache.aw_region), + .icache_aw_len_o (icache.aw_len), + .icache_aw_size_o (icache.aw_size), + .icache_aw_burst_o (icache.aw_burst), + .icache_aw_lock_o (icache.aw_lock), + .icache_aw_atop_o (icache.aw_atop), + .icache_aw_cache_o (icache.aw_cache), + .icache_aw_qos_o (icache.aw_qos), + .icache_aw_id_o (icache.aw_id), + .icache_aw_user_o (icache.aw_user), + .icache_aw_valid_o (icache.aw_valid), + .icache_aw_ready_i (icache.aw_ready), + .icache_ar_addr_o (icache.ar_addr), + .icache_ar_prot_o (icache.ar_prot), + .icache_ar_region_o (icache.ar_region), + .icache_ar_len_o (icache.ar_len), + .icache_ar_size_o (icache.ar_size), + .icache_ar_burst_o (icache.ar_burst), + .icache_ar_lock_o (icache.ar_lock), + .icache_ar_cache_o (icache.ar_cache), + .icache_ar_qos_o (icache.ar_qos), + .icache_ar_id_o (icache.ar_id), + .icache_ar_user_o (icache.ar_user), + .icache_ar_valid_o (icache.ar_valid), + .icache_ar_ready_i (icache.ar_ready), + .icache_w_data_o (icache.w_data), + .icache_w_strb_o (icache.w_strb), + .icache_w_user_o (icache.w_user), + .icache_w_last_o (icache.w_last), + .icache_w_valid_o (icache.w_valid), + .icache_w_ready_i (icache.w_ready), + .icache_r_data_i (icache.r_data), + .icache_r_resp_i (icache.r_resp), + .icache_r_last_i (icache.r_last), + .icache_r_id_i (icache.r_id), + .icache_r_user_i (icache.r_user), + .icache_r_valid_i (icache.r_valid), + .icache_r_ready_o (icache.r_ready), + .icache_b_resp_i (icache.b_resp), + .icache_b_id_i (icache.b_id), + .icache_b_user_i (icache.b_user), + .icache_b_valid_i (icache.b_valid), + .icache_b_ready_o (icache.b_ready), + + .task_valid_i (task_valid_i), + .task_ready_o (task_ready_o), + .task_descr_i (task_descr_i), + .feedback_valid_o (feedback_valid_o), + .feedback_ready_i (feedback_ready_i), + .feedback_o (feedback_o), + .cluster_active_o (cluster_active_o), + .cmd_ready_i (cmd_ready_i), + .cmd_valid_o (cmd_valid_o), + .cmd_o (cmd_o), + .cmd_resp_valid_i (cmd_resp_valid_i), + .cmd_resp_i (cmd_resp_i) + ); +endmodule + +// Interface wrapper for OOC-synthesized asynchronous PULP cluster +module pulp_cluster_async ( + input logic clk_i, + input logic rst_ni, + input logic ref_clk_i, + input cluster_id_t cluster_id_i, + input logic fetch_en_i, + output logic eoc_o, + output logic busy_o, + AXI_BUS_ASYNC.Slave slv, + AXI_BUS_ASYNC.Master mst, + AXI_BUS_ASYNC.Master dma, + AXI_BUS_ASYNC.Master icache +); + + pulp_cluster_ooc i_ooc ( + .clk_i, + .rst_ni, + .ref_clk_i, + .cluster_id_i, + .fetch_en_i, + .eoc_o, + .busy_o, + + .slv_aw_addr_i (slv.aw_addr), + .slv_aw_prot_i (slv.aw_prot), + .slv_aw_region_i (slv.aw_region), + .slv_aw_len_i (slv.aw_len), + .slv_aw_size_i (slv.aw_size), + .slv_aw_burst_i (slv.aw_burst), + .slv_aw_lock_i (slv.aw_lock), + .slv_aw_atop_i (slv.aw_atop), + .slv_aw_cache_i (slv.aw_cache), + .slv_aw_qos_i (slv.aw_qos), + .slv_aw_id_i (slv.aw_id), + .slv_aw_user_i (slv.aw_user), + .slv_aw_valid_i (), + .slv_aw_ready_o (), + .slv_aw_writetoken_i (slv.aw_writetoken), + .slv_aw_readpointer_o (slv.aw_readpointer), + .slv_ar_addr_i (slv.ar_addr), + .slv_ar_prot_i (slv.ar_prot), + .slv_ar_region_i (slv.ar_region), + .slv_ar_len_i (slv.ar_len), + .slv_ar_size_i (slv.ar_size), + .slv_ar_burst_i (slv.ar_burst), + .slv_ar_lock_i (slv.ar_lock), + .slv_ar_cache_i (slv.ar_cache), + .slv_ar_qos_i (slv.ar_qos), + .slv_ar_id_i (slv.ar_id), + .slv_ar_user_i (slv.ar_user), + .slv_ar_valid_i (), + .slv_ar_ready_o (), + .slv_ar_writetoken_i (slv.ar_writetoken), + .slv_ar_readpointer_o (slv.ar_readpointer), + .slv_w_data_i (slv.w_data), + .slv_w_strb_i (slv.w_strb), + .slv_w_user_i (slv.w_user), + .slv_w_last_i (slv.w_last), + .slv_w_valid_i (), + .slv_w_ready_o (), + .slv_w_writetoken_i (slv.w_writetoken), + .slv_w_readpointer_o (slv.w_readpointer), + .slv_r_data_o (slv.r_data), + .slv_r_resp_o (slv.r_resp), + .slv_r_last_o (slv.r_last), + .slv_r_id_o (slv.r_id), + .slv_r_user_o (slv.r_user), + .slv_r_valid_o (), + .slv_r_ready_i (), + .slv_r_writetoken_o (slv.r_writetoken), + .slv_r_readpointer_i (slv.r_readpointer), + .slv_b_resp_o (slv.b_resp), + .slv_b_id_o (slv.b_id), + .slv_b_user_o (slv.b_user), + .slv_b_valid_o (), + .slv_b_ready_i (), + .slv_b_writetoken_o (slv.b_writetoken), + .slv_b_readpointer_i (slv.b_readpointer), + + .mst_aw_addr_o (mst.aw_addr), + .mst_aw_prot_o (mst.aw_prot), + .mst_aw_region_o (mst.aw_region), + .mst_aw_len_o (mst.aw_len), + .mst_aw_size_o (mst.aw_size), + .mst_aw_burst_o (mst.aw_burst), + .mst_aw_lock_o (mst.aw_lock), + .mst_aw_atop_o (mst.aw_atop), + .mst_aw_cache_o (mst.aw_cache), + .mst_aw_qos_o (mst.aw_qos), + .mst_aw_id_o (mst.aw_id), + .mst_aw_user_o (mst.aw_user), + .mst_aw_valid_o (), + .mst_aw_ready_i (), + .mst_aw_writetoken_o (mst.aw_writetoken), + .mst_aw_readpointer_i (mst.aw_readpointer), + .mst_ar_addr_o (mst.ar_addr), + .mst_ar_prot_o (mst.ar_prot), + .mst_ar_region_o (mst.ar_region), + .mst_ar_len_o (mst.ar_len), + .mst_ar_size_o (mst.ar_size), + .mst_ar_burst_o (mst.ar_burst), + .mst_ar_lock_o (mst.ar_lock), + .mst_ar_cache_o (mst.ar_cache), + .mst_ar_qos_o (mst.ar_qos), + .mst_ar_id_o (mst.ar_id), + .mst_ar_user_o (mst.ar_user), + .mst_ar_valid_o (), + .mst_ar_ready_i (), + .mst_ar_writetoken_o (mst.ar_writetoken), + .mst_ar_readpointer_i (mst.ar_readpointer), + .mst_w_data_o (mst.w_data), + .mst_w_strb_o (mst.w_strb), + .mst_w_user_o (mst.w_user), + .mst_w_last_o (mst.w_last), + .mst_w_valid_o (), + .mst_w_ready_i (), + .mst_w_writetoken_o (mst.w_writetoken), + .mst_w_readpointer_i (mst.w_readpointer), + .mst_r_data_i (mst.r_data), + .mst_r_resp_i (mst.r_resp), + .mst_r_last_i (mst.r_last), + .mst_r_id_i (mst.r_id), + .mst_r_user_i (mst.r_user), + .mst_r_valid_i (), + .mst_r_ready_o (), + .mst_r_writetoken_i (mst.r_writetoken), + .mst_r_readpointer_o (mst.r_readpointer), + .mst_b_resp_i (mst.b_resp), + .mst_b_id_i (mst.b_id), + .mst_b_user_i (mst.b_user), + .mst_b_valid_i (), + .mst_b_ready_o (), + .mst_b_writetoken_i (mst.b_writetoken), + .mst_b_readpointer_o (mst.b_readpointer), + + .dma_aw_addr_o (dma.aw_addr), + .dma_aw_prot_o (dma.aw_prot), + .dma_aw_region_o (dma.aw_region), + .dma_aw_len_o (dma.aw_len), + .dma_aw_size_o (dma.aw_size), + .dma_aw_burst_o (dma.aw_burst), + .dma_aw_lock_o (dma.aw_lock), + .dma_aw_atop_o (dma.aw_atop), + .dma_aw_cache_o (dma.aw_cache), + .dma_aw_qos_o (dma.aw_qos), + .dma_aw_id_o (dma.aw_id), + .dma_aw_user_o (dma.aw_user), + .dma_aw_valid_o (), + .dma_aw_ready_i (), + .dma_ar_addr_o (dma.ar_addr), + .dma_ar_prot_o (dma.ar_prot), + .dma_ar_region_o (dma.ar_region), + .dma_ar_len_o (dma.ar_len), + .dma_ar_size_o (dma.ar_size), + .dma_ar_burst_o (dma.ar_burst), + .dma_ar_lock_o (dma.ar_lock), + .dma_ar_cache_o (dma.ar_cache), + .dma_ar_qos_o (dma.ar_qos), + .dma_ar_id_o (dma.ar_id), + .dma_ar_user_o (dma.ar_user), + .dma_ar_valid_o (), + .dma_ar_ready_i (), + .dma_w_data_o (dma.w_data), + .dma_w_strb_o (dma.w_strb), + .dma_w_user_o (dma.w_user), + .dma_w_last_o (dma.w_last), + .dma_w_valid_o (), + .dma_w_ready_i (), + .dma_r_data_i (dma.r_data), + .dma_r_resp_i (dma.r_resp), + .dma_r_last_i (dma.r_last), + .dma_r_id_i (dma.r_id), + .dma_r_user_i (dma.r_user), + .dma_r_valid_i (), + .dma_r_ready_o (), + .dma_b_resp_i (dma.b_resp), + .dma_b_id_i (dma.b_id), + .dma_b_user_i (dma.b_user), + .dma_b_valid_i (), + .dma_b_ready_o (), + + .icache_aw_addr_o (icache.aw_addr), + .icache_aw_prot_o (icache.aw_prot), + .icache_aw_region_o (icache.aw_region), + .icache_aw_len_o (icache.aw_len), + .icache_aw_size_o (icache.aw_size), + .icache_aw_burst_o (icache.aw_burst), + .icache_aw_lock_o (icache.aw_lock), + .icache_aw_atop_o (icache.aw_atop), + .icache_aw_cache_o (icache.aw_cache), + .icache_aw_qos_o (icache.aw_qos), + .icache_aw_id_o (icache.aw_id), + .icache_aw_user_o (icache.aw_user), + .icache_aw_valid_o (), + .icache_aw_ready_i (), + .icache_ar_addr_o (icache.ar_addr), + .icache_ar_prot_o (icache.ar_prot), + .icache_ar_region_o (icache.ar_region), + .icache_ar_len_o (icache.ar_len), + .icache_ar_size_o (icache.ar_size), + .icache_ar_burst_o (icache.ar_burst), + .icache_ar_lock_o (icache.ar_lock), + .icache_ar_cache_o (icache.ar_cache), + .icache_ar_qos_o (icache.ar_qos), + .icache_ar_id_o (icache.ar_id), + .icache_ar_user_o (icache.ar_user), + .icache_ar_valid_o (), + .icache_ar_ready_i (), + .icache_w_data_o (icache.w_data), + .icache_w_strb_o (icache.w_strb), + .icache_w_user_o (icache.w_user), + .icache_w_last_o (icache.w_last), + .icache_w_valid_o (), + .icache_w_ready_i (), + .icache_r_data_i (icache.r_data), + .icache_r_resp_i (icache.r_resp), + .icache_r_last_i (icache.r_last), + .icache_r_id_i (icache.r_id), + .icache_r_user_i (icache.r_user), + .icache_r_valid_i (), + .icache_r_ready_o (), + .icache_b_resp_i (icache.b_resp), + .icache_b_id_i (icache.b_id), + .icache_b_user_i (icache.b_user), + .icache_b_valid_i (), + .icache_b_ready_o () + ); +endmodule diff --git a/hw/src/soc_ctrl_regs.sv b/hw/src/soc_ctrl_regs.sv new file mode 100644 index 0000000..508cfa0 --- /dev/null +++ b/hw/src/soc_ctrl_regs.sv @@ -0,0 +1,92 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +module soc_ctrl_regs #( + parameter int unsigned N_CORES = 0, + parameter int unsigned N_CLUSTERS = 0, + parameter int unsigned ADDR_WIDTH = 0, + parameter int unsigned DATA_WIDTH = 0 +) ( + input logic clk_i, + input logic rst_ni, + APB_BUS.Slave apb +); + + localparam int unsigned N_SLV = 5; + + APB_BUS #( + .APB_ADDR_WIDTH (ADDR_WIDTH), + .APB_DATA_WIDTH (DATA_WIDTH) + ) apb_bus[N_SLV-1:0] (); + + apb_bus_wrap #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_SLV (N_SLV), + .ADDR_BEGIN ({32'h0000_0090, 32'h0000_0080, 32'h0000_0014, 32'h0000_0010, 32'h0000_0000}), + .ADDR_END ({32'h0000_0FFF, 32'h0000_008F, 32'h0000_007F, 32'h0000_0013, 32'h0000_000F}) + ) i_apb_bus ( + .inp (apb), + .oup (apb_bus) + ); + + apb_ro_regs #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_REGS (4) + ) i_zero_0 ( + .apb (apb_bus[0]), + .reg_i ('0) + ); + + logic [DATA_WIDTH-1:0] info_reg; + assign info_reg = {N_CORES, N_CLUSTERS}; + apb_ro_regs #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_REGS (1) + ) i_info ( + .apb (apb_bus[1]), + .reg_i (info_reg) + ); + + apb_ro_regs #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_REGS (27) + ) i_zero_1 ( + .apb (apb_bus[2]), + .reg_i ('0) + ); + + apb_rw_regs #( + .DATA_WIDTH (DATA_WIDTH), + .ADDR_WIDTH (ADDR_WIDTH), + .N_REGS (4) // TODO: Why 4 and not the actual number of cores? Are these regs even needed? + ) i_core_res ( + .clk_i, + .rst_ni, + .apb (apb_bus[3]), + .init_i ('0), + .q_o () + ); + + apb_ro_regs #( + .ADDR_WIDTH (ADDR_WIDTH), + .DATA_WIDTH (DATA_WIDTH), + .N_REGS (988) + ) i_zero_2 ( + .apb (apb_bus[4]), + /* verilator lint_off WIDTHCONCAT */ + .reg_i ('0) + /* verilator lint_on WIDTHCONCAT */ + ); + +endmodule diff --git a/hw/src/soc_dma_wrap.sv b/hw/src/soc_dma_wrap.sv new file mode 100644 index 0000000..a6d03a7 --- /dev/null +++ b/hw/src/soc_dma_wrap.sv @@ -0,0 +1,336 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +import pspin_cfg_pkg::*; + +module soc_dma_wrap #( + /// id width of the DMA AXI Master port + parameter int unsigned DmaAxiIdWidth = -1, + /// data width of the DMA AXI Master port + parameter int unsigned DmaDataWidth = -1, + /// user width + parameter int unsigned DmaUserWidth = -1, + /// number of AX requests in-flight + parameter int unsigned AxiAxReqDepth = -1, + /// number of 1D transfers buffered in backend + parameter int unsigned TfReqFifoDepth = -1, + /// NHI data request type + parameter type axi_nhi_req_t = logic, + /// NHI data response type + parameter type axi_nhi_res_t = logic, + /// host data request type (64 bit) + parameter type axi_host_req_t = logic, + /// host data response type (64 bit) + parameter type axi_host_res_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + //command + input logic cmd_req_valid_i, + output logic cmd_req_ready_o, + input pspin_cmd_t cmd_req_i, + + //response + output logic cmd_resp_valid_o, + output pspin_cmd_resp_t cmd_resp_o, + + /// to NHI (32 bit address) + output axi_nhi_req_t nhi_req_o, + input axi_nhi_res_t nhi_resp_i, + + /// to host (64 bit address) + output axi_host_req_t host_req_o, + input axi_host_res_t host_resp_i +); + + localparam logic[64:0] PCIeStartAddr = 65'h1_0000_0000_0000_0000; + localparam logic[64:0] PCIeEndAddr = 65'h1_FFFF_FFFF_FFFF_FFFF; + localparam logic[64:0] NHIStartAddr = 65'h0_0000_0000_0000_0000; + localparam logic[64:0] NHIEndAddr = 65'h0_0000_0000_FFFF_FFFF; + + localparam int unsigned IDX_PCIE = 0; + localparam int unsigned IDX_NHI = 1; + localparam int unsigned RespFIFODepth = TfReqFifoDepth + AxiAxReqDepth; + + localparam int unsigned DmaAddrWidth = 65; //64th bit used to distinguish host/NIC addresses + + logic [$clog2(RespFIFODepth):0] to_pop_rx_d; + logic [$clog2(RespFIFODepth):0] to_pop_rx_q; + + logic [$clog2(RespFIFODepth):0] to_pop_tx_d; + logic [$clog2(RespFIFODepth):0] to_pop_tx_q; + + logic tx_req_valid, rx_req_valid; + logic tx_req_ready, rx_req_ready; + logic tx_resp_valid, rx_resp_valid; + + transf_descr_soc_t xfer_descr; + pspin_cmd_resp_t cmd_resp; + + pspin_cmd_resp_t cmd_rx_resp, cmd_tx_resp; + + logic fifo_rx_full, fifo_tx_full; + logic fifo_rx_sel, fifo_tx_sel; + + logic fifo_rx_pop, fifo_tx_pop; + + logic fifo_rx_resp_avail, fifo_tx_resp_avail; + + assign xfer_descr.num_bytes = cmd_req_i.descr.host_dma_cmd.length; + + assign xfer_descr.dst_addr[64] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? 1'b1 : 1'b0; + assign xfer_descr.dst_addr[63:32] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? cmd_req_i.descr.host_dma_cmd.host_addr[63:32] : '0; + assign xfer_descr.dst_addr[31:0] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? cmd_req_i.descr.host_dma_cmd.host_addr[31:0] : cmd_req_i.descr.host_dma_cmd.nic_addr; + + assign xfer_descr.src_addr[64] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? 1'b0 : 1'b1; + assign xfer_descr.src_addr[63:32] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? '0 : cmd_req_i.descr.host_dma_cmd.host_addr[63:32]; + assign xfer_descr.src_addr[31:0] = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? cmd_req_i.descr.host_dma_cmd.nic_addr : cmd_req_i.descr.host_dma_cmd.host_addr[31:0]; + assign xfer_descr.deburst = 1'b0; + assign xfer_descr.decouple = 1'b1; + assign xfer_descr.serialize = 1'b0; // TODO: connect me! + + assign cmd_resp.cmd_id = cmd_req_i.cmd_id; + + always_comb begin + cmd_req_ready_o = 1'b0; + rx_req_valid = 1'b0; + tx_req_valid = 1'b0; + + if (cmd_req_valid_i) begin + cmd_req_ready_o = (cmd_req_i.descr.host_dma_cmd.nic_to_host) ? (!fifo_rx_full && rx_req_ready) : (!fifo_tx_full && tx_req_ready); + rx_req_valid = cmd_req_i.descr.host_dma_cmd.nic_to_host == 1'b1; + tx_req_valid = cmd_req_i.descr.host_dma_cmd.nic_to_host == 1'b0; + end + end + + //FIFO with RX responses + assign fifo_rx_resp_avail = to_pop_rx_q > 0; + assign fifo_rx_pop = fifo_rx_resp_avail && fifo_rx_sel; + + fifo_v3 #( + .dtype (pspin_cmd_resp_t), + .DEPTH (RespFIFODepth) + ) i_rx_resp_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i(1'b0), + .full_o (fifo_rx_full), + .empty_o (), + .usage_o (), + .data_i (cmd_resp), + .push_i (cmd_req_ready_o && rx_req_valid), + .data_o (cmd_rx_resp), + .pop_i (fifo_rx_pop) + ); + + always_comb begin + case ({rx_resp_valid, fifo_rx_pop}) + 2'b10 : to_pop_rx_d = to_pop_rx_q + 1; + 2'b01 : to_pop_rx_d = to_pop_rx_q - 1; + default : to_pop_rx_d = to_pop_rx_q; + endcase + end + + //FIFO with TX responses + assign fifo_tx_resp_avail = to_pop_tx_q > 0; + assign fifo_tx_pop = fifo_tx_resp_avail && fifo_tx_sel; + + fifo_v3 #( + .dtype (pspin_cmd_resp_t), + .DEPTH (RespFIFODepth) + ) i_tx_resp_fifo ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .testmode_i(1'b0), + .full_o (fifo_tx_full), + .empty_o (), + .usage_o (), + .data_i (cmd_resp), + .push_i (cmd_req_ready_o && tx_req_valid), + .data_o (cmd_tx_resp), + .pop_i (fifo_tx_pop) + ); + + always_comb begin + case ({tx_resp_valid, fifo_tx_pop}) + 2'b10 : to_pop_tx_d = to_pop_tx_q + 1; + 2'b01 : to_pop_tx_d = to_pop_tx_q - 1; + default : to_pop_tx_d = to_pop_tx_q; + endcase + end + + // arbitrate response from the two ports + rr_arb_tree #( + .NumIn (2), + .DataType (pspin_cmd_resp_t), + .ExtPrio (0), + .AxiVldRdy (1), + .LockIn (1) + ) i_resp_arb ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (1'b0), + .rr_i ('0), + .req_i ({fifo_tx_resp_avail, fifo_rx_resp_avail}), + .gnt_o ({fifo_tx_sel, fifo_rx_sel}), + .data_i ({cmd_tx_resp, cmd_rx_resp}), + .gnt_i (1'b1), + .req_o (cmd_resp_valid_o), + .data_o (cmd_resp_o), + .idx_o () + ); + + typedef logic [DmaDataWidth-1 :0] data_t; + typedef logic [DmaAxiIdWidth-1 :0] id_t; + typedef logic [DmaDataWidth/8-1 :0] strb_t; + typedef logic [DmaUserWidth-1 :0] user_t; + typedef logic [DmaAddrWidth-1 :0] wide_addr_t; + + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, wide_addr_t, id_t, user_t); + `AXI_TYPEDEF_W_CHAN_T (w_chan_t, data_t, strb_t, user_t); + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, wide_addr_t, id_t, user_t); + `AXI_TYPEDEF_B_CHAN_T (b_chan_t, id_t, user_t); + `AXI_TYPEDEF_R_CHAN_T (r_chan_t, data_t, id_t, user_t); + `AXI_TYPEDEF_REQ_T (axi_dma_wide_req_t, aw_chan_t, w_chan_t, ar_chan_t); + `AXI_TYPEDEF_RESP_T (axi_dma_wide_resp_t, b_chan_t, r_chan_t); + + axi_dma_wide_req_t nhi_wide_req; + axi_dma_wide_req_t host_wide_req; + + //cut NHI address to 32 bit (lower) + assign nhi_req_o.aw.id = nhi_wide_req.aw.id; + assign nhi_req_o.aw.addr = nhi_wide_req.aw.addr[31:0]; + assign nhi_req_o.aw.len = nhi_wide_req.aw.len; + assign nhi_req_o.aw.size = nhi_wide_req.aw.size; + assign nhi_req_o.aw.burst = nhi_wide_req.aw.burst; + assign nhi_req_o.aw.lock = nhi_wide_req.aw.lock; + assign nhi_req_o.aw.cache = nhi_wide_req.aw.cache; + assign nhi_req_o.aw.prot = nhi_wide_req.aw.prot; + assign nhi_req_o.aw.qos = nhi_wide_req.aw.qos; + assign nhi_req_o.aw.region = nhi_wide_req.aw.region; + assign nhi_req_o.aw.atop = nhi_wide_req.aw.atop; + assign nhi_req_o.aw.user = nhi_wide_req.aw.user; + assign nhi_req_o.aw_valid = nhi_wide_req.aw_valid; + + assign nhi_req_o.w.data = nhi_wide_req.w.data; + assign nhi_req_o.w.strb = nhi_wide_req.w.strb; + assign nhi_req_o.w.last = nhi_wide_req.w.last; + assign nhi_req_o.w.user = nhi_wide_req.w.user; + assign nhi_req_o.w_valid = nhi_wide_req.w_valid; + + assign nhi_req_o.ar.id = nhi_wide_req.ar.id; + assign nhi_req_o.ar.addr = nhi_wide_req.ar.addr[31:0]; + assign nhi_req_o.ar.len = nhi_wide_req.ar.len; + assign nhi_req_o.ar.size = nhi_wide_req.ar.size; + assign nhi_req_o.ar.burst = nhi_wide_req.ar.burst; + assign nhi_req_o.ar.lock = nhi_wide_req.ar.lock; + assign nhi_req_o.ar.cache = nhi_wide_req.ar.cache; + assign nhi_req_o.ar.prot = nhi_wide_req.ar.prot; + assign nhi_req_o.ar.qos = nhi_wide_req.ar.qos; + assign nhi_req_o.ar.region = nhi_wide_req.ar.region; + assign nhi_req_o.ar.user = nhi_wide_req.ar.user; + assign nhi_req_o.ar_valid = nhi_wide_req.ar_valid; + + assign nhi_req_o.r_ready = nhi_wide_req.r_ready; + assign nhi_req_o.b_ready = nhi_wide_req.b_ready; + + //cut host address to 64 bit (lower) + assign host_req_o.aw.id = host_wide_req.aw.id; + assign host_req_o.aw.addr = host_wide_req.aw.addr[63:0]; + assign host_req_o.aw.len = host_wide_req.aw.len; + assign host_req_o.aw.size = host_wide_req.aw.size; + assign host_req_o.aw.burst = host_wide_req.aw.burst; + assign host_req_o.aw.lock = host_wide_req.aw.lock; + assign host_req_o.aw.cache = host_wide_req.aw.cache; + assign host_req_o.aw.prot = host_wide_req.aw.prot; + assign host_req_o.aw.qos = host_wide_req.aw.qos; + assign host_req_o.aw.region = host_wide_req.aw.region; + assign host_req_o.aw.atop = host_wide_req.aw.atop; + assign host_req_o.aw.user = host_wide_req.aw.user; + assign host_req_o.aw_valid = host_wide_req.aw_valid; + + assign host_req_o.w.data = host_wide_req.w.data; + assign host_req_o.w.strb = host_wide_req.w.strb; + assign host_req_o.w.last = host_wide_req.w.last; + assign host_req_o.w.user = host_wide_req.w.user; + assign host_req_o.w_valid = host_wide_req.w_valid; + + assign host_req_o.ar.id = host_wide_req.ar.id; + assign host_req_o.ar.addr = host_wide_req.ar.addr[63:0]; + assign host_req_o.ar.len = host_wide_req.ar.len; + assign host_req_o.ar.size = host_wide_req.ar.size; + assign host_req_o.ar.burst = host_wide_req.ar.burst; + assign host_req_o.ar.lock = host_wide_req.ar.lock; + assign host_req_o.ar.cache = host_wide_req.ar.cache; + assign host_req_o.ar.prot = host_wide_req.ar.prot; + assign host_req_o.ar.qos = host_wide_req.ar.qos; + assign host_req_o.ar.region = host_wide_req.ar.region; + assign host_req_o.ar.user = host_wide_req.ar.user; + assign host_req_o.ar_valid = host_wide_req.ar_valid; + + assign host_req_o.r_ready = host_wide_req.r_ready; + assign host_req_o.b_ready = host_wide_req.b_ready; + + //DMA engine + pspin_soc_dma #( + .DmaAxiIdWidth (DmaAxiIdWidth), + .DmaDataWidth (DmaDataWidth), + .DmaAddrWidth (DmaAddrWidth), + .DmaUserWidth (DmaUserWidth), + .AxiAxReqDepth (AxiAxReqDepth), + .TfReqFifoDepth (TfReqFifoDepth), + .axi_req_t (axi_dma_wide_req_t), + .axi_res_t (axi_dma_wide_resp_t), + .transf_descr_t (pspin_cfg_pkg::transf_descr_soc_t), + .PCIeStartAddr (PCIeStartAddr), + .PCIeEndAddr (PCIeEndAddr), + .NHIStartAddr (NHIStartAddr), + .NHIEndAddr (NHIEndAddr) + ) i_soc_dma ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + //direct hw port 1 + .rx_req_valid_i (rx_req_valid ), + .rx_req_ready_o (rx_req_ready ), + .rx_req_i (xfer_descr ), + .rx_rsp_valid_o (rx_resp_valid ), + //direct hw port 2 + .tx_req_valid_i (tx_req_valid ), + .tx_req_ready_o (tx_req_ready ), + .tx_req_i (xfer_descr ), + .tx_rsp_valid_o (tx_resp_valid ), + //AXI wide port 1 (to NHI) + .nhi_dma_req_o (nhi_wide_req ), + .nhi_dma_res_i (nhi_resp_i ), + //AXI wide port 2 (to HOST) + .pcie_dma_req_o (host_wide_req ), + .pcie_dma_res_i (host_resp_i ), + //status + .idle_o ( ) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + to_pop_tx_q <= '0; + to_pop_rx_q <= '0; + end else begin + to_pop_tx_q <= to_pop_tx_d; + to_pop_rx_q <= to_pop_rx_d; + end + end + +endmodule \ No newline at end of file diff --git a/hw/src/soc_peripherals.sv b/hw/src/soc_peripherals.sv new file mode 100644 index 0000000..2ac46a8 --- /dev/null +++ b/hw/src/soc_peripherals.sv @@ -0,0 +1,94 @@ +// Copyright (c) 2020 ETH Zurich and 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. + +module soc_peripherals #( + parameter int unsigned AXI_AW = 0, + parameter int unsigned AXI_IW = 0, + parameter int unsigned AXI_UW = 0, + parameter int unsigned N_CORES = 0, + parameter int unsigned N_CLUSTERS = 0 +) ( + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, + + AXI_BUS.Slave axi +); + + localparam int unsigned APB_AW = 32; + localparam int unsigned APB_DW = 32; + localparam int unsigned AXI_DW = 64; + + APB_BUS #( + .APB_ADDR_WIDTH (APB_AW), + .APB_DATA_WIDTH (APB_DW) + ) apb (); + + axi2apb_wrap #( + .AXI_ADDR_WIDTH (AXI_AW), + .AXI_DATA_WIDTH (AXI_DW), + .AXI_ID_WIDTH (AXI_IW), + .AXI_USER_WIDTH (AXI_UW), + .APB_ADDR_WIDTH (APB_AW), + .APB_DATA_WIDTH (APB_DW) + ) i_axi2apb ( + .clk_i, + .rst_ni, + .test_en_i, + .axi_slave (axi), + .apb_master (apb) + ); + + APB_BUS #( + .APB_ADDR_WIDTH (APB_AW), + .APB_DATA_WIDTH (APB_DW) + ) apb_periphs[1:0] (); + + apb_bus_wrap #( + .ADDR_WIDTH (APB_AW), + .DATA_WIDTH (APB_DW), + .N_SLV (2), + .ADDR_BEGIN ({32'h1A10_4000, 32'h1A10_3000}), + .ADDR_END ({32'h1A10_4FFF, 32'h1A10_3FFF}) + ) i_bus ( + .inp (apb), + .oup (apb_periphs) + ); + + `ifndef TARGET_SYNTHESIS + apb_stdout #( + .N_CORES (N_CORES), + .N_CLUSTERS (N_CLUSTERS), + .ADDR_WIDTH (APB_AW), + .DATA_WIDTH (APB_DW) + ) i_stdout ( + .clk_i, + .rst_ni, + .apb (apb_periphs[1]) + ); + `else + assign apb_periphs[1].pready = 1'b1; + assign apb_periphs[1].pslverr = 1'b1; + assign apb_periphs[1].prdata = '0; + `endif + + soc_ctrl_regs #( + .N_CORES (N_CORES), + .N_CLUSTERS (N_CLUSTERS), + .ADDR_WIDTH (APB_AW), + .DATA_WIDTH (APB_DW) + ) i_soc_ctrl_regs ( + .clk_i, + .rst_ni, + .apb (apb_periphs[0]) + ); + +endmodule diff --git a/hw/verilator_model/Makefile b/hw/verilator_model/Makefile new file mode 100644 index 0000000..d3aafa4 --- /dev/null +++ b/hw/verilator_model/Makefile @@ -0,0 +1,285 @@ +PSPIN_VERSION ?= undef +VERILATOR_CMD ?= verilator +VERILATOR_CC=$(VERILATOR_BIN)$(VERILATOR_CMD) +TOP_MODULE=pspin_verilator +SIM_EXE_SRCS=src/main.cpp +SIM_LIB_SRCS=src/pspinsim.cpp + +TRACE_DEPTH?=6 +VFLAGS_RELEASE=--Mdir obj_dir_release --sv -Wno-UNOPTFLAT -Wno-NOLATCH -Wno-WIDTHCONCAT -j 8 +systemverilogext+sv -Wno-lint -CFLAGS "-fPIC" +VFLAGS_DEBUG=--Mdir obj_dir_debug --sv --assert --trace --trace-structs --trace-depth $(TRACE_DEPTH) -CFLAGS "-DVERILATOR_HAS_TRACE -fPIC" -Wno-UNOPTFLAT -Wno-NOLATCH -Wno-WIDTHCONCAT -j 8 +systemverilogext+sv -Wno-lint + +CC ?= gcc +CXX ?= g++ + +LIB_RELEASE_FLAGS=-fPIC --std=c++11 -Os -shared -Iobj_dir_release -I$(VERILATOR_HOME)/include -I$(VERILATOR_HOME)/include/vltstd/ -Iinclude/ +LIB_DEBUG_FLAGS=-fPIC -g --std=c++11 -Os -shared -Iobj_dir_debug -I$(VERILATOR_HOME)/include -I$(VERILATOR_HOME)/include/vltstd/ -Iinclude/ -DVERILATOR_HAS_TRACE + +EXE_RELEASE_FLAGS=-Iinclude/ +EXE_DEBUG_FLAGS=-Iinclude/ -DVERILATOR_HAS_TRACE + +SV_INC=-I../deps/axi/include/ -I../deps/common_cells/include -I../deps/cluster_interconnect/rtl/low_latency_interco/ -I../deps/riscv/include/ +SV_SRCS=../deps/axi/src/axi_pkg.sv \ + ../deps/axi/src/axi_intf.sv \ + ../src/pulp_cluster_cfg_pkg.sv \ + ../src/pspin_cfg_pkg.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect_pkg.sv \ + ../deps/common_cells/src/fifo_v3.sv \ + ../deps/common_cells/src/stream_fifo.sv \ + ../deps/axi/src/axi_buf.sv \ + ../deps/common_cells/src/delta_counter.sv \ + ../deps/common_cells/src/cf_math_pkg.sv \ + ../deps/common_cells/src/lzc.sv \ + ../deps/common_cells/src/rr_arb_tree.sv \ + ../deps/common_cells/src/spill_register.sv \ + ../deps/axi/src/axi_demux.sv \ + ../deps/riscv/include/fpnew_pkg.sv \ + ../deps/riscv/include/riscv_defines.sv \ + ../deps/common_cells/src/deprecated/fifo_v2.sv \ + ../deps/common_cells/src/fall_through_register.sv \ + ../deps/common_cells/src/stream_demux.sv \ + ../deps/common_cells/src/stream_mux.sv \ + ../deps/common_cells/src/stream_fork.sv \ + ../deps/common_cells/src/stream_fork_dynamic.sv \ + ../deps/common_cells/src/stream_to_mem.sv \ + ../deps/common_cells/src/stream_join.sv \ + ../deps/axi2mem/src/axi_to_mem.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/addr_dec_resp_mux.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/xbar.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_interconnect.sv \ + ../deps/axi2mem/src/axi_to_mem_banked_mp.sv \ + ../deps/tech_cells_generic/src/rtl/tc_sram.sv \ + ../src/memories/sram.sv \ + ../src/memories/l2_mem.sv \ + ../src/pkt_scheduler/fifo_engine.sv \ + ../src/pkt_scheduler/mpq_engine.sv \ + ../src/pkt_scheduler/scheduler.sv \ + ../deps/axi/src/dma/axi_dma_burst_reshaper.sv \ + ../deps/axi/src/dma/axi_dma_data_path \ + ../deps/axi/src/dma/axi_dma_data_mover.sv \ + ../deps/axi/src/dma/axi_dma_backend.sv \ + ../deps/common_cells/src/addr_decode.sv \ + ../deps/common_cells/src/stream_register.sv \ + ../deps/common_cells/src/counter.sv \ + ../deps/axi/src/axi_atop_filter.sv \ + ../deps/axi/src/axi_err_slv.sv \ + ../deps/axi/src/axi_id_prepend.sv \ + ../deps/axi/src/axi_mux.sv \ + ../deps/axi/src/axi_xbar.sv \ + ../deps/axi/src/dma/frontends/pspin_soc_frontend/src/pspin_soc_dma.sv \ + ../src/soc_dma_wrap.sv \ + ../src/cmds/cmd_unit.sv \ + ../deps/pulp_cluster/packages/pulp_cluster_package.sv \ + ../deps/riscv/include/apu_core_package.sv \ + ../deps/pulp_cluster/packages/apu_package.sv \ + ../deps/cluster_interconnect/rtl/interfaces/xbar_tcdm_bus.sv \ + ../deps/cluster_interconnect/rtl/interfaces/xbar_periph_bus.sv \ + ../deps/pulp_cluster/rtl/cpu_marx_if.sv \ + ../deps/cluster_interconnect/rtl/interfaces/tcdm_bank_mem_bus.sv \ + ../deps/cluster_interconnect/rtl/interfaces/wide_dma_tcdm.sv \ + ../deps/cluster_peripherals/icache_ctrl_unit/interfaces/mp_pf_icache_ctrl_unit_bus.sv \ + ../deps/common_cells/src/rstgen_bypass.sv \ + ../deps/common_cells/src/rstgen.sv \ + ../deps/pulp_cluster/rtl/cluster_bus_wrap.sv \ + ../deps/axi_slice/src/axi_w_buffer.sv \ + ../deps/axi_slice/src/axi_r_buffer.sv \ + ../deps/axi_slice/src/axi_ar_buffer.sv \ + ../deps/axi_slice/src/axi_b_buffer.sv \ + ../deps/common_cells/src/deprecated/fifo_v1.sv \ + ../deps/axi_slice/src/axi_single_slice.sv \ + ../deps/axi_slice/src/axi_aw_buffer.sv \ + ../deps/axi2per/axi2per_req_channel.sv \ + ../deps/axi2per/axi2per_res_channel.sv \ + ../deps/axi2per/axi2per.sv \ + ../deps/pulp_cluster/rtl/axi2per_wrap.sv \ + ../deps/pulp_cluster/rtl/per_demux_wrap.sv \ + ../deps/per2axi/src/per2axi_req_channel.sv \ + ../deps/per2axi/src/per2axi_res_channel.sv \ + ../deps/per2axi/src/per2axi_busy_unit.sv \ + ../deps/per2axi/src/per2axi.sv \ + ../deps/pulp_cluster/rtl/per2axi_wrap.sv \ + ../deps/pulp_cluster/rtl/tryx_ctrl.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/superbank_addr_decoder.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/tcdm_superbank_mux.sv \ + ../deps/cluster_interconnect/rtl/tcdm_interconnect/amo_shim.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_Req_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/RR_Flag_Req_PE \ + ../deps/cluster_interconnect/rtl/peripheral_interco/ArbitrationTree_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/MUX2_REQ_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_Resp_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/RequestBlock2CH_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/FanInPrimitive_PE_Resp \ + ../deps/cluster_interconnect/rtl/peripheral_interco/ResponseTree_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/AddressDecoder_PE_Req.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/ResponseBlock_PE.sv \ + ../deps/cluster_interconnect/rtl/peripheral_interco/XBAR_PE.sv \ + ../deps/pulp_cluster/rtl/cluster_interconnect_wrap.sv \ + ../deps/axi/src/axi_serializer.sv \ + ../deps/axi/src/dma/frontends/pulp_cluster_frontend/src/transfer_id_gen.sv \ + ../deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend_regs.sv \ + ../deps/axi/src/dma/frontends/pulp_cluster_frontend/src/pulp_cluster_frontend.sv \ + ../deps/pulp_cluster/rtl/dmac_wrap.sv \ + ../deps/axi2mem/src/axi_to_mem_interleaved.sv \ + ../deps/pulp_cluster/rtl/nhi_port_wrap.sv \ + ../deps/event_unit_flex/message_bus.sv \ + ../deps/cluster_peripherals/cluster_control_unit/cluster_control_unit.sv \ + ../deps/pulp_cluster/rtl/cluster_timer_wrap.sv \ + ../deps/timer_unit/rtl/timer_unit_counter_presc.sv \ + ../deps/timer_unit/rtl/timer_unit_counter.sv \ + ../deps/timer_unit/rtl/timer_unit.sv \ + ../deps/event_unit_flex/event_unit_interface_mux.sv \ + ../deps/pulp_cluster/rtl/cluster_event_map.sv \ + ../deps/event_unit_flex/interc_sw_evt_trig.sv \ + ../deps/event_unit_flex/event_unit_core.sv \ + ../deps/event_unit_flex/hw_barrier_unit.sv \ + ../deps/event_unit_flex/hw_mutex_unit.sv \ + ../deps/event_unit_flex/hw_dispatch.sv \ + ../deps/event_unit_flex/event_unit_top.sv \ + ../deps/cluster_peripherals/icache_ctrl_unit/mp_pf_icache_ctrl_unit.sv \ + ../deps/pulp_cluster/rtl/cluster_peripherals.sv \ + ../src/pkt_scheduler/cluster_rb.sv \ + ../src/pkt_scheduler/cluster_scheduler.sv \ + ../src/cmds/cluster_cmd.sv \ + ../deps/cluster_interconnect/rtl/interfaces/xbar_demux_bus.sv \ + ../deps/riscv/verilator-model/cluster_clock_gating.sv \ + ../deps/riscv/riscv_L0_buffer.sv \ + ../deps/riscv/riscv_prefetch_L0_buffer.sv \ + ../deps/riscv/riscv_hwloop_controller.sv \ + ../deps/riscv/riscv_compressed_decoder.sv \ + ../deps/riscv/riscv_if_stage.sv \ + ../deps/riscv/riscv_register_file.sv \ + ../deps/riscv/riscv_decoder.sv \ + ../deps/riscv/riscv_controller.sv \ + ../deps/riscv/riscv_int_controller.sv \ + ../deps/riscv/riscv_hwloop_regs.sv \ + ../deps/riscv/riscv_id_stage.sv \ + ../deps/riscv/riscv_popcnt.sv \ + ../deps/riscv/riscv_ff_one.sv \ + ../deps/riscv/riscv_alu_div.sv \ + ../deps/riscv/riscv_alu.sv \ + ../deps/riscv/riscv_mult.sv \ + ../deps/riscv/riscv_apu_disp.sv \ + ../deps/riscv/riscv_ex_stage.sv \ + ../deps/riscv/riscv_load_store_unit.sv \ + ../deps/riscv/riscv_cs_registers.sv \ + ../deps/riscv/riscv_pmp.sv \ + ../deps/riscv/include/riscv_tracer_defines.sv \ + ../deps/riscv/riscv_tracer.sv \ + ../deps/riscv/riscv_core.sv \ + ../deps/common_cells/src/deprecated/generic_fifo.sv \ + ../deps/pulp_cluster/rtl/periph_FIFO.sv \ + ../deps/pulp_cluster/rtl/core_demux.sv \ + ../deps/riscv/riscv_store_buffer.sv \ + ../deps/pulp_cluster/rtl/periph_demux.sv \ + ../deps/pulp_cluster/rtl/inter_core_fifo.sv \ + ../deps/pulp_cluster/rtl/virtual_stdout_demux.sv \ + ../deps/pulp_cluster/rtl/core_region.sv \ + ../src/pkt_scheduler/hpu_driver.sv \ + ../deps/common_cells/src/deprecated/generic_LFSR_8bit.sv \ + ../deps/common_cells/src/onehot_to_bin.sv \ + ../deps/icache_mp_128_pf/RTL/icache_bank_mp_128.sv \ + ../deps/scm/latch_scm/register_file_1w_multi_port_read.sv \ + ../deps/icache-intc/Req_Arb_Node_icache_intc.sv \ + ../deps/icache-intc/DistributedArbitrationNetwork_Req_icache_intc.sv \ + ../deps/icache-intc/RoutingBlock_Req_icache_intc.sv \ + ../deps/icache-intc/DistributedArbitrationNetwork_Resp_icache_intc.sv \ + ../deps/icache-intc/RoutingBlock_Resp_icache_intc.sv \ + ../deps/icache-intc/icache_intc.sv \ + ../deps/icache_mp_128_pf/RTL/pf_miss_mux.sv \ + ../deps/icache_mp_128_pf/RTL/merge_refill_cam_128_16.sv \ + ../deps/icache_mp_128_pf/RTL/central_controller_128.sv \ + ../deps/icache_mp_128_pf/RTL/cache_controller_to_axi_128_PF.sv \ + ../deps/icache_mp_128_pf/RTL/icache_bank_mp_PF.sv \ + ../deps/icache_mp_128_pf/RTL/prefetcher_if.sv \ + ../deps/icache_mp_128_pf/RTL/icache_top_mp_128_PF.sv \ + ../deps/axi/src/axi_cut.sv \ + ../deps/axi_slice_dc/src/dc_token_ring.v \ + ../deps/axi_slice_dc/src/dc_synchronizer.v \ + ../deps/axi_slice_dc/src/dc_token_ring_fifo_dout.v \ + ../deps/common_cells/src/edge_propagator_tx.sv \ + ../deps/pulp_cluster/rtl/pulp_cluster.sv \ + ../src/pulp_cluster_ooc.sv \ + ../src/memories/prog_mem.sv \ + ../deps/axi/src/axi_dw_upsizer.sv \ + ../deps/axi/src/axi_dw_converter.sv \ + ../src/interconnects/pe_noc.sv \ + ../src/interconnects/dma_noc.sv \ + ../src/interconnects/cluster_noc.sv \ + ../src/interconnects/l2_xbar.sv \ + ../deps/axi/src/axi_id_remap.sv \ + ../src/interconnects/nhi_xbar.sv \ + ../deps/axi_riscv_atomics/src/axi_riscv_amos_alu.sv \ + ../deps/axi_riscv_atomics/src/axi_riscv_amos.sv \ + ../deps/common_cells/src/id_queue.sv \ + ../deps/common_cells/src/stream_filter.sv \ + ../deps/common_cells/src/stream_arbiter_flushable.sv \ + ../deps/common_cells/src/stream_arbiter.sv \ + ../deps/axi_riscv_atomics/src/axi_res_tbl.sv \ + ../deps/axi_riscv_atomics/src/axi_riscv_lrsc.sv \ + ../deps/axi_riscv_atomics/src/axi_riscv_atomics.sv \ + ../deps/axi_riscv_atomics/src/axi_riscv_atomics_wrap.sv \ + ../deps/apb/src/apb_intf.sv \ + ../deps/axi2apb/src/axi2apb_64_32.sv \ + ../deps/axi2apb/src/axi2apb_wrap.sv \ + ../src/apb/apb_bus.sv \ + ../src/apb/apb_bus_wrap.sv \ + ../src/apb/apb_stdout.sv \ + ../src/apb/apb_ro_regs.sv \ + ../src/apb/apb_rw_regs.sv \ + ../src/soc_ctrl_regs.sv \ + ../src/soc_peripherals.sv \ + ../deps/axi/src/axi_dw_downsizer.sv \ + ../src/host_direct.sv \ + ../src/host_mst_mux.sv \ + ../src/pspin.sv \ + ../src/pspin_verilator.sv \ + +.PHONY: archive + +lib/libpspin_debug.so: + $(VERILATOR_CC) $(VFLAGS_DEBUG) $(SV_INC) -cc $(SV_SRCS) --top-module $(TOP_MODULE) --build $(SIM_LIB_SRCS) -o pspin + @mkdir -p lib/ + $(CXX) $(LIB_DEBUG_FLAGS) -o lib/libpspin_debug.so $(SIM_LIB_SRCS) obj_dir_debug/Vpspin_verilator__ALL.a $(VERILATOR_HOME)/include/verilated.cpp $(VERILATOR_HOME)/include/verilated_vcd_c.cpp + +lib/libpspin.so: + $(VERILATOR_CC) $(VFLAGS_RELEASE) $(SV_INC) -cc $(SV_SRCS) --top-module $(TOP_MODULE) --build $(SIM_LIB_SRCS) -o pspin + @mkdir -p lib/ + $(CXX) $(LIB_RELEASE_FLAGS) -o lib/libpspin.so $(SIM_LIB_SRCS) obj_dir_release/Vpspin_verilator__ALL.a $(VERILATOR_HOME)/include/verilated.cpp + +release: lib/libpspin.so + @mkdir -p bin/ + $(CC) $(EXE_RELEASE_FLAGS) $(SIM_EXE_SRCS) -Llib/ -lpspin -o bin/pspin_release + +debug: lib/libpspin_debug.so + @mkdir -p bin/ + $(CC) $(EXE_DEBUG_FLAGS) $(SIM_EXE_SRCS) -Llib/ -lpspin_debug -o bin/pspin_debug + +build-debug: debug + @mkdir -p verilator/ + @mkdir -p verilator/bin/ + cp start_sim.sh verilator/ + cp bin/pspin_debug verilator/bin/ + cp -r lib/ verilator/ + +build-release: release + @mkdir -p verilator/ + @mkdir -p verilator/bin/ + cp start_sim.sh verilator/ + cp bin/pspin_release verilator/bin/ + cp -r lib/ verilator/ + + +clean: + @rm -rf obj_dir_debug/ obj_dir_release/ bin/pspin bin/pspin_debug lib/libpspin.so lib/libpspin_debug.so > /dev/null 2> /dev/null + +pack: + mkdir -p pspin-v${PSPIN_VERSION}/sim_files/slm_files/ + mkdir -p pspin-v${PSPIN_VERSION}/verilator_model/bin/ + mkdir -p pspin-v${PSPIN_VERSION}/verilator_model/lib/ + cp bin/pspin* pspin-v${PSPIN_VERSION}/verilator_model/bin/ + cp lib/lib* pspin-v${PSPIN_VERSION}/verilator_model/lib/ + cp -r include pspin-v${PSPIN_VERSION}/verilator_model/ + cp start_sim.sh pspin-v${PSPIN_VERSION}/verilator_model/ + tar -czvf pspin-v${PSPIN_VERSION}.tar.gz pspin-v${PSPIN_VERSION}/ + +.PHONY: lib/libpspin.so lib/libpspin_debug.so clean pack diff --git a/hw/verilator_model/include/pspinsim.h b/hw/verilator_model/include/pspinsim.h new file mode 100644 index 0000000..472d86d --- /dev/null +++ b/hw/verilator_model/include/pspinsim.h @@ -0,0 +1,87 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#ifndef __PSPINSIM_H__ +#define __PSPINSIM_H__ + +#include "spin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ni_conf +{ + uint32_t axi_aw_buffer; + uint32_t axi_w_buffer; + uint32_t axi_b_buffer; +} ni_conf_t; + +typedef struct no_conf +{ + uint32_t axi_ar_buffer; + uint32_t axi_r_buffer; + double network_G; + uint32_t max_pkt_size; + uint32_t max_network_queue_len; +} no_conf_t; + +typedef struct pcie_slv_conf +{ + uint32_t axi_aw_buffer; + uint32_t axi_w_buffer; + uint32_t axi_ar_buffer; + uint32_t axi_b_buffer; + uint32_t axi_r_buffer; + uint32_t pcie_L; + double pcie_G; +} pcie_slv_conf_t; + +typedef struct pspin_conf { + char *slm_files_path; + ni_conf_t ni_conf; + no_conf_t no_conf; + pcie_slv_conf_t pcie_slv_conf; +} pspin_conf_t; + +typedef void (*pkt_out_cb_t)(uint8_t*, size_t); +typedef void (*pkt_feedback_cb_t)(uint64_t, uint64_t, uint64_t, uint64_t); +typedef void (*pcie_slv_write_cb_t)(uint64_t, uint8_t*, size_t); +typedef void (*pcie_slv_read_cb_t)(uint64_t, uint8_t*, size_t); +typedef void (*pcie_mst_write_cb_t)(void*); +typedef void (*pcie_mst_read_cb_t)(void*); + +int pspinsim_default_conf(pspin_conf_t *conf); + +int pspinsim_init(int argc, char **argv, pspin_conf_t *conf); +int pspinsim_run(); +int pspinsim_run_tick(uint8_t *done_flag); +int pspinsim_fini(); + +int pspinsim_packet_trace_read(const char* pkt_file_path, const char* data_file_path); +int pspinsim_packet_add(spin_ec_t* ec, uint32_t msgid, uint8_t* pkt_data, size_t pkt_len, size_t pkt_l1_len, uint8_t eom, uint32_t wait_cycles, uint64_t user_ptr); +int pspinsim_packet_eos(); + +int pspinsim_cb_set_pkt_out(pkt_out_cb_t cb); +int pspinsim_cb_set_pcie_slv_write(pcie_slv_write_cb_t cb); +int pspinsim_cb_set_pcie_slv_read(pcie_slv_read_cb_t cb); +int pspinsim_cb_set_pcie_mst_write_completion(pcie_mst_write_cb_t cb); +int pspinsim_cb_set_pcie_mst_read_completion(pcie_mst_read_cb_t cb); +int pspinsim_cb_set_pkt_feedback(pkt_feedback_cb_t cb); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __PSPINSIM_H__ */ diff --git a/hw/verilator_model/include/spin.h b/hw/verilator_model/include/spin.h new file mode 100644 index 0000000..6704992 --- /dev/null +++ b/hw/verilator_model/include/spin.h @@ -0,0 +1,72 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#ifndef __SPIN_H__ +#define __SPIN_H__ + +#include +#include + +#include "spin_hw_conf.h" + +#define SPIN_SUCCESS 0 +#define SPIN_ERR 1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t mem_addr_t; +typedef uint32_t mem_size_t; +typedef uint64_t host_addr_t; + +typedef struct spin_ec +{ + //handler memory + mem_addr_t handler_mem_addr; + mem_size_t handler_mem_size; + + //host memory + host_addr_t host_mem_addr; + mem_size_t host_mem_size; + + //header handler + mem_addr_t hh_addr; + mem_size_t hh_size; + + //payload handler + mem_addr_t ph_addr; + mem_size_t ph_size; + + //completion (aka tail) handler + mem_addr_t th_addr; + mem_size_t th_size; + + //L1 scratchpads + mem_addr_t scratchpad_addr[NUM_CLUSTERS]; + mem_size_t scratchpad_size[NUM_CLUSTERS]; + +} __attribute__((__packed__)) spin_ec_t; + +typedef uint32_t spin_nic_addr_t; + +int spin_nicmem_write(spin_nic_addr_t addr, void *data, size_t size, void* user_ptr); +int spin_nicmem_read(spin_nic_addr_t addr, void *data, size_t size, void* user_ptr); +int spin_find_handler_by_name(char *binfile, char* handler_name, spin_nic_addr_t *handler_addr, size_t *handler_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __SPIN_H__ */ \ No newline at end of file diff --git a/hw/verilator_model/include/spin_hw_conf.h b/hw/verilator_model/include/spin_hw_conf.h new file mode 100644 index 0000000..597a907 --- /dev/null +++ b/hw/verilator_model/include/spin_hw_conf.h @@ -0,0 +1,41 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +// WARNING: this has to match pspin_cfg_pkg.sv !!! +#define NUM_CLUSTERS 4 +#define NUM_CORES 8 +#define C_MSGID_WIDTH 10 +#define PCIE_START_ADDR 0x1000000000000000 + +// 1 MiB +#define L1_CLUSTER_ACTUAL_MEM_SIZE 0x00100000 + +// 1 KiB reserved at the beginning. +#define L1_RUNTIME_OFFSET 0x00000400 + +// 16 KiB +#define L1_RUNTIME_SIZE 0x00004000 + +#define L1_PKT_BUFF_OFFSET (L1_RUNTIME_OFFSET + L1_RUNTIME_SIZE) + +// 32 KiB +#define L1_PKT_BUFF_SIZE 0x00008000 + +#define L2_PKT_BUFF_START 0x1c400000 +#define L2_PKT_BUFF_SIZE 4 * 1024 * 1024 + +#define L1_SCRATCHPAD_OFFSET (L1_PKT_BUFF_OFFSET + L1_PKT_BUFF_SIZE) +#define L1_SCRATCHPAD_SIZE (L1_CLUSTER_ACTUAL_MEM_SIZE - L1_PKT_BUFF_OFFSET) diff --git a/hw/verilator_model/src/AXIDriver.hpp b/hw/verilator_model/src/AXIDriver.hpp new file mode 100644 index 0000000..bf4b373 --- /dev/null +++ b/hw/verilator_model/src/AXIDriver.hpp @@ -0,0 +1,247 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include + +#include "AXIPort.hpp" + +namespace PsPIN +{ + template + class AXIDriver + { + typedef typename AXIPortType::axi_addr_t axi_addr_t; + typedef typename AXIPortType::axi_strb_t axi_strb_t; + typedef typename AXIPortType::axi_prot_t axi_prot_t; + typedef typename AXIPortType::axi_region_t axi_region_t; + typedef typename AXIPortType::axi_len_t axi_len_t; + typedef typename AXIPortType::axi_size_t axi_size_t; + typedef typename AXIPortType::axi_burst_t axi_burst_t; + typedef typename AXIPortType::axi_lock_t axi_lock_t; + typedef typename AXIPortType::axi_atop_t axi_atop_t; + typedef typename AXIPortType::axi_cache_t axi_cache_t; + typedef typename AXIPortType::axi_qos_t axi_qos_t; + typedef typename AXIPortType::axi_id_t axi_id_t; + typedef typename AXIPortType::axi_user_t axi_user_t; + + protected: + typedef struct axi_ax_beat + { + axi_id_t ax_id; + axi_addr_t ax_addr; + axi_len_t ax_len; + axi_size_t ax_size; + axi_burst_t ax_burst; + axi_lock_t ax_lock; + axi_cache_t ax_cache; + axi_prot_t ax_prot; + axi_qos_t ax_qos; + axi_region_t ax_region; + axi_atop_t ax_atop; // Only defined on the AW channel. + axi_user_t ax_user; + + uint32_t offset; //bytes already received + } axi_ax_beat_t; + + typedef struct axi_w_beat + { + uint8_t w_data[AXI_SW]; + axi_strb_t w_strb; + axi_user_t w_user; + uint8_t w_last; + } axi_w_beat_t; + + typedef struct axi_b_beat + { + uint8_t b_resp; + axi_id_t b_id; + axi_user_t b_user; + } axi_b_beat_t; + + typedef struct axi_r_beat + { + uint8_t r_resp; + uint8_t r_last; + axi_id_t r_id; + axi_user_t r_user; + uint8_t r_data[AXI_SW]; + } axi_r_beat_t; + + typedef struct axi_b_queue_entry + { + uint32_t n_bursts; + void *b_callback_arg; + } axi_b_queue_entry_t; + + typedef struct axi_r_queue_entry + { + uint32_t data_left; + uint32_t n_bursts; + void *r_callback_arg; + } axi_r_queue_entry_t; + + typedef struct beat_and_size + { + axi_ax_beat_t beat; + uint32_t n_bytes; + } beat_and_size_t; + + public: + AXIDriver(AXIPortType &port) : port(port) + { + *port.aw_valid = 0; + *port.w_valid = 0; + *port.b_ready = 0; + *port.ar_valid = 0; + *port.r_ready = 0; + } + + virtual void posedge() = 0; + virtual void negedge() = 0; + + protected: + AXIPortType &port; + + protected: + uint32_t axi_num_bytes(axi_size_t size) + { + return 1 << size; + } + + axi_addr_t axi_aligned_address(axi_addr_t addr, axi_size_t size) + { + return (addr / axi_num_bytes(size)) * axi_num_bytes(size); + } + + axi_addr_t beat_addr(axi_ax_beat_t ax, uint32_t i_beat) + { + if (i_beat == 0) + return ax.ax_addr; + else + return axi_aligned_address(ax.ax_addr, ax.ax_size) + i_beat * (1 << ax.ax_size); + } + + uint32_t beat_lower_byte(axi_ax_beat_t ax, uint32_t i_beat) + { + axi_addr_t addr = beat_addr(ax, i_beat); + return addr - (addr / AXI_SW) * AXI_SW; + } + + uint32_t beat_upper_byte(axi_ax_beat_t ax, uint32_t i_beat, uint32_t n_bytes) + { + if (i_beat == 0) + { + return axi_aligned_address(ax.ax_addr, ax.ax_size) + (1 << ax.ax_size) - (ax.ax_addr / AXI_SW) * AXI_SW; + } + else if (i_beat == ax.ax_len) + { + return n_bytes - (AXI_SW - beat_lower_byte(ax, 0)) - (ax.ax_len - 1) * AXI_SW; + } + else + { + return beat_lower_byte(ax, i_beat) + (1 << ax.ax_size); + } + } + + uint64_t page_num(axi_addr_t addr) + { + return addr >> 12; + } + + void create_ax_beats(axi_addr_t addr, uint32_t n_bytes, std::queue &ax_beats) + { + uint64_t n_beats; + uint32_t bytes_in_first_beat, bytes_in_last_beat; + size_t ax_size; + + // Iteratively create Ax beats until all bytes have been transferred. + while (n_bytes > 0) + { + axi_ax_beat_t ax_beat; + uint32_t bytes_in_burst; + + memset(&ax_beat, 0, sizeof(axi_ax_beat_t)); + + ax_beat.ax_addr = addr; + ax_beat.ax_burst = AXI_BURST_INCR; + + // Determine size of each beat. + if (n_bytes > AXI_SW || (addr >> ((uint32_t)log2(AXI_SW))) != (addr + n_bytes - 1) >> ((uint32_t)log2(AXI_SW))) + { + // If the number of bytes exceeds the data bus width or the first byte is not on the same + // AXI line as the last byte, we have to write multiple beats. In this case, the burst must + // use the full data bus. + ax_beat.ax_size = log2(AXI_SW); + } + else + { + // If the number of bytes is less or equal to the data bus width, a single beat is + // sufficient. The size of the beat depends on the address, which determines the lower byte + // lane; all bytes must fit into the beat. + // The smallest possible value is the number of bytes to be transferred. + ax_beat.ax_size = log2(n_bytes); + // If the resulting upper byte lane is not high enough to accommodate all bytes, increment + // the size. + while (beat_upper_byte(ax_beat, 0, n_bytes) - beat_lower_byte(ax_beat, 0) < n_bytes) + { + assert(ax_beat.ax_size < log2(AXI_SW)); + ax_beat.ax_size++; + } + } + + // Calculate bytes per beat and total number of beats. + bytes_in_first_beat = AXI_SW - (addr % AXI_SW); + if (n_bytes <= bytes_in_first_beat) + { + bytes_in_first_beat = n_bytes; + n_beats = 1; + } + else + { + n_beats = 1 + ceil(((double)(n_bytes - bytes_in_first_beat)) / AXI_SW); + bytes_in_last_beat = n_bytes - bytes_in_first_beat - AXI_SW * (n_beats - 2); + } + + if (page_num(addr) != page_num(addr + n_bytes - 1)) + { + bytes_in_burst = 4096 - (addr & 0xFFF); + create_ax_beats(addr, bytes_in_burst, ax_beats); + } + else + { + beat_and_size_t bs; + bytes_in_burst = bytes_in_first_beat; + if (n_beats > 256) + { + n_beats = 256; + bytes_in_last_beat = AXI_SW; + } + if (n_beats > 1) + { + bytes_in_burst += (n_beats - 2) * AXI_SW + bytes_in_last_beat; + } + ax_beat.ax_len = n_beats - 1; + bs.beat = ax_beat; + bs.n_bytes = bytes_in_burst; + ax_beats.push(bs); + } + addr += bytes_in_burst; + n_bytes -= bytes_in_burst; + } + } + }; + +} // namespace PsPIN diff --git a/hw/verilator_model/src/AXIMaster.hpp b/hw/verilator_model/src/AXIMaster.hpp new file mode 100644 index 0000000..5a01554 --- /dev/null +++ b/hw/verilator_model/src/AXIMaster.hpp @@ -0,0 +1,492 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIDriver.hpp" + +namespace PsPIN +{ + + template + class AXIMaster : public AXIDriver + { + using typename AXIDriver::axi_ax_beat_t; + using typename AXIDriver::axi_w_beat_t; + using typename AXIDriver::axi_b_queue_entry_t; + using typename AXIDriver::axi_r_queue_entry_t; + using typename AXIDriver::beat_and_size_t; + + typedef typename AXIPortType::axi_addr_t axi_addr_t; + + using AXIDriver::port; + using AXIDriver::create_ax_beats; + using AXIDriver::beat_lower_byte; + using AXIDriver::beat_upper_byte; + + private: + typedef struct axi_r_buffered + { + uint32_t data_length; + uint8_t data[AXI_SW]; + bool is_last; + } axi_r_buffered_t; + + private: + std::queue aw_queue; + std::queue w_queue; + std::queue r_queue; + + // a bit more high level. Takes into account that a write can be composed + // by multiple AW beats. Same for reads. + std::queue write_queue; + std::queue read_queue; + + + std::queue ar_queue; + std::queue b_queue; + + std::queue aw_pending_queue; + std::queue ar_pending_queue; + std::queue w_pending_queue; + + bool aw_wait; + bool ar_wait; + bool w_wait; + + uint32_t aw_beats_buffer_size; + uint32_t w_beats_buffer_size; + uint32_t b_beats_buffer_size; + uint32_t ar_beats_buffer_size; + uint32_t r_beats_buffer_size; + + public: + + bool has_aw_beat() + { + return !aw_pending_queue.empty(); + } + + bool can_send_aw_beat() + { + return aw_beats_buffer_size == 0 || aw_queue.size() < aw_beats_buffer_size; + } + + void send_aw_beat() + { + assert(!aw_pending_queue.empty() && can_send_aw_beat()); + axi_ax_beat_t &aw = aw_pending_queue.front(); + aw_queue.push(aw); + aw_pending_queue.pop(); + } + + bool has_ar_beat() + { + return !ar_pending_queue.empty(); + } + + bool can_send_ar_beat() + { + return ar_beats_buffer_size == 0 || ar_queue.size() < ar_beats_buffer_size; + } + + void send_ar_beat() + { + assert(!ar_pending_queue.empty() && can_send_ar_beat()); + axi_ax_beat_t &ar = ar_pending_queue.front(); + ar_queue.push(ar); + ar_pending_queue.pop(); + } + + bool has_w_beat() + { + return !w_pending_queue.empty(); + } + + bool can_send_w_beat() + { + return w_beats_buffer_size == 0 || w_queue.size() < w_beats_buffer_size; + } + + void send_w_beat() + { + assert(!w_pending_queue.empty() && can_send_w_beat()); + axi_w_beat_t &w = w_pending_queue.front(); + w_queue.push(w); + w_pending_queue.pop(); + } + + bool has_r_beat() + { + return !r_queue.empty(); + } + + bool consume_r_beat(uint8_t *data, uint32_t &data_length) + { + assert(has_r_beat()); + axi_r_buffered_t r = r_queue.front(); + data_length = std::min(data_length, r.data_length); + if (data!=NULL) { + memcpy(data, &(r.data[0]), data_length); + } + bool read_complete = r.is_last; + r_queue.pop(); + return read_complete; + } + + bool has_b_beat() + { + return !b_queue.empty(); + } + + bool consume_b_beat() + { + bool res = b_queue.front(); + b_queue.pop(); + return res; + } + + void set_aw_buffer(uint32_t aw_buffer_size) + { + aw_beats_buffer_size = aw_buffer_size; + } + + void set_ar_buffer(uint32_t ar_buffer_size) + { + ar_beats_buffer_size = ar_buffer_size; + } + + void set_w_buffer(uint32_t w_buffer_size) + { + w_beats_buffer_size = w_buffer_size; + } + + void set_r_buffer(uint32_t r_buffer_size) + { + r_beats_buffer_size = r_buffer_size; + } + + void set_b_buffer(uint32_t b_buffer_size) + { + b_beats_buffer_size = b_buffer_size; + } + + public: + AXIMaster(AXIPortType &port) : AXIDriver(port) + { + *port.aw_valid = 0; + *port.aw_valid = 0; + *port.w_valid = 0; + + *port.b_ready = 0; + *port.r_ready = 0; + + aw_wait = false; + ar_wait = false; + w_wait = false; + + aw_beats_buffer_size = 0; + ar_beats_buffer_size = 0; + w_beats_buffer_size = 0; + r_beats_buffer_size = 0; + b_beats_buffer_size = 0; + } + + void posedge() + { + aw_posedge(); + ar_posedge(); + w_posedge(); + b_posedge(); + r_posedge(); + } + + void negedge() + { + aw_negedge(); + ar_negedge(); + w_negedge(); + b_negedge(); + r_negedge(); + } + + public: /* interface */ + void write(axi_addr_t addr, uint8_t *data, uint32_t n_bytes, uint32_t offset) + { + // Create and send AW. + uint32_t bytes_written = 0; + axi_b_queue_entry_t write_queue_entry; + + std::queue aw_beats; + create_ax_beats(addr, n_bytes, aw_beats); + + write_queue_entry.n_bursts = aw_beats.size(); + write_queue.push(write_queue_entry); + + //printf("Write: #aw: %u\n", aw_beats.size()); + uint32_t aw_cnt = 0; + while (aw_beats.size() != 0) + { + uint32_t burst_bytes_written = 0; + beat_and_size_t bs = aw_beats.front(); + aw_beats.pop(); + axi_ax_beat_t aw_beat = bs.beat; + aw_pending_queue.push(aw_beat); + + aw_cnt++; + //printf("Write: #w (aw_cnt: %u): %u; bytes_written: %u\n", aw_cnt, aw_beat.ax_len, bytes_written); + + // Send W beats filled with data from the `data` array. + for (uint32_t i_beat = 0; i_beat <= aw_beat.ax_len; i_beat++) + { + uint32_t lower_byte = beat_lower_byte(aw_beat, i_beat); + uint32_t upper_byte = beat_upper_byte(aw_beat, i_beat, bs.n_bytes); + + axi_w_beat_t w_beat; + memset(&w_beat, 0, sizeof(axi_w_beat_t)); + + uint32_t beat_size = std::min(upper_byte - lower_byte, bs.n_bytes); + + //printf("lb: %u; ub: %u; ub-lb: %u; bs.n_bytes: %u\n", lower_byte, upper_byte, upper_byte - lower_byte, bs.n_bytes); + + memcpy(w_beat.w_data + lower_byte, data + offset + bytes_written + burst_bytes_written, beat_size); + + for (uint32_t i_byte = lower_byte; i_byte < upper_byte && burst_bytes_written < bs.n_bytes; i_byte++) + { + w_beat.w_strb = w_beat.w_strb | ((1ul << (AXI_SW-1)) >> (AXI_SW - i_byte - 1)); + //printf("%% i_byte: %u; w_strb: 0x%lx\n", i_byte, w_beat.w_strb); + } + if (i_beat == aw_beat.ax_len) + { + w_beat.w_last = 1; + } + + w_pending_queue.push(w_beat); + burst_bytes_written += beat_size; + } + bytes_written += burst_bytes_written; + } + if (bytes_written != n_bytes) + { + printf("ERROR: bytes_written: %u; n_bytes: %u\n", bytes_written, n_bytes); + assert(bytes_written == n_bytes); + } + } + + void read(axi_addr_t addr, uint32_t n_bytes) + { + axi_r_queue_entry_t read_queue_entry; + std::queue ar_beats; + + create_ax_beats(addr, n_bytes, ar_beats); + read_queue_entry.n_bursts = ar_beats.size(); + read_queue_entry.data_left = n_bytes; + read_queue.push(read_queue_entry); + + while (ar_beats.size() != 0) + { + beat_and_size_t &bs = ar_beats.front(); + ar_beats.pop(); + axi_ax_beat_t ar_beat = bs.beat; + ar_pending_queue.push(ar_beat); + } + } + + private: + void aw_posedge() + { + if (aw_wait) + { + return; + } + + *port.aw_valid = 0; + + if (aw_queue.empty()) + { + return; + } + + // send next AW beat + axi_ax_beat_t &aw_beat = aw_queue.front(); + + *port.aw_addr = aw_beat.ax_addr; + *port.aw_prot = aw_beat.ax_prot; + *port.aw_region = aw_beat.ax_region; + *port.aw_len = aw_beat.ax_len; + *port.aw_size = aw_beat.ax_size; + *port.aw_burst = aw_beat.ax_burst; + *port.aw_lock = aw_beat.ax_lock; + *port.aw_atop = aw_beat.ax_atop; + *port.aw_cache = aw_beat.ax_cache; + *port.aw_qos = aw_beat.ax_qos; + *port.aw_id = aw_beat.ax_id; + *port.aw_user = aw_beat.ax_user; + + *port.aw_valid = 1; + aw_queue.pop(); + } + + void aw_negedge() + { + //AW_READY can be function of AW_VALID, so let's see if we have it set already + aw_wait = false; + if (*port.aw_valid && !(*port.aw_ready)) + { + aw_wait = true; + } + } + + void ar_posedge() + { + if (ar_wait) + { + return; + } + + *port.ar_valid = 0; + + if (ar_queue.empty()) + { + return; + } + + // send next AR beat + axi_ax_beat_t &ar_beat = ar_queue.front(); + + *port.ar_addr = ar_beat.ax_addr; + *port.ar_prot = ar_beat.ax_prot; + *port.ar_region = ar_beat.ax_region; + *port.ar_len = ar_beat.ax_len; + *port.ar_size = ar_beat.ax_size; + *port.ar_burst = ar_beat.ax_burst; + *port.ar_lock = ar_beat.ax_lock; + *port.ar_cache = ar_beat.ax_cache; + *port.ar_qos = ar_beat.ax_qos; + *port.ar_id = ar_beat.ax_id; + *port.ar_user = ar_beat.ax_user; + + *port.ar_valid = 1; + ar_queue.pop(); + } + + void ar_negedge() + { + //AR_READY can be function of AR_VALID, so let's see if we have it set already + ar_wait = false; + if (*port.ar_valid && !(*port.ar_ready)) + { + ar_wait = true; + } + } + + void w_posedge() + { + if (w_wait) + { + return; + } + + *port.w_valid = 0; + *port.w_last = 0; + + if (w_queue.empty()) + { + return; + } + + // send next W beat + axi_w_beat_t &w_beat = w_queue.front(); + + //copy data + memcpy(port.w_data, w_beat.w_data, AXI_SW); + + *port.w_strb = w_beat.w_strb; + *port.w_user = w_beat.w_user; + *port.w_last = w_beat.w_last; + + *port.w_valid = 1; + w_queue.pop(); + } + + void w_negedge() + { + //AW_READY can be function of AW_VALID, so let's see if we have it set already + w_wait = false; + if (*port.w_valid && !(*port.w_ready)) + { + w_wait = true; + } + } + + void b_posedge() + { + bool can_accept_b = b_beats_buffer_size == 0 || b_queue.size() < b_beats_buffer_size; + + if (*port.b_valid && can_accept_b) + { + assert(!write_queue.empty()); + axi_b_queue_entry_t &entry = write_queue.front(); + + entry.n_bursts--; + bool is_complete = entry.n_bursts == 0; + + *port.b_ready = 1; + if (is_complete) { + write_queue.pop(); + } + + b_queue.push(is_complete); + } + } + + void b_negedge() + { + //nothing to do here + } + + void r_posedge() + { + bool can_accept_r = r_beats_buffer_size == 0 || r_queue.size() < r_beats_buffer_size; + + if (*port.r_valid && can_accept_r) + { + assert(!read_queue.empty()); + axi_r_queue_entry_t &entry = read_queue.front(); + + uint32_t data_size = std::min((uint32_t)AXI_SW, entry.data_left); + uint32_t completed_burst = (*port.r_last == 1) ? 1 : 0; + + *port.r_ready = 1; + + entry.n_bursts -= completed_burst; + entry.data_left -= data_size; + bool is_complete = entry.n_bursts == 0; + if (is_complete) read_queue.pop(); + + axi_r_buffered_t r_buff; + r_buff.data_length = data_size; + memcpy(r_buff.data, port.r_data, data_size); + r_buff.is_last = is_complete; + r_queue.push(r_buff); + } + } + + void r_negedge() + { + //nothing to do here + } + }; + +} // namespace PsPIN \ No newline at end of file diff --git a/hw/verilator_model/src/AXIPort.hpp b/hw/verilator_model/src/AXIPort.hpp new file mode 100644 index 0000000..7042997 --- /dev/null +++ b/hw/verilator_model/src/AXIPort.hpp @@ -0,0 +1,218 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once +#include +#include + +#define PASTER(x, y) x##_##y +#define EVALUATOR(x, y) PASTER(x, y) +#define NAME(fun) EVALUATOR(fun, VARIABLE) + +#define AXI_MASTER_PORT_ASSIGN(SRC, SRC_PREFIX, DST) \ + { \ + (DST)->aw_addr = &((SRC)->EVALUATOR(SRC_PREFIX, aw_addr_i)); \ + (DST)->aw_prot = &((SRC)->EVALUATOR(SRC_PREFIX, aw_prot_i)); \ + (DST)->aw_region = &((SRC)->EVALUATOR(SRC_PREFIX, aw_region_i)); \ + (DST)->aw_len = &((SRC)->EVALUATOR(SRC_PREFIX, aw_len_i)); \ + (DST)->aw_size = &((SRC)->EVALUATOR(SRC_PREFIX, aw_size_i)); \ + (DST)->aw_burst = &((SRC)->EVALUATOR(SRC_PREFIX, aw_burst_i)); \ + (DST)->aw_lock = &((SRC)->EVALUATOR(SRC_PREFIX, aw_lock_i)); \ + (DST)->aw_atop = &((SRC)->EVALUATOR(SRC_PREFIX, aw_atop_i)); \ + (DST)->aw_cache = &((SRC)->EVALUATOR(SRC_PREFIX, aw_cache_i)); \ + (DST)->aw_qos = &((SRC)->EVALUATOR(SRC_PREFIX, aw_qos_i)); \ + (DST)->aw_id = &((SRC)->EVALUATOR(SRC_PREFIX, aw_id_i)); \ + (DST)->aw_user = &((SRC)->EVALUATOR(SRC_PREFIX, aw_user_i)); \ + (DST)->aw_valid = &((SRC)->EVALUATOR(SRC_PREFIX, aw_valid_i)); \ + (DST)->aw_ready = &((SRC)->EVALUATOR(SRC_PREFIX, aw_ready_o)); \ + \ + (DST)->ar_addr = &((SRC)->EVALUATOR(SRC_PREFIX, ar_addr_i)); \ + (DST)->ar_prot = &((SRC)->EVALUATOR(SRC_PREFIX, ar_prot_i)); \ + (DST)->ar_region = &((SRC)->EVALUATOR(SRC_PREFIX, ar_region_i)); \ + (DST)->ar_len = &((SRC)->EVALUATOR(SRC_PREFIX, ar_len_i)); \ + (DST)->ar_size = &((SRC)->EVALUATOR(SRC_PREFIX, ar_size_i)); \ + (DST)->ar_burst = &((SRC)->EVALUATOR(SRC_PREFIX, ar_burst_i)); \ + (DST)->ar_lock = &((SRC)->EVALUATOR(SRC_PREFIX, ar_lock_i)); \ + (DST)->ar_cache = &((SRC)->EVALUATOR(SRC_PREFIX, ar_cache_i)); \ + (DST)->ar_qos = &((SRC)->EVALUATOR(SRC_PREFIX, ar_qos_i)); \ + (DST)->ar_id = &((SRC)->EVALUATOR(SRC_PREFIX, ar_id_i)); \ + (DST)->ar_user = &((SRC)->EVALUATOR(SRC_PREFIX, ar_user_i)); \ + (DST)->ar_valid = &((SRC)->EVALUATOR(SRC_PREFIX, ar_valid_i)); \ + (DST)->ar_ready = &((SRC)->EVALUATOR(SRC_PREFIX, ar_ready_o)); \ + \ + (DST)->w_data = (uint8_t *)&((SRC)->EVALUATOR(SRC_PREFIX, w_data_i)); \ + (DST)->w_strb = &((SRC)->EVALUATOR(SRC_PREFIX, w_strb_i)); \ + (DST)->w_user = &((SRC)->EVALUATOR(SRC_PREFIX, w_user_i)); \ + (DST)->w_last = &((SRC)->EVALUATOR(SRC_PREFIX, w_last_i)); \ + (DST)->w_valid = &((SRC)->EVALUATOR(SRC_PREFIX, w_valid_i)); \ + (DST)->w_ready = &((SRC)->EVALUATOR(SRC_PREFIX, w_ready_o)); \ + \ + (DST)->r_data = (uint8_t *)&((SRC)->EVALUATOR(SRC_PREFIX, r_data_o)); \ + (DST)->r_resp = &((SRC)->EVALUATOR(SRC_PREFIX, r_resp_o)); \ + (DST)->r_last = &((SRC)->EVALUATOR(SRC_PREFIX, r_last_o)); \ + (DST)->r_id = &((SRC)->EVALUATOR(SRC_PREFIX, r_id_o)); \ + (DST)->r_user = &((SRC)->EVALUATOR(SRC_PREFIX, r_user_o)); \ + (DST)->r_valid = &((SRC)->EVALUATOR(SRC_PREFIX, r_valid_o)); \ + (DST)->r_ready = &((SRC)->EVALUATOR(SRC_PREFIX, r_ready_i)); \ + \ + (DST)->b_resp = &((SRC)->EVALUATOR(SRC_PREFIX, b_resp_o)); \ + (DST)->b_id = &((SRC)->EVALUATOR(SRC_PREFIX, b_id_o)); \ + (DST)->b_user = &((SRC)->EVALUATOR(SRC_PREFIX, b_user_o)); \ + (DST)->b_valid = &((SRC)->EVALUATOR(SRC_PREFIX, b_valid_o)); \ + (DST)->b_ready = &((SRC)->EVALUATOR(SRC_PREFIX, b_ready_i)); \ + } + + +#define AXI_SLAVE_PORT_ASSIGN(SRC, SRC_PREFIX, DST) \ + { \ + (DST)->aw_addr = &((SRC)->EVALUATOR(SRC_PREFIX, aw_addr_o)); \ + (DST)->aw_prot = &((SRC)->EVALUATOR(SRC_PREFIX, aw_prot_o)); \ + (DST)->aw_region = &((SRC)->EVALUATOR(SRC_PREFIX, aw_region_o)); \ + (DST)->aw_len = &((SRC)->EVALUATOR(SRC_PREFIX, aw_len_o)); \ + (DST)->aw_size = &((SRC)->EVALUATOR(SRC_PREFIX, aw_size_o)); \ + (DST)->aw_burst = &((SRC)->EVALUATOR(SRC_PREFIX, aw_burst_o)); \ + (DST)->aw_lock = &((SRC)->EVALUATOR(SRC_PREFIX, aw_lock_o)); \ + (DST)->aw_atop = &((SRC)->EVALUATOR(SRC_PREFIX, aw_atop_o)); \ + (DST)->aw_cache = &((SRC)->EVALUATOR(SRC_PREFIX, aw_cache_o)); \ + (DST)->aw_qos = &((SRC)->EVALUATOR(SRC_PREFIX, aw_qos_o)); \ + (DST)->aw_id = &((SRC)->EVALUATOR(SRC_PREFIX, aw_id_o)); \ + (DST)->aw_user = &((SRC)->EVALUATOR(SRC_PREFIX, aw_user_o)); \ + (DST)->aw_valid = &((SRC)->EVALUATOR(SRC_PREFIX, aw_valid_o)); \ + (DST)->aw_ready = &((SRC)->EVALUATOR(SRC_PREFIX, aw_ready_i)); \ + \ + (DST)->ar_addr = &((SRC)->EVALUATOR(SRC_PREFIX, ar_addr_o)); \ + (DST)->ar_prot = &((SRC)->EVALUATOR(SRC_PREFIX, ar_prot_o)); \ + (DST)->ar_region = &((SRC)->EVALUATOR(SRC_PREFIX, ar_region_o)); \ + (DST)->ar_len = &((SRC)->EVALUATOR(SRC_PREFIX, ar_len_o)); \ + (DST)->ar_size = &((SRC)->EVALUATOR(SRC_PREFIX, ar_size_o)); \ + (DST)->ar_burst = &((SRC)->EVALUATOR(SRC_PREFIX, ar_burst_o)); \ + (DST)->ar_lock = &((SRC)->EVALUATOR(SRC_PREFIX, ar_lock_o)); \ + (DST)->ar_cache = &((SRC)->EVALUATOR(SRC_PREFIX, ar_cache_o)); \ + (DST)->ar_qos = &((SRC)->EVALUATOR(SRC_PREFIX, ar_qos_o)); \ + (DST)->ar_id = &((SRC)->EVALUATOR(SRC_PREFIX, ar_id_o)); \ + (DST)->ar_user = &((SRC)->EVALUATOR(SRC_PREFIX, ar_user_o)); \ + (DST)->ar_valid = &((SRC)->EVALUATOR(SRC_PREFIX, ar_valid_o)); \ + (DST)->ar_ready = &((SRC)->EVALUATOR(SRC_PREFIX, ar_ready_i)); \ + \ + (DST)->w_data = (uint8_t *)&((SRC)->EVALUATOR(SRC_PREFIX, w_data_o)); \ + (DST)->w_strb = &((SRC)->EVALUATOR(SRC_PREFIX, w_strb_o)); \ + (DST)->w_user = &((SRC)->EVALUATOR(SRC_PREFIX, w_user_o)); \ + (DST)->w_last = &((SRC)->EVALUATOR(SRC_PREFIX, w_last_o)); \ + (DST)->w_valid = &((SRC)->EVALUATOR(SRC_PREFIX, w_valid_o)); \ + (DST)->w_ready = &((SRC)->EVALUATOR(SRC_PREFIX, w_ready_i)); \ + \ + (DST)->r_data = (uint8_t *)&((SRC)->EVALUATOR(SRC_PREFIX, r_data_i)); \ + (DST)->r_resp = &((SRC)->EVALUATOR(SRC_PREFIX, r_resp_i)); \ + (DST)->r_last = &((SRC)->EVALUATOR(SRC_PREFIX, r_last_i)); \ + (DST)->r_id = &((SRC)->EVALUATOR(SRC_PREFIX, r_id_i)); \ + (DST)->r_user = &((SRC)->EVALUATOR(SRC_PREFIX, r_user_i)); \ + (DST)->r_valid = &((SRC)->EVALUATOR(SRC_PREFIX, r_valid_i)); \ + (DST)->r_ready = &((SRC)->EVALUATOR(SRC_PREFIX, r_ready_o)); \ + \ + (DST)->b_resp = &((SRC)->EVALUATOR(SRC_PREFIX, b_resp_i)); \ + (DST)->b_id = &((SRC)->EVALUATOR(SRC_PREFIX, b_id_i)); \ + (DST)->b_user = &((SRC)->EVALUATOR(SRC_PREFIX, b_user_i)); \ + (DST)->b_valid = &((SRC)->EVALUATOR(SRC_PREFIX, b_valid_i)); \ + (DST)->b_ready = &((SRC)->EVALUATOR(SRC_PREFIX, b_ready_o)); \ + } + +#define AXI_BURST_FIXED 0 +#define AXI_BURST_INCR 1 +#define AXI_BURST_WRAP 2 + +#define AXI_RESP_OKAY 0 +#define AXI_RESP_EXOKAY 1 +#define AXI_RESP_SLVERR 2 +#define AXI_RESP_DECERR 3 + +// data width +#define AXI_DW 512 + +// strobe width = number of bytes in beat +#define AXI_SW (AXI_DW / 8) + + +namespace PsPIN { + +template +class AXIPort +{ +public: + typedef AW_T axi_addr_t; + typedef STRB_T axi_strb_t; + typedef uint8_t axi_prot_t; + typedef uint8_t axi_region_t; + typedef uint8_t axi_len_t; + typedef uint8_t axi_size_t; + typedef uint8_t axi_burst_t; + typedef uint8_t axi_lock_t; + typedef uint8_t axi_atop_t; + typedef uint8_t axi_cache_t; + typedef uint8_t axi_qos_t; + typedef uint8_t axi_id_t; + typedef uint8_t axi_user_t; + +public: + axi_addr_t *aw_addr; + axi_prot_t *aw_prot; + axi_region_t *aw_region; + axi_len_t *aw_len; + axi_size_t *aw_size; + axi_burst_t *aw_burst; + axi_lock_t *aw_lock; + axi_atop_t *aw_atop; + axi_cache_t *aw_cache; + axi_qos_t *aw_qos; + axi_id_t *aw_id; + axi_user_t *aw_user; + uint8_t *aw_valid; + uint8_t *aw_ready; + + axi_addr_t *ar_addr; + axi_prot_t *ar_prot; + axi_region_t *ar_region; + axi_len_t *ar_len; + axi_size_t *ar_size; + axi_burst_t *ar_burst; + axi_lock_t *ar_lock; + axi_cache_t *ar_cache; + axi_qos_t *ar_qos; + axi_id_t *ar_id; + axi_user_t *ar_user; + uint8_t *ar_valid; + uint8_t *ar_ready; + + uint8_t *w_data; + axi_strb_t *w_strb; + axi_user_t *w_user; + uint8_t *w_last; + uint8_t *w_valid; + uint8_t *w_ready; + + uint8_t *r_data; + uint8_t *r_resp; + uint8_t *r_last; + axi_id_t *r_id; + axi_user_t *r_user; + uint8_t *r_valid; + uint8_t *r_ready; + + uint8_t *b_resp; + axi_id_t *b_id; + axi_user_t *b_user; + uint8_t *b_valid; + uint8_t *b_ready; +}; + +} \ No newline at end of file diff --git a/hw/verilator_model/src/AXISlave.hpp b/hw/verilator_model/src/AXISlave.hpp new file mode 100644 index 0000000..1d08dd8 --- /dev/null +++ b/hw/verilator_model/src/AXISlave.hpp @@ -0,0 +1,404 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIDriver.hpp" + +namespace PsPIN +{ + + template + class AXISlave : public AXIDriver + { + using typename AXIDriver::axi_ax_beat_t; + using typename AXIDriver::axi_b_beat_t; + using typename AXIDriver::axi_r_beat_t; + using typename AXIDriver::axi_w_beat_t; + + using AXIDriver::port; + using AXIDriver::create_ax_beats; + using AXIDriver::beat_lower_byte; + using AXIDriver::beat_upper_byte; + + typedef typename AXIPortType::axi_addr_t axi_addr_t; + + public: + typedef struct r_beat_request + { + axi_addr_t addr; + uint32_t data_size; + axi_r_beat_t r_beat; + } r_beat_request_t; + + typedef struct w_beat_request + { + axi_addr_t addr; + uint32_t data_size; + axi_w_beat_t w_beat; + } w_beat_request_t; + + private: + uint32_t aw_beats_buffer_size; + uint32_t ar_beats_buffer_size; + uint32_t w_beats_buffer_size; + uint32_t r_beats_buffer_size; + uint32_t b_beats_buffer_size; + + std::queue aw_beats; + std::queue ar_beats; + std::queue b_beats; + std::queue r_beats; + + std::queue aw_pending_resp; + std::queue w_beat_requests; + + private: + bool r_wait; + bool b_wait; + + public: + AXISlave(AXIPortType &port) + : AXIDriver(port) + { + r_wait = 0; + b_wait = 0; + + *port.ar_ready = 0; + *port.aw_ready = 0; + *port.w_ready = 0; + *port.r_valid = 0; + *port.b_valid = 0; + + aw_beats_buffer_size = 0; + ar_beats_buffer_size = 0; + w_beats_buffer_size = 0; + r_beats_buffer_size = 0; + b_beats_buffer_size = 0; + } + + void set_aw_buffer(uint32_t aw_buffer_size) + { + aw_beats_buffer_size = aw_buffer_size; + } + + void set_ar_buffer(uint32_t ar_buffer_size) + { + ar_beats_buffer_size = ar_buffer_size; + } + + void set_w_buffer(uint32_t w_buffer_size) + { + w_beats_buffer_size = w_buffer_size; + } + + void set_r_buffer(uint32_t r_buffer_size) + { + r_beats_buffer_size = r_buffer_size; + } + + void set_b_buffer(uint32_t b_buffer_size) + { + b_beats_buffer_size = b_buffer_size; + } + + void posedge() + { + aw_posedge(); + ar_posedge(); + w_posedge(); + r_posedge(); + b_posedge(); + } + + void negedge() + { + aw_negedge(); + ar_negedge(); + w_negedge(); + r_negedge(); + b_negedge(); + } + + bool can_send_r_beat() + { + return r_beats_buffer_size == 0 || r_beats.size() < r_beats_buffer_size; + } + + void send_r_beat(axi_r_beat_t beat) + { + assert(can_send_r_beat()); + r_beats.push(beat); + } + + bool can_send_b_beat() + { + return b_beats_buffer_size == 0 || b_beats.size() < b_beats_buffer_size; + } + + void send_b_beat() + { + assert(!aw_pending_resp.empty()); + assert(can_send_b_beat()); + axi_ax_beat_t &aw = aw_pending_resp.front(); + + // prepare B beat + axi_b_beat_t b; + b.b_resp = AXI_RESP_OKAY; + b.b_id = aw.ax_id; + b.b_user = aw.ax_user; + b_beats.push(b); + + aw_pending_resp.pop(); + } + + bool has_w_beat() + { + return !w_beat_requests.empty(); + } + + w_beat_request_t get_next_w_beat() + { + assert(has_w_beat()); + w_beat_request_t w = w_beat_requests.front(); + w_beat_requests.pop(); + return w; + } + + bool has_r_beat() + { + return !ar_beats.empty(); + } + + r_beat_request_t get_next_r_beat() + { + assert(has_r_beat()); + + axi_ax_beat_t &ar = ar_beats.front(); + uint32_t data_size = pow(2, ar.ax_size); + + bool is_last = ar.ax_len == 0; + //printf("AXISlave AR beat ax_len: %u; is_last: %u\n", (uint32_t) ar.ax_len, (uint32_t) is_last); + r_beat_request_t req; + req.addr = ar.ax_addr; + req.data_size = data_size; + + req.r_beat.r_resp = AXI_RESP_OKAY; + req.r_beat.r_last = is_last; + req.r_beat.r_id = ar.ax_id; + req.r_beat.r_user = ar.ax_user; + + // AXI_BURST_WRAP is not implemented + assert(ar.ax_burst == AXI_BURST_FIXED || ar.ax_burst == AXI_BURST_INCR); + if (ar.ax_burst == AXI_BURST_INCR) + { + ar.ax_addr += data_size; + } + + //ax_len = n_beats + 1; + if (is_last) + { + ar_beats.pop(); + } + else + { + ar.ax_len--; + } + + return req; + } + + private: + void aw_posedge() + { + *port.aw_ready = 0; + + bool can_accept_aw = aw_beats_buffer_size == 0 || aw_beats.size() < aw_beats_buffer_size; + if (*port.aw_valid && can_accept_aw) + { + axi_ax_beat_t aw_beat; + + aw_beat.ax_addr = *port.aw_addr; + aw_beat.ax_atop = *port.aw_atop; + aw_beat.ax_burst = *port.aw_burst; + aw_beat.ax_cache = *port.aw_cache; + aw_beat.ax_id = *port.aw_id; + aw_beat.ax_len = *port.aw_len; + aw_beat.ax_lock = *port.aw_lock; + aw_beat.ax_prot = *port.aw_prot; + aw_beat.ax_qos = *port.aw_qos; + aw_beat.ax_region = *port.aw_region; + aw_beat.ax_size = *port.aw_size; + aw_beat.ax_user = *port.aw_user; + aw_beat.offset = 0; + + aw_beats.push(aw_beat); + + *port.aw_ready = 1; + } + } + + void aw_negedge() + { + // Nothing to do here + } + + void ar_posedge() + { + *port.ar_ready = 0; + + bool can_accept_ar = ar_beats_buffer_size == 0 || ar_beats.size() < ar_beats_buffer_size; + if (*port.ar_valid && can_accept_ar) + { + axi_ax_beat_t ar_beat; + + ar_beat.ax_addr = *port.ar_addr; + ar_beat.ax_burst = *port.ar_burst; + ar_beat.ax_cache = *port.ar_cache; + ar_beat.ax_id = *port.ar_id; + ar_beat.ax_len = *port.ar_len; + ar_beat.ax_lock = *port.ar_lock; + ar_beat.ax_prot = *port.ar_prot; + ar_beat.ax_qos = *port.ar_qos; + ar_beat.ax_region = *port.ar_region; + ar_beat.ax_size = *port.ar_size; + ar_beat.ax_user = *port.ar_user; + + ar_beat.offset = 0; + + ar_beats.push(ar_beat); + + *port.ar_ready = 1; + } + } + + void ar_negedge() + { + // Nothing to do here + } + + void w_posedge() + { + *port.w_ready = 0; + + bool can_accept_w = w_beats_buffer_size == 0 || w_beat_requests.size() < w_beats_buffer_size; + if (*port.w_valid && can_accept_w) + { + assert(!aw_beats.empty()); + axi_ax_beat_t &aw = aw_beats.front(); + unsigned int strb_low = (unsigned int) ((*port.w_strb)); + unsigned int strb_high = (unsigned int) ((*port.w_strb) >> 32); + uint32_t data_size = __builtin_popcount(strb_low) + __builtin_popcount(strb_high); + + w_beat_request_t req; + req.addr = aw.ax_addr + aw.offset; + req.data_size = data_size; + req.w_beat.w_strb = *port.w_strb; + req.w_beat.w_user = *port.w_user; + req.w_beat.w_last = *port.w_last; + + aw.offset += data_size; + + memcpy(req.w_beat.w_data, port.w_data, AXI_SW); + + w_beat_requests.push(req); + + if (*port.w_last == 1) + { + aw_pending_resp.push(aw); + aw_beats.pop(); + } + + *port.w_ready = 1; + } + } + + void w_negedge() + { + // Nothing to do here + } + + void r_posedge() + { + if (r_wait) + { + return; + } + + *port.r_valid = 0; + + if (r_beats.empty()) + { + return; + } + + axi_r_beat_t &r = r_beats.front(); + + + *port.r_resp = r.r_resp; + *port.r_last = r.r_last; + *port.r_id = r.r_id; + *port.r_user = r.r_user; + memcpy(port.r_data, r.r_data, AXI_SW); + + *port.r_valid = 1; + r_beats.pop(); + } + + void r_negedge() + { + //R_READY can be function of R_VALID, so let's see if we have it set already + r_wait = false; + if (*port.r_valid && !(*port.r_ready)) + { + r_wait = true; + } + } + + void b_posedge() + { + if (b_wait) + { + return; + } + + *port.b_valid = 0; + + if (b_beats.empty()) + { + return; + } + + axi_b_beat_t &b = b_beats.front(); + + *port.b_resp = b.b_resp; + *port.b_id = b.b_id; + *port.b_user = b.b_user; + b_beats.pop(); + + *port.b_valid = 1; + } + + void b_negedge() + { + //B_READY can be function of B_VALID, so let's see if we have it set already + b_wait = false; + if (*port.b_valid && !(*port.b_ready)) + { + b_wait = true; + } + } + }; + +} // namespace PsPIN \ No newline at end of file diff --git a/hw/verilator_model/src/NICInbound.hpp b/hw/verilator_model/src/NICInbound.hpp new file mode 100644 index 0000000..c88aa06 --- /dev/null +++ b/hw/verilator_model/src/NICInbound.hpp @@ -0,0 +1,549 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIPort.hpp" +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "SimModule.hpp" +#include "AXIMaster.hpp" +#include "pspin.hpp" +#include "spin.h" +#include "pspinsim.h" + +#include +#include +#include +#include + +#define NI_PKT_ADDR_ALIGNMENT 64 + +namespace PsPIN +{ + + template + class NICInbound : public SimModule + { + typedef typename AXIPortType::axi_addr_t axi_addr_t; + + typedef struct incoming_her + { + her_descr_t her; + std::vector pkt_data; + size_t pkt_len; + uint32_t wait_cycles; + } incoming_her_t; + + public: + ni_control_port_t &ni_ctrl; + + public: + typedef std::function pkt_feedback_cb_t; + + private: + AXIMaster axi_driver; + axi_addr_t l2_pkt_buff_start; + uint32_t l2_pkt_buff_size; + uint32_t hers_to_send; + + //HERs that are coming from the network (virtual delay applied) + std::queue incoming_hers; + + //HERs that have been read and for which a DMA write is in flight + std::queue queued_hers; + + //HERs that are ready to be sent to PsPIN (DMA completed) + std::queue ready_hers; + + uint32_t packet_wait_cycles; + + FILE *pkt_file; + FILE *data_file; + uint64_t head_ptr, tail_ptr, cut_ptr; + bool cut; + uint32_t in_flight_packets; + std::unordered_map free_req_queue; + + bool her_cmd_wait; + + bool app_sent_eos; + + pkt_feedback_cb_t feedback_cb; + + //Statistics + private: + typedef struct pktentry + { + uint64_t nic_arrival_time; + uint64_t pspin_arrival_time; + uint32_t size; + uint64_t user_ptr; + } pktentry_t; + + uint32_t total_bytes_sent; + uint32_t total_pkts; + + uint64_t time_last_feedback; + uint64_t time_first_feedback; + uint32_t total_feedbacks; + uint32_t ni_ctrl_stalls; + + uint32_t sum_pkt_latency; + uint32_t min_pkt_latency; + uint32_t max_pkt_latency; + + std::unordered_map pktmap; + + public: + NICInbound(AXIPortType &ni_mst, ni_control_port_t &ni_ctrl, axi_addr_t l2_pkt_buff_start, uint32_t l2_pkt_buff_size) + : axi_driver(ni_mst), ni_ctrl(ni_ctrl), l2_pkt_buff_start(l2_pkt_buff_start), l2_pkt_buff_size(l2_pkt_buff_size) + { + *ni_ctrl.her_valid_o = 0; + *ni_ctrl.eos_o = 0; + + // Accept feedbacks + *ni_ctrl.feedback_ready_o = 1; + + packet_wait_cycles = 0; + + pkt_file = NULL; + data_file = NULL; + + app_sent_eos = false; + + head_ptr = 0; + tail_ptr = 0; + cut_ptr = 0; + cut = false; + in_flight_packets = 0; + + //printf("sizeof(her_descr_t): %lu\n", sizeof(her_descr_t)); + + total_bytes_sent = 0; + total_pkts = 0; + time_last_feedback = 0; + time_first_feedback = 0; + total_feedbacks = 0; + sum_pkt_latency = 0; + min_pkt_latency = 0; + max_pkt_latency = 0; + ni_ctrl_stalls = 0; + + hers_to_send = 0; + + her_cmd_wait = false; + } + + ~NICInbound() + { + if (data_file != NULL) + fclose(data_file); + if (pkt_file != NULL) + fclose(pkt_file); + } + + void set_feedback_cb(pkt_feedback_cb_t cb) + { + this->feedback_cb = cb; + } + + void set_eos() + { + app_sent_eos = true; + } + + int add_packet(her_descr_t &her, uint8_t *pkt_data, size_t pkt_len, uint32_t wait_cycles) + { + incoming_her_t ih; + ih.her = her; + ih.pkt_data.resize(pkt_len); + memcpy(&(ih.pkt_data[0]), pkt_data, pkt_len); + ih.pkt_len = pkt_len; + ih.wait_cycles = wait_cycles; + + incoming_hers.push(ih); + hers_to_send++; + + return SPIN_SUCCESS; + } + + int read_trace(const char *pkt_filename, const char *data_filename) + { + // Note: this can be optimized if the packet trace becomes too big + FILE *pkt_file = fopen(pkt_filename, "r"); + if (pkt_file == NULL) + { + printf("Task file not found!\n"); + return SPIN_ERR; + } + + FILE *data_file = fopen(data_filename, "rb"); + if (data_file == NULL) + { + printf("Data file not found!\n"); + return SPIN_ERR; + } + + while (!feof(pkt_file)) + { + uint32_t msgid, hh_addr, hh_size, ph_addr, ph_size, th_addr, th_size, hmem_addr, hmem_size, pkt_size, pkt_xfer_size, eom, wait_cycles; + int code = fscanf(pkt_file, "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", &msgid, &hh_addr, &hh_size, &ph_addr, &ph_size, &th_addr, &th_size, &hmem_addr, &hmem_size, &pkt_size, &pkt_xfer_size, &eom, &wait_cycles); + assert(code == 13); + + uint8_t *pkt_data = new uint8_t[pkt_size]; + code = fread(&(pkt_data[0]), sizeof(uint8_t), pkt_size, data_file); + assert(code == pkt_size); + + her_descr_t her_descr; + + // prepare handler execution request (HER) + her_descr.mpq_meta.hh_addr = hh_addr; + her_descr.mpq_meta.hh_size = hh_size; + + her_descr.mpq_meta.ph_addr = ph_addr; + her_descr.mpq_meta.ph_size = ph_size; + + her_descr.mpq_meta.th_addr = th_addr; + her_descr.mpq_meta.th_size = th_size; + + her_descr.mpq_meta.handler_mem_addr = hmem_addr; + her_descr.mpq_meta.handler_mem_size = hmem_size; + + her_descr.mpq_meta.host_mem_addr = PCIE_START_ADDR; + her_descr.mpq_meta.host_mem_size = 0x40000000; + + for (int i = 0; i < NUM_CLUSTERS; i++) + { + her_descr.mpq_meta.scratchpad_addr[i] = 0; + her_descr.mpq_meta.scratchpad_size[i] = L1_SCRATCHPAD_SIZE; + } + + her_descr.msgid = msgid; + her_descr.her_addr = 0x0; //will be set later + her_descr.her_size = pkt_size; + her_descr.xfer_size = pkt_xfer_size; + her_descr.eom = (eom == 1); + + add_packet(her_descr, pkt_data, pkt_size, wait_cycles); + } + fclose(data_file); + fclose(pkt_file); + + return SPIN_SUCCESS; + } + + bool allocate_pkt_space(uint32_t pkt_size, axi_addr_t *addr) + { + bool can_allocate = false; + + uint32_t segments = (pkt_size + NI_PKT_ADDR_ALIGNMENT - 1) / NI_PKT_ADDR_ALIGNMENT; + pkt_size = segments * NI_PKT_ADDR_ALIGNMENT; + + if (tail_ptr > head_ptr || (tail_ptr == head_ptr && in_flight_packets == 0)) + { + if (l2_pkt_buff_size - tail_ptr >= pkt_size) + { + can_allocate = true; + } + else if (head_ptr >= pkt_size) + { + cut_ptr = tail_ptr; + cut = true; + tail_ptr = 0; + can_allocate = true; + } + } + else if (head_ptr > tail_ptr) + { + if (head_ptr - tail_ptr >= pkt_size) + { + can_allocate = true; + } + } + + if (can_allocate) + { + *addr = l2_pkt_buff_start + tail_ptr; + tail_ptr += pkt_size; + in_flight_packets++; + SIM_PRINT("NIC inbound engine: allocated %u bytes; head_ptr: %lu; tail_ptr: %lu; in_flight_packets: %lu\n", pkt_size, head_ptr, tail_ptr, in_flight_packets); + } + else{ + SIM_PRINT("NIC inbound engine: allocation failed! bytes: %u; head_ptr: %lu; tail_ptr: %lu; in_flight_packets: %lu\n", pkt_size, head_ptr, tail_ptr, in_flight_packets); + } + + return can_allocate; + } + + void free_pkt_space(axi_addr_t addr, uint32_t size) + { + uint32_t offset = addr - l2_pkt_buff_start; + assert(addr >= l2_pkt_buff_start); + + uint32_t segments = (size + NI_PKT_ADDR_ALIGNMENT - 1) / NI_PKT_ADDR_ALIGNMENT; + size = segments * NI_PKT_ADDR_ALIGNMENT; + + assert(free_req_queue.find(offset) == free_req_queue.end()); + free_req_queue[offset] = size; + + while (!free_req_queue.empty() && free_req_queue.find(head_ptr) != free_req_queue.end()) + { + uint32_t head_ptr_increase = free_req_queue[head_ptr]; + free_req_queue.erase(head_ptr); + + head_ptr += head_ptr_increase; + in_flight_packets--; + SIM_PRINT("NIC inbound engine: freeing %u bytes; head_ptr: %lu; tail_ptr: %lu; in_flight_packets: %lu; cut: %u; cut_ptr: %lu\n", head_ptr_increase, head_ptr, tail_ptr, in_flight_packets, (uint32_t) cut, cut_ptr); + + if (cut && head_ptr == cut_ptr) + { + head_ptr = 0; + cut = false; + SIM_PRINT("NIC inbound engine: resetting head_ptr! cut_ptr: %lu;\n", cut_ptr); + } + } + } + + bool process_packet(her_descr_t &her_descr, uint8_t *pkt_data, uint32_t pkt_size) + { + axi_addr_t pkt_addr; + if (!allocate_pkt_space(pkt_size, &pkt_addr)) + { + return false; + } + + axi_driver.write(pkt_addr, pkt_data, pkt_size, 0); + + her_descr.her_addr = pkt_addr; + her_descr.nic_arrival_time = sim_time(); + + queued_hers.push(her_descr); + + return true; + } + + void progress_incoming_packets() + { + if (incoming_hers.empty()) + return; + + if (packet_wait_cycles > 0) + { + packet_wait_cycles--; + if (packet_wait_cycles > 0) + return; + } + + incoming_her_t &ih = incoming_hers.front(); + + if (process_packet(ih.her, &(ih.pkt_data[0]), ih.pkt_len)) + { + // we won't serve the next packet before wait_cycles; + packet_wait_cycles = ih.wait_cycles; + + incoming_hers.pop(); + } + else + { + //the packet is here and we cannot push it to PsPIN because of no space in L2; + //still spending "wait" cycles. + ih.wait_cycles = (ih.wait_cycles > 0) ? ih.wait_cycles-- : 0; + } + } + + void posedge() + { + if (*ni_ctrl.pspin_active_i) + { + progress_axi_writes(); + axi_driver.posedge(); + progress_axi_write_responses(); + progress_incoming_packets(); + her_progress_posedge(); + feedback_progress(); + } + } + + void negedge() + { + axi_driver.negedge(); + her_progress_negedge(); + } + + private: + // Progress HERs + void her_progress_posedge() + { + if (her_cmd_wait) + { + ni_ctrl_stalls++; + return; + } + + *ni_ctrl.her_valid_o = 0; + + if (ready_hers.empty()) + { + return; + } + + her_descr_t her = ready_hers.front(); + + *ni_ctrl.her_o.msgid = her.msgid; + *ni_ctrl.her_o.eom = her.eom; + *ni_ctrl.her_o.her_addr = her.her_addr; + *ni_ctrl.her_o.her_size = her.her_size; + *ni_ctrl.her_o.xfer_size = her.xfer_size; + *ni_ctrl.her_o.mpq_meta.handler_mem_addr = her.mpq_meta.handler_mem_addr; + *ni_ctrl.her_o.mpq_meta.handler_mem_size = her.mpq_meta.handler_mem_size; + *ni_ctrl.her_o.mpq_meta.host_mem_addr = her.mpq_meta.host_mem_addr; + *ni_ctrl.her_o.mpq_meta.host_mem_size = her.mpq_meta.host_mem_size; + *ni_ctrl.her_o.mpq_meta.hh_addr = her.mpq_meta.hh_addr; + *ni_ctrl.her_o.mpq_meta.hh_size = her.mpq_meta.hh_size; + *ni_ctrl.her_o.mpq_meta.ph_addr = her.mpq_meta.ph_addr; + *ni_ctrl.her_o.mpq_meta.ph_size = her.mpq_meta.ph_size; + *ni_ctrl.her_o.mpq_meta.th_addr = her.mpq_meta.th_addr; + *ni_ctrl.her_o.mpq_meta.th_size = her.mpq_meta.th_size; + *ni_ctrl.her_o.mpq_meta.scratchpad_addr[0] = her.mpq_meta.scratchpad_addr[0]; + *ni_ctrl.her_o.mpq_meta.scratchpad_addr[1] = her.mpq_meta.scratchpad_addr[1]; + *ni_ctrl.her_o.mpq_meta.scratchpad_addr[2] = her.mpq_meta.scratchpad_addr[2]; + *ni_ctrl.her_o.mpq_meta.scratchpad_addr[3] = her.mpq_meta.scratchpad_addr[3]; + *ni_ctrl.her_o.mpq_meta.scratchpad_size[0] = her.mpq_meta.scratchpad_size[0]; + *ni_ctrl.her_o.mpq_meta.scratchpad_size[1] = her.mpq_meta.scratchpad_size[1]; + *ni_ctrl.her_o.mpq_meta.scratchpad_size[2] = her.mpq_meta.scratchpad_size[2]; + *ni_ctrl.her_o.mpq_meta.scratchpad_size[3] = her.mpq_meta.scratchpad_size[3]; + + *ni_ctrl.her_valid_o = 1; + + hers_to_send--; + + ready_hers.pop(); + + SIM_PRINT("HER sent (0x%x)\n", *ni_ctrl.her_o.her_addr); + + pktentry_t pktentry; + pktentry.pspin_arrival_time = sim_time(); + pktentry.nic_arrival_time = her.nic_arrival_time; + pktentry.size = her.her_size; + pktentry.user_ptr = her.user_ptr; + + assert(pktmap.find(*ni_ctrl.her_o.her_addr) == pktmap.end()); + pktmap[*ni_ctrl.her_o.her_addr] = pktentry; + + //stats + total_bytes_sent += her.her_size; + total_pkts++; + + if (hers_to_send == 0 && app_sent_eos) + { + *ni_ctrl.eos_o = 1; + } + } + + void her_progress_negedge() + { + her_cmd_wait = false; + if (*ni_ctrl.her_valid_o && !(*ni_ctrl.her_ready_i)) + { + her_cmd_wait = true; + } + } + + // Get feedback + void feedback_progress() + { + if (*ni_ctrl.feedback_ready_o && *ni_ctrl.feedback_valid_i) + { + assert(pktmap.find(*ni_ctrl.feedback_her_addr_i) != pktmap.end()); + pktentry_t pktentry = pktmap[*ni_ctrl.feedback_her_addr_i]; + uint32_t latency = sim_time() - pktentry.nic_arrival_time; + + SIM_PRINT("INFO FEEDBACK 0x%x %u %u\n", *ni_ctrl.feedback_her_addr_i, latency, pktentry.size); + + assert(*ni_ctrl.feedback_her_size_i == pktentry.size); + free_pkt_space(*ni_ctrl.feedback_her_addr_i, *ni_ctrl.feedback_her_size_i); + + sum_pkt_latency += latency; + + if (feedback_cb) + feedback_cb(pktentry.user_ptr, pktentry.nic_arrival_time, pktentry.pspin_arrival_time, sim_time()); + + pktmap.erase(*ni_ctrl.feedback_her_addr_i); + + if (total_feedbacks == 0) + { + time_first_feedback = sim_time(); + min_pkt_latency = latency; + max_pkt_latency = latency; + } + else + { + min_pkt_latency = std::min(min_pkt_latency, latency); + max_pkt_latency = std::max(max_pkt_latency, latency); + } + + time_last_feedback = sim_time(); + + total_feedbacks++; + } + } + + void progress_axi_writes() + { + if (axi_driver.has_aw_beat() && axi_driver.can_send_aw_beat()) + { + axi_driver.send_aw_beat(); + } + + if (axi_driver.has_w_beat() && axi_driver.can_send_w_beat()) + { + axi_driver.send_w_beat(); + } + } + + void progress_axi_write_responses() + { + if (!axi_driver.has_b_beat()) + return; + + bool write_completed = axi_driver.consume_b_beat(); + + if (write_completed) + { + assert(!queued_hers.empty()); + her_descr_t her = queued_hers.front(); + queued_hers.pop(); + ready_hers.push(her); + } + } + + public: + void print_stats() + { + double avg_pkt_length = ((double)total_bytes_sent) / total_pkts; + double avg_intra_feedback = ((double)(time_last_feedback - time_first_feedback)) / (1000 * (total_feedbacks - 1)); + double avg_feedback_throughput = THROUGHPUT_1GHZ(avg_intra_feedback, avg_pkt_length); + double avg_pkt_latency = ((double)sum_pkt_latency) / (1000 * total_pkts); + + printf("NIC inbound engine:\n"); + printf("\tPackets: %d; Bytes: %d\n", total_pkts, total_bytes_sent); + printf("\tAvg packet length: %.3lf B\n", avg_pkt_length); + printf("\tFeedback throughput: %.3lf Gbit/s (feedback arrival time: %.3lf ns)\n", avg_feedback_throughput, avg_intra_feedback); + printf("\tPacket latency: avg: %.3lf ns; min: %d ns; max: %d ns\n", avg_pkt_latency, min_pkt_latency / 1000, max_pkt_latency / 1000); + printf("\tHER stalls: %d\n", ni_ctrl_stalls); + } + }; + +} // namespace PsPIN diff --git a/hw/verilator_model/src/NICOutbound.hpp b/hw/verilator_model/src/NICOutbound.hpp new file mode 100644 index 0000000..af31d30 --- /dev/null +++ b/hw/verilator_model/src/NICOutbound.hpp @@ -0,0 +1,325 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIPort.hpp" +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "SimModule.hpp" +#include "AXIMaster.hpp" +#include "pspin.hpp" + +#include +#include + +#define RDMA_HEADER_LENGTH 32 +#define NUM_PARALLEL_CMD 16 + +// The network delay is computed by slicing the packet in words +// and applying G to the number of segments. This is to +#define WORD_SIZE 64 + +namespace PsPIN +{ + template + class NICOutbound : public SimModule + { + + private: + class NetworkPacket + { + public: + uint64_t source_addr; + uint32_t current_offset; + uint32_t length; + uint32_t payload_length; + uint8_t cmd_id; + bool is_last; + std::vector data; + + NetworkPacket(uint32_t length) : length(length) + { + current_offset = 0; + data.resize(length); + } + }; + + class NICCommand + { + public: + uint64_t source_addr; + uint32_t length; + uint32_t nid; + uint32_t fid; + uint8_t cmd_id; + }; + + class Packetizer + { + private: + uint32_t num_parallel_cmds; + uint32_t max_packet_len; + std::queue commands; + + public: + Packetizer(uint32_t num_parallel_cmds, uint32_t max_packet_len) : num_parallel_cmds(num_parallel_cmds), max_packet_len(max_packet_len) + { + ; + } + + bool has_free_cmd_slot() + { + return commands.size() < num_parallel_cmds; + } + + bool has_packets() + { + return commands.size() > 0; + } + + void new_cmd(NICCommand cmd) + { + assert(commands.size() < num_parallel_cmds); + commands.push(cmd); + } + + NetworkPacket get_next_packet() + { + assert(!commands.empty()); + NICCommand cmd = commands.front(); + commands.pop(); + + uint32_t header_length = 0; + if (cmd.fid>0) { /* RDMA (can be multi packet) */ + header_length = RDMA_HEADER_LENGTH; + } else { /* single packet */ + assert(cmd.length <= max_packet_len); + } + + uint32_t payloadlen = std::min(max_packet_len - header_length, cmd.length); + uint32_t pktlen = header_length + payloadlen; + + NetworkPacket pkt(pktlen); + + pkt.cmd_id = cmd.cmd_id; + pkt.is_last = cmd.length - payloadlen == 0; + pkt.length = pktlen; + pkt.payload_length = payloadlen; + pkt.source_addr = cmd.source_addr; + + cmd.length -= payloadlen; + cmd.source_addr += payloadlen; + + //printf("generating packet: length: %d; payload: %d; new cmd length: %d; next pkt addr: 0x%lx\n", pktlen, payloadlen, cmd.length, cmd.source_addr); + + if (cmd.length>0){ + commands.push(cmd); + } + + return pkt; + } + }; + + public: + typedef std::function out_packet_cb_t; + + private: + AXIMaster axi_driver; + no_cmd_port &no_cmd; + double network_G; //ns + uint32_t max_pkt_length; + uint32_t network_buffer_size; + + uint32_t wait_cycles; + + std::queue network_queue; + + std::queue dma_pkt_in_flight; + + Packetizer packetizer; + + public: + out_packet_cb_t pktout_cb; + + //statistics + private: + uint32_t total_cmds; + uint32_t total_pkts; + uint32_t total_bytes; + uint64_t time_first_pkt; + uint64_t time_last_pkt; + + public: + NICOutbound(AXIPortType &no_mst, no_cmd_port_t &no_cmd, double network_G, uint32_t max_pkt_length, uint32_t network_buffer_size) + : axi_driver(no_mst), no_cmd(no_cmd), network_G(network_G), max_pkt_length(max_pkt_length), network_buffer_size(network_buffer_size), packetizer(NUM_PARALLEL_CMD, max_pkt_length) + { + *no_cmd.no_cmd_resp_valid_o = 0; + *no_cmd.no_cmd_req_ready_o = 0; + + wait_cycles = 0; + + total_cmds = 0; + total_pkts = 0; + total_bytes = 0; + time_first_pkt = 0; + time_last_pkt = 0; + } + + void posedge() + { + progress_axi_reads(); + axi_driver.posedge(); + progress_axi_read_responses(); + progress_netqueue(); + handle_cmd_posedge(); + progress_packets(); + } + + void negedge() + { + axi_driver.negedge(); + } + + void set_packet_out_cb(out_packet_cb_t cb) + { + this->pktout_cb = cb; + } + + private: + void handle_cmd_posedge() + { + *no_cmd.no_cmd_req_ready_o = 0; + + bool can_accept_cmd = packetizer.has_free_cmd_slot(); + + if (*no_cmd.no_cmd_req_valid_i && can_accept_cmd) + { + + NICCommand cmd; + cmd.source_addr = *no_cmd.no_cmd_req_src_addr_i; + cmd.length = *no_cmd.no_cmd_req_length_i; + cmd.nid = *no_cmd.no_cmd_req_nid_i; + cmd.fid = *no_cmd.no_cmd_req_fid_i; + cmd.cmd_id = *no_cmd.no_cmd_req_id_i; + + assert(cmd.fid>0 || cmd.length <= max_pkt_length); + + SIM_PRINT("NIC outbound got new command: source_addr: 0x%lx; length: %d; FID: %d (>0 is RDMA)\n", cmd.source_addr, cmd.length, cmd.fid); + total_cmds++; + + packetizer.new_cmd(cmd); + + *no_cmd.no_cmd_req_ready_o = 1; + } + } + + void progress_packets() + { + bool can_send_pkt = network_queue.size() + dma_pkt_in_flight.size() < network_buffer_size; + if (packetizer.has_packets() && can_send_pkt) + { + NetworkPacket pkt = packetizer.get_next_packet(); + axi_driver.read(pkt.source_addr, pkt.payload_length); + dma_pkt_in_flight.push(pkt); + } + } + + void progress_netqueue() + { + *no_cmd.no_cmd_resp_valid_o = 0; + + if (wait_cycles > 0) + { + wait_cycles--; + if (wait_cycles > 0) return; + } + + if (!network_queue.empty()) + { + NetworkPacket &pkt = network_queue.front(); + + wait_cycles = ((uint32_t)(network_G * WORD_SIZE)) * std::floor((double) pkt.length / WORD_SIZE); + + if (pkt.is_last) + { + *no_cmd.no_cmd_resp_valid_o = 1; + *no_cmd.no_cmd_resp_id_o = pkt.cmd_id; + } + + // TODO: packet is ready. This is the point where we can do something with it. + + if (pktout_cb) pktout_cb((uint8_t*) &(pkt.data[0]), pkt.length); + + SIM_PRINT("packet sent; size: %d; wait_cycles: %d (G: %lf); is_last: %d\n", pkt.length, wait_cycles, network_G, (uint32_t) pkt.is_last); + + if (total_pkts==0) time_first_pkt = sim_time(); + time_last_pkt = sim_time(); + total_pkts++; + total_bytes += pkt.length; + + network_queue.pop(); + + } + } + + void progress_axi_reads() + { + if (axi_driver.has_ar_beat() && axi_driver.can_send_ar_beat()) + { + axi_driver.send_ar_beat(); + } + } + + void progress_axi_read_responses() + { + + if (axi_driver.has_r_beat()) + { + bool read_complete; + uint32_t length = AXI_SW; + + assert(!dma_pkt_in_flight.empty()); + NetworkPacket &pkt = dma_pkt_in_flight.front(); + + uint8_t *dest_ptr = ((uint8_t *)&(pkt.data[0])) + pkt.current_offset; + read_complete = axi_driver.consume_r_beat(dest_ptr, length); + + pkt.current_offset += length; + + if (read_complete) + { + //printf("pkt.current_offset: %d; pkt.length: %d\n", pkt.current_offset, pkt.length); + assert(pkt.current_offset == pkt.payload_length); + network_queue.push(pkt); + dma_pkt_in_flight.pop(); + } + } + } + + public: + void print_stats() + { + double avg_pkt_length = ((double) total_bytes) / total_pkts; + double avg_intra_pkt = ((double) (time_last_pkt - time_first_pkt)) / (1000*(total_pkts-1)); + double avg_pkt_throughput = THROUGHPUT_1GHZ(avg_intra_pkt, avg_pkt_length); + + printf("NIC outbound engine:\n"); + printf("\tCommands: %d; Packets: %d; Bytes: %d\n", total_cmds, total_pkts, total_bytes); + printf("\tAvg packet length: %.3lf B\n", avg_pkt_length); + printf("\tPacket throughput: %.3lf Gbit/s (pkt departure time: %.3lf ns)\n", avg_pkt_throughput, avg_intra_pkt); + } + }; + +} // namespace PsPIN \ No newline at end of file diff --git a/hw/verilator_model/src/PCIe.hpp b/hw/verilator_model/src/PCIe.hpp new file mode 100644 index 0000000..d940e24 --- /dev/null +++ b/hw/verilator_model/src/PCIe.hpp @@ -0,0 +1,251 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIPort.hpp" +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "SimModule.hpp" +#include "AXIMaster.hpp" +#include "AXISlave.hpp" +#include "pspin.hpp" + +#include +#include + +namespace PsPIN +{ + using std::placeholders::_1; + + template + class PCIe : public SimModule + { + + typedef typename AXISlave::w_beat_request_t w_beat_request_t; + typedef typename AXISlave::r_beat_request_t r_beat_request_t; + + private: + typedef struct pcie_write + { + w_beat_request_t req; + uint64_t time; + } pcie_write_t; + + typedef struct pcie_read + { + r_beat_request_t req; + uint64_t time; + } pcie_read_t; + + private: + AXIMaster axi_driver_mst; + AXISlave axi_driver_slv; + + uint32_t pcie_L; + double pcie_G; + + uint32_t write_wait_cycles; + uint32_t read_wait_cycles; + + std::queue in_flight_write_requests; + std::queue in_flight_read_requests; + + public: + typedef std::function slv_write_cb_t; + typedef std::function slv_read_cb_t; + + // Statistics + private: + uint32_t bytes_written; + uint32_t bytes_read; + uint64_t time_first_read; + uint64_t time_last_write; + uint64_t time_first_write; + uint64_t time_last_read; + uint32_t num_reads; + uint32_t num_writes; + + slv_write_cb_t slv_write_cb; + slv_read_cb_t slv_read_cb; + + public: + PCIe(AXIMstPortType &axi_mst, AXISlvPortType &axi_slv, uint32_t aw_buffer_size, uint32_t w_buffer_size, uint32_t ar_buffer_size, uint32_t r_buffer_size, uint32_t b_buffer_size, uint32_t pcie_L, uint32_t pcie_G) + : axi_driver_mst(axi_mst), axi_driver_slv(axi_slv), pcie_L(pcie_L), pcie_G(pcie_G) + { + write_wait_cycles = 0; + read_wait_cycles = 0; + + axi_driver_slv.set_ar_buffer(ar_buffer_size); + axi_driver_slv.set_aw_buffer(aw_buffer_size); + axi_driver_slv.set_w_buffer(w_buffer_size); + axi_driver_slv.set_r_buffer(r_buffer_size); + axi_driver_slv.set_b_buffer(b_buffer_size); + + bytes_written = 0; + bytes_read = 0; + time_first_read = 0; + time_last_write = 0; + time_first_write = 0; + time_last_read = 0; + num_reads = 0; + num_writes = 0; + } + + void set_slv_write_cb(slv_write_cb_t cb) + { + this->slv_write_cb = cb; + } + + void set_slv_read_cb(slv_read_cb_t cb) + { + this->slv_read_cb = cb; + } + + private: + + void progress_new_writes() + { + if (write_wait_cycles > 0) { + write_wait_cycles--; + return; + } + + if (axi_driver_slv.has_w_beat()) + { + w_beat_request_t w_beat_req = axi_driver_slv.get_next_w_beat(); + + pcie_write_t write; + write.req = w_beat_req; + write.time = sim_time() + pcie_L; + + in_flight_write_requests.push(write); + + + write_wait_cycles = (uint32_t) (pcie_G * w_beat_req.data_size); + } + } + + + void progress_in_flight_writes() + { + if (in_flight_write_requests.empty()) return; + + pcie_write_t &write = in_flight_write_requests.front(); + + + if (sim_time() >= write.time && axi_driver_slv.can_send_b_beat()) + { + // TODO: consume data here! + SIM_PRINT("PCIe got data (data size: %d)!\n", write.req.data_size); + if (slv_write_cb) slv_write_cb(write.req.addr, write.req.w_beat.w_data, write.req.data_size); + + bytes_written += write.req.data_size; + if (num_writes==0) time_first_write = sim_time(); + num_writes++; + time_last_write = sim_time(); + + if (write.req.w_beat.w_last) + { + axi_driver_slv.send_b_beat(); + } + + in_flight_write_requests.pop(); + } + } + + + void progress_new_reads() + { + if (read_wait_cycles > 0) { + read_wait_cycles--; + return; + } + + if (axi_driver_slv.has_r_beat()) + { + r_beat_request_t r_beat_req = axi_driver_slv.get_next_r_beat(); + + pcie_read_t read; + read.req = r_beat_req; + read.time = sim_time() + pcie_L; + + in_flight_read_requests.push(read); + + read_wait_cycles = (uint32_t) (pcie_G * r_beat_req.data_size); + } + } + + + void progress_in_flight_reads() + { + if (in_flight_read_requests.empty()) return; + + pcie_read_t &read = in_flight_read_requests.front(); + + if (sim_time() >= read.time && axi_driver_slv.can_send_r_beat()) + { + // TODO: copy data here (memcpy in read.req.r_beat.r_data)! + SIM_PRINT("PCIe: got read request (data size: %d)!\n", read.req.data_size); + if (slv_read_cb) slv_read_cb(read.req.addr, read.req.r_beat.r_data, read.req.data_size); + + bytes_read += read.req.data_size; + if (num_reads==0) time_first_read = sim_time(); + num_reads++; + time_last_read = sim_time(); + + axi_driver_slv.send_r_beat(read.req.r_beat); + in_flight_read_requests.pop(); + } + } + + + private: + + void posedge() + { + //push staff on the AXI interface + progress_in_flight_reads(); + progress_in_flight_writes(); + + //progress AXI interface + axi_driver_mst.posedge(); + axi_driver_slv.posedge(); + + //sample signals from AXI interface + progress_new_reads(); + progress_new_writes(); + } + + void negedge() + { + axi_driver_mst.negedge(); + axi_driver_slv.negedge(); + } + + public: + void print_stats() + { + double write_time = ((double) (time_last_write - time_first_write)) / 1000; + double read_time = ((double) (time_last_read - time_first_read)) / 1000; + double write_throghput = THROUGHPUT_1GHZ(write_time, bytes_written); + double read_throghput = THROUGHPUT_1GHZ(read_time, bytes_read); + + printf("PCIe:\n"); + printf("\tWrites: beats: %d; bytes: %d; avg throughput: %.03lf Gbit/s\n", num_writes, bytes_written, write_throghput); + printf("\tReads: beats: %d; bytes: %d; avg throughput: %.03lf Gbit/s\n", num_reads, bytes_read, read_throghput); + } + }; + +} // namespace PsPIN \ No newline at end of file diff --git a/hw/verilator_model/src/PCIeMaster.hpp b/hw/verilator_model/src/PCIeMaster.hpp new file mode 100644 index 0000000..0ddf01b --- /dev/null +++ b/hw/verilator_model/src/PCIeMaster.hpp @@ -0,0 +1,193 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIPort.hpp" +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "SimModule.hpp" +#include "AXIMaster.hpp" +#include "pspin.hpp" + +#include +#include + +namespace PsPIN +{ + using std::placeholders::_1; + + template + class PCIeMaster : public SimModule + { + + public: + typedef std::function mst_write_cb_t; + typedef std::function mst_read_cb_t; + + private: + typedef struct write_descr + { + void *user_ptr; + } write_descr_t; + + typedef struct read_descr + { + uint8_t *data; + uint32_t offset; + size_t len; + void *user_ptr; + } read_descr_t; + + private: + AXIMaster axi_driver; + std::queue in_flight_reads; + std::queue in_flight_writes; + + mst_write_cb_t write_cb; + mst_read_cb_t read_cb; + + uint32_t bytes_written, bytes_read; + + public: + PCIeMaster(AXIPortType &axi_mst) + : axi_driver(axi_mst) + { + bytes_written = 0; + bytes_read = 0; + } + + void nic_mem_write(uint32_t nic_mem_addr, uint8_t *data, size_t len, void *user_ptr) + { + write_descr_t write; + write.user_ptr = user_ptr; + axi_driver.write(nic_mem_addr, data, len, 0); + in_flight_writes.push(write); + + bytes_written += len; + } + + void nic_mem_read(uint32_t nic_mem_addr, uint8_t *data, size_t len, void *user_ptr) + { + read_descr_t read; + read.data = data; + read.offset = 0; + read.len = len; + read.user_ptr = user_ptr; + axi_driver.read(nic_mem_addr, len); + in_flight_reads.push(read); + + bytes_read += len; + } + + void set_mst_write_cb(mst_write_cb_t wb) + { + this->write_cb = wb; + } + + void set_mst_read_cb(mst_read_cb_t rb) + { + this->read_cb = rb; + } + + private: + void posedge() + { + progress_axi_writes(); + progress_axi_reads(); + axi_driver.posedge(); + progress_axi_write_responses(); + progress_axi_read_responses(); + } + + void negedge() + { + axi_driver.negedge(); + } + + void print_stats() + { + printf("PCIe Master:\n"); + printf("\tBytes written: %d; Bytes read: %d\n", bytes_written, bytes_read); + + } + + private: + void progress_axi_writes() + { + if (axi_driver.has_aw_beat() && axi_driver.can_send_aw_beat()) + { + axi_driver.send_aw_beat(); + } + + if (axi_driver.has_w_beat() && axi_driver.can_send_w_beat()) + { + axi_driver.send_w_beat(); + } + } + + void progress_axi_write_responses() + { + if (!axi_driver.has_b_beat()) + return; + + bool write_completed = axi_driver.consume_b_beat(); + + if (write_completed) + { + assert(!in_flight_writes.empty()); + write_descr_t &write_descr = in_flight_writes.front(); + if (write_cb) write_cb(write_descr.user_ptr); + in_flight_writes.pop(); + } + } + + void progress_axi_reads() + { + if (axi_driver.has_ar_beat() && axi_driver.can_send_ar_beat()) + { + axi_driver.send_ar_beat(); + } + } + + void progress_axi_read_responses() + { + + if (axi_driver.has_r_beat()) + { + bool read_complete; + uint32_t length = AXI_SW; + + assert(!in_flight_reads.empty()); + read_descr_t &read_descr = in_flight_reads.front(); + + assert(read_descr.offset + length < read_descr.len); + uint8_t *dest_ptr = read_descr.data + read_descr.offset; + read_descr.offset += length; + + //do something with this data + read_complete = axi_driver.consume_r_beat(dest_ptr, length); + + if (read_complete) + { + // read complete + assert(read_descr.offset == read_descr.len); + if (read_cb) read_cb(read_descr.user_ptr); + in_flight_reads.pop(); + } + } + } + }; + +} // namespace PsPIN \ No newline at end of file diff --git a/hw/verilator_model/src/PCIeSlave.hpp b/hw/verilator_model/src/PCIeSlave.hpp new file mode 100644 index 0000000..3036a3d --- /dev/null +++ b/hw/verilator_model/src/PCIeSlave.hpp @@ -0,0 +1,257 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "AXIPort.hpp" +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "SimModule.hpp" +#include "AXIMaster.hpp" +#include "AXISlave.hpp" +#include "pspin.hpp" + +#include +#include + +namespace PsPIN +{ + using std::placeholders::_1; + + template + class PCIeSlave : public SimModule + { + + typedef typename AXISlave::w_beat_request_t w_beat_request_t; + typedef typename AXISlave::r_beat_request_t r_beat_request_t; + + private: + typedef struct pcie_write + { + w_beat_request_t req; + uint64_t time; + } pcie_write_t; + + typedef struct pcie_read + { + r_beat_request_t req; + uint64_t time; + } pcie_read_t; + + private: + AXISlave axi_driver_slv; + + uint32_t pcie_L; + double pcie_G; + + uint32_t write_wait_cycles; + uint32_t read_wait_cycles; + + std::queue in_flight_write_requests; + std::queue in_flight_read_requests; + + public: + typedef std::function slv_write_cb_t; + typedef std::function slv_read_cb_t; + + // Statistics + private: + uint32_t bytes_written; + uint32_t bytes_read; + uint64_t time_first_read; + uint64_t time_last_write; + uint64_t time_first_write; + uint64_t time_last_read; + uint32_t num_reads; + uint32_t num_writes; + + slv_write_cb_t slv_write_cb; + slv_read_cb_t slv_read_cb; + + public: + PCIeSlave(AXISlvPortType &axi_slv, uint32_t aw_buffer_size, uint32_t w_buffer_size, uint32_t ar_buffer_size, uint32_t r_buffer_size, uint32_t b_buffer_size, uint32_t pcie_L, double pcie_G) + : axi_driver_slv(axi_slv), pcie_L(pcie_L), pcie_G(pcie_G) + { + write_wait_cycles = 0; + read_wait_cycles = 0; + + axi_driver_slv.set_ar_buffer(ar_buffer_size); + axi_driver_slv.set_aw_buffer(aw_buffer_size); + axi_driver_slv.set_w_buffer(w_buffer_size); + axi_driver_slv.set_r_buffer(r_buffer_size); + axi_driver_slv.set_b_buffer(b_buffer_size); + + bytes_written = 0; + bytes_read = 0; + time_first_read = 0; + time_last_write = 0; + time_first_write = 0; + time_last_read = 0; + num_reads = 0; + num_writes = 0; + } + + void set_slv_write_cb(slv_write_cb_t cb) + { + this->slv_write_cb = cb; + } + + void set_slv_read_cb(slv_read_cb_t cb) + { + this->slv_read_cb = cb; + } + + private: + + void progress_new_writes() + { + if (write_wait_cycles > 0) { + write_wait_cycles--; + if (write_wait_cycles > 0) return; + } + + if (axi_driver_slv.has_w_beat()) + { + w_beat_request_t w_beat_req = axi_driver_slv.get_next_w_beat(); + + pcie_write_t write; + write.req = w_beat_req; + write.time = sim_time() + pcie_L; + + in_flight_write_requests.push(write); + + write_wait_cycles = (uint32_t) (pcie_G * w_beat_req.data_size); + //SIM_PRINT("PCIe write wait cycles: %u\n", write_wait_cycles); + } + } + + + void progress_in_flight_writes() + { + if (in_flight_write_requests.empty()) return; + + pcie_write_t &write = in_flight_write_requests.front(); + + if (sim_time() >= write.time && axi_driver_slv.can_send_b_beat()) + { + // TODO: consume data here! + assert(write.req.w_beat.w_strb>0); + //int fs = __builtin_clzl(write.req.w_beat.w_strb); + int fs = __builtin_ffsl(write.req.w_beat.w_strb) - 1; + + //SIM_PRINT("PCIe got data: addr: %lx; offset: %d; actual address: %lx; size: %d (last: %u)!\n", write.req.addr, fs, write.req.addr + fs, write.req.data_size, (uint32_t) write.req.w_beat.w_last); + //for (int i=0; i<16; i++){ printf("%x ", ((uint32_t *) (write.req.w_beat.w_data))[i]); } + //uint64_t data = ((uint64_t *) write.req.w_beat.w_data)[0]; + //printf("\n U64: %lx\n", data); + + if (slv_write_cb) slv_write_cb(write.req.addr + fs, write.req.w_beat.w_data + fs, write.req.data_size); + + bytes_written += write.req.data_size; + if (num_writes==0) time_first_write = sim_time(); + num_writes++; + time_last_write = sim_time(); + + if (write.req.w_beat.w_last) + { + axi_driver_slv.send_b_beat(); + } + + in_flight_write_requests.pop(); + } + } + + + void progress_new_reads() + { + if (read_wait_cycles > 0) { + read_wait_cycles--; + return; + } + + if (axi_driver_slv.has_r_beat()) + { + r_beat_request_t r_beat_req = axi_driver_slv.get_next_r_beat(); + + pcie_read_t read; + read.req = r_beat_req; + read.time = sim_time() + pcie_L; + + in_flight_read_requests.push(read); + + read_wait_cycles = (uint32_t) (pcie_G * r_beat_req.data_size); + } + } + + + void progress_in_flight_reads() + { + if (in_flight_read_requests.empty()) return; + + pcie_read_t &read = in_flight_read_requests.front(); + + if (sim_time() >= read.time && axi_driver_slv.can_send_r_beat()) + { + // TODO: copy data here (memcpy in read.req.r_beat.r_data)! + SIM_PRINT("PCIe: got read request (data size: %d)!\n", read.req.data_size); + if (slv_read_cb) slv_read_cb(read.req.addr, read.req.r_beat.r_data, read.req.data_size); + + bytes_read += read.req.data_size; + if (num_reads==0) time_first_read = sim_time(); + num_reads++; + time_last_read = sim_time(); + + axi_driver_slv.send_r_beat(read.req.r_beat); + in_flight_read_requests.pop(); + } + } + + + private: + + void posedge() + { + //push staff on the AXI interface + progress_in_flight_reads(); + progress_in_flight_writes(); + + //progress AXI interface + //axi_driver_mst.posedge(); + axi_driver_slv.posedge(); + + //sample signals from AXI interface + progress_new_reads(); + progress_new_writes(); + } + + void negedge() + { + //axi_driver_mst.negedge(); + axi_driver_slv.negedge(); + } + + public: + void print_stats() + { + double write_time = ((double) (time_last_write - time_first_write)) / 1000; + double read_time = ((double) (time_last_read - time_first_read)) / 1000; + double write_throghput = THROUGHPUT_1GHZ(write_time, bytes_written); + double read_throghput = THROUGHPUT_1GHZ(read_time, bytes_read); + + printf("PCIe Slave:\n"); + printf("\tWrites: beats: %d; bytes: %d; avg throughput: %.03lf Gbit/s\n", num_writes, bytes_written, write_throghput); + printf("\tReads: beats: %d; bytes: %d; avg throughput: %.03lf Gbit/s\n", num_reads, bytes_read, read_throghput); + } + }; + +} // namespace PsPIN diff --git a/hw/verilator_model/src/SimControl.hpp b/hw/verilator_model/src/SimControl.hpp new file mode 100644 index 0000000..58c1d52 --- /dev/null +++ b/hw/verilator_model/src/SimControl.hpp @@ -0,0 +1,183 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include "verilated.h" +#include "verilated_vcd_c.h" + +#include "SimModule.hpp" + +#include +#include + +template +class SimControl +{ +private: + T *tb; + VerilatedVcdC *m_trace; + uint64_t m_tickcount; + bool trace; + std::vector> sim_modules; + +public: + SimControl(T *tb, const char *trace_filename) : tb(tb) + { + m_tickcount = 0; + +#ifdef VERILATOR_HAS_TRACE + trace = trace_filename != NULL; + + if (trace) + { + Verilated::traceEverOn(true); + + m_trace = new VerilatedVcdC; + + // Initialize trace + tb->trace(m_trace, 99); + m_trace->open(trace_filename); + printf("trace on!\n"); + } +#else + printf("trace off!\n"); + trace = false; +#endif + } + + ~SimControl() + { +#ifdef VERILATOR_HAS_TRACE + m_trace->flush(); + m_trace->close(); +#endif + } + + std::vector>& get_modules() + { + return sim_modules; + } + + void add_module(SimModule &module) + { + sim_modules.push_back(std::ref(module)); + } + + // simulated time (ps) + uint64_t time() + { + return m_tickcount*1000; + } + + void reset() + { + tb->rst_ni = 0; + for (int i = 0; i < 4; i++) + { + tb->clk_i = 1; + tb->eval(); + tb->clk_i = 0; + tb->eval(); + } + tb->rst_ni = 1; + } + + void run_single() + { + m_tickcount++; + + tb->clk_i = 1; + tb->eval(); + +#ifdef VERILATOR_HAS_TRACE + if (trace) + { + m_trace->dump(1000 * m_tickcount); + } +#endif + run_sim_modules_posedge(); + + // Allow any combinatorial logic to settle before we tick + // the clock. This becomes necessary in the case where + // we may have modified or adjusted the inputs prior to + // coming into here, since we need all combinatorial logic + // to be settled before we call for a clock tick. + tb->clk_i = 1; + tb->eval(); + +#ifdef VERILATOR_HAS_TRACE + if (trace) + { + m_trace->dump(1000 * m_tickcount + 250); + m_trace->flush(); + } +#endif + + tb->clk_i = 0; + tb->eval(); + +#ifdef VERILATOR_HAS_TRACE + if (trace) + { + m_trace->dump(1000 * m_tickcount + 500); + } +#endif + + run_sim_modules_negedge(); + + tb->clk_i = 0; + tb->eval(); + +#ifdef VERILATOR_HAS_TRACE + if (trace) + { + m_trace->dump(1000 * m_tickcount + 750); + } +#endif + + } + + void run_all() + { + while (!done()) + { + run_single(); + } + } + + bool done() + { + return Verilated::gotFinish(); + } + +private: + void run_sim_modules_posedge() + { + for (auto it=sim_modules.begin(); it!=sim_modules.end(); ++it) + { + it->get().posedge(); + } + } + + void run_sim_modules_negedge() + { + for (auto it=sim_modules.begin(); it!=sim_modules.end(); ++it) + { + it->get().negedge(); + } + } + + +}; diff --git a/hw/verilator_model/src/SimModule.hpp b/hw/verilator_model/src/SimModule.hpp new file mode 100644 index 0000000..6014cb7 --- /dev/null +++ b/hw/verilator_model/src/SimModule.hpp @@ -0,0 +1,31 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once +#include + +#define SIM_PRINT(FORMAT, ...) printf ("[%lu][%s:%u]: " FORMAT, sim_time(), __FILE__, __LINE__, ## __VA_ARGS__) + +class SimModule { +public: + virtual void posedge() = 0; + virtual void negedge() = 0; + + virtual void print_stats() = 0; + +public: + uint64_t sim_time() { + return sc_time_stamp(); + } +}; diff --git a/hw/verilator_model/src/main.cpp b/hw/verilator_model/src/main.cpp new file mode 100644 index 0000000..0e94385 --- /dev/null +++ b/hw/verilator_model/src/main.cpp @@ -0,0 +1,79 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#include "pspinsim.h" +#include "spin.h" + +#include +#include +#include + +//this is where the runtime SLM files are (they are flashed to L2) +#define SLM_FILES_PATH "../sim_files/slm_files" +#define PKT_TASK_FILE "../sim_files/tasks.csv" +#define PKT_DATA_FILE "../sim_files/data.bin" + +void pkt_out(uint8_t* data, size_t len) +{ + printf("Got packet! (len: %lu)\n", len); +} + +void pcie_slv_write(uint64_t addr, uint8_t* data, size_t len) +{ + printf("NIC wants to write %lu bytes to addr %lx\n", len, addr); +} + +void pcie_slv_read(uint64_t addr, uint8_t* data, size_t len) +{ + printf("NIC wants to read %lu bytes from addr %lx\n", len, addr); +} + +void pcie_mst_write_complete(void *user_ptr) +{ + printf("Write to NIC memory completed (user_ptr: %p)\n", user_ptr); +} + +void pcie_mst_read_complete(void *user_ptr) +{ + printf("Read from NIC memory completed (user_ptr: %p)\n", user_ptr); +} + +int main(int argc, char**argv) +{ + pspin_conf_t conf; + pspinsim_default_conf(&conf); + conf.slm_files_path = (char*) SLM_FILES_PATH; + + pspinsim_init(argc, argv, &conf); + + pspinsim_cb_set_pkt_out(pkt_out); + pspinsim_cb_set_pcie_slv_write(pcie_slv_write); + pspinsim_cb_set_pcie_slv_read(pcie_slv_read); + pspinsim_cb_set_pcie_mst_write_completion(pcie_mst_write_complete); + pspinsim_cb_set_pcie_mst_read_completion(pcie_mst_read_complete); + + int ret = pspinsim_packet_trace_read(PKT_TASK_FILE, PKT_DATA_FILE); + if (ret!=SPIN_SUCCESS) { + printf("Error while reading packet trace!\n"); + exit(1); + } + + pspinsim_packet_eos(); + + pspinsim_run(); + + pspinsim_fini(); + + return 0; +} diff --git a/hw/verilator_model/src/pspin.hpp b/hw/verilator_model/src/pspin.hpp new file mode 100644 index 0000000..369efb8 --- /dev/null +++ b/hw/verilator_model/src/pspin.hpp @@ -0,0 +1,170 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#pragma once + +#include + +#include "spin.h" +#include "spin_hw_conf.h" + +#define THROUGHPUT_1GHZ(T, S) (((double)8 * S) / T) + +#define NI_CTRL_PORT_ASSIGN(SRC, SRC_PREFIX, DST) \ + { \ + (DST)->her_ready_i = &((SRC)->EVALUATOR(SRC_PREFIX, ready_o)); \ + (DST)->her_valid_o = &((SRC)->EVALUATOR(SRC_PREFIX, valid_i)); \ + (DST)->her_o.msgid = &((SRC)->EVALUATOR(SRC_PREFIX, msgid_i)); \ + (DST)->her_o.eom = &((SRC)->EVALUATOR(SRC_PREFIX, is_eom_i)); \ + (DST)->her_o.her_addr = &((SRC)->EVALUATOR(SRC_PREFIX, addr_i)); \ + (DST)->her_o.her_size = &((SRC)->EVALUATOR(SRC_PREFIX, size_i)); \ + (DST)->her_o.her_size = &((SRC)->EVALUATOR(SRC_PREFIX, size_i)); \ + (DST)->her_o.xfer_size = &((SRC)->EVALUATOR(SRC_PREFIX, xfer_size_i)); \ + (DST)->her_o.mpq_meta.handler_mem_addr = &((SRC)->EVALUATOR(SRC_PREFIX, meta_handler_mem_addr_i)); \ + (DST)->her_o.mpq_meta.handler_mem_size = &((SRC)->EVALUATOR(SRC_PREFIX, meta_handler_mem_size_i)); \ + (DST)->her_o.mpq_meta.host_mem_addr = &((SRC)->EVALUATOR(SRC_PREFIX, meta_host_mem_addr_i)); \ + (DST)->her_o.mpq_meta.host_mem_size = &((SRC)->EVALUATOR(SRC_PREFIX, meta_host_mem_size_i)); \ + (DST)->her_o.mpq_meta.hh_addr = &((SRC)->EVALUATOR(SRC_PREFIX, meta_hh_addr_i)); \ + (DST)->her_o.mpq_meta.hh_size = &((SRC)->EVALUATOR(SRC_PREFIX, meta_hh_size_i)); \ + (DST)->her_o.mpq_meta.ph_addr = &((SRC)->EVALUATOR(SRC_PREFIX, meta_ph_addr_i)); \ + (DST)->her_o.mpq_meta.ph_size = &((SRC)->EVALUATOR(SRC_PREFIX, meta_ph_size_i)); \ + (DST)->her_o.mpq_meta.th_addr = &((SRC)->EVALUATOR(SRC_PREFIX, meta_th_addr_i)); \ + (DST)->her_o.mpq_meta.th_size = &((SRC)->EVALUATOR(SRC_PREFIX, meta_th_size_i)); \ + (DST)->her_o.mpq_meta.scratchpad_addr[0] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_0_addr_i)); \ + (DST)->her_o.mpq_meta.scratchpad_size[0] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_0_size_i)); \ + (DST)->her_o.mpq_meta.scratchpad_addr[1] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_1_addr_i)); \ + (DST)->her_o.mpq_meta.scratchpad_size[1] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_1_size_i)); \ + (DST)->her_o.mpq_meta.scratchpad_addr[2] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_2_addr_i)); \ + (DST)->her_o.mpq_meta.scratchpad_size[2] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_2_size_i)); \ + (DST)->her_o.mpq_meta.scratchpad_addr[3] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_3_addr_i)); \ + (DST)->her_o.mpq_meta.scratchpad_size[3] = &((SRC)->EVALUATOR(SRC_PREFIX, meta_scratchpad_3_size_i)); \ + (DST)->pspin_active_i = &tb->pspin_active_o; \ + (DST)->feedback_valid_i = &tb->feedback_valid_o; \ + (DST)->feedback_ready_o = &tb->feedback_ready_i; \ + (DST)->feedback_msgid_i = &tb->feedback_msgid_o; \ + (DST)->feedback_her_addr_i = &tb->feedback_her_addr_o; \ + (DST)->feedback_her_size_i = &tb->feedback_her_size_o; \ + (DST)->eos_o = &tb->eos_i; \ + } + +#define NO_CMD_PORT_ASSIGN(SRC, SRC_PREFIX, DST) \ + { \ + (DST)->no_cmd_req_ready_o = &((SRC)->EVALUATOR(SRC_PREFIX, req_ready_i)); \ + (DST)->no_cmd_req_valid_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_valid_o)); \ + (DST)->no_cmd_req_src_addr_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_src_addr_o)); \ + (DST)->no_cmd_req_length_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_length_o)); \ + (DST)->no_cmd_req_user_ptr_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_user_ptr_o)); \ + (DST)->no_cmd_req_id_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_id_o)); \ + (DST)->no_cmd_req_nid_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_nid_o)); \ + (DST)->no_cmd_req_fid_i = &((SRC)->EVALUATOR(SRC_PREFIX, req_fid_o)); \ + (DST)->no_cmd_resp_valid_o = &((SRC)->EVALUATOR(SRC_PREFIX, resp_valid_i)); \ + (DST)->no_cmd_resp_id_o = &((SRC)->EVALUATOR(SRC_PREFIX, resp_id_i)); \ + } + +namespace PsPIN +{ + + typedef spin_ec_t mpq_meta_t; + + typedef struct her_descr + { + uint32_t msgid; + uint8_t eom; + + //full her descriptor + mem_addr_t her_addr; + mem_size_t her_size; + mem_size_t xfer_size; + + mpq_meta_t mpq_meta; + + //Note: this is used only between the driver and the NIC inbound engine. It + //is not sent to PsPIN. + uint64_t user_ptr; + uint64_t nic_arrival_time; + } __attribute__((__packed__)) her_descr_t; + + typedef struct mpq_meta_p + { + //handler memory + mem_addr_t *handler_mem_addr; + mem_size_t *handler_mem_size; + + //host memory + host_addr_t *host_mem_addr; + mem_size_t *host_mem_size; + + //header handler + mem_addr_t *hh_addr; + mem_size_t *hh_size; + + //payload handler + mem_addr_t *ph_addr; + mem_size_t *ph_size; + + //completion (aka tail) handler + mem_addr_t *th_addr; + mem_size_t *th_size; + + //L1 scratchpads + mem_addr_t *scratchpad_addr[NUM_CLUSTERS]; + mem_size_t *scratchpad_size[NUM_CLUSTERS]; + + } __attribute__((__packed__)) mpq_meta_p_t; + + typedef struct her_descr_p + { + uint16_t *msgid; + uint8_t *eom; + + //full her descriptor + mem_addr_t *her_addr; + mem_size_t *her_size; + mem_size_t *xfer_size; + + mpq_meta_p_t mpq_meta; + } __attribute__((__packed__)) her_descr_p_t; + + typedef struct ni_control_port + { + uint8_t *her_valid_o; + uint8_t *her_ready_i; + her_descr_p_t her_o; + uint8_t *pspin_active_i; + uint8_t *feedback_valid_i; + uint8_t *feedback_ready_o; + uint16_t *feedback_msgid_i; + uint32_t *feedback_her_addr_i; + uint32_t *feedback_her_size_i; + uint8_t *eos_o; + } ni_control_port_t; + + typedef struct no_cmd_port + { + // Request + uint8_t *no_cmd_req_ready_o; + uint8_t *no_cmd_req_valid_i; + uint64_t *no_cmd_req_src_addr_i; + uint32_t *no_cmd_req_length_i; + uint64_t *no_cmd_req_user_ptr_i; + uint8_t *no_cmd_req_id_i; + uint32_t *no_cmd_req_nid_i; + uint32_t *no_cmd_req_fid_i; + + // Response + uint8_t *no_cmd_resp_valid_o; + uint8_t *no_cmd_resp_id_o; + } no_cmd_port_t; + +} // namespace PsPIN diff --git a/hw/verilator_model/src/pspinsim.cpp b/hw/verilator_model/src/pspinsim.cpp new file mode 100644 index 0000000..771bb21 --- /dev/null +++ b/hw/verilator_model/src/pspinsim.cpp @@ -0,0 +1,335 @@ +// Copyright 2020 ETH Zurich +// +// 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. + +#include +#include +#include +#include +#include + +#include "Vpspin_verilator.h" +#include "verilated.h" +#include "verilated_vcd_c.h" +#include "AXIPort.hpp" +#include "NICInbound.hpp" +#include "NICOutbound.hpp" +#include "PCIeSlave.hpp" +#include "PCIeMaster.hpp" +#include "SimControl.hpp" + +#include "pspinsim.h" +#include "spin.h" +#include "pspin.hpp" + +#define VCD_FILE "waves.vcd" + + +#define DEFAULT_NI_AXI_AW_BUFFER 32 +#define DEFAULT_NI_AXI_W_BUFFER 32 +#define DEFAULT_NI_AXI_B_BUFFER 32 + +#define NETWORK_G_200G 0.037252 +#define NETWORK_G_400G 0.018626 +#define PCIE_G_5_16 0.014782 + +#define DEFAULT_NO_AXI_AR_BUFFER 32 +#define DEFAULT_NO_AXI_R_BUFFER 32 +//#define DEFAULT_NO_NETWORK_G NETWORK_G_200G +#define DEFAULT_NO_NETWORK_G 0 +#define DEFAULT_NO_MAX_PKT_SIZE 2048 +#define DEFAULT_NO_NET_PKT_QUEUE_LEN 32 + +#define DEFAULT_PCIE_SLV_AW_BUFFER_SIZE 32 +#define DEFAULT_PCIE_SLV_W_BUFFER_SIZE 32 +#define DEFAULT_PCIE_SLV_AR_BUFFER_SIZE 32 +#define DEFAULT_PCIE_SLV_B_BUFFER_SIZE 32 +#define DEFAULT_PCIE_SLV_R_BUFFER_SIZE 32 +#define DEFAULT_PCIE_SLV_L 2 +#define DEFAULT_PCIE_SLV_G PCIE_G_5_16 + +#define PATH_MAX 1024 + +using namespace PsPIN; + +AXIPort ni_mst; +ni_control_port_t ni_control; +AXIPort no_mst; +no_cmd_port_t no_cmd; +AXIPort pcie_slv_port; +AXIPort pcie_mst_port; + +SimControl *sim; +NICInbound> *ni; +NICOutbound> *no; +PCIeSlave> *pcie_slv; +PCIeMaster> *pcie_mst; + +char slm_path[PATH_MAX]; + +double sc_time_stamp() +{ // Called by $time in Verilog + return sim->time(); +} + +const char* get_slm_path() +{ + return slm_path; +} + +int pspinsim_default_conf(pspin_conf_t *conf) +{ + conf->slm_files_path = NULL; + conf->ni_conf.axi_aw_buffer = DEFAULT_NI_AXI_AW_BUFFER; + conf->ni_conf.axi_w_buffer = DEFAULT_NI_AXI_W_BUFFER; + conf->ni_conf.axi_b_buffer = DEFAULT_NI_AXI_B_BUFFER; + + conf->no_conf.axi_ar_buffer = DEFAULT_NO_AXI_AR_BUFFER; + conf->no_conf.axi_r_buffer = DEFAULT_NO_AXI_R_BUFFER; + conf->no_conf.network_G = DEFAULT_NO_NETWORK_G; + conf->no_conf.max_pkt_size = DEFAULT_NO_MAX_PKT_SIZE; + conf->no_conf.max_network_queue_len = DEFAULT_NO_NET_PKT_QUEUE_LEN; + + conf->pcie_slv_conf.axi_aw_buffer = DEFAULT_PCIE_SLV_AW_BUFFER_SIZE; + conf->pcie_slv_conf.axi_w_buffer = DEFAULT_PCIE_SLV_W_BUFFER_SIZE; + conf->pcie_slv_conf.axi_ar_buffer = DEFAULT_PCIE_SLV_AR_BUFFER_SIZE; + conf->pcie_slv_conf.axi_b_buffer = DEFAULT_PCIE_SLV_B_BUFFER_SIZE; + conf->pcie_slv_conf.axi_r_buffer = DEFAULT_PCIE_SLV_R_BUFFER_SIZE; + conf->pcie_slv_conf.pcie_L = DEFAULT_PCIE_SLV_L; + conf->pcie_slv_conf.pcie_G = DEFAULT_PCIE_SLV_G; + + return SPIN_SUCCESS; +} + +int pspinsim_init(int argc, char **argv, pspin_conf_t *conf) +{ + Verilated::commandArgs(argc, argv); + Vpspin_verilator *tb = new Vpspin_verilator(); + sim = new SimControl(tb, VCD_FILE); + + pspin_conf_t default_conf; + if (conf==NULL) { + pspinsim_default_conf(&default_conf); + conf = &default_conf; + } + + // Define ports + AXI_MASTER_PORT_ASSIGN(tb, ni_slave, &ni_mst); + NI_CTRL_PORT_ASSIGN(tb, her, &ni_control) + AXI_MASTER_PORT_ASSIGN(tb, no_slave, &no_mst); + NO_CMD_PORT_ASSIGN(tb, nic_cmd, &no_cmd); + AXI_SLAVE_PORT_ASSIGN(tb, host_master, &pcie_slv_port); + AXI_MASTER_PORT_ASSIGN(tb, host_slave, &pcie_mst_port); + + // Instantiate simulation-only modules + ni = new NICInbound>(ni_mst, ni_control, L2_PKT_BUFF_START, L2_PKT_BUFF_SIZE); + no = new NICOutbound>(no_mst, no_cmd, conf->no_conf.network_G, conf->no_conf.max_pkt_size, conf->no_conf.max_network_queue_len); + pcie_slv = new PCIeSlave>(pcie_slv_port, conf->pcie_slv_conf.axi_aw_buffer, conf->pcie_slv_conf.axi_w_buffer, conf->pcie_slv_conf.axi_ar_buffer, conf->pcie_slv_conf.axi_r_buffer, conf->pcie_slv_conf.axi_b_buffer, conf->pcie_slv_conf.pcie_L, conf->pcie_slv_conf.pcie_G); + pcie_mst = new PCIeMaster>(pcie_mst_port); + + // Add simulation only modules + sim->add_module(*ni); + sim->add_module(*no); + sim->add_module(*pcie_slv); + sim->add_module(*pcie_mst); + + //before the reset! + char *slm_files_path = conf->slm_files_path; + if (slm_files_path==NULL) { + char *pspin_hw_env = getenv("PSPIN_HW"); + if (pspin_hw_env == NULL) { + printf("Error: you need to either specify where to read SLM files from or set PSPIN_HW env var and put slm files in sim_files/slm_files/!\n"); + return SPIN_ERR; + } + snprintf(slm_path, PATH_MAX, "%s/sim_files/slm_files/", pspin_hw_env); + } else { + snprintf(slm_path, PATH_MAX, "%s/", slm_files_path); + } + + // Send reset signal + sim->reset(); + + return SPIN_SUCCESS; +} + +int pspinsim_run() +{ + // Main loop + sim->run_all(); + + return SPIN_SUCCESS; +} + +int pspinsim_run_tick(uint8_t* done_flag) +{ + // Single step of the main loop + *done_flag = 0; + sim->run_single(); + if (sim->done()) *done_flag = 1; + + return SPIN_SUCCESS; +} + +int pspinsim_fini() +{ + printf("\n###### Statistics ######\n"); + for (auto it = sim->get_modules().begin(); it != sim->get_modules().end(); ++it){ + it->get().print_stats(); + printf("----------------------------------\n"); + } + delete sim; + + return SPIN_SUCCESS; +} + +int pspinsim_packet_trace_read(const char* pkt_file_path, const char* data_file_path) +{ + return ni->read_trace(pkt_file_path, data_file_path); +} + +int pspinsim_packet_add(spin_ec_t* ec, uint32_t msgid, uint8_t* pkt_data, size_t pkt_len, size_t pkt_l1_len, uint8_t eom, uint32_t wait_cycles, uint64_t user_ptr) +{ + her_descr_t her; + memcpy(&(her.mpq_meta), ec, sizeof(spin_ec_t)); + + her.msgid = msgid; + her.eom = eom; + her.her_addr = 0; //will be assigned later + her.her_size = pkt_len; + her.xfer_size = pkt_l1_len; + her.user_ptr = user_ptr; + + return ni->add_packet(her, pkt_data, pkt_len, wait_cycles); +} + +int pspinsim_packet_eos() +{ + ni->set_eos(); + return SPIN_SUCCESS; +} + +int pspinsim_cb_set_pkt_out(pkt_out_cb_t cb) +{ + NICOutbound>::out_packet_cb_t f(cb); + no->set_packet_out_cb(f); + return SPIN_SUCCESS; +} + + +int pspinsim_cb_set_pcie_slv_write(pcie_slv_write_cb_t cb) +{ + PCIeSlave>::slv_write_cb_t f(cb); + pcie_slv->set_slv_write_cb(f); + return SPIN_SUCCESS; +} + + +int pspinsim_cb_set_pcie_slv_read(pcie_slv_read_cb_t cb) +{ + PCIeSlave>::slv_read_cb_t f(cb); + pcie_slv->set_slv_read_cb(f); + return SPIN_SUCCESS; +} + +int pspinsim_cb_set_pcie_mst_write_completion(pcie_mst_write_cb_t cb) +{ + PCIeMaster>::mst_write_cb_t f(cb); + pcie_mst->set_mst_write_cb(f); + return SPIN_SUCCESS; +} + +int pspinsim_cb_set_pcie_mst_read_completion(pcie_mst_read_cb_t cb) +{ + PCIeMaster>::mst_read_cb_t f(cb); + pcie_mst->set_mst_read_cb(f); + return SPIN_SUCCESS; +} + +int pspinsim_cb_set_pkt_feedback(pkt_feedback_cb_t cb) +{ + NICInbound>::pkt_feedback_cb_t f(cb); + ni->set_feedback_cb(f); + return SPIN_SUCCESS; +} + +/* sPIN API functions (these are inteded to be into the actual API, no simulation) */ +int spin_nicmem_write(spin_nic_addr_t addr, void *data, size_t size, void* user_ptr) +{ + pcie_mst->nic_mem_write(addr, (uint8_t*) data, size, user_ptr); + return SPIN_SUCCESS; +} + +int spin_nicmem_read(spin_nic_addr_t addr, void *data, size_t size, void* user_ptr) +{ + pcie_mst->nic_mem_read(addr, (uint8_t*) data, size, user_ptr); + return SPIN_SUCCESS; +} + + +// this will be swapped with Timo's stuff +int spin_find_handler_by_name(char *binfile, char* handler_name, spin_nic_addr_t *handler_addr, size_t *handler_size) +{ + struct stat sb; + FILE *f = fopen(binfile, "rb"); + int fno = fileno(f); + fstat(fno, &sb); + + Elf32_Ehdr *elf_ptr = (Elf32_Ehdr*) mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fno, 0); + uint32_t num_sections = elf_ptr->e_shnum; + + Elf32_Shdr *section_header_table = (Elf32_Shdr *)(((uint8_t *)elf_ptr) + elf_ptr->e_shoff); + + Elf32_Shdr *section_header_string_table = &(section_header_table[elf_ptr->e_shstrndx]); + char *sec_string_table = (char *)(((uint8_t *)elf_ptr) + section_header_string_table->sh_offset); + + //find string table for the symbols + char *sym_string_tab = NULL; + for (int i = 0; i < num_sections; i++) + { + //printf("section: %s\n", sec_string_table + section_header_table[i].sh_name); + char *sec_name = sec_string_table + section_header_table[i].sh_name; + if (!strcmp(sec_name, ".strtab")) + { + sym_string_tab = (char *)(((uint8_t *)elf_ptr) + section_header_table[i].sh_offset); + } + } + assert(sym_string_tab != NULL); + + for (int i = 0; i < num_sections; i++) + { + if (section_header_table[i].sh_type == SHT_SYMTAB) + { + //printf("sh type: %u; sh addr: %x\n", section_header_table[i].sh_type, section_header_table[i].sh_addr); + + Elf32_Sym *symbol_table = (Elf32_Sym *)(((uint8_t *)elf_ptr) + section_header_table[i].sh_offset); + uint32_t num_symbols = section_header_table[i].sh_size / sizeof(Elf32_Sym); + + for (int j = 0; j < num_symbols; j++) + { + char *sym_name = sym_string_tab + symbol_table[j].st_name; + + if (!strcmp(sym_name, handler_name)) + { + *handler_addr = symbol_table[j].st_value; + *handler_size = 4096; + break; + } + } + } + } + + munmap(elf_ptr, sb.st_size); + fclose(f); + + return SPIN_SUCCESS; +} diff --git a/hw/verilator_model/start_sim.sh b/hw/verilator_model/start_sim.sh new file mode 100755 index 0000000..b57e152 --- /dev/null +++ b/hw/verilator_model/start_sim.sh @@ -0,0 +1,9 @@ +#/bin/bash + +sim=pspin_release + +if [ "$1" -eq "1" ]; then + sim=pspin_debug +fi + +stdbuf -oL ${PSPIN_HW}/${PSPIN_SIM}/bin/$sim | tee transcript diff --git a/sourceme-template.sh b/sourceme-template.sh new file mode 100644 index 0000000..3df862a --- /dev/null +++ b/sourceme-template.sh @@ -0,0 +1,16 @@ +#ModelSim +#export PSPIN_SIM="modelsim_model" + +#Verilator +export PSPIN_SIM="verilator_model" + +#Update these! +export RISCV_GCC= +export PSPIN_HW= +export PSPIN_RT= + +#Don't change +export TARGET_VSIM=${PSPIN_HW}/$PSPIN_SIM +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${PSPIN_HW}/verilator_model/lib/ +export TRACE_DIR="./" + diff --git a/sw/pulp-sdk/archi/.gitignore b/sw/pulp-sdk/archi/.gitignore new file mode 100644 index 0000000..fce4f97 --- /dev/null +++ b/sw/pulp-sdk/archi/.gitignore @@ -0,0 +1,6 @@ +*~ +build +build.log +.sconsign.dblite +include/archi/chips/gap9/memory_map.h +include/archi/chips/vega/memory_map.h \ No newline at end of file diff --git a/sw/pulp-sdk/archi/LICENSE b/sw/pulp-sdk/archi/LICENSE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/sw/pulp-sdk/archi/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/sw/pulp-sdk/archi/Makefile b/sw/pulp-sdk/archi/Makefile new file mode 100644 index 0000000..64e6591 --- /dev/null +++ b/sw/pulp-sdk/archi/Makefile @@ -0,0 +1,69 @@ +build: + scons + +clean: + rm -f .sconsign.dblite + scons -c + +hwce_v4: + regmap --name=hwce --input-xls=doc/hwce/HWCE_v4_reference.xlsx --header=include/archi/hwce/hwce_v4.h + +hwce_v5: + regmap --name=hwce --input-xls=doc/hwce/HWCE_v5_reference.xlsx --header=include/archi/hwce/hwce_v5.h + +mchan_v7: + regmap --name=mchan --input-xls=doc/mchan/CL_DMA_v7_reference.xlsx --header=include/archi/dma/mchan_v7.h + +udma_mram_v1: + regmap --name=udma_mram --input-xls=doc/udma/MRAM_reference.xlsx --header=include/archi/udma/mram/udma_mram_v1.h + +udma_memcpy_v1: + regmap --name=udma_memcpy --input-xls=doc/udma/MEMCPY_v1_reference.xlsx --header=include/archi/udma/memcpy/v1/udma_memcpy_v1 + +udma_i2s_v2: + regmap --name=udma_i2s --input-xls=doc/udma/i2s/I2S_V2_reference.xlsx --header=include/archi/udma/i2s/udma_i2s_v2.h + +udma_i2s_v3: + regmap --name=udma_i2s --input-xls=doc/udma/i2s/I2S_V3_reference.xlsx --header=include/archi/udma/i2s/v3/udma_i2s_v3 + +udma_cpi_v1: + regmap --name=udma_cpi --input-xls=doc/udma/CAM_CPI_V1_reference.xlsx --header=include/archi/udma/cpi/udma_cpi_v1.h + +udma_hyper_v2: + regmap --name=hyper --input-xls=doc/HYPER_V2_reference.xlsx --header=include/archi/udma/hyper/udma_hyper_v2.h + +pmu_v3: + regmap --name=maestro --input-json=ips/pmu/pmu_v3.json --header=include/archi/maestro/maestro_v3.h + +gpio_v3: + regmap --name=gpio --input-xls=doc/gpio/APB_GPIO_V3_reference.xlsx --header=include/archi/gpio/gpio_v3.h + +pwm_v1: + regmap --name=pwm --input-xls=doc/pwm/pwm_v1.xlsx --header=include/archi/pwm/v1/pwm_v1 + +vega.apb_soc_ctrl: + regmap --name=apb_soc --input-xls=doc/vega/APB_SOC_CTRL_reference.xlsx --header=include/archi/chips/vega/apb_soc_ctrl.h + +gap9: udma_i2s_v3 + +vega: udma_i2s_v2 pmu_v3 udma_hyper_v2 mchan_v7 udma_mram_v1 hwce_v5 gpio_v3 vega.apb_soc_ctrl udma_cpi_v1 + regmap --name=pmu --input-json=chips/vega/pmu.json --header=include/archi/chips/vega/pmu.h + +gap: hwce_v4 udma_memcpy_v1 pwm_v1 + regmap --name=apb_soc --input-xls doc/gap/APB_SOC_CTRL_reference.xlsx --header=include/archi/chips/gap/apb_soc.h + +pulpissimo: udma_i2s_v2 + regmap --name=apb_soc --input-xls=doc/PULPISSIMO_APB_SOC_CTRL_reference.xlsx --header=include/archi/chips/pulpissimo/apb_soc_ctrl.h + +gen: + regmap --name=itc --input-json=ips/itc/itc_v1.json --header=include/archi/itc/itc_v1.h + regmap --name=udma_i2s --input-xls=doc/I2S_V1_reference.xlsx --header=include/archi/udma/i2s/udma_i2s_v1_new.h + regmap --name=maestro --input-json=ips/pmu/pmu_v2.json --header=include/archi/maestro/maestro_v2_new.h + regmap --name=pmu --input-json=chips/wolfe/pmu.json --header=include/archi/chips/wolfe/pmu.h + regmap --name=maestro --input-json=ips/pmu/pmu_v1.json --header=include/archi/maestro/maestro_v1_new.h + regmap --name=timer --input-xls=doc/TIMER_UNIT_reference.xlsx --header=include/archi/timer/timer_v2.h + regmap --name=rtc --input-xls=doc/RTC_UNIT_reference.xlsx --header=include/archi/rtc/rtc_v2.h + regmap --name=apb_soc --input-xls=doc/WOLFE_APB_SOC_CTRL_reference.xlsx --header=include/archi/chips/wolfe/apb_soc_ctrl_new.h + regmap --name=gpio --input-xls=doc/APB_GPIO_reference.xlsx --header=include/archi/gpio/gpio_v2_new.h + +.PHONY: build clean gen \ No newline at end of file diff --git a/sw/pulp-sdk/archi/SConstruct b/sw/pulp-sdk/archi/SConstruct new file mode 100644 index 0000000..74f3827 --- /dev/null +++ b/sw/pulp-sdk/archi/SConstruct @@ -0,0 +1,207 @@ +import os +import subprocess +import shlex +import pulp_config as plpconfig +import SCons.Util + +install_dir = os.environ.get('INSTALL_DIR') +target_install_dir = os.environ.get('TARGET_INSTALL_DIR') + +if install_dir is None: + install_dir = 'install' + +if target_install_dir is None: + target_install_dir = 'install' + +files = [ 'archi/pulp_defs.h', 'archi/pulp.h', 'archi/utils.h' ] +files.append('archi/gvsoc/gvsoc.h') + +try: + files += subprocess.check_output(shlex.split('plpfiles copy --item=archi_files')).decode('UTF-8').split() +except subprocess.CalledProcessError as e: + print (e.output) + raise + +configs = plpconfig.get_configs_from_env() + +def append_file(file): + global files + if not file in files: + files.append(file) + +def append_archi_files(file): + append_file(file + '.h') + append_file(file + '_accessors.h') + append_file(file + '_constants.h') + append_file(file + '_groups.h') + append_file(file + '_gvsoc.h') + append_file(file + '_macros.h') + append_file(file + '_regfields.h') + append_file(file + '_regmap.h') + append_file(file + '_regs.h') + append_file(file + '_structs.h') + + +for config in configs: + + # The old system is storing the path to archi files in the json file + # This has to be migrated so that only IP information is stored in the + # json file and this build system is them copying the archi files according + # to the IP information found in the json file. + + chip = config.get('**/chip/pulp_chip_family').get() + + # UDMA I2S + udma_i2s = config.get_child_int('**/udma/i2s/version') + if udma_i2s is not None: + if udma_i2s == 1: + append_file('archi/udma/i2s/udma_i2s_v%d_new.h' % udma_i2s) + else: + if udma_i2s >= 3: + append_archi_files('archi/udma/i2s/v%d/udma_i2s_v%d' % (udma_i2s, udma_i2s)) + else: + append_file('archi/udma/i2s/udma_i2s_v%d.h' % udma_i2s) + + # UDMA CPI + udma_cpi = config.get_child_int('**/udma/cpi/version') + if udma_cpi is not None: + append_file('archi/udma/cpi/udma_cpi_v%d.h' % udma_cpi) + if udma_cpi == 1: + append_file('archi/udma/cpi/udma_cpi_v%d_old.h' % udma_cpi) + + # UDMA HYPER + udma_hyper = config.get_child_int('**/udma/hyper/version') + if udma_hyper is not None: + append_file('archi/udma/hyper/udma_hyper_v%d.h' % udma_hyper) + + # UDMA MEMCPY + udma_memcpy = config.get_child_int('**/udma/tcdm/version') + if udma_memcpy is not None: + append_archi_files('archi/udma/memcpy/v1/udma_memcpy_v%d' % udma_memcpy) + + + # UDMA MRAM + udma_mram = config.get_child_int('**/udma/mram/version') + if udma_mram is not None: + append_file('archi/udma/mram/udma_mram_v%d.h' % udma_mram) + + + + # HWCE + hwce = config.get_child_int('**/hwce/version') + if hwce is not None: + append_file('archi/hwce/hwce_v%d.h' % hwce) + if hwce == 4: + append_file('archi/hwce/hwce_v%d_old.h' % hwce) + + + # RTC + rtc = config.get('**/soc/rtc') + if rtc is None: + rtc = config.get('**/chip/rtc') + if rtc is not None: + rtc_version = config.get_child_int('**/rtc/version') + if rtc_version == 1 or rtc_version is None: + append_file('archi/vendors/dolphin/rtc.h') + else: + append_file('archi/rtc/rtc_v%d.h' % (rtc_version)) + + # PMU + pmu = config.get_child_int('**/soc/pmu/version') + if pmu is None: + pmu = config.get_child_int('**/chip/pmu/version') + + if pmu is not None: + append_file('archi/maestro/maestro_v1_new.h') + if pmu >= 3: + append_file('archi/maestro/maestro_v%d.h' % pmu) + else: + append_file('archi/maestro/maestro_v%d.h' % pmu) + append_file('archi/maestro/maestro_v%d_new.h' % pmu) + + # ITC + itc = config.get_child_int('**/soc/fc_itc/version') + if itc is not None: + append_file('archi/itc/itc_v%d.h' % itc) + + # GPIO + gpio = config.get_child_int('**/gpio/version') + if gpio is not None: + append_file('archi/gpio/gpio_v%d.h' % gpio) + if gpio == 2: + append_file('archi/gpio/gpio_v%d_new.h' % gpio) + + # TIMER + timer = config.get_child_int('**/timer/version') + if timer is not None: + append_file('archi/timer/timer_v%d.h' % timer) + + + # Chip specific files can be included here + if chip == 'vega': + append_file('archi/pwm/pwm_v1.h') + append_file('archi/chips/vega/apb_soc_ctrl.h') + append_file('archi/chips/vega/pmu.h') + elif chip == 'gap9': + append_file('archi/pwm/pwm_v1.h') + append_file('archi/chips/gap9/apb_soc_ctrl.h') + append_file('archi/chips/gap9/pmu.h') + elif chip == 'pulpissimo': + append_file('archi/chips/pulpissimo/apb_soc_ctrl.h') + elif chip == 'pulp': + append_file('archi/chips/pulp/apb_soc_ctrl.h') + elif chip == 'gap': + append_file('archi/pwm/pwm_v1.h') + append_archi_files('archi/pwm/v1/pwm_v1') + elif chip == 'wolfe': + append_archi_files('archi/pwm/v1/pwm_v1') + append_file('archi/pwm/pwm_v1.h') + append_file('archi/chips/wolfe/pmu.h') + append_file('archi/chips/wolfe/apb_soc.h') + append_file('archi/chips/wolfe/apb_soc_ctrl_new.h') + elif chip == 'wolfe': + append_file('archi/pwm/pwm_v1.h') + elif chip == 'vivosoc3': + append_file('archi/chips/vivosoc3/fll.h') + append_file('archi/chips/vivosoc3/freq.h') + elif chip == 'vivosoc3_5': + append_file('archi/chips/vivosoc3_5/fll.h') + append_file('archi/chips/vivosoc3_5/freq.h') + elif chip == 'vivosoc3_1': + append_file('archi/chips/vivosoc3_1/fll.h') + append_file('archi/chips/vivosoc3_1/freq.h') + elif chip == 'vivosoc4': + append_file('archi/chips/vivosoc4/fll.h') + append_file('archi/chips/vivosoc4/freq.h') + + + if chip == 'vega' or chip == 'gap9': + out_file_path = 'archi/chips/%s/memory_map.h' % chip + + try: + os.makedirs(os.path.dirname(out_file_path)) + except: + pass + + with open('include/' + out_file_path, 'w') as out_file: + with open('include/archi/chips/%s/memory_map.h.in' % chip, 'r') as in_file: + content = in_file.read() + + content = content.replace('@l2_shared_size@', config.get_int('**/l2_shared/size')) + + out_file.write(content) + + append_file(out_file_path) + + + + +targets = [] + +for file in files: + file_path = os.path.join('include', file) + targets.append(InstallAs(os.path.join(install_dir, file_path), file_path)) + targets.append(InstallAs(os.path.join(target_install_dir, file_path), file_path)) + + +Default(targets) diff --git a/sw/pulp-sdk/archi/doc/APB_GPIO_reference.xlsx b/sw/pulp-sdk/archi/doc/APB_GPIO_reference.xlsx new file mode 120000 index 0000000..8d3d62f --- /dev/null +++ b/sw/pulp-sdk/archi/doc/APB_GPIO_reference.xlsx @@ -0,0 +1 @@ +../../../rtl/gap/docs/IP_REFERENCES/APB_GPIO_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/CL_EVENT_UNIT_reference.xlsx b/sw/pulp-sdk/archi/doc/CL_EVENT_UNIT_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5b8a45bc2a2b0c89279d307761d6a74761e38f03 GIT binary patch literal 35270 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/FC_EVENT_UNIT_reference.xlsx b/sw/pulp-sdk/archi/doc/FC_EVENT_UNIT_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..36e1a17b2d4afe9b3a4a5839014d9ba641e11258 GIT binary patch literal 85411 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/HYPER_V2_reference.xlsx b/sw/pulp-sdk/archi/doc/HYPER_V2_reference.xlsx new file mode 120000 index 0000000..5aef280 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/HYPER_V2_reference.xlsx @@ -0,0 +1 @@ +../../../rtl/vega/fe/ips/udma/udma_hyperbus_octospi/docs/HYPERBUS_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/PULPISSIMO_APB_SOC_CTRL_reference.xlsx b/sw/pulp-sdk/archi/doc/PULPISSIMO_APB_SOC_CTRL_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b67b776492c49d08da86da3c6ccb9633a39695d4 GIT binary patch literal 10067 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/RTC_UNIT_reference.xlsx b/sw/pulp-sdk/archi/doc/RTC_UNIT_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a7fcc8a5f7a971a057d1d4b8bd7ab803e139f0ca GIT binary patch literal 14802 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/TIMER_UNIT_reference.xlsx b/sw/pulp-sdk/archi/doc/TIMER_UNIT_reference.xlsx new file mode 120000 index 0000000..c6b50da --- /dev/null +++ b/sw/pulp-sdk/archi/doc/TIMER_UNIT_reference.xlsx @@ -0,0 +1 @@ +../../../rtl/vega/fe/ips/timer_unit/doc/TIMER_UNIT_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/WOLFE_APB_SOC_CTRL_reference.xlsx b/sw/pulp-sdk/archi/doc/WOLFE_APB_SOC_CTRL_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a852af4a573c128c3ff0eae7214d58caf52b2185 GIT binary patch literal 18185 zcmeI4c|6qJ`~U4bGsu>hQ3+Wm$!^d_wpJ>Gj3kn=WjAAsku}7Wts-s-(PAeVO%h^~ z-C#mv&2AVoKkn|&oxA(4Z{2_W{6aU({iZFFpGY;-ZE zX(n`A3g^bZZQSjhJror-UkeiIOzV}n!e{(%>|Ivr*JZnxQ)z5aDY0Mt#cmhTXOUUh z(7B~U{Cr$7CH1jxNE8+RV8GZ#Za`^|k#*#mbCC?yd+Y*pu}xGrU&RB>_mQu7)sCJ- z9Ng<3XLfAi?U3G^Y=6)AV;rC6O^n*;$LuCA(rN2PxLcj^-bcNN9t}G;8O`VBV1B;~ z#Z(n$a`lReiy>%-pN{gd#m+;uc22s24MB3w!aCcG&U zqtmYi@ujg6>q$){42Hj=eAL|)zQEF4#TTaJ;OTF&E6~7rI#WPQ+2&Z(`3y?aDF1OI zR<`SR_TQP_7=#uEI=bWE9VY&b8W$0E$K4UG9*TC?JUkIs6@0EbKf{|KLX?DAKd9kC{Z8Y~YW?kxBANEQ@} zciFpGaNKipo;)sgSDNF<ov&f>OP+qUSF@Xq z?tAzUw>`7<<*F$GHc7uIr|>O45m&K)s?J$x#R@*uOYzF}Nct)zdFF@o4L5Fjy9 zGm#jhb^Dwo^y!I6Rq?wL`n*-9haU^k90C5l)~*K|PeAaVYNC>2j!~6vSsDJ%V@?SW zXEfv?(05e_31PprOd@<$)jkcSeCTT|c>VYu;0R8;LZa+`UW}iTT6vJ9`BZB4RNaKC z5prY1S=rQ|=85Xj)6wNK{%8h(TW7%5)pc|D)8m^rRx2=UM(gm!#XDV*;M2E=9ARo_ zLJsQo?X*Lj&ssUUlyi(A&Ums{xm2uqyf=NQx52c57rt-cT6UqZ%nO;Km|pLX1t^8i zYy;`^CAKX_9|#*#hJsC-OSe2wlkYq zHw*4)4=+xB88W#4)4sIek8x${!>D^b`I)qKe-y`UDIdTAV?I4sKN0^p_wg9!wgFW+ zO^0TXJ|;Q=W5laDFETW;%u$^`{;=RqM@yNnh|Y(pcLRbJoCi&3nK>Mr2yM%RW#H^=IN<+}@;s};2|Uf*A>yj#c04&iRUIaq-wt;}93Z3|qskP8G^9ewdY zWY>xM#NB(|UJl6bXMSke`BaF7HsJC&@>oFSavI*F_D&1njL2l2#+eBb+blHGU3)9( z>f1NR0(kfAc9r&&cyqo!dPm(&U$4Yt_4ZeX8b7ee?R5=SZI3ll-eq~HUgnxR=PlP= zMej0TozM9`ovOTdKi@e|TV%^y=;z?hCTg zFAVd!RxK}ykr_Yx$}C(O6Uq$c$+Sqn7}S%P{Bo!rgetgOrs)?adzNtS+AAtZp8ed8 zSB5P+bs~MW%7qJ5Kkc>b%3lIpat`RdB^LA?QR+{li_EY}FV@gjT1Gn{vcVAV=2P@NQAN zXtnAjy&}tHx>qNL-(e3VEaf7gaWV4OPkKpfiZm`Qujx8{n3>PEzUdQPr+X&pu2NZ7 zjIGk=D*v*I&})@W;%+4gnU6vI`4p+g^oj}7&n}I*J%?e#BnS&PFUgi?>q$*4dFfiE zj1=TZGWP7s>G5K@+G6u3)u2(9An;%J47ikZZUst>BIa z4<9SvHkf$y-ADHo+sC)YC6edrUJ^K`68kXM2+yx29MoI94GYyZ+H*#a+ohwrpp)bB zLl3%BuDu>UMM7OfbI!fJSv{`2|2OHyy$cow zomt(Mx&zRl9+hUs(rx?pfD0b3yF1uF_$}Y_k$X$~wv6ZgfU9IV+DtmtZ8*wXw=};B zTZf#U_k?PSd*p-#-`jJK?(+7ZM@635JDNzy)UM*aOWKGo{G8S6}L<^ z`a=zkACGt4v^)Q)2x_)N|8>s}qavwe?B^vjW&`GZwTKt0@D{xx_skBNpZc_Ta6TTJ^@R`{uo}=d7Dicg&q|uh�I2@U*o2#Ck9BHkwd2r?A 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/gap/APB_SOC_CTRL_reference.xlsx b/sw/pulp-sdk/archi/doc/gap/APB_SOC_CTRL_reference.xlsx new file mode 120000 index 0000000..b9a4173 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/gap/APB_SOC_CTRL_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/gap_rev1/docs/IP_REFERENCES/APB_SOC_CTRL_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/gpio/APB_GPIO_V3_reference.xlsx b/sw/pulp-sdk/archi/doc/gpio/APB_GPIO_V3_reference.xlsx new file mode 120000 index 0000000..3fab498 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/gpio/APB_GPIO_V3_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/fe/ips/apb/apb_gpio/docs/APB_GPIO_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/hwce/HWCE_v4_reference.xlsx b/sw/pulp-sdk/archi/doc/hwce/HWCE_v4_reference.xlsx new file mode 120000 index 0000000..fbd272a --- /dev/null +++ b/sw/pulp-sdk/archi/doc/hwce/HWCE_v4_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/gap_master/docs/IP_REFERENCES/HWCE_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/hwce/HWCE_v5_reference.xlsx b/sw/pulp-sdk/archi/doc/hwce/HWCE_v5_reference.xlsx new file mode 120000 index 0000000..2f9c210 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/hwce/HWCE_v5_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/fe/ips/hwce-new/docs/HWCE_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/mchan/CL_DMA_v7_reference.xlsx b/sw/pulp-sdk/archi/doc/mchan/CL_DMA_v7_reference.xlsx new file mode 120000 index 0000000..f8365f4 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/mchan/CL_DMA_v7_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/fe/ips/mchan/doc/CL_DMA_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/pwm/pwm_v1.xlsx b/sw/pulp-sdk/archi/doc/pwm/pwm_v1.xlsx new file mode 120000 index 0000000..89d987b --- /dev/null +++ b/sw/pulp-sdk/archi/doc/pwm/pwm_v1.xlsx @@ -0,0 +1 @@ +../../../../rtl/gap8_revc/docs/IP_REFERENCES/APB_ADV_TIMER_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/CAM_CPI_V1_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/CAM_CPI_V1_reference.xlsx new file mode 120000 index 0000000..f749cf6 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/udma/CAM_CPI_V1_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/fe/ips/udma/udma_camera/doc/CAM_CPI_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/MEMCPY_v1_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/MEMCPY_v1_reference.xlsx new file mode 120000 index 0000000..c4ce0d1 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/udma/MEMCPY_v1_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/gap8_revc/fe/ips/udma/doc/MEMCPY_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/MRAM_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/MRAM_reference.xlsx new file mode 120000 index 0000000..fe45789 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/udma/MRAM_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/fe/ips/udma/udma_mram/docs/MRAM_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V1_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V1_reference.xlsx new file mode 120000 index 0000000..75f5c57 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V1_reference.xlsx @@ -0,0 +1 @@ +../../../../../rtl/gap_rev1/fe/ips/udma/doc/I2S_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V2_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V2_reference.xlsx new file mode 120000 index 0000000..8cd9a97 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V2_reference.xlsx @@ -0,0 +1 @@ +../../../../../rtl/vega/fe/ips/udma/udma_i2s/doc/I2S_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V3_reference.xlsx b/sw/pulp-sdk/archi/doc/udma/i2s/I2S_V3_reference.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..eca596210613e6fb1fc056371dcc594fe3820f3a GIT binary patch literal 26482 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 literal 0 HcmV?d00001 diff --git a/sw/pulp-sdk/archi/doc/vega/APB_SOC_CTRL_reference.xlsx b/sw/pulp-sdk/archi/doc/vega/APB_SOC_CTRL_reference.xlsx new file mode 120000 index 0000000..a5f9656 --- /dev/null +++ b/sw/pulp-sdk/archi/doc/vega/APB_SOC_CTRL_reference.xlsx @@ -0,0 +1 @@ +../../../../rtl/vega/docs/IP_REFERENCES/APB_SOC_CTRL_reference.xlsx \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/arnold/apb_soc.h b/sw/pulp-sdk/archi/include/archi/chips/arnold/apb_soc.h new file mode 100644 index 0000000..d49c543 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/arnold/apb_soc.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_ARNOLD_APB_SOC_H__ +#define __ARCHI_ARNOLD_APB_SOC_H__ + +#define APB_SOC_BOOT_OTHER 0 +#define APB_SOC_BOOT_JTAG 1 +#define APB_SOC_BOOT_SPI 2 +#define APB_SOC_BOOT_ROM 3 +#define APB_SOC_BOOT_PRELOAD 4 +#define APB_SOC_BOOT_HYPER 5 +#define APB_SOC_BOOT_SPIM 6 +#define APB_SOC_BOOT_SPIM_QPI 7 + +#define APB_SOC_PLT_OTHER 0 +#define APB_SOC_PLT_FPGA 1 +#define APB_SOC_PLT_RTL 2 +#define APB_SOC_PLT_VP 3 +#define APB_SOC_PLT_CHIP 4 + +//PADs configuration is made of 8bits out of which only the first 6 are used +//bit0 enable pull UP +//bit1 enable pull DOWN +//bit2 enable ST +//bit3 enable SlewRate Limit +//bit4..5 Driving Strength +//bit6..7 not used + +#define APB_SOC_BOOTADDR_OFFSET 0x04 +#define APB_SOC_INFO_OFFSET 0x00 //contains number of cores [31:16] and clusters [15:0] +#define APB_SOC_INFOEXTD_OFFSET 0x04 //not used at the moment +#define APB_SOC_NOTUSED0_OFFSET 0x08 //not used at the moment +#define APB_SOC_CLUSTER_ISOLATE_OFFSET 0x0C //not used at the moment + +#define APB_SOC_PADFUN0_OFFSET 0x10 +#define APB_SOC_PADCFG0_OFFSET 0x20 + +#define APB_SOC_PADFUN_OFFSET(g) (APB_SOC_PADFUN0_OFFSET+(g)*4) //sets the mux for pins g*16+0 (bits [1:0]) to g*16+15 (bits [31:30]) +#define APB_SOC_PADFUN_NO(pad) ((pad) >> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/arnold/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/arnold/memory_map.h new file mode 100644 index 0000000..e05ca19 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/arnold/memory_map.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_ARNOLD_MEMORY_MAP_H__ +#define __ARCHI_ARNOLD_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_HWPE_OFFSET 0x0000C000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_FC_HWPE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_HWPE_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_OFFSET 0x00000400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/arnold/properties.h b/sw/pulp-sdk/archi/include/archi/chips/arnold/properties.h new file mode 100644 index 0000000..cd6d238 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/arnold/properties.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_ARNOLD_PROPERTIES_H__ +#define __ARCHI_ARNOLD_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 3 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 2 +#define APB_SOC_VERSION 3 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 3 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define HWME_VERSION 1 +#define PADS_VERSION 2 + + +/* + * CORE IDS + */ + +#define ARCHI_FC_CID 31 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0x80 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/bigpulp/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/bigpulp/memory_map.h new file mode 100644 index 0000000..5444e49 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/bigpulp/memory_map.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_BIGPULP_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_BIGPULP_MEMORY_MAP_H__ + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_UART_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00003000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 +#define ARCHI_RAB_CFG_OFFSET 0x00030000 +#define ARCHI_MAILBOX_OFFSET 0x00021000 // Interface 1 + +#define ARCHI_UART_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UART_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_RAB_CFG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_RAB_CFG_OFFSET ) +#define ARCHI_MAILBOX_BASE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_MAILBOX_OFFSET ) + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x1B000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TRYX_OFFSET 0x00000BFC +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_TRYX_ADDR ( 0x10000000 + ARCHI_CLUSTER_PERIPHERALS_OFFSET + ARCHI_TRYX_OFFSET ) +#define ARCHI_TIMER_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_TIMER_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/bigpulp/properties.h b/sw/pulp-sdk/archi/include/archi/chips/bigpulp/properties.h new file mode 100644 index 0000000..190121e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/bigpulp/properties.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_BIGPULP_PROPERTIES_H__ +#define __ARCHI_CHIPS_BIGPULP_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 262144 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_NO_L1_TINY 1 + + + +/* + * IP VERSIONS + */ + +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define EU_VERSION 3 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 +#if PULP_CHIP == CHIP_BIGPULP_ZU9EG +#define ARCHI_NB_CLUSTER 2 +#endif + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/devchip/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/devchip/memory_map.h new file mode 100644 index 0000000..d84b39f --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/devchip/memory_map.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_DEVCHIP_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_DEVCHIP_MEMORY_MAP_H__ + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/devchip/properties.h b/sw/pulp-sdk/archi/include/archi/chips/devchip/properties.h new file mode 100644 index 0000000..f78bac7 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/devchip/properties.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_DEVCHIP_PROPERTIES_H__ +#define __ARCHI_CHIPS_DEVCHIP_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 65536 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define HWCE_VERSION 5 +#define PADS_VERSION 2 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1< +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Core information register +#define APB_SOC_INFO_OFFSET 0x0 + +// RFU +#define APB_SOC_NOTUSED0_OFFSET 0x4 + +// RFU +#define APB_SOC_NOTUSED1_OFFSET 0x8 + +// Isolate cluster register +#define APB_SOC_CL_ISOLATE_OFFSET 0xc + +// Cluster busy register +#define APB_SOC_CL_BUSY_OFFSET 0x6c + +// PMU bypass configuration register +#define APB_SOC_CL_BYPASS_OFFSET 0x70 + +// JTAG external register +#define APB_SOC_JTAGREG_OFFSET 0x74 + +// L2 sleep configuration register +#define APB_SOC_L2_SLEEP_OFFSET 0x78 + +// Alias for SAFE_PMU_SLEEPCTRL +#define APB_SOC_SLEEP_CTRL_OFFSET 0x7c + +// EOC and chip status register +#define APB_SOC_CORESTATUS_OFFSET 0xa0 + +// EOC and chip status register read mirror +#define APB_SOC_CORESTATUS_RO_OFFSET 0xc0 + +// DC/DC configuration register +#define APB_SOC_SAFE_PMU_RAR_OFFSET 0x100 + +// Sleep modes configuration register +#define APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET 0x104 + +// L2 rententive state configuration +#define APB_SOC_SAFE_PMU_FORCE_OFFSET 0x108 + +// Mux config register (pad 0-15) +#define APB_SOC_SAFE_PADFUN0_OFFSET 0x140 + +// Mux config register (pad 16-31) +#define APB_SOC_SAFE_PADFUN1_OFFSET 0x144 + +// Mux config register (pad 32-47) +#define APB_SOC_SAFE_PADFUN2_OFFSET 0x148 + +// Mux config register (pad 48-63) +#define APB_SOC_SAFE_PADFUN3_OFFSET 0x14c + +// Sleep config register (pad 0-15) +#define APB_SOC_SAFE_SLEEPPADCFG0_OFFSET 0x150 + +// Mux config register (pad 16-31) +#define APB_SOC_SAFE_SLEEPPADCFG1_OFFSET 0x154 + +// Mux config register (pad 32-47) +#define APB_SOC_SAFE_SLEEPPADCFG2_OFFSET 0x158 + +// Mux config register (pad 48-63) +#define APB_SOC_SAFE_SLEEPPADCFG3_OFFSET 0x15c + +// Enable Sleep mode for pads +#define APB_SOC_SAFE_PADSLEEP_OFFSET 0x160 + +// Function register (pad 0 to 3) +#define APB_SOC_SAFE_PADCFG0_OFFSET 0x180 + +// Function register (pad 4 to 7) +#define APB_SOC_SAFE_PADCFG1_OFFSET 0x184 + +// Function register (pad 8 to 11) +#define APB_SOC_SAFE_PADCFG2_OFFSET 0x188 + +// Function register (pad 12 to 15) +#define APB_SOC_SAFE_PADCFG3_OFFSET 0x18c + +// Function register (pad 16 to 19) +#define APB_SOC_SAFE_PADCFG4_OFFSET 0x190 + +// Function register (pad 20 to 23) +#define APB_SOC_SAFE_PADCFG5_OFFSET 0x194 + +// Function register (pad 24 to 27) +#define APB_SOC_SAFE_PADCFG6_OFFSET 0x198 + +// Function register (pad 28 to 31) +#define APB_SOC_SAFE_PADCFG7_OFFSET 0x19c + +// Function register (pad 32 to 35) +#define APB_SOC_SAFE_PADCFG8_OFFSET 0x1a0 + +// Function register (pad 36 to 39) +#define APB_SOC_SAFE_PADCFG9_OFFSET 0x1a4 + +// Function register (pad 40 to 43) +#define APB_SOC_SAFE_PADCFG10_OFFSET 0x1a8 + +// Function register (pad 44 to 47) +#define APB_SOC_SAFE_PADCFG11_OFFSET 0x1ac + +// Function register (pad 48 to 51) +#define APB_SOC_SAFE_PADCFG12_OFFSET 0x1b0 + +// Function register (pad 52 to 55) +#define APB_SOC_SAFE_PADCFG13_OFFSET 0x1b4 + +// Function register (pad 56 to 59) +#define APB_SOC_SAFE_PADCFG14_OFFSET 0x1b8 + +// Function register (pad 60 to 63) +#define APB_SOC_SAFE_PADCFG15_OFFSET 0x1bc + +// GPIO power domain pad input isolation register +#define APB_SOC_REG_GPIO_ISO_OFFSET 0x1c0 + +// CAM power domain pad input isolation register +#define APB_SOC_REG_CAM_ISO_OFFSET 0x1c4 + +// LVDS power domain pad input isolation register +#define APB_SOC_REG_LVDS_ISO_OFFSET 0x1c8 + + + +// +// REGISTERS FIELDS +// + +// Number of clusters (access: R) +#define APB_SOC_INFO_NB_CL_BIT 0 +#define APB_SOC_INFO_NB_CL_WIDTH 16 +#define APB_SOC_INFO_NB_CL_MASK 0xffff + +// Number of cores (access: R) +#define APB_SOC_INFO_NB_CORES_BIT 16 +#define APB_SOC_INFO_NB_CORES_WIDTH 16 +#define APB_SOC_INFO_NB_CORES_MASK 0xffff0000 + +// Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable (access: R/W) +#define APB_SOC_CL_ISOLATE_EN_BIT 0 +#define APB_SOC_CL_ISOLATE_EN_WIDTH 1 +#define APB_SOC_CL_ISOLATE_EN_MASK 0x1 + +// Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) (access: R) +#define APB_SOC_CL_BUSY_BUSY_BIT 0 +#define APB_SOC_CL_BUSY_BUSY_WIDTH 1 +#define APB_SOC_CL_BUSY_BUSY_MASK 0x1 + +// Bypass Maestro PMU controller configuration bitfield: - 1b0: disabled - 1b1: enabled (access: R/W) +#define APB_SOC_CL_BYPASS_BYP_POW_BIT 0 +#define APB_SOC_CL_BYPASS_BYP_POW_WIDTH 1 +#define APB_SOC_CL_BYPASS_BYP_POW_MASK 0x1 + +// Bypass Maestro PMU configuration selection configuration bitfield: - 1b0: use default - 1b1: use user configuration (bitfields from bits 3 to 15 of CL_BYPASS register) (access: R/W) +#define APB_SOC_CL_BYPASS_BYP_CFG_BIT 1 +#define APB_SOC_CL_BYPASS_BYP_CFG_WIDTH 1 +#define APB_SOC_CL_BYPASS_BYP_CFG_MASK 0x2 + +// Cluster state configuration and status bitfield: - 1b0: off - 1b1: on Status information is correct only when bypass mode is enabled. (access: R/W) +#define APB_SOC_CL_BYPASS_CL_STATE_BIT 3 +#define APB_SOC_CL_BYPASS_CL_STATE_WIDTH 1 +#define APB_SOC_CL_BYPASS_CL_STATE_MASK 0x8 + +// Max current allowed on cluster TRC configuration bitfield. (access: R/W) +#define APB_SOC_CL_BYPASS_CURRSET_BIT 4 +#define APB_SOC_CL_BYPASS_CURRSET_WIDTH 3 +#define APB_SOC_CL_BYPASS_CURRSET_MASK 0x70 + +// Number of REFCLK 32kHz after cluster power ok has arised to release TR isolation configuration bitfield. (access: R/W) +#define APB_SOC_CL_BYPASS_PROG_DEL_BIT 7 +#define APB_SOC_CL_BYPASS_PROG_DEL_WIDTH 2 +#define APB_SOC_CL_BYPASS_PROG_DEL_MASK 0x180 + +// Bypass cluster clock and reset control by Maestro PMU configuration bitfield: - 1b0: disabled - 1b1: enabled (access: R/W) +#define APB_SOC_CL_BYPASS_BYP_CLK_BIT 9 +#define APB_SOC_CL_BYPASS_BYP_CLK_WIDTH 1 +#define APB_SOC_CL_BYPASS_BYP_CLK_MASK 0x200 + +// Cluster clock gate configuration bitfield: - 1b0: disabled - 1b1: enabled It should always be used before switching cluster FLL to shutdown or retentive mode. (access: R/W) +#define APB_SOC_CL_BYPASS_CG_BIT 10 +#define APB_SOC_CL_BYPASS_CG_WIDTH 1 +#define APB_SOC_CL_BYPASS_CG_MASK 0x400 + +// Cluster FLL shutdown configuration bitfield: - 1b0: FLL on - 1b1: FLL shutdown mode (access: R/W) +#define APB_SOC_CL_BYPASS_FLL_PWD_BIT 11 +#define APB_SOC_CL_BYPASS_FLL_PWD_WIDTH 1 +#define APB_SOC_CL_BYPASS_FLL_PWD_MASK 0x800 + +// Cluster FLL retentive configuration bitfield: - 1b0: FLL on - 1b1: FLL retentive mode (access: R/W) +#define APB_SOC_CL_BYPASS_FLL_RET_BIT 12 +#define APB_SOC_CL_BYPASS_FLL_RET_WIDTH 1 +#define APB_SOC_CL_BYPASS_FLL_RET_MASK 0x1000 + +// Cluster reset configuration bitfield: - 1b0: nothing - 1b1: reset the cluster (access: R/W) +#define APB_SOC_CL_BYPASS_RST_BIT 13 +#define APB_SOC_CL_BYPASS_RST_WIDTH 1 +#define APB_SOC_CL_BYPASS_RST_MASK 0x2000 + +// ? (access: R/W) +#define APB_SOC_CL_BYPASS_BYP_ISO_BIT 14 +#define APB_SOC_CL_BYPASS_BYP_ISO_WIDTH 1 +#define APB_SOC_CL_BYPASS_BYP_ISO_MASK 0x4000 + +// ? (access: R/W) +#define APB_SOC_CL_BYPASS_PWISO_BIT 15 +#define APB_SOC_CL_BYPASS_PWISO_WIDTH 1 +#define APB_SOC_CL_BYPASS_PWISO_MASK 0x8000 + +// Cluster power ok from cluster TRC status bitfield (access: R/W) +#define APB_SOC_CL_BYPASS_TRCPOWOK_BIT 16 +#define APB_SOC_CL_BYPASS_TRCPOWOK_WIDTH 1 +#define APB_SOC_CL_BYPASS_TRCPOWOK_MASK 0x10000 + +// Cluster power down from Maestro PMU status bitfield. (access: R/W) +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_BIT 17 +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_WIDTH 1 +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_MASK 0x20000 + +// JTAG internal register used for synchronisation from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_SYNC_BIT 0 +#define APB_SOC_JTAGREG_INT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_INT_SYNC_MASK 0x1 + +// JTAG internal register used for selecting boot mode configuration from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_BT_MD_BIT 1 +#define APB_SOC_JTAGREG_INT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_INT_BT_MD_MASK 0xe + +// JTAG external register used for synchronisation from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_SYNC_BIT 8 +#define APB_SOC_JTAGREG_EXT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_EXT_SYNC_MASK 0x100 + +// JTAG external register used for selecting boot mode configuration from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_BT_MD_BIT 9 +#define APB_SOC_JTAGREG_EXT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_EXT_BT_MD_MASK 0xe00 + +// L2 memory sleep configuration (access: R/W) +#define APB_SOC_L2_SLEEP_L2_SLEEP_BIT 0 +#define APB_SOC_L2_SLEEP_L2_SLEEP_WIDTH 1 +#define APB_SOC_L2_SLEEP_L2_SLEEP_MASK 0x1 + +// Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) (access: R) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT 0 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH 32 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_MASK 0xffffffff + +// EOC and chip status register (access: R/W) +#define APB_SOC_CORESTATUS_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_STATUS_MASK 0xffffffff + +// EOC and chip status register (access: R) +#define APB_SOC_CORESTATUS_RO_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_RO_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_RO_STATUS_MASK 0xffffffff + +// DC/DC Nominal Voltage setting (access: R/W) +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_BIT 0 +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_WIDTH 5 +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_MASK 0x1f + +// DC/DC Medium Voltage setting (not used) (access: R/W) +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_BIT 8 +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_WIDTH 5 +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_MASK 0x1f00 + +// DC/DC Low Voltage setting (access: R/W) +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_BIT 16 +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_WIDTH 5 +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_MASK 0x1f0000 + +// DC/DC Retentive Voltage setting (access: R/W) +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_BIT 24 +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_WIDTH 5 +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_MASK 0x1f000000 + +// Configure retention mode for region 0 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_BIT 0 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_MASK 0x1 + +// Configure retention mode for region 1 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_BIT 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_MASK 0x2 + +// Configure retention mode for region 2 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_BIT 2 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_MASK 0x4 + +// Configure retention mode for region 3 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_BIT 3 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_MASK 0x8 + +// Configure retention mode for SoC FLL: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_BIT 4 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_MASK 0x10 + +// Configure retention mode for cluster FLL: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_BIT 5 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_MASK 0x20 + +// Select external wake-up source (GPIO ID): - 5'b00000: GPIO 0 - 5'b00001: GPIO 1 - 5'b00010: GPIO 2 - 5'b00011: GPIO 3 - 5'b00100: GPIO 4 - 5'b00101: GPIO 5 - 5'b00110: GPIO 6 - 5'b00111: GPIO 7 - 5'b01000: GPIO 8 - 5'b01001: GPIO 9 - 5'b01010: GPIO 10 - 5'b01011: GPIO 11 - 5'b01100: GPIO 12 - 5'b01101: GPIO 13 - 5'b01110: GPIO 14 - 5'b01111: GPIO 15 - 5'b10000: GPIO 16 - 5'b10001: GPIO 17 - 5'b10010: GPIO 18 - 5'b10011: GPIO 19 - 5'b10100: GPIO 20 - 5'b10101: GPIO 21 - 5'b10110: GPIO 22 - 5'b10111: GPIO 23 - 5'b11000: GPIO 24 - 5'b11001: GPIO 25 - 5'b11010: GPIO 26 - 5'b11011: GPIO 27 - 5'b11100: GPIO 28 - 5'b11101: GPIO 29 - 5'b11110: GPIO 30 - 5'b11111: GPIO 31 (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_BIT 6 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_WIDTH 5 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_MASK 0x7c0 + +// Select external wake-up mode: - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT 11 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH 2 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_MASK 0x1800 + +// Enable external wake-up; - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT 13 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_MASK 0x2000 + +// - (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_BIT 15 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_MASK 0x8000 + +// Warm bootmode: - 1'b0: Boot from ROM - 1'b1: Boot from L2 (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_BIT 16 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_MASK 0x10000 + +// External wake-up interrupt status (automatically resetted after read) - 1'b0: wake-up triggered by RTC - 1'b1: wake-up triggered by external event (access: R) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_BIT 17 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_MASK 0x20000 + +// Select boot type: - 2'b00: cold boot - 2'b01: deep sleep - 2'b10: retentive deep sleep (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_BIT 18 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_WIDTH 2 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_MASK 0xc0000 + +// Cluster state to restore after warm boot: - 1b0: off - 1b1: on (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_BIT 20 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_MASK 0x100000 + +// Force retentive state on region 0 of L2 memory: 1'b0: not state retentive 1'b1: state retentive (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_BIT 0 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_MASK 0x1 + +// Force retentive state on region 1 of L2 memory: 1'b0: not state retentive 1'b1: state retentive (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_BIT 1 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_MASK 0x2 + +// Force retentive state on region 2 of L2 memory: 1'b0: not state retentive 1'b1: state retentive (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_BIT 2 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_MASK 0x4 + +// Force retentive state on region 3 of L2 memory: 1'b0: not state retentive 1'b1: state retentive (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_BIT 3 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_MASK 0x8 + +// Force power down on region 0 of L2 memory: 1'b0: power up 1'b1: power down (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_BIT 4 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_MASK 0x10 + +// Force power down on region 1 of L2 memory: 1'b0: power up 1'b1: power down (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_BIT 5 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_MASK 0x20 + +// Force power down on region 2 of L2 memory: 1'b0: power up 1'b1: power down (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_BIT 6 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_MASK 0x40 + +// Force power down on region 3 of L2 memory: 1'b0: power up 1'b1: power down (access: R/W) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_BIT 7 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_WIDTH 1 +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_MASK 0x80 + +// Enable pad sleep mode: 1'b0: disable 1'b1: enable (access: R/W) +#define APB_SOC_SAFE_PADSLEEP_EN_BIT 0 +#define APB_SOC_SAFE_PADSLEEP_EN_WIDTH 1 +#define APB_SOC_SAFE_PADSLEEP_EN_MASK 0x1 + +// Configuration of GPIO domain pads isolation: - 1'b0: not isolated - 1'b1: isolated (access: R/W) +#define APB_SOC_REG_GPIO_ISO_ISO_BIT 0 +#define APB_SOC_REG_GPIO_ISO_ISO_WIDTH 1 +#define APB_SOC_REG_GPIO_ISO_ISO_MASK 0x1 + +// Configuration of CAM domain pads isolation: - 1'b0: not isolated - 1'b1: isolated (access: R/W) +#define APB_SOC_REG_CAM_ISO_ISO_BIT 0 +#define APB_SOC_REG_CAM_ISO_ISO_WIDTH 1 +#define APB_SOC_REG_CAM_ISO_ISO_MASK 0x1 + +// Configuration of LVDS domain pads isolation: - 1'b0: not isolated - 1'b1: isolated (access: R/W) +#define APB_SOC_REG_LVDS_ISO_ISO_BIT 0 +#define APB_SOC_REG_LVDS_ISO_ISO_WIDTH 1 +#define APB_SOC_REG_LVDS_ISO_ISO_MASK 0x1 + + + +// +// REGISTERS STRUCTS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef union { + struct { + unsigned int nb_cl :16; // Number of clusters + unsigned int nb_cores :16; // Number of cores + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_info_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_notused0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_notused1_t; + +typedef union { + struct { + unsigned int en :1 ; // Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_isolate_t; + +typedef union { + struct { + unsigned int busy :1 ; // Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_busy_t; + +typedef union { + struct { + unsigned int byp_pow :1 ; // Bypass Maestro PMU controller configuration bitfield: - 1b0: disabled - 1b1: enabled + unsigned int byp_cfg :1 ; // Bypass Maestro PMU configuration selection configuration bitfield: - 1b0: use default - 1b1: use user configuration (bitfields from bits 3 to 15 of CL_BYPASS register) + unsigned int padding0:1 ; + unsigned int cl_state :1 ; // Cluster state configuration and status bitfield: - 1b0: off - 1b1: on Status information is correct only when bypass mode is enabled. + unsigned int currset :3 ; // Max current allowed on cluster TRC configuration bitfield. + unsigned int prog_del :2 ; // Number of REFCLK 32kHz after cluster power ok has arised to release TR isolation configuration bitfield. + unsigned int byp_clk :1 ; // Bypass cluster clock and reset control by Maestro PMU configuration bitfield: - 1b0: disabled - 1b1: enabled + unsigned int cg :1 ; // Cluster clock gate configuration bitfield: - 1b0: disabled - 1b1: enabled It should always be used before switching cluster FLL to shutdown or retentive mode. + unsigned int fll_pwd :1 ; // Cluster FLL shutdown configuration bitfield: - 1b0: FLL on - 1b1: FLL shutdown mode + unsigned int fll_ret :1 ; // Cluster FLL retentive configuration bitfield: - 1b0: FLL on - 1b1: FLL retentive mode + unsigned int rst :1 ; // Cluster reset configuration bitfield: - 1b0: nothing - 1b1: reset the cluster + unsigned int byp_iso :1 ; // ? + unsigned int pwiso :1 ; // ? + unsigned int trcpowok :1 ; // Cluster power ok from cluster TRC status bitfield + unsigned int pmupowdown :1 ; // Cluster power down from Maestro PMU status bitfield. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_bypass_t; + +typedef union { + struct { + unsigned int int_sync :1 ; // JTAG internal register used for synchronisation from external debugger + unsigned int int_bt_md :3 ; // JTAG internal register used for selecting boot mode configuration from external debugger + unsigned int padding0:4 ; + unsigned int ext_sync :1 ; // JTAG external register used for synchronisation from external debugger + unsigned int ext_bt_md :3 ; // JTAG external register used for selecting boot mode configuration from external debugger + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_jtagreg_t; + +typedef union { + struct { + unsigned int l2_sleep :1 ; // L2 memory sleep configuration + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_l2_sleep_t; + +typedef union { + struct { + unsigned int sleep_ctrl :32; // Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_sleep_ctrl_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_ro_t; + +typedef union { + struct { + unsigned int nv_volt :5 ; // DC/DC Nominal Voltage setting + unsigned int padding0:3 ; + unsigned int mv_volt :5 ; // DC/DC Medium Voltage setting (not used) + unsigned int padding1:3 ; + unsigned int lv_volt :5 ; // DC/DC Low Voltage setting + unsigned int padding2:3 ; + unsigned int rv_volt :5 ; // DC/DC Retentive Voltage setting + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_pmu_rar_t; + +typedef union { + struct { + unsigned int l2_r0 :1 ; // Configure retention mode for region 0 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int l2_r1 :1 ; // Configure retention mode for region 1 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int l2_r2 :1 ; // Configure retention mode for region 2 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int l2_r3 :1 ; // Configure retention mode for region 3 of L2 memory: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int soc_fll :1 ; // Configure retention mode for SoC FLL: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int cl_fll :1 ; // Configure retention mode for cluster FLL: - 1'b0: Non retentive - 1'b1: Retentive + unsigned int extwake_src :5 ; // Select external wake-up source (GPIO ID): - 5'b00000: GPIO 0 - 5'b00001: GPIO 1 - 5'b00010: GPIO 2 - 5'b00011: GPIO 3 - 5'b00100: GPIO 4 - 5'b00101: GPIO 5 - 5'b00110: GPIO 6 - 5'b00111: GPIO 7 - 5'b01000: GPIO 8 - 5'b01001: GPIO 9 - 5'b01010: GPIO 10 - 5'b01011: GPIO 11 - 5'b01100: GPIO 12 - 5'b01101: GPIO 13 - 5'b01110: GPIO 14 - 5'b01111: GPIO 15 - 5'b10000: GPIO 16 - 5'b10001: GPIO 17 - 5'b10010: GPIO 18 - 5'b10011: GPIO 19 - 5'b10100: GPIO 20 - 5'b10101: GPIO 21 - 5'b10110: GPIO 22 - 5'b10111: GPIO 23 - 5'b11000: GPIO 24 - 5'b11001: GPIO 25 - 5'b11010: GPIO 26 - 5'b11011: GPIO 27 - 5'b11100: GPIO 28 - 5'b11101: GPIO 29 - 5'b11110: GPIO 30 - 5'b11111: GPIO 31 + unsigned int extwake_type :2 ; // Select external wake-up mode: - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level + unsigned int extwake_en :1 ; // Enable external wake-up; - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled + unsigned int padding0:1 ; + unsigned int wakestate :1 ; // - + unsigned int btdev :1 ; // Warm bootmode: - 1'b0: Boot from ROM - 1'b1: Boot from L2 + unsigned int extint :1 ; // External wake-up interrupt status (automatically resetted after read) - 1'b0: wake-up triggered by RTC - 1'b1: wake-up triggered by external event + unsigned int bttype :2 ; // Select boot type: - 2'b00: cold boot - 2'b01: deep sleep - 2'b10: retentive deep sleep + unsigned int cl_wake :1 ; // Cluster state to restore after warm boot: - 1b0: off - 1b1: on + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_pmu_sleepctrl_t; + +typedef union { + struct { + unsigned int ret_l2_r0 :1 ; // Force retentive state on region 0 of L2 memory: 1'b0: not state retentive 1'b1: state retentive + unsigned int ret_l2_r1 :1 ; // Force retentive state on region 1 of L2 memory: 1'b0: not state retentive 1'b1: state retentive + unsigned int ret_l2_r2 :1 ; // Force retentive state on region 2 of L2 memory: 1'b0: not state retentive 1'b1: state retentive + unsigned int ret_l2_r3 :1 ; // Force retentive state on region 3 of L2 memory: 1'b0: not state retentive 1'b1: state retentive + unsigned int pd_l2_r0 :1 ; // Force power down on region 0 of L2 memory: 1'b0: power up 1'b1: power down + unsigned int pd_l2_r1 :1 ; // Force power down on region 1 of L2 memory: 1'b0: power up 1'b1: power down + unsigned int pd_l2_r2 :1 ; // Force power down on region 2 of L2 memory: 1'b0: power up 1'b1: power down + unsigned int pd_l2_r3 :1 ; // Force power down on region 3 of L2 memory: 1'b0: power up 1'b1: power down + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_pmu_force_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padfun0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padfun1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padfun2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padfun3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg3_t; + +typedef union { + struct { + unsigned int en :1 ; // Enable pad sleep mode: 1'b0: disable 1'b1: enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padsleep_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg4_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg5_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg6_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg7_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg8_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg9_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg10_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg11_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg12_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg13_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg14_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_padcfg15_t; + +typedef union { + struct { + unsigned int iso :1 ; // Configuration of GPIO domain pads isolation: - 1'b0: not isolated - 1'b1: isolated + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_gpio_iso_t; + +typedef union { + struct { + unsigned int iso :1 ; // Configuration of CAM domain pads isolation: - 1'b0: not isolated - 1'b1: isolated + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_cam_iso_t; + +typedef union { + struct { + unsigned int iso :1 ; // Configuration of LVDS domain pads isolation: - 1'b0: not isolated - 1'b1: isolated + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_lvds_iso_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_info : public vp::reg_32 +{ +public: + inline void nb_cl_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline uint32_t nb_cl_get() { return this->get_field(APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline void nb_cores_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } + inline uint32_t nb_cores_get() { return this->get_field(APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } +}; + +class vp_apb_soc_notused0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_notused1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_cl_isolate : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } +}; + +class vp_apb_soc_cl_busy : public vp::reg_32 +{ +public: + inline void busy_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } + inline uint32_t busy_get() { return this->get_field(APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } +}; + +class vp_apb_soc_cl_bypass : public vp::reg_32 +{ +public: + inline void byp_pow_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_BYP_POW_BIT, APB_SOC_CL_BYPASS_BYP_POW_WIDTH); } + inline uint32_t byp_pow_get() { return this->get_field(APB_SOC_CL_BYPASS_BYP_POW_BIT, APB_SOC_CL_BYPASS_BYP_POW_WIDTH); } + inline void byp_cfg_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_BYP_CFG_BIT, APB_SOC_CL_BYPASS_BYP_CFG_WIDTH); } + inline uint32_t byp_cfg_get() { return this->get_field(APB_SOC_CL_BYPASS_BYP_CFG_BIT, APB_SOC_CL_BYPASS_BYP_CFG_WIDTH); } + inline void cl_state_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_CL_STATE_BIT, APB_SOC_CL_BYPASS_CL_STATE_WIDTH); } + inline uint32_t cl_state_get() { return this->get_field(APB_SOC_CL_BYPASS_CL_STATE_BIT, APB_SOC_CL_BYPASS_CL_STATE_WIDTH); } + inline void currset_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_CURRSET_BIT, APB_SOC_CL_BYPASS_CURRSET_WIDTH); } + inline uint32_t currset_get() { return this->get_field(APB_SOC_CL_BYPASS_CURRSET_BIT, APB_SOC_CL_BYPASS_CURRSET_WIDTH); } + inline void prog_del_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_PROG_DEL_BIT, APB_SOC_CL_BYPASS_PROG_DEL_WIDTH); } + inline uint32_t prog_del_get() { return this->get_field(APB_SOC_CL_BYPASS_PROG_DEL_BIT, APB_SOC_CL_BYPASS_PROG_DEL_WIDTH); } + inline void byp_clk_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_BYP_CLK_BIT, APB_SOC_CL_BYPASS_BYP_CLK_WIDTH); } + inline uint32_t byp_clk_get() { return this->get_field(APB_SOC_CL_BYPASS_BYP_CLK_BIT, APB_SOC_CL_BYPASS_BYP_CLK_WIDTH); } + inline void cg_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_CG_BIT, APB_SOC_CL_BYPASS_CG_WIDTH); } + inline uint32_t cg_get() { return this->get_field(APB_SOC_CL_BYPASS_CG_BIT, APB_SOC_CL_BYPASS_CG_WIDTH); } + inline void fll_pwd_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_FLL_PWD_BIT, APB_SOC_CL_BYPASS_FLL_PWD_WIDTH); } + inline uint32_t fll_pwd_get() { return this->get_field(APB_SOC_CL_BYPASS_FLL_PWD_BIT, APB_SOC_CL_BYPASS_FLL_PWD_WIDTH); } + inline void fll_ret_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_FLL_RET_BIT, APB_SOC_CL_BYPASS_FLL_RET_WIDTH); } + inline uint32_t fll_ret_get() { return this->get_field(APB_SOC_CL_BYPASS_FLL_RET_BIT, APB_SOC_CL_BYPASS_FLL_RET_WIDTH); } + inline void rst_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_RST_BIT, APB_SOC_CL_BYPASS_RST_WIDTH); } + inline uint32_t rst_get() { return this->get_field(APB_SOC_CL_BYPASS_RST_BIT, APB_SOC_CL_BYPASS_RST_WIDTH); } + inline void byp_iso_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_BYP_ISO_BIT, APB_SOC_CL_BYPASS_BYP_ISO_WIDTH); } + inline uint32_t byp_iso_get() { return this->get_field(APB_SOC_CL_BYPASS_BYP_ISO_BIT, APB_SOC_CL_BYPASS_BYP_ISO_WIDTH); } + inline void pwiso_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_PWISO_BIT, APB_SOC_CL_BYPASS_PWISO_WIDTH); } + inline uint32_t pwiso_get() { return this->get_field(APB_SOC_CL_BYPASS_PWISO_BIT, APB_SOC_CL_BYPASS_PWISO_WIDTH); } + inline void trcpowok_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_TRCPOWOK_BIT, APB_SOC_CL_BYPASS_TRCPOWOK_WIDTH); } + inline uint32_t trcpowok_get() { return this->get_field(APB_SOC_CL_BYPASS_TRCPOWOK_BIT, APB_SOC_CL_BYPASS_TRCPOWOK_WIDTH); } + inline void pmupowdown_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BYPASS_PMUPOWDOWN_BIT, APB_SOC_CL_BYPASS_PMUPOWDOWN_WIDTH); } + inline uint32_t pmupowdown_get() { return this->get_field(APB_SOC_CL_BYPASS_PMUPOWDOWN_BIT, APB_SOC_CL_BYPASS_PMUPOWDOWN_WIDTH); } +}; + +class vp_apb_soc_jtagreg : public vp::reg_32 +{ +public: + inline void int_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline uint32_t int_sync_get() { return this->get_field(APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline void int_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline uint32_t int_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline void ext_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline uint32_t ext_sync_get() { return this->get_field(APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline void ext_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } + inline uint32_t ext_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } +}; + +class vp_apb_soc_l2_sleep : public vp::reg_32 +{ +public: + inline void l2_sleep_set(uint32_t value) { this->set_field(value, APB_SOC_L2_SLEEP_L2_SLEEP_BIT, APB_SOC_L2_SLEEP_L2_SLEEP_WIDTH); } + inline uint32_t l2_sleep_get() { return this->get_field(APB_SOC_L2_SLEEP_L2_SLEEP_BIT, APB_SOC_L2_SLEEP_L2_SLEEP_WIDTH); } +}; + +class vp_apb_soc_sleep_ctrl : public vp::reg_32 +{ +public: + inline void sleep_ctrl_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } + inline uint32_t sleep_ctrl_get() { return this->get_field(APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } +}; + +class vp_apb_soc_corestatus : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } +}; + +class vp_apb_soc_corestatus_ro : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } +}; + +class vp_apb_soc_safe_pmu_rar : public vp::reg_32 +{ +public: + inline void nv_volt_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_RAR_NV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_NV_VOLT_WIDTH); } + inline uint32_t nv_volt_get() { return this->get_field(APB_SOC_SAFE_PMU_RAR_NV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_NV_VOLT_WIDTH); } + inline void mv_volt_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_RAR_MV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_MV_VOLT_WIDTH); } + inline uint32_t mv_volt_get() { return this->get_field(APB_SOC_SAFE_PMU_RAR_MV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_MV_VOLT_WIDTH); } + inline void lv_volt_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_RAR_LV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_LV_VOLT_WIDTH); } + inline uint32_t lv_volt_get() { return this->get_field(APB_SOC_SAFE_PMU_RAR_LV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_LV_VOLT_WIDTH); } + inline void rv_volt_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_RAR_RV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_RV_VOLT_WIDTH); } + inline uint32_t rv_volt_get() { return this->get_field(APB_SOC_SAFE_PMU_RAR_RV_VOLT_BIT, APB_SOC_SAFE_PMU_RAR_RV_VOLT_WIDTH); } +}; + +class vp_apb_soc_safe_pmu_sleepctrl : public vp::reg_32 +{ +public: + inline void l2_r0_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_WIDTH); } + inline uint32_t l2_r0_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_WIDTH); } + inline void l2_r1_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_WIDTH); } + inline uint32_t l2_r1_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_WIDTH); } + inline void l2_r2_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_WIDTH); } + inline uint32_t l2_r2_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_WIDTH); } + inline void l2_r3_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_WIDTH); } + inline uint32_t l2_r3_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_WIDTH); } + inline void soc_fll_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_WIDTH); } + inline uint32_t soc_fll_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_WIDTH); } + inline void cl_fll_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_WIDTH); } + inline uint32_t cl_fll_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_WIDTH); } + inline void extwake_src_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_WIDTH); } + inline uint32_t extwake_src_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_WIDTH); } + inline void extwake_type_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline uint32_t extwake_type_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline void extwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline uint32_t extwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline void wakestate_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_WIDTH); } + inline uint32_t wakestate_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_WIDTH); } + inline void btdev_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_WIDTH); } + inline uint32_t btdev_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_WIDTH); } + inline void extint_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_WIDTH); } + inline uint32_t extint_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_WIDTH); } + inline void bttype_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_WIDTH); } + inline uint32_t bttype_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_WIDTH); } + inline void cl_wake_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_WIDTH); } + inline uint32_t cl_wake_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_WIDTH); } +}; + +class vp_apb_soc_safe_pmu_force : public vp::reg_32 +{ +public: + inline void ret_l2_r0_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_WIDTH); } + inline uint32_t ret_l2_r0_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_WIDTH); } + inline void ret_l2_r1_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_WIDTH); } + inline uint32_t ret_l2_r1_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_WIDTH); } + inline void ret_l2_r2_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_WIDTH); } + inline uint32_t ret_l2_r2_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_WIDTH); } + inline void ret_l2_r3_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_WIDTH); } + inline uint32_t ret_l2_r3_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_BIT, APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_WIDTH); } + inline void pd_l2_r0_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_WIDTH); } + inline uint32_t pd_l2_r0_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_WIDTH); } + inline void pd_l2_r1_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_WIDTH); } + inline uint32_t pd_l2_r1_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_WIDTH); } + inline void pd_l2_r2_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_WIDTH); } + inline uint32_t pd_l2_r2_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_WIDTH); } + inline void pd_l2_r3_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_WIDTH); } + inline uint32_t pd_l2_r3_get() { return this->get_field(APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_BIT, APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_WIDTH); } +}; + +class vp_apb_soc_safe_padfun0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padfun1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padfun2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padfun3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padsleep : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PADSLEEP_EN_BIT, APB_SOC_SAFE_PADSLEEP_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(APB_SOC_SAFE_PADSLEEP_EN_BIT, APB_SOC_SAFE_PADSLEEP_EN_WIDTH); } +}; + +class vp_apb_soc_safe_padcfg0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg4 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg5 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg6 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg7 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg8 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg9 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg10 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg11 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg12 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg13 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg14 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_padcfg15 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_reg_gpio_iso : public vp::reg_32 +{ +public: + inline void iso_set(uint32_t value) { this->set_field(value, APB_SOC_REG_GPIO_ISO_ISO_BIT, APB_SOC_REG_GPIO_ISO_ISO_WIDTH); } + inline uint32_t iso_get() { return this->get_field(APB_SOC_REG_GPIO_ISO_ISO_BIT, APB_SOC_REG_GPIO_ISO_ISO_WIDTH); } +}; + +class vp_apb_soc_reg_cam_iso : public vp::reg_32 +{ +public: + inline void iso_set(uint32_t value) { this->set_field(value, APB_SOC_REG_CAM_ISO_ISO_BIT, APB_SOC_REG_CAM_ISO_ISO_WIDTH); } + inline uint32_t iso_get() { return this->get_field(APB_SOC_REG_CAM_ISO_ISO_BIT, APB_SOC_REG_CAM_ISO_ISO_WIDTH); } +}; + +class vp_apb_soc_reg_lvds_iso : public vp::reg_32 +{ +public: + inline void iso_set(uint32_t value) { this->set_field(value, APB_SOC_REG_LVDS_ISO_ISO_BIT, APB_SOC_REG_LVDS_ISO_ISO_WIDTH); } + inline uint32_t iso_get() { return this->get_field(APB_SOC_REG_LVDS_ISO_ISO_BIT, APB_SOC_REG_LVDS_ISO_ISO_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef struct { + unsigned int info ; // Core information register + unsigned int notused0 ; // RFU + unsigned int notused1 ; // RFU + unsigned int cl_isolate ; // Isolate cluster register + unsigned int cl_busy ; // Cluster busy register + unsigned int cl_bypass ; // PMU bypass configuration register + unsigned int jtagreg ; // JTAG external register + unsigned int l2_sleep ; // L2 sleep configuration register + unsigned int sleep_ctrl ; // Alias for SAFE_PMU_SLEEPCTRL + unsigned int corestatus ; // EOC and chip status register + unsigned int corestatus_ro ; // EOC and chip status register read mirror + unsigned int safe_pmu_rar ; // DC/DC configuration register + unsigned int safe_pmu_sleepctrl; // Sleep modes configuration register + unsigned int safe_pmu_force ; // L2 rententive state configuration + unsigned int safe_padfun0 ; // Mux config register (pad 0-15) + unsigned int safe_padfun1 ; // Mux config register (pad 16-31) + unsigned int safe_padfun2 ; // Mux config register (pad 32-47) + unsigned int safe_padfun3 ; // Mux config register (pad 48-63) + unsigned int safe_sleeppadcfg0; // Sleep config register (pad 0-15) + unsigned int safe_sleeppadcfg1; // Mux config register (pad 16-31) + unsigned int safe_sleeppadcfg2; // Mux config register (pad 32-47) + unsigned int safe_sleeppadcfg3; // Mux config register (pad 48-63) + unsigned int safe_padsleep ; // Enable Sleep mode for pads + unsigned int safe_padcfg0 ; // Function register (pad 0 to 3) + unsigned int safe_padcfg1 ; // Function register (pad 4 to 7) + unsigned int safe_padcfg2 ; // Function register (pad 8 to 11) + unsigned int safe_padcfg3 ; // Function register (pad 12 to 15) + unsigned int safe_padcfg4 ; // Function register (pad 16 to 19) + unsigned int safe_padcfg5 ; // Function register (pad 20 to 23) + unsigned int safe_padcfg6 ; // Function register (pad 24 to 27) + unsigned int safe_padcfg7 ; // Function register (pad 28 to 31) + unsigned int safe_padcfg8 ; // Function register (pad 32 to 35) + unsigned int safe_padcfg9 ; // Function register (pad 36 to 39) + unsigned int safe_padcfg10 ; // Function register (pad 40 to 43) + unsigned int safe_padcfg11 ; // Function register (pad 44 to 47) + unsigned int safe_padcfg12 ; // Function register (pad 48 to 51) + unsigned int safe_padcfg13 ; // Function register (pad 52 to 55) + unsigned int safe_padcfg14 ; // Function register (pad 56 to 59) + unsigned int safe_padcfg15 ; // Function register (pad 60 to 63) + unsigned int reg_gpio_iso ; // GPIO power domain pad input isolation register + unsigned int reg_cam_iso ; // CAM power domain pad input isolation register + unsigned int reg_lvds_iso ; // LVDS power domain pad input isolation register +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +static inline uint32_t apb_soc_info_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_INFO_OFFSET); } +static inline void apb_soc_info_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_INFO_OFFSET, value); } + +static inline uint32_t apb_soc_notused0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_NOTUSED0_OFFSET); } +static inline void apb_soc_notused0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_NOTUSED0_OFFSET, value); } + +static inline uint32_t apb_soc_notused1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_NOTUSED1_OFFSET); } +static inline void apb_soc_notused1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_NOTUSED1_OFFSET, value); } + +static inline uint32_t apb_soc_cl_isolate_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_ISOLATE_OFFSET); } +static inline void apb_soc_cl_isolate_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_ISOLATE_OFFSET, value); } + +static inline uint32_t apb_soc_cl_busy_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_BUSY_OFFSET); } +static inline void apb_soc_cl_busy_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_BUSY_OFFSET, value); } + +static inline uint32_t apb_soc_cl_bypass_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_BYPASS_OFFSET); } +static inline void apb_soc_cl_bypass_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_BYPASS_OFFSET, value); } + +static inline uint32_t apb_soc_jtagreg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_JTAGREG_OFFSET); } +static inline void apb_soc_jtagreg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_JTAGREG_OFFSET, value); } + +static inline uint32_t apb_soc_l2_sleep_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_L2_SLEEP_OFFSET); } +static inline void apb_soc_l2_sleep_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_L2_SLEEP_OFFSET, value); } + +static inline uint32_t apb_soc_sleep_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SLEEP_CTRL_OFFSET); } +static inline void apb_soc_sleep_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SLEEP_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_OFFSET); } +static inline void apb_soc_corestatus_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_ro_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_RO_OFFSET); } +static inline void apb_soc_corestatus_ro_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_RO_OFFSET, value); } + +static inline uint32_t apb_soc_safe_pmu_rar_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PMU_RAR_OFFSET); } +static inline void apb_soc_safe_pmu_rar_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PMU_RAR_OFFSET, value); } + +static inline uint32_t apb_soc_safe_pmu_sleepctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET); } +static inline void apb_soc_safe_pmu_sleepctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_pmu_force_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PMU_FORCE_OFFSET); } +static inline void apb_soc_safe_pmu_force_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PMU_FORCE_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padfun0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADFUN0_OFFSET); } +static inline void apb_soc_safe_padfun0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADFUN0_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padfun1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADFUN1_OFFSET); } +static inline void apb_soc_safe_padfun1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADFUN1_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padfun2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADFUN2_OFFSET); } +static inline void apb_soc_safe_padfun2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADFUN2_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padfun3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADFUN3_OFFSET); } +static inline void apb_soc_safe_padfun3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADFUN3_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG2_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG2_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG3_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG3_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padsleep_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADSLEEP_OFFSET); } +static inline void apb_soc_safe_padsleep_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADSLEEP_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG0_OFFSET); } +static inline void apb_soc_safe_padcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG1_OFFSET); } +static inline void apb_soc_safe_padcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG2_OFFSET); } +static inline void apb_soc_safe_padcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG2_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG3_OFFSET); } +static inline void apb_soc_safe_padcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG3_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg4_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG4_OFFSET); } +static inline void apb_soc_safe_padcfg4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG4_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg5_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG5_OFFSET); } +static inline void apb_soc_safe_padcfg5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG5_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg6_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG6_OFFSET); } +static inline void apb_soc_safe_padcfg6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG6_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg7_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG7_OFFSET); } +static inline void apb_soc_safe_padcfg7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG7_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg8_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG8_OFFSET); } +static inline void apb_soc_safe_padcfg8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG8_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg9_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG9_OFFSET); } +static inline void apb_soc_safe_padcfg9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG9_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg10_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG10_OFFSET); } +static inline void apb_soc_safe_padcfg10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG10_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg11_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG11_OFFSET); } +static inline void apb_soc_safe_padcfg11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG11_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg12_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG12_OFFSET); } +static inline void apb_soc_safe_padcfg12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG12_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg13_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG13_OFFSET); } +static inline void apb_soc_safe_padcfg13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG13_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg14_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG14_OFFSET); } +static inline void apb_soc_safe_padcfg14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG14_OFFSET, value); } + +static inline uint32_t apb_soc_safe_padcfg15_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PADCFG15_OFFSET); } +static inline void apb_soc_safe_padcfg15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PADCFG15_OFFSET, value); } + +static inline uint32_t apb_soc_reg_gpio_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_GPIO_ISO_OFFSET); } +static inline void apb_soc_reg_gpio_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_GPIO_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_cam_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_CAM_ISO_OFFSET); } +static inline void apb_soc_reg_cam_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_CAM_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_lvds_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_LVDS_ISO_OFFSET); } +static inline void apb_soc_reg_lvds_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_LVDS_ISO_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#define APB_SOC_INFO_NB_CL_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define APB_SOC_INFO_NB_CL_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define APB_SOC_INFO_NB_CL_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define APB_SOC_INFO_NB_CL(val) ((val) << 0) + +#define APB_SOC_INFO_NB_CORES_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_INFO_NB_CORES_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_INFO_NB_CORES_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_INFO_NB_CORES(val) ((val) << 16) + +#define APB_SOC_CL_ISOLATE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_ISOLATE_EN(val) ((val) << 0) + +#define APB_SOC_CL_BUSY_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_BUSY_BUSY(val) ((val) << 0) + +#define APB_SOC_CL_BYPASS_BYP_POW_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_BYPASS_BYP_POW_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_BYPASS_BYP_POW_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_BYPASS_BYP_POW(val) ((val) << 0) + +#define APB_SOC_CL_BYPASS_BYP_CFG_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define APB_SOC_CL_BYPASS_BYP_CFG_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define APB_SOC_CL_BYPASS_BYP_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define APB_SOC_CL_BYPASS_BYP_CFG(val) ((val) << 1) + +#define APB_SOC_CL_BYPASS_CL_STATE_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define APB_SOC_CL_BYPASS_CL_STATE_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define APB_SOC_CL_BYPASS_CL_STATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define APB_SOC_CL_BYPASS_CL_STATE(val) ((val) << 3) + +#define APB_SOC_CL_BYPASS_CURRSET_GET(value) (ARCHI_BEXTRACTU((value),3,4)) +#define APB_SOC_CL_BYPASS_CURRSET_GETS(value) (ARCHI_BEXTRACT((value),3,4)) +#define APB_SOC_CL_BYPASS_CURRSET_SET(value,field) (ARCHI_BINSERT((value),(field),3,4)) +#define APB_SOC_CL_BYPASS_CURRSET(val) ((val) << 4) + +#define APB_SOC_CL_BYPASS_PROG_DEL_GET(value) (ARCHI_BEXTRACTU((value),2,7)) +#define APB_SOC_CL_BYPASS_PROG_DEL_GETS(value) (ARCHI_BEXTRACT((value),2,7)) +#define APB_SOC_CL_BYPASS_PROG_DEL_SET(value,field) (ARCHI_BINSERT((value),(field),2,7)) +#define APB_SOC_CL_BYPASS_PROG_DEL(val) ((val) << 7) + +#define APB_SOC_CL_BYPASS_BYP_CLK_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define APB_SOC_CL_BYPASS_BYP_CLK_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define APB_SOC_CL_BYPASS_BYP_CLK_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define APB_SOC_CL_BYPASS_BYP_CLK(val) ((val) << 9) + +#define APB_SOC_CL_BYPASS_CG_GET(value) (ARCHI_BEXTRACTU((value),1,10)) +#define APB_SOC_CL_BYPASS_CG_GETS(value) (ARCHI_BEXTRACT((value),1,10)) +#define APB_SOC_CL_BYPASS_CG_SET(value,field) (ARCHI_BINSERT((value),(field),1,10)) +#define APB_SOC_CL_BYPASS_CG(val) ((val) << 10) + +#define APB_SOC_CL_BYPASS_FLL_PWD_GET(value) (ARCHI_BEXTRACTU((value),1,11)) +#define APB_SOC_CL_BYPASS_FLL_PWD_GETS(value) (ARCHI_BEXTRACT((value),1,11)) +#define APB_SOC_CL_BYPASS_FLL_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),1,11)) +#define APB_SOC_CL_BYPASS_FLL_PWD(val) ((val) << 11) + +#define APB_SOC_CL_BYPASS_FLL_RET_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define APB_SOC_CL_BYPASS_FLL_RET_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define APB_SOC_CL_BYPASS_FLL_RET_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define APB_SOC_CL_BYPASS_FLL_RET(val) ((val) << 12) + +#define APB_SOC_CL_BYPASS_RST_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define APB_SOC_CL_BYPASS_RST_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define APB_SOC_CL_BYPASS_RST_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define APB_SOC_CL_BYPASS_RST(val) ((val) << 13) + +#define APB_SOC_CL_BYPASS_BYP_ISO_GET(value) (ARCHI_BEXTRACTU((value),1,14)) +#define APB_SOC_CL_BYPASS_BYP_ISO_GETS(value) (ARCHI_BEXTRACT((value),1,14)) +#define APB_SOC_CL_BYPASS_BYP_ISO_SET(value,field) (ARCHI_BINSERT((value),(field),1,14)) +#define APB_SOC_CL_BYPASS_BYP_ISO(val) ((val) << 14) + +#define APB_SOC_CL_BYPASS_PWISO_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define APB_SOC_CL_BYPASS_PWISO_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define APB_SOC_CL_BYPASS_PWISO_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define APB_SOC_CL_BYPASS_PWISO(val) ((val) << 15) + +#define APB_SOC_CL_BYPASS_TRCPOWOK_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define APB_SOC_CL_BYPASS_TRCPOWOK_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define APB_SOC_CL_BYPASS_TRCPOWOK_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define APB_SOC_CL_BYPASS_TRCPOWOK(val) ((val) << 16) + +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define APB_SOC_CL_BYPASS_PMUPOWDOWN_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define APB_SOC_CL_BYPASS_PMUPOWDOWN(val) ((val) << 17) + +#define APB_SOC_JTAGREG_INT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC(val) ((val) << 0) + +#define APB_SOC_JTAGREG_INT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD(val) ((val) << 1) + +#define APB_SOC_JTAGREG_EXT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC(val) ((val) << 8) + +#define APB_SOC_JTAGREG_EXT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD(val) ((val) << 9) + +#define APB_SOC_L2_SLEEP_L2_SLEEP_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_L2_SLEEP_L2_SLEEP_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_L2_SLEEP_L2_SLEEP_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_L2_SLEEP_L2_SLEEP(val) ((val) << 0) + +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_STATUS(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_RO_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define APB_SOC_SAFE_PMU_RAR_NV_VOLT(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define APB_SOC_SAFE_PMU_RAR_MV_VOLT(val) ((val) << 8) + +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_GET(value) (ARCHI_BEXTRACTU((value),5,16)) +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_GETS(value) (ARCHI_BEXTRACT((value),5,16)) +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT_SET(value,field) (ARCHI_BINSERT((value),(field),5,16)) +#define APB_SOC_SAFE_PMU_RAR_LV_VOLT(val) ((val) << 16) + +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_GET(value) (ARCHI_BEXTRACTU((value),5,24)) +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_GETS(value) (ARCHI_BEXTRACT((value),5,24)) +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT_SET(value,field) (ARCHI_BINSERT((value),(field),5,24)) +#define APB_SOC_SAFE_PMU_RAR_RV_VOLT(val) ((val) << 24) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R0(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R1(val) ((val) << 1) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R2(val) ((val) << 2) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_L2_R3(val) ((val) << 3) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SOC_FLL(val) ((val) << 4) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_FLL(val) ((val) << 5) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_GET(value) (ARCHI_BEXTRACTU((value),5,6)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_GETS(value) (ARCHI_BEXTRACT((value),5,6)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC_SET(value,field) (ARCHI_BINSERT((value),(field),5,6)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_SRC(val) ((val) << 6) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GET(value) (ARCHI_BEXTRACTU((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GETS(value) (ARCHI_BEXTRACT((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE(val) ((val) << 11) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN(val) ((val) << 13) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_WAKESTATE(val) ((val) << 15) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTDEV(val) ((val) << 16) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTINT(val) ((val) << 17) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_GET(value) (ARCHI_BEXTRACTU((value),2,18)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_GETS(value) (ARCHI_BEXTRACT((value),2,18)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,18)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_BTTYPE(val) ((val) << 18) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_GET(value) (ARCHI_BEXTRACTU((value),1,20)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_GETS(value) (ARCHI_BEXTRACT((value),1,20)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE_SET(value,field) (ARCHI_BINSERT((value),(field),1,20)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CL_WAKE(val) ((val) << 20) + +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R0(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R1(val) ((val) << 1) + +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R2(val) ((val) << 2) + +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define APB_SOC_SAFE_PMU_FORCE_RET_L2_R3(val) ((val) << 3) + +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R0(val) ((val) << 4) + +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R1(val) ((val) << 5) + +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R2(val) ((val) << 6) + +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define APB_SOC_SAFE_PMU_FORCE_PD_L2_R3(val) ((val) << 7) + +#define APB_SOC_SAFE_PADSLEEP_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_SAFE_PADSLEEP_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_SAFE_PADSLEEP_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_SAFE_PADSLEEP_EN(val) ((val) << 0) + +#define APB_SOC_REG_GPIO_ISO_ISO_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_REG_GPIO_ISO_ISO_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_REG_GPIO_ISO_ISO_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_REG_GPIO_ISO_ISO(val) ((val) << 0) + +#define APB_SOC_REG_CAM_ISO_ISO_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_REG_CAM_ISO_ISO_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_REG_CAM_ISO_ISO_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_REG_CAM_ISO_ISO(val) ((val) << 0) + +#define APB_SOC_REG_LVDS_ISO_ISO_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_REG_LVDS_ISO_ISO_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_REG_LVDS_ISO_ISO_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_REG_LVDS_ISO_ISO(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/gap/memory_map.h new file mode 100644 index 0000000..6d3dcde --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap/memory_map.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_GAP_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_GAP_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_ADDR 0x1c000000 +#define ARCHI_L2_SIZE 0x00080000 + +#define ARCHI_FC_TCDM_ADDR 0x1b000000 +#define ARCHI_FC_TCDM_SIZE 0x00004000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_PWM_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_PMU_OFFSET 0x00007000 +#define ARCHI_RTC_BASE_OFFSET 0x00008000 +#define ARCHI_EFUSE_OFFSET 0x00009000 +#define ARCHI_STDOUT_OFFSET 0x00010000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_PWM_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PWM_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_PMU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PMU_OFFSET ) +#define ARCHI_EFUSE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_EFUSE_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_RTC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_RTC_BASE_OFFSET ) + + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + + +/* + * FC PERIPHERALS + */ + +#define ARCHI_FC_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_FC_PERIPHERALS_ADDR ( ARCHI_FC_ADDR + ARCHI_FC_PERIPHERALS_OFFSET ) + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FC_TIMER_OFFSET 0x00000400 +#define ARCHI_FC_EU_OFFSET 0x00000800 +#define ARCHI_FC_ICACHE_OFFSET 0x00001400 + +#define ARCHI_FC_TIMER_ADDR ( ARCHI_FC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_FC_EU_ADDR ( ARCHI_FC_PERIPHERALS_ADDR + ARCHI_FC_EU_OFFSET ) +#define ARCHI_FC_ICACHE_ADDR ( ARCHI_FC_PERIPHERALS_ADDR + ARCHI_FC_ICACHE_OFFSET ) + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap/padframe.h b/sw/pulp-sdk/archi/include/archi/chips/gap/padframe.h new file mode 100644 index 0000000..852f2d2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap/padframe.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_GAP_PADFRAME_H__ +#define __ARCHI_GAP_PADFRAME_H__ + +#define PLP_PAD_GPIO_0 8 +#define PLP_PAD_GPIO_1 9 +#define PLP_PAD_GPIO_2 10 +#define PLP_PAD_GPIO_3 11 +#define PLP_PAD_GPIO_0_A 12 +#define PLP_PAD_GPIO_1_A 13 +#define PLP_PAD_GPIO_2_A 14 +#define PLP_PAD_GPIO_3_A 15 +#define PLP_PAD_GPIO_4_A 16 +#define PLP_PAD_GPIO_5_A 17 +#define PLP_PAD_GPIO_4 18 +#define PLP_PAD_GPIO_5 19 +#define PLP_PAD_GPIO_6 20 +#define PLP_PAD_GPIO_7 21 +#define PLP_PAD_GPIO_8 22 +#define PLP_PAD_GPIO_9 23 +#define PLP_PAD_GPIO_10 24 +#define PLP_PAD_GPIO_11 25 +#define PLP_PAD_GPIO_12 26 +#define PLP_PAD_GPIO_13 27 +#define PLP_PAD_GPIO_14 28 +#define PLP_PAD_GPIO_15 29 +#define PLP_PAD_GPIO_16 30 +#define PLP_PAD_GPIO_17 31 +#define PLP_PAD_GPIO_18 32 +#define PLP_PAD_GPIO_19 33 +#define PLP_PAD_GPIO_20 34 +#define PLP_PAD_GPIO_21 35 +#define PLP_PAD_GPIO_22 36 +#define PLP_PAD_GPIO_23 37 +#define PLP_PAD_GPIO_24 38 +#define PLP_PAD_GPIO_25 39 +#define PLP_PAD_GPIO_26 42 +#define PLP_PAD_GPIO_27 43 +#define PLP_PAD_GPIO_28 45 +#define PLP_PAD_GPIO_29 47 +#define PLP_PAD_GPIO_30 48 +#define PLP_PAD_GPIO_31 49 + +#define PLP_PAD_RF_MISO 8 +#define PLP_PAD_RF_MOSI 9 +#define PLP_PAD_RF_CSN 10 +#define PLP_PAD_RF_SCK 11 +#define PLP_PAD_GPIO_PACTRL0 12 +#define PLP_PAD_GPIO_PACTRL1 13 +#define PLP_PAD_GPIO_PACTRL2 14 +#define PLP_PAD_GPIO_PACTRL3 15 +#define PLP_PAD_GPIO_PACTRL4 16 +#define PLP_PAD_GPIO_PACTRL5 17 +#define PLP_PAD_CAM_PCLK 18 +#define PLP_PAD_CAM_HSYNC 19 +#define PLP_PAD_CAM_DATA0 20 +#define PLP_PAD_CAM_DATA1 21 +#define PLP_PAD_CAM_DATA2 22 +#define PLP_PAD_CAM_DATA3 23 +#define PLP_PAD_CAM_DATA4 24 +#define PLP_PAD_CAM_DATA5 25 +#define PLP_PAD_CAM_DATA6 26 +#define PLP_PAD_CAM_DATA7 27 +#define PLP_PAD_CAM_VSYNC 28 +#define PLP_PAD_CAM_SDA 29 +#define PLP_PAD_CAM_SCL 30 +#define PLP_PAD_TIMER0_CH0 31 +#define PLP_PAD_TIMER0_CH1 32 +#define PLP_PAD_TIMER0_CH2 33 +#define PLP_PAD_TIMER0_CH3 34 +#define PLP_PAD_I2S1_SCK 35 +#define PLP_PAD_I2S1_WS 36 +#define PLP_PAD_I2S1_SDI 37 +#define PLP_PAD_UART_RX 38 +#define PLP_PAD_UART_TX 39 +#define PLP_PAD_SPIM_SDIO0 40 +#define PLP_PAD_SPIM_SDIO1 41 +#define PLP_PAD_SPIM_SDIO2 42 +#define PLP_PAD_SPIM_SDIO3 43 +#define PLP_PAD_SPIM_CSN0 44 +#define PLP_PAD_SPIM_CSN1 45 +#define PLP_PAD_SPIM_SCK 46 +#define PLP_PAD_SPIM1_CSN 47 +#define PLP_PAD_SPIM1_CS0 47 +#define PLP_PAD_SPIM1_MISO 48 +#define PLP_PAD_SPIM1_MOSI 49 +#define PLP_PAD_SPIM1_SCK 50 + +#define PLP_PAD_SPIS0_SDIO0 16 +#define PLP_PAD_SPIS0_SDIO1 17 +#define PLP_PAD_SPIS0_SCK 35 +#define PLP_PAD_SPIS0_CS 36 +#define PLP_PAD_SPIS0_SDIO2 37 +#define PLP_PAD_SPIS0_SDIO3 45 + +#define PLP_PAD_ORCA_TXSYNC 12 +#define PLP_PAD_ORCA_RXSYNC 13 +#define PLP_PAD_ORCA_TXI 14 +#define PLP_PAD_ORCA_TXQ 15 +#define PLP_PAD_ORCA_RXI 16 +#define PLP_PAD_ORCA_RXQ 17 +#define PLP_PAD_ORCA_CLK 30 + +#define PLP_PAD_HYPER_CKN 36 +#define PLP_PAD_HYPER_CK 37 +#define PLP_PAD_HYPER_DQ0 40 +#define PLP_PAD_HYPER_DQ1 41 +#define PLP_PAD_HYPER_DQ2 42 +#define PLP_PAD_HYPER_DQ3 43 +#define PLP_PAD_HYPER_DQ4 44 +#define PLP_PAD_HYPER_DQ5 45 +#define PLP_PAD_HYPER_DQ6 46 +#define PLP_PAD_HYPER_DQ7 47 +#define PLP_PAD_HYPER_CSN0 48 +#define PLP_PAD_HYPER_CSN1 49 +#define PLP_PAD_HYPER_RWDS 50 + +#define PLP_PAD_GPIO_DEFAULT 0 +#define PLP_PAD_GPIO_ALTERNATE1 1 +#define PLP_PAD_GPIO_ALTERNATE2 2 +#define PLP_PAD_GPIO_ALTERNATE3 3 + +#define PLP_PAD_GPIO_NUM 32 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap/properties.h b/sw/pulp-sdk/archi/include/archi/chips/gap/properties.h new file mode 100644 index 0000000..3bf4206 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap/properties.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_GAP_PROPERTIES_H__ +#define __ARCHI_CHIPS_GAP_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 +#define ARCHI_HAS_FC_TCDM 1 + +#define ARCHI_L1_SIZE 65536 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define HWCE_VERSION 4 +#define MCHAN_VERSION 6 +#define EFUSE_VERSION 1 +#define PADS_VERSION 2 +#define PWM_VERSION 1 + + +/* + * SOC + */ + +#define ARCHI_PWM_NB 1 +#define ARCHI_PWM_NB_TIMERS 4 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 +#if PULP_CHIP != CHIP_GAP +#define ARCHI_HAS_CLUSTER_CLK_GATE 1 +#endif + +/* + * CLUSTER EVENT UNIT + */ + +//#define ARCHI_HAS_NO_BARRIER 1 +//#define ARCHI_HAS_NO_DISPATCH 1 +//#define ARCHI_HAS_NO_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 32 +#define ARCHI_HAS_FC_EU 1 +#define ARCHI_FC_HAS_ICACHE 1 +#define ARCHI_HAS_FC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 0 // FIXME put it to the right value once the padframe is specified +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_SLEEP_CONTROL 0x104 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 8 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 8 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap9/apb_soc_ctrl.h b/sw/pulp-sdk/archi/include/archi/chips/gap9/apb_soc_ctrl.h new file mode 100644 index 0000000..e07d9ad --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap9/apb_soc_ctrl.h @@ -0,0 +1,1581 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_VEGA_APB_SOC_CTRL_H__ +#define __INCLUDE_ARCHI_CHIPS_VEGA_APB_SOC_CTRL_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Core information register +#define APB_SOC_INFO_OFFSET 0x0 + +// Boot address +#define APB_SOC_FC_BOOT_OFFSET 0x4 + +// FC Fetch enable +#define APB_SOC_FC_FETCH_OFFSET 0x8 + +// Isolate cluster register +#define APB_SOC_CL_ISOLATE_OFFSET 0xc + +// Mux config register (pad 0-15) +#define APB_SOC_PADFUN0_OFFSET 0x10 + +// Mux config register (pad 16-31) +#define APB_SOC_PADFUN1_OFFSET 0x14 + +// Mux config register (pad 32-47) +#define APB_SOC_PADFUN2_OFFSET 0x18 + +// Mux config register (pad 48-63) +#define APB_SOC_PADFUN3_OFFSET 0x1c + +// Function register (pad 0 to 3) +#define APB_SOC_PADCFG0_OFFSET 0x20 + +// Function register (pad 4 to 7) +#define APB_SOC_PADCFG1_OFFSET 0x24 + +// Function register (pad 8 to 11) +#define APB_SOC_PADCFG2_OFFSET 0x28 + +// Function register (pad 12 to 15) +#define APB_SOC_PADCFG3_OFFSET 0x2c + +// Function register (pad 16 to 19) +#define APB_SOC_PADCFG4_OFFSET 0x30 + +// Function register (pad 20 to 23) +#define APB_SOC_PADCFG5_OFFSET 0x34 + +// Function register (pad 24 to 27) +#define APB_SOC_PADCFG6_OFFSET 0x38 + +// Function register (pad 28 to 31) +#define APB_SOC_PADCFG7_OFFSET 0x3c + +// Function register (pad 32 to 35) +#define APB_SOC_PADCFG8_OFFSET 0x40 + +// Function register (pad 36 to 39) +#define APB_SOC_PADCFG9_OFFSET 0x44 + +// Function register (pad 40 to 43) +#define APB_SOC_PADCFG10_OFFSET 0x48 + +// Function register (pad 44 to 47) +#define APB_SOC_PADCFG11_OFFSET 0x4c + +// Function register (pad 48 to 51) +#define APB_SOC_PADCFG12_OFFSET 0x50 + +// Function register (pad 52 to 55) +#define APB_SOC_PADCFG13_OFFSET 0x54 + +// Function register (pad 56 to 59) +#define APB_SOC_PADCFG14_OFFSET 0x58 + +// Function register (pad 60 to 63) +#define APB_SOC_PADCFG15_OFFSET 0x5c + +// Cluster busy register +#define APB_SOC_CL_BUSY_OFFSET 0x6c + +// JTAG external register +#define APB_SOC_JTAGREG_OFFSET 0x74 + +// Alias for SAFE_PMU_SLEEPCTRL +#define APB_SOC_SLEEP_CTRL_OFFSET 0x7c + +// Clock divider for I3C +#define APB_SOC_CLK_DIV_I3C_OFFSET 0x80 + +// EOC and chip status register +#define APB_SOC_CORESTATUS_OFFSET 0xa0 + +// EOC and chip status register read mirror +#define APB_SOC_CORESTATUS_RO_OFFSET 0xc0 + +// Value of pad bootsel +#define APB_SOC_BOOTSEL_OFFSET 0xc4 + +// Clear WD timer +#define APB_SOC_WD_CLR_OFFSET 0xc8 + +// Clock selection for SOC,Cluster and Periph +#define APB_SOC_CLK_SEL_OFFSET 0xd0 + +// SOC Clock Divider settings +#define APB_SOC_CLK_DIV_SOC_OFFSET 0xd4 + +// Cluster Clock Divider settings +#define APB_SOC_CLK_DIV_CLU_OFFSET 0xd8 + +// Peripheral Clock Divider Settings +#define APB_SOC_CLK_DIV_PER_OFFSET 0xdc + +// nan +#define APB_SOC_SUPERVISOR_DBG_OFFSET 0xe0 + +// nan +#define APB_SOC_RWM_GRP0_OFFSET 0xe4 + +// nan +#define APB_SOC_RWM_GRP1_OFFSET 0xe8 + +// nan +#define APB_SOC_RWM_GRP2_OFFSET 0xec + +// nan +#define APB_SOC_RWM_GRP3_OFFSET 0xf0 + +// nan +#define APB_SOC_RWM_GRP4_OFFSET 0xf4 + +// nan +#define APB_SOC_RWM_GRP5_OFFSET 0xf8 + +// nan +#define APB_SOC_RWM_GRP6_OFFSET 0xfc + +// Sleep modes configuration register +#define APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET 0x104 + +// Enables and configures WatchDog Timer +#define APB_SOC_SAFE_WD_OFFSET 0x110 + +// Sleep config register (pad 0-7) +#define APB_SOC_SAFE_SLEEPPADCFG0_OFFSET 0x150 + +// Sleep config register (pad 8-15) +#define APB_SOC_SAFE_SLEEPPADCFG1_OFFSET 0x154 + +// Config timings for NEVA +#define APB_SOC_SAFE_NEVACF_OFFSET 0x164 + +// General purpouse register AO +#define APB_SOC_SAFE_GPREG_OFFSET 0x170 + +// L2 standby configuration +#define APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET 0x174 + +// FLL2 and FLL3 power control +#define APB_SOC_SAFE_FLL_CTRL_OFFSET 0x178 + +// L1 power control +#define APB_SOC_SAFE_L1_PWR_CTRL_OFFSET 0x17c + +// L2 power control +#define APB_SOC_SAFE_L2_PWR_CTRL_OFFSET 0x180 + +// GPIO power domain pad input isolation register +#define APB_SOC_REG_GPIO_ISO_OFFSET 0x1c0 + +// CAM power domain pad input isolation register +#define APB_SOC_REG_CAM_ISO_OFFSET 0x1c4 + +// LVDS power domain pad input isolation register +#define APB_SOC_REG_LVDS_ISO_OFFSET 0x1c8 + + + +// +// REGISTERS FIELDS +// + +// Number of clusters (access: R) +#define APB_SOC_INFO_NB_CL_BIT 0 +#define APB_SOC_INFO_NB_CL_WIDTH 16 +#define APB_SOC_INFO_NB_CL_MASK 0xffff + +// Number of cores (access: R) +#define APB_SOC_INFO_NB_CORES_BIT 16 +#define APB_SOC_INFO_NB_CORES_WIDTH 16 +#define APB_SOC_INFO_NB_CORES_MASK 0xffff0000 + +// FC Boot Address (access: R/W) +#define APB_SOC_FC_BOOT_ADDR_BIT 0 +#define APB_SOC_FC_BOOT_ADDR_WIDTH 32 +#define APB_SOC_FC_BOOT_ADDR_MASK 0xffffffff + +// FC Fetch Enable (access: R/W) +#define APB_SOC_FC_FETCH_FC_FE_BIT 0 +#define APB_SOC_FC_FETCH_FC_FE_WIDTH 1 +#define APB_SOC_FC_FETCH_FC_FE_MASK 0x1 + +// Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable (access: R/W) +#define APB_SOC_CL_ISOLATE_EN_BIT 0 +#define APB_SOC_CL_ISOLATE_EN_WIDTH 1 +#define APB_SOC_CL_ISOLATE_EN_MASK 0x1 + +// Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) (access: R) +#define APB_SOC_CL_BUSY_BUSY_BIT 0 +#define APB_SOC_CL_BUSY_BUSY_WIDTH 1 +#define APB_SOC_CL_BUSY_BUSY_MASK 0x1 + +// JTAG internal register used for synchronisation from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_SYNC_BIT 0 +#define APB_SOC_JTAGREG_INT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_INT_SYNC_MASK 0x1 + +// JTAG internal register used for selecting boot mode configuration from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_BT_MD_BIT 1 +#define APB_SOC_JTAGREG_INT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_INT_BT_MD_MASK 0xe + +// JTAG external register used for synchronisation from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_SYNC_BIT 8 +#define APB_SOC_JTAGREG_EXT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_EXT_SYNC_MASK 0x100 + +// JTAG external register used for selecting boot mode configuration from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_BT_MD_BIT 9 +#define APB_SOC_JTAGREG_EXT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_EXT_BT_MD_MASK 0xe00 + +// Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) (access: R) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT 0 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH 32 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_MASK 0xffffffff + +// EOC and chip status register (access: R/W) +#define APB_SOC_CORESTATUS_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_STATUS_MASK 0xffffffff + +// EOC and chip status register (access: R) +#define APB_SOC_CORESTATUS_RO_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_RO_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_RO_STATUS_MASK 0xffffffff + +// SoC domain clock selection: - 1b0: First FLL is used (FLL1) - 1b1: Second FLL is used (FLL2) (access: R/W) +#define APB_SOC_CLK_SEL_CLK_SOC_BIT 0 +#define APB_SOC_CLK_SEL_CLK_SOC_WIDTH 1 +#define APB_SOC_CLK_SEL_CLK_SOC_MASK 0x1 + +// Cluster domain clock selection: - 2b00: First FLL is used (FLL1) - 2b01: Second FLL is used (FLL2) - 2b10: Third FLL is used (FLL3) (access: R/W) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_BIT 1 +#define APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH 2 +#define APB_SOC_CLK_SEL_CLK_CLUSTER_MASK 0x6 + +// User value which is kept retentive after wakeup (even in non-retentive sleep). This value is only partially interpreted by the ROM code (TBD) to distinguish betweem cold boot, non-retentive sleep and retentive sleep. (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT 0 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH 3 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_MASK 0x7 + +// Enable smart wake-up; - 1'b0; smart wake-up disabled - 1'b1: smart wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT 9 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_MASK 0x200 + +// Enable RTC wake-up; - 1'b0; rtc wake-up disabled - 1'b1: rtc wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT 10 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_MASK 0x400 + +// Select external wake-up mode (through dedicated pin): - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT 11 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH 2 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_MASK 0x1800 + +// Enable external wake-up (through dedicated pin); - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT 13 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_MASK 0x2000 + +// Power state of the MRAM to restore after warm boot - 1'b0: MRAM OFF - 1'b1: MRAM ON (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT 14 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_MASK 0x4000 + +// Power state of the cluster to restore after warm boot - 1'b0: cluster OFF - 1'b1: cluster ON (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT 15 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_MASK 0x8000 + +// Configure retention mode of L2 memory. There is one bit per cut: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT 16 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH 16 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_MASK 0xffff0000 + +// Pad state when the chip is down with low-speed IOs ON: - 4b0000: Tristate with no pull-up and no pull-down - 4b0001: Tristate with pull-up - 4b0010: Tristate with pull-down - 4b0011: Drive 0 - 4b0100: Drive 1 (access: R/W) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT 0 +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH 4 +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_MASK 0xf + +// L2 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. (access: R/W) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT 0 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH 4 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_MASK 0xf + +// L2 cuts standby active low. One bit per L2 cut for 16 cuts, the cut is in standby when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT 4 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH 16 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_MASK 0xffff0 + +// FLL2 power down. The FLL is powered down when this bit is 1b1. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT 0 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_MASK 0x1 + +// FLL3 power down. The FLL is powered down when this bit is 1b1. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_MASK 0x2 + +// FLL2 reset active low. The FLL is reset when this bit is 1b0. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT 2 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_MASK 0x4 + +// FLL3 reset active low. The FLL is reset when this bit is 1b0. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT 3 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_MASK 0x8 + +// L1 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT 0 +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH 4 +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_MASK 0xf + +// L1 cuts standby active low. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT 4 +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH 2 +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_MASK 0x30 + +// L1 power down. The corresponding L1 part is powered down when this bit is 1b1. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT 6 +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH 2 +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_MASK 0xc0 + +// L2 VDDDE active low. One bit per L2 cut for 16 cuts, the cut periphery is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT 0 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_MASK 0xffff + +// L2 VDDME active low. One bit per L2 cut for 16 cuts, the cut array is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_MASK 0xffff0000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int nb_cl :16; // Number of clusters + unsigned int nb_cores :16; // Number of cores + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_info_t; + +typedef union { + struct { + unsigned int addr :32; // FC Boot Address + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_fc_boot_t; + +typedef union { + struct { + unsigned int fc_fe :1 ; // FC Fetch Enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_fc_fetch_t; + +typedef union { + struct { + unsigned int en :1 ; // Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_isolate_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg4_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg5_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg6_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg7_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg8_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg9_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg10_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg11_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg12_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg13_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg14_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg15_t; + +typedef union { + struct { + unsigned int busy :1 ; // Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_busy_t; + +typedef union { + struct { + unsigned int int_sync :1 ; // JTAG internal register used for synchronisation from external debugger + unsigned int int_bt_md :3 ; // JTAG internal register used for selecting boot mode configuration from external debugger + unsigned int padding0:4 ; + unsigned int ext_sync :1 ; // JTAG external register used for synchronisation from external debugger + unsigned int ext_bt_md :3 ; // JTAG external register used for selecting boot mode configuration from external debugger + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_jtagreg_t; + +typedef union { + struct { + unsigned int sleep_ctrl :32; // Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_sleep_ctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_i3c_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_ro_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_bootsel_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_wd_clr_t; + +typedef union { + struct { + unsigned int clk_soc :1 ; // SoC domain clock selection: - 1b0: First FLL is used (FLL1) - 1b1: Second FLL is used (FLL2) + unsigned int clk_cluster :2 ; // Cluster domain clock selection: - 2b00: First FLL is used (FLL1) - 2b01: Second FLL is used (FLL2) - 2b10: Third FLL is used (FLL3) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_sel_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_soc_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_clu_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_per_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_supervisor_dbg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp4_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp5_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp6_t; + +typedef union { + struct { + unsigned int reboot :3 ; // User value which is kept retentive after wakeup (even in non-retentive sleep). This value is only partially interpreted by the ROM code (TBD) to distinguish betweem cold boot, non-retentive sleep and retentive sleep. + unsigned int padding0:6 ; + unsigned int smartwake_en :1 ; // Enable smart wake-up; - 1'b0; smart wake-up disabled - 1'b1: smart wake-up enabled + unsigned int rtcwake_en :1 ; // Enable RTC wake-up; - 1'b0; rtc wake-up disabled - 1'b1: rtc wake-up enabled + unsigned int extwake_type :2 ; // Select external wake-up mode (through dedicated pin): - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level + unsigned int extwake_en :1 ; // Enable external wake-up (through dedicated pin); - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled + unsigned int mram_wakestate :1 ; // Power state of the MRAM to restore after warm boot - 1'b0: MRAM OFF - 1'b1: MRAM ON + unsigned int cluster_wakestate:1 ; // Power state of the cluster to restore after warm boot - 1'b0: cluster OFF - 1'b1: cluster ON + unsigned int ret_mem :16; // Configure retention mode of L2 memory. There is one bit per cut: - 1'b0: Non retentive - 1'b1: Retentive + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_pmu_sleepctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_wd_t; + +typedef union { + struct { + unsigned int state :4 ; // Pad state when the chip is down with low-speed IOs ON: - 4b0000: Tristate with no pull-up and no pull-down - 4b0001: Tristate with pull-up - 4b0010: Tristate with pull-down - 4b0011: Drive 0 - 4b0100: Drive 1 + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_nevacf_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_gpreg_t; + +typedef union { + struct { + unsigned int btrim :4 ; // L2 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. + unsigned int stdby_n :16; // L2 cuts standby active low. One bit per L2 cut for 16 cuts, the cut is in standby when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l2_btrim_stdby_t; + +typedef union { + struct { + unsigned int fll2_pwd :1 ; // FLL2 power down. The FLL is powered down when this bit is 1b1. + unsigned int fll3_pwd :1 ; // FLL3 power down. The FLL is powered down when this bit is 1b1. + unsigned int fll2_rstb :1 ; // FLL2 reset active low. The FLL is reset when this bit is 1b0. + unsigned int fll3_rstb :1 ; // FLL3 reset active low. The FLL is reset when this bit is 1b0. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_fll_ctrl_t; + +typedef union { + struct { + unsigned int btrim :4 ; // L1 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. + unsigned int stdby_n :2 ; // L1 cuts standby active low. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. + unsigned int pwd :2 ; // L1 power down. The corresponding L1 part is powered down when this bit is 1b1. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l1_pwr_ctrl_t; + +typedef union { + struct { + unsigned int vddde_n :16; // L2 VDDDE active low. One bit per L2 cut for 16 cuts, the cut periphery is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + unsigned int vddme_n :16; // L2 VDDME active low. One bit per L2 cut for 16 cuts, the cut array is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l2_pwr_ctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_gpio_iso_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_cam_iso_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_lvds_iso_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_info : public vp::reg_32 +{ +public: + inline void nb_cl_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline uint32_t nb_cl_get() { return this->get_field(APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline void nb_cores_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } + inline uint32_t nb_cores_get() { return this->get_field(APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } +}; + +class vp_apb_soc_fc_boot : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, APB_SOC_FC_BOOT_ADDR_BIT, APB_SOC_FC_BOOT_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(APB_SOC_FC_BOOT_ADDR_BIT, APB_SOC_FC_BOOT_ADDR_WIDTH); } +}; + +class vp_apb_soc_fc_fetch : public vp::reg_32 +{ +public: + inline void fc_fe_set(uint32_t value) { this->set_field(value, APB_SOC_FC_FETCH_FC_FE_BIT, APB_SOC_FC_FETCH_FC_FE_WIDTH); } + inline uint32_t fc_fe_get() { return this->get_field(APB_SOC_FC_FETCH_FC_FE_BIT, APB_SOC_FC_FETCH_FC_FE_WIDTH); } +}; + +class vp_apb_soc_cl_isolate : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } +}; + +class vp_apb_soc_padfun0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg4 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg5 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg6 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg7 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg8 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg9 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg10 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg11 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg12 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg13 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg14 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg15 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_cl_busy : public vp::reg_32 +{ +public: + inline void busy_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } + inline uint32_t busy_get() { return this->get_field(APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } +}; + +class vp_apb_soc_jtagreg : public vp::reg_32 +{ +public: + inline void int_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline uint32_t int_sync_get() { return this->get_field(APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline void int_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline uint32_t int_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline void ext_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline uint32_t ext_sync_get() { return this->get_field(APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline void ext_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } + inline uint32_t ext_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } +}; + +class vp_apb_soc_sleep_ctrl : public vp::reg_32 +{ +public: + inline void sleep_ctrl_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } + inline uint32_t sleep_ctrl_get() { return this->get_field(APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } +}; + +class vp_apb_soc_clk_div_i3c : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_corestatus : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } +}; + +class vp_apb_soc_corestatus_ro : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } +}; + +class vp_apb_soc_bootsel : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_wd_clr : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_sel : public vp::reg_32 +{ +public: + inline void clk_soc_set(uint32_t value) { this->set_field(value, APB_SOC_CLK_SEL_CLK_SOC_BIT, APB_SOC_CLK_SEL_CLK_SOC_WIDTH); } + inline uint32_t clk_soc_get() { return this->get_field(APB_SOC_CLK_SEL_CLK_SOC_BIT, APB_SOC_CLK_SEL_CLK_SOC_WIDTH); } + inline void clk_cluster_set(uint32_t value) { this->set_field(value, APB_SOC_CLK_SEL_CLK_CLUSTER_BIT, APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH); } + inline uint32_t clk_cluster_get() { return this->get_field(APB_SOC_CLK_SEL_CLK_CLUSTER_BIT, APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH); } +}; + +class vp_apb_soc_clk_div_soc : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_div_clu : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_div_per : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_supervisor_dbg : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp4 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp5 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp6 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_pmu_sleepctrl : public vp::reg_32 +{ +public: + inline void reboot_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH); } + inline uint32_t reboot_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH); } + inline void smartwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH); } + inline uint32_t smartwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH); } + inline void rtcwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH); } + inline uint32_t rtcwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH); } + inline void extwake_type_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline uint32_t extwake_type_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline void extwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline uint32_t extwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline void mram_wakestate_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH); } + inline uint32_t mram_wakestate_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH); } + inline void cluster_wakestate_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH); } + inline uint32_t cluster_wakestate_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH); } + inline void ret_mem_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH); } + inline uint32_t ret_mem_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH); } +}; + +class vp_apb_soc_safe_wd : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg0 : public vp::reg_32 +{ +public: + inline void state_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT, APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH); } + inline uint32_t state_get() { return this->get_field(APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT, APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH); } +}; + +class vp_apb_soc_safe_sleeppadcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_nevacf : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_gpreg : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_l2_btrim_stdby : public vp::reg_32 +{ +public: + inline void btrim_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH); } + inline uint32_t btrim_get() { return this->get_field(APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH); } + inline void stdby_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH); } + inline uint32_t stdby_n_get() { return this->get_field(APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH); } +}; + +class vp_apb_soc_safe_fll_ctrl : public vp::reg_32 +{ +public: + inline void fll2_pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH); } + inline uint32_t fll2_pwd_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH); } + inline void fll3_pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH); } + inline uint32_t fll3_pwd_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH); } + inline void fll2_rstb_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH); } + inline uint32_t fll2_rstb_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH); } + inline void fll3_rstb_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH); } + inline uint32_t fll3_rstb_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH); } +}; + +class vp_apb_soc_safe_l1_pwr_ctrl : public vp::reg_32 +{ +public: + inline void btrim_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH); } + inline uint32_t btrim_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH); } + inline void stdby_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH); } + inline uint32_t stdby_n_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH); } + inline void pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT, APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH); } + inline uint32_t pwd_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT, APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH); } +}; + +class vp_apb_soc_safe_l2_pwr_ctrl : public vp::reg_32 +{ +public: + inline void vddde_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH); } + inline uint32_t vddde_n_get() { return this->get_field(APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH); } + inline void vddme_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH); } + inline uint32_t vddme_n_get() { return this->get_field(APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH); } +}; + +class vp_apb_soc_reg_gpio_iso : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_reg_cam_iso : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_reg_lvds_iso : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int info ; // Core information register + unsigned int fc_boot ; // Boot address + unsigned int fc_fetch ; // FC Fetch enable + unsigned int cl_isolate ; // Isolate cluster register + unsigned int padfun0 ; // Mux config register (pad 0-15) + unsigned int padfun1 ; // Mux config register (pad 16-31) + unsigned int padfun2 ; // Mux config register (pad 32-47) + unsigned int padfun3 ; // Mux config register (pad 48-63) + unsigned int padcfg0 ; // Function register (pad 0 to 3) + unsigned int padcfg1 ; // Function register (pad 4 to 7) + unsigned int padcfg2 ; // Function register (pad 8 to 11) + unsigned int padcfg3 ; // Function register (pad 12 to 15) + unsigned int padcfg4 ; // Function register (pad 16 to 19) + unsigned int padcfg5 ; // Function register (pad 20 to 23) + unsigned int padcfg6 ; // Function register (pad 24 to 27) + unsigned int padcfg7 ; // Function register (pad 28 to 31) + unsigned int padcfg8 ; // Function register (pad 32 to 35) + unsigned int padcfg9 ; // Function register (pad 36 to 39) + unsigned int padcfg10 ; // Function register (pad 40 to 43) + unsigned int padcfg11 ; // Function register (pad 44 to 47) + unsigned int padcfg12 ; // Function register (pad 48 to 51) + unsigned int padcfg13 ; // Function register (pad 52 to 55) + unsigned int padcfg14 ; // Function register (pad 56 to 59) + unsigned int padcfg15 ; // Function register (pad 60 to 63) + unsigned int cl_busy ; // Cluster busy register + unsigned int jtagreg ; // JTAG external register + unsigned int sleep_ctrl ; // Alias for SAFE_PMU_SLEEPCTRL + unsigned int clk_div_i3c ; // Clock divider for I3C + unsigned int corestatus ; // EOC and chip status register + unsigned int corestatus_ro ; // EOC and chip status register read mirror + unsigned int bootsel ; // Value of pad bootsel + unsigned int wd_clr ; // Clear WD timer + unsigned int clk_sel ; // Clock selection for SOC,Cluster and Periph + unsigned int clk_div_soc ; // SOC Clock Divider settings + unsigned int clk_div_clu ; // Cluster Clock Divider settings + unsigned int clk_div_per ; // Peripheral Clock Divider Settings + unsigned int supervisor_dbg ; // nan + unsigned int rwm_grp0 ; // nan + unsigned int rwm_grp1 ; // nan + unsigned int rwm_grp2 ; // nan + unsigned int rwm_grp3 ; // nan + unsigned int rwm_grp4 ; // nan + unsigned int rwm_grp5 ; // nan + unsigned int rwm_grp6 ; // nan + unsigned int safe_pmu_sleepctrl; // Sleep modes configuration register + unsigned int safe_wd ; // Enables and configures WatchDog Timer + unsigned int safe_sleeppadcfg0; // Sleep config register (pad 0-7) + unsigned int safe_sleeppadcfg1; // Sleep config register (pad 8-15) + unsigned int safe_nevacf ; // Config timings for NEVA + unsigned int safe_gpreg ; // General purpouse register AO + unsigned int safe_l2_btrim_stdby; // L2 standby configuration + unsigned int safe_fll_ctrl ; // FLL2 and FLL3 power control + unsigned int safe_l1_pwr_ctrl; // L1 power control + unsigned int safe_l2_pwr_ctrl; // L2 power control + unsigned int reg_gpio_iso ; // GPIO power domain pad input isolation register + unsigned int reg_cam_iso ; // CAM power domain pad input isolation register + unsigned int reg_lvds_iso ; // LVDS power domain pad input isolation register +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t apb_soc_info_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_INFO_OFFSET); } +static inline void apb_soc_info_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_INFO_OFFSET, value); } + +static inline uint32_t apb_soc_fc_boot_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_FC_BOOT_OFFSET); } +static inline void apb_soc_fc_boot_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_FC_BOOT_OFFSET, value); } + +static inline uint32_t apb_soc_fc_fetch_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_FC_FETCH_OFFSET); } +static inline void apb_soc_fc_fetch_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_FC_FETCH_OFFSET, value); } + +static inline uint32_t apb_soc_cl_isolate_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_ISOLATE_OFFSET); } +static inline void apb_soc_cl_isolate_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_ISOLATE_OFFSET, value); } + +static inline uint32_t apb_soc_padfun0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN0_OFFSET); } +static inline void apb_soc_padfun0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN0_OFFSET, value); } + +static inline uint32_t apb_soc_padfun1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN1_OFFSET); } +static inline void apb_soc_padfun1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN1_OFFSET, value); } + +static inline uint32_t apb_soc_padfun2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN2_OFFSET); } +static inline void apb_soc_padfun2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN2_OFFSET, value); } + +static inline uint32_t apb_soc_padfun3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN3_OFFSET); } +static inline void apb_soc_padfun3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN3_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG0_OFFSET); } +static inline void apb_soc_padcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG1_OFFSET); } +static inline void apb_soc_padcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG2_OFFSET); } +static inline void apb_soc_padcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG2_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG3_OFFSET); } +static inline void apb_soc_padcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG3_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg4_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG4_OFFSET); } +static inline void apb_soc_padcfg4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG4_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg5_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG5_OFFSET); } +static inline void apb_soc_padcfg5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG5_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg6_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG6_OFFSET); } +static inline void apb_soc_padcfg6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG6_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg7_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG7_OFFSET); } +static inline void apb_soc_padcfg7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG7_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg8_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG8_OFFSET); } +static inline void apb_soc_padcfg8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG8_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg9_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG9_OFFSET); } +static inline void apb_soc_padcfg9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG9_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg10_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG10_OFFSET); } +static inline void apb_soc_padcfg10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG10_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg11_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG11_OFFSET); } +static inline void apb_soc_padcfg11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG11_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg12_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG12_OFFSET); } +static inline void apb_soc_padcfg12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG12_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg13_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG13_OFFSET); } +static inline void apb_soc_padcfg13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG13_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg14_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG14_OFFSET); } +static inline void apb_soc_padcfg14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG14_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg15_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG15_OFFSET); } +static inline void apb_soc_padcfg15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG15_OFFSET, value); } + +static inline uint32_t apb_soc_cl_busy_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_BUSY_OFFSET); } +static inline void apb_soc_cl_busy_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_BUSY_OFFSET, value); } + +static inline uint32_t apb_soc_jtagreg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_JTAGREG_OFFSET); } +static inline void apb_soc_jtagreg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_JTAGREG_OFFSET, value); } + +static inline uint32_t apb_soc_sleep_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SLEEP_CTRL_OFFSET); } +static inline void apb_soc_sleep_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SLEEP_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_i3c_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_I3C_OFFSET); } +static inline void apb_soc_clk_div_i3c_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_I3C_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_OFFSET); } +static inline void apb_soc_corestatus_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_ro_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_RO_OFFSET); } +static inline void apb_soc_corestatus_ro_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_RO_OFFSET, value); } + +static inline uint32_t apb_soc_bootsel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_BOOTSEL_OFFSET); } +static inline void apb_soc_bootsel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_BOOTSEL_OFFSET, value); } + +static inline uint32_t apb_soc_wd_clr_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_WD_CLR_OFFSET); } +static inline void apb_soc_wd_clr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_WD_CLR_OFFSET, value); } + +static inline uint32_t apb_soc_clk_sel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_SEL_OFFSET); } +static inline void apb_soc_clk_sel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_SEL_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_soc_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_SOC_OFFSET); } +static inline void apb_soc_clk_div_soc_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_SOC_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_clu_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_CLU_OFFSET); } +static inline void apb_soc_clk_div_clu_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_CLU_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_per_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_PER_OFFSET); } +static inline void apb_soc_clk_div_per_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_PER_OFFSET, value); } + +static inline uint32_t apb_soc_supervisor_dbg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SUPERVISOR_DBG_OFFSET); } +static inline void apb_soc_supervisor_dbg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SUPERVISOR_DBG_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP0_OFFSET); } +static inline void apb_soc_rwm_grp0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP0_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP1_OFFSET); } +static inline void apb_soc_rwm_grp1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP1_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP2_OFFSET); } +static inline void apb_soc_rwm_grp2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP2_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP3_OFFSET); } +static inline void apb_soc_rwm_grp3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP3_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp4_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP4_OFFSET); } +static inline void apb_soc_rwm_grp4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP4_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp5_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP5_OFFSET); } +static inline void apb_soc_rwm_grp5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP5_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp6_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP6_OFFSET); } +static inline void apb_soc_rwm_grp6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP6_OFFSET, value); } + +static inline uint32_t apb_soc_safe_pmu_sleepctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET); } +static inline void apb_soc_safe_pmu_sleepctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_wd_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_WD_OFFSET); } +static inline void apb_soc_safe_wd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_WD_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_safe_nevacf_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_NEVACF_OFFSET); } +static inline void apb_soc_safe_nevacf_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_NEVACF_OFFSET, value); } + +static inline uint32_t apb_soc_safe_gpreg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_GPREG_OFFSET); } +static inline void apb_soc_safe_gpreg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_GPREG_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l2_btrim_stdby_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET); } +static inline void apb_soc_safe_l2_btrim_stdby_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET, value); } + +static inline uint32_t apb_soc_safe_fll_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_FLL_CTRL_OFFSET); } +static inline void apb_soc_safe_fll_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_FLL_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l1_pwr_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L1_PWR_CTRL_OFFSET); } +static inline void apb_soc_safe_l1_pwr_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L1_PWR_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l2_pwr_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L2_PWR_CTRL_OFFSET); } +static inline void apb_soc_safe_l2_pwr_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L2_PWR_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_reg_gpio_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_GPIO_ISO_OFFSET); } +static inline void apb_soc_reg_gpio_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_GPIO_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_cam_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_CAM_ISO_OFFSET); } +static inline void apb_soc_reg_cam_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_CAM_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_lvds_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_LVDS_ISO_OFFSET); } +static inline void apb_soc_reg_lvds_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_LVDS_ISO_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define APB_SOC_INFO_NB_CL_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define APB_SOC_INFO_NB_CL_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define APB_SOC_INFO_NB_CL_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define APB_SOC_INFO_NB_CL(val) ((val) << 0) + +#define APB_SOC_INFO_NB_CORES_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_INFO_NB_CORES_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_INFO_NB_CORES_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_INFO_NB_CORES(val) ((val) << 16) + +#define APB_SOC_FC_BOOT_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_FC_BOOT_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_FC_BOOT_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_FC_BOOT_ADDR(val) ((val) << 0) + +#define APB_SOC_FC_FETCH_FC_FE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_FC_FETCH_FC_FE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_FC_FETCH_FC_FE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_FC_FETCH_FC_FE(val) ((val) << 0) + +#define APB_SOC_CL_ISOLATE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_ISOLATE_EN(val) ((val) << 0) + +#define APB_SOC_CL_BUSY_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_BUSY_BUSY(val) ((val) << 0) + +#define APB_SOC_JTAGREG_INT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC(val) ((val) << 0) + +#define APB_SOC_JTAGREG_INT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD(val) ((val) << 1) + +#define APB_SOC_JTAGREG_EXT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC(val) ((val) << 8) + +#define APB_SOC_JTAGREG_EXT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD(val) ((val) << 9) + +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_STATUS(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_RO_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS(val) ((val) << 0) + +#define APB_SOC_CLK_SEL_CLK_SOC_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC(val) ((val) << 0) + +#define APB_SOC_CLK_SEL_CLK_CLUSTER_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER(val) ((val) << 1) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN(val) ((val) << 9) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN(val) ((val) << 10) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GET(value) (ARCHI_BEXTRACTU((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GETS(value) (ARCHI_BEXTRACT((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE(val) ((val) << 11) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN(val) ((val) << 13) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_GET(value) (ARCHI_BEXTRACTU((value),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_GETS(value) (ARCHI_BEXTRACT((value),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE(val) ((val) << 14) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE(val) ((val) << 15) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM(val) ((val) << 16) + +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_GET(value) (ARCHI_BEXTRACTU((value),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_GETS(value) (ARCHI_BEXTRACT((value),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N(val) ((val) << 4) + +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD(val) ((val) << 0) + +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD(val) ((val) << 1) + +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB(val) ((val) << 2) + +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB(val) ((val) << 3) + +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM(val) ((val) << 0) + +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_GET(value) (ARCHI_BEXTRACTU((value),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_GETS(value) (ARCHI_BEXTRACT((value),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_SET(value,field) (ARCHI_BINSERT((value),(field),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N(val) ((val) << 4) + +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_GET(value) (ARCHI_BEXTRACTU((value),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_GETS(value) (ARCHI_BEXTRACT((value),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD(val) ((val) << 6) + +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N(val) ((val) << 16) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap9/memory_map.h.in b/sw/pulp-sdk/archi/include/archi/chips/gap9/memory_map.h.in new file mode 100644 index 0000000..63c751d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap9/memory_map.h.in @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VEGA_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VEGA_MEMORY_MAP_H__ + + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE @l2_shared_size@ + + + +/* + * MRAM + */ + +#define ARCHI_MRAM_ADDR 0x1D000000 + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_CVP_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_PWM_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 /// FIXME: not soc eu but soc event generator +#define ARCHI_PMU_OFFSET 0x00007000 +#define ARCHI_RTC_BASE_OFFSET 0x00008000 +#define ARCHI_FC_ICACHE_OFFSET 0x00008800 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_I3C0_OFFSET 0x0000A000 +#define ARCHI_I3C1_OFFSET 0x0000A800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_TIMER1_OFFSET 0x0000B800 +#define ARCHI_DPHY_OFFSET 0x0000C000 +#define ARCHI_CSI2_OFFSET 0x0000D000 +#define ARCHI_MPU_OFFSET 0x0000E000 +#define ARCHI_EFUSE_OFFSET 0x0000F000 +#define ARCHI_DEBUG_OFFSET 0x00010000 +#define ARCHI_STDOUT_OFFSET 0x00020000 +#define ARCHI_QUIDDIKEY_OFFSET 0x00021000 + +#define ARCHI_FLL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FLL_OFFSET ) +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_PWM_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PWM_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_PMU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PMU_OFFSET ) +#define ARCHI_RTC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_RTC_BASE_OFFSET ) +#define ARCHI_FC_ICACHE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ICACHE_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_I3C0_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_I3C0_OFFSET ) +#define ARCHI_I3C1_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_I3C1_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +// #define ARCHI_FC_TIMER1_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER1_OFFSET ) +#define ARCHI_DPHY_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_DPHY_OFFSET ) +#define ARCHI_CSI2_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_CSI2_OFFSET ) +#define ARCHI_MPU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_MPU_OFFSET ) +#define ARCHI_EFUSE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_EFUSE_OFFSET ) +#define ARCHI_DEBUG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_DEBUG_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_QUIDDIKEY_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_QUIDDIKEY_OFFSET ) + + + +// VEGA HAL Handles definition +#define QUIDDIKEY_HANDLE ((halQuiddikeyHandle_t *)(ARCHI_QUIDDIKEY_ADDR)) +#define CSI2_HANDLE ((halCsi2Handle_t *)(ARCHI_CSI2_ADDR)) +#define DPHY_HANDLE ((halDphyHandle_t *)(ARCHI_DPHY_ADDR)) + +#define UDMA_CSI2_HANDLE(id) ((plpUdmaCsi2Handle_t *)(ARCHI_UDMA_ADDR + UDMA_CSI2_OFFSET(id))) + + + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + +/* + * FC + */ +// NOTE: they are all in SOC PERIPH now + +#define ARCHI_FC_ADDR 0x00000000 +// #define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap9/pmu.h b/sw/pulp-sdk/archi/include/archi/chips/gap9/pmu.h new file mode 100644 index 0000000..01155f7 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap9/pmu.h @@ -0,0 +1,510 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_VEGA_PMU_H__ +#define __INCLUDE_ARCHI_CHIPS_VEGA_PMU_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_pmu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu0 +// + +#define PMU_ICU0_OFFSET 0x2 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu1 +// + +#define PMU_ICU1_OFFSET 0x3 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu1_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP dmu0 +// + +#define PMU_DMU0_OFFSET 0x4 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_dmu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu_soc +// + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// CUSTOM FIELDS +// +#define PMU_SOC_ON_NV 0x00 +#define PMU_SOC_ON_LV 0x01 +#define PMU_SOC_RET_OFF 0x02 +#define PMU_SOC_RET_NV 0x03 +#define PMU_SOC_RET_LV 0x04 +#define PMU_SOC_RET_RV 0x05 +#define PMU_SOC_EXT_OFF 0x06 +#define PMU_SOC_EXT_NV 0x07 +#define PMU_SOC_EXT_LV 0x08 +#define PMU_SOC_EXT_RV 0x09 +#define PMU_SOC_CKOFF_NV 0x11 +#define PMU_SOC_CKOFF_LV 0x12 +#define PMU_SOC_CKOFF_RV 0x13 + + + +// +// GROUP icu_cluster +// + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu_cluster_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// CUSTOM FIELDS +// +#define PMU_CLUSTER_ON_NV 0x00 +#define PMU_CLUSTER_ON_LV 0x01 +#define PMU_CLUSTER_RET_OFF 0x02 +#define PMU_CLUSTER_RET_NV 0x03 +#define PMU_CLUSTER_RET_LV 0x04 +#define PMU_CLUSTER_RET_RV 0x05 +#define PMU_CLUSTER_EXT_OFF 0x06 +#define PMU_CLUSTER_EXT_NV 0x07 +#define PMU_CLUSTER_EXT_LV 0x08 +#define PMU_CLUSTER_EXT_RV 0x09 +#define PMU_CLUSTER_CKOFF_NV 0x11 +#define PMU_CLUSTER_CKOFF_LV 0x12 +#define PMU_CLUSTER_CKOFF_RV 0x13 + + + +// +// CUSTOM FIELDS +// +#define PMU_BOOT 0x01 +#define PMU_SOC_ACTIVE_NV 0x01 +#define PMU_SOC_ACTIVE_LV 0x02 +#define PMU_SOC_CLUSTER_ACTIVE_NV 0x04 +#define PMU_SOC_CLUSTER_ACTIVE_LV 0x08 +#define PMU_DEEP_SLEEP_ALL_OFF 0x10 +#define PMU_DEEP_SLEEP_RETENTIVE 0x20 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/gap9/properties.h b/sw/pulp-sdk/archi/include/archi/chips/gap9/properties.h new file mode 100644 index 0000000..9ff3bb2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/gap9/properties.h @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna and GreenWaves Technologies + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VEGA_PROPERTIES_H__ +#define __ARCHI_CHIPS_VEGA_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 0x20000 + +#define ARCHI_MEMORY_POWER 1 + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define FLL_VERSION 1 +#define GPIO_VERSION 2 +#define UDMA_VERSION 3 +#define PERIPH_VERSION 3 +#define APB_SOC_VERSION 3 +#define ADV_TIMER_VERSION 1 +#define SOC_EU_VERSION 2 +#define PMU_VERSION 3 +#define FC_ICACHE_CTRL_VERSION 2 +#define ITC_VERSION 1 +#define I3C_VERSION 1 +#define TIMER_VERSION 2 +#define DPHY_VERSION 1 +#define CSI2_VERSION 1 +#define MPU_VERSION 1 +#define EFUSE_VERSION 1 +#define DEBUG_VERSION 1 +#define STDOUT_VERSION 2 +#define QUIDDIKEY_VERSION 1 +#define ROM_VERSION 2 +#define RTC_VERSION 1 + +#define EU_VERSION 3 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 7 +#define HWCE_VERSION 5 + +#define CL_CTRL_VERSION 2 +#define PADS_VERSION 2 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_CL_CID 0 + +// TAS = Test&Set +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_HAS_CC 1 +#define ARCHI_CC_CORE_ID 8 +#define ARCHI_CLUSTER_NB_PE 8 +#define ARCHI_HAS_CLUSTER_CLK_GATE 1 + + +/* + * CLUSTER EVENT UNIT + */ + +//#define ARCHI_HAS_NO_BARRIER 1 +//#define ARCHI_HAS_NO_DISPATCH 1 +//#define ARCHI_HAS_NO_MUTEX 1 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 +#define ARCHI_FC_HAS_ICACHE 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/multino/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/multino/memory_map.h new file mode 100644 index 0000000..998871e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/multino/memory_map.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_MULTINO_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_MULTINO_MEMORY_MAP_H__ + + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UART_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SPIM_OFFSET 0x00005000 +#define ARCHI_STDOUT_OFFSET 0x00006000 +#define ARCHI_RAB_CFG_OFFSET 0x00030000 + + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UART_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UART_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SPIM_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SPIM_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_RAB_CFG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_RAB_CFG_OFFSET ) + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x1B000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_TIMER_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_TIMER_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + + +#define ARCHI_TRYX_CTRL_ADDR ( 0x10200BFC ) + + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/multino/properties.h b/sw/pulp-sdk/archi/include/archi/chips/multino/properties.h new file mode 100644 index 0000000..ee45c17 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/multino/properties.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_MULTINO_PROPERTIES_H__ +#define __ARCHI_CHIPS_MULTINO_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_NO_L1_TINY 1 + +#define ARCHI_L1_SIZE 262144 + +/* + * IP VERSIONS + */ + +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define EU_VERSION 3 +#define RISCV_VERSION 4 +#define GPIO_VERSION 2 +#define PADS_VERSION 2 +#define MCHAN_VERSION 6 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 2 +#define ARCHI_NB_CLUSTER 2 + + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/memory_map.h new file mode 100644 index 0000000..c6eca7b --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/memory_map.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_OPRECOMPKW_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_OPRECOMPKW_MEMORY_MAP_H__ + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/properties.h b/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/properties.h new file mode 100644 index 0000000..020a134 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/oprecompkw/properties.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_OPRECOMPKW_PROPERTIES_H__ +#define __ARCHI_CHIPS_OPRECOMPKW_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 + +#define ARCHI_L1_SIZE 65536 +#define ARCHI_NO_L1_TINY 1 + + +/* + * IP VERSIONS + */ + +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define EU_VERSION 3 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 +#define ARCHI_HAS_MCHAN_64 1 + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulp/apb_soc_ctrl.h b/sw/pulp-sdk/archi/include/archi/chips/pulp/apb_soc_ctrl.h new file mode 100644 index 0000000..fc38a90 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulp/apb_soc_ctrl.h @@ -0,0 +1,116 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_PULP_APB_SOC_CTRL_H__ +#define __INCLUDE_ARCHI_CHIPS_PULP_APB_SOC_CTRL_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Value of pad bootsel +#define APB_SOC_BOOTSEL_OFFSET 0xc4 + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_bootsel_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_bootsel : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int bootsel ; // Value of pad bootsel +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t apb_soc_bootsel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_BOOTSEL_OFFSET); } +static inline void apb_soc_bootsel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_BOOTSEL_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulp/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/pulp/memory_map.h new file mode 100644 index 0000000..8c12def --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulp/memory_map.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_PULP_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_PULP_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulp/properties.h b/sw/pulp-sdk/archi/include/archi/chips/pulp/properties.h new file mode 100644 index 0000000..87e24f3 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulp/properties.h @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_PULP_PROPERTIES_H__ +#define __ARCHI_CHIPS_PULP_PROPERTIES_H__ + +/* + * FPGA + */ + +#define ARCHI_FPGA_FREQUENCY 5000000 + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L2_MULTI 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 3 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 2 +#define APB_SOC_VERSION 3 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 7 +#define PADS_VERSION 2 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 +#define ARCHI_NB_CLUSTER 1 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 +#define ARCHI_HAS_FC 1 + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/memory_map.h new file mode 100644 index 0000000..9e57e4d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/memory_map.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_PULP_V1_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_PULP_V1_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/properties.h b/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/properties.h new file mode 100644 index 0000000..4d37b57 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulp_v1/properties.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_PULP_V1_PROPERTIES_H__ +#define __ARCHI_CHIPS_PULP_V1_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 65536 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/apb_soc_ctrl.h b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/apb_soc_ctrl.h new file mode 100644 index 0000000..f364de1 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/apb_soc_ctrl.h @@ -0,0 +1,116 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_PULPISSIMO_APB_SOC_CTRL_H__ +#define __INCLUDE_ARCHI_CHIPS_PULPISSIMO_APB_SOC_CTRL_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Value of pad bootsel +#define APB_SOC_BOOTSEL_OFFSET 0xc4 + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_bootsel_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_bootsel : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int bootsel ; // Value of pad bootsel +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t apb_soc_bootsel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_BOOTSEL_OFFSET); } +static inline void apb_soc_bootsel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_BOOTSEL_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/memory_map.h new file mode 100644 index 0000000..4e226bb --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/memory_map.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULPISSIMO_MEMORY_MAP_H__ +#define __ARCHI_PULPISSIMO_MEMORY_MAP_H__ + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_HWPE_OFFSET 0x0000C000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_FC_HWPE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_HWPE_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_OFFSET 0x00000400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/properties.h b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/properties.h new file mode 100644 index 0000000..c2fa2f2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo/properties.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULPISSIMO_PROPERTIES_H__ +#define __ARCHI_PULPISSIMO_PROPERTIES_H__ + +/* + * FPGA + */ + +#define ARCHI_FPGA_FREQUENCY 5000000 + + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 3 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 2 +#define APB_SOC_VERSION 3 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define HWME_VERSION 1 +#define PADS_VERSION 2 + + +/* + * CORE IDS + */ + +#define ARCHI_FC_CID 31 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/memory_map.h new file mode 100644 index 0000000..dd444b0 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/memory_map.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULPISSIMO_V1_MEMORY_MAP_H__ +#define __ARCHI_PULPISSIMO_V1_MEMORY_MAP_H__ + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_HWPE_OFFSET 0x0000C000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_FC_HWPE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_HWPE_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_OFFSET 0x00000400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/properties.h b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/properties.h new file mode 100644 index 0000000..7203804 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/pulpissimo_v1/properties.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULPISSIMO_V1_PROPERTIES_H__ +#define __ARCHI_PULPISSIMO_V1_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 3 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define HWME_VERSION 1 +#define PADS_VERSION 2 + + +/* + * CORE IDS + */ + +#define ARCHI_FC_CID 31 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/quentin/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/quentin/memory_map.h new file mode 100644 index 0000000..ef5a9cc --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/quentin/memory_map.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_QUENTIN_MEMORY_MAP_H__ +#define __ARCHI_QUENTIN_MEMORY_MAP_H__ + + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00007000 + +#define ARCHI_L2_SCM_ADDR 0x1c007000 +#define ARCHI_L2_SCM_SIZE 0x00001000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_HWPE_OFFSET 0x0000C000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_FC_HWPE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_HWPE_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_OFFSET 0x00000400 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/quentin/properties.h b/sw/pulp-sdk/archi/include/archi/chips/quentin/properties.h new file mode 100644 index 0000000..6a87179 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/quentin/properties.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_QUENTIN_PROPERTIES_H__ +#define __ARCHI_QUENTIN_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L2_SCM 1 + + + +/* + * MEMORY ALIAS + */ + +// Alias is deactivated to allow putting the code and data in scm +//#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 3 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define XNE_VERSION 1 +#define PADS_VERSION 2 + + + +/* + * CORE IDS + */ + +#define ARCHI_FC_CID 31 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define ARCHI_GPIO_INTTYPE_GPIO(inttype) ((inttype)*16) +#define ARCHI_GPIO_INTTYPE_SIZE 2 +#define ARCHI_GPIO_INTTYPE_BIT(pad) (((pad) & 0xF) << 1) +#define ARCHI_GPIO_INTTYPE_GET(gpio,value) (((value) >> ARCHI_GPIO_INTTYPE_BIT(gpio)) & ((1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 0 // FIXME put it to the right value once the padframe is specified +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_SLEEP_CONTROL 0x104 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 8 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 8 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vega/apb_soc_ctrl.h b/sw/pulp-sdk/archi/include/archi/chips/vega/apb_soc_ctrl.h new file mode 100644 index 0000000..e07d9ad --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vega/apb_soc_ctrl.h @@ -0,0 +1,1581 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_VEGA_APB_SOC_CTRL_H__ +#define __INCLUDE_ARCHI_CHIPS_VEGA_APB_SOC_CTRL_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Core information register +#define APB_SOC_INFO_OFFSET 0x0 + +// Boot address +#define APB_SOC_FC_BOOT_OFFSET 0x4 + +// FC Fetch enable +#define APB_SOC_FC_FETCH_OFFSET 0x8 + +// Isolate cluster register +#define APB_SOC_CL_ISOLATE_OFFSET 0xc + +// Mux config register (pad 0-15) +#define APB_SOC_PADFUN0_OFFSET 0x10 + +// Mux config register (pad 16-31) +#define APB_SOC_PADFUN1_OFFSET 0x14 + +// Mux config register (pad 32-47) +#define APB_SOC_PADFUN2_OFFSET 0x18 + +// Mux config register (pad 48-63) +#define APB_SOC_PADFUN3_OFFSET 0x1c + +// Function register (pad 0 to 3) +#define APB_SOC_PADCFG0_OFFSET 0x20 + +// Function register (pad 4 to 7) +#define APB_SOC_PADCFG1_OFFSET 0x24 + +// Function register (pad 8 to 11) +#define APB_SOC_PADCFG2_OFFSET 0x28 + +// Function register (pad 12 to 15) +#define APB_SOC_PADCFG3_OFFSET 0x2c + +// Function register (pad 16 to 19) +#define APB_SOC_PADCFG4_OFFSET 0x30 + +// Function register (pad 20 to 23) +#define APB_SOC_PADCFG5_OFFSET 0x34 + +// Function register (pad 24 to 27) +#define APB_SOC_PADCFG6_OFFSET 0x38 + +// Function register (pad 28 to 31) +#define APB_SOC_PADCFG7_OFFSET 0x3c + +// Function register (pad 32 to 35) +#define APB_SOC_PADCFG8_OFFSET 0x40 + +// Function register (pad 36 to 39) +#define APB_SOC_PADCFG9_OFFSET 0x44 + +// Function register (pad 40 to 43) +#define APB_SOC_PADCFG10_OFFSET 0x48 + +// Function register (pad 44 to 47) +#define APB_SOC_PADCFG11_OFFSET 0x4c + +// Function register (pad 48 to 51) +#define APB_SOC_PADCFG12_OFFSET 0x50 + +// Function register (pad 52 to 55) +#define APB_SOC_PADCFG13_OFFSET 0x54 + +// Function register (pad 56 to 59) +#define APB_SOC_PADCFG14_OFFSET 0x58 + +// Function register (pad 60 to 63) +#define APB_SOC_PADCFG15_OFFSET 0x5c + +// Cluster busy register +#define APB_SOC_CL_BUSY_OFFSET 0x6c + +// JTAG external register +#define APB_SOC_JTAGREG_OFFSET 0x74 + +// Alias for SAFE_PMU_SLEEPCTRL +#define APB_SOC_SLEEP_CTRL_OFFSET 0x7c + +// Clock divider for I3C +#define APB_SOC_CLK_DIV_I3C_OFFSET 0x80 + +// EOC and chip status register +#define APB_SOC_CORESTATUS_OFFSET 0xa0 + +// EOC and chip status register read mirror +#define APB_SOC_CORESTATUS_RO_OFFSET 0xc0 + +// Value of pad bootsel +#define APB_SOC_BOOTSEL_OFFSET 0xc4 + +// Clear WD timer +#define APB_SOC_WD_CLR_OFFSET 0xc8 + +// Clock selection for SOC,Cluster and Periph +#define APB_SOC_CLK_SEL_OFFSET 0xd0 + +// SOC Clock Divider settings +#define APB_SOC_CLK_DIV_SOC_OFFSET 0xd4 + +// Cluster Clock Divider settings +#define APB_SOC_CLK_DIV_CLU_OFFSET 0xd8 + +// Peripheral Clock Divider Settings +#define APB_SOC_CLK_DIV_PER_OFFSET 0xdc + +// nan +#define APB_SOC_SUPERVISOR_DBG_OFFSET 0xe0 + +// nan +#define APB_SOC_RWM_GRP0_OFFSET 0xe4 + +// nan +#define APB_SOC_RWM_GRP1_OFFSET 0xe8 + +// nan +#define APB_SOC_RWM_GRP2_OFFSET 0xec + +// nan +#define APB_SOC_RWM_GRP3_OFFSET 0xf0 + +// nan +#define APB_SOC_RWM_GRP4_OFFSET 0xf4 + +// nan +#define APB_SOC_RWM_GRP5_OFFSET 0xf8 + +// nan +#define APB_SOC_RWM_GRP6_OFFSET 0xfc + +// Sleep modes configuration register +#define APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET 0x104 + +// Enables and configures WatchDog Timer +#define APB_SOC_SAFE_WD_OFFSET 0x110 + +// Sleep config register (pad 0-7) +#define APB_SOC_SAFE_SLEEPPADCFG0_OFFSET 0x150 + +// Sleep config register (pad 8-15) +#define APB_SOC_SAFE_SLEEPPADCFG1_OFFSET 0x154 + +// Config timings for NEVA +#define APB_SOC_SAFE_NEVACF_OFFSET 0x164 + +// General purpouse register AO +#define APB_SOC_SAFE_GPREG_OFFSET 0x170 + +// L2 standby configuration +#define APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET 0x174 + +// FLL2 and FLL3 power control +#define APB_SOC_SAFE_FLL_CTRL_OFFSET 0x178 + +// L1 power control +#define APB_SOC_SAFE_L1_PWR_CTRL_OFFSET 0x17c + +// L2 power control +#define APB_SOC_SAFE_L2_PWR_CTRL_OFFSET 0x180 + +// GPIO power domain pad input isolation register +#define APB_SOC_REG_GPIO_ISO_OFFSET 0x1c0 + +// CAM power domain pad input isolation register +#define APB_SOC_REG_CAM_ISO_OFFSET 0x1c4 + +// LVDS power domain pad input isolation register +#define APB_SOC_REG_LVDS_ISO_OFFSET 0x1c8 + + + +// +// REGISTERS FIELDS +// + +// Number of clusters (access: R) +#define APB_SOC_INFO_NB_CL_BIT 0 +#define APB_SOC_INFO_NB_CL_WIDTH 16 +#define APB_SOC_INFO_NB_CL_MASK 0xffff + +// Number of cores (access: R) +#define APB_SOC_INFO_NB_CORES_BIT 16 +#define APB_SOC_INFO_NB_CORES_WIDTH 16 +#define APB_SOC_INFO_NB_CORES_MASK 0xffff0000 + +// FC Boot Address (access: R/W) +#define APB_SOC_FC_BOOT_ADDR_BIT 0 +#define APB_SOC_FC_BOOT_ADDR_WIDTH 32 +#define APB_SOC_FC_BOOT_ADDR_MASK 0xffffffff + +// FC Fetch Enable (access: R/W) +#define APB_SOC_FC_FETCH_FC_FE_BIT 0 +#define APB_SOC_FC_FETCH_FC_FE_WIDTH 1 +#define APB_SOC_FC_FETCH_FC_FE_MASK 0x1 + +// Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable (access: R/W) +#define APB_SOC_CL_ISOLATE_EN_BIT 0 +#define APB_SOC_CL_ISOLATE_EN_WIDTH 1 +#define APB_SOC_CL_ISOLATE_EN_MASK 0x1 + +// Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) (access: R) +#define APB_SOC_CL_BUSY_BUSY_BIT 0 +#define APB_SOC_CL_BUSY_BUSY_WIDTH 1 +#define APB_SOC_CL_BUSY_BUSY_MASK 0x1 + +// JTAG internal register used for synchronisation from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_SYNC_BIT 0 +#define APB_SOC_JTAGREG_INT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_INT_SYNC_MASK 0x1 + +// JTAG internal register used for selecting boot mode configuration from external debugger (access: R/W) +#define APB_SOC_JTAGREG_INT_BT_MD_BIT 1 +#define APB_SOC_JTAGREG_INT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_INT_BT_MD_MASK 0xe + +// JTAG external register used for synchronisation from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_SYNC_BIT 8 +#define APB_SOC_JTAGREG_EXT_SYNC_WIDTH 1 +#define APB_SOC_JTAGREG_EXT_SYNC_MASK 0x100 + +// JTAG external register used for selecting boot mode configuration from external debugger (access: R) +#define APB_SOC_JTAGREG_EXT_BT_MD_BIT 9 +#define APB_SOC_JTAGREG_EXT_BT_MD_WIDTH 3 +#define APB_SOC_JTAGREG_EXT_BT_MD_MASK 0xe00 + +// Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) (access: R) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT 0 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH 32 +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_MASK 0xffffffff + +// EOC and chip status register (access: R/W) +#define APB_SOC_CORESTATUS_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_STATUS_MASK 0xffffffff + +// EOC and chip status register (access: R) +#define APB_SOC_CORESTATUS_RO_STATUS_BIT 0 +#define APB_SOC_CORESTATUS_RO_STATUS_WIDTH 32 +#define APB_SOC_CORESTATUS_RO_STATUS_MASK 0xffffffff + +// SoC domain clock selection: - 1b0: First FLL is used (FLL1) - 1b1: Second FLL is used (FLL2) (access: R/W) +#define APB_SOC_CLK_SEL_CLK_SOC_BIT 0 +#define APB_SOC_CLK_SEL_CLK_SOC_WIDTH 1 +#define APB_SOC_CLK_SEL_CLK_SOC_MASK 0x1 + +// Cluster domain clock selection: - 2b00: First FLL is used (FLL1) - 2b01: Second FLL is used (FLL2) - 2b10: Third FLL is used (FLL3) (access: R/W) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_BIT 1 +#define APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH 2 +#define APB_SOC_CLK_SEL_CLK_CLUSTER_MASK 0x6 + +// User value which is kept retentive after wakeup (even in non-retentive sleep). This value is only partially interpreted by the ROM code (TBD) to distinguish betweem cold boot, non-retentive sleep and retentive sleep. (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT 0 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH 3 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_MASK 0x7 + +// Enable smart wake-up; - 1'b0; smart wake-up disabled - 1'b1: smart wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT 9 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_MASK 0x200 + +// Enable RTC wake-up; - 1'b0; rtc wake-up disabled - 1'b1: rtc wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT 10 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_MASK 0x400 + +// Select external wake-up mode (through dedicated pin): - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT 11 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH 2 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_MASK 0x1800 + +// Enable external wake-up (through dedicated pin); - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT 13 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_MASK 0x2000 + +// Power state of the MRAM to restore after warm boot - 1'b0: MRAM OFF - 1'b1: MRAM ON (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT 14 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_MASK 0x4000 + +// Power state of the cluster to restore after warm boot - 1'b0: cluster OFF - 1'b1: cluster ON (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT 15 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH 1 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_MASK 0x8000 + +// Configure retention mode of L2 memory. There is one bit per cut: - 1'b0: Non retentive - 1'b1: Retentive (access: R/W) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT 16 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH 16 +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_MASK 0xffff0000 + +// Pad state when the chip is down with low-speed IOs ON: - 4b0000: Tristate with no pull-up and no pull-down - 4b0001: Tristate with pull-up - 4b0010: Tristate with pull-down - 4b0011: Drive 0 - 4b0100: Drive 1 (access: R/W) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT 0 +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH 4 +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_MASK 0xf + +// L2 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. (access: R/W) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT 0 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH 4 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_MASK 0xf + +// L2 cuts standby active low. One bit per L2 cut for 16 cuts, the cut is in standby when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT 4 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH 16 +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_MASK 0xffff0 + +// FLL2 power down. The FLL is powered down when this bit is 1b1. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT 0 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_MASK 0x1 + +// FLL3 power down. The FLL is powered down when this bit is 1b1. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_MASK 0x2 + +// FLL2 reset active low. The FLL is reset when this bit is 1b0. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT 2 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_MASK 0x4 + +// FLL3 reset active low. The FLL is reset when this bit is 1b0. (access: R/W) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT 3 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH 1 +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_MASK 0x8 + +// L1 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT 0 +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH 4 +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_MASK 0xf + +// L1 cuts standby active low. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT 4 +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH 2 +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_MASK 0x30 + +// L1 power down. The corresponding L1 part is powered down when this bit is 1b1. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. (access: R/W) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT 6 +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH 2 +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_MASK 0xc0 + +// L2 VDDDE active low. One bit per L2 cut for 16 cuts, the cut periphery is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT 0 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_MASK 0xffff + +// L2 VDDME active low. One bit per L2 cut for 16 cuts, the cut array is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. (access: R/W) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH 16 +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_MASK 0xffff0000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int nb_cl :16; // Number of clusters + unsigned int nb_cores :16; // Number of cores + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_info_t; + +typedef union { + struct { + unsigned int addr :32; // FC Boot Address + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_fc_boot_t; + +typedef union { + struct { + unsigned int fc_fe :1 ; // FC Fetch Enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_fc_fetch_t; + +typedef union { + struct { + unsigned int en :1 ; // Isolate cluster. Inhibits AXI transactions from cluster to SoC: - 1'b0: Disable - 1'b1: Enable + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_isolate_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padfun3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg4_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg5_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg6_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg7_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg8_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg9_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg10_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg11_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg12_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg13_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg14_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_padcfg15_t; + +typedef union { + struct { + unsigned int busy :1 ; // Cluster busy flag (i.e. It's 1 if there is at least 1 active block in the cluster) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_cl_busy_t; + +typedef union { + struct { + unsigned int int_sync :1 ; // JTAG internal register used for synchronisation from external debugger + unsigned int int_bt_md :3 ; // JTAG internal register used for selecting boot mode configuration from external debugger + unsigned int padding0:4 ; + unsigned int ext_sync :1 ; // JTAG external register used for synchronisation from external debugger + unsigned int ext_bt_md :3 ; // JTAG external register used for selecting boot mode configuration from external debugger + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_jtagreg_t; + +typedef union { + struct { + unsigned int sleep_ctrl :32; // Alias for SAFE_PMU_SLEEPCTRL(i.e. will be accessible in 1 clock cycle) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_sleep_ctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_i3c_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_t; + +typedef union { + struct { + unsigned int status :32; // EOC and chip status register + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_corestatus_ro_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_bootsel_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_wd_clr_t; + +typedef union { + struct { + unsigned int clk_soc :1 ; // SoC domain clock selection: - 1b0: First FLL is used (FLL1) - 1b1: Second FLL is used (FLL2) + unsigned int clk_cluster :2 ; // Cluster domain clock selection: - 2b00: First FLL is used (FLL1) - 2b01: Second FLL is used (FLL2) - 2b10: Third FLL is used (FLL3) + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_sel_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_soc_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_clu_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_clk_div_per_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_supervisor_dbg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp4_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp5_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rwm_grp6_t; + +typedef union { + struct { + unsigned int reboot :3 ; // User value which is kept retentive after wakeup (even in non-retentive sleep). This value is only partially interpreted by the ROM code (TBD) to distinguish betweem cold boot, non-retentive sleep and retentive sleep. + unsigned int padding0:6 ; + unsigned int smartwake_en :1 ; // Enable smart wake-up; - 1'b0; smart wake-up disabled - 1'b1: smart wake-up enabled + unsigned int rtcwake_en :1 ; // Enable RTC wake-up; - 1'b0; rtc wake-up disabled - 1'b1: rtc wake-up enabled + unsigned int extwake_type :2 ; // Select external wake-up mode (through dedicated pin): - 2'b00: rise event - 2'b01: fall event - 2'b10: high level - 2'b11: low level + unsigned int extwake_en :1 ; // Enable external wake-up (through dedicated pin); - 1'b0; external wake-up disabled - 1'b1: external wake-up enabled + unsigned int mram_wakestate :1 ; // Power state of the MRAM to restore after warm boot - 1'b0: MRAM OFF - 1'b1: MRAM ON + unsigned int cluster_wakestate:1 ; // Power state of the cluster to restore after warm boot - 1'b0: cluster OFF - 1'b1: cluster ON + unsigned int ret_mem :16; // Configure retention mode of L2 memory. There is one bit per cut: - 1'b0: Non retentive - 1'b1: Retentive + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_pmu_sleepctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_wd_t; + +typedef union { + struct { + unsigned int state :4 ; // Pad state when the chip is down with low-speed IOs ON: - 4b0000: Tristate with no pull-up and no pull-down - 4b0001: Tristate with pull-up - 4b0010: Tristate with pull-down - 4b0011: Drive 0 - 4b0100: Drive 1 + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_sleeppadcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_nevacf_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_gpreg_t; + +typedef union { + struct { + unsigned int btrim :4 ; // L2 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. + unsigned int stdby_n :16; // L2 cuts standby active low. One bit per L2 cut for 16 cuts, the cut is in standby when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l2_btrim_stdby_t; + +typedef union { + struct { + unsigned int fll2_pwd :1 ; // FLL2 power down. The FLL is powered down when this bit is 1b1. + unsigned int fll3_pwd :1 ; // FLL3 power down. The FLL is powered down when this bit is 1b1. + unsigned int fll2_rstb :1 ; // FLL2 reset active low. The FLL is reset when this bit is 1b0. + unsigned int fll3_rstb :1 ; // FLL3 reset active low. The FLL is reset when this bit is 1b0. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_fll_ctrl_t; + +typedef union { + struct { + unsigned int btrim :4 ; // L1 cuts bias trim. This code is forwarded to all cuts and defines the level of current when the cut is in standby mode. 4b0000 is the least amount of current and 4b1110 is the most amount. 4bxxx1 is disabling the bias. + unsigned int stdby_n :2 ; // L1 cuts standby active low. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. + unsigned int pwd :2 ; // L1 power down. The corresponding L1 part is powered down when this bit is 1b1. First bit is for first L1 64Kbytes and second bit for second L1 64Kbytes. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l1_pwr_ctrl_t; + +typedef union { + struct { + unsigned int vddde_n :16; // L2 VDDDE active low. One bit per L2 cut for 16 cuts, the cut periphery is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + unsigned int vddme_n :16; // L2 VDDME active low. One bit per L2 cut for 16 cuts, the cut array is supplied when its corresponding bit is 0. The 4 last bits are for the private banks and the rest for the shared banks. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_safe_l2_pwr_ctrl_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_gpio_iso_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_cam_iso_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_reg_lvds_iso_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_info : public vp::reg_32 +{ +public: + inline void nb_cl_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline uint32_t nb_cl_get() { return this->get_field(APB_SOC_INFO_NB_CL_BIT, APB_SOC_INFO_NB_CL_WIDTH); } + inline void nb_cores_set(uint32_t value) { this->set_field(value, APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } + inline uint32_t nb_cores_get() { return this->get_field(APB_SOC_INFO_NB_CORES_BIT, APB_SOC_INFO_NB_CORES_WIDTH); } +}; + +class vp_apb_soc_fc_boot : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, APB_SOC_FC_BOOT_ADDR_BIT, APB_SOC_FC_BOOT_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(APB_SOC_FC_BOOT_ADDR_BIT, APB_SOC_FC_BOOT_ADDR_WIDTH); } +}; + +class vp_apb_soc_fc_fetch : public vp::reg_32 +{ +public: + inline void fc_fe_set(uint32_t value) { this->set_field(value, APB_SOC_FC_FETCH_FC_FE_BIT, APB_SOC_FC_FETCH_FC_FE_WIDTH); } + inline uint32_t fc_fe_get() { return this->get_field(APB_SOC_FC_FETCH_FC_FE_BIT, APB_SOC_FC_FETCH_FC_FE_WIDTH); } +}; + +class vp_apb_soc_cl_isolate : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(APB_SOC_CL_ISOLATE_EN_BIT, APB_SOC_CL_ISOLATE_EN_WIDTH); } +}; + +class vp_apb_soc_padfun0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padfun3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg4 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg5 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg6 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg7 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg8 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg9 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg10 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg11 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg12 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg13 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg14 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_padcfg15 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_cl_busy : public vp::reg_32 +{ +public: + inline void busy_set(uint32_t value) { this->set_field(value, APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } + inline uint32_t busy_get() { return this->get_field(APB_SOC_CL_BUSY_BUSY_BIT, APB_SOC_CL_BUSY_BUSY_WIDTH); } +}; + +class vp_apb_soc_jtagreg : public vp::reg_32 +{ +public: + inline void int_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline uint32_t int_sync_get() { return this->get_field(APB_SOC_JTAGREG_INT_SYNC_BIT, APB_SOC_JTAGREG_INT_SYNC_WIDTH); } + inline void int_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline uint32_t int_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_INT_BT_MD_BIT, APB_SOC_JTAGREG_INT_BT_MD_WIDTH); } + inline void ext_sync_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline uint32_t ext_sync_get() { return this->get_field(APB_SOC_JTAGREG_EXT_SYNC_BIT, APB_SOC_JTAGREG_EXT_SYNC_WIDTH); } + inline void ext_bt_md_set(uint32_t value) { this->set_field(value, APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } + inline uint32_t ext_bt_md_get() { return this->get_field(APB_SOC_JTAGREG_EXT_BT_MD_BIT, APB_SOC_JTAGREG_EXT_BT_MD_WIDTH); } +}; + +class vp_apb_soc_sleep_ctrl : public vp::reg_32 +{ +public: + inline void sleep_ctrl_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } + inline uint32_t sleep_ctrl_get() { return this->get_field(APB_SOC_SLEEP_CTRL_SLEEP_CTRL_BIT, APB_SOC_SLEEP_CTRL_SLEEP_CTRL_WIDTH); } +}; + +class vp_apb_soc_clk_div_i3c : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_corestatus : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_STATUS_BIT, APB_SOC_CORESTATUS_STATUS_WIDTH); } +}; + +class vp_apb_soc_corestatus_ro : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(APB_SOC_CORESTATUS_RO_STATUS_BIT, APB_SOC_CORESTATUS_RO_STATUS_WIDTH); } +}; + +class vp_apb_soc_bootsel : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_wd_clr : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_sel : public vp::reg_32 +{ +public: + inline void clk_soc_set(uint32_t value) { this->set_field(value, APB_SOC_CLK_SEL_CLK_SOC_BIT, APB_SOC_CLK_SEL_CLK_SOC_WIDTH); } + inline uint32_t clk_soc_get() { return this->get_field(APB_SOC_CLK_SEL_CLK_SOC_BIT, APB_SOC_CLK_SEL_CLK_SOC_WIDTH); } + inline void clk_cluster_set(uint32_t value) { this->set_field(value, APB_SOC_CLK_SEL_CLK_CLUSTER_BIT, APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH); } + inline uint32_t clk_cluster_get() { return this->get_field(APB_SOC_CLK_SEL_CLK_CLUSTER_BIT, APB_SOC_CLK_SEL_CLK_CLUSTER_WIDTH); } +}; + +class vp_apb_soc_clk_div_soc : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_div_clu : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_clk_div_per : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_supervisor_dbg : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp0 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp2 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp3 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp4 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp5 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rwm_grp6 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_pmu_sleepctrl : public vp::reg_32 +{ +public: + inline void reboot_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH); } + inline uint32_t reboot_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_WIDTH); } + inline void smartwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH); } + inline uint32_t smartwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_WIDTH); } + inline void rtcwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH); } + inline uint32_t rtcwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_WIDTH); } + inline void extwake_type_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline uint32_t extwake_type_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_WIDTH); } + inline void extwake_en_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline uint32_t extwake_en_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_WIDTH); } + inline void mram_wakestate_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH); } + inline uint32_t mram_wakestate_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_WIDTH); } + inline void cluster_wakestate_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH); } + inline uint32_t cluster_wakestate_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_WIDTH); } + inline void ret_mem_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH); } + inline uint32_t ret_mem_get() { return this->get_field(APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_BIT, APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_WIDTH); } +}; + +class vp_apb_soc_safe_wd : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_sleeppadcfg0 : public vp::reg_32 +{ +public: + inline void state_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT, APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH); } + inline uint32_t state_get() { return this->get_field(APB_SOC_SAFE_SLEEPPADCFG0_STATE_BIT, APB_SOC_SAFE_SLEEPPADCFG0_STATE_WIDTH); } +}; + +class vp_apb_soc_safe_sleeppadcfg1 : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_nevacf : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_gpreg : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_safe_l2_btrim_stdby : public vp::reg_32 +{ +public: + inline void btrim_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH); } + inline uint32_t btrim_get() { return this->get_field(APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_WIDTH); } + inline void stdby_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH); } + inline uint32_t stdby_n_get() { return this->get_field(APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_BIT, APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_WIDTH); } +}; + +class vp_apb_soc_safe_fll_ctrl : public vp::reg_32 +{ +public: + inline void fll2_pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH); } + inline uint32_t fll2_pwd_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_WIDTH); } + inline void fll3_pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH); } + inline uint32_t fll3_pwd_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_WIDTH); } + inline void fll2_rstb_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH); } + inline uint32_t fll2_rstb_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_WIDTH); } + inline void fll3_rstb_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH); } + inline uint32_t fll3_rstb_get() { return this->get_field(APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_BIT, APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_WIDTH); } +}; + +class vp_apb_soc_safe_l1_pwr_ctrl : public vp::reg_32 +{ +public: + inline void btrim_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH); } + inline uint32_t btrim_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_BIT, APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_WIDTH); } + inline void stdby_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH); } + inline uint32_t stdby_n_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_BIT, APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_WIDTH); } + inline void pwd_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT, APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH); } + inline uint32_t pwd_get() { return this->get_field(APB_SOC_SAFE_L1_PWR_CTRL_PWD_BIT, APB_SOC_SAFE_L1_PWR_CTRL_PWD_WIDTH); } +}; + +class vp_apb_soc_safe_l2_pwr_ctrl : public vp::reg_32 +{ +public: + inline void vddde_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH); } + inline uint32_t vddde_n_get() { return this->get_field(APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_WIDTH); } + inline void vddme_n_set(uint32_t value) { this->set_field(value, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH); } + inline uint32_t vddme_n_get() { return this->get_field(APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_BIT, APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_WIDTH); } +}; + +class vp_apb_soc_reg_gpio_iso : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_reg_cam_iso : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_reg_lvds_iso : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int info ; // Core information register + unsigned int fc_boot ; // Boot address + unsigned int fc_fetch ; // FC Fetch enable + unsigned int cl_isolate ; // Isolate cluster register + unsigned int padfun0 ; // Mux config register (pad 0-15) + unsigned int padfun1 ; // Mux config register (pad 16-31) + unsigned int padfun2 ; // Mux config register (pad 32-47) + unsigned int padfun3 ; // Mux config register (pad 48-63) + unsigned int padcfg0 ; // Function register (pad 0 to 3) + unsigned int padcfg1 ; // Function register (pad 4 to 7) + unsigned int padcfg2 ; // Function register (pad 8 to 11) + unsigned int padcfg3 ; // Function register (pad 12 to 15) + unsigned int padcfg4 ; // Function register (pad 16 to 19) + unsigned int padcfg5 ; // Function register (pad 20 to 23) + unsigned int padcfg6 ; // Function register (pad 24 to 27) + unsigned int padcfg7 ; // Function register (pad 28 to 31) + unsigned int padcfg8 ; // Function register (pad 32 to 35) + unsigned int padcfg9 ; // Function register (pad 36 to 39) + unsigned int padcfg10 ; // Function register (pad 40 to 43) + unsigned int padcfg11 ; // Function register (pad 44 to 47) + unsigned int padcfg12 ; // Function register (pad 48 to 51) + unsigned int padcfg13 ; // Function register (pad 52 to 55) + unsigned int padcfg14 ; // Function register (pad 56 to 59) + unsigned int padcfg15 ; // Function register (pad 60 to 63) + unsigned int cl_busy ; // Cluster busy register + unsigned int jtagreg ; // JTAG external register + unsigned int sleep_ctrl ; // Alias for SAFE_PMU_SLEEPCTRL + unsigned int clk_div_i3c ; // Clock divider for I3C + unsigned int corestatus ; // EOC and chip status register + unsigned int corestatus_ro ; // EOC and chip status register read mirror + unsigned int bootsel ; // Value of pad bootsel + unsigned int wd_clr ; // Clear WD timer + unsigned int clk_sel ; // Clock selection for SOC,Cluster and Periph + unsigned int clk_div_soc ; // SOC Clock Divider settings + unsigned int clk_div_clu ; // Cluster Clock Divider settings + unsigned int clk_div_per ; // Peripheral Clock Divider Settings + unsigned int supervisor_dbg ; // nan + unsigned int rwm_grp0 ; // nan + unsigned int rwm_grp1 ; // nan + unsigned int rwm_grp2 ; // nan + unsigned int rwm_grp3 ; // nan + unsigned int rwm_grp4 ; // nan + unsigned int rwm_grp5 ; // nan + unsigned int rwm_grp6 ; // nan + unsigned int safe_pmu_sleepctrl; // Sleep modes configuration register + unsigned int safe_wd ; // Enables and configures WatchDog Timer + unsigned int safe_sleeppadcfg0; // Sleep config register (pad 0-7) + unsigned int safe_sleeppadcfg1; // Sleep config register (pad 8-15) + unsigned int safe_nevacf ; // Config timings for NEVA + unsigned int safe_gpreg ; // General purpouse register AO + unsigned int safe_l2_btrim_stdby; // L2 standby configuration + unsigned int safe_fll_ctrl ; // FLL2 and FLL3 power control + unsigned int safe_l1_pwr_ctrl; // L1 power control + unsigned int safe_l2_pwr_ctrl; // L2 power control + unsigned int reg_gpio_iso ; // GPIO power domain pad input isolation register + unsigned int reg_cam_iso ; // CAM power domain pad input isolation register + unsigned int reg_lvds_iso ; // LVDS power domain pad input isolation register +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t apb_soc_info_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_INFO_OFFSET); } +static inline void apb_soc_info_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_INFO_OFFSET, value); } + +static inline uint32_t apb_soc_fc_boot_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_FC_BOOT_OFFSET); } +static inline void apb_soc_fc_boot_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_FC_BOOT_OFFSET, value); } + +static inline uint32_t apb_soc_fc_fetch_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_FC_FETCH_OFFSET); } +static inline void apb_soc_fc_fetch_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_FC_FETCH_OFFSET, value); } + +static inline uint32_t apb_soc_cl_isolate_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_ISOLATE_OFFSET); } +static inline void apb_soc_cl_isolate_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_ISOLATE_OFFSET, value); } + +static inline uint32_t apb_soc_padfun0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN0_OFFSET); } +static inline void apb_soc_padfun0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN0_OFFSET, value); } + +static inline uint32_t apb_soc_padfun1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN1_OFFSET); } +static inline void apb_soc_padfun1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN1_OFFSET, value); } + +static inline uint32_t apb_soc_padfun2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN2_OFFSET); } +static inline void apb_soc_padfun2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN2_OFFSET, value); } + +static inline uint32_t apb_soc_padfun3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADFUN3_OFFSET); } +static inline void apb_soc_padfun3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADFUN3_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG0_OFFSET); } +static inline void apb_soc_padcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG1_OFFSET); } +static inline void apb_soc_padcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG2_OFFSET); } +static inline void apb_soc_padcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG2_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG3_OFFSET); } +static inline void apb_soc_padcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG3_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg4_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG4_OFFSET); } +static inline void apb_soc_padcfg4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG4_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg5_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG5_OFFSET); } +static inline void apb_soc_padcfg5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG5_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg6_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG6_OFFSET); } +static inline void apb_soc_padcfg6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG6_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg7_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG7_OFFSET); } +static inline void apb_soc_padcfg7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG7_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg8_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG8_OFFSET); } +static inline void apb_soc_padcfg8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG8_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg9_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG9_OFFSET); } +static inline void apb_soc_padcfg9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG9_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg10_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG10_OFFSET); } +static inline void apb_soc_padcfg10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG10_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg11_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG11_OFFSET); } +static inline void apb_soc_padcfg11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG11_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg12_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG12_OFFSET); } +static inline void apb_soc_padcfg12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG12_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg13_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG13_OFFSET); } +static inline void apb_soc_padcfg13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG13_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg14_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG14_OFFSET); } +static inline void apb_soc_padcfg14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG14_OFFSET, value); } + +static inline uint32_t apb_soc_padcfg15_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_PADCFG15_OFFSET); } +static inline void apb_soc_padcfg15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_PADCFG15_OFFSET, value); } + +static inline uint32_t apb_soc_cl_busy_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CL_BUSY_OFFSET); } +static inline void apb_soc_cl_busy_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CL_BUSY_OFFSET, value); } + +static inline uint32_t apb_soc_jtagreg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_JTAGREG_OFFSET); } +static inline void apb_soc_jtagreg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_JTAGREG_OFFSET, value); } + +static inline uint32_t apb_soc_sleep_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SLEEP_CTRL_OFFSET); } +static inline void apb_soc_sleep_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SLEEP_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_i3c_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_I3C_OFFSET); } +static inline void apb_soc_clk_div_i3c_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_I3C_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_OFFSET); } +static inline void apb_soc_corestatus_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_OFFSET, value); } + +static inline uint32_t apb_soc_corestatus_ro_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CORESTATUS_RO_OFFSET); } +static inline void apb_soc_corestatus_ro_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CORESTATUS_RO_OFFSET, value); } + +static inline uint32_t apb_soc_bootsel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_BOOTSEL_OFFSET); } +static inline void apb_soc_bootsel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_BOOTSEL_OFFSET, value); } + +static inline uint32_t apb_soc_wd_clr_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_WD_CLR_OFFSET); } +static inline void apb_soc_wd_clr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_WD_CLR_OFFSET, value); } + +static inline uint32_t apb_soc_clk_sel_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_SEL_OFFSET); } +static inline void apb_soc_clk_sel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_SEL_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_soc_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_SOC_OFFSET); } +static inline void apb_soc_clk_div_soc_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_SOC_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_clu_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_CLU_OFFSET); } +static inline void apb_soc_clk_div_clu_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_CLU_OFFSET, value); } + +static inline uint32_t apb_soc_clk_div_per_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_CLK_DIV_PER_OFFSET); } +static inline void apb_soc_clk_div_per_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_CLK_DIV_PER_OFFSET, value); } + +static inline uint32_t apb_soc_supervisor_dbg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SUPERVISOR_DBG_OFFSET); } +static inline void apb_soc_supervisor_dbg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SUPERVISOR_DBG_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP0_OFFSET); } +static inline void apb_soc_rwm_grp0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP0_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP1_OFFSET); } +static inline void apb_soc_rwm_grp1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP1_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp2_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP2_OFFSET); } +static inline void apb_soc_rwm_grp2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP2_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp3_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP3_OFFSET); } +static inline void apb_soc_rwm_grp3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP3_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp4_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP4_OFFSET); } +static inline void apb_soc_rwm_grp4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP4_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp5_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP5_OFFSET); } +static inline void apb_soc_rwm_grp5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP5_OFFSET, value); } + +static inline uint32_t apb_soc_rwm_grp6_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RWM_GRP6_OFFSET); } +static inline void apb_soc_rwm_grp6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RWM_GRP6_OFFSET, value); } + +static inline uint32_t apb_soc_safe_pmu_sleepctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET); } +static inline void apb_soc_safe_pmu_sleepctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_PMU_SLEEPCTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_wd_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_WD_OFFSET); } +static inline void apb_soc_safe_wd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_WD_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg0_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG0_OFFSET, value); } + +static inline uint32_t apb_soc_safe_sleeppadcfg1_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET); } +static inline void apb_soc_safe_sleeppadcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_SLEEPPADCFG1_OFFSET, value); } + +static inline uint32_t apb_soc_safe_nevacf_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_NEVACF_OFFSET); } +static inline void apb_soc_safe_nevacf_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_NEVACF_OFFSET, value); } + +static inline uint32_t apb_soc_safe_gpreg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_GPREG_OFFSET); } +static inline void apb_soc_safe_gpreg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_GPREG_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l2_btrim_stdby_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET); } +static inline void apb_soc_safe_l2_btrim_stdby_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L2_BTRIM_STDBY_OFFSET, value); } + +static inline uint32_t apb_soc_safe_fll_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_FLL_CTRL_OFFSET); } +static inline void apb_soc_safe_fll_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_FLL_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l1_pwr_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L1_PWR_CTRL_OFFSET); } +static inline void apb_soc_safe_l1_pwr_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L1_PWR_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_safe_l2_pwr_ctrl_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SAFE_L2_PWR_CTRL_OFFSET); } +static inline void apb_soc_safe_l2_pwr_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SAFE_L2_PWR_CTRL_OFFSET, value); } + +static inline uint32_t apb_soc_reg_gpio_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_GPIO_ISO_OFFSET); } +static inline void apb_soc_reg_gpio_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_GPIO_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_cam_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_CAM_ISO_OFFSET); } +static inline void apb_soc_reg_cam_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_CAM_ISO_OFFSET, value); } + +static inline uint32_t apb_soc_reg_lvds_iso_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_REG_LVDS_ISO_OFFSET); } +static inline void apb_soc_reg_lvds_iso_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_REG_LVDS_ISO_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define APB_SOC_INFO_NB_CL_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define APB_SOC_INFO_NB_CL_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define APB_SOC_INFO_NB_CL_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define APB_SOC_INFO_NB_CL(val) ((val) << 0) + +#define APB_SOC_INFO_NB_CORES_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_INFO_NB_CORES_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_INFO_NB_CORES_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_INFO_NB_CORES(val) ((val) << 16) + +#define APB_SOC_FC_BOOT_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_FC_BOOT_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_FC_BOOT_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_FC_BOOT_ADDR(val) ((val) << 0) + +#define APB_SOC_FC_FETCH_FC_FE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_FC_FETCH_FC_FE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_FC_FETCH_FC_FE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_FC_FETCH_FC_FE(val) ((val) << 0) + +#define APB_SOC_CL_ISOLATE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_ISOLATE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_ISOLATE_EN(val) ((val) << 0) + +#define APB_SOC_CL_BUSY_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CL_BUSY_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CL_BUSY_BUSY(val) ((val) << 0) + +#define APB_SOC_JTAGREG_INT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_JTAGREG_INT_SYNC(val) ((val) << 0) + +#define APB_SOC_JTAGREG_INT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,1)) +#define APB_SOC_JTAGREG_INT_BT_MD(val) ((val) << 1) + +#define APB_SOC_JTAGREG_EXT_SYNC_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define APB_SOC_JTAGREG_EXT_SYNC(val) ((val) << 8) + +#define APB_SOC_JTAGREG_EXT_BT_MD_GET(value) (ARCHI_BEXTRACTU((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_GETS(value) (ARCHI_BEXTRACT((value),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD_SET(value,field) (ARCHI_BINSERT((value),(field),3,9)) +#define APB_SOC_JTAGREG_EXT_BT_MD(val) ((val) << 9) + +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_SLEEP_CTRL_SLEEP_CTRL(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_STATUS(val) ((val) << 0) + +#define APB_SOC_CORESTATUS_RO_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define APB_SOC_CORESTATUS_RO_STATUS(val) ((val) << 0) + +#define APB_SOC_CLK_SEL_CLK_SOC_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_CLK_SEL_CLK_SOC(val) ((val) << 0) + +#define APB_SOC_CLK_SEL_CLK_CLUSTER_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define APB_SOC_CLK_SEL_CLK_CLUSTER(val) ((val) << 1) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_REBOOT(val) ((val) << 0) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_SMARTWAKE_EN(val) ((val) << 9) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,10)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RTCWAKE_EN(val) ((val) << 10) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GET(value) (ARCHI_BEXTRACTU((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_GETS(value) (ARCHI_BEXTRACT((value),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,11)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_TYPE(val) ((val) << 11) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_EXTWAKE_EN(val) ((val) << 13) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_GET(value) (ARCHI_BEXTRACTU((value),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_GETS(value) (ARCHI_BEXTRACT((value),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,14)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_MRAM_WAKESTATE(val) ((val) << 14) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_CLUSTER_WAKESTATE(val) ((val) << 15) + +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_SAFE_PMU_SLEEPCTRL_RET_MEM(val) ((val) << 16) + +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_SLEEPPADCFG0_STATE(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_BTRIM(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_GET(value) (ARCHI_BEXTRACTU((value),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_GETS(value) (ARCHI_BEXTRACT((value),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,4)) +#define APB_SOC_SAFE_L2_BTRIM_STDBY_STDBY_N(val) ((val) << 4) + +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_PWD(val) ((val) << 0) + +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_PWD(val) ((val) << 1) + +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define APB_SOC_SAFE_FLL_CTRL_FLL2_RSTB(val) ((val) << 2) + +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define APB_SOC_SAFE_FLL_CTRL_FLL3_RSTB(val) ((val) << 3) + +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define APB_SOC_SAFE_L1_PWR_CTRL_BTRIM(val) ((val) << 0) + +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_GET(value) (ARCHI_BEXTRACTU((value),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_GETS(value) (ARCHI_BEXTRACT((value),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N_SET(value,field) (ARCHI_BINSERT((value),(field),2,4)) +#define APB_SOC_SAFE_L1_PWR_CTRL_STDBY_N(val) ((val) << 4) + +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_GET(value) (ARCHI_BEXTRACTU((value),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_GETS(value) (ARCHI_BEXTRACT((value),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD_SET(value,field) (ARCHI_BINSERT((value),(field),2,6)) +#define APB_SOC_SAFE_L1_PWR_CTRL_PWD(val) ((val) << 6) + +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDDE_N(val) ((val) << 0) + +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define APB_SOC_SAFE_L2_PWR_CTRL_VDDME_N(val) ((val) << 16) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vega/memory_map.h.in b/sw/pulp-sdk/archi/include/archi/chips/vega/memory_map.h.in new file mode 100644 index 0000000..63c751d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vega/memory_map.h.in @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VEGA_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VEGA_MEMORY_MAP_H__ + + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE @l2_shared_size@ + + + +/* + * MRAM + */ + +#define ARCHI_MRAM_ADDR 0x1D000000 + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_CVP_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_PWM_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 /// FIXME: not soc eu but soc event generator +#define ARCHI_PMU_OFFSET 0x00007000 +#define ARCHI_RTC_BASE_OFFSET 0x00008000 +#define ARCHI_FC_ICACHE_OFFSET 0x00008800 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_I3C0_OFFSET 0x0000A000 +#define ARCHI_I3C1_OFFSET 0x0000A800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_FC_TIMER1_OFFSET 0x0000B800 +#define ARCHI_DPHY_OFFSET 0x0000C000 +#define ARCHI_CSI2_OFFSET 0x0000D000 +#define ARCHI_MPU_OFFSET 0x0000E000 +#define ARCHI_EFUSE_OFFSET 0x0000F000 +#define ARCHI_DEBUG_OFFSET 0x00010000 +#define ARCHI_STDOUT_OFFSET 0x00020000 +#define ARCHI_QUIDDIKEY_OFFSET 0x00021000 + +#define ARCHI_FLL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FLL_OFFSET ) +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_PWM_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PWM_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_PMU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PMU_OFFSET ) +#define ARCHI_RTC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_RTC_BASE_OFFSET ) +#define ARCHI_FC_ICACHE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ICACHE_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_I3C0_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_I3C0_OFFSET ) +#define ARCHI_I3C1_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_I3C1_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +// #define ARCHI_FC_TIMER1_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER1_OFFSET ) +#define ARCHI_DPHY_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_DPHY_OFFSET ) +#define ARCHI_CSI2_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_CSI2_OFFSET ) +#define ARCHI_MPU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_MPU_OFFSET ) +#define ARCHI_EFUSE_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_EFUSE_OFFSET ) +#define ARCHI_DEBUG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_DEBUG_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_QUIDDIKEY_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_QUIDDIKEY_OFFSET ) + + + +// VEGA HAL Handles definition +#define QUIDDIKEY_HANDLE ((halQuiddikeyHandle_t *)(ARCHI_QUIDDIKEY_ADDR)) +#define CSI2_HANDLE ((halCsi2Handle_t *)(ARCHI_CSI2_ADDR)) +#define DPHY_HANDLE ((halDphyHandle_t *)(ARCHI_DPHY_ADDR)) + +#define UDMA_CSI2_HANDLE(id) ((plpUdmaCsi2Handle_t *)(ARCHI_UDMA_ADDR + UDMA_CSI2_OFFSET(id))) + + + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + +/* + * FC + */ +// NOTE: they are all in SOC PERIPH now + +#define ARCHI_FC_ADDR 0x00000000 +// #define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vega/pmu.h b/sw/pulp-sdk/archi/include/archi/chips/vega/pmu.h new file mode 100644 index 0000000..01155f7 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vega/pmu.h @@ -0,0 +1,510 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_VEGA_PMU_H__ +#define __INCLUDE_ARCHI_CHIPS_VEGA_PMU_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_pmu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu0 +// + +#define PMU_ICU0_OFFSET 0x2 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu1 +// + +#define PMU_ICU1_OFFSET 0x3 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu1_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP dmu0 +// + +#define PMU_DMU0_OFFSET 0x4 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_dmu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu_soc +// + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// CUSTOM FIELDS +// +#define PMU_SOC_ON_NV 0x00 +#define PMU_SOC_ON_LV 0x01 +#define PMU_SOC_RET_OFF 0x02 +#define PMU_SOC_RET_NV 0x03 +#define PMU_SOC_RET_LV 0x04 +#define PMU_SOC_RET_RV 0x05 +#define PMU_SOC_EXT_OFF 0x06 +#define PMU_SOC_EXT_NV 0x07 +#define PMU_SOC_EXT_LV 0x08 +#define PMU_SOC_EXT_RV 0x09 +#define PMU_SOC_CKOFF_NV 0x11 +#define PMU_SOC_CKOFF_LV 0x12 +#define PMU_SOC_CKOFF_RV 0x13 + + + +// +// GROUP icu_cluster +// + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu_cluster_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// CUSTOM FIELDS +// +#define PMU_CLUSTER_ON_NV 0x00 +#define PMU_CLUSTER_ON_LV 0x01 +#define PMU_CLUSTER_RET_OFF 0x02 +#define PMU_CLUSTER_RET_NV 0x03 +#define PMU_CLUSTER_RET_LV 0x04 +#define PMU_CLUSTER_RET_RV 0x05 +#define PMU_CLUSTER_EXT_OFF 0x06 +#define PMU_CLUSTER_EXT_NV 0x07 +#define PMU_CLUSTER_EXT_LV 0x08 +#define PMU_CLUSTER_EXT_RV 0x09 +#define PMU_CLUSTER_CKOFF_NV 0x11 +#define PMU_CLUSTER_CKOFF_LV 0x12 +#define PMU_CLUSTER_CKOFF_RV 0x13 + + + +// +// CUSTOM FIELDS +// +#define PMU_BOOT 0x01 +#define PMU_SOC_ACTIVE_NV 0x01 +#define PMU_SOC_ACTIVE_LV 0x02 +#define PMU_SOC_CLUSTER_ACTIVE_NV 0x04 +#define PMU_SOC_CLUSTER_ACTIVE_LV 0x08 +#define PMU_DEEP_SLEEP_ALL_OFF 0x10 +#define PMU_DEEP_SLEEP_RETENTIVE 0x20 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vega/properties.h b/sw/pulp-sdk/archi/include/archi/chips/vega/properties.h new file mode 100644 index 0000000..4897580 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vega/properties.h @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna and GreenWaves Technologies + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VEGA_PROPERTIES_H__ +#define __ARCHI_CHIPS_VEGA_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 0x20000 + +#define ARCHI_MEMORY_POWER 1 + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define FLL_VERSION 1 +#define GPIO_VERSION 2 +#define UDMA_VERSION 3 +#define PERIPH_VERSION 3 +#define APB_SOC_VERSION 3 +#define ADV_TIMER_VERSION 1 +#define SOC_EU_VERSION 2 +#define PMU_VERSION 3 +#define FC_ICACHE_CTRL_VERSION 2 +#define ITC_VERSION 1 +#define I3C_VERSION 1 +#define TIMER_VERSION 2 +#define DPHY_VERSION 1 +#define CSI2_VERSION 1 +#define MPU_VERSION 1 +#define EFUSE_VERSION 1 +#define DEBUG_VERSION 1 +#define STDOUT_VERSION 2 +#define QUIDDIKEY_VERSION 1 +#define ROM_VERSION 2 +#define RTC_VERSION 1 + +#define EU_VERSION 3 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 7 +#define HWCE_VERSION 5 + +#define CL_CTRL_VERSION 2 +#define PADS_VERSION 2 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_CL_CID 0 + +// TAS = Test&Set +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_HAS_CC 1 +#define ARCHI_CC_CORE_ID 8 +#define ARCHI_CLUSTER_NB_PE 8 +#define ARCHI_HAS_CLUSTER_CLK_GATE 1 + + +/* + * CLUSTER EVENT UNIT + */ + +//#define ARCHI_HAS_NO_BARRIER 1 +//#define ARCHI_HAS_NO_DISPATCH 1 +//#define ARCHI_HAS_NO_MUTEX 1 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 +#define ARCHI_FC_HAS_ICACHE 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0x80 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/fll.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/fll.h new file mode 100644 index 0000000..eae92ee --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/fll.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_FLL_H__ +#define __ARCHI_CHIPS_VIVOSOC3_FLL_H__ + +// register address offsets +#define FLL_CONTROL_OFFSET 0x044 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FLL_RESET_OFFSET 0x048 +#define FLL_GPIO_OUTPUT 0x104 + +#define FLL_OFFSET 0x040 // base addr 0x1A100000 (ARCHI_SOC_PERIPHERALS_ADDR) + +#define FLL_SET_SEL_OFFSET 0x000 // base addr 0x1A100000 + fll * FLL_OFFSET +#define FLL_REF_CLK_OFFSET 0x004 +#define FLL_FSM_OBS_OFFSET 0x008 +#define FLL_SHARED_CONFIG_OFFSET 0x00C +#define FLL_SET_OFFSET 0x00C +#define FLL_FREQ_REGULATION_OFFSET 0x010 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CLK_GOOD_OFFSET 0x014 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CONFIG_OFFSET 0x018 // + set * FLL_SET_OFFSET +#define FLL_OBSERVATION_OFFSET 0x100 + +#define FLL_ANALOG_CLKIPC_OFFSET 0x4638 // base addr ARCHI_ANALOG_ADDR + +// register bitfields +#define FLL_SET_RSS_BIT 0 +#define FLL_SET_RSS_WIDTH 2 +#define FLL_SET_RSS_MASK (0x0003) + + +#define FLL_FREQ_REGULATION_LOW_BIT 0 +#define FLL_FREQ_REGULATION_LOW_WIDTH 14 +#define FLL_FREQ_REGULATION_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_REGULATION_HIGH_BIT 16 +#define FLL_FREQ_REGULATION_HIGH_WIDTH 14 +#define FLL_FREQ_REGULATION_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CLK_GOOD_LOW_BIT 0 +#define FLL_FREQ_CLK_GOOD_LOW_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_CLK_GOOD_HIGH_BIT 16 +#define FLL_FREQ_CLK_GOOD_HIGH_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CONFIG_LEVEL_BIT 0 +#define FLL_FREQ_CONFIG_LEVEL_WIDTH 4 +#define FLL_FREQ_CONFIG_LEVEL_MASK (0x0000000F) + +#define FLL_FREQ_CONFIG_DCO_LSB_BIT 4 +#define FLL_FREQ_CONFIG_DCO_LSB_WIDTH 3 +#define FLL_FREQ_CONFIG_DCO_LSB_MASK (0x00000070) + +#define FLL_FREQ_CONFIG_DCO_MSB_BIT 8 +#define FLL_FREQ_CONFIG_DCO_MSB_WIDTH 6 +#define FLL_FREQ_CONFIG_DCO_MSB_MASK (0x00003F00) + +#define FLL_FREQ_CONFIG_OL_BIT 16 +#define FLL_FREQ_CONFIG_OL_WIDTH 1 +#define FLL_FREQ_CONFIG_OL_MASK (0x00010000) + + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rss:1; /* Register set selection, 0b00 or 0b01 */ + unsigned int reserved_0:31; + }; + unsigned int raw; +} fll_reg_rss_t; + +typedef union { + struct { + unsigned int nref_reg_low:14; /* Regulation, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_reg_high:14; /* Regulation, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr0_t; + +typedef union { + struct { + unsigned int nref_cg_low:14; /* Clock good, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_cg_high:14; /* Clock good, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr1_t; + +typedef union { + struct { + unsigned int level:4; /* Start level of binary search, reset value: 0x0 */ + unsigned int dco_lsb:3; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_0:1; + unsigned int dco_msb:6; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_1:2; + unsigned int open_loop:1; /* Open-loop operation */ + unsigned int reserved_2:15; + }; + unsigned int raw; +} fll_reg_fcr2_t; + +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/freq.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/freq.h new file mode 100644 index 0000000..66506a6 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/freq.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_FREQ_H__ +#define __ARCHI_CHIPS_VIVOSOC3_FREQ_H__ + +// register address offsets +#define FREQ_CLK_TREE_CONF_GLOBAL_OFFSET 0x040 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FREQ_CLK_TREE_CONF_CL_OFFSET 0x050 +#define FREQ_CLK_TREE_CONF_SOC_OFFSET 0x054 +#define FREQ_CLK_TREE_CONF_PER_OFFSET 0x058 +#define FREQ_CLK_TREE_CONF_PM_OFFSET 0x05C + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/memory_map.h new file mode 100644 index 0000000..e4258d5 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/memory_map.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VIVOSOC3_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00004000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c004000 +#define ARCHI_L2_PRIV1_SIZE 0x00004000 + +#define ARCHI_L2_SHARED_ADDR 0x1c008000 +#define ARCHI_L2_SHARED_SIZE 0x00010000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + + +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 +#define ARCHI_ANALOG_OFFSET 0x00010000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_ANALOG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_ANALOG_OFFSET ) + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/properties.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/properties.h new file mode 100644 index 0000000..1f6754b --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3/properties.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_PROPERTIES_H__ +#define __ARCHI_CHIPS_VIVOSOC3_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 32768 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 +#define FLL_VERSION 1 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 2 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +// PADs configuration is made of 8bits out of which only the first 3 are used +// bit0 enable pull UP +// bit1 enable pull DOWN +// bit2 enable ST +// bit3..7 not used + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +// aliases +#define APB_SOC_PADS_CONFIG APB_SOC_PADCFG0_OFFSET + +// HAL compatibility definitions, functions not supported +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_CLUSTER_ISOLATE_OFFSET 0x0C +#define APB_SOC_BUSY_OFFSET 0x6C +#define APB_SOC_JTAG_REG 0x74 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/fll.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/fll.h new file mode 100644 index 0000000..c1ce3ea --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/fll.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_1_FLL_H__ +#define __ARCHI_CHIPS_VIVOSOC3_1_FLL_H__ + +// register address offsets +#define FLL_CONTROL_OFFSET 0x044 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FLL_RESET_OFFSET 0x048 +#define FLL_GPIO_OUTPUT 0x104 + +#define FLL_OFFSET 0x040 // base addr 0x1A100000 (ARCHI_SOC_PERIPHERALS_ADDR) + +#define FLL_SET_SEL_OFFSET 0x000 // base addr 0x1A100000 + fll * FLL_OFFSET +#define FLL_REF_CLK_OFFSET 0x004 +#define FLL_FSM_OBS_OFFSET 0x008 +#define FLL_SHARED_CONFIG_OFFSET 0x00C +#define FLL_SET_OFFSET 0x00C +#define FLL_FREQ_REGULATION_OFFSET 0x010 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CLK_GOOD_OFFSET 0x014 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CONFIG_OFFSET 0x018 // + set * FLL_SET_OFFSET +#define FLL_OBSERVATION_OFFSET 0x100 + +#define FLL_ANALOG_CLKIPC_OFFSET 0x4638 // base addr ARCHI_ANALOG_ADDR + +// register bitfields +#define FLL_SET_RSS_BIT 0 +#define FLL_SET_RSS_WIDTH 2 +#define FLL_SET_RSS_MASK (0x0003) + + +#define FLL_FREQ_REGULATION_LOW_BIT 0 +#define FLL_FREQ_REGULATION_LOW_WIDTH 14 +#define FLL_FREQ_REGULATION_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_REGULATION_HIGH_BIT 16 +#define FLL_FREQ_REGULATION_HIGH_WIDTH 14 +#define FLL_FREQ_REGULATION_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CLK_GOOD_LOW_BIT 0 +#define FLL_FREQ_CLK_GOOD_LOW_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_CLK_GOOD_HIGH_BIT 16 +#define FLL_FREQ_CLK_GOOD_HIGH_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CONFIG_LEVEL_BIT 0 +#define FLL_FREQ_CONFIG_LEVEL_WIDTH 4 +#define FLL_FREQ_CONFIG_LEVEL_MASK (0x0000000F) + +#define FLL_FREQ_CONFIG_DCO_LSB_BIT 4 +#define FLL_FREQ_CONFIG_DCO_LSB_WIDTH 3 +#define FLL_FREQ_CONFIG_DCO_LSB_MASK (0x00000070) + +#define FLL_FREQ_CONFIG_DCO_MSB_BIT 8 +#define FLL_FREQ_CONFIG_DCO_MSB_WIDTH 6 +#define FLL_FREQ_CONFIG_DCO_MSB_MASK (0x00003F00) + +#define FLL_FREQ_CONFIG_OL_BIT 16 +#define FLL_FREQ_CONFIG_OL_WIDTH 1 +#define FLL_FREQ_CONFIG_OL_MASK (0x00010000) + + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rss:1; /* Register set selection, 0b00 or 0b01 */ + unsigned int reserved_0:31; + }; + unsigned int raw; +} fll_reg_rss_t; + +typedef union { + struct { + unsigned int nref_reg_low:14; /* Regulation, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_reg_high:14; /* Regulation, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr0_t; + +typedef union { + struct { + unsigned int nref_cg_low:14; /* Clock good, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_cg_high:14; /* Clock good, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr1_t; + +typedef union { + struct { + unsigned int level:4; /* Start level of binary search, reset value: 0x0 */ + unsigned int dco_lsb:3; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_0:1; + unsigned int dco_msb:6; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_1:2; + unsigned int open_loop:1; /* Open-loop operation */ + unsigned int reserved_2:15; + }; + unsigned int raw; +} fll_reg_fcr2_t; + +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/freq.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/freq.h new file mode 100644 index 0000000..75280e2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/freq.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_1_FREQ_H__ +#define __ARCHI_CHIPS_VIVOSOC3_1_FREQ_H__ + +// register address offsets +#define FREQ_CLK_TREE_CONF_GLOBAL_OFFSET 0x040 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FREQ_CLK_TREE_CONF_CL_OFFSET 0x050 +#define FREQ_CLK_TREE_CONF_SOC_OFFSET 0x054 +#define FREQ_CLK_TREE_CONF_PER_OFFSET 0x058 +#define FREQ_CLK_TREE_CONF_PM_OFFSET 0x05C + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/memory_map.h new file mode 100644 index 0000000..74ef7f1 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/memory_map.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_1_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VIVOSOC3_1_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00004000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c004000 +#define ARCHI_L2_PRIV1_SIZE 0x00004000 + +#define ARCHI_L2_SHARED_ADDR 0x1c008000 +#define ARCHI_L2_SHARED_SIZE 0x00010000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_IF_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_APB_ADV_TIMER_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_DEBUG_OFFSET 0x00008000 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 +#define ARCHI_ANALOG_OFFSET 0x00010000 + +#define ARCHI_FLL_IF_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FLL_IF_OFFSET ) +#define ARCHI_GPIO_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_APB_ADV_TIMER_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_ADV_TIMER_OFFSET) +#define ARCHI_SOC_EU_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_DEBUG_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_DEBUG_OFFSET ) +#define ARCHI_FC_ITC_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_ANALOG_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_ANALOG_OFFSET ) + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR (ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) (ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET 0x00000 +#define ARCHI_MCHAN_DEMUX_OFFSET 0x00400 + +#define ARCHI_DEMUX_PERIPHERALS_ADDR (ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR (ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR (ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/properties.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/properties.h new file mode 100755 index 0000000..e797fce --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_1/properties.h @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_1_PROPERTIES_H__ +#define __ARCHI_CHIPS_VIVOSOC3_1_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 32768 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 3 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 3 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 +#define FLL_VERSION 1 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0x80 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/fll.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/fll.h new file mode 100644 index 0000000..3f72e0b --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/fll.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_5_FLL_H__ +#define __ARCHI_CHIPS_VIVOSOC3_5_FLL_H__ + +// register address offsets +#define FLL_CONTROL_OFFSET 0x044 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FLL_RESET_OFFSET 0x048 +#define FLL_GPIO_OUTPUT 0x104 + +#define FLL_OFFSET 0x040 // base addr 0x1A100000 (ARCHI_SOC_PERIPHERALS_ADDR) + +#define FLL_SET_SEL_OFFSET 0x000 // base addr 0x1A100000 + fll * FLL_OFFSET +#define FLL_REF_CLK_OFFSET 0x004 +#define FLL_FSM_OBS_OFFSET 0x008 +#define FLL_SHARED_CONFIG_OFFSET 0x00C +#define FLL_SET_OFFSET 0x00C +#define FLL_FREQ_REGULATION_OFFSET 0x010 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CLK_GOOD_OFFSET 0x014 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CONFIG_OFFSET 0x018 // + set * FLL_SET_OFFSET +#define FLL_OBSERVATION_OFFSET 0x100 + +#define FLL_ANALOG_CLKIPC_OFFSET 0x4638 // base addr ARCHI_ANALOG_ADDR + +// register bitfields +#define FLL_SET_RSS_BIT 0 +#define FLL_SET_RSS_WIDTH 2 +#define FLL_SET_RSS_MASK (0x0003) + + +#define FLL_FREQ_REGULATION_LOW_BIT 0 +#define FLL_FREQ_REGULATION_LOW_WIDTH 14 +#define FLL_FREQ_REGULATION_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_REGULATION_HIGH_BIT 16 +#define FLL_FREQ_REGULATION_HIGH_WIDTH 14 +#define FLL_FREQ_REGULATION_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CLK_GOOD_LOW_BIT 0 +#define FLL_FREQ_CLK_GOOD_LOW_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_CLK_GOOD_HIGH_BIT 16 +#define FLL_FREQ_CLK_GOOD_HIGH_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CONFIG_LEVEL_BIT 0 +#define FLL_FREQ_CONFIG_LEVEL_WIDTH 4 +#define FLL_FREQ_CONFIG_LEVEL_MASK (0x0000000F) + +#define FLL_FREQ_CONFIG_DCO_LSB_BIT 4 +#define FLL_FREQ_CONFIG_DCO_LSB_WIDTH 3 +#define FLL_FREQ_CONFIG_DCO_LSB_MASK (0x00000070) + +#define FLL_FREQ_CONFIG_DCO_MSB_BIT 8 +#define FLL_FREQ_CONFIG_DCO_MSB_WIDTH 6 +#define FLL_FREQ_CONFIG_DCO_MSB_MASK (0x00003F00) + +#define FLL_FREQ_CONFIG_OL_BIT 16 +#define FLL_FREQ_CONFIG_OL_WIDTH 1 +#define FLL_FREQ_CONFIG_OL_MASK (0x00010000) + + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rss:1; /* Register set selection, 0b00 or 0b01 */ + unsigned int reserved_0:31; + }; + unsigned int raw; +} fll_reg_rss_t; + +typedef union { + struct { + unsigned int nref_reg_low:14; /* Regulation, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_reg_high:14; /* Regulation, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr0_t; + +typedef union { + struct { + unsigned int nref_cg_low:14; /* Clock good, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_cg_high:14; /* Clock good, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr1_t; + +typedef union { + struct { + unsigned int level:4; /* Start level of binary search, reset value: 0x0 */ + unsigned int dco_lsb:3; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_0:1; + unsigned int dco_msb:6; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_1:2; + unsigned int open_loop:1; /* Open-loop operation */ + unsigned int reserved_2:15; + }; + unsigned int raw; +} fll_reg_fcr2_t; + +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/freq.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/freq.h new file mode 100644 index 0000000..06191ed --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/freq.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC3_5_FREQ_H__ +#define __ARCHI_CHIPS_VIVOSOC3_5_FREQ_H__ + +// register address offsets +#define FREQ_CLK_TREE_CONF_GLOBAL_OFFSET 0x040 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FREQ_CLK_TREE_CONF_CL_OFFSET 0x050 +#define FREQ_CLK_TREE_CONF_SOC_OFFSET 0x054 +#define FREQ_CLK_TREE_CONF_PER_OFFSET 0x058 +#define FREQ_CLK_TREE_CONF_PM_OFFSET 0x05C + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/memory_map.h new file mode 100644 index 0000000..12cdc4e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/memory_map.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_5_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VIVOSOC3_5_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00004000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c004000 +#define ARCHI_L2_PRIV1_SIZE 0x00004000 + +#define ARCHI_L2_SHARED_ADDR 0x1c008000 +#define ARCHI_L2_SHARED_SIZE 0x00010000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + + +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 +#define ARCHI_ANALOG_OFFSET 0x00010000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_ANALOG_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_ANALOG_OFFSET ) + + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/properties.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/properties.h new file mode 100644 index 0000000..7dc58ab --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc3_5/properties.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC3_5_PROPERTIES_H__ +#define __ARCHI_CHIPS_VIVOSOC3_5_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 32768 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 +#define FLL_VERSION 1 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 2 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +// PADs configuration is made of 8bits out of which only the first 3 are used +// bit0 enable pull UP +// bit1 enable pull DOWN +// bit2 enable ST +// bit3..7 not used + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +// aliases +#define APB_SOC_PADS_CONFIG APB_SOC_PADCFG0_OFFSET + +// HAL compatibility definitions, functions not supported +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_CLUSTER_ISOLATE_OFFSET 0x0C +#define APB_SOC_BUSY_OFFSET 0x6C +#define APB_SOC_JTAG_REG 0x74 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/fll.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/fll.h new file mode 100644 index 0000000..7978df9 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/fll.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC4_FLL_H__ +#define __ARCHI_CHIPS_VIVOSOC4_FLL_H__ + +// register address offsets +#define FLL_CONTROL_OFFSET 0x044 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FLL_RESET_OFFSET 0x048 +#define FLL_GPIO_OUTPUT 0x104 + +#define FLL_OFFSET 0x040 // base addr 0x1A100000 (ARCHI_SOC_PERIPHERALS_ADDR) + +#define FLL_SET_SEL_OFFSET 0x000 // base addr 0x1A100000 + fll * FLL_OFFSET +#define FLL_REF_CLK_OFFSET 0x004 +#define FLL_FSM_OBS_OFFSET 0x008 +#define FLL_SHARED_CONFIG_OFFSET 0x00C +#define FLL_SET_OFFSET 0x00C +#define FLL_FREQ_REGULATION_OFFSET 0x010 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CLK_GOOD_OFFSET 0x014 // + set * FLL_SET_OFFSET +#define FLL_FREQ_CONFIG_OFFSET 0x018 // + set * FLL_SET_OFFSET +#define FLL_OBSERVATION_OFFSET 0x100 + +#define FLL_ANALOG_CLKIPC_OFFSET 0x4638 // base addr ARCHI_ANALOG_ADDR + +// register bitfields +#define FLL_SET_RSS_BIT 0 +#define FLL_SET_RSS_WIDTH 2 +#define FLL_SET_RSS_MASK (0x0003) + + +#define FLL_FREQ_REGULATION_LOW_BIT 0 +#define FLL_FREQ_REGULATION_LOW_WIDTH 14 +#define FLL_FREQ_REGULATION_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_REGULATION_HIGH_BIT 16 +#define FLL_FREQ_REGULATION_HIGH_WIDTH 14 +#define FLL_FREQ_REGULATION_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CLK_GOOD_LOW_BIT 0 +#define FLL_FREQ_CLK_GOOD_LOW_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_LOW_MASK (0x00003FFF) + +#define FLL_FREQ_CLK_GOOD_HIGH_BIT 16 +#define FLL_FREQ_CLK_GOOD_HIGH_WIDTH 14 +#define FLL_FREQ_CLK_GOOD_HIGH_MASK (0x3FFF0000) + + +#define FLL_FREQ_CONFIG_LEVEL_BIT 0 +#define FLL_FREQ_CONFIG_LEVEL_WIDTH 4 +#define FLL_FREQ_CONFIG_LEVEL_MASK (0x0000000F) + +#define FLL_FREQ_CONFIG_DCO_LSB_BIT 4 +#define FLL_FREQ_CONFIG_DCO_LSB_WIDTH 3 +#define FLL_FREQ_CONFIG_DCO_LSB_MASK (0x00000070) + +#define FLL_FREQ_CONFIG_DCO_MSB_BIT 8 +#define FLL_FREQ_CONFIG_DCO_MSB_WIDTH 6 +#define FLL_FREQ_CONFIG_DCO_MSB_MASK (0x00003F00) + +#define FLL_FREQ_CONFIG_OL_BIT 16 +#define FLL_FREQ_CONFIG_OL_WIDTH 1 +#define FLL_FREQ_CONFIG_OL_MASK (0x00010000) + + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rss:1; /* Register set selection, 0b00 or 0b01 */ + unsigned int reserved_0:31; + }; + unsigned int raw; +} fll_reg_rss_t; + +typedef union { + struct { + unsigned int nref_reg_low:14; /* Regulation, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_reg_high:14; /* Regulation, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr0_t; + +typedef union { + struct { + unsigned int nref_cg_low:14; /* Clock good, lower boundary, in ref clk cycles */ + unsigned int reserved_0:2; + unsigned int nref_cg_high:14; /* Clock good, upper boundary, in ref clk cycles */ + unsigned int reserved_1:2; + }; + unsigned int raw; +} fll_reg_fcr1_t; + +typedef union { + struct { + unsigned int level:4; /* Start level of binary search, reset value: 0x0 */ + unsigned int dco_lsb:3; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_0:1; + unsigned int dco_msb:6; /* Start point for the binary search, reset value: 0x0 */ + unsigned int reserved_1:2; + unsigned int open_loop:1; /* Open-loop operation */ + unsigned int reserved_2:15; + }; + unsigned int raw; +} fll_reg_fcr2_t; + +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/freq.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/freq.h new file mode 100644 index 0000000..97f5782 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/freq.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_CHIPS_VIVOSOC4_FREQ_H__ +#define __ARCHI_CHIPS_VIVOSOC4_FREQ_H__ + +// register address offsets +#define FREQ_CLK_TREE_CONF_GLOBAL_OFFSET 0x040 // base addr 0x1A104000 (ARCHI_APB_SOC_CTRL_ADDR) +#define FREQ_CLK_TREE_CONF_CL_OFFSET 0x050 +#define FREQ_CLK_TREE_CONF_SOC_OFFSET 0x054 +#define FREQ_CLK_TREE_CONF_PER_OFFSET 0x058 +#define FREQ_CLK_TREE_CONF_PM_OFFSET 0x05C + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/memory_map.h new file mode 100644 index 0000000..a924156 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/memory_map.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC4_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_VIVOSOC4_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00004000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c004000 +#define ARCHI_L2_PRIV1_SIZE 0x00004000 + +#define ARCHI_L2_SHARED_ADDR 0x1c008000 +#define ARCHI_L2_SHARED_SIZE 0x00010000 + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_IF_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_APB_ADV_TIMER_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_DEBUG_OFFSET 0x00008000 +#define ARCHI_FC_ITC_OFFSET 0x00009000 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 +#define ARCHI_ANALOG_OFFSET 0x00010000 + +#define ARCHI_FLL_IF_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FLL_IF_OFFSET ) +#define ARCHI_GPIO_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_APB_ADV_TIMER_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_ADV_TIMER_OFFSET) +#define ARCHI_SOC_EU_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_FC_DEBUG_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_DEBUG_OFFSET ) +#define ARCHI_FC_ITC_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) +#define ARCHI_ANALOG_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_ANALOG_OFFSET ) + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR (ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) (ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR (ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET 0x00000 +#define ARCHI_MCHAN_DEMUX_OFFSET 0x00400 + +#define ARCHI_DEMUX_PERIPHERALS_ADDR (ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR (ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR (ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/properties.h b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/properties.h new file mode 100755 index 0000000..25a2240 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/vivosoc4/properties.h @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_VIVOSOC4_PROPERTIES_H__ +#define __ARCHI_CHIPS_VIVOSOC4_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + +#define ARCHI_L1_SIZE 32768 + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 3 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 3 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 +#define FLL_VERSION 1 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#define ARCHI_CLUSTER_NB_PE 8 + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 4) +#define APB_SOC_PADFUN_PAD(padfun) ((padfun)*16) +#define APB_SOC_PADFUN_SIZE 2 +#define ARCHI_APB_SOC_PADFUN_NB 4 +#define APB_SOC_PADFUN_BIT(pad) (((pad) & 0xF) << 1) + +#define APB_SOC_PADCFG_OFFSET(g) (APB_SOC_PADCFG0_OFFSET+(g)*4) //sets config for pin g*4+0(bits [7:0]) to pin g*4+3(bits [31:24]) +#define APB_SOC_PADCFG_NO(pad) ((pad) >> 2) +#define APB_SOC_PADCFG_PAD(padfun) ((padfun)*4) +#define APB_SOC_PADCFG_SIZE 8 +#define APB_SOC_PADCFG_BIT(pad) (((pad) & 0x3) << 3) + +#define APB_SOC_PWRCMD_OFFSET 0x60 //change power mode(not funtional yet) +#define APB_SOC_PWRCFG_OFFSET 0x64 //configures power modes(not funtional yet) +#define APB_SOC_PWRREG_OFFSET 0x68 //32 bit GP register used by power pngmt routines to see if is hard or cold reboot +#define APB_SOC_BUSY_OFFSET 0x6C //not used at the moment +#define APB_SOC_MMARGIN_OFFSET 0x70 //memory margin pins(not used at the moment) +#define APB_SOC_JTAG_REG 0x74 // R/W register for interaction with the the chip environment +#define APB_SOC_L2_SLEEP_OFFSET 0x78 //memory margin pins(not used at the moment) +#define APB_SOC_NOTUSED3_OFFSET 0x7C //not used at the moment +#define APB_SOC_CLKDIV0_OFFSET 0x80 //soc clock divider(to be removed) +#define APB_SOC_CLKDIV1_OFFSET 0x84 //cluster clock divider(to be removed) +#define APB_SOC_CLKDIV2_OFFSET 0x88 //not used at the moment +#define APB_SOC_CLKDIV3_OFFSET 0x8C //not used at the moment +#define APB_SOC_CLKDIV4_OFFSET 0x90 //not used at the moment +#define APB_SOC_NOTUSED4_OFFSET 0x94 //not used at the moment +#define APB_SOC_NOTUSED5_OFFSET 0x98 //not used at the moment +#define APB_SOC_NOTUSED6_OFFSET 0x9C //not used at the moment +#define APB_SOC_CORESTATUS_OFFSET 0xA0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_CORESTATUS_RO_OFFSET 0xC0 //32bit GP register to be used during testing to return EOC(bit[31]) and status(bit[30:0]) +#define APB_SOC_PADS_CONFIG 0xC4 +#define APB_SOC_RAR 0x100 + +#define APB_SOC_PADS_CONFIG_BOOTSEL_BIT 0 + +#define APB_SOC_JTAG_REG_EXT_BIT 8 +#define APB_SOC_JTAG_REG_EXT_WIDTH 4 + +#define APB_SOC_JTAG_REG_LOC_BIT 0 +#define APB_SOC_JTAG_REG_LOC_WIDTH 4 + +#define APB_SOC_INFO_CORES_OFFSET (APB_SOC_INFO_OFFSET + 2) +#define APB_SOC_INFO_CLUSTERS_OFFSET (APB_SOC_INFO_OFFSET) + +#define APB_SOC_STATUS_EOC_BIT 31 +#define APB_SOC_NB_CORE_BIT 16 + + +#define APB_SOC_BYPASS_OFFSET 0x70 + +#define APB_SOC_BYPASS_CLOCK_GATE_BIT 10 +#define APB_SOC_BYPASS_CLUSTER_STATE_BIT 3 +#define APB_SOC_BYPASS_USER0_BIT 14 +#define APB_SOC_BYPASS_USER1_BIT 15 + + +#define APB_SOC_FLL_CTRL_OFFSET 0xD0 +#define APB_SOC_CLKDIV_SOC_OFFSET 0xD4 +#define APB_SOC_CLKDIV_CLUSTER_OFFSET 0xD8 +#define APB_SOC_CLKDIV_PERIPH_OFFSET 0xDC + + +#define APB_SOC_FLL_CTRL_SOC_BIT 0 +#define APB_SOC_FLL_CTRL_CLUSTER_BIT 1 +#define APB_SOC_FLL_CTRL_PERIPH_BIT 2 + +#define APB_SOC_SLEEP_CONTROL 0x104 + + +#define APB_SOC_RTC_OFFSET 0x1D0 + +#define ARCHI_APB_SOC_BYPASS_ENABLE_BIT 0 +#define ARCHI_APB_SOC_BYPASS_CLUSTER_POWER_BIT 1 +#define ARCHI_APB_SOC_BYPASS_CLUSTER_CLOCK_BIT 2 +#define ARCHI_APB_SOC_BYPASS_FLL_RETENTIVE_BIT 3 +#define ARCHI_APB_SOC_BYPASS_FLL_OFF_BIT 4 +#define ARCHI_APB_SOC_BYPASS_CLUSTER_RESET_BIT 5 +#define ARCHI_APB_SOC_BYPASS_CLUSTER_ISOLATE_BIT 6 +#define ARCHI_APB_SOC_BYPASS_CLUSTER_RETENTIVE_BIT 7 +#define ARCHI_APB_SOC_BYPASS_POWER_OK_BIT 8 +#define ARCHI_APB_SOC_BYPASS_CLOCK_OK_BIT 9 +#define ARCHI_APB_SOC_BYPASS_POWER_DOWN_BIT 10 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/wolfe/apb_soc_ctrl_new.h b/sw/pulp-sdk/archi/include/archi/chips/wolfe/apb_soc_ctrl_new.h new file mode 100644 index 0000000..d09e928 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/wolfe/apb_soc_ctrl_new.h @@ -0,0 +1,271 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_WOLFE_APB_SOC_CTRL_NEW_H__ +#define __INCLUDE_ARCHI_CHIPS_WOLFE_APB_SOC_CTRL_NEW_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Deep sleep control register +#define APB_SOC_SLEEP_CONTROL_OFFSET 0x104 + +// First RTC register +#define APB_SOC_RTC_FIRST_REG_OFFSET 0x1d0 + +// Last RTC register +#define APB_SOC_RTC_LAST_REG_OFFSET 0x1dc + + + +// +// REGISTERS FIELDS +// + +// FLL retention configuration. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_FLL_RET_BIT 0 +#define APB_SOC_SLEEP_CONTROL_FLL_RET_WIDTH 2 +#define APB_SOC_SLEEP_CONTROL_FLL_RET_MASK 0x3 + +// Memory retention configuration part 0. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_BIT 2 +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_WIDTH 1 +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_MASK 0x4 + +// External wakeup selection. This gives the GPIO numer which can wakeup the chip when it is in deep sleep mode. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_BIT 6 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_WIDTH 5 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_MASK 0x7c0 + +// External wakeup type. This tells the way the external GPIO can wakeup the chip while it is in deep sleep (raising edge, falling edge, etc). Possible values: - 0: Rising edge. - 1: Falling edge. - 2: Level high. - 3: Level low. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_BIT 11 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_WIDTH 2 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_MASK 0x1800 + +// External wakeup enable. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_BIT 13 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_WIDTH 1 +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_MASK 0x2000 + +// Wake-up state. This specifies in which state the PMU should wakeup the chip. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_WAKEUP_BIT 14 +#define APB_SOC_SLEEP_CONTROL_WAKEUP_WIDTH 2 +#define APB_SOC_SLEEP_CONTROL_WAKEUP_MASK 0xc000 + +// Boot type. This is a user field written by the SW which is interpreted by the oot code and runtime after the chip has rebooted. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_BIT 18 +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_WIDTH 2 +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_MASK 0xc0000 + +// Cluster wakeup state. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_BIT 20 +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_WIDTH 1 +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_MASK 0x100000 + +// Memory retention configuration part 1. (access: R/W) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_BIT 21 +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_WIDTH 11 +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_MASK 0xffe00000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int fll_ret :2 ; // FLL retention configuration. + unsigned int mem_ret_0 :1 ; // Memory retention configuration part 0. + unsigned int padding0:3 ; + unsigned int extwakeup_sel :5 ; // External wakeup selection. This gives the GPIO numer which can wakeup the chip when it is in deep sleep mode. + unsigned int extwakeup_type :2 ; // External wakeup type. This tells the way the external GPIO can wakeup the chip while it is in deep sleep (raising edge, falling edge, etc). Possible values: - 0: Rising edge. - 1: Falling edge. - 2: Level high. - 3: Level low. + unsigned int extwakeup_en :1 ; // External wakeup enable. + unsigned int wakeup :2 ; // Wake-up state. This specifies in which state the PMU should wakeup the chip. + unsigned int padding1:2 ; + unsigned int boot_type :2 ; // Boot type. This is a user field written by the SW which is interpreted by the oot code and runtime after the chip has rebooted. + unsigned int cluster_wakeup :1 ; // Cluster wakeup state. + unsigned int mem_ret_1 :11; // Memory retention configuration part 1. + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_sleep_control_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rtc_first_reg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) apb_soc_rtc_last_reg_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_apb_soc_sleep_control : public vp::reg_32 +{ +public: + inline void fll_ret_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_FLL_RET_BIT, APB_SOC_SLEEP_CONTROL_FLL_RET_WIDTH); } + inline uint32_t fll_ret_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_FLL_RET_BIT, APB_SOC_SLEEP_CONTROL_FLL_RET_WIDTH); } + inline void mem_ret_0_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_MEM_RET_0_BIT, APB_SOC_SLEEP_CONTROL_MEM_RET_0_WIDTH); } + inline uint32_t mem_ret_0_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_MEM_RET_0_BIT, APB_SOC_SLEEP_CONTROL_MEM_RET_0_WIDTH); } + inline void extwakeup_sel_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_WIDTH); } + inline uint32_t extwakeup_sel_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_WIDTH); } + inline void extwakeup_type_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_WIDTH); } + inline uint32_t extwakeup_type_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_WIDTH); } + inline void extwakeup_en_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_WIDTH); } + inline uint32_t extwakeup_en_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_BIT, APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_WIDTH); } + inline void wakeup_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_WAKEUP_BIT, APB_SOC_SLEEP_CONTROL_WAKEUP_WIDTH); } + inline uint32_t wakeup_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_WAKEUP_BIT, APB_SOC_SLEEP_CONTROL_WAKEUP_WIDTH); } + inline void boot_type_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_BOOT_TYPE_BIT, APB_SOC_SLEEP_CONTROL_BOOT_TYPE_WIDTH); } + inline uint32_t boot_type_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_BOOT_TYPE_BIT, APB_SOC_SLEEP_CONTROL_BOOT_TYPE_WIDTH); } + inline void cluster_wakeup_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_BIT, APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_WIDTH); } + inline uint32_t cluster_wakeup_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_BIT, APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_WIDTH); } + inline void mem_ret_1_set(uint32_t value) { this->set_field(value, APB_SOC_SLEEP_CONTROL_MEM_RET_1_BIT, APB_SOC_SLEEP_CONTROL_MEM_RET_1_WIDTH); } + inline uint32_t mem_ret_1_get() { return this->get_field(APB_SOC_SLEEP_CONTROL_MEM_RET_1_BIT, APB_SOC_SLEEP_CONTROL_MEM_RET_1_WIDTH); } +}; + +class vp_apb_soc_rtc_first_reg : public vp::reg_32 +{ +public: +}; + +class vp_apb_soc_rtc_last_reg : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int sleep_control ; // Deep sleep control register + unsigned int rtc_first_reg ; // First RTC register + unsigned int rtc_last_reg ; // Last RTC register +} __attribute__((packed)) apb_soc_apb_soc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t apb_soc_sleep_control_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_SLEEP_CONTROL_OFFSET); } +static inline void apb_soc_sleep_control_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_SLEEP_CONTROL_OFFSET, value); } + +static inline uint32_t apb_soc_rtc_first_reg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RTC_FIRST_REG_OFFSET); } +static inline void apb_soc_rtc_first_reg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RTC_FIRST_REG_OFFSET, value); } + +static inline uint32_t apb_soc_rtc_last_reg_get(uint32_t base) { return ARCHI_READ(base, APB_SOC_RTC_LAST_REG_OFFSET); } +static inline void apb_soc_rtc_last_reg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, APB_SOC_RTC_LAST_REG_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define APB_SOC_SLEEP_CONTROL_FLL_RET_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define APB_SOC_SLEEP_CONTROL_FLL_RET_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define APB_SOC_SLEEP_CONTROL_FLL_RET_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define APB_SOC_SLEEP_CONTROL_FLL_RET(val) ((val) << 0) + +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_0(val) ((val) << 2) + +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_GET(value) (ARCHI_BEXTRACTU((value),5,6)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_GETS(value) (ARCHI_BEXTRACT((value),5,6)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL_SET(value,field) (ARCHI_BINSERT((value),(field),5,6)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_SEL(val) ((val) << 6) + +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_GET(value) (ARCHI_BEXTRACTU((value),2,11)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_GETS(value) (ARCHI_BEXTRACT((value),2,11)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,11)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_TYPE(val) ((val) << 11) + +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define APB_SOC_SLEEP_CONTROL_EXTWAKEUP_EN(val) ((val) << 13) + +#define APB_SOC_SLEEP_CONTROL_WAKEUP_GET(value) (ARCHI_BEXTRACTU((value),2,14)) +#define APB_SOC_SLEEP_CONTROL_WAKEUP_GETS(value) (ARCHI_BEXTRACT((value),2,14)) +#define APB_SOC_SLEEP_CONTROL_WAKEUP_SET(value,field) (ARCHI_BINSERT((value),(field),2,14)) +#define APB_SOC_SLEEP_CONTROL_WAKEUP(val) ((val) << 14) + +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_GET(value) (ARCHI_BEXTRACTU((value),2,18)) +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_GETS(value) (ARCHI_BEXTRACT((value),2,18)) +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),2,18)) +#define APB_SOC_SLEEP_CONTROL_BOOT_TYPE(val) ((val) << 18) + +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_GET(value) (ARCHI_BEXTRACTU((value),1,20)) +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_GETS(value) (ARCHI_BEXTRACT((value),1,20)) +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP_SET(value,field) (ARCHI_BINSERT((value),(field),1,20)) +#define APB_SOC_SLEEP_CONTROL_CLUSTER_WAKEUP(val) ((val) << 20) + +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_GET(value) (ARCHI_BEXTRACTU((value),11,21)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_GETS(value) (ARCHI_BEXTRACT((value),11,21)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1_SET(value,field) (ARCHI_BINSERT((value),(field),11,21)) +#define APB_SOC_SLEEP_CONTROL_MEM_RET_1(val) ((val) << 21) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/wolfe/memory_map.h b/sw/pulp-sdk/archi/include/archi/chips/wolfe/memory_map.h new file mode 100644 index 0000000..84690a5 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/wolfe/memory_map.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_WOLFE_MEMORY_MAP_H__ +#define __ARCHI_CHIPS_WOLFE_MEMORY_MAP_H__ + + +/* + * MEMORIES + */ + +#define ARCHI_L2_PRIV0_ADDR 0x1c000000 +#define ARCHI_L2_PRIV0_SIZE 0x00008000 + +#define ARCHI_L2_PRIV1_ADDR 0x1c008000 +#define ARCHI_L2_PRIV1_SIZE 0x00008000 + +#define ARCHI_L2_SHARED_ADDR 0x1c010000 +#define ARCHI_L2_SHARED_SIZE 0x00070000 + + + +/* + * SOC PERIPHERALS + */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + + +#define ARCHI_FC_TIMER_SIZE 0x00000800 + +#define ARCHI_FLL_OFFSET 0x00000000 +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_PWM_OFFSET 0x00005000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_PMU_OFFSET 0x00007000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + + + +#define ARCHI_GPIO_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET ) +#define ARCHI_UDMA_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET ) +#define ARCHI_APB_SOC_CTRL_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET ) +#define ARCHI_PWM_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PWM_OFFSET ) +#define ARCHI_SOC_EU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET ) +#define ARCHI_PMU_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_PMU_OFFSET ) +#define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) +#define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) +#define ARCHI_STDOUT_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET ) + + +#define ARCHI_FLL_AREA_SIZE 0x00000010 + + + +/* + * FC + */ + +#define ARCHI_FC_ADDR 0x00000000 +#define ARCHI_FC_GLOBAL_ADDR 0x1B000000 + + +/* + * CLUSTER + */ + +#define ARCHI_CLUSTER_ADDR 0x00000000 +#define ARCHI_CLUSTER_SIZE 0x00400000 +#define ARCHI_CLUSTER_GLOBAL_ADDR(cid) (0x10000000 + (cid)*ARCHI_CLUSTER_SIZE) + + + +/* + * CLUSTER PERIPHERALS + */ + +#define ARCHI_CLUSTER_PERIPHERALS_OFFSET 0x00200000 + +#define ARCHI_TIMER_SIZE 0x00000800 + +#define ARCHI_CLUSTER_CTRL_OFFSET 0x00000000 +#define ARCHI_TIMER_OFFSET 0x00000400 +#define ARCHI_EU_OFFSET 0x00000800 +#define ARCHI_HWCE_OFFSET 0x00001000 +#define ARCHI_ICACHE_CTRL_OFFSET 0x00001400 +#define ARCHI_MCHAN_EXT_OFFSET 0x00001800 + +#define ARCHI_CLUSTER_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) +#define ARCHI_CLUSTER_PERIPHERALS_GLOBAL_ADDR(cid) ( ARCHI_CLUSTER_GLOBAL_ADDR(cid) + ARCHI_CLUSTER_PERIPHERALS_OFFSET ) + +#define ARCHI_CLUSTER_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_CLUSTER_CTRL_OFFSET ) +#define ARCHI_ICACHE_CTRL_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_ICACHE_CTRL_OFFSET ) +#define ARCHI_EU_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_EU_OFFSET ) +#define ARCHI_HWCE_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_HWCE_OFFSET ) +#define ARCHI_MCHAN_EXT_ADDR ( ARCHI_CLUSTER_PERIPHERALS_ADDR + ARCHI_MCHAN_EXT_OFFSET ) + + + +/* + * CLUSTER DEMUX PERIPHERALS + */ + +#define ARCHI_DEMUX_PERIPHERALS_OFFSET 0x204000 + +#define ARCHI_EU_DEMUX_OFFSET ( 0x00000 ) +#define ARCHI_MCHAN_DEMUX_OFFSET ( 0x00400 ) + + +#define ARCHI_DEMUX_PERIPHERALS_ADDR ( ARCHI_CLUSTER_ADDR + ARCHI_DEMUX_PERIPHERALS_OFFSET ) + +#define ARCHI_EU_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_EU_DEMUX_OFFSET ) +#define ARCHI_MCHAN_DEMUX_ADDR ( ARCHI_DEMUX_PERIPHERALS_ADDR + ARCHI_MCHAN_DEMUX_OFFSET ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/wolfe/pmu.h b/sw/pulp-sdk/archi/include/archi/chips/wolfe/pmu.h new file mode 100644 index 0000000..e473db2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/wolfe/pmu.h @@ -0,0 +1,330 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_CHIPS_WOLFE_PMU_H__ +#define __INCLUDE_ARCHI_CHIPS_WOLFE_PMU_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_pmu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu0 +// + +#define PMU_ICU0_OFFSET 0x2 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP icu1 +// + +#define PMU_ICU1_OFFSET 0x3 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_icu1_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP dmu0 +// + +#define PMU_DMU0_OFFSET 0x4 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) pmu_dmu0_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// CUSTOM FIELDS +// +#define PMU_BOOT -1 +#define PMU_SOC_ACTIVE_NV 0x00 +#define PMU_SOC_ACTIVE_LV 0x01 +#define PMU_SOC_CLUSTER_ACTIVE_NV 0x02 +#define PMU_SOC_CLUSTER_ACTIVE_LV 0x03 +#define PMU_DEEP_SLEEP 0x04 +#define PMU_DEEP_SLEEP_RETENTIVE 0x05 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/chips/wolfe/properties.h b/sw/pulp-sdk/archi/include/archi/chips/wolfe/properties.h new file mode 100644 index 0000000..e840e33 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/chips/wolfe/properties.h @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_CHIPS_WOLFE_PROPERTIES_H__ +#define __ARCHI_CHIPS_WOLFE_PROPERTIES_H__ + +/* + * MEMORIES + */ + +#define ARCHI_HAS_L2 1 +#define ARCHI_HAS_L1 1 + + + +/* + * MEMORY ALIAS + */ + +#define ARCHI_HAS_L1_ALIAS 1 +#define ARCHI_HAS_L2_ALIAS 1 + +#define ARCHI_L1_SIZE 65536 + + + +/* + * IP VERSIONS + */ + +#define UDMA_VERSION 2 +#define PERIPH_VERSION 2 +#define TIMER_VERSION 2 +#define SOC_EU_VERSION 1 +#define APB_SOC_VERSION 2 +#define STDOUT_VERSION 2 +#define GPIO_VERSION 2 +#define EU_VERSION 3 +#define ITC_VERSION 1 +#define FLL_VERSION 1 +#define RISCV_VERSION 4 +#define MCHAN_VERSION 6 +#define PADS_VERSION 2 +#define RTC_VERSION 2 +#define PWM_VERSION 1 + +/* + * SOC + */ + +#define ARCHI_PWM_NB 1 +#define ARCHI_PWM_NB_TIMERS 4 + + +/* + * CLUSTER + */ + +#define ARCHI_HAS_CLUSTER 1 +#define ARCHI_L1_TAS_BIT 20 +#if PULP_CHIP == CHIP_WOLFE_16 +#define ARCHI_CLUSTER_NB_PE 16 +#else +#define ARCHI_CLUSTER_NB_PE 8 +#endif + + + +/* + * HWS + */ + +#define ARCHI_EU_NB_HW_MUTEX 1 + + + +/* + * FC + */ + +#define ARCHI_FC_CID 31 +#define ARCHI_HAS_FC_ITC 1 + + + +/* + * CLOCKS + */ + +#define ARCHI_REF_CLOCK_LOG2 15 +#define ARCHI_REF_CLOCK (1<> 2) + +#define ARCHI_CLUSTER_CTRL_EOC 0x0 +#define ARCHI_CLUSTER_CTRL_FETCH_EN 0x8 +#define ARCHI_CLUSTER_CTRL_EVENT 0x10 +#define ARCHI_CLUSTER_CTRL_CLUSTER_CFG 0x18 +#define ARCHI_CLUSTER_CTRL_CLUSTER_CLK_GATE 0x20 +#define ARCHI_CLUSTER_CTRL_DBG_STATUS 0x28 +#define ARCHI_CLUSTER_CTRL_DBG_HALT_MASK 0x38 +#define ARCHI_CLUSTER_CTRL_BOOTADDR(core) (0x40 + 4*(core)) +#define ARCHI_CLUSTER_CTRL_BOOTADDR_COREID(offset) (((offset) - ARCHI_CLUSTER_CTRL_BOOTADDR(0)) >> 2) + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/dma/mchan_v3.h b/sw/pulp-sdk/archi/include/archi/dma/mchan_v3.h new file mode 100644 index 0000000..746ad1b --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/dma/mchan_v3.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef ARCHI_DMA_MCHAN_V3_H +#define ARCHI_DMA_MCHAN_V3_H + +#define TCDM_ADDR_REG_OFFSET ( 0x0 ) +#define EXT_ADDR_REG_OFFSET ( 0x4 ) +#define CMD_QUEUE_OFFSET ( 0x8 ) +#define CMD_QUEUE_BUSY_REG_OFFSET ( 0xC ) + +#define ST1 0x0001 +#define ST2 0x0002 +#define ST4 0x0004 +#define ST8 0x0008 +#define ST16 0x0010 +#define ST32 0x0020 +#define ST64 0x0040 +#define ST128 0x0080 +#define ST256 0x0100 +#define ST512 0x0200 +#define ST1024 0x0400 +#define ST2048 0x0800 +#define ST4096 0x1000 +#define ST8192 0x2000 +#define ST16384 0x4000 + +#define LD1 0x8001 +#define LD2 0x8002 +#define LD4 0x8004 +#define LD8 0x8008 +#define LD16 0x8010 +#define LD32 0x8020 +#define LD64 0x8040 +#define LD128 0x8080 +#define LD256 0x8100 +#define LD512 0x8200 +#define LD1024 0x8400 +#define LD2048 0x8800 +#define LD4096 0x9000 +#define LD8192 0xA000 +#define LD16384 0xC000 + +#define MCHAN_TYPE_OFFSET 15 +#define MCHAN_TYPE(x) (((x) >> MCHAN_TYPE_OFFSET) & 1) + +#define MCHAN_SIZE_OFFSET 0 +#define MCHAN_SIZE(x) (((x) >> MCHAN_SIZE_OFFSET) & 0x7fff) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/dma/mchan_v5.h b/sw/pulp-sdk/archi/include/archi/dma/mchan_v5.h new file mode 100644 index 0000000..395467e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/dma/mchan_v5.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_DMA_MCHAN_V5_H__ +#define __ARCHI_DMA_MCHAN_V5_H__ + +#define MCHAN_COMMAND_QUEUE_OFFSET 0x0 +#define MCHAN_STATUS_REGISTER_OFFSET 0x4 + +#define MCHAN_SIZE_OFFSET 0 +#define MCHAN_LEN_WIDTH 16 +#define MCHAN_LEN_MASK ((1<> MCHAN_SIZE_OFFSET) & MCHAN_LEN_MASK) + +#define MCHAN_TYPE_OFFSET (MCHAN_LEN_WIDTH) +#define MCHAN_TYPE(x) (((x) >> MCHAN_TYPE_OFFSET) & 1) + +#define MCHAN_INCR_OFFSET (MCHAN_LEN_WIDTH + 1) +#define MCHAN_INCR(x) (((x) >> MCHAN_INCR_OFFSET) & 1) + +#define MCHAN_TWD_OFFSET (MCHAN_LEN_WIDTH + 2) +#define MCHAN_TWD(x) (((x) >> MCHAN_TWD_OFFSET) & 1) + +#define MCHAN_2D_STRIDE_OFFSET (16) +#define MCHAN_2D_STRIDE_WIDTH (16) +#define MCHAN_2D_STRIDE_MASK ((1<> MCHAN_2D_STRIDE_OFFSET) & MCHAN_2D_STRIDE_MASK) + +#define MCHAN_2D_LEN_OFFSET (0) +#define MCHAN_2D_LEN_WIDTH (16) +#define MCHAN_2D_LEN_MASK ((1<> MCHAN_2D_LEN_OFFSET) & MCHAN_2D_LEN_MASK) + +// Direction of the transfer +#define MCHAN_LOC_TO_EXT_MODE 0x0 // From inside the cluster to outside (e.g. L1 to L2) +#define MCHAN_EXT_TO_LOC_MODE 0x1 // From outside the cluster to inside the cluster (e.g. L2 to L1) +#define MCHAN_TX_MODE 0x0 +#define MCHAN_RX_MODE 0x1 + +// Address increment +#define MCHAN_FIX_MODE 0x0 // No increment, the access address is always the same, useful for streaming devices +#define MCHAN_INC_MODE 0x1 // Classic address increment + +// 1D or 2D transfer +#define MCHAN_LIN_MODE 0x0 // Classic linear (1D) mode +#define MCHAN_TWD_MODE 0x1 // 2D mode, for block transfer + +#define MCHAN_NB_COUNTERS 4 + + + + + + + + + + + + + + +// Register map + +#define PLP_DMA_QUEUE_OFFSET 0x0 +#define PLP_DMA_STATUS_OFFSET 0x4 + +// Command bitfield + +#define PLP_DMA_SIZE_BIT 0 +#define PLP_DMA_SIZE_WIDTH 16 +#define PLP_DMA_TYPE_BIT (PLP_DMA_SIZE_WIDTH) +#define PLP_DMA_INCR_BIT (PLP_DMA_SIZE_WIDTH + 1) +#define PLP_DMA_2D_BIT (PLP_DMA_SIZE_WIDTH + 2) + +#define PLP_DMA_LOC2EXT 0 +#define PLP_DMA_EXT2LOC 1 + +#define PLP_DMA_1D 0 +#define PLP_DMA_2D 1 + +#define PLP_DMA_FIX 0 +#define PLP_DMA_INC 1 + +// Stride bitfield + +#define PLP_DMA_2D_STRIDE_BIT 16 +#define PLP_DMA_2D_STRIDE_WIDTH 16 + +#define PLP_DMA_2D_LEN_BIT 0 +#define PLP_DMA_2D_LEN_WIDTH 16 + +// Macros +#define PLP_DMA_SIZE_GET(x) (((x) >> PLP_DMA_SIZE_BIT) & ((1<> PLP_DMA_TYPE_BIT) & 1) +#define PLP_DMA_INCR_GET(x) (((x) >> PLP_DMA_INCR_BIT) & 1) +#define PLP_DMA_2D_GET(x) (((x) >> PLP_DMA_2D_BIT) & 1) + +#define PLP_DMA_2D_STRIDE_GET(x) (((x) >> PLP_DMA_2D_STRIDE_BIT) & ((1<> PLP_DMA_2D_LEN_BIT) & ((1<> PLP_DMA_SIZE_BIT) & ((1<> PLP_DMA_TYPE_BIT) & 1) +#define PLP_DMA_INCR_GET(x) (((x) >> PLP_DMA_INCR_BIT) & 1) +#define PLP_DMA_2D_GET(x) (((x) >> PLP_DMA_2D_BIT) & 1) +#define PLP_DMA_ELE_GET(x) (((x) >> PLP_DMA_ELE_BIT) & 1) +#define PLP_DMA_ILE_GET(x) (((x) >> PLP_DMA_ILE_BIT) & 1) +#define PLP_DMA_BLE_GET(x) (((x) >> PLP_DMA_BLE_BIT) & 1) + +#define PLP_DMA_2D_STRIDE_GET(x) (((x) >> PLP_DMA_2D_STRIDE_BIT) & ((1<> PLP_DMA_2D_LEN_BIT) & ((1< +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Cluster DMA configuration register. +#define MCHAN_CMD_OFFSET 0x0 + +// Cluster DMA status register. +#define MCHAN_STATUS_OFFSET 0x4 + + + +// +// REGISTERS FIELDS +// + +// Format is operation dependent. See below. (access: R/W) +#define MCHAN_CMD_CMD_BIT 0 +#define MCHAN_CMD_CMD_WIDTH 32 +#define MCHAN_CMD_CMD_MASK 0xffffffff + +// Format is operation dependent. See below. (access: R/W) +#define MCHAN_STATUS_STATUS_BIT 0 +#define MCHAN_STATUS_STATUS_WIDTH 32 +#define MCHAN_STATUS_STATUS_MASK 0xffffffff + +// Transfer length in bytes configuration bitfield. (access: W) +#define MCHAN_CMD_CMD_LEN_BIT 0 +#define MCHAN_CMD_CMD_LEN_WIDTH 17 +#define MCHAN_CMD_CMD_LEN_MASK 0x1ffff + +// Transfer direction configuration bitfield: - 1'b0: L1 to L2 - 1'b1: L2 to L2 (access: W) +#define MCHAN_CMD_CMD_TYPE_BIT 17 +#define MCHAN_CMD_CMD_TYPE_WIDTH 1 +#define MCHAN_CMD_CMD_TYPE_MASK 0x20000 + +// Transfer incremental configuration bitfield: - 1'b0: non incremental - 1'b1: incremental (access: W) +#define MCHAN_CMD_CMD_INC_BIT 18 +#define MCHAN_CMD_CMD_INC_WIDTH 1 +#define MCHAN_CMD_CMD_INC_MASK 0x40000 + +// Transfer type configuration bitfield: - 1'b0: linear transfer in EXT interface - 1'b1: 2D transfer in EXT interface (access: W) +#define MCHAN_CMD_CMD__2D_EXT_BIT 19 +#define MCHAN_CMD_CMD__2D_EXT_WIDTH 1 +#define MCHAN_CMD_CMD__2D_EXT_MASK 0x80000 + +// Transfer event generation configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: W) +#define MCHAN_CMD_CMD_ELE_BIT 20 +#define MCHAN_CMD_CMD_ELE_WIDTH 1 +#define MCHAN_CMD_CMD_ELE_MASK 0x100000 + +// Transfer interrupt generation configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: W) +#define MCHAN_CMD_CMD_ILE_BIT 21 +#define MCHAN_CMD_CMD_ILE_WIDTH 1 +#define MCHAN_CMD_CMD_ILE_MASK 0x200000 + +// Transfer event or interrupt broadcast configuration bitfield: - 1'b0: event or interrupt is routed to the cluster core who initiated the transfer - 1'b1: event or interrupt are broadcasted to all cluster cores (access: W) +#define MCHAN_CMD_CMD_BLE_BIT 22 +#define MCHAN_CMD_CMD_BLE_WIDTH 1 +#define MCHAN_CMD_CMD_BLE_MASK 0x400000 + +// Transfer type configuration bitfield: - 1'b0: linear transfer in TCDM interface - 1'b1: 2D transfer in TCDM interface (access: W) +#define MCHAN_CMD_CMD__2D_TCDM_BIT 23 +#define MCHAN_CMD_CMD__2D_TCDM_WIDTH 1 +#define MCHAN_CMD_CMD__2D_TCDM_MASK 0x800000 + +// Transfer identifier value bitfield. (access: R) +#define MCHAN_CMD_GET_TID_TID_BIT 0 +#define MCHAN_CMD_GET_TID_TID_WIDTH 4 +#define MCHAN_CMD_GET_TID_TID_MASK 0xf + +// Transfer L1 base address configuration bitfield. (access: W) +#define MCHAN_CMD_TCDM_ADDR_ADDR_BIT 0 +#define MCHAN_CMD_TCDM_ADDR_ADDR_WIDTH 32 +#define MCHAN_CMD_TCDM_ADDR_ADDR_MASK 0xffffffff + +// Transfer L2 base address configuration bitfield. (access: W) +#define MCHAN_CMD_EXT_ADDR_ADDR_BIT 0 +#define MCHAN_CMD_EXT_ADDR_ADDR_WIDTH 32 +#define MCHAN_CMD_EXT_ADDR_ADDR_MASK 0xffffffff + +// EXT 2D transfer conut value configuration bitfield. (access: W) +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_BIT 0 +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_WIDTH 32 +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_MASK 0xffffffff + +// EXT 2D transfer stride value configuration bitfield. (access: W) +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_BIT 0 +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_WIDTH 32 +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_MASK 0xffffffff + +// TCDM 2D transfer conut value configuration bitfield. (access: W) +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_BIT 0 +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_WIDTH 32 +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_MASK 0xffffffff + +// TCDM 2D transfer stride value configuration bitfield. (access: W) +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_BIT 0 +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_WIDTH 32 +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_MASK 0xffffffff + +// Transfer status bitfield: TID_TR[i]=1'b1 means that transfer with TID i is active. (access: R) +#define MCHAN_STATUS_STATUS_TID_TR_BIT 0 +#define MCHAN_STATUS_STATUS_TID_TR_WIDTH 16 +#define MCHAN_STATUS_STATUS_TID_TR_MASK 0xffff + +// Transfer status bitfield: - TID_TR[i]=1'b0 means that transfer allocator with TID i-16 is free. - TID_TR[i]=1'b1 means that transfer allocator with TID i-16 is reserved. (access: R) +#define MCHAN_STATUS_STATUS_TID_ALLOC_BIT 16 +#define MCHAN_STATUS_STATUS_TID_ALLOC_WIDTH 16 +#define MCHAN_STATUS_STATUS_TID_ALLOC_MASK 0xffff0000 + +// Transfer canceller configuration bitfield. Writing a 1'b1 in TID_FREE[i] will free transfer with TID i. (access: W) +#define MCHAN_STATUS_FREE_TID_TID_FREE_BIT 0 +#define MCHAN_STATUS_FREE_TID_TID_FREE_WIDTH 16 +#define MCHAN_STATUS_FREE_TID_TID_FREE_MASK 0xffff + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int cmd :32; // Format is operation dependent. See below. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_t; + +typedef union { + struct { + unsigned int status :32; // Format is operation dependent. See below. + }; + unsigned int raw; +} __attribute__((packed)) mchan_status_t; + +typedef union { + struct { + unsigned int len :17; // Transfer length in bytes configuration bitfield. + unsigned int type :1 ; // Transfer direction configuration bitfield: - 1'b0: L1 to L2 - 1'b1: L2 to L2 + unsigned int inc :1 ; // Transfer incremental configuration bitfield: - 1'b0: non incremental - 1'b1: incremental + unsigned int _2d_ext :1 ; // Transfer type configuration bitfield: - 1'b0: linear transfer in EXT interface - 1'b1: 2D transfer in EXT interface + unsigned int ele :1 ; // Transfer event generation configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int ile :1 ; // Transfer interrupt generation configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int ble :1 ; // Transfer event or interrupt broadcast configuration bitfield: - 1'b0: event or interrupt is routed to the cluster core who initiated the transfer - 1'b1: event or interrupt are broadcasted to all cluster cores + unsigned int _2d_tcdm :1 ; // Transfer type configuration bitfield: - 1'b0: linear transfer in TCDM interface - 1'b1: 2D transfer in TCDM interface + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_cmd_t; + +typedef union { + struct { + unsigned int tid :4 ; // Transfer identifier value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_get_tid_t; + +typedef union { + struct { + unsigned int addr :32; // Transfer L1 base address configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_tcdm_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Transfer L2 base address configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_ext_addr_t; + +typedef union { + struct { + unsigned int _2d_ext_count :32; // EXT 2D transfer conut value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_2d_ext_count_t; + +typedef union { + struct { + unsigned int _2d_ext_stride :32; // EXT 2D transfer stride value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_2d_ext_stride_t; + +typedef union { + struct { + unsigned int _2d_tcdm_count :32; // TCDM 2D transfer conut value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_2d_tcdm_count_t; + +typedef union { + struct { + unsigned int _2d_tcdm_stride :32; // TCDM 2D transfer stride value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) mchan_cmd_2d_tcdm_stride_t; + +typedef union { + struct { + unsigned int tid_tr :16; // Transfer status bitfield: TID_TR[i]=1'b1 means that transfer with TID i is active. + unsigned int tid_alloc :16; // Transfer status bitfield: - TID_TR[i]=1'b0 means that transfer allocator with TID i-16 is free. - TID_TR[i]=1'b1 means that transfer allocator with TID i-16 is reserved. + }; + unsigned int raw; +} __attribute__((packed)) mchan_status_status_t; + +typedef union { + struct { + unsigned int tid_free :16; // Transfer canceller configuration bitfield. Writing a 1'b1 in TID_FREE[i] will free transfer with TID i. + }; + unsigned int raw; +} __attribute__((packed)) mchan_status_free_tid_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_mchan_cmd : public vp::reg_32 +{ +public: + inline void cmd_set(uint32_t value) { this->set_field(value, MCHAN_CMD_CMD_BIT, MCHAN_CMD_CMD_WIDTH); } + inline uint32_t cmd_get() { return this->get_field(MCHAN_CMD_CMD_BIT, MCHAN_CMD_CMD_WIDTH); } +}; + +class vp_mchan_status : public vp::reg_32 +{ +public: + inline void status_set(uint32_t value) { this->set_field(value, MCHAN_STATUS_STATUS_BIT, MCHAN_STATUS_STATUS_WIDTH); } + inline uint32_t status_get() { return this->get_field(MCHAN_STATUS_STATUS_BIT, MCHAN_STATUS_STATUS_WIDTH); } +}; + +class vp_mchan_cmd_tcdm_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, MCHAN_CMD_TCDM_ADDR_ADDR_BIT, MCHAN_CMD_TCDM_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(MCHAN_CMD_TCDM_ADDR_ADDR_BIT, MCHAN_CMD_TCDM_ADDR_ADDR_WIDTH); } +}; + +class vp_mchan_cmd_ext_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, MCHAN_CMD_EXT_ADDR_ADDR_BIT, MCHAN_CMD_EXT_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(MCHAN_CMD_EXT_ADDR_ADDR_BIT, MCHAN_CMD_EXT_ADDR_ADDR_WIDTH); } +}; + +class vp_mchan_cmd_2d_ext_count : public vp::reg_32 +{ +public: + inline void _2d_ext_count_set(uint32_t value) { this->set_field(value, MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_BIT, MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_WIDTH); } + inline uint32_t _2d_ext_count_get() { return this->get_field(MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_BIT, MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_WIDTH); } +}; + +class vp_mchan_cmd_2d_ext_stride : public vp::reg_32 +{ +public: + inline void _2d_ext_stride_set(uint32_t value) { this->set_field(value, MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_BIT, MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_WIDTH); } + inline uint32_t _2d_ext_stride_get() { return this->get_field(MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_BIT, MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_WIDTH); } +}; + +class vp_mchan_cmd_2d_tcdm_count : public vp::reg_32 +{ +public: + inline void _2d_tcdm_count_set(uint32_t value) { this->set_field(value, MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_BIT, MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_WIDTH); } + inline uint32_t _2d_tcdm_count_get() { return this->get_field(MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_BIT, MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_WIDTH); } +}; + +class vp_mchan_cmd_2d_tcdm_stride : public vp::reg_32 +{ +public: + inline void _2d_tcdm_stride_set(uint32_t value) { this->set_field(value, MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_BIT, MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_WIDTH); } + inline uint32_t _2d_tcdm_stride_get() { return this->get_field(MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_BIT, MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_WIDTH); } +}; + +class vp_mchan_status_status : public vp::reg_16 +{ +public: + inline void tid_tr_set(uint16_t value) { this->set_field(value, MCHAN_STATUS_STATUS_TID_TR_BIT, MCHAN_STATUS_STATUS_TID_TR_WIDTH); } + inline uint16_t tid_tr_get() { return this->get_field(MCHAN_STATUS_STATUS_TID_TR_BIT, MCHAN_STATUS_STATUS_TID_TR_WIDTH); } + inline void tid_alloc_set(uint16_t value) { this->set_field(value, MCHAN_STATUS_STATUS_TID_ALLOC_BIT, MCHAN_STATUS_STATUS_TID_ALLOC_WIDTH); } + inline uint16_t tid_alloc_get() { return this->get_field(MCHAN_STATUS_STATUS_TID_ALLOC_BIT, MCHAN_STATUS_STATUS_TID_ALLOC_WIDTH); } +}; + +class vp_mchan_status_free_tid : public vp::reg_16 +{ +public: + inline void tid_free_set(uint16_t value) { this->set_field(value, MCHAN_STATUS_FREE_TID_TID_FREE_BIT, MCHAN_STATUS_FREE_TID_TID_FREE_WIDTH); } + inline uint16_t tid_free_get() { return this->get_field(MCHAN_STATUS_FREE_TID_TID_FREE_BIT, MCHAN_STATUS_FREE_TID_TID_FREE_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int cmd ; // Cluster DMA configuration register. + unsigned int status ; // Cluster DMA status register. + unsigned int cmd_cmd ; // Transfer length in bytes configuration bitfield. + unsigned int cmd_get_tid ; // Transfer identifier value bitfield. + unsigned int cmd_tcdm_addr ; // Transfer L1 base address configuration bitfield. + unsigned int cmd_ext_addr ; // Transfer L2 base address configuration bitfield. + unsigned int cmd_2d_ext_count; // EXT 2D transfer conut value configuration bitfield. + unsigned int cmd_2d_ext_stride; // EXT 2D transfer stride value configuration bitfield. + unsigned int cmd_2d_tcdm_count; // TCDM 2D transfer conut value configuration bitfield. + unsigned int cmd_2d_tcdm_stride; // TCDM 2D transfer stride value configuration bitfield. + unsigned int status_status ; // Transfer status bitfield: TID_TR[i]=1'b1 means that transfer with TID i is active. + unsigned int status_free_tid ; // Transfer canceller configuration bitfield. Writing a 1'b1 in TID_FREE[i] will free transfer with TID i. +} __attribute__((packed)) mchan_mchan_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t mchan_cmd_get(uint32_t base) { return ARCHI_READ(base, MCHAN_CMD_OFFSET); } +static inline void mchan_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MCHAN_CMD_OFFSET, value); } + +static inline uint32_t mchan_status_get(uint32_t base) { return ARCHI_READ(base, MCHAN_STATUS_OFFSET); } +static inline void mchan_status_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MCHAN_STATUS_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MCHAN_CMD_CMD_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_CMD_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_CMD_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_CMD(val) ((val) << 0) + +#define MCHAN_STATUS_STATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_STATUS_STATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_STATUS_STATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_STATUS_STATUS(val) ((val) << 0) + +#define MCHAN_CMD_CMD_LEN_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define MCHAN_CMD_CMD_LEN_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define MCHAN_CMD_CMD_LEN_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define MCHAN_CMD_CMD_LEN(val) ((val) << 0) + +#define MCHAN_CMD_CMD_TYPE_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define MCHAN_CMD_CMD_TYPE_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define MCHAN_CMD_CMD_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define MCHAN_CMD_CMD_TYPE(val) ((val) << 17) + +#define MCHAN_CMD_CMD_INC_GET(value) (ARCHI_BEXTRACTU((value),1,18)) +#define MCHAN_CMD_CMD_INC_GETS(value) (ARCHI_BEXTRACT((value),1,18)) +#define MCHAN_CMD_CMD_INC_SET(value,field) (ARCHI_BINSERT((value),(field),1,18)) +#define MCHAN_CMD_CMD_INC(val) ((val) << 18) + +#define MCHAN_CMD_CMD__2D_EXT_GET(value) (ARCHI_BEXTRACTU((value),1,19)) +#define MCHAN_CMD_CMD__2D_EXT_GETS(value) (ARCHI_BEXTRACT((value),1,19)) +#define MCHAN_CMD_CMD__2D_EXT_SET(value,field) (ARCHI_BINSERT((value),(field),1,19)) +#define MCHAN_CMD_CMD__2D_EXT(val) ((val) << 19) + +#define MCHAN_CMD_CMD_ELE_GET(value) (ARCHI_BEXTRACTU((value),1,20)) +#define MCHAN_CMD_CMD_ELE_GETS(value) (ARCHI_BEXTRACT((value),1,20)) +#define MCHAN_CMD_CMD_ELE_SET(value,field) (ARCHI_BINSERT((value),(field),1,20)) +#define MCHAN_CMD_CMD_ELE(val) ((val) << 20) + +#define MCHAN_CMD_CMD_ILE_GET(value) (ARCHI_BEXTRACTU((value),1,21)) +#define MCHAN_CMD_CMD_ILE_GETS(value) (ARCHI_BEXTRACT((value),1,21)) +#define MCHAN_CMD_CMD_ILE_SET(value,field) (ARCHI_BINSERT((value),(field),1,21)) +#define MCHAN_CMD_CMD_ILE(val) ((val) << 21) + +#define MCHAN_CMD_CMD_BLE_GET(value) (ARCHI_BEXTRACTU((value),1,22)) +#define MCHAN_CMD_CMD_BLE_GETS(value) (ARCHI_BEXTRACT((value),1,22)) +#define MCHAN_CMD_CMD_BLE_SET(value,field) (ARCHI_BINSERT((value),(field),1,22)) +#define MCHAN_CMD_CMD_BLE(val) ((val) << 22) + +#define MCHAN_CMD_CMD__2D_TCDM_GET(value) (ARCHI_BEXTRACTU((value),1,23)) +#define MCHAN_CMD_CMD__2D_TCDM_GETS(value) (ARCHI_BEXTRACT((value),1,23)) +#define MCHAN_CMD_CMD__2D_TCDM_SET(value,field) (ARCHI_BINSERT((value),(field),1,23)) +#define MCHAN_CMD_CMD__2D_TCDM(val) ((val) << 23) + +#define MCHAN_CMD_GET_TID_TID_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MCHAN_CMD_GET_TID_TID_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MCHAN_CMD_GET_TID_TID_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MCHAN_CMD_GET_TID_TID(val) ((val) << 0) + +#define MCHAN_CMD_TCDM_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_TCDM_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_TCDM_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_TCDM_ADDR_ADDR(val) ((val) << 0) + +#define MCHAN_CMD_EXT_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_EXT_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_EXT_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_EXT_ADDR_ADDR(val) ((val) << 0) + +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_2D_EXT_COUNT__2D_EXT_COUNT(val) ((val) << 0) + +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_2D_EXT_STRIDE__2D_EXT_STRIDE(val) ((val) << 0) + +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_2D_TCDM_COUNT__2D_TCDM_COUNT(val) ((val) << 0) + +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define MCHAN_CMD_2D_TCDM_STRIDE__2D_TCDM_STRIDE(val) ((val) << 0) + +#define MCHAN_STATUS_STATUS_TID_TR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define MCHAN_STATUS_STATUS_TID_TR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define MCHAN_STATUS_STATUS_TID_TR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define MCHAN_STATUS_STATUS_TID_TR(val) ((val) << 0) + +#define MCHAN_STATUS_STATUS_TID_ALLOC_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define MCHAN_STATUS_STATUS_TID_ALLOC_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define MCHAN_STATUS_STATUS_TID_ALLOC_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define MCHAN_STATUS_STATUS_TID_ALLOC(val) ((val) << 16) + +#define MCHAN_STATUS_FREE_TID_TID_FREE_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define MCHAN_STATUS_FREE_TID_TID_FREE_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define MCHAN_STATUS_FREE_TID_TID_FREE_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define MCHAN_STATUS_FREE_TID_TID_FREE(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/efuse/efuse_v1.h b/sw/pulp-sdk/archi/include/archi/efuse/efuse_v1.h new file mode 100644 index 0000000..98adf35 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/efuse/efuse_v1.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_EFUSE_EFUSE_V1_H__ +#define __ARCHI_EFUSE_EFUSE_V1_H__ + +#define EFUSE_CMD_OFFSET 0x000 +#define EFUSE_CFG_OFFSET 0x004 +#define EFUSE_REGS_OFFSET 0x200 + +#define EFUSE_CMD_READ 0x1 +#define EFUSE_CMD_WRITE 0x2 +#define EFUSE_CMD_SLEEP 0x4 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/eu/eu_v1.h b/sw/pulp-sdk/archi/include/archi/eu/eu_v1.h new file mode 100644 index 0000000..fad814c --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/eu/eu_v1.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_EU_EU_V1_H_ +#define __ARCHI_EU_EU_V1_H_ + +#define PULP_CKG_MAX_NB_BARRIERS 18 + +#define PULP_NB_GP_EVENTS 3 + // TODO this is wrong should be 1 !!! +#define PULP_FIRST_GP_EVENT 0 +#define PULP_HW_BAR_EVENT 0 + + +#define PULP_DEMUX_CORE_CLKGATE_OFFSET 0x0 +#define PULP_DEMUX_EV_BUFFER_CLEAR_OFFSET 0x4 + +#define PULP_BODYBIAS_SRAM0_OFFSET 0x0 +#define PULP_BODYBIAS_SRAM1_OFFSET 0x4 +#define PULP_BODYBIAS_SRAM2_OFFSET 0x8 +#define PULP_BODYBIAS_SRAM3_OFFSET 0xC +#define PULP_BODYBIAS_CORE0_OFFSET 0x10 +#define PULP_BODYBIAS_CORE1_OFFSET 0x14 +#define PULP_BODYBIAS_CORE2_OFFSET 0x18 +#define PULP_BODYBIAS_CORE3_OFFSET 0x1C + +#define PULP_CLKGATE_SRAM0_OFFSET 0x100 +#define PULP_CLKGATE_SRAM1_OFFSET 0x104 +#define PULP_CLKGATE_SRAM2_OFFSET 0x108 +#define PULP_CLKGATE_SRAM3_OFFSET 0x10C +#define PULP_CLKGATE_SCM_OFFSET 0x124 +#define PULP_CLKGATE_STATUS 0x170 + +#define PULP_CLKGATE_TRIGG_BARRIER 0x35c +#define PULP_CLKGATE_WAIT_BARRIER 0x36c +#define PULP_CLKGATE_SET_BARRIER 0x374 +#define PULP_CLKGATE_SET_BARRIER_SIZE (0x4*PULP_CKG_MAX_NB_BARRIERS) + + +#define PULP_EV_MASK_LOW 0x100 +#define PULP_EV_MASK_LOW_SIZE 0x040 + +#define PULP_EV_BUFFER_LOW 0x180 +#define PULP_EV_BUFFER_LOW_SIZE 0x040 + +#define PULP_CORE_CLKGATE 0x308 + +#define PULP_EVNT_GEN 0x30C + +#define PULP_EVNT_GEN_GP0 0x360 +#define PULP_EVNT_GEN_GP1 0x364 +#define PULP_EVNT_GEN_GP2 0x368 + + +#define PULP_DEMUX_IRQ_BUFFER_CLEAR_OFFSET 0x8 +#define PULP_IRQ_MASK_LOW_BASE 0X200 +#define PULP_IRQ_MASK_LOW_SIZE 0X040 +#define PULP_IRQ_MASK_HIGH_BASE 0X240 +#define PULP_IRQ_MASK_HIGH_SIZE 0X040 +#define PULP_IRQ_BUFFER_LOW_BASE 0X280 +#define PULP_IRQ_BUFFER_LOW_SIZE 0X040 +#define PULP_IRQ_BUFFER_HIGH_BASE 0X2C0 +#define PULP_IRQ_BUFFER_HIGH_SIZE 0X040 + +#define PULP_READ_IRQ_ID_BASE 0X31C +#define PULP_READ_IRQ_ID_SIZE 0X040 + + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/eu/eu_v3.h b/sw/pulp-sdk/archi/include/archi/eu/eu_v3.h new file mode 100644 index 0000000..f74983c --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/eu/eu_v3.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_EU_EU_V3_H__ +#define __ARCHI_EU_EU_V3_H__ + +/* + * Register memory map + */ + +// Global offsets +#define EU_CORES_AREA_OFFSET 0x0000 +#define EU_CORES_AREA_SIZE 0x0400 +#define EU_CORE_AREA_SIZE_LOG2 6 +#define EU_CORE_AREA_SIZE (1<>EU_CORE_AREA_SIZE_LOG2) +#define EU_ROM_AREA_OFFSET_GET(coreId) (EU_CORE_AREA_OFFSET_GET(coreId) + EU_ROM_AREA_OFFSET) +#define EU_BARRIER_AREA_OFFSET_GET(barrier) ((barrier)*EU_BARRIER_SIZE) +#define EU_BARRIER_AREA_BARRIERID_GET(offset) (((offset) & (EU_BARRIER_AREA_SIZE - 1)) >> EU_BARRIER_SIZE_LOG2) +#define EU_MUTEX_AREA_OFFSET_GET(mutex) ((mutex)*EU_MUTEX_AREA_SIZE) +#define EU_MUTEX_AREA_MUTEXID_GET(offset) (((offset) & (EU_MUTEX_AREA_SIZE - 1)) >> 2) +#define EU_DISPATCH_AREA_OFFSET_GET(dispatch) ((dispatch)*EU_DISPATCH_AREA_SIZE) +#define EU_DISPATCH_AREA_DISPATCHID_GET(dispatch) (((offset) & (EU_DISPATCH_AREA_SIZE - 1)) >> 3) + +// Core area +#define EU_CORE_TRIGG_SW_EVENT_OFFSET(event) (EU_CORE_TRIGG_SW_EVENT + ((event)*0x4)) +#define EU_CORE_TRIGG_SW_EVENT_WAIT_OFFSET(event) (EU_CORE_TRIGG_SW_EVENT_WAIT + ((event)*0x4)) +#define EU_CORE_TRIGG_SW_EVENT_WAIT_CLEAR_OFFSET(event) (EU_CORE_TRIGG_SW_EVENT_WAIT_CLEAR + ((event)*0x4)) + +// ROM area +#define EU_ROM_EVENT_SOURCE_OFFSET(event) (EU_ROM_EVENT_SOURCE + ((event)*0x4)) + +// TODO should be moved to chip part ? +#define PULP_NB_GP_EVENTS 8 +#define PULP_FIRST_GP_EVENT 0 +#define PULP_TIMER0_EVENT 10 +#define PULP_TIMER1_EVENT 11 + // TODO the real value is not yet specified +#define EVENT_HWCE 15 +#define PULP_HW_BAR_EVENT 16 +#define PULP_MUTEX_EVENT 17 +#define PULP_DISPATCH_EVENT 18 +#define PULP_LOOP_EVENT 19 +#if PULP_CHIP_FAMILY == CHIP_GAP +#define PULP_FC_SOC_EVENTS_EVENT 27 +#else +#define PULP_FC_SOC_EVENTS_EVENT 26 +#endif +#define PULP_SOC_EVENTS_EVENT 27 +#define PULP_SOC_TRIGGER_EVENT 28 +#define PULP_SOC_LOCK_EVENT 29 +#define PULP_SOC_HW_BAR_EVENT 30 + +// SOC areas +#define EU_SOC_BARRIER_AREA_OFFSET_GET(barrier) ((barrier)*EU_SOC_BARRIER_SIZE) +#define EU_SOC_BARRIER_AREA_BARRIERID_GET(offset) (((offset) & (EU_SOC_BARRIER_AREA_SIZE - 1)) >> EU_SOC_BARRIER_SIZE_LOG2) + +#define EU_SOC_LOCK_AREA_OFFSET_GET(lock) ((lock)*EU_SOC_LOCK_SIZE) +#define EU_SOC_LOCK_AREA_LOCKID_GET(offset) (((offset) & (EU_SOC_LOCK_AREA_SIZE - 1)) >> EU_SOC_LOCK_SIZE_LOG2) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/fll/fll_v0.h b/sw/pulp-sdk/archi/include/archi/fll/fll_v0.h new file mode 100644 index 0000000..65aa27b --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/fll/fll_v0.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_FLL_FLL_V0_H__ +#define __ARCHI_FLL_FLL_V0_H__ + +#define SOC_FLL_CONFIG_REG_1 ( ARCHI_FLL_ADDR + 0x04 ) +#define SOC_FLL_CONFIG_REG_2 ( ARCHI_FLL_ADDR + 0x08 ) +#define SOC_FLL_CONFIG_REG_3 ( ARCHI_FLL_ADDR + 0x0C ) +#define SOC_FLL_LOCK_REG ( ARCHI_FLL_ADDR + 0x20 ) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/fll/fll_v1.h b/sw/pulp-sdk/archi/include/archi/fll/fll_v1.h new file mode 100644 index 0000000..e371ae3 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/fll/fll_v1.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_FLL_FLL_V1_H__ +#define __ARCHI_FLL_FLL_V1_H__ + + +#define FLL_STATUS_OFFSET 0x000 +#define FLL_CONF1_OFFSET 0x004 +#define FLL_CONF2_OFFSET 0x008 +#define FLL_INTEGRATOR_OFFSET 0x00C + + +#define FLL_STATUS_MULT_FACTOR_BIT 0 +#define FLL_STATUS_MULT_FACTOR_WIDTH 16 +#define FLL_STATUS_MULT_FACTOR_MASK (0xFFFF) + + + +#define FLL_CONF1_MODE_BIT 31 +#define FLL_CONF1_MODE_WIDTH 1 +#define FLL_CONF1_MODE_MASK (0x80000000) + +#define FLL_CONF1_LOCK_BIT 30 +#define FLL_CONF1_LOCK_WIDTH 1 +#define FLL_CONF1_LOCK_MASK (0x40000000) + +#define FLL_CONF1_DIV_BIT 26 +#define FLL_CONF1_DIV_WIDTH 4 +#define FLL_CONF1_DIV_MASK (0x3C000000) + +#define FLL_CONF1_DCO_BIT 16 +#define FLL_CONF1_DCO_WIDTH 10 +#define FLL_CONF1_DCO_MASK (0x03FF0000) + +#define FLL_CONF1_MULT_FACTOR_BIT 0 +#define FLL_CONF1_MULT_FACTOR_WIDTH 16 +#define FLL_CONF1_MULT_FACTOR_MASK (0xFFFF) + +#define FLL_CONF1_MODE_STANDALONE 0 +#define FLL_CONF1_MODE_NORMAL 1 + + + +#define FLL_CONF2_GAIN_BIT 0 +#define FLL_CONF2_GAIN_WIDTH 4 +#define FLL_CONF2_GAIN_MASK (0x0000000F) + +#define FLL_CONF2_DEASSERT_CYCLES_BIT 4 +#define FLL_CONF2_DEASSERT_CYCLES_WIDTH 6 +#define FLL_CONF2_DEASSERT_CYCLES_MASK (0x000003F0) + +#define FLL_CONF2_ASSERT_CYCLES_BIT 10 +#define FLL_CONF2_ASSERT_CYCLES_WIDTH 6 +#define FLL_CONF2_ASSERT_CYCLES_MASK (0x0000FC00) + +#define FLL_CONF2_TOLERANCE_BIT 16 +#define FLL_CONF2_TOLERANCE_WIDTH 12 +#define FLL_CONF2_TOLERANCE_MASK (0x0FFF0000) + +#define FLL_CONF2_STA_CLOCK_BIT 29 +#define FLL_CONF2_STA_CLOCK_WIDTH 1 +#define FLL_CONF2_STA_CLOCK_MASK (0x20000000) + +#define FLL_CONF2_OPEN_LOOP_BIT 30 +#define FLL_CONF2_OPEN_LOOP_WIDTH 1 +#define FLL_CONF2_OPEN_LOOP_MASK (0x40000000) + +#define FLL_CONF2_DITHERING_BIT 31 +#define FLL_CONF2_DITHERING_WIDTH 1 +#define FLL_CONF2_DITHERING_MASK (0x80000000) + + + +#define FLL_INTEGRATOR_INT_BIT 16 +#define FLL_INTEGRATOR_INT_WIDTH 10 +#define FLL_INTEGRATOR_INT_MASK (0x03FF0000) + +#define FLL_INTEGRATOR_FRACT_BIT 6 +#define FLL_INTEGRATOR_FRACT_WIDTH 10 +#define FLL_INTEGRATOR_FRACT_MASK (0x0000FFC0) + + + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(_ASMLANGUAGE) + +typedef union { + struct { + unsigned int actual_mult_factor:16; /* Fll current multiplication factor */ + unsigned int reserved:16; + }; + unsigned int raw; +} fll_reg_status_t; + +typedef union { + struct { + unsigned int mult_factor:16; /* Fll requested multiplication factor, reset: 0x5f5. + If RefClk=32768 and Div=2 Freq= 24.98 MHz */ + unsigned int dco_input:10; /* DCO input code for stand alone mode, reset: 0x121 */ + unsigned int clock_out_divider:4; /* Fll clock output divider, reset: 0x1 e.g div 2 */ + unsigned int output_lock_enable:1;/* Fll output gated by lock signal (active high), reset 1 */ + unsigned int mode:1; /* Fll mode. 0: stand alone (unlocked), 1: normal, reset 0 */ + }; + unsigned int raw; +} fll_reg_conf1_t; + +typedef union { + struct { + unsigned int loop_gain:4; /* Fll loop gain, reset: 0x9 */ + unsigned int de_assert_cycles:6; /* Normal mode: number of refclock unstable cycles till lock de-assert + Standalone mode: lower 6 bits of lock assert counter. Reset: 0x10 */ + unsigned int assert_cycles:6; /* Normal mode: number of refclock stable cycles till lock assert + Standalone mode: upper 6 bits of lock assert counter. Reset: 0x10 */ + unsigned int lock_tolerance:12; /* Lock tolerance: margin arounf the target mult factor where clock is + considered as stable. Reset: 0x200 + With Fmax=250Mhw (Div=2^4), Fmin=32K (Div=2^15) + Tolerance: 32K*(512/16)=1.048MHz .. 512 Hz */ + unsigned int pad:1; + unsigned int config_clock_sel:1; /* Select ref clock when mode = standalone, 0:RefClock, 1: DcoOut. Reset:1 */ + unsigned int open_loop:1; /* When 1 clock operates in open loop when locked */ + unsigned int dithering:1; /* When 1 Dithering is enabled */ + }; + unsigned int raw; +} fll_reg_conf2_t; + +typedef union { + struct { + unsigned int pad1:6; + unsigned int state_fract_part:10; /* Integrator state: fractional part (dithering input unit) */ + unsigned int state_int_part:10; /* Integratot state: integer part (DCO input bits) */ + unsigned int pad2:6; + }; + unsigned int raw; +} fll_reg_integrator_t; + +#endif + + + +#define FLL_STATUS_MULT_FACTOR_GET(value) ((((unsigned int)(value)) >> 0) & 0xFFFF) +#define FLL_STATUS_MULT_FACTOR_SET(dst,src,factor) (__BITINSERT((dst),(src),16,0)) +#define FLL_STATUS_MULT_FACTOR(factor) ((factor) << 16) + + +#define FLL_CONF1_MODE_GET(value) ((((unsigned int)(value)) >> 16) & 0x1) +#define FLL_CONF1_MODE_SET(dst,src) (__BITINSERT((dst),(src),1,31)) +#define FLL_CONF1_MODE(factor) ((factor) << 31) + +#define FLL_CONF1_LOCK_GET(value) ((((unsigned int)(value)) >> 16) & 0x1) +#define FLL_CONF1_LOCK_SET(dst,src) (__BITINSERT((dst),(src),30,1)) +#define FLL_CONF1_LOCK(factor) ((factor) << 30) + +#define FLL_CONF1_DIV_GET(value) ((((unsigned int)(value)) >> 26) & 0xF) +#define FLL_CONF1_DIV_SET(dst,src) (__BITINSERT((dst),(src),26,4)) +#define FLL_CONF1_DIV(factor) ((factor) << 26) + +#define FLL_CONF1_DCO_GET(value) ((((unsigned int)(value)) >> 16) & 0x3FF) +#define FLL_CONF1_DCO_SET(dst,src) (__BITINSERT((dst),(src),16,10)) +#define FLL_CONF1_DCO(factor) ((factor) << 16) + +#define FLL_CONF1_MULT_FACTOR_GET(value) ((((unsigned int)(value)) >> 0) &0xFFFF) +#define FLL_CONF1_MULT_FACTOR_SET(dst,src) (__BITINSERT((dst),(src),0,16)) +#define FLL_CONF1_MULT_FACTOR(factor) ((factor) << 0) + + + +#define FLL_CONF2_GAIN_GET(value) ((((unsigned int)(value)) >> 0) & 0xF) +#define FLL_CONF2_GAIN_SET(dst,src) (__BITINSERT((dst),(src),4,0)) +#define FLL_CONF2_GAIN(value) ((value) << 0) + +#define FLL_CONF2_ASSERT_CYCLES_GET(value) ((((unsigned int)(value)) >> 4) & 0x3F) +#define FLL_CONF2_ASSERT_CYCLES_SET(dst,src) (__BITINSERT((dst),(src),6,4)) +#define FLL_CONF2_ASSERT_CYCLES(value) ((value) << 4) + +#define FLL_CONF2_DEASSERT_CYCLES_GET(value) ((((unsigned int)(value)) >> 10) & 0x3F) +#define FLL_CONF2_DEASSERT_CYCLES_SET(dst,src) (__BITINSERT((dst),(src),6,10)) +#define FLL_CONF2_DEASSERT_CYCLES(value) ((value) << 10) + +#define FLL_CONF2_TOLERANCE_GET(value) ((((unsigned int)(value)) >> 16) & 0xFFF) +#define FLL_CONF2_TOLERANCE_SET(dst,src) (__BITINSERT((dst),(src),12,16)) +#define FLL_CONF2_TOLERANCE(value) ((value) << 16) + +#define FLL_CONF2_STA_CLOCK_GET(value) ((((unsigned int)(value)) >> 29) & 0x1) +#define FLL_CONF2_STA_CLOCK_SET(dst,src) (__BITINSERT((dst),(src),1,29)) +#define FLL_CONF2_STA_CLOCK(value) ((value) << 29) + +#define FLL_CONF2_OPEN_LOOP_GET(value) ((((unsigned int)(value)) >> 30) & 0x1) +#define FLL_CONF2_OPEN_LOOP_SET(dst,src) (__BITINSERT((dst),(src),1,30)) +#define FLL_CONF2_OPEN_LOOP(value) ((value) << 30) + +#define FLL_CONF2_DITHER_GET(value) ((((unsigned int)(value)) >> 31) & 0x1) +#define FLL_CONF2_DITHER_SET(dst,src) (__BITINSERT((dst),(src),1,31)) +#define FLL_CONF2_DITHER(value) ((value) << 31) + + + +#define FLL_INTEGRATOR_FRACT_GET(value) ((((unsigned int)(value)) >> 6) & 0x3FF) +#define FLL_INTEGRATOR_FRACT_SET(dst,src) (__BITINSERT((dst),(src),6,10)) +#define FLL_INTEGRATOR_FRACT(value) ((value) << 6) + +#define FLL_INTEGRATOR_INT_GET(value) ((((unsigned int)(value)) >> 16) & 0x3FF) +#define FLL_INTEGRATOR_INT_SET(dst,src) (__BITINSERT((dst),(src),16,10)) +#define FLL_INTEGRATOR_INT(value) ((value) << 16) + + + + + + +/* Maximum Log2(DCO Frequency) */ +#define FLL_LOG2_MAXDCO 29 +/* Maximum Log2(Clok Divider) */ +#define FLL_LOG2_MAXDIV 15 +/* Maximum Log2(Multiplier) */ +#define FLL_LOG2_MAXM (FLL_LOG2_MAXDCO - ARCHI_REF_CLOCK_LOG2) + + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2.h b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2.h new file mode 100644 index 0000000..479846d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_GPIO_GPIO_V2_H__ +#define __ARCHI_GPIO_GPIO_V2_H__ + +#include "archi/gpio/gpio_v2_new.h" + +#define ARCHI_GPIO_PADDIR 0x0 // Direction i:0..31, GPIOi => Bit[i] = 1 Output, Bit[i] = 0 Input (Default) +#define ARCHI_GPIO_PADIN 0x4 // i:0..31, Bit[i] Received bit from GPIOi +#define ARCHI_GPIO_PADOUT 0x8 // i:0..31, Bit[i] Bit to transmit through GPIOi +#define ARCHI_GPIO_INTEN 0xC // i:0..31, Bit[i]=1 Enable Event for GPIOi +#define ARCHI_GPIO_INTTYPE0 0x10 // Interrupt Condition i:0..15, Bit[2*i:2*i+1] = 00 Falling edge on GPIOi + // = 01 Raising edge on GPIOi + // = 11 Raising then falling edge on GPIOi +#define ARCHI_GPIO_INTTYPE1 0x14 // Interrupt Condition i:0..15, Bit[2*i:2*i+1] = 00 Falling edge on GPIOi+16 + // = 01 Raising edge on GPIOi+16 + // = 11 Raising the falling edge on GPIOi+16 +#define ARCHI_GPIO_INTSTATUS 0x18 // Interrupt Status i:0..31, Bit[i]=1 Event received for GPIOi, bit is cleared when readen +#define GPIO_INTSTATUS_OFFSET ARCHI_GPIO_INTSTATUS +#define ARCHI_GPIO_EN 0x1C + +#define ARCHI_GPIO_PADCFG0 0x20 +#define ARCHI_GPIO_PADCFG1 0x24 +#define ARCHI_GPIO_PADCFG2 0x28 +#define ARCHI_GPIO_PADCFG3 0x2C +#define ARCHI_GPIO_PADCFG4 0x30 +#define ARCHI_GPIO_PADCFG5 0x34 +#define ARCHI_GPIO_PADCFG6 0x38 +#define ARCHI_GPIO_PADCFG7 0x3C + + +#define ARCHI_GPIO_PADDIR_IN 0 +#define ARCHI_GPIO_PADDIR_OUT 1 + +#define ARCHI_GPIO_INTTYPE_RISE 1 +#define ARCHI_GPIO_INTTYPE_FALL 0 +#define ARCHI_GPIO_INTTYPE_RISE_AND_FALL 2 + +#define ARCHI_GPIO_INTTYPE(id) (ARCHI_GPIO_INTTYPE0 + (id)*4) +#define ARCHI_GPIO_INTTYPE_NO(gpio) ((gpio) >> 4) +#define ARCHI_GPIO_INTTYPE_GPIO(inttype) ((inttype)*16) +#define ARCHI_GPIO_INTTYPE_SIZE 2 +#define ARCHI_GPIO_INTTYPE_BIT(pad) (((pad) & 0xF) << 1) +#define ARCHI_GPIO_INTTYPE_GET(gpio,value) (((value) >> ARCHI_GPIO_INTTYPE_BIT(gpio)) & ((1<> 2) +#define ARCHI_GPIO_PADCFG_GROUP(gpio) ((gpio) & ((1<<2)-1)) + + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + int pull:1; + int strength:1; + int reserved:6; +} __attribute__((packed)) gpio_padcfg_group_t; + +typedef union { + gpio_padcfg_group_t pin[4]; + uint32_t raw; +} __attribute__((packed)) gpio_reg_padcfg_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2_new.h b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2_new.h new file mode 100644 index 0000000..615d3f0 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v2_new.h @@ -0,0 +1,1346 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_GPIO_GPIO_V2_NEW_H__ +#define __INCLUDE_ARCHI_GPIO_GPIO_V2_NEW_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// GPIO pad direction configuration +#define GPIO_APBGPIO_PADDIR_OFFSET 0x0 + +// GPIO pad input value +#define GPIO_APBGPIO_PADIN_OFFSET 0x4 + +// GPIO pad output value +#define GPIO_APBGPIO_PADOUT_OFFSET 0x8 + +// GPIO pad interrupt enable configuration +#define GPIO_APBGPIO_INTEN_OFFSET 0xc + +// GPIO pad interrupt type bit 0 configuration +#define GPIO_APBGPIO_INTTYPE0_OFFSET 0x10 + +// GPIO pad interrupt type bit 1 configuration +#define GPIO_APBGPIO_INTTYPE1_OFFSET 0x14 + +// GPIO pad interrupt status +#define GPIO_APBGPIO_INTSTATUS_OFFSET 0x18 + +// GPIO pad enable configuration +#define GPIO_APBGPIO_GPIOEN_OFFSET 0x1c + +// GPIO pad pin 0 to 3 configuration +#define GPIO_APBGPIO_PADCFG0_OFFSET 0x20 + +// GPIO pad pin 4 to 7 configuration +#define GPIO_APBGPIO_PADCFG1_OFFSET 0x24 + +// GPIO pad pin 8 to 11 configuration +#define GPIO_APBGPIO_PADCFG2_OFFSET 0x28 + +// GPIO pad pin 12 to 15 configuration +#define GPIO_APBGPIO_PADCFG3_OFFSET 0x2c + +// GPIO pad pin 16 to 19 configuration +#define GPIO_APBGPIO_PADCFG4_OFFSET 0x30 + +// GPIO pad pin 20 to 23 configuration +#define GPIO_APBGPIO_PADCFG5_OFFSET 0x34 + +// GPIO pad pin 24 to 27 configuration +#define GPIO_APBGPIO_PADCFG6_OFFSET 0x38 + +// GPIO pad pin 28 to 31 configuration +#define GPIO_APBGPIO_PADCFG7_OFFSET 0x3c + + + +// +// REGISTERS FIELDS +// + +// Configure direction of the 32 GPIOs: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] (access: R/W) +#define GPIO_APBGPIO_PADDIR_DIR_BIT 0 +#define GPIO_APBGPIO_PADDIR_DIR_WIDTH 32 +#define GPIO_APBGPIO_PADDIR_DIR_MASK 0xffffffff + +// Read value of the 32 GPIOs. (access: R) +#define GPIO_APBGPIO_PADIN_DATA_IN_BIT 0 +#define GPIO_APBGPIO_PADIN_DATA_IN_WIDTH 32 +#define GPIO_APBGPIO_PADIN_DATA_IN_MASK 0xffffffff + +// Write value to the 32 GPIOs. (access: R/W) +#define GPIO_APBGPIO_PADOUT_DATA_OUT_BIT 0 +#define GPIO_APBGPIO_PADOUT_DATA_OUT_WIDTH 32 +#define GPIO_APBGPIO_PADOUT_DATA_OUT_MASK 0xffffffff + +// Configure interrupt mode for the 32 GPIOs: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] (access: R/W) +#define GPIO_APBGPIO_INTEN_INTEN_BIT 0 +#define GPIO_APBGPIO_INTEN_INTEN_WIDTH 32 +#define GPIO_APBGPIO_INTEN_INTEN_MASK 0xffffffff + +// Configure interrupt condition for the GPIO[15:0]: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_BIT 0 +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_WIDTH 32 +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_MASK 0xffffffff + +// Configure interrupt condition for the GPIO[31:16]: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_BIT 0 +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_WIDTH 32 +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_MASK 0xffffffff + +// Interrupt status flags for the 32 GPIOs. - bit[i]=1 when interrupt received on GPIO[i] Register is cleared when read. GPIO interrupt line is also cleared when this register is red. (access: R) +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_BIT 0 +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_WIDTH 32 +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_MASK 0xffffffff + +// Configure clock enable for the 32 GPIOs: - bit[i]=1'b0: disable mode for GPIO[i] - bit[i]=1'b1: enable mode for GPIO[i] GPIOs are gathered by groups of 4. The clock-gating of one group is done only if all 4 GPIOs are disabled. (access: R/W) +#define GPIO_APBGPIO_GPIOEN_GPIOEN_BIT 0 +#define GPIO_APBGPIO_GPIOEN_GPIOEN_WIDTH 32 +#define GPIO_APBGPIO_GPIOEN_GPIOEN_MASK 0xffffffff + +// Configure pull activation for GPIO[0]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_MASK 0x1 + +// Configure drive strength for GPIO[0]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_MASK 0x2 + +// Configure pull activation for GPIO[1]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_MASK 0x100 + +// Configure drive strength for GPIO[1]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_MASK 0x200 + +// Configure pull activation for GPIO[2]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_MASK 0x10000 + +// Configure drive strength for GPIO[2]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_MASK 0x20000 + +// Configure pull activation for GPIO[3]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[3]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[4]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_MASK 0x1 + +// Configure drive strength for GPIO[4]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_MASK 0x2 + +// Configure pull activation for GPIO[5]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_MASK 0x100 + +// Configure drive strength for GPIO[5]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_MASK 0x200 + +// Configure pull activation for GPIO[6]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_MASK 0x10000 + +// Configure drive strength for GPIO[6]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_MASK 0x20000 + +// Configure pull activation for GPIO[7]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[7]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[8]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_MASK 0x1 + +// Configure drive strength for GPIO[8]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_MASK 0x2 + +// Configure pull activation for GPIO[9]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_MASK 0x100 + +// Configure drive strength for GPIO[9]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_MASK 0x200 + +// Configure pull activation for GPIO[10]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_MASK 0x10000 + +// Configure drive strength for GPIO[10]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_MASK 0x20000 + +// Configure pull activation for GPIO[11]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[11]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[12]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_MASK 0x1 + +// Configure drive strength for GPIO[12]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_MASK 0x2 + +// Configure pull activation for GPIO[13]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_MASK 0x100 + +// Configure drive strength for GPIO[13]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_MASK 0x200 + +// Configure pull activation for GPIO[14]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_MASK 0x10000 + +// Configure drive strength for GPIO[14]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_MASK 0x20000 + +// Configure pull activation for GPIO[15]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[15]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[16]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_MASK 0x1 + +// Configure drive strength for GPIO[16]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_MASK 0x2 + +// Configure pull activation for GPIO[17]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_MASK 0x100 + +// Configure drive strength for GPIO[17]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_MASK 0x200 + +// Configure pull activation for GPIO[18]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_MASK 0x10000 + +// Configure drive strength for GPIO[18]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_MASK 0x20000 + +// Configure pull activation for GPIO[19]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[19]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[20]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_MASK 0x1 + +// Configure drive strength for GPIO[20]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_MASK 0x2 + +// Configure pull activation for GPIO[21]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_MASK 0x100 + +// Configure drive strength for GPIO[21]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_MASK 0x200 + +// Configure pull activation for GPIO[22]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_MASK 0x10000 + +// Configure drive strength for GPIO[22]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_MASK 0x20000 + +// Configure pull activation for GPIO[23]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[23]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[24]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_MASK 0x1 + +// Configure drive strength for GPIO[24]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_MASK 0x2 + +// Configure pull activation for GPIO[25]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_MASK 0x100 + +// Configure drive strength for GPIO[25]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_MASK 0x200 + +// Configure pull activation for GPIO[26]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_MASK 0x10000 + +// Configure drive strength for GPIO[26]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_MASK 0x20000 + +// Configure pull activation for GPIO[27]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[27]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_MASK 0x2000000 + +// Configure pull activation for GPIO[28]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_BIT 0 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_MASK 0x1 + +// Configure drive strength for GPIO[28]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_BIT 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_MASK 0x2 + +// Configure pull activation for GPIO[29]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_BIT 8 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_MASK 0x100 + +// Configure drive strength for GPIO[29]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_BIT 9 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_MASK 0x200 + +// Configure pull activation for GPIO[30]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_BIT 16 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_MASK 0x10000 + +// Configure drive strength for GPIO[30]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_BIT 17 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_MASK 0x20000 + +// Configure pull activation for GPIO[31]: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_BIT 24 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_MASK 0x1000000 + +// Configure drive strength for GPIO[31]: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_BIT 25 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_WIDTH 1 +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_MASK 0x2000000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int dir :32; // Configure direction of the 32 GPIOs: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_paddir_t; + +typedef union { + struct { + unsigned int data_in :32; // Read value of the 32 GPIOs. + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padin_t; + +typedef union { + struct { + unsigned int data_out :32; // Write value to the 32 GPIOs. + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padout_t; + +typedef union { + struct { + unsigned int inten :32; // Configure interrupt mode for the 32 GPIOs: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_inten_t; + +typedef union { + struct { + unsigned int inttype0 :32; // Configure interrupt condition for the GPIO[15:0]: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_inttype0_t; + +typedef union { + struct { + unsigned int inttype1 :32; // Configure interrupt condition for the GPIO[31:16]: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_inttype1_t; + +typedef union { + struct { + unsigned int intstatus :32; // Interrupt status flags for the 32 GPIOs. - bit[i]=1 when interrupt received on GPIO[i] Register is cleared when read. GPIO interrupt line is also cleared when this register is red. + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_intstatus_t; + +typedef union { + struct { + unsigned int gpioen :32; // Configure clock enable for the 32 GPIOs: - bit[i]=1'b0: disable mode for GPIO[i] - bit[i]=1'b1: enable mode for GPIO[i] GPIOs are gathered by groups of 4. The clock-gating of one group is done only if all 4 GPIOs are disabled. + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_gpioen_t; + +typedef union { + struct { + unsigned int padcfg0_gpio0_pe:1 ; // Configure pull activation for GPIO[0]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg0_gpio0_ds:1 ; // Configure drive strength for GPIO[0]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg0_gpio1_pe:1 ; // Configure pull activation for GPIO[1]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg0_gpio1_ds:1 ; // Configure drive strength for GPIO[1]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg0_gpio2_pe:1 ; // Configure pull activation for GPIO[2]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg0_gpio2_ds:1 ; // Configure drive strength for GPIO[2]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg0_gpio3_pe:1 ; // Configure pull activation for GPIO[3]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg0_gpio3_ds:1 ; // Configure drive strength for GPIO[3]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg0_t; + +typedef union { + struct { + unsigned int padcfg1_gpio4_pe:1 ; // Configure pull activation for GPIO[4]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg1_gpio4_ds:1 ; // Configure drive strength for GPIO[4]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg1_gpio5_pe:1 ; // Configure pull activation for GPIO[5]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg1_gpio5_ds:1 ; // Configure drive strength for GPIO[5]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg1_gpio6_pe:1 ; // Configure pull activation for GPIO[6]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg1_gpio6_ds:1 ; // Configure drive strength for GPIO[6]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg1_gpio7_pe:1 ; // Configure pull activation for GPIO[7]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg1_gpio7_ds:1 ; // Configure drive strength for GPIO[7]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg1_t; + +typedef union { + struct { + unsigned int padcfg2_gpio8_pe:1 ; // Configure pull activation for GPIO[8]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg2_gpio8_ds:1 ; // Configure drive strength for GPIO[8]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg2_gpio9_pe:1 ; // Configure pull activation for GPIO[9]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg2_gpio9_ds:1 ; // Configure drive strength for GPIO[9]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg2_gpio10_pe:1 ; // Configure pull activation for GPIO[10]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg2_gpio10_ds:1 ; // Configure drive strength for GPIO[10]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg2_gpio11_pe:1 ; // Configure pull activation for GPIO[11]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg2_gpio11_ds:1 ; // Configure drive strength for GPIO[11]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg2_t; + +typedef union { + struct { + unsigned int padcfg3_gpio12_pe:1 ; // Configure pull activation for GPIO[12]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg3_gpio12_ds:1 ; // Configure drive strength for GPIO[12]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg3_gpio13_pe:1 ; // Configure pull activation for GPIO[13]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg3_gpio13_ds:1 ; // Configure drive strength for GPIO[13]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg3_gpio14_pe:1 ; // Configure pull activation for GPIO[14]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg3_gpio14_ds:1 ; // Configure drive strength for GPIO[14]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg3_gpio15_pe:1 ; // Configure pull activation for GPIO[15]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg3_gpio15_ds:1 ; // Configure drive strength for GPIO[15]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg3_t; + +typedef union { + struct { + unsigned int padcfg4_gpio16_pe:1 ; // Configure pull activation for GPIO[16]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg4_gpio16_ds:1 ; // Configure drive strength for GPIO[16]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg4_gpio17_pe:1 ; // Configure pull activation for GPIO[17]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg4_gpio17_ds:1 ; // Configure drive strength for GPIO[17]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg4_gpio18_pe:1 ; // Configure pull activation for GPIO[18]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg4_gpio18_ds:1 ; // Configure drive strength for GPIO[18]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg4_gpio19_pe:1 ; // Configure pull activation for GPIO[19]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg4_gpio19_ds:1 ; // Configure drive strength for GPIO[19]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg4_t; + +typedef union { + struct { + unsigned int padcfg5_gpio20_pe:1 ; // Configure pull activation for GPIO[20]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg5_gpio20_ds:1 ; // Configure drive strength for GPIO[20]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg5_gpio21_pe:1 ; // Configure pull activation for GPIO[21]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg5_gpio21_ds:1 ; // Configure drive strength for GPIO[21]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg5_gpio22_pe:1 ; // Configure pull activation for GPIO[22]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg5_gpio22_ds:1 ; // Configure drive strength for GPIO[22]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg5_gpio23_pe:1 ; // Configure pull activation for GPIO[23]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg5_gpio23_ds:1 ; // Configure drive strength for GPIO[23]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg5_t; + +typedef union { + struct { + unsigned int padcfg6_gpio24_pe:1 ; // Configure pull activation for GPIO[24]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg6_gpio24_ds:1 ; // Configure drive strength for GPIO[24]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg6_gpio25_pe:1 ; // Configure pull activation for GPIO[25]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg6_gpio25_ds:1 ; // Configure drive strength for GPIO[25]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg6_gpio26_pe:1 ; // Configure pull activation for GPIO[26]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg6_gpio26_ds:1 ; // Configure drive strength for GPIO[26]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg6_gpio27_pe:1 ; // Configure pull activation for GPIO[27]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg6_gpio27_ds:1 ; // Configure drive strength for GPIO[27]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg6_t; + +typedef union { + struct { + unsigned int padcfg7_gpio28_pe:1 ; // Configure pull activation for GPIO[28]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg7_gpio28_ds:1 ; // Configure drive strength for GPIO[28]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding0:6 ; + unsigned int padcfg7_gpio29_pe:1 ; // Configure pull activation for GPIO[29]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg7_gpio29_ds:1 ; // Configure drive strength for GPIO[29]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding1:6 ; + unsigned int padcfg7_gpio30_pe:1 ; // Configure pull activation for GPIO[30]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg7_gpio30_ds:1 ; // Configure drive strength for GPIO[30]: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int padding2:6 ; + unsigned int padcfg7_gpio31_pe:1 ; // Configure pull activation for GPIO[31]: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int padcfg7_gpio31_ds:1 ; // Configure drive strength for GPIO[31]: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_apbgpio_padcfg7_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_gpio_apbgpio_paddir : public vp::reg_32 +{ +public: + inline void dir_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADDIR_DIR_BIT, GPIO_APBGPIO_PADDIR_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(GPIO_APBGPIO_PADDIR_DIR_BIT, GPIO_APBGPIO_PADDIR_DIR_WIDTH); } +}; + +class vp_gpio_apbgpio_padin : public vp::reg_32 +{ +public: + inline void data_in_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADIN_DATA_IN_BIT, GPIO_APBGPIO_PADIN_DATA_IN_WIDTH); } + inline uint32_t data_in_get() { return this->get_field(GPIO_APBGPIO_PADIN_DATA_IN_BIT, GPIO_APBGPIO_PADIN_DATA_IN_WIDTH); } +}; + +class vp_gpio_apbgpio_padout : public vp::reg_32 +{ +public: + inline void data_out_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADOUT_DATA_OUT_BIT, GPIO_APBGPIO_PADOUT_DATA_OUT_WIDTH); } + inline uint32_t data_out_get() { return this->get_field(GPIO_APBGPIO_PADOUT_DATA_OUT_BIT, GPIO_APBGPIO_PADOUT_DATA_OUT_WIDTH); } +}; + +class vp_gpio_apbgpio_inten : public vp::reg_32 +{ +public: + inline void inten_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_INTEN_INTEN_BIT, GPIO_APBGPIO_INTEN_INTEN_WIDTH); } + inline uint32_t inten_get() { return this->get_field(GPIO_APBGPIO_INTEN_INTEN_BIT, GPIO_APBGPIO_INTEN_INTEN_WIDTH); } +}; + +class vp_gpio_apbgpio_inttype0 : public vp::reg_32 +{ +public: + inline void inttype0_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_INTTYPE0_INTTYPE0_BIT, GPIO_APBGPIO_INTTYPE0_INTTYPE0_WIDTH); } + inline uint32_t inttype0_get() { return this->get_field(GPIO_APBGPIO_INTTYPE0_INTTYPE0_BIT, GPIO_APBGPIO_INTTYPE0_INTTYPE0_WIDTH); } +}; + +class vp_gpio_apbgpio_inttype1 : public vp::reg_32 +{ +public: + inline void inttype1_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_INTTYPE1_INTTYPE1_BIT, GPIO_APBGPIO_INTTYPE1_INTTYPE1_WIDTH); } + inline uint32_t inttype1_get() { return this->get_field(GPIO_APBGPIO_INTTYPE1_INTTYPE1_BIT, GPIO_APBGPIO_INTTYPE1_INTTYPE1_WIDTH); } +}; + +class vp_gpio_apbgpio_intstatus : public vp::reg_32 +{ +public: + inline void intstatus_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_INTSTATUS_INTSTATUS_BIT, GPIO_APBGPIO_INTSTATUS_INTSTATUS_WIDTH); } + inline uint32_t intstatus_get() { return this->get_field(GPIO_APBGPIO_INTSTATUS_INTSTATUS_BIT, GPIO_APBGPIO_INTSTATUS_INTSTATUS_WIDTH); } +}; + +class vp_gpio_apbgpio_gpioen : public vp::reg_32 +{ +public: + inline void gpioen_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_GPIOEN_GPIOEN_BIT, GPIO_APBGPIO_GPIOEN_GPIOEN_WIDTH); } + inline uint32_t gpioen_get() { return this->get_field(GPIO_APBGPIO_GPIOEN_GPIOEN_BIT, GPIO_APBGPIO_GPIOEN_GPIOEN_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg0 : public vp::reg_32 +{ +public: + inline void padcfg0_gpio0_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_WIDTH); } + inline uint32_t padcfg0_gpio0_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_WIDTH); } + inline void padcfg0_gpio0_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_WIDTH); } + inline uint32_t padcfg0_gpio0_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_WIDTH); } + inline void padcfg0_gpio1_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_WIDTH); } + inline uint32_t padcfg0_gpio1_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_WIDTH); } + inline void padcfg0_gpio1_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_WIDTH); } + inline uint32_t padcfg0_gpio1_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_WIDTH); } + inline void padcfg0_gpio2_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_WIDTH); } + inline uint32_t padcfg0_gpio2_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_WIDTH); } + inline void padcfg0_gpio2_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_WIDTH); } + inline uint32_t padcfg0_gpio2_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_WIDTH); } + inline void padcfg0_gpio3_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_WIDTH); } + inline uint32_t padcfg0_gpio3_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_WIDTH); } + inline void padcfg0_gpio3_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_WIDTH); } + inline uint32_t padcfg0_gpio3_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_BIT, GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg1 : public vp::reg_32 +{ +public: + inline void padcfg1_gpio4_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_WIDTH); } + inline uint32_t padcfg1_gpio4_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_WIDTH); } + inline void padcfg1_gpio4_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_WIDTH); } + inline uint32_t padcfg1_gpio4_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_WIDTH); } + inline void padcfg1_gpio5_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_WIDTH); } + inline uint32_t padcfg1_gpio5_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_WIDTH); } + inline void padcfg1_gpio5_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_WIDTH); } + inline uint32_t padcfg1_gpio5_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_WIDTH); } + inline void padcfg1_gpio6_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_WIDTH); } + inline uint32_t padcfg1_gpio6_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_WIDTH); } + inline void padcfg1_gpio6_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_WIDTH); } + inline uint32_t padcfg1_gpio6_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_WIDTH); } + inline void padcfg1_gpio7_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_WIDTH); } + inline uint32_t padcfg1_gpio7_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_WIDTH); } + inline void padcfg1_gpio7_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_WIDTH); } + inline uint32_t padcfg1_gpio7_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_BIT, GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg2 : public vp::reg_32 +{ +public: + inline void padcfg2_gpio8_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_WIDTH); } + inline uint32_t padcfg2_gpio8_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_WIDTH); } + inline void padcfg2_gpio8_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_WIDTH); } + inline uint32_t padcfg2_gpio8_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_WIDTH); } + inline void padcfg2_gpio9_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_WIDTH); } + inline uint32_t padcfg2_gpio9_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_WIDTH); } + inline void padcfg2_gpio9_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_WIDTH); } + inline uint32_t padcfg2_gpio9_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_WIDTH); } + inline void padcfg2_gpio10_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_WIDTH); } + inline uint32_t padcfg2_gpio10_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_WIDTH); } + inline void padcfg2_gpio10_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_WIDTH); } + inline uint32_t padcfg2_gpio10_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_WIDTH); } + inline void padcfg2_gpio11_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_WIDTH); } + inline uint32_t padcfg2_gpio11_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_WIDTH); } + inline void padcfg2_gpio11_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_WIDTH); } + inline uint32_t padcfg2_gpio11_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_BIT, GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg3 : public vp::reg_32 +{ +public: + inline void padcfg3_gpio12_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_WIDTH); } + inline uint32_t padcfg3_gpio12_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_WIDTH); } + inline void padcfg3_gpio12_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_WIDTH); } + inline uint32_t padcfg3_gpio12_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_WIDTH); } + inline void padcfg3_gpio13_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_WIDTH); } + inline uint32_t padcfg3_gpio13_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_WIDTH); } + inline void padcfg3_gpio13_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_WIDTH); } + inline uint32_t padcfg3_gpio13_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_WIDTH); } + inline void padcfg3_gpio14_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_WIDTH); } + inline uint32_t padcfg3_gpio14_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_WIDTH); } + inline void padcfg3_gpio14_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_WIDTH); } + inline uint32_t padcfg3_gpio14_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_WIDTH); } + inline void padcfg3_gpio15_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_WIDTH); } + inline uint32_t padcfg3_gpio15_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_WIDTH); } + inline void padcfg3_gpio15_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_WIDTH); } + inline uint32_t padcfg3_gpio15_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_BIT, GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg4 : public vp::reg_32 +{ +public: + inline void padcfg4_gpio16_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_WIDTH); } + inline uint32_t padcfg4_gpio16_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_WIDTH); } + inline void padcfg4_gpio16_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_WIDTH); } + inline uint32_t padcfg4_gpio16_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_WIDTH); } + inline void padcfg4_gpio17_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_WIDTH); } + inline uint32_t padcfg4_gpio17_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_WIDTH); } + inline void padcfg4_gpio17_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_WIDTH); } + inline uint32_t padcfg4_gpio17_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_WIDTH); } + inline void padcfg4_gpio18_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_WIDTH); } + inline uint32_t padcfg4_gpio18_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_WIDTH); } + inline void padcfg4_gpio18_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_WIDTH); } + inline uint32_t padcfg4_gpio18_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_WIDTH); } + inline void padcfg4_gpio19_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_WIDTH); } + inline uint32_t padcfg4_gpio19_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_WIDTH); } + inline void padcfg4_gpio19_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_WIDTH); } + inline uint32_t padcfg4_gpio19_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_BIT, GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg5 : public vp::reg_32 +{ +public: + inline void padcfg5_gpio20_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_WIDTH); } + inline uint32_t padcfg5_gpio20_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_WIDTH); } + inline void padcfg5_gpio20_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_WIDTH); } + inline uint32_t padcfg5_gpio20_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_WIDTH); } + inline void padcfg5_gpio21_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_WIDTH); } + inline uint32_t padcfg5_gpio21_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_WIDTH); } + inline void padcfg5_gpio21_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_WIDTH); } + inline uint32_t padcfg5_gpio21_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_WIDTH); } + inline void padcfg5_gpio22_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_WIDTH); } + inline uint32_t padcfg5_gpio22_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_WIDTH); } + inline void padcfg5_gpio22_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_WIDTH); } + inline uint32_t padcfg5_gpio22_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_WIDTH); } + inline void padcfg5_gpio23_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_WIDTH); } + inline uint32_t padcfg5_gpio23_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_WIDTH); } + inline void padcfg5_gpio23_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_WIDTH); } + inline uint32_t padcfg5_gpio23_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_BIT, GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg6 : public vp::reg_32 +{ +public: + inline void padcfg6_gpio24_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_WIDTH); } + inline uint32_t padcfg6_gpio24_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_WIDTH); } + inline void padcfg6_gpio24_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_WIDTH); } + inline uint32_t padcfg6_gpio24_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_WIDTH); } + inline void padcfg6_gpio25_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_WIDTH); } + inline uint32_t padcfg6_gpio25_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_WIDTH); } + inline void padcfg6_gpio25_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_WIDTH); } + inline uint32_t padcfg6_gpio25_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_WIDTH); } + inline void padcfg6_gpio26_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_WIDTH); } + inline uint32_t padcfg6_gpio26_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_WIDTH); } + inline void padcfg6_gpio26_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_WIDTH); } + inline uint32_t padcfg6_gpio26_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_WIDTH); } + inline void padcfg6_gpio27_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_WIDTH); } + inline uint32_t padcfg6_gpio27_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_WIDTH); } + inline void padcfg6_gpio27_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_WIDTH); } + inline uint32_t padcfg6_gpio27_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_BIT, GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_WIDTH); } +}; + +class vp_gpio_apbgpio_padcfg7 : public vp::reg_32 +{ +public: + inline void padcfg7_gpio28_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_WIDTH); } + inline uint32_t padcfg7_gpio28_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_WIDTH); } + inline void padcfg7_gpio28_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_WIDTH); } + inline uint32_t padcfg7_gpio28_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_WIDTH); } + inline void padcfg7_gpio29_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_WIDTH); } + inline uint32_t padcfg7_gpio29_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_WIDTH); } + inline void padcfg7_gpio29_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_WIDTH); } + inline uint32_t padcfg7_gpio29_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_WIDTH); } + inline void padcfg7_gpio30_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_WIDTH); } + inline uint32_t padcfg7_gpio30_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_WIDTH); } + inline void padcfg7_gpio30_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_WIDTH); } + inline uint32_t padcfg7_gpio30_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_WIDTH); } + inline void padcfg7_gpio31_pe_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_WIDTH); } + inline uint32_t padcfg7_gpio31_pe_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_WIDTH); } + inline void padcfg7_gpio31_ds_set(uint32_t value) { this->set_field(value, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_WIDTH); } + inline uint32_t padcfg7_gpio31_ds_get() { return this->get_field(GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_BIT, GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int apbgpio_paddir ; // GPIO pad direction configuration + unsigned int apbgpio_padin ; // GPIO pad input value + unsigned int apbgpio_padout ; // GPIO pad output value + unsigned int apbgpio_inten ; // GPIO pad interrupt enable configuration + unsigned int apbgpio_inttype0; // GPIO pad interrupt type bit 0 configuration + unsigned int apbgpio_inttype1; // GPIO pad interrupt type bit 1 configuration + unsigned int apbgpio_intstatus; // GPIO pad interrupt status + unsigned int apbgpio_gpioen ; // GPIO pad enable configuration + unsigned int apbgpio_padcfg0 ; // GPIO pad pin 0 to 3 configuration + unsigned int apbgpio_padcfg1 ; // GPIO pad pin 4 to 7 configuration + unsigned int apbgpio_padcfg2 ; // GPIO pad pin 8 to 11 configuration + unsigned int apbgpio_padcfg3 ; // GPIO pad pin 12 to 15 configuration + unsigned int apbgpio_padcfg4 ; // GPIO pad pin 16 to 19 configuration + unsigned int apbgpio_padcfg5 ; // GPIO pad pin 20 to 23 configuration + unsigned int apbgpio_padcfg6 ; // GPIO pad pin 24 to 27 configuration + unsigned int apbgpio_padcfg7 ; // GPIO pad pin 28 to 31 configuration +} __attribute__((packed)) gpio_gpio_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t gpio_apbgpio_paddir_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADDIR_OFFSET); } +static inline void gpio_apbgpio_paddir_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADDIR_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padin_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADIN_OFFSET); } +static inline void gpio_apbgpio_padin_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADIN_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padout_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADOUT_OFFSET); } +static inline void gpio_apbgpio_padout_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADOUT_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_inten_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_INTEN_OFFSET); } +static inline void gpio_apbgpio_inten_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_INTEN_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_inttype0_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_INTTYPE0_OFFSET); } +static inline void gpio_apbgpio_inttype0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_INTTYPE0_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_inttype1_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_INTTYPE1_OFFSET); } +static inline void gpio_apbgpio_inttype1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_INTTYPE1_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_intstatus_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_INTSTATUS_OFFSET); } +static inline void gpio_apbgpio_intstatus_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_INTSTATUS_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_gpioen_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_GPIOEN_OFFSET); } +static inline void gpio_apbgpio_gpioen_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_GPIOEN_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg0_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG0_OFFSET); } +static inline void gpio_apbgpio_padcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG0_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg1_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG1_OFFSET); } +static inline void gpio_apbgpio_padcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG1_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg2_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG2_OFFSET); } +static inline void gpio_apbgpio_padcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG2_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg3_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG3_OFFSET); } +static inline void gpio_apbgpio_padcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG3_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg4_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG4_OFFSET); } +static inline void gpio_apbgpio_padcfg4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG4_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg5_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG5_OFFSET); } +static inline void gpio_apbgpio_padcfg5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG5_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg6_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG6_OFFSET); } +static inline void gpio_apbgpio_padcfg6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG6_OFFSET, value); } + +static inline uint32_t gpio_apbgpio_padcfg7_get(uint32_t base) { return ARCHI_READ(base, GPIO_APBGPIO_PADCFG7_OFFSET); } +static inline void gpio_apbgpio_padcfg7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_APBGPIO_PADCFG7_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define GPIO_APBGPIO_PADDIR_DIR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_PADDIR_DIR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_PADDIR_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_PADDIR_DIR(val) ((val) << 0) + +#define GPIO_APBGPIO_PADIN_DATA_IN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_PADIN_DATA_IN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_PADIN_DATA_IN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_PADIN_DATA_IN(val) ((val) << 0) + +#define GPIO_APBGPIO_PADOUT_DATA_OUT_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_PADOUT_DATA_OUT_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_PADOUT_DATA_OUT_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_PADOUT_DATA_OUT(val) ((val) << 0) + +#define GPIO_APBGPIO_INTEN_INTEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_INTEN_INTEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_INTEN_INTEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_INTEN_INTEN(val) ((val) << 0) + +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_INTTYPE0_INTTYPE0(val) ((val) << 0) + +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_INTTYPE1_INTTYPE1(val) ((val) << 0) + +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_INTSTATUS_INTSTATUS(val) ((val) << 0) + +#define GPIO_APBGPIO_GPIOEN_GPIOEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_APBGPIO_GPIOEN_GPIOEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_APBGPIO_GPIOEN_GPIOEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_APBGPIO_GPIOEN_GPIOEN(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO0_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO1_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO2_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG0_PADCFG0_GPIO3_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO4_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO5_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO6_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG1_PADCFG1_GPIO7_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO8_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO9_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO10_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG2_PADCFG2_GPIO11_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO12_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO13_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO14_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG3_PADCFG3_GPIO15_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO16_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO17_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO18_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG4_PADCFG4_GPIO19_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO20_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO21_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO22_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG5_PADCFG5_GPIO23_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO24_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO25_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO26_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG6_PADCFG6_GPIO27_DS(val) ((val) << 25) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_PE(val) ((val) << 0) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO28_DS(val) ((val) << 1) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_PE(val) ((val) << 8) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO29_DS(val) ((val) << 9) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_PE(val) ((val) << 16) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO30_DS(val) ((val) << 17) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_PE(val) ((val) << 24) + +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define GPIO_APBGPIO_PADCFG7_PADCFG7_GPIO31_DS(val) ((val) << 25) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/gpio/gpio_v3.h b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v3.h new file mode 100644 index 0000000..54eebc2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/gpio/gpio_v3.h @@ -0,0 +1,992 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_GPIO_GPIO_V3_H__ +#define __INCLUDE_ARCHI_GPIO_GPIO_V3_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// GPIO pad direction configuration register. +#define GPIO_PADDIR_OFFSET 0x0 + +// GPIO enable register. +#define GPIO_GPIOEN_OFFSET 0x4 + +// GPIO pad input value register. +#define GPIO_PADIN_OFFSET 0x8 + +// GPIO pad output value register. +#define GPIO_PADOUT_OFFSET 0xc + +// GPIO pad output set register. +#define GPIO_PADOUTSET_OFFSET 0x10 + +// GPIO pad output clear register. +#define GPIO_PADOUTCLR_OFFSET 0x14 + +// GPIO pad interrupt enable configuration register. +#define GPIO_INTEN_OFFSET 0x18 + +// GPIO pad interrupt type gpio 0 to 15 register. +#define GPIO_INTTYPE0_OFFSET 0x1c + +// GPIO pad interrupt type gpio 16 to 31 register. +#define GPIO_INTTYPE1_OFFSET 0x20 + +// GPIO pad interrupt status register. +#define GPIO_INTSTATUS_OFFSET 0x24 + +// GPIO pad pin 0 to 7 configuration register. +#define GPIO_PADCFG0_OFFSET 0x28 + +// GPIO pad pin 8 to 15 configuration register. +#define GPIO_PADCFG1_OFFSET 0x2c + +// GPIO pad pin 16 to 23 configuration register. +#define GPIO_PADCFG2_OFFSET 0x30 + +// GPIO pad pin 24 to 31 configuration register. +#define GPIO_PADCFG3_OFFSET 0x34 + +// GPIO pad direction configuration register. +#define GPIO_PADDIR_32_63_OFFSET 0x38 + +// GPIO enable register. +#define GPIO_GPIOEN_32_63_OFFSET 0x3c + +// GPIO pad input value register. +#define GPIO_PADIN_32_63_OFFSET 0x40 + +// GPIO pad output value register. +#define GPIO_PADOUT_32_63_OFFSET 0x44 + +// GPIO pad output set register. +#define GPIO_PADOUTSET_32_63_OFFSET 0x48 + +// GPIO pad output clear register. +#define GPIO_PADOUTCLR_32_63_OFFSET 0x4c + +// GPIO pad interrupt enable configuration register. +#define GPIO_INTEN_32_63_OFFSET 0x50 + +// GPIO pad interrupt type gpio 32 to 47 register. +#define GPIO_INTTYPE_32_47_OFFSET 0x54 + +// GPIO pad interrupt type gpio 48 to 63 register. +#define GPIO_INTTYPE_48_63_OFFSET 0x58 + +// GPIO pad interrupt status register. +#define GPIO_INTSTATUS_32_63_OFFSET 0x5c + +// GPIO pad pin 32 to 39 configuration register. +#define GPIO_PADCFG_32_39_OFFSET 0x60 + +// GPIO pad pin 40 to 47 configuration register. +#define GPIO_PADCFG_40_47_OFFSET 0x64 + +// GPIO pad pin 48 to 55 configuration register. +#define GPIO_PADCFG_48_55_OFFSET 0x68 + +// GPIO pad pin 56 to 63 configuration register. +#define GPIO_PADCFG_56_63_OFFSET 0x6c + + + +// +// REGISTERS FIELDS +// + +// GPIO[31:0] direction configuration bitfield: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] (access: R/W) +#define GPIO_PADDIR_DIR_BIT 0 +#define GPIO_PADDIR_DIR_WIDTH 32 +#define GPIO_PADDIR_DIR_MASK 0xffffffff + +// GPIO[31:0] clock enable configuration bitfield: - bit[i]=1'b0: disable clock for GPIO[i] - bit[i]=1'b1: enable clock for GPIO[i] GPIOs are gathered by groups of 4. The clock gating of one group is done only if all 4 GPIOs are disabled. Clock must be enabled for a GPIO if it's direction is configured in input mode. (access: R/W) +#define GPIO_GPIOEN_GPIOEN_BIT 0 +#define GPIO_GPIOEN_GPIOEN_WIDTH 32 +#define GPIO_GPIOEN_GPIOEN_MASK 0xffffffff + +// GPIO[31:0] input data read bitfield. DATA_IN[i] corresponds to input data of GPIO[i]. (access: R) +#define GPIO_PADIN_DATA_IN_BIT 0 +#define GPIO_PADIN_DATA_IN_WIDTH 32 +#define GPIO_PADIN_DATA_IN_MASK 0xffffffff + +// GPIO[31:0] output data read bitfield. DATA_OUT[i] corresponds to output data set on GPIO[i]. (access: R/W) +#define GPIO_PADOUT_DATA_OUT_BIT 0 +#define GPIO_PADOUT_DATA_OUT_WIDTH 32 +#define GPIO_PADOUT_DATA_OUT_MASK 0xffffffff + +// GPIO[31:0] set bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Sets GPIO[i] to 1 (access: W) +#define GPIO_PADOUTSET_DATA_SET_BIT 0 +#define GPIO_PADOUTSET_DATA_SET_WIDTH 32 +#define GPIO_PADOUTSET_DATA_SET_MASK 0xffffffff + +// GPIO[31:0] clear bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Clears GPIO[i] (access: W) +#define GPIO_PADOUTCLR_DATA_CLEAR_BIT 0 +#define GPIO_PADOUTCLR_DATA_CLEAR_WIDTH 32 +#define GPIO_PADOUTCLR_DATA_CLEAR_MASK 0xffffffff + +// GPIO[31:0] interrupt enable configuration bitfield: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] (access: R/W) +#define GPIO_INTEN_INTEN_BIT 0 +#define GPIO_INTEN_INTEN_WIDTH 32 +#define GPIO_INTEN_INTEN_MASK 0xffffffff + +// GPIO[15:0] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_INTTYPE0_INTTYPE0_BIT 0 +#define GPIO_INTTYPE0_INTTYPE0_WIDTH 32 +#define GPIO_INTTYPE0_INTTYPE0_MASK 0xffffffff + +// GPIO[31:16] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_INTTYPE1_INTTYPE1_BIT 0 +#define GPIO_INTTYPE1_INTTYPE1_WIDTH 32 +#define GPIO_INTTYPE1_INTTYPE1_MASK 0xffffffff + +// GPIO[31:0] Interrupt status flags bitfield. INTSTATUS[i]=1 when interrupt received on GPIO[i]. INTSTATUS is cleared when it is red. GPIO interrupt line is also cleared when INTSTATUS register is red. (access: R) +#define GPIO_INTSTATUS_INTSTATUS_BIT 0 +#define GPIO_INTSTATUS_INTSTATUS_WIDTH 32 +#define GPIO_INTSTATUS_INTSTATUS_MASK 0xffffffff + +// GPIO[0] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_PADCFG0_GPIO0_CFG_BIT 0 +#define GPIO_PADCFG0_GPIO0_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO0_CFG_MASK 0xf + +// GPIO[0] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_PADCFG0_GPIO1_CFG_BIT 4 +#define GPIO_PADCFG0_GPIO1_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO1_CFG_MASK 0xf0 + +// GPIO[1] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_PADCFG0_GPIO2_CFG_BIT 8 +#define GPIO_PADCFG0_GPIO2_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO2_CFG_MASK 0xf00 + +// GPIO[1] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_PADCFG0_GPIO3_CFG_BIT 12 +#define GPIO_PADCFG0_GPIO3_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO3_CFG_MASK 0xf000 + +// GPIO[2] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_PADCFG0_GPIO4_CFG_BIT 16 +#define GPIO_PADCFG0_GPIO4_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO4_CFG_MASK 0xf0000 + +// GPIO[2] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_PADCFG0_GPIO5_CFG_BIT 20 +#define GPIO_PADCFG0_GPIO5_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO5_CFG_MASK 0xf00000 + +// GPIO[3] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_PADCFG0_GPIO6_CFG_BIT 24 +#define GPIO_PADCFG0_GPIO6_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO6_CFG_MASK 0xf000000 + +// GPIO[3] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_PADCFG0_GPIO7_CFG_BIT 28 +#define GPIO_PADCFG0_GPIO7_CFG_WIDTH 4 +#define GPIO_PADCFG0_GPIO7_CFG_MASK 0xf0000000 + +// GPIO[4] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled (access: R/W) +#define GPIO_PADCFG1_GPIO4_PE_BIT 0 +#define GPIO_PADCFG1_GPIO4_PE_WIDTH 1 +#define GPIO_PADCFG1_GPIO4_PE_MASK 0x1 + +// GPIO[4] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength (access: R/W) +#define GPIO_PADCFG1_GPIO4_DS_BIT 1 +#define GPIO_PADCFG1_GPIO4_DS_WIDTH 1 +#define GPIO_PADCFG1_GPIO4_DS_MASK 0x2 + +// GPIO[63:32] direction configuration bitfield: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] (access: R/W) +#define GPIO_PADDIR_32_63_DIR_BIT 0 +#define GPIO_PADDIR_32_63_DIR_WIDTH 32 +#define GPIO_PADDIR_32_63_DIR_MASK 0xffffffff + +// GPIO[63:32] clock enable configuration bitfield: - bit[i]=1'b0: disable clock for GPIO[i] - bit[i]=1'b1: enable clock for GPIO[i] GPIOs are gathered by groups of 4. The clock gating of one group is done only if all 4 GPIOs are disabled. Clock must be enabled for a GPIO if it's direction is configured in input mode. (access: R/W) +#define GPIO_GPIOEN_32_63_GPIOEN_BIT 0 +#define GPIO_GPIOEN_32_63_GPIOEN_WIDTH 32 +#define GPIO_GPIOEN_32_63_GPIOEN_MASK 0xffffffff + +// GPIO[63:32] input data read bitfield. DATA_IN[i] corresponds to input data of GPIO[i]. (access: R) +#define GPIO_PADIN_32_63_DATA_IN_BIT 0 +#define GPIO_PADIN_32_63_DATA_IN_WIDTH 32 +#define GPIO_PADIN_32_63_DATA_IN_MASK 0xffffffff + +// GPIO[63:32] output data read bitfield. DATA_OUT[i] corresponds to output data set on GPIO[i]. (access: R/W) +#define GPIO_PADOUT_32_63_DATA_OUT_BIT 0 +#define GPIO_PADOUT_32_63_DATA_OUT_WIDTH 32 +#define GPIO_PADOUT_32_63_DATA_OUT_MASK 0xffffffff + +// GPIO[63:32] set bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Sets GPIO[i] to 1 (access: W) +#define GPIO_PADOUTSET_32_63_DATA_SET_BIT 0 +#define GPIO_PADOUTSET_32_63_DATA_SET_WIDTH 32 +#define GPIO_PADOUTSET_32_63_DATA_SET_MASK 0xffffffff + +// GPIO[63:32] clear bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Clears GPIO[i] (access: W) +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_BIT 0 +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_WIDTH 32 +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_MASK 0xffffffff + +// GPIO[63:32] interrupt enable configuration bitfield: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] (access: R/W) +#define GPIO_INTEN_32_63_INTEN_BIT 0 +#define GPIO_INTEN_32_63_INTEN_WIDTH 32 +#define GPIO_INTEN_32_63_INTEN_MASK 0xffffffff + +// GPIO[47:32] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_INTTYPE_32_47_INTTYPE0_BIT 0 +#define GPIO_INTTYPE_32_47_INTTYPE0_WIDTH 32 +#define GPIO_INTTYPE_32_47_INTTYPE0_MASK 0xffffffff + +// GPIO[63:48] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU (access: R/W) +#define GPIO_INTTYPE_48_63_INTTYPE1_BIT 0 +#define GPIO_INTTYPE_48_63_INTTYPE1_WIDTH 32 +#define GPIO_INTTYPE_48_63_INTTYPE1_MASK 0xffffffff + +// GPIO[63:32] Interrupt status flags bitfield. INTSTATUS[i]=1 when interrupt received on GPIO[i]. INTSTATUS is cleared when it is red. GPIO interrupt line is also cleared when INTSTATUS register is red. (access: R) +#define GPIO_INTSTATUS_32_63_INTSTATUS_BIT 0 +#define GPIO_INTSTATUS_32_63_INTSTATUS_WIDTH 32 +#define GPIO_INTSTATUS_32_63_INTSTATUS_MASK 0xffffffff + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int dir :32; // GPIO[31:0] direction configuration bitfield: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_paddir_t; + +typedef union { + struct { + unsigned int gpioen :32; // GPIO[31:0] clock enable configuration bitfield: - bit[i]=1'b0: disable clock for GPIO[i] - bit[i]=1'b1: enable clock for GPIO[i] GPIOs are gathered by groups of 4. The clock gating of one group is done only if all 4 GPIOs are disabled. Clock must be enabled for a GPIO if it's direction is configured in input mode. + }; + unsigned int raw; +} __attribute__((packed)) gpio_gpioen_t; + +typedef union { + struct { + unsigned int data_in :32; // GPIO[31:0] input data read bitfield. DATA_IN[i] corresponds to input data of GPIO[i]. + }; + unsigned int raw; +} __attribute__((packed)) gpio_padin_t; + +typedef union { + struct { + unsigned int data_out :32; // GPIO[31:0] output data read bitfield. DATA_OUT[i] corresponds to output data set on GPIO[i]. + }; + unsigned int raw; +} __attribute__((packed)) gpio_padout_t; + +typedef union { + struct { + unsigned int data_set :32; // GPIO[31:0] set bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Sets GPIO[i] to 1 + }; + unsigned int raw; +} __attribute__((packed)) gpio_padoutset_t; + +typedef union { + struct { + unsigned int data_clear :32; // GPIO[31:0] clear bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Clears GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_padoutclr_t; + +typedef union { + struct { + unsigned int inten :32; // GPIO[31:0] interrupt enable configuration bitfield: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_inten_t; + +typedef union { + struct { + unsigned int inttype0 :32; // GPIO[15:0] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_inttype0_t; + +typedef union { + struct { + unsigned int inttype1 :32; // GPIO[31:16] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_inttype1_t; + +typedef union { + struct { + unsigned int intstatus :32; // GPIO[31:0] Interrupt status flags bitfield. INTSTATUS[i]=1 when interrupt received on GPIO[i]. INTSTATUS is cleared when it is red. GPIO interrupt line is also cleared when INTSTATUS register is red. + }; + unsigned int raw; +} __attribute__((packed)) gpio_intstatus_t; + +typedef union { + struct { + unsigned int gpio0_cfg :4 ; // GPIO[0] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int gpio1_cfg :4 ; // GPIO[0] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int gpio2_cfg :4 ; // GPIO[1] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int gpio3_cfg :4 ; // GPIO[1] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int gpio4_cfg :4 ; // GPIO[2] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int gpio5_cfg :4 ; // GPIO[2] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength + unsigned int gpio6_cfg :4 ; // GPIO[3] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int gpio7_cfg :4 ; // GPIO[3] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg0_t; + +typedef union { + struct { + unsigned int gpio4_pe :1 ; // GPIO[4] pull activation configuration bitfield: - 1'b0: pull disabled - 1'b1: pull enabled + unsigned int gpio4_ds :1 ; // GPIO[4] drive strength configuration bitfield: - 1'b0: low drive strength - 1'b1: high drive strength + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg2_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg3_t; + +typedef union { + struct { + unsigned int dir :32; // GPIO[63:32] direction configuration bitfield: - bit[i]=1'b0: Input mode for GPIO[i] - bit[i]=1'b1: Output mode for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_paddir_32_63_t; + +typedef union { + struct { + unsigned int gpioen :32; // GPIO[63:32] clock enable configuration bitfield: - bit[i]=1'b0: disable clock for GPIO[i] - bit[i]=1'b1: enable clock for GPIO[i] GPIOs are gathered by groups of 4. The clock gating of one group is done only if all 4 GPIOs are disabled. Clock must be enabled for a GPIO if it's direction is configured in input mode. + }; + unsigned int raw; +} __attribute__((packed)) gpio_gpioen_32_63_t; + +typedef union { + struct { + unsigned int data_in :32; // GPIO[63:32] input data read bitfield. DATA_IN[i] corresponds to input data of GPIO[i]. + }; + unsigned int raw; +} __attribute__((packed)) gpio_padin_32_63_t; + +typedef union { + struct { + unsigned int data_out :32; // GPIO[63:32] output data read bitfield. DATA_OUT[i] corresponds to output data set on GPIO[i]. + }; + unsigned int raw; +} __attribute__((packed)) gpio_padout_32_63_t; + +typedef union { + struct { + unsigned int data_set :32; // GPIO[63:32] set bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Sets GPIO[i] to 1 + }; + unsigned int raw; +} __attribute__((packed)) gpio_padoutset_32_63_t; + +typedef union { + struct { + unsigned int data_clear :32; // GPIO[63:32] clear bitfield: - bit[i]=1'b0: No change for GPIO[i] - bit[i]=1'b1: Clears GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_padoutclr_32_63_t; + +typedef union { + struct { + unsigned int inten :32; // GPIO[63:32] interrupt enable configuration bitfield: - bit[i]=1'b0: disable interrupt for GPIO[i] - bit[i]=1'b1: enable interrupt for GPIO[i] + }; + unsigned int raw; +} __attribute__((packed)) gpio_inten_32_63_t; + +typedef union { + struct { + unsigned int inttype0 :32; // GPIO[47:32] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_inttype_32_47_t; + +typedef union { + struct { + unsigned int inttype1 :32; // GPIO[63:48] interrupt type configuration bitfield: - bit[2*i+1:2*i]=2'b00: interrupt on falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b01: interrupt on rising edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b10: interrupt on rising and falling edge for GPIO[16+i] - bit[2*i+1:2*i]=2'b11: RFU + }; + unsigned int raw; +} __attribute__((packed)) gpio_inttype_48_63_t; + +typedef union { + struct { + unsigned int intstatus :32; // GPIO[63:32] Interrupt status flags bitfield. INTSTATUS[i]=1 when interrupt received on GPIO[i]. INTSTATUS is cleared when it is red. GPIO interrupt line is also cleared when INTSTATUS register is red. + }; + unsigned int raw; +} __attribute__((packed)) gpio_intstatus_32_63_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg_32_39_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg_40_47_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg_48_55_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) gpio_padcfg_56_63_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_gpio_paddir : public vp::reg_32 +{ +public: + inline void dir_set(uint32_t value) { this->set_field(value, GPIO_PADDIR_DIR_BIT, GPIO_PADDIR_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(GPIO_PADDIR_DIR_BIT, GPIO_PADDIR_DIR_WIDTH); } +}; + +class vp_gpio_gpioen : public vp::reg_32 +{ +public: + inline void gpioen_set(uint32_t value) { this->set_field(value, GPIO_GPIOEN_GPIOEN_BIT, GPIO_GPIOEN_GPIOEN_WIDTH); } + inline uint32_t gpioen_get() { return this->get_field(GPIO_GPIOEN_GPIOEN_BIT, GPIO_GPIOEN_GPIOEN_WIDTH); } +}; + +class vp_gpio_padin : public vp::reg_32 +{ +public: + inline void data_in_set(uint32_t value) { this->set_field(value, GPIO_PADIN_DATA_IN_BIT, GPIO_PADIN_DATA_IN_WIDTH); } + inline uint32_t data_in_get() { return this->get_field(GPIO_PADIN_DATA_IN_BIT, GPIO_PADIN_DATA_IN_WIDTH); } +}; + +class vp_gpio_padout : public vp::reg_32 +{ +public: + inline void data_out_set(uint32_t value) { this->set_field(value, GPIO_PADOUT_DATA_OUT_BIT, GPIO_PADOUT_DATA_OUT_WIDTH); } + inline uint32_t data_out_get() { return this->get_field(GPIO_PADOUT_DATA_OUT_BIT, GPIO_PADOUT_DATA_OUT_WIDTH); } +}; + +class vp_gpio_padoutset : public vp::reg_32 +{ +public: + inline void data_set_set(uint32_t value) { this->set_field(value, GPIO_PADOUTSET_DATA_SET_BIT, GPIO_PADOUTSET_DATA_SET_WIDTH); } + inline uint32_t data_set_get() { return this->get_field(GPIO_PADOUTSET_DATA_SET_BIT, GPIO_PADOUTSET_DATA_SET_WIDTH); } +}; + +class vp_gpio_padoutclr : public vp::reg_32 +{ +public: + inline void data_clear_set(uint32_t value) { this->set_field(value, GPIO_PADOUTCLR_DATA_CLEAR_BIT, GPIO_PADOUTCLR_DATA_CLEAR_WIDTH); } + inline uint32_t data_clear_get() { return this->get_field(GPIO_PADOUTCLR_DATA_CLEAR_BIT, GPIO_PADOUTCLR_DATA_CLEAR_WIDTH); } +}; + +class vp_gpio_inten : public vp::reg_32 +{ +public: + inline void inten_set(uint32_t value) { this->set_field(value, GPIO_INTEN_INTEN_BIT, GPIO_INTEN_INTEN_WIDTH); } + inline uint32_t inten_get() { return this->get_field(GPIO_INTEN_INTEN_BIT, GPIO_INTEN_INTEN_WIDTH); } +}; + +class vp_gpio_inttype0 : public vp::reg_32 +{ +public: + inline void inttype0_set(uint32_t value) { this->set_field(value, GPIO_INTTYPE0_INTTYPE0_BIT, GPIO_INTTYPE0_INTTYPE0_WIDTH); } + inline uint32_t inttype0_get() { return this->get_field(GPIO_INTTYPE0_INTTYPE0_BIT, GPIO_INTTYPE0_INTTYPE0_WIDTH); } +}; + +class vp_gpio_inttype1 : public vp::reg_32 +{ +public: + inline void inttype1_set(uint32_t value) { this->set_field(value, GPIO_INTTYPE1_INTTYPE1_BIT, GPIO_INTTYPE1_INTTYPE1_WIDTH); } + inline uint32_t inttype1_get() { return this->get_field(GPIO_INTTYPE1_INTTYPE1_BIT, GPIO_INTTYPE1_INTTYPE1_WIDTH); } +}; + +class vp_gpio_intstatus : public vp::reg_32 +{ +public: + inline void intstatus_set(uint32_t value) { this->set_field(value, GPIO_INTSTATUS_INTSTATUS_BIT, GPIO_INTSTATUS_INTSTATUS_WIDTH); } + inline uint32_t intstatus_get() { return this->get_field(GPIO_INTSTATUS_INTSTATUS_BIT, GPIO_INTSTATUS_INTSTATUS_WIDTH); } +}; + +class vp_gpio_padcfg0 : public vp::reg_32 +{ +public: + inline void gpio0_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO0_CFG_BIT, GPIO_PADCFG0_GPIO0_CFG_WIDTH); } + inline uint32_t gpio0_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO0_CFG_BIT, GPIO_PADCFG0_GPIO0_CFG_WIDTH); } + inline void gpio1_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO1_CFG_BIT, GPIO_PADCFG0_GPIO1_CFG_WIDTH); } + inline uint32_t gpio1_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO1_CFG_BIT, GPIO_PADCFG0_GPIO1_CFG_WIDTH); } + inline void gpio2_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO2_CFG_BIT, GPIO_PADCFG0_GPIO2_CFG_WIDTH); } + inline uint32_t gpio2_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO2_CFG_BIT, GPIO_PADCFG0_GPIO2_CFG_WIDTH); } + inline void gpio3_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO3_CFG_BIT, GPIO_PADCFG0_GPIO3_CFG_WIDTH); } + inline uint32_t gpio3_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO3_CFG_BIT, GPIO_PADCFG0_GPIO3_CFG_WIDTH); } + inline void gpio4_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO4_CFG_BIT, GPIO_PADCFG0_GPIO4_CFG_WIDTH); } + inline uint32_t gpio4_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO4_CFG_BIT, GPIO_PADCFG0_GPIO4_CFG_WIDTH); } + inline void gpio5_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO5_CFG_BIT, GPIO_PADCFG0_GPIO5_CFG_WIDTH); } + inline uint32_t gpio5_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO5_CFG_BIT, GPIO_PADCFG0_GPIO5_CFG_WIDTH); } + inline void gpio6_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO6_CFG_BIT, GPIO_PADCFG0_GPIO6_CFG_WIDTH); } + inline uint32_t gpio6_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO6_CFG_BIT, GPIO_PADCFG0_GPIO6_CFG_WIDTH); } + inline void gpio7_cfg_set(uint32_t value) { this->set_field(value, GPIO_PADCFG0_GPIO7_CFG_BIT, GPIO_PADCFG0_GPIO7_CFG_WIDTH); } + inline uint32_t gpio7_cfg_get() { return this->get_field(GPIO_PADCFG0_GPIO7_CFG_BIT, GPIO_PADCFG0_GPIO7_CFG_WIDTH); } +}; + +class vp_gpio_padcfg1 : public vp::reg_32 +{ +public: + inline void gpio4_pe_set(uint32_t value) { this->set_field(value, GPIO_PADCFG1_GPIO4_PE_BIT, GPIO_PADCFG1_GPIO4_PE_WIDTH); } + inline uint32_t gpio4_pe_get() { return this->get_field(GPIO_PADCFG1_GPIO4_PE_BIT, GPIO_PADCFG1_GPIO4_PE_WIDTH); } + inline void gpio4_ds_set(uint32_t value) { this->set_field(value, GPIO_PADCFG1_GPIO4_DS_BIT, GPIO_PADCFG1_GPIO4_DS_WIDTH); } + inline uint32_t gpio4_ds_get() { return this->get_field(GPIO_PADCFG1_GPIO4_DS_BIT, GPIO_PADCFG1_GPIO4_DS_WIDTH); } +}; + +class vp_gpio_padcfg2 : public vp::reg_32 +{ +public: +}; + +class vp_gpio_padcfg3 : public vp::reg_32 +{ +public: +}; + +class vp_gpio_paddir_32_63 : public vp::reg_32 +{ +public: + inline void dir_set(uint32_t value) { this->set_field(value, GPIO_PADDIR_32_63_DIR_BIT, GPIO_PADDIR_32_63_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(GPIO_PADDIR_32_63_DIR_BIT, GPIO_PADDIR_32_63_DIR_WIDTH); } +}; + +class vp_gpio_gpioen_32_63 : public vp::reg_32 +{ +public: + inline void gpioen_set(uint32_t value) { this->set_field(value, GPIO_GPIOEN_32_63_GPIOEN_BIT, GPIO_GPIOEN_32_63_GPIOEN_WIDTH); } + inline uint32_t gpioen_get() { return this->get_field(GPIO_GPIOEN_32_63_GPIOEN_BIT, GPIO_GPIOEN_32_63_GPIOEN_WIDTH); } +}; + +class vp_gpio_padin_32_63 : public vp::reg_32 +{ +public: + inline void data_in_set(uint32_t value) { this->set_field(value, GPIO_PADIN_32_63_DATA_IN_BIT, GPIO_PADIN_32_63_DATA_IN_WIDTH); } + inline uint32_t data_in_get() { return this->get_field(GPIO_PADIN_32_63_DATA_IN_BIT, GPIO_PADIN_32_63_DATA_IN_WIDTH); } +}; + +class vp_gpio_padout_32_63 : public vp::reg_32 +{ +public: + inline void data_out_set(uint32_t value) { this->set_field(value, GPIO_PADOUT_32_63_DATA_OUT_BIT, GPIO_PADOUT_32_63_DATA_OUT_WIDTH); } + inline uint32_t data_out_get() { return this->get_field(GPIO_PADOUT_32_63_DATA_OUT_BIT, GPIO_PADOUT_32_63_DATA_OUT_WIDTH); } +}; + +class vp_gpio_padoutset_32_63 : public vp::reg_32 +{ +public: + inline void data_set_set(uint32_t value) { this->set_field(value, GPIO_PADOUTSET_32_63_DATA_SET_BIT, GPIO_PADOUTSET_32_63_DATA_SET_WIDTH); } + inline uint32_t data_set_get() { return this->get_field(GPIO_PADOUTSET_32_63_DATA_SET_BIT, GPIO_PADOUTSET_32_63_DATA_SET_WIDTH); } +}; + +class vp_gpio_padoutclr_32_63 : public vp::reg_32 +{ +public: + inline void data_clear_set(uint32_t value) { this->set_field(value, GPIO_PADOUTCLR_32_63_DATA_CLEAR_BIT, GPIO_PADOUTCLR_32_63_DATA_CLEAR_WIDTH); } + inline uint32_t data_clear_get() { return this->get_field(GPIO_PADOUTCLR_32_63_DATA_CLEAR_BIT, GPIO_PADOUTCLR_32_63_DATA_CLEAR_WIDTH); } +}; + +class vp_gpio_inten_32_63 : public vp::reg_32 +{ +public: + inline void inten_set(uint32_t value) { this->set_field(value, GPIO_INTEN_32_63_INTEN_BIT, GPIO_INTEN_32_63_INTEN_WIDTH); } + inline uint32_t inten_get() { return this->get_field(GPIO_INTEN_32_63_INTEN_BIT, GPIO_INTEN_32_63_INTEN_WIDTH); } +}; + +class vp_gpio_inttype_32_47 : public vp::reg_32 +{ +public: + inline void inttype0_set(uint32_t value) { this->set_field(value, GPIO_INTTYPE_32_47_INTTYPE0_BIT, GPIO_INTTYPE_32_47_INTTYPE0_WIDTH); } + inline uint32_t inttype0_get() { return this->get_field(GPIO_INTTYPE_32_47_INTTYPE0_BIT, GPIO_INTTYPE_32_47_INTTYPE0_WIDTH); } +}; + +class vp_gpio_inttype_48_63 : public vp::reg_32 +{ +public: + inline void inttype1_set(uint32_t value) { this->set_field(value, GPIO_INTTYPE_48_63_INTTYPE1_BIT, GPIO_INTTYPE_48_63_INTTYPE1_WIDTH); } + inline uint32_t inttype1_get() { return this->get_field(GPIO_INTTYPE_48_63_INTTYPE1_BIT, GPIO_INTTYPE_48_63_INTTYPE1_WIDTH); } +}; + +class vp_gpio_intstatus_32_63 : public vp::reg_32 +{ +public: + inline void intstatus_set(uint32_t value) { this->set_field(value, GPIO_INTSTATUS_32_63_INTSTATUS_BIT, GPIO_INTSTATUS_32_63_INTSTATUS_WIDTH); } + inline uint32_t intstatus_get() { return this->get_field(GPIO_INTSTATUS_32_63_INTSTATUS_BIT, GPIO_INTSTATUS_32_63_INTSTATUS_WIDTH); } +}; + +class vp_gpio_padcfg_32_39 : public vp::reg_32 +{ +public: +}; + +class vp_gpio_padcfg_40_47 : public vp::reg_32 +{ +public: +}; + +class vp_gpio_padcfg_48_55 : public vp::reg_32 +{ +public: +}; + +class vp_gpio_padcfg_56_63 : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int paddir ; // GPIO pad direction configuration register. + unsigned int gpioen ; // GPIO enable register. + unsigned int padin ; // GPIO pad input value register. + unsigned int padout ; // GPIO pad output value register. + unsigned int padoutset ; // GPIO pad output set register. + unsigned int padoutclr ; // GPIO pad output clear register. + unsigned int inten ; // GPIO pad interrupt enable configuration register. + unsigned int inttype0 ; // GPIO pad interrupt type gpio 0 to 15 register. + unsigned int inttype1 ; // GPIO pad interrupt type gpio 16 to 31 register. + unsigned int intstatus ; // GPIO pad interrupt status register. + unsigned int padcfg0 ; // GPIO pad pin 0 to 7 configuration register. + unsigned int padcfg1 ; // GPIO pad pin 8 to 15 configuration register. + unsigned int padcfg2 ; // GPIO pad pin 16 to 23 configuration register. + unsigned int padcfg3 ; // GPIO pad pin 24 to 31 configuration register. + unsigned int paddir_32_63 ; // GPIO pad direction configuration register. + unsigned int gpioen_32_63 ; // GPIO enable register. + unsigned int padin_32_63 ; // GPIO pad input value register. + unsigned int padout_32_63 ; // GPIO pad output value register. + unsigned int padoutset_32_63 ; // GPIO pad output set register. + unsigned int padoutclr_32_63 ; // GPIO pad output clear register. + unsigned int inten_32_63 ; // GPIO pad interrupt enable configuration register. + unsigned int inttype_32_47 ; // GPIO pad interrupt type gpio 32 to 47 register. + unsigned int inttype_48_63 ; // GPIO pad interrupt type gpio 48 to 63 register. + unsigned int intstatus_32_63 ; // GPIO pad interrupt status register. + unsigned int padcfg_32_39 ; // GPIO pad pin 32 to 39 configuration register. + unsigned int padcfg_40_47 ; // GPIO pad pin 40 to 47 configuration register. + unsigned int padcfg_48_55 ; // GPIO pad pin 48 to 55 configuration register. + unsigned int padcfg_56_63 ; // GPIO pad pin 56 to 63 configuration register. +} __attribute__((packed)) gpio_gpio_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t gpio_paddir_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADDIR_OFFSET); } +static inline void gpio_paddir_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADDIR_OFFSET, value); } + +static inline uint32_t gpio_gpioen_get(uint32_t base) { return ARCHI_READ(base, GPIO_GPIOEN_OFFSET); } +static inline void gpio_gpioen_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_GPIOEN_OFFSET, value); } + +static inline uint32_t gpio_padin_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADIN_OFFSET); } +static inline void gpio_padin_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADIN_OFFSET, value); } + +static inline uint32_t gpio_padout_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUT_OFFSET); } +static inline void gpio_padout_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUT_OFFSET, value); } + +static inline uint32_t gpio_padoutset_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUTSET_OFFSET); } +static inline void gpio_padoutset_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUTSET_OFFSET, value); } + +static inline uint32_t gpio_padoutclr_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUTCLR_OFFSET); } +static inline void gpio_padoutclr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUTCLR_OFFSET, value); } + +static inline uint32_t gpio_inten_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTEN_OFFSET); } +static inline void gpio_inten_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTEN_OFFSET, value); } + +static inline uint32_t gpio_inttype0_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTTYPE0_OFFSET); } +static inline void gpio_inttype0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTTYPE0_OFFSET, value); } + +static inline uint32_t gpio_inttype1_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTTYPE1_OFFSET); } +static inline void gpio_inttype1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTTYPE1_OFFSET, value); } + +static inline uint32_t gpio_intstatus_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTSTATUS_OFFSET); } +static inline void gpio_intstatus_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTSTATUS_OFFSET, value); } + +static inline uint32_t gpio_padcfg0_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG0_OFFSET); } +static inline void gpio_padcfg0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG0_OFFSET, value); } + +static inline uint32_t gpio_padcfg1_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG1_OFFSET); } +static inline void gpio_padcfg1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG1_OFFSET, value); } + +static inline uint32_t gpio_padcfg2_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG2_OFFSET); } +static inline void gpio_padcfg2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG2_OFFSET, value); } + +static inline uint32_t gpio_padcfg3_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG3_OFFSET); } +static inline void gpio_padcfg3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG3_OFFSET, value); } + +static inline uint32_t gpio_paddir_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADDIR_32_63_OFFSET); } +static inline void gpio_paddir_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADDIR_32_63_OFFSET, value); } + +static inline uint32_t gpio_gpioen_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_GPIOEN_32_63_OFFSET); } +static inline void gpio_gpioen_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_GPIOEN_32_63_OFFSET, value); } + +static inline uint32_t gpio_padin_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADIN_32_63_OFFSET); } +static inline void gpio_padin_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADIN_32_63_OFFSET, value); } + +static inline uint32_t gpio_padout_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUT_32_63_OFFSET); } +static inline void gpio_padout_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUT_32_63_OFFSET, value); } + +static inline uint32_t gpio_padoutset_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUTSET_32_63_OFFSET); } +static inline void gpio_padoutset_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUTSET_32_63_OFFSET, value); } + +static inline uint32_t gpio_padoutclr_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADOUTCLR_32_63_OFFSET); } +static inline void gpio_padoutclr_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADOUTCLR_32_63_OFFSET, value); } + +static inline uint32_t gpio_inten_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTEN_32_63_OFFSET); } +static inline void gpio_inten_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTEN_32_63_OFFSET, value); } + +static inline uint32_t gpio_inttype_32_47_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTTYPE_32_47_OFFSET); } +static inline void gpio_inttype_32_47_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTTYPE_32_47_OFFSET, value); } + +static inline uint32_t gpio_inttype_48_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTTYPE_48_63_OFFSET); } +static inline void gpio_inttype_48_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTTYPE_48_63_OFFSET, value); } + +static inline uint32_t gpio_intstatus_32_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_INTSTATUS_32_63_OFFSET); } +static inline void gpio_intstatus_32_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_INTSTATUS_32_63_OFFSET, value); } + +static inline uint32_t gpio_padcfg_32_39_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG_32_39_OFFSET); } +static inline void gpio_padcfg_32_39_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG_32_39_OFFSET, value); } + +static inline uint32_t gpio_padcfg_40_47_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG_40_47_OFFSET); } +static inline void gpio_padcfg_40_47_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG_40_47_OFFSET, value); } + +static inline uint32_t gpio_padcfg_48_55_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG_48_55_OFFSET); } +static inline void gpio_padcfg_48_55_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG_48_55_OFFSET, value); } + +static inline uint32_t gpio_padcfg_56_63_get(uint32_t base) { return ARCHI_READ(base, GPIO_PADCFG_56_63_OFFSET); } +static inline void gpio_padcfg_56_63_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, GPIO_PADCFG_56_63_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define GPIO_PADDIR_DIR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADDIR_DIR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADDIR_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADDIR_DIR(val) ((val) << 0) + +#define GPIO_GPIOEN_GPIOEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_GPIOEN_GPIOEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_GPIOEN_GPIOEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_GPIOEN_GPIOEN(val) ((val) << 0) + +#define GPIO_PADIN_DATA_IN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADIN_DATA_IN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADIN_DATA_IN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADIN_DATA_IN(val) ((val) << 0) + +#define GPIO_PADOUT_DATA_OUT_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUT_DATA_OUT_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUT_DATA_OUT_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUT_DATA_OUT(val) ((val) << 0) + +#define GPIO_PADOUTSET_DATA_SET_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUTSET_DATA_SET_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUTSET_DATA_SET_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUTSET_DATA_SET(val) ((val) << 0) + +#define GPIO_PADOUTCLR_DATA_CLEAR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUTCLR_DATA_CLEAR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUTCLR_DATA_CLEAR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUTCLR_DATA_CLEAR(val) ((val) << 0) + +#define GPIO_INTEN_INTEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTEN_INTEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTEN_INTEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTEN_INTEN(val) ((val) << 0) + +#define GPIO_INTTYPE0_INTTYPE0_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTTYPE0_INTTYPE0_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTTYPE0_INTTYPE0_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTTYPE0_INTTYPE0(val) ((val) << 0) + +#define GPIO_INTTYPE1_INTTYPE1_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTTYPE1_INTTYPE1_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTTYPE1_INTTYPE1_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTTYPE1_INTTYPE1(val) ((val) << 0) + +#define GPIO_INTSTATUS_INTSTATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTSTATUS_INTSTATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTSTATUS_INTSTATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTSTATUS_INTSTATUS(val) ((val) << 0) + +#define GPIO_PADCFG0_GPIO0_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define GPIO_PADCFG0_GPIO0_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define GPIO_PADCFG0_GPIO0_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define GPIO_PADCFG0_GPIO0_CFG(val) ((val) << 0) + +#define GPIO_PADCFG0_GPIO1_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,4)) +#define GPIO_PADCFG0_GPIO1_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,4)) +#define GPIO_PADCFG0_GPIO1_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,4)) +#define GPIO_PADCFG0_GPIO1_CFG(val) ((val) << 4) + +#define GPIO_PADCFG0_GPIO2_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,8)) +#define GPIO_PADCFG0_GPIO2_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,8)) +#define GPIO_PADCFG0_GPIO2_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,8)) +#define GPIO_PADCFG0_GPIO2_CFG(val) ((val) << 8) + +#define GPIO_PADCFG0_GPIO3_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,12)) +#define GPIO_PADCFG0_GPIO3_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,12)) +#define GPIO_PADCFG0_GPIO3_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,12)) +#define GPIO_PADCFG0_GPIO3_CFG(val) ((val) << 12) + +#define GPIO_PADCFG0_GPIO4_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,16)) +#define GPIO_PADCFG0_GPIO4_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,16)) +#define GPIO_PADCFG0_GPIO4_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,16)) +#define GPIO_PADCFG0_GPIO4_CFG(val) ((val) << 16) + +#define GPIO_PADCFG0_GPIO5_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,20)) +#define GPIO_PADCFG0_GPIO5_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,20)) +#define GPIO_PADCFG0_GPIO5_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,20)) +#define GPIO_PADCFG0_GPIO5_CFG(val) ((val) << 20) + +#define GPIO_PADCFG0_GPIO6_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,24)) +#define GPIO_PADCFG0_GPIO6_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,24)) +#define GPIO_PADCFG0_GPIO6_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,24)) +#define GPIO_PADCFG0_GPIO6_CFG(val) ((val) << 24) + +#define GPIO_PADCFG0_GPIO7_CFG_GET(value) (ARCHI_BEXTRACTU((value),4,28)) +#define GPIO_PADCFG0_GPIO7_CFG_GETS(value) (ARCHI_BEXTRACT((value),4,28)) +#define GPIO_PADCFG0_GPIO7_CFG_SET(value,field) (ARCHI_BINSERT((value),(field),4,28)) +#define GPIO_PADCFG0_GPIO7_CFG(val) ((val) << 28) + +#define GPIO_PADCFG1_GPIO4_PE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define GPIO_PADCFG1_GPIO4_PE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define GPIO_PADCFG1_GPIO4_PE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define GPIO_PADCFG1_GPIO4_PE(val) ((val) << 0) + +#define GPIO_PADCFG1_GPIO4_DS_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define GPIO_PADCFG1_GPIO4_DS_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define GPIO_PADCFG1_GPIO4_DS_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define GPIO_PADCFG1_GPIO4_DS(val) ((val) << 1) + +#define GPIO_PADDIR_32_63_DIR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADDIR_32_63_DIR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADDIR_32_63_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADDIR_32_63_DIR(val) ((val) << 0) + +#define GPIO_GPIOEN_32_63_GPIOEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_GPIOEN_32_63_GPIOEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_GPIOEN_32_63_GPIOEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_GPIOEN_32_63_GPIOEN(val) ((val) << 0) + +#define GPIO_PADIN_32_63_DATA_IN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADIN_32_63_DATA_IN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADIN_32_63_DATA_IN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADIN_32_63_DATA_IN(val) ((val) << 0) + +#define GPIO_PADOUT_32_63_DATA_OUT_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUT_32_63_DATA_OUT_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUT_32_63_DATA_OUT_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUT_32_63_DATA_OUT(val) ((val) << 0) + +#define GPIO_PADOUTSET_32_63_DATA_SET_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUTSET_32_63_DATA_SET_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUTSET_32_63_DATA_SET_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUTSET_32_63_DATA_SET(val) ((val) << 0) + +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_PADOUTCLR_32_63_DATA_CLEAR(val) ((val) << 0) + +#define GPIO_INTEN_32_63_INTEN_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTEN_32_63_INTEN_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTEN_32_63_INTEN_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTEN_32_63_INTEN(val) ((val) << 0) + +#define GPIO_INTTYPE_32_47_INTTYPE0_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTTYPE_32_47_INTTYPE0_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTTYPE_32_47_INTTYPE0_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTTYPE_32_47_INTTYPE0(val) ((val) << 0) + +#define GPIO_INTTYPE_48_63_INTTYPE1_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTTYPE_48_63_INTTYPE1_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTTYPE_48_63_INTTYPE1_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTTYPE_48_63_INTTYPE1(val) ((val) << 0) + +#define GPIO_INTSTATUS_32_63_INTSTATUS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define GPIO_INTSTATUS_32_63_INTSTATUS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define GPIO_INTSTATUS_32_63_INTSTATUS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define GPIO_INTSTATUS_32_63_INTSTATUS(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/gvsoc/gvsoc.h b/sw/pulp-sdk/archi/include/archi/gvsoc/gvsoc.h new file mode 100644 index 0000000..85a3dee --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/gvsoc/gvsoc.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna and GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_GVSOC_GVSOC_H__ +#define __ARCHI_GVSOC_GVSOC_H__ + +#define GV_SEMIHOSTING_FIRST_CUSTOM 0x1000 + +#define GV_SEMIHOSTING_VCD_CONFIGURE 0x1000 +#define GV_SEMIHOSTING_VCD_OPEN_TRACE 0x1001 +#define GV_SEMIHOSTING_VCD_CONF_TRACE 0x1002 +#define GV_SEMIHOSTING_VCD_DUMP_TRACE 0x1003 +#define GV_SEMIHOSTING_VCD_DUMP_TRACE_STRING 0x1004 + +#define GV_SEMIHOSTING_TRACE_OPEN 0x1010 +#define GV_SEMIHOSTING_TRACE_ENABLE 0x1011 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4.h b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4.h new file mode 100644 index 0000000..d1c79b7 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4.h @@ -0,0 +1,1806 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_HWCE_HWCE_V4_H__ +#define __INCLUDE_ARCHI_HWCE_HWCE_V4_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Trigger the execution of an offloaded job +#define HWCE_TRIGGER_OFFSET 0x0 + +// Acquire the lock to offload job +#define HWCE_ACQUIRE_OFFSET 0x4 + +// Number of concluded jobs since last read +#define HWCE_FINISHED_JOBS_OFFSET 0x8 + +// Status of the HWCE +#define HWCE_STATUS_OFFSET 0xc + +// ID of the currently running job +#define HWCE_RUNNING_JOB_OFFSET 0x10 + +// Reset HWCE to known idle state +#define HWCE_SOFT_CLEAR_OFFSET 0x14 + +// Generic configuration register 0 +#define HWCE_GEN_CONFIG0_OFFSET 0x20 + +// Generic configuration register 1 +#define HWCE_GEN_CONFIG1_OFFSET 0x24 + +// Total number of words to be read for yin and yout +#define HWCE_Y_TRANS_SIZE_OFFSET 0x40 + +// Line stride and length for yin and yout +#define HWCE_Y_LINE_STRIDE_LENGTH_OFFSET 0x44 + +// Feature (block) stride and length for yin and yout +#define HWCE_Y_FEAT_STRIDE_LENGTH_OFFSET 0x48 + +// Base address of yout[3] +#define HWCE_Y_OUT_3_BASE_ADDR_OFFSET 0x4c + +// Base address of yout[2] +#define HWCE_Y_OUT_2_BASE_ADDR_OFFSET 0x50 + +// Base address of yout[1] +#define HWCE_Y_OUT_1_BASE_ADDR_OFFSET 0x54 + +// Base address of yout[0] +#define HWCE_Y_OUT_0_BASE_ADDR_OFFSET 0x58 + +// Base address of yin[3] +#define HWCE_Y_IN_3_BASE_ADDR_OFFSET 0x5c + +// Base address of yin[2] +#define HWCE_Y_IN_2_BASE_ADDR_OFFSET 0x60 + +// Base address of yin[1] +#define HWCE_Y_IN_1_BASE_ADDR_OFFSET 0x64 + +// Base address of yin[0] +#define HWCE_Y_IN_0_BASE_ADDR_OFFSET 0x68 + +// Total number of words to be read for xin +#define HWCE_X_TRANS_SIZE_OFFSET 0x6c + +// Line stride and length for xin +#define HWCE_X_LINE_STRIDE_LENGTH_OFFSET 0x70 + +// Feature (block) stride and length for xin +#define HWCE_X_FEAT_STRIDE_LENGTH_OFFSET 0x74 + +// Base address of xin +#define HWCE_X_IN_BASE_ADDR_OFFSET 0x78 + +// Base address of W +#define HWCE_W_BASE_ADDR_OFFSET 0x7c + +// Job configuration register 0 +#define HWCE_JOB_CONFIG0_OFFSET 0x80 + +// Job configuration register 1 +#define HWCE_JOB_CONFIG1_OFFSET 0x84 + +// Total number of words to be read for yin and yout +#define HWCE_Y_TRANS_SIZE_CTX0_OFFSET 0x140 + +// Line stride and length for yin and yout +#define HWCE_Y_LINE_STRIDE_LENGTH_CTX0_OFFSET 0x144 + +// Feature (block) stride and length for yin and yout +#define HWCE_Y_FEAT_STRIDE_LENGTH_CTX0_OFFSET 0x148 + +// Base address of yout[3] +#define HWCE_Y_OUT_3_BASE_ADDR_CTX0_OFFSET 0x14c + +// Base address of yout[2] +#define HWCE_Y_OUT_2_BASE_ADDR_CTX0_OFFSET 0x150 + +// Base address of yout[1] +#define HWCE_Y_OUT_1_BASE_ADDR_CTX0_OFFSET 0x154 + +// Base address of yout[0] +#define HWCE_Y_OUT_0_BASE_ADDR_CTX0_OFFSET 0x158 + +// Base address of yin[3] +#define HWCE_Y_IN_3_BASE_ADDR_CTX0_OFFSET 0x15c + +// Base address of yin[2] +#define HWCE_Y_IN_2_BASE_ADDR_CTX0_OFFSET 0x160 + +// Base address of yin[1] +#define HWCE_Y_IN_1_BASE_ADDR_CTX0_OFFSET 0x164 + +// Base address of yin[0] +#define HWCE_Y_IN_0_BASE_ADDR_CTX0_OFFSET 0x168 + +// Total number of words to be read for xin +#define HWCE_X_TRANS_SIZE_CTX0_OFFSET 0x16c + +// Line stride and length for xin +#define HWCE_X_LINE_STRIDE_LENGTH_CTX0_OFFSET 0x170 + +// Feature (block) stride and length for xin +#define HWCE_X_FEAT_STRIDE_LENGTH_CTX0_OFFSET 0x174 + +// Base address of xin +#define HWCE_X_IN_BASE_ADDR_CTX0_OFFSET 0x178 + +// Base address of W +#define HWCE_W_BASE_ADDR_CTX0_OFFSET 0x17c + +// Job configuration register 0 +#define HWCE_JOB_CONFIG0_CTX0_OFFSET 0x180 + +// Job configuration register 1 +#define HWCE_JOB_CONFIG1_CTX0_OFFSET 0x184 + +// Total number of words to be read for yin and yout +#define HWCE_Y_TRANS_SIZE_CTX1_OFFSET 0x240 + +// Line stride and length for yin and yout +#define HWCE_Y_LINE_STRIDE_LENGTH_CTX1_OFFSET 0x244 + +// Feature (block) stride and length for yin and yout +#define HWCE_Y_FEAT_STRIDE_LENGTH_CTX1_OFFSET 0x248 + +// Base address of yout[3] +#define HWCE_Y_OUT_3_BASE_ADDR_CTX1_OFFSET 0x24c + +// Base address of yout[2] +#define HWCE_Y_OUT_2_BASE_ADDR_CTX1_OFFSET 0x250 + +// Base address of yout[1] +#define HWCE_Y_OUT_1_BASE_ADDR_CTX1_OFFSET 0x254 + +// Base address of yout[0] +#define HWCE_Y_OUT_0_BASE_ADDR_CTX1_OFFSET 0x258 + +// Base address of yin[3] +#define HWCE_Y_IN_3_BASE_ADDR_CTX1_OFFSET 0x25c + +// Base address of yin[2] +#define HWCE_Y_IN_2_BASE_ADDR_CTX1_OFFSET 0x260 + +// Base address of yin[1] +#define HWCE_Y_IN_1_BASE_ADDR_CTX1_OFFSET 0x264 + +// Base address of yin[0] +#define HWCE_Y_IN_0_BASE_ADDR_CTX1_OFFSET 0x268 + +// Total number of words to be read for xin +#define HWCE_X_TRANS_SIZE_CTX1_OFFSET 0x26c + +// Line stride and length for xin +#define HWCE_X_LINE_STRIDE_LENGTH_CTX1_OFFSET 0x270 + +// Feature (block) stride and length for xin +#define HWCE_X_FEAT_STRIDE_LENGTH_CTX1_OFFSET 0x274 + +// Base address of xin +#define HWCE_X_IN_BASE_ADDR_CTX1_OFFSET 0x278 + +// Base address of W +#define HWCE_W_BASE_ADDR_CTX1_OFFSET 0x27c + +// Job configuration register 0 +#define HWCE_JOB_CONFIG0_CTX1_OFFSET 0x280 + +// Job configuration register 1 +#define HWCE_JOB_CONFIG1_CTX1_OFFSET 0x284 + + + +// +// REGISTERS FIELDS +// + +// Write of any value will close the current offload phase by releasing the job offload lock and inserting the currently offloaded job in the control queue. (access: W) +#define HWCE_TRIGGER_ANY_BIT 0 +#define HWCE_TRIGGER_ANY_WIDTH 32 +#define HWCE_TRIGGER_ANY_MASK 0xffffffff + +// If ERR is 0 then the ID of the offloaded job. Otherwise, part of the error code (access: R) +#define HWCE_ACQUIRE_ID_ERR_BIT 0 +#define HWCE_ACQUIRE_ID_ERR_WIDTH 8 +#define HWCE_ACQUIRE_ID_ERR_MASK 0xff + +// An error code if one of the following conditions apply: 1. if the context copy is going on, it will answer 0xfffffffd (-3) 2. else, if the job offload lock has been established, it will answer 0xfffffffe (-2) 3. else, if the job queue is full, it will answer 0xffffffff (-1) (access: R) +#define HWCE_ACQUIRE_ERR_BIT 8 +#define HWCE_ACQUIRE_ERR_WIDTH 24 +#define HWCE_ACQUIRE_ERR_MASK 0xffffff00 + +// The number of jobs that the HWCE executed and finished since the last time the same FINISHED_JOBS register was accessed. A read to FINISHED_JOBS returns: - 0x0 if no job was completed since the last access - 0x1 if a single job was completed since the last access - 0x2 if two or more jobs were completed since the last access (access: R) +#define HWCE_FINISHED_JOBS_JOBS_BIT 0 +#define HWCE_FINISHED_JOBS_JOBS_WIDTH 32 +#define HWCE_FINISHED_JOBS_JOBS_MASK 0xffffffff + +// Status of the HWCE - 1'b0 Not running a job - 1'b1 Running a job (access: R) +#define HWCE_STATUS_ST_BIT 0 +#define HWCE_STATUS_ST_WIDTH 1 +#define HWCE_STATUS_ST_MASK 0x1 + +// ID of the currently running job (access: R) +#define HWCE_RUNNING_JOB_ID_BIT 0 +#define HWCE_RUNNING_JOB_ID_WIDTH 8 +#define HWCE_RUNNING_JOB_ID_MASK 0xff + +// A write of any value to this register will reset the HWCE to its idle state. (access: W) +#define HWCE_SOFT_CLEAR_ANY_BIT 0 +#define HWCE_SOFT_CLEAR_ANY_WIDTH 32 +#define HWCE_SOFT_CLEAR_ANY_MASK 0xffffffff + +// Fixed-point format. Pixels will be shifted to the right by QF bits in the normalization step after the sum-of-products stage. (access: R/W) +#define HWCE_GEN_CONFIG0_QF_BIT 0 +#define HWCE_GEN_CONFIG0_QF_WIDTH 6 +#define HWCE_GEN_CONFIG0_QF_MASK 0x3f + +// Operation type: - 1'b0 - Normal convolution - 1'b1 - Does not flip weights (i.e. implements a stencil instead of a mathematical convolution). (access: R/W) +#define HWCE_GEN_CONFIG0_NF_BIT 6 +#define HWCE_GEN_CONFIG0_NF_WIDTH 1 +#define HWCE_GEN_CONFIG0_NF_MASK 0x40 + +// No y_in mode: - 1'b0 - Normal operation - 1'b1 - Disable loading of y_in and add a constant set in the CONFIG2 register (access: R/W) +#define HWCE_GEN_CONFIG0_NY_BIT 7 +#define HWCE_GEN_CONFIG0_NY_WIDTH 1 +#define HWCE_GEN_CONFIG0_NY_MASK 0x80 + +// Set unsigned multiplication - 1'b0 - Consider multiplication results as signed fixed-point numbers. - 1'b1 - Consider multiplication results as unsigned fixed-point numbers. (access: R/W) +#define HWCE_GEN_CONFIG0_UNS_BIT 8 +#define HWCE_GEN_CONFIG0_UNS_WIDTH 1 +#define HWCE_GEN_CONFIG0_UNS_MASK 0x100 + +// Vector mode: - 2'b00 - mode is scalar (1 feat/cycle, 1x16-bit weights). - 2'b01 - mode is vectorial 2 (2 feat/cycle, 2x8-bit weights). - 2'b10 - mode is vectorial 4 (4 feat/cycle, 4x4-bit weights). (access: R/W) +#define HWCE_GEN_CONFIG0_VECT_BIT 9 +#define HWCE_GEN_CONFIG0_VECT_WIDTH 2 +#define HWCE_GEN_CONFIG0_VECT_MASK 0x600 + +// Convolution mode: - 2'b00 - mode is 5x5. - 2'b01 - mode is 3x3. - 2'b10 - mode is 4x7. (access: R/W) +#define HWCE_GEN_CONFIG0_CONV_BIT 11 +#define HWCE_GEN_CONFIG0_CONV_WIDTH 2 +#define HWCE_GEN_CONFIG0_CONV_MASK 0x1800 + +// No job copy: - 1'b0 - do job copy - 1'b1 - don't do job copy (access: R/W) +#define HWCE_GEN_CONFIG0_NCP_BIT 13 +#define HWCE_GEN_CONFIG0_NCP_WIDTH 1 +#define HWCE_GEN_CONFIG0_NCP_MASK 0x2000 + +// Stride between one FILTER_SIZExFILTER_SIZE filter and the next. (access: R/W) +#define HWCE_GEN_CONFIG0_WSTRIDE_BIT 16 +#define HWCE_GEN_CONFIG0_WSTRIDE_WIDTH 16 +#define HWCE_GEN_CONFIG0_WSTRIDE_MASK 0xffff0000 + +// Shift input pixels to the left by this number of positions when PIXMODE is not 16bit. (access: R/W) +#define HWCE_GEN_CONFIG1_PIXSHIFTL_BIT 0 +#define HWCE_GEN_CONFIG1_PIXSHIFTL_WIDTH 5 +#define HWCE_GEN_CONFIG1_PIXSHIFTL_MASK 0x1f + +// Input pixel size - 2'b00 16bit - 2'b01 - 8bit - 2'b10 - 4bit - 2'b11 16bit bis (access: R/W) +#define HWCE_GEN_CONFIG1_PIXMODE_BIT 8 +#define HWCE_GEN_CONFIG1_PIXMODE_WIDTH 2 +#define HWCE_GEN_CONFIG1_PIXMODE_MASK 0x300 + +// Shift output pixels to the right by this number of positions when PIXMODE is not 16bit. (access: R/W) +#define HWCE_GEN_CONFIG1_PIXSHIFTR_BIT 16 +#define HWCE_GEN_CONFIG1_PIXSHIFTR_WIDTH 5 +#define HWCE_GEN_CONFIG1_PIXSHIFTR_MASK 0x1f0000 + +// Contains the total number of words (i.e. double 16bit pixels, quad 8bit pixels, etc.) to be read / written by the streaming source and sink interfaces for yin and yout streams. (access: R/W) +#define HWCE_Y_TRANS_SIZE_SIZE_BIT 0 +#define HWCE_Y_TRANS_SIZE_SIZE_WIDTH 32 +#define HWCE_Y_TRANS_SIZE_SIZE_MASK 0xffffffff + +// Length of a line in number of words (access: R/W) +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_BIT 0 +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_WIDTH 16 +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_MASK 0xffff + +// Distance in bytes between two consecutive lines. (access: R/W) +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_BIT 16 +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_WIDTH 16 +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_MASK 0xffff0000 + +// Length of a line in number of words (access: R/W) +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_BIT 0 +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_WIDTH 16 +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_MASK 0xffff + +// Distance in bytes between two consecutive lines. (access: R/W) +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_BIT 16 +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_WIDTH 16 +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_MASK 0xffff0000 + +// Pointer into cluster L1 memory (4x4 bit mode) (access: R/W) +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit mode) (access: R/W) +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit and 2x8 bit modes) (access: R/W) +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit, 2x8 bit and 1x16 bit modes) (access: R/W) +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit mode) (access: R/W) +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit mode) (access: R/W) +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit and 2x8 bit modes) (access: R/W) +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (4x4 bit, 2x8 bit and 1x16 bit modes) (access: R/W) +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_BIT 0 +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_MASK 0xffffffff + +// Contains the total number of words (i.e. double 16bit pixels, quad 8bit pixels, etc.) to be read / written by the streaming source interface for the xin stream. (access: R/W) +#define HWCE_X_TRANS_SIZE_SIZE_BIT 0 +#define HWCE_X_TRANS_SIZE_SIZE_WIDTH 32 +#define HWCE_X_TRANS_SIZE_SIZE_MASK 0xffffffff + +// Length of a line in number of words (access: R/W) +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_BIT 0 +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_WIDTH 16 +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_MASK 0xffff + +// Distance in bytes between two consecutive lines. (access: R/W) +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_BIT 16 +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_WIDTH 16 +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_MASK 0xffff0000 + +// Length of a line in number of words (access: R/W) +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_BIT 0 +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_WIDTH 16 +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_MASK 0xffff + +// Distance in bytes between two consecutive lines. (access: R/W) +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_BIT 16 +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_WIDTH 16 +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_MASK 0xffff0000 + +// Pointer into cluster L1 memory (access: R/W) +#define HWCE_X_IN_BASE_ADDR_ADDR_BIT 0 +#define HWCE_X_IN_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_X_IN_BASE_ADDR_ADDR_MASK 0xffffffff + +// Pointer into cluster L1 memory (access: R/W) +#define HWCE_W_BASE_ADDR_ADDR_BIT 0 +#define HWCE_W_BASE_ADDR_ADDR_WIDTH 32 +#define HWCE_W_BASE_ADDR_ADDR_MASK 0xffffffff + +// Linebuffer virtual length. Set to the same number as X_LINE_LENGTH. Acceptable LBUFLEN values range between 2 and LINEBUF_LENGTH. (access: R/W) +#define HWCE_JOB_CONFIG0_LBUFLEN_BIT 0 +#define HWCE_JOB_CONFIG0_LBUFLEN_WIDTH 10 +#define HWCE_JOB_CONFIG0_LBUFLEN_MASK 0x3ff + +// Constant to sum instead of yin if the NY flag is active in the CONFIG1 register. (access: R/W) +#define HWCE_JOB_CONFIG0_NOYCONST_BIT 16 +#define HWCE_JOB_CONFIG0_NOYCONST_WIDTH 16 +#define HWCE_JOB_CONFIG0_NOYCONST_MASK 0xffff0000 + +// Vector mode mask. Defaults to 0x0, which means that all vectors are enabled. Can be used to disable unused vector routes when using approximate vector or 3x3 mode. The bits are reversed in order, so bit 3 indicates vector 0, bit 2 vector 1, etc. (access: R/W) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_BIT 0 +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_WIDTH 4 +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_MASK 0xf + +// Output feature (OF) counter wrap parameter. If both WIF and WOF are 1'b0, the looping mechanism is disabled (access: R/W) +#define HWCE_JOB_CONFIG1_WOF_PARAM_BIT 8 +#define HWCE_JOB_CONFIG1_WOF_PARAM_WIDTH 6 +#define HWCE_JOB_CONFIG1_WOF_PARAM_MASK 0x3f00 + +// Input feature (IF) counter wrap parameter. If both WIF and WOF are 1'b0, the looping mechanism is disabled (access: R/W) +#define HWCE_JOB_CONFIG1_WIF_PARAM_BIT 16 +#define HWCE_JOB_CONFIG1_WIF_PARAM_WIDTH 6 +#define HWCE_JOB_CONFIG1_WIF_PARAM_MASK 0x3f0000 + +// Loop order: - 1'b0 - output features (OF) are the outer loop - 1'b1 - input features (IF) are the outer loop (access: R/W) +#define HWCE_JOB_CONFIG1_LO_BIT 24 +#define HWCE_JOB_CONFIG1_LO_WIDTH 1 +#define HWCE_JOB_CONFIG1_LO_MASK 0x1000000 + +// Looping mechanism: - 1'b0 - both counters work as inner loops - 1'b1 - outer loop feature address is updated only when the feature counter reaches the wrap parameter, inner loop feature address is updated when the counter is less than the wrap parameter and reset when it is reached (access: R/W) +#define HWCE_JOB_CONFIG1_LN_BIT 25 +#define HWCE_JOB_CONFIG1_LN_WIDTH 1 +#define HWCE_JOB_CONFIG1_LN_MASK 0x2000000 + + + +// +// REGISTERS STRUCTS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef union { + struct { + unsigned int any :32; // Write of any value will close the current offload phase by releasing the job offload lock and inserting the currently offloaded job in the control queue. + }; + unsigned int raw; +} __attribute__((packed)) hwce_trigger_t; + +typedef union { + struct { + unsigned int id_err :8 ; // If ERR is 0 then the ID of the offloaded job. Otherwise, part of the error code + unsigned int err :24; // An error code if one of the following conditions apply: 1. if the context copy is going on, it will answer 0xfffffffd (-3) 2. else, if the job offload lock has been established, it will answer 0xfffffffe (-2) 3. else, if the job queue is full, it will answer 0xffffffff (-1) + }; + unsigned int raw; +} __attribute__((packed)) hwce_acquire_t; + +typedef union { + struct { + unsigned int jobs :32; // The number of jobs that the HWCE executed and finished since the last time the same FINISHED_JOBS register was accessed. A read to FINISHED_JOBS returns: - 0x0 if no job was completed since the last access - 0x1 if a single job was completed since the last access - 0x2 if two or more jobs were completed since the last access + }; + unsigned int raw; +} __attribute__((packed)) hwce_finished_jobs_t; + +typedef union { + struct { + unsigned int st :1 ; // Status of the HWCE - 1'b0 Not running a job - 1'b1 Running a job + }; + unsigned int raw; +} __attribute__((packed)) hwce_status_t; + +typedef union { + struct { + unsigned int id :8 ; // ID of the currently running job + }; + unsigned int raw; +} __attribute__((packed)) hwce_running_job_t; + +typedef union { + struct { + unsigned int any :32; // A write of any value to this register will reset the HWCE to its idle state. + }; + unsigned int raw; +} __attribute__((packed)) hwce_soft_clear_t; + +typedef union { + struct { + unsigned int qf :6 ; // Fixed-point format. Pixels will be shifted to the right by QF bits in the normalization step after the sum-of-products stage. + unsigned int nf :1 ; // Operation type: - 1'b0 - Normal convolution - 1'b1 - Does not flip weights (i.e. implements a stencil instead of a mathematical convolution). + unsigned int ny :1 ; // No y_in mode: - 1'b0 - Normal operation - 1'b1 - Disable loading of y_in and add a constant set in the CONFIG2 register + unsigned int uns :1 ; // Set unsigned multiplication - 1'b0 - Consider multiplication results as signed fixed-point numbers. - 1'b1 - Consider multiplication results as unsigned fixed-point numbers. + unsigned int vect :2 ; // Vector mode: - 2'b00 - mode is scalar (1 feat/cycle, 1x16-bit weights). - 2'b01 - mode is vectorial 2 (2 feat/cycle, 2x8-bit weights). - 2'b10 - mode is vectorial 4 (4 feat/cycle, 4x4-bit weights). + unsigned int conv :2 ; // Convolution mode: - 2'b00 - mode is 5x5. - 2'b01 - mode is 3x3. - 2'b10 - mode is 4x7. + unsigned int ncp :1 ; // No job copy: - 1'b0 - do job copy - 1'b1 - don't do job copy + unsigned int padding0:2 ; + unsigned int wstride :16; // Stride between one FILTER_SIZExFILTER_SIZE filter and the next. + }; + unsigned int raw; +} __attribute__((packed)) hwce_gen_config0_t; + +typedef union { + struct { + unsigned int pixshiftl :5 ; // Shift input pixels to the left by this number of positions when PIXMODE is not 16bit. + unsigned int padding0:3 ; + unsigned int pixmode :2 ; // Input pixel size - 2'b00 16bit - 2'b01 - 8bit - 2'b10 - 4bit - 2'b11 16bit bis + unsigned int padding1:6 ; + unsigned int pixshiftr :5 ; // Shift output pixels to the right by this number of positions when PIXMODE is not 16bit. + }; + unsigned int raw; +} __attribute__((packed)) hwce_gen_config1_t; + +typedef union { + struct { + unsigned int size :32; // Contains the total number of words (i.e. double 16bit pixels, quad 8bit pixels, etc.) to be read / written by the streaming source and sink interfaces for yin and yout streams. + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_trans_size_t; + +typedef union { + struct { + unsigned int length :16; // Length of a line in number of words + unsigned int stride :16; // Distance in bytes between two consecutive lines. + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_line_stride_length_t; + +typedef union { + struct { + unsigned int length :16; // Length of a line in number of words + unsigned int stride :16; // Distance in bytes between two consecutive lines. + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_feat_stride_length_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit mode) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_3_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit mode) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_2_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit and 2x8 bit modes) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_1_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit, 2x8 bit and 1x16 bit modes) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_0_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit mode) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_3_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit mode) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_2_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit and 2x8 bit modes) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_1_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory (4x4 bit, 2x8 bit and 1x16 bit modes) + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_0_base_addr_t; + +typedef union { + struct { + unsigned int size :32; // Contains the total number of words (i.e. double 16bit pixels, quad 8bit pixels, etc.) to be read / written by the streaming source interface for the xin stream. + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_trans_size_t; + +typedef union { + struct { + unsigned int length :16; // Length of a line in number of words + unsigned int stride :16; // Distance in bytes between two consecutive lines. + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_line_stride_length_t; + +typedef union { + struct { + unsigned int length :16; // Length of a line in number of words + unsigned int stride :16; // Distance in bytes between two consecutive lines. + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_feat_stride_length_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_in_base_addr_t; + +typedef union { + struct { + unsigned int addr :32; // Pointer into cluster L1 memory + }; + unsigned int raw; +} __attribute__((packed)) hwce_w_base_addr_t; + +typedef union { + struct { + unsigned int lbuflen :10; // Linebuffer virtual length. Set to the same number as X_LINE_LENGTH. Acceptable LBUFLEN values range between 2 and LINEBUF_LENGTH. + unsigned int padding0:6 ; + unsigned int noyconst :16; // Constant to sum instead of yin if the NY flag is active in the CONFIG1 register. + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config0_t; + +typedef union { + struct { + unsigned int vect_disable_mask:4 ; // Vector mode mask. Defaults to 0x0, which means that all vectors are enabled. Can be used to disable unused vector routes when using approximate vector or 3x3 mode. The bits are reversed in order, so bit 3 indicates vector 0, bit 2 vector 1, etc. + unsigned int padding0:4 ; + unsigned int wof_param :6 ; // Output feature (OF) counter wrap parameter. If both WIF and WOF are 1'b0, the looping mechanism is disabled + unsigned int padding1:2 ; + unsigned int wif_param :6 ; // Input feature (IF) counter wrap parameter. If both WIF and WOF are 1'b0, the looping mechanism is disabled + unsigned int padding2:2 ; + unsigned int lo :1 ; // Loop order: - 1'b0 - output features (OF) are the outer loop - 1'b1 - input features (IF) are the outer loop + unsigned int ln :1 ; // Looping mechanism: - 1'b0 - both counters work as inner loops - 1'b1 - outer loop feature address is updated only when the feature counter reaches the wrap parameter, inner loop feature address is updated when the counter is less than the wrap parameter and reset when it is reached + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_trans_size_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_line_stride_length_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_feat_stride_length_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_3_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_2_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_1_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_0_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_3_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_2_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_1_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_0_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_trans_size_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_line_stride_length_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_feat_stride_length_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_in_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_w_base_addr_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config0_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config1_ctx0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_trans_size_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_line_stride_length_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_feat_stride_length_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_3_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_2_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_1_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_out_0_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_3_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_2_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_1_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_y_in_0_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_trans_size_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_line_stride_length_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_feat_stride_length_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_x_in_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_w_base_addr_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config0_ctx1_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hwce_job_config1_ctx1_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_hwce_trigger : public vp::reg_32 +{ +public: + inline void any_set(uint32_t value) { this->set_field(value, HWCE_TRIGGER_ANY_BIT, HWCE_TRIGGER_ANY_WIDTH); } + inline uint32_t any_get() { return this->get_field(HWCE_TRIGGER_ANY_BIT, HWCE_TRIGGER_ANY_WIDTH); } +}; + +class vp_hwce_acquire : public vp::reg_32 +{ +public: + inline void id_err_set(uint32_t value) { this->set_field(value, HWCE_ACQUIRE_ID_ERR_BIT, HWCE_ACQUIRE_ID_ERR_WIDTH); } + inline uint32_t id_err_get() { return this->get_field(HWCE_ACQUIRE_ID_ERR_BIT, HWCE_ACQUIRE_ID_ERR_WIDTH); } + inline void err_set(uint32_t value) { this->set_field(value, HWCE_ACQUIRE_ERR_BIT, HWCE_ACQUIRE_ERR_WIDTH); } + inline uint32_t err_get() { return this->get_field(HWCE_ACQUIRE_ERR_BIT, HWCE_ACQUIRE_ERR_WIDTH); } +}; + +class vp_hwce_finished_jobs : public vp::reg_32 +{ +public: + inline void jobs_set(uint32_t value) { this->set_field(value, HWCE_FINISHED_JOBS_JOBS_BIT, HWCE_FINISHED_JOBS_JOBS_WIDTH); } + inline uint32_t jobs_get() { return this->get_field(HWCE_FINISHED_JOBS_JOBS_BIT, HWCE_FINISHED_JOBS_JOBS_WIDTH); } +}; + +class vp_hwce_status : public vp::reg_32 +{ +public: + inline void st_set(uint32_t value) { this->set_field(value, HWCE_STATUS_ST_BIT, HWCE_STATUS_ST_WIDTH); } + inline uint32_t st_get() { return this->get_field(HWCE_STATUS_ST_BIT, HWCE_STATUS_ST_WIDTH); } +}; + +class vp_hwce_running_job : public vp::reg_32 +{ +public: + inline void id_set(uint32_t value) { this->set_field(value, HWCE_RUNNING_JOB_ID_BIT, HWCE_RUNNING_JOB_ID_WIDTH); } + inline uint32_t id_get() { return this->get_field(HWCE_RUNNING_JOB_ID_BIT, HWCE_RUNNING_JOB_ID_WIDTH); } +}; + +class vp_hwce_soft_clear : public vp::reg_32 +{ +public: + inline void any_set(uint32_t value) { this->set_field(value, HWCE_SOFT_CLEAR_ANY_BIT, HWCE_SOFT_CLEAR_ANY_WIDTH); } + inline uint32_t any_get() { return this->get_field(HWCE_SOFT_CLEAR_ANY_BIT, HWCE_SOFT_CLEAR_ANY_WIDTH); } +}; + +class vp_hwce_gen_config0 : public vp::reg_32 +{ +public: + inline void qf_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_QF_BIT, HWCE_GEN_CONFIG0_QF_WIDTH); } + inline uint32_t qf_get() { return this->get_field(HWCE_GEN_CONFIG0_QF_BIT, HWCE_GEN_CONFIG0_QF_WIDTH); } + inline void nf_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_NF_BIT, HWCE_GEN_CONFIG0_NF_WIDTH); } + inline uint32_t nf_get() { return this->get_field(HWCE_GEN_CONFIG0_NF_BIT, HWCE_GEN_CONFIG0_NF_WIDTH); } + inline void ny_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_NY_BIT, HWCE_GEN_CONFIG0_NY_WIDTH); } + inline uint32_t ny_get() { return this->get_field(HWCE_GEN_CONFIG0_NY_BIT, HWCE_GEN_CONFIG0_NY_WIDTH); } + inline void uns_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_UNS_BIT, HWCE_GEN_CONFIG0_UNS_WIDTH); } + inline uint32_t uns_get() { return this->get_field(HWCE_GEN_CONFIG0_UNS_BIT, HWCE_GEN_CONFIG0_UNS_WIDTH); } + inline void vect_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_VECT_BIT, HWCE_GEN_CONFIG0_VECT_WIDTH); } + inline uint32_t vect_get() { return this->get_field(HWCE_GEN_CONFIG0_VECT_BIT, HWCE_GEN_CONFIG0_VECT_WIDTH); } + inline void conv_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_CONV_BIT, HWCE_GEN_CONFIG0_CONV_WIDTH); } + inline uint32_t conv_get() { return this->get_field(HWCE_GEN_CONFIG0_CONV_BIT, HWCE_GEN_CONFIG0_CONV_WIDTH); } + inline void ncp_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_NCP_BIT, HWCE_GEN_CONFIG0_NCP_WIDTH); } + inline uint32_t ncp_get() { return this->get_field(HWCE_GEN_CONFIG0_NCP_BIT, HWCE_GEN_CONFIG0_NCP_WIDTH); } + inline void wstride_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG0_WSTRIDE_BIT, HWCE_GEN_CONFIG0_WSTRIDE_WIDTH); } + inline uint32_t wstride_get() { return this->get_field(HWCE_GEN_CONFIG0_WSTRIDE_BIT, HWCE_GEN_CONFIG0_WSTRIDE_WIDTH); } +}; + +class vp_hwce_gen_config1 : public vp::reg_32 +{ +public: + inline void pixshiftl_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG1_PIXSHIFTL_BIT, HWCE_GEN_CONFIG1_PIXSHIFTL_WIDTH); } + inline uint32_t pixshiftl_get() { return this->get_field(HWCE_GEN_CONFIG1_PIXSHIFTL_BIT, HWCE_GEN_CONFIG1_PIXSHIFTL_WIDTH); } + inline void pixmode_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG1_PIXMODE_BIT, HWCE_GEN_CONFIG1_PIXMODE_WIDTH); } + inline uint32_t pixmode_get() { return this->get_field(HWCE_GEN_CONFIG1_PIXMODE_BIT, HWCE_GEN_CONFIG1_PIXMODE_WIDTH); } + inline void pixshiftr_set(uint32_t value) { this->set_field(value, HWCE_GEN_CONFIG1_PIXSHIFTR_BIT, HWCE_GEN_CONFIG1_PIXSHIFTR_WIDTH); } + inline uint32_t pixshiftr_get() { return this->get_field(HWCE_GEN_CONFIG1_PIXSHIFTR_BIT, HWCE_GEN_CONFIG1_PIXSHIFTR_WIDTH); } +}; + +class vp_hwce_y_trans_size : public vp::reg_32 +{ +public: + inline void size_set(uint32_t value) { this->set_field(value, HWCE_Y_TRANS_SIZE_SIZE_BIT, HWCE_Y_TRANS_SIZE_SIZE_WIDTH); } + inline uint32_t size_get() { return this->get_field(HWCE_Y_TRANS_SIZE_SIZE_BIT, HWCE_Y_TRANS_SIZE_SIZE_WIDTH); } +}; + +class vp_hwce_y_line_stride_length : public vp::reg_32 +{ +public: + inline void length_set(uint32_t value) { this->set_field(value, HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_BIT, HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_WIDTH); } + inline uint32_t length_get() { return this->get_field(HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_BIT, HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_WIDTH); } + inline void stride_set(uint32_t value) { this->set_field(value, HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_BIT, HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_WIDTH); } + inline uint32_t stride_get() { return this->get_field(HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_BIT, HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_WIDTH); } +}; + +class vp_hwce_y_feat_stride_length : public vp::reg_32 +{ +public: + inline void length_set(uint32_t value) { this->set_field(value, HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_BIT, HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_WIDTH); } + inline uint32_t length_get() { return this->get_field(HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_BIT, HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_WIDTH); } + inline void stride_set(uint32_t value) { this->set_field(value, HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_BIT, HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_WIDTH); } + inline uint32_t stride_get() { return this->get_field(HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_BIT, HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_WIDTH); } +}; + +class vp_hwce_y_out_3_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_OUT_3_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_3_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_OUT_3_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_3_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_out_2_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_OUT_2_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_2_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_OUT_2_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_2_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_out_1_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_OUT_1_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_1_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_OUT_1_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_1_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_out_0_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_OUT_0_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_0_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_OUT_0_BASE_ADDR_ADDR_BIT, HWCE_Y_OUT_0_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_in_3_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_IN_3_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_3_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_IN_3_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_3_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_in_2_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_IN_2_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_2_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_IN_2_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_2_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_in_1_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_IN_1_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_1_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_IN_1_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_1_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_y_in_0_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_Y_IN_0_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_0_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_Y_IN_0_BASE_ADDR_ADDR_BIT, HWCE_Y_IN_0_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_x_trans_size : public vp::reg_32 +{ +public: + inline void size_set(uint32_t value) { this->set_field(value, HWCE_X_TRANS_SIZE_SIZE_BIT, HWCE_X_TRANS_SIZE_SIZE_WIDTH); } + inline uint32_t size_get() { return this->get_field(HWCE_X_TRANS_SIZE_SIZE_BIT, HWCE_X_TRANS_SIZE_SIZE_WIDTH); } +}; + +class vp_hwce_x_line_stride_length : public vp::reg_32 +{ +public: + inline void length_set(uint32_t value) { this->set_field(value, HWCE_X_LINE_STRIDE_LENGTH_LENGTH_BIT, HWCE_X_LINE_STRIDE_LENGTH_LENGTH_WIDTH); } + inline uint32_t length_get() { return this->get_field(HWCE_X_LINE_STRIDE_LENGTH_LENGTH_BIT, HWCE_X_LINE_STRIDE_LENGTH_LENGTH_WIDTH); } + inline void stride_set(uint32_t value) { this->set_field(value, HWCE_X_LINE_STRIDE_LENGTH_STRIDE_BIT, HWCE_X_LINE_STRIDE_LENGTH_STRIDE_WIDTH); } + inline uint32_t stride_get() { return this->get_field(HWCE_X_LINE_STRIDE_LENGTH_STRIDE_BIT, HWCE_X_LINE_STRIDE_LENGTH_STRIDE_WIDTH); } +}; + +class vp_hwce_x_feat_stride_length : public vp::reg_32 +{ +public: + inline void length_set(uint32_t value) { this->set_field(value, HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_BIT, HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_WIDTH); } + inline uint32_t length_get() { return this->get_field(HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_BIT, HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_WIDTH); } + inline void stride_set(uint32_t value) { this->set_field(value, HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_BIT, HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_WIDTH); } + inline uint32_t stride_get() { return this->get_field(HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_BIT, HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_WIDTH); } +}; + +class vp_hwce_x_in_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_X_IN_BASE_ADDR_ADDR_BIT, HWCE_X_IN_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_X_IN_BASE_ADDR_ADDR_BIT, HWCE_X_IN_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_w_base_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, HWCE_W_BASE_ADDR_ADDR_BIT, HWCE_W_BASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(HWCE_W_BASE_ADDR_ADDR_BIT, HWCE_W_BASE_ADDR_ADDR_WIDTH); } +}; + +class vp_hwce_job_config0 : public vp::reg_32 +{ +public: + inline void lbuflen_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG0_LBUFLEN_BIT, HWCE_JOB_CONFIG0_LBUFLEN_WIDTH); } + inline uint32_t lbuflen_get() { return this->get_field(HWCE_JOB_CONFIG0_LBUFLEN_BIT, HWCE_JOB_CONFIG0_LBUFLEN_WIDTH); } + inline void noyconst_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG0_NOYCONST_BIT, HWCE_JOB_CONFIG0_NOYCONST_WIDTH); } + inline uint32_t noyconst_get() { return this->get_field(HWCE_JOB_CONFIG0_NOYCONST_BIT, HWCE_JOB_CONFIG0_NOYCONST_WIDTH); } +}; + +class vp_hwce_job_config1 : public vp::reg_32 +{ +public: + inline void vect_disable_mask_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_BIT, HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_WIDTH); } + inline uint32_t vect_disable_mask_get() { return this->get_field(HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_BIT, HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_WIDTH); } + inline void wof_param_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG1_WOF_PARAM_BIT, HWCE_JOB_CONFIG1_WOF_PARAM_WIDTH); } + inline uint32_t wof_param_get() { return this->get_field(HWCE_JOB_CONFIG1_WOF_PARAM_BIT, HWCE_JOB_CONFIG1_WOF_PARAM_WIDTH); } + inline void wif_param_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG1_WIF_PARAM_BIT, HWCE_JOB_CONFIG1_WIF_PARAM_WIDTH); } + inline uint32_t wif_param_get() { return this->get_field(HWCE_JOB_CONFIG1_WIF_PARAM_BIT, HWCE_JOB_CONFIG1_WIF_PARAM_WIDTH); } + inline void lo_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG1_LO_BIT, HWCE_JOB_CONFIG1_LO_WIDTH); } + inline uint32_t lo_get() { return this->get_field(HWCE_JOB_CONFIG1_LO_BIT, HWCE_JOB_CONFIG1_LO_WIDTH); } + inline void ln_set(uint32_t value) { this->set_field(value, HWCE_JOB_CONFIG1_LN_BIT, HWCE_JOB_CONFIG1_LN_WIDTH); } + inline uint32_t ln_get() { return this->get_field(HWCE_JOB_CONFIG1_LN_BIT, HWCE_JOB_CONFIG1_LN_WIDTH); } +}; + +class vp_hwce_y_trans_size_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_line_stride_length_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_feat_stride_length_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_3_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_2_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_1_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_0_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_3_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_2_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_1_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_0_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_trans_size_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_line_stride_length_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_feat_stride_length_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_in_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_w_base_addr_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_job_config0_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_job_config1_ctx0 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_trans_size_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_line_stride_length_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_feat_stride_length_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_3_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_2_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_1_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_out_0_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_3_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_2_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_1_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_y_in_0_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_trans_size_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_line_stride_length_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_feat_stride_length_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_x_in_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_w_base_addr_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_job_config0_ctx1 : public vp::reg_32 +{ +public: +}; + +class vp_hwce_job_config1_ctx1 : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef struct { + unsigned int trigger ; // Trigger the execution of an offloaded job + unsigned int acquire ; // Acquire the lock to offload job + unsigned int finished_jobs ; // Number of concluded jobs since last read + unsigned int status ; // Status of the HWCE + unsigned int running_job ; // ID of the currently running job + unsigned int soft_clear ; // Reset HWCE to known idle state + unsigned int gen_config0 ; // Generic configuration register 0 + unsigned int gen_config1 ; // Generic configuration register 1 + unsigned int y_trans_size ; // Total number of words to be read for yin and yout + unsigned int y_line_stride_length; // Line stride and length for yin and yout + unsigned int y_feat_stride_length; // Feature (block) stride and length for yin and yout + unsigned int y_out_3_base_addr; // Base address of yout[3] + unsigned int y_out_2_base_addr; // Base address of yout[2] + unsigned int y_out_1_base_addr; // Base address of yout[1] + unsigned int y_out_0_base_addr; // Base address of yout[0] + unsigned int y_in_3_base_addr; // Base address of yin[3] + unsigned int y_in_2_base_addr; // Base address of yin[2] + unsigned int y_in_1_base_addr; // Base address of yin[1] + unsigned int y_in_0_base_addr; // Base address of yin[0] + unsigned int x_trans_size ; // Total number of words to be read for xin + unsigned int x_line_stride_length; // Line stride and length for xin + unsigned int x_feat_stride_length; // Feature (block) stride and length for xin + unsigned int x_in_base_addr ; // Base address of xin + unsigned int w_base_addr ; // Base address of W + unsigned int job_config0 ; // Job configuration register 0 + unsigned int job_config1 ; // Job configuration register 1 + unsigned int y_trans_size_ctx0; // Total number of words to be read for yin and yout + unsigned int y_line_stride_length_ctx0; // Line stride and length for yin and yout + unsigned int y_feat_stride_length_ctx0; // Feature (block) stride and length for yin and yout + unsigned int y_out_3_base_addr_ctx0; // Base address of yout[3] + unsigned int y_out_2_base_addr_ctx0; // Base address of yout[2] + unsigned int y_out_1_base_addr_ctx0; // Base address of yout[1] + unsigned int y_out_0_base_addr_ctx0; // Base address of yout[0] + unsigned int y_in_3_base_addr_ctx0; // Base address of yin[3] + unsigned int y_in_2_base_addr_ctx0; // Base address of yin[2] + unsigned int y_in_1_base_addr_ctx0; // Base address of yin[1] + unsigned int y_in_0_base_addr_ctx0; // Base address of yin[0] + unsigned int x_trans_size_ctx0; // Total number of words to be read for xin + unsigned int x_line_stride_length_ctx0; // Line stride and length for xin + unsigned int x_feat_stride_length_ctx0; // Feature (block) stride and length for xin + unsigned int x_in_base_addr_ctx0; // Base address of xin + unsigned int w_base_addr_ctx0; // Base address of W + unsigned int job_config0_ctx0; // Job configuration register 0 + unsigned int job_config1_ctx0; // Job configuration register 1 + unsigned int y_trans_size_ctx1; // Total number of words to be read for yin and yout + unsigned int y_line_stride_length_ctx1; // Line stride and length for yin and yout + unsigned int y_feat_stride_length_ctx1; // Feature (block) stride and length for yin and yout + unsigned int y_out_3_base_addr_ctx1; // Base address of yout[3] + unsigned int y_out_2_base_addr_ctx1; // Base address of yout[2] + unsigned int y_out_1_base_addr_ctx1; // Base address of yout[1] + unsigned int y_out_0_base_addr_ctx1; // Base address of yout[0] + unsigned int y_in_3_base_addr_ctx1; // Base address of yin[3] + unsigned int y_in_2_base_addr_ctx1; // Base address of yin[2] + unsigned int y_in_1_base_addr_ctx1; // Base address of yin[1] + unsigned int y_in_0_base_addr_ctx1; // Base address of yin[0] + unsigned int x_trans_size_ctx1; // Total number of words to be read for xin + unsigned int x_line_stride_length_ctx1; // Line stride and length for xin + unsigned int x_feat_stride_length_ctx1; // Feature (block) stride and length for xin + unsigned int x_in_base_addr_ctx1; // Base address of xin + unsigned int w_base_addr_ctx1; // Base address of W + unsigned int job_config0_ctx1; // Job configuration register 0 + unsigned int job_config1_ctx1; // Job configuration register 1 +} __attribute__((packed)) hwce_hwce_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +static inline uint32_t hwce_trigger_get(uint32_t base) { return ARCHI_READ(base, HWCE_TRIGGER_OFFSET); } +static inline void hwce_trigger_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_TRIGGER_OFFSET, value); } + +static inline uint32_t hwce_acquire_get(uint32_t base) { return ARCHI_READ(base, HWCE_ACQUIRE_OFFSET); } +static inline void hwce_acquire_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_ACQUIRE_OFFSET, value); } + +static inline uint32_t hwce_finished_jobs_get(uint32_t base) { return ARCHI_READ(base, HWCE_FINISHED_JOBS_OFFSET); } +static inline void hwce_finished_jobs_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_FINISHED_JOBS_OFFSET, value); } + +static inline uint32_t hwce_status_get(uint32_t base) { return ARCHI_READ(base, HWCE_STATUS_OFFSET); } +static inline void hwce_status_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_STATUS_OFFSET, value); } + +static inline uint32_t hwce_running_job_get(uint32_t base) { return ARCHI_READ(base, HWCE_RUNNING_JOB_OFFSET); } +static inline void hwce_running_job_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_RUNNING_JOB_OFFSET, value); } + +static inline uint32_t hwce_soft_clear_get(uint32_t base) { return ARCHI_READ(base, HWCE_SOFT_CLEAR_OFFSET); } +static inline void hwce_soft_clear_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_SOFT_CLEAR_OFFSET, value); } + +static inline uint32_t hwce_gen_config0_get(uint32_t base) { return ARCHI_READ(base, HWCE_GEN_CONFIG0_OFFSET); } +static inline void hwce_gen_config0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_GEN_CONFIG0_OFFSET, value); } + +static inline uint32_t hwce_gen_config1_get(uint32_t base) { return ARCHI_READ(base, HWCE_GEN_CONFIG1_OFFSET); } +static inline void hwce_gen_config1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_GEN_CONFIG1_OFFSET, value); } + +static inline uint32_t hwce_y_trans_size_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_TRANS_SIZE_OFFSET); } +static inline void hwce_y_trans_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_TRANS_SIZE_OFFSET, value); } + +static inline uint32_t hwce_y_line_stride_length_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_LINE_STRIDE_LENGTH_OFFSET); } +static inline void hwce_y_line_stride_length_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_LINE_STRIDE_LENGTH_OFFSET, value); } + +static inline uint32_t hwce_y_feat_stride_length_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_FEAT_STRIDE_LENGTH_OFFSET); } +static inline void hwce_y_feat_stride_length_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_FEAT_STRIDE_LENGTH_OFFSET, value); } + +static inline uint32_t hwce_y_out_3_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_3_BASE_ADDR_OFFSET); } +static inline void hwce_y_out_3_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_3_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_out_2_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_2_BASE_ADDR_OFFSET); } +static inline void hwce_y_out_2_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_2_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_out_1_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_1_BASE_ADDR_OFFSET); } +static inline void hwce_y_out_1_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_1_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_out_0_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_0_BASE_ADDR_OFFSET); } +static inline void hwce_y_out_0_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_0_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_in_3_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_3_BASE_ADDR_OFFSET); } +static inline void hwce_y_in_3_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_3_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_in_2_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_2_BASE_ADDR_OFFSET); } +static inline void hwce_y_in_2_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_2_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_in_1_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_1_BASE_ADDR_OFFSET); } +static inline void hwce_y_in_1_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_1_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_y_in_0_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_0_BASE_ADDR_OFFSET); } +static inline void hwce_y_in_0_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_0_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_x_trans_size_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_TRANS_SIZE_OFFSET); } +static inline void hwce_x_trans_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_TRANS_SIZE_OFFSET, value); } + +static inline uint32_t hwce_x_line_stride_length_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_LINE_STRIDE_LENGTH_OFFSET); } +static inline void hwce_x_line_stride_length_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_LINE_STRIDE_LENGTH_OFFSET, value); } + +static inline uint32_t hwce_x_feat_stride_length_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_FEAT_STRIDE_LENGTH_OFFSET); } +static inline void hwce_x_feat_stride_length_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_FEAT_STRIDE_LENGTH_OFFSET, value); } + +static inline uint32_t hwce_x_in_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_IN_BASE_ADDR_OFFSET); } +static inline void hwce_x_in_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_IN_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_w_base_addr_get(uint32_t base) { return ARCHI_READ(base, HWCE_W_BASE_ADDR_OFFSET); } +static inline void hwce_w_base_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_W_BASE_ADDR_OFFSET, value); } + +static inline uint32_t hwce_job_config0_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG0_OFFSET); } +static inline void hwce_job_config0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG0_OFFSET, value); } + +static inline uint32_t hwce_job_config1_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG1_OFFSET); } +static inline void hwce_job_config1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG1_OFFSET, value); } + +static inline uint32_t hwce_y_trans_size_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_TRANS_SIZE_CTX0_OFFSET); } +static inline void hwce_y_trans_size_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_TRANS_SIZE_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_line_stride_length_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_LINE_STRIDE_LENGTH_CTX0_OFFSET); } +static inline void hwce_y_line_stride_length_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_LINE_STRIDE_LENGTH_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_feat_stride_length_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_FEAT_STRIDE_LENGTH_CTX0_OFFSET); } +static inline void hwce_y_feat_stride_length_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_FEAT_STRIDE_LENGTH_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_out_3_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_3_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_out_3_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_3_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_out_2_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_2_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_out_2_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_2_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_out_1_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_1_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_out_1_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_1_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_out_0_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_0_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_out_0_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_0_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_in_3_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_3_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_in_3_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_3_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_in_2_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_2_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_in_2_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_2_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_in_1_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_1_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_in_1_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_1_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_in_0_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_0_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_y_in_0_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_0_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_x_trans_size_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_TRANS_SIZE_CTX0_OFFSET); } +static inline void hwce_x_trans_size_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_TRANS_SIZE_CTX0_OFFSET, value); } + +static inline uint32_t hwce_x_line_stride_length_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_LINE_STRIDE_LENGTH_CTX0_OFFSET); } +static inline void hwce_x_line_stride_length_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_LINE_STRIDE_LENGTH_CTX0_OFFSET, value); } + +static inline uint32_t hwce_x_feat_stride_length_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_FEAT_STRIDE_LENGTH_CTX0_OFFSET); } +static inline void hwce_x_feat_stride_length_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_FEAT_STRIDE_LENGTH_CTX0_OFFSET, value); } + +static inline uint32_t hwce_x_in_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_IN_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_x_in_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_IN_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_w_base_addr_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_W_BASE_ADDR_CTX0_OFFSET); } +static inline void hwce_w_base_addr_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_W_BASE_ADDR_CTX0_OFFSET, value); } + +static inline uint32_t hwce_job_config0_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG0_CTX0_OFFSET); } +static inline void hwce_job_config0_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG0_CTX0_OFFSET, value); } + +static inline uint32_t hwce_job_config1_ctx0_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG1_CTX0_OFFSET); } +static inline void hwce_job_config1_ctx0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG1_CTX0_OFFSET, value); } + +static inline uint32_t hwce_y_trans_size_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_TRANS_SIZE_CTX1_OFFSET); } +static inline void hwce_y_trans_size_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_TRANS_SIZE_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_line_stride_length_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_LINE_STRIDE_LENGTH_CTX1_OFFSET); } +static inline void hwce_y_line_stride_length_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_LINE_STRIDE_LENGTH_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_feat_stride_length_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_FEAT_STRIDE_LENGTH_CTX1_OFFSET); } +static inline void hwce_y_feat_stride_length_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_FEAT_STRIDE_LENGTH_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_out_3_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_3_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_out_3_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_3_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_out_2_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_2_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_out_2_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_2_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_out_1_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_1_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_out_1_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_1_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_out_0_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_OUT_0_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_out_0_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_OUT_0_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_in_3_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_3_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_in_3_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_3_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_in_2_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_2_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_in_2_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_2_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_in_1_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_1_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_in_1_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_1_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_y_in_0_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_Y_IN_0_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_y_in_0_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_Y_IN_0_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_x_trans_size_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_TRANS_SIZE_CTX1_OFFSET); } +static inline void hwce_x_trans_size_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_TRANS_SIZE_CTX1_OFFSET, value); } + +static inline uint32_t hwce_x_line_stride_length_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_LINE_STRIDE_LENGTH_CTX1_OFFSET); } +static inline void hwce_x_line_stride_length_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_LINE_STRIDE_LENGTH_CTX1_OFFSET, value); } + +static inline uint32_t hwce_x_feat_stride_length_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_FEAT_STRIDE_LENGTH_CTX1_OFFSET); } +static inline void hwce_x_feat_stride_length_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_FEAT_STRIDE_LENGTH_CTX1_OFFSET, value); } + +static inline uint32_t hwce_x_in_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_X_IN_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_x_in_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_X_IN_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_w_base_addr_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_W_BASE_ADDR_CTX1_OFFSET); } +static inline void hwce_w_base_addr_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_W_BASE_ADDR_CTX1_OFFSET, value); } + +static inline uint32_t hwce_job_config0_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG0_CTX1_OFFSET); } +static inline void hwce_job_config0_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG0_CTX1_OFFSET, value); } + +static inline uint32_t hwce_job_config1_ctx1_get(uint32_t base) { return ARCHI_READ(base, HWCE_JOB_CONFIG1_CTX1_OFFSET); } +static inline void hwce_job_config1_ctx1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HWCE_JOB_CONFIG1_CTX1_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#define HWCE_TRIGGER_ANY_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_TRIGGER_ANY_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_TRIGGER_ANY_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_TRIGGER_ANY(val) ((val) << 0) + +#define HWCE_ACQUIRE_ID_ERR_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define HWCE_ACQUIRE_ID_ERR_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define HWCE_ACQUIRE_ID_ERR_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define HWCE_ACQUIRE_ID_ERR(val) ((val) << 0) + +#define HWCE_ACQUIRE_ERR_GET(value) (ARCHI_BEXTRACTU((value),24,8)) +#define HWCE_ACQUIRE_ERR_GETS(value) (ARCHI_BEXTRACT((value),24,8)) +#define HWCE_ACQUIRE_ERR_SET(value,field) (ARCHI_BINSERT((value),(field),24,8)) +#define HWCE_ACQUIRE_ERR(val) ((val) << 8) + +#define HWCE_FINISHED_JOBS_JOBS_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_FINISHED_JOBS_JOBS_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_FINISHED_JOBS_JOBS_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_FINISHED_JOBS_JOBS(val) ((val) << 0) + +#define HWCE_STATUS_ST_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HWCE_STATUS_ST_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HWCE_STATUS_ST_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HWCE_STATUS_ST(val) ((val) << 0) + +#define HWCE_RUNNING_JOB_ID_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define HWCE_RUNNING_JOB_ID_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define HWCE_RUNNING_JOB_ID_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define HWCE_RUNNING_JOB_ID(val) ((val) << 0) + +#define HWCE_SOFT_CLEAR_ANY_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_SOFT_CLEAR_ANY_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_SOFT_CLEAR_ANY_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_SOFT_CLEAR_ANY(val) ((val) << 0) + +#define HWCE_GEN_CONFIG0_QF_GET(value) (ARCHI_BEXTRACTU((value),6,0)) +#define HWCE_GEN_CONFIG0_QF_GETS(value) (ARCHI_BEXTRACT((value),6,0)) +#define HWCE_GEN_CONFIG0_QF_SET(value,field) (ARCHI_BINSERT((value),(field),6,0)) +#define HWCE_GEN_CONFIG0_QF(val) ((val) << 0) + +#define HWCE_GEN_CONFIG0_NF_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define HWCE_GEN_CONFIG0_NF_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define HWCE_GEN_CONFIG0_NF_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define HWCE_GEN_CONFIG0_NF(val) ((val) << 6) + +#define HWCE_GEN_CONFIG0_NY_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define HWCE_GEN_CONFIG0_NY_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define HWCE_GEN_CONFIG0_NY_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define HWCE_GEN_CONFIG0_NY(val) ((val) << 7) + +#define HWCE_GEN_CONFIG0_UNS_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define HWCE_GEN_CONFIG0_UNS_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define HWCE_GEN_CONFIG0_UNS_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define HWCE_GEN_CONFIG0_UNS(val) ((val) << 8) + +#define HWCE_GEN_CONFIG0_VECT_GET(value) (ARCHI_BEXTRACTU((value),2,9)) +#define HWCE_GEN_CONFIG0_VECT_GETS(value) (ARCHI_BEXTRACT((value),2,9)) +#define HWCE_GEN_CONFIG0_VECT_SET(value,field) (ARCHI_BINSERT((value),(field),2,9)) +#define HWCE_GEN_CONFIG0_VECT(val) ((val) << 9) + +#define HWCE_GEN_CONFIG0_CONV_GET(value) (ARCHI_BEXTRACTU((value),2,11)) +#define HWCE_GEN_CONFIG0_CONV_GETS(value) (ARCHI_BEXTRACT((value),2,11)) +#define HWCE_GEN_CONFIG0_CONV_SET(value,field) (ARCHI_BINSERT((value),(field),2,11)) +#define HWCE_GEN_CONFIG0_CONV(val) ((val) << 11) + +#define HWCE_GEN_CONFIG0_NCP_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define HWCE_GEN_CONFIG0_NCP_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define HWCE_GEN_CONFIG0_NCP_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define HWCE_GEN_CONFIG0_NCP(val) ((val) << 13) + +#define HWCE_GEN_CONFIG0_WSTRIDE_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_GEN_CONFIG0_WSTRIDE_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_GEN_CONFIG0_WSTRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_GEN_CONFIG0_WSTRIDE(val) ((val) << 16) + +#define HWCE_GEN_CONFIG1_PIXSHIFTL_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define HWCE_GEN_CONFIG1_PIXSHIFTL_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define HWCE_GEN_CONFIG1_PIXSHIFTL_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define HWCE_GEN_CONFIG1_PIXSHIFTL(val) ((val) << 0) + +#define HWCE_GEN_CONFIG1_PIXMODE_GET(value) (ARCHI_BEXTRACTU((value),2,8)) +#define HWCE_GEN_CONFIG1_PIXMODE_GETS(value) (ARCHI_BEXTRACT((value),2,8)) +#define HWCE_GEN_CONFIG1_PIXMODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,8)) +#define HWCE_GEN_CONFIG1_PIXMODE(val) ((val) << 8) + +#define HWCE_GEN_CONFIG1_PIXSHIFTR_GET(value) (ARCHI_BEXTRACTU((value),5,16)) +#define HWCE_GEN_CONFIG1_PIXSHIFTR_GETS(value) (ARCHI_BEXTRACT((value),5,16)) +#define HWCE_GEN_CONFIG1_PIXSHIFTR_SET(value,field) (ARCHI_BINSERT((value),(field),5,16)) +#define HWCE_GEN_CONFIG1_PIXSHIFTR(val) ((val) << 16) + +#define HWCE_Y_TRANS_SIZE_SIZE_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_TRANS_SIZE_SIZE_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_TRANS_SIZE_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_TRANS_SIZE_SIZE(val) ((val) << 0) + +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HWCE_Y_LINE_STRIDE_LENGTH_LENGTH(val) ((val) << 0) + +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_Y_LINE_STRIDE_LENGTH_STRIDE(val) ((val) << 16) + +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_LENGTH(val) ((val) << 0) + +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_Y_FEAT_STRIDE_LENGTH_STRIDE(val) ((val) << 16) + +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_OUT_3_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_OUT_2_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_OUT_1_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_OUT_0_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_IN_3_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_IN_3_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_IN_2_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_IN_2_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_IN_1_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_IN_1_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_Y_IN_0_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_Y_IN_0_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_X_TRANS_SIZE_SIZE_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_X_TRANS_SIZE_SIZE_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_X_TRANS_SIZE_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_X_TRANS_SIZE_SIZE(val) ((val) << 0) + +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HWCE_X_LINE_STRIDE_LENGTH_LENGTH(val) ((val) << 0) + +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_X_LINE_STRIDE_LENGTH_STRIDE(val) ((val) << 16) + +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HWCE_X_FEAT_STRIDE_LENGTH_LENGTH(val) ((val) << 0) + +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_X_FEAT_STRIDE_LENGTH_STRIDE(val) ((val) << 16) + +#define HWCE_X_IN_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_X_IN_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_X_IN_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_X_IN_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_W_BASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define HWCE_W_BASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define HWCE_W_BASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define HWCE_W_BASE_ADDR_ADDR(val) ((val) << 0) + +#define HWCE_JOB_CONFIG0_LBUFLEN_GET(value) (ARCHI_BEXTRACTU((value),10,0)) +#define HWCE_JOB_CONFIG0_LBUFLEN_GETS(value) (ARCHI_BEXTRACT((value),10,0)) +#define HWCE_JOB_CONFIG0_LBUFLEN_SET(value,field) (ARCHI_BINSERT((value),(field),10,0)) +#define HWCE_JOB_CONFIG0_LBUFLEN(val) ((val) << 0) + +#define HWCE_JOB_CONFIG0_NOYCONST_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define HWCE_JOB_CONFIG0_NOYCONST_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define HWCE_JOB_CONFIG0_NOYCONST_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define HWCE_JOB_CONFIG0_NOYCONST(val) ((val) << 16) + +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK(val) ((val) << 0) + +#define HWCE_JOB_CONFIG1_WOF_PARAM_GET(value) (ARCHI_BEXTRACTU((value),6,8)) +#define HWCE_JOB_CONFIG1_WOF_PARAM_GETS(value) (ARCHI_BEXTRACT((value),6,8)) +#define HWCE_JOB_CONFIG1_WOF_PARAM_SET(value,field) (ARCHI_BINSERT((value),(field),6,8)) +#define HWCE_JOB_CONFIG1_WOF_PARAM(val) ((val) << 8) + +#define HWCE_JOB_CONFIG1_WIF_PARAM_GET(value) (ARCHI_BEXTRACTU((value),6,16)) +#define HWCE_JOB_CONFIG1_WIF_PARAM_GETS(value) (ARCHI_BEXTRACT((value),6,16)) +#define HWCE_JOB_CONFIG1_WIF_PARAM_SET(value,field) (ARCHI_BINSERT((value),(field),6,16)) +#define HWCE_JOB_CONFIG1_WIF_PARAM(val) ((val) << 16) + +#define HWCE_JOB_CONFIG1_LO_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define HWCE_JOB_CONFIG1_LO_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define HWCE_JOB_CONFIG1_LO_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define HWCE_JOB_CONFIG1_LO(val) ((val) << 24) + +#define HWCE_JOB_CONFIG1_LN_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define HWCE_JOB_CONFIG1_LN_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define HWCE_JOB_CONFIG1_LN_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define HWCE_JOB_CONFIG1_LN(val) ((val) << 25) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4_old.h b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4_old.h new file mode 100644 index 0000000..ac5abc0 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v4_old.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_HWCE_HWCE_V4_H__ +#define __ARCHI_HWCE_HWCE_V4_H__ + +#define HWCE_ADDR_BASE ARCHI_HWCE_ADDR + +#define HWCE_TRIGGER 0x00 +#define HWCE_ACQUIRE 0x04 +#define HWCE_FINISHED 0x08 +#define HWCE_STATUS 0x0C +#define HWCE_RUNNING_JOB 0x10 +#define HWCE_SOFT_CLEAR 0x14 +#define HWCE_GEN_CONFIG0 0x20 +#define HWCE_GEN_CONFIG1 0x24 + +#define HWCE_Y_TRANS_SIZE 0x40 +#define HWCE_Y_LINE_STRIDE_LENGTH 0x44 +#define HWCE_Y_FEAT_STRIDE_LENGTH 0x48 +#define HWCE_Y_OUT_3_BASE_ADDR 0x4C +#define HWCE_Y_OUT_2_BASE_ADDR 0x50 +#define HWCE_Y_OUT_1_BASE_ADDR 0x54 +#define HWCE_Y_OUT_0_BASE_ADDR 0x58 +#define HWCE_Y_IN_3_BASE_ADDR 0x5C +#define HWCE_Y_IN_2_BASE_ADDR 0x60 +#define HWCE_Y_IN_1_BASE_ADDR 0x64 +#define HWCE_Y_IN_0_BASE_ADDR 0x68 +#define HWCE_X_TRANS_SIZE 0x6C +#define HWCE_X_LINE_STRIDE_LENGTH 0x70 +#define HWCE_X_FEAT_STRIDE_LENGTH 0x74 +#define HWCE_X_IN_BASE_ADDR 0x78 +#define HWCE_W_BASE_ADDR 0x7C +#define HWCE_JOB_CONFIG0 0x80 +#define HWCE_JOB_CONFIG1 0x84 + +#define HWCE_NB_IO_REGS 18 + +#define HWCE_ACQUIRE_CONTEXT_COPY -3 +#define HWCE_ACQUIRE_LOCKED -2 +#define HWCE_ACQUIRE_QUEUE_FULL -1 +#define HWCE_ACQUIRE_READY 0 + +#define HWCE_GEN_CONFIG0_WSTRIDE(x) ((x) >> 16) +#define HWCE_GEN_CONFIG0_NCP(x) (((x) >> 13) & 0x1) +#define HWCE_GEN_CONFIG0_CONV(x) (((x) >> 11) & 0x3) +#define HWCE_GEN_CONFIG0_VECT(x) (((x) >> 9) & 0x3) +#define HWCE_GEN_CONFIG0_UNS(x) (((x) >> 8) & 1) +#define HWCE_GEN_CONFIG0_NY(x) (((x) >> 7) & 1) +#define HWCE_GEN_CONFIG0_NF(x) (((x) >> 6) & 1) +#define HWCE_GEN_CONFIG0_QF(x) ((x) & 0x3f) + +#define HWCE_GEN_CONFIG0_CONV_5x5 0 +#define HWCE_GEN_CONFIG0_CONV_3x3 1 +#define HWCE_GEN_CONFIG0_CONV_4x7 2 + +#define HWCE_GEN_CONFIG0_VECT_1 0 +#define HWCE_GEN_CONFIG0_VECT_2 1 +#define HWCE_GEN_CONFIG0_VECT_4 2 + +#define HWCE_GEN_CONFIG1_PIXSHIFTR(x) (((x) >> 16) & 0x1F) +#define HWCE_GEN_CONFIG1_PIXMODE(x) (((x) >> 8) & 0x3) +#define HWCE_GEN_CONFIG1_PIXSHIFTL(x) (((x) >> 0) & 0x1F) + +#define HWCE_JOB_CONFIG0_NOYCONST(x) ((x) >> 16) +#define HWCE_JOB_CONFIG0_LBUFLEN(x) ((x) & 0x3ff) + +#define HWCE_JOB_CONFIG1_LO(x) (((x) >> 24) & 0x1) +#define HWCE_JOB_CONFIG1_WIF(x) (((x) >> 16) & 0x3F) +#define HWCE_JOB_CONFIG1_WOF(x) (((x) >> 8) & 0x1F) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK(x) (((x) >> 0) & 0xF) + +#define HWCE_JOB_STRIDE(x) ((x) >> 16) +#define HWCE_JOB_LENGTH(x) ((x) & 0xffff) + +/* utility constants - used by hwce_rt and other libs */ + +// linebuffer width in 16-bit half-words +#define HWCE_LBSIZE 32 + +// loop order modes +#define HWCE_LOOP_ORDER_OLD 0 +#define HWCE_LOOP_ORDER_OF_IF 2 +#define HWCE_LOOP_ORDER_IF_OF 3 + +// 8-bit and 4-bit pixel modes +#define HWCE_PIXMODE_16BIT 0 +#define HWCE_PIXMODE_8BIT 1 +#define HWCE_PIXMODE_4BIT 2 + +// y_in modes +#define HWCE_Y_IN_MODE_ON 1 +#define HWCE_Y_IN_MODE_OFF 0 + +// disable vectors +#define HWCE_VECT_DISABLE(y0, y1, y2, y3) ( y0 << 3 | y1 << 2 | y2 << 1 | y3 ) + +// conv mode +#define HWCE_CONVMODE_5x5 HWCE_GEN_CONFIG0_CONV_5x5 +#define HWCE_CONVMODE_3x3 HWCE_GEN_CONFIG0_CONV_3x3 +#define HWCE_CONVMODE_4x7 HWCE_GEN_CONFIG0_CONV_4x7 + +// vect mode +#define HWCE_VECTMODE_1 HWCE_GEN_CONFIG0_VECT_1 +#define HWCE_VECTMODE_2 HWCE_GEN_CONFIG0_VECT_2 +#define HWCE_VECTMODE_4 HWCE_GEN_CONFIG0_VECT_4 + +// sign mode +#define HWCE_SIGNMODE_SIGNED 1 +#define HWCE_SIGNMODE_UNSIGNED 0 + +// weight order +#define HWCE_WEIGHTORDER_AUTOCORR 1 +#define HWCE_WEIGHTORDER_CONV 0 + +// job copy mechanism +#define HWCE_JOBCOPY_ON 1 +#define HWCE_JOBCOPY_OFF 0 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/hwce/hwce_v5.h b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v5.h new file mode 100644 index 0000000..07fc8ae --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/hwce/hwce_v5.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_HWCE_HWCE_V5_H__ +#define __ARCHI_HWCE_HWCE_V5_H__ + +#define HWCE_TRIGGER 0x00 +#define HWCE_ACQUIRE 0x04 +#define HWCE_FINISHED 0x08 +#define HWCE_STATUS 0x0C +#define HWCE_RUNNING_JOB 0x10 +#define HWCE_SOFT_CLEAR 0x14 +#define HWCE_OFFLOADER_ID 0x18 +#define HWCE_SW_EVT 0x1C + +#define HWCE_GEN_CONFIG0 0x20 +#define HWCE_GEN_CONFIG1 0x24 +#define HWCE_GEN_CONFIG2 0x28 + +#define HWCE_Y_TRANS_SIZE 0x40 +#define HWCE_Y_LINE_STRIDE_LENGTH 0x44 +#define HWCE_Y_FEAT_STRIDE_LENGTH 0x48 +#define HWCE_Y_OUT_3_BASE_ADDR 0x4C +#define HWCE_Y_OUT_2_BASE_ADDR 0x50 +#define HWCE_Y_OUT_1_BASE_ADDR 0x54 +#define HWCE_Y_OUT_0_BASE_ADDR 0x58 +#define HWCE_Y_IN_3_BASE_ADDR 0x5C +#define HWCE_Y_IN_2_BASE_ADDR 0x60 +#define HWCE_Y_IN_1_BASE_ADDR 0x64 +#define HWCE_Y_IN_0_BASE_ADDR 0x68 +#define HWCE_X_TRANS_SIZE 0x6C +#define HWCE_X_LINE_STRIDE_LENGTH 0x70 +#define HWCE_X_FEAT_STRIDE_LENGTH 0x74 +#define HWCE_X_IN_BASE_ADDR 0x78 +#define HWCE_W_BASE_ADDR 0x7C +#define HWCE_JOB_CONFIG0 0x80 +#define HWCE_JOB_CONFIG1 0x84 +#define HWCE_JOB_CONFIG2 0x88 +#define HWCE_TH_BASE_ADDR 0x8C +#define HWCE_LBUFXTRANSSIZE_ADDR 0x90 + +#define HWCE_NB_IO_REGS 19 + +#define HWCE_ACQUIRE_CONTEXT_COPY -3 +#define HWCE_ACQUIRE_LOCKED -2 +#define HWCE_ACQUIRE_QUEUE_FULL -1 +#define HWCE_ACQUIRE_READY 0 + +#define HWCE_GEN_CONFIG0_WSTRIDE(x) ((x) >> 16) +#define HWCE_GEN_CONFIG0_NCP(x) (((x) >> 13) & 0x1) +#define HWCE_GEN_CONFIG0_CONV(x) (((x) >> 11) & 0x3) +#define HWCE_GEN_CONFIG0_VECT(x) (((x) >> 9) & 0x3) +#define HWCE_GEN_CONFIG0_UNS(x) (((x) >> 8) & 1) +#define HWCE_GEN_CONFIG0_NY(x) (((x) >> 7) & 1) +#define HWCE_GEN_CONFIG0_NF(x) (((x) >> 6) & 1) +#define HWCE_GEN_CONFIG0_QF(x) ((x) & 0x3f) + +#define HWCE_GEN_CONFIG0_CONV_5x5 0 +#define HWCE_GEN_CONFIG0_CONV_3x3 1 +#define HWCE_GEN_CONFIG0_CONV_4x7 2 + +#define HWCE_GEN_CONFIG0_VECT_1 0 +#define HWCE_GEN_CONFIG0_VECT_2 1 +#define HWCE_GEN_CONFIG0_VECT_4 2 + +#define HWCE_GEN_CONFIG1_PIXSHIFTR(x) (((x) >> 16) & 0x1F) +#define HWCE_GEN_CONFIG1_PIXMODE(x) (((x) >> 8) & 0x3) +#define HWCE_GEN_CONFIG1_PIXSHIFTL(x) (((x) >> 0) & 0x1F) + +#define HWCE_JOB_CONFIG0_NOYCONST(x) ((x) >> 16) +#define HWCE_JOB_CONFIG0_LBUFLEN(x) ((x) & 0x3ff) + +#define HWCE_JOB_CONFIG1_LO(x) (((x) >> 24) & 0x1) +#define HWCE_JOB_CONFIG1_WIF(x) (((x) >> 16) & 0x3F) +#define HWCE_JOB_CONFIG1_WOF(x) (((x) >> 8) & 0x1F) +#define HWCE_JOB_CONFIG1_VECT_DISABLE_MASK(x) (((x) >> 0) & 0xF) + +#define HWCE_JOB_STRIDE(x) ((x) >> 16) +#define HWCE_JOB_LENGTH(x) ((x) & 0xffff) + +/* utility constants - used by hwce_rt and other libs */ + +// linebuffer width in 16-bit half-words +#define HWCE_LBSIZE 32 + +// loop order modes +#define HWCE_LOOP_ORDER_OF_IF 0 +#define HWCE_LOOP_ORDER_IF_OF 1 + +// quantization modes +#define HWCE_QMODE_16BIT 0 +#define HWCE_QMODE_8BIT 4 +#define HWCE_QMODE_4BIT 3 +#define HWCE_QMODE_2BIT 2 +#define HWCE_QMODE_1BIT 1 + +// y_in modes +#define HWCE_Y_IN_MODE_ON 1 +#define HWCE_Y_IN_MODE_OFF 0 + +// disable vectors +#define HWCE_VECT_DISABLE(y0, y1, y2, y3) ( y0 << 3 | y1 << 2 | y2 << 1 | y3 ) + +// conv mode +#define HWCE_CONVMODE_5x5 HWCE_GEN_CONFIG0_CONV_5x5 +#define HWCE_CONVMODE_3x3 HWCE_GEN_CONFIG0_CONV_3x3 +#define HWCE_CONVMODE_4x7 HWCE_GEN_CONFIG0_CONV_4x7 + +// vect mode +#define HWCE_VECTMODE_1 HWCE_GEN_CONFIG0_VECT_1 +#define HWCE_VECTMODE_2 HWCE_GEN_CONFIG0_VECT_2 +#define HWCE_VECTMODE_4 HWCE_GEN_CONFIG0_VECT_4 + +// sign mode +#define HWCE_SIGNMODE_SIGNED 1 +#define HWCE_SIGNMODE_UNSIGNED 0 + +// weight order +#define HWCE_WEIGHTORDER_AUTOCORR 1 +#define HWCE_WEIGHTORDER_CONV 0 + +// job copy mechanism +#define HWCE_JOBCOPY_ON 1 +#define HWCE_JOBCOPY_OFF 0 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/hwme/hwme_v1.h b/sw/pulp-sdk/archi/include/archi/hwme/hwme_v1.h new file mode 100644 index 0000000..79eebec --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/hwme/hwme_v1.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +/* + * Authors: Francesco Conti + */ + +#ifndef __ARCHI_HWME_V1_H__ +#define __ARCHI_HWME_V1_H__ + +/* + * Control and generic configuration register layout + * ================================================================================ + * # reg | offset | bits | bitmask || content + * -------+----------+---------+--------------++----------------------------------- + * 0 | 0x0000 | 31: 0 | 0xffffffff || TRIGGER + * 1 | 0x0004 | 31: 0 | 0xffffffff || ACQUIRE + * 2 | 0x0008 | 31: 0 | 0xffffffff || EVT_ENABLE + * 3 | 0x000c | 31: 0 | 0xffffffff || STATUS + * 4 | 0x0010 | 31: 0 | 0xffffffff || RUNNING_JOB + * 5 | 0x0014 | 31: 0 | 0xffffffff || SOFT_CLEAR + * 6-7 | | | || Reserved + * 8 | 0x0020 | 31: 0 | 0xffffffff || BYTECODE0 [31:0] + * 9 | 0x0024 | 31: 0 | 0xffffffff || BYTECODE1 [63:32] + * 10 | 0x0028 | 31: 0 | 0xffffffff || BYTECODE2 [95:64] + * 11 | 0x002c | 31: 0 | 0xffffffff || BYTECODE3 [127:96] + * 12 | 0x0030 | 31: 0 | 0xffffffff || BYTECODE4 [159:128] + * 13 | 0x0034 | 31:16 | 0xffff0000 || LOOPS0 [15:0] + * | | 15: 0 | 0x0000ffff || BYTECODE5 [175:160] + * 14 | 0x0038 | 31: 0 | 0xffffffff || LOOPS1 [47:16] + * 15 | | 31: 0 | 0xffffffff || Reserved + * ================================================================================ + * + * Job-dependent registers layout + * ================================================================================ + * # reg | offset | bits | bitmask || content + * -------+----------+---------+--------------++----------------------------------- + * 0 | 0x0040 | 31: 0 | 0xffffffff || A_ADDR + * 1 | 0x0044 | 31: 0 | 0xffffffff || B_ADDR + * 2 | 0x0048 | 31: 0 | 0xffffffff || C_ADDR + * 3 | 0x004c | 31: 0 | 0xffffffff || D_ADDR + * 4 | 0x0050 | 31: 0 | 0xffffffff || NB_ITER + * 5 | 0x0054 | 31: 0 | 0xffffffff || LEN_ITER + * 6 | 0x0058 | 31:16 | 0xffff0000 || SHIFT + * | | 0: 0 | 0x00000001 || SIMPLEMUL + * 7 | 0x005c | 31: 0 | 0xffffffff || VECTSTRIDE + * 8 | 0x0060 | 31: 0 | 0xffffffff || VECTSTRIDE2 + * ================================================================================ + * + */ + +#define HWME_TRIGGER 0x00 +#define HWME_ACQUIRE 0x04 +#define HWME_FINISHED 0x08 +#define HWME_STATUS 0x0c +#define HWME_RUNNING_JOB 0x10 +#define HWME_SOFT_CLEAR 0x14 + +#define HWME_BYTECODE 0x20 +#define HWME_BYTECODE0_OFFS 0x00 +#define HWME_BYTECODE1_OFFS 0x04 +#define HWME_BYTECODE2_OFFS 0x08 +#define HWME_BYTECODE3_OFFS 0x0c +#define HWME_BYTECODE4_OFFS 0x10 +#define HWME_BYTECODE5_LOOPS0_OFFS 0x14 +#define HWME_LOOPS1_OFFS 0x18 + +#define HWME_A_ADDR 0x40 +#define HWME_B_ADDR 0x44 +#define HWME_C_ADDR 0x48 +#define HWME_D_ADDR 0x4c +#define HWME_NB_ITER 0x50 +#define HWME_LEN_ITER 0x54 +#define HWME_SHIFT_SIMPLEMUL 0x58 +#define HWME_VECTSTRIDE 0x5c +#define HWME_VECTSTRIDE2 0x60 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/itc/itc_v1.h b/sw/pulp-sdk/archi/include/archi/itc/itc_v1.h new file mode 100644 index 0000000..bf15bea --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/itc/itc_v1.h @@ -0,0 +1,268 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_ITC_ITC_V1_H__ +#define __INCLUDE_ARCHI_ITC_ITC_V1_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +#define ITC_MASK_OFFSET 0x0 + +#define ITC_MASK_SET_OFFSET 0x4 + +#define ITC_MASK_CLR_OFFSET 0x8 + +#define ITC_STATUS_OFFSET 0xc + +#define ITC_STATUS_SET_OFFSET 0x10 + +#define ITC_STATUS_CLR_OFFSET 0x14 + +#define ITC_ACK_OFFSET 0x18 + +#define ITC_ACK_SET_OFFSET 0x1c + +#define ITC_ACK_CLR_OFFSET 0x20 + +#define ITC_FIFO_OFFSET 0x24 + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_mask_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_mask_set_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_mask_clr_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_status_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_status_set_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_status_clr_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_ack_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_ack_set_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_ack_clr_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) itc_fifo_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_itc_mask : public vp::reg_32 +{ +public: +}; + +class vp_itc_mask_set : public vp::reg_32 +{ +public: +}; + +class vp_itc_mask_clr : public vp::reg_32 +{ +public: +}; + +class vp_itc_status : public vp::reg_32 +{ +public: +}; + +class vp_itc_status_set : public vp::reg_32 +{ +public: +}; + +class vp_itc_status_clr : public vp::reg_32 +{ +public: +}; + +class vp_itc_ack : public vp::reg_32 +{ +public: +}; + +class vp_itc_ack_set : public vp::reg_32 +{ +public: +}; + +class vp_itc_ack_clr : public vp::reg_32 +{ +public: +}; + +class vp_itc_fifo : public vp::reg_32 +{ +public: +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int mask ; + unsigned int mask_set ; + unsigned int mask_clr ; + unsigned int status ; + unsigned int status_set ; + unsigned int status_clr ; + unsigned int ack ; + unsigned int ack_set ; + unsigned int ack_clr ; + unsigned int fifo ; +} __attribute__((packed)) itc_itc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t itc_mask_get(uint32_t base) { return ARCHI_READ(base, ITC_MASK_OFFSET); } +static inline void itc_mask_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_MASK_OFFSET, value); } + +static inline uint32_t itc_mask_set_get(uint32_t base) { return ARCHI_READ(base, ITC_MASK_SET_OFFSET); } +static inline void itc_mask_set_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_MASK_SET_OFFSET, value); } + +static inline uint32_t itc_mask_clr_get(uint32_t base) { return ARCHI_READ(base, ITC_MASK_CLR_OFFSET); } +static inline void itc_mask_clr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_MASK_CLR_OFFSET, value); } + +static inline uint32_t itc_status_get(uint32_t base) { return ARCHI_READ(base, ITC_STATUS_OFFSET); } +static inline void itc_status_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_STATUS_OFFSET, value); } + +static inline uint32_t itc_status_set_get(uint32_t base) { return ARCHI_READ(base, ITC_STATUS_SET_OFFSET); } +static inline void itc_status_set_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_STATUS_SET_OFFSET, value); } + +static inline uint32_t itc_status_clr_get(uint32_t base) { return ARCHI_READ(base, ITC_STATUS_CLR_OFFSET); } +static inline void itc_status_clr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_STATUS_CLR_OFFSET, value); } + +static inline uint32_t itc_ack_get(uint32_t base) { return ARCHI_READ(base, ITC_ACK_OFFSET); } +static inline void itc_ack_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_ACK_OFFSET, value); } + +static inline uint32_t itc_ack_set_get(uint32_t base) { return ARCHI_READ(base, ITC_ACK_SET_OFFSET); } +static inline void itc_ack_set_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_ACK_SET_OFFSET, value); } + +static inline uint32_t itc_ack_clr_get(uint32_t base) { return ARCHI_READ(base, ITC_ACK_CLR_OFFSET); } +static inline void itc_ack_clr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_ACK_CLR_OFFSET, value); } + +static inline uint32_t itc_fifo_get(uint32_t base) { return ARCHI_READ(base, ITC_FIFO_OFFSET); } +static inline void itc_fifo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, ITC_FIFO_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1.h b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1.h new file mode 100644 index 0000000..630c85e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_MAESTRO_MAESTRO_V1_H__ +#define __ARCHI_MAESTRO_MAESTRO_V1_H__ + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1_new.h b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1_new.h new file mode 100644 index 0000000..5f3274d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v1_new.h @@ -0,0 +1,1472 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_MAESTRO_MAESTRO_V1_NEW_H__ +#define __INCLUDE_ARCHI_MAESTRO_MAESTRO_V1_NEW_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// PICL control register +#define MAESTRO_DLC_PCTRL_OFFSET 0x0 + +// PICL data read register +#define MAESTRO_PRDATA_OFFSET 0x4 + +// Status register +#define MAESTRO_DLC_SR_OFFSET 0x8 + +// Interrupt Mask register +#define MAESTRO_DLC_IMR_OFFSET 0xc + +// Interrupt flag register +#define MAESTRO_DLC_IFR_OFFSET 0x10 + +// icu_ok interrupt flag register +#define MAESTRO_DLC_IOIFR_OFFSET 0x14 + +// icu_delayed interrupt flag register +#define MAESTRO_DLC_IDIFR_OFFSET 0x18 + +// icu_mode_changed interrupt flags register +#define MAESTRO_DLC_IMCIFR_OFFSET 0x1c + + + +// +// REGISTERS FIELDS +// + +// Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. (access: R/W) +#define MAESTRO_DLC_PCTRL_START_BIT 0 +#define MAESTRO_DLC_PCTRL_START_WIDTH 1 +#define MAESTRO_DLC_PCTRL_START_MASK 0x1 +#define MAESTRO_DLC_PCTRL_START_RESET 0x0 + +// Address of the transfer on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PADDR_BIT 1 +#define MAESTRO_DLC_PCTRL_PADDR_WIDTH 14 +#define MAESTRO_DLC_PCTRL_PADDR_MASK 0x7ffe +#define MAESTRO_DLC_PCTRL_PADDR_RESET 0x0 + +// Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. (access: R/W) +#define MAESTRO_DLC_PCTRL_DIR_BIT 15 +#define MAESTRO_DLC_PCTRL_DIR_WIDTH 1 +#define MAESTRO_DLC_PCTRL_DIR_MASK 0x8000 +#define MAESTRO_DLC_PCTRL_DIR_RESET 0x0 + +// Data to write on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PWDATA_BIT 16 +#define MAESTRO_DLC_PCTRL_PWDATA_WIDTH 16 +#define MAESTRO_DLC_PCTRL_PWDATA_MASK 0xffff0000 +#define MAESTRO_DLC_PCTRL_PWDATA_RESET 0x0 + +// Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. (access: R) +#define MAESTRO_PRDATA_PRDATA_BIT 0 +#define MAESTRO_PRDATA_PRDATA_WIDTH 8 +#define MAESTRO_PRDATA_PRDATA_MASK 0xff +#define MAESTRO_PRDATA_PRDATA_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_PICL_BUSY_BIT 0 +#define MAESTRO_DLC_SR_PICL_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_PICL_BUSY_MASK 0x1 +#define MAESTRO_DLC_SR_PICL_BUSY_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_SCU_BUSY_BIT 1 +#define MAESTRO_DLC_SR_SCU_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_SCU_BUSY_MASK 0x2 +#define MAESTRO_DLC_SR_SCU_BUSY_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_BIT 0 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_MASK 0x1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_MASK 0x2 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT 2 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_MASK 0x4 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_BIT 3 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_MASK 0x8 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_BIT 4 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_MASK 0x10 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT 0 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_MASK 0x1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_MASK 0x2 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT 2 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_MASK 0x4 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_RESET 0x0 + +// Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT 3 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_MASK 0x8 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_RESET 0x0 + +// Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT 4 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_MASK 0x10 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT 1 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT 1 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT 1 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int start :1 ; // Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. + unsigned int paddr :14; // Address of the transfer on the PICL bus. + unsigned int dir :1 ; // Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. + unsigned int pwdata :16; // Data to write on the PICL bus. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_pctrl_t; + +typedef union { + struct { + unsigned int prdata :8 ; // Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. + }; + unsigned int raw; +} __attribute__((packed)) maestro_prdata_t; + +typedef union { + struct { + unsigned int picl_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + unsigned int scu_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_sr_t; + +typedef union { + struct { + unsigned int icu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_delayed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_mode_changed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int picl_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int scu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imr_t; + +typedef union { + struct { + unsigned int icu_ok_flag :1 ; // Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. + unsigned int icu_delayed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. + unsigned int icu_mode_changed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. + unsigned int picl_ok_flag :1 ; // Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. + unsigned int scu_ok_flag :1 ; // Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_ok_flags :31; // Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ioifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_delayed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_idifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_mode_changed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imcifr_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_dlc_pctrl : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline void paddr_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline uint32_t paddr_get() { return this->get_field(MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline void dir_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline void pwdata_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } + inline uint32_t pwdata_get() { return this->get_field(MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } +}; + +class vp_maestro_prdata : public vp::reg_32 +{ +public: + inline void prdata_set(uint32_t value) { this->set_field(value, MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } + inline uint32_t prdata_get() { return this->get_field(MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } +}; + +class vp_maestro_dlc_sr : public vp::reg_32 +{ +public: + inline void picl_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline uint32_t picl_busy_get() { return this->get_field(MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline void scu_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } + inline uint32_t scu_busy_get() { return this->get_field(MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } +}; + +class vp_maestro_dlc_imr : public vp::reg_32 +{ +public: + inline void icu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline uint32_t icu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline void icu_delayed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline uint32_t icu_delayed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline void icu_mode_changed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline uint32_t icu_mode_changed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline void picl_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline uint32_t picl_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline void scu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } + inline uint32_t scu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } +}; + +class vp_maestro_dlc_ifr : public vp::reg_32 +{ +public: + inline void icu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline uint32_t icu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline void icu_delayed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline uint32_t icu_delayed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline void icu_mode_changed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline uint32_t icu_mode_changed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline void picl_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline uint32_t picl_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline void scu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } + inline uint32_t scu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } +}; + +class vp_maestro_dlc_ioifr : public vp::reg_32 +{ +public: + inline void icu_ok_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } + inline uint32_t icu_ok_flags_get() { return this->get_field(MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_idifr : public vp::reg_32 +{ +public: + inline void icu_delayed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } + inline uint32_t icu_delayed_flags_get() { return this->get_field(MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_imcifr : public vp::reg_32 +{ +public: + inline void icu_mode_changed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } + inline uint32_t icu_mode_changed_flags_get() { return this->get_field(MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int dlc_pctrl ; // PICL control register + unsigned int prdata ; // PICL data read register + unsigned int dlc_sr ; // Status register + unsigned int dlc_imr ; // Interrupt Mask register + unsigned int dlc_ifr ; // Interrupt flag register + unsigned int dlc_ioifr ; // icu_ok interrupt flag register + unsigned int dlc_idifr ; // icu_delayed interrupt flag register + unsigned int dlc_imcifr ; // icu_mode_changed interrupt flags register +} __attribute__((packed)) maestro_maestro_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_dlc_pctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_PCTRL_OFFSET); } +static inline void maestro_dlc_pctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_PCTRL_OFFSET, value); } + +static inline uint32_t maestro_prdata_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_PRDATA_OFFSET); } +static inline void maestro_prdata_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_PRDATA_OFFSET, value); } + +static inline uint32_t maestro_dlc_sr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_SR_OFFSET); } +static inline void maestro_dlc_sr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_SR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMR_OFFSET); } +static inline void maestro_dlc_imr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IFR_OFFSET); } +static inline void maestro_dlc_ifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ioifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IOIFR_OFFSET); } +static inline void maestro_dlc_ioifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IOIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_idifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IDIFR_OFFSET); } +static inline void maestro_dlc_idifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IDIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imcifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMCIFR_OFFSET); } +static inline void maestro_dlc_imcifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMCIFR_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_DLC_PCTRL_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_PCTRL_START(val) ((val) << 0) + +#define MAESTRO_DLC_PCTRL_PADDR_GET(value) (ARCHI_BEXTRACTU((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_GETS(value) (ARCHI_BEXTRACT((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_SET(value,field) (ARCHI_BINSERT((value),(field),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR(val) ((val) << 1) + +#define MAESTRO_DLC_PCTRL_DIR_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define MAESTRO_DLC_PCTRL_DIR(val) ((val) << 15) + +#define MAESTRO_DLC_PCTRL_PWDATA_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA(val) ((val) << 16) + +#define MAESTRO_PRDATA_PRDATA_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_PRDATA_PRDATA(val) ((val) << 0) + +#define MAESTRO_DLC_SR_PICL_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY(val) ((val) << 0) + +#define MAESTRO_DLC_SR_SCU_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK(val) ((val) << 0) + +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK(val) ((val) << 2) + +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK(val) ((val) << 3) + +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK(val) ((val) << 4) + +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG(val) ((val) << 0) + +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG(val) ((val) << 1) + +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG(val) ((val) << 2) + +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG(val) ((val) << 3) + +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG(val) ((val) << 4) + +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS(val) ((val) << 1) + +#endif + + + +// +// GROUP wiu +// + +#define MAESTRO_WIU_OFFSET 0x0 + + + +// +// REGISTERS +// + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_0_OFFSET 0x0 + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_1_OFFSET 0x1 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_0_OFFSET 0x2 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_1_OFFSET 0x3 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_0_OFFSET 0x4 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_1_OFFSET 0x5 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_2_OFFSET 0x6 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_3_OFFSET 0x7 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_4_OFFSET 0x8 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_5_OFFSET 0x9 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_6_OFFSET 0xa + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_7_OFFSET 0xb + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_8_OFFSET 0xc + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_9_OFFSET 0xd + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_10_OFFSET 0xe + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_11_OFFSET 0xf + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_12_OFFSET 0x10 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_13_OFFSET 0x11 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_14_OFFSET 0x12 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_15_OFFSET 0x13 + + + +// +// REGISTERS FIELDS +// + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT 0 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH 5 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_MASK 0x1f +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT 0 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH 5 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_MASK 0x1f +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT 0 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH 5 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_MASK 0x1f +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT 0 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH 5 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_MASK 0x1f +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT 0 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH 5 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_MASK 0x1f +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT 0 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH 5 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_MASK 0x1f +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT 0 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH 5 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_MASK 0x1f +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT 0 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH 5 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_MASK 0x1f +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT 0 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH 5 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_MASK 0x1f +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT 0 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH 5 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_MASK 0x1f +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT 0 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH 5 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_MASK 0x1f +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT 0 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH 5 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_MASK 0x1f +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT 0 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH 5 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_MASK 0x1f +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT 0 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH 5 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_MASK 0x1f +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT 0 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH 5 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_MASK 0x1f +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT 0 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH 5 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_MASK 0x1f +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_0_t; + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_1_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_0_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_0 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_0_t; + +typedef union { + struct { + unsigned int seq_sel_irq_1 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_2 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_2_t; + +typedef union { + struct { + unsigned int seq_sel_irq_3 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_3_t; + +typedef union { + struct { + unsigned int seq_sel_irq_4 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_4_t; + +typedef union { + struct { + unsigned int seq_sel_irq_5 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_5_t; + +typedef union { + struct { + unsigned int seq_sel_irq_6 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_6_t; + +typedef union { + struct { + unsigned int seq_sel_irq_7 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_7_t; + +typedef union { + struct { + unsigned int seq_sel_irq_8 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_8_t; + +typedef union { + struct { + unsigned int seq_sel_irq_9 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_9_t; + +typedef union { + struct { + unsigned int seq_sel_irq_10 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_10_t; + +typedef union { + struct { + unsigned int seq_sel_irq_11 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_11_t; + +typedef union { + struct { + unsigned int seq_sel_irq_12 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_12_t; + +typedef union { + struct { + unsigned int seq_sel_irq_13 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_13_t; + +typedef union { + struct { + unsigned int seq_sel_irq_14 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_14_t; + +typedef union { + struct { + unsigned int seq_sel_irq_15 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_15_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_wiu_ispmr_0 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ispmr_1 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_0 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_1 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_icr_0 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_0_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } + inline uint8_t seq_sel_irq_0_get() { return this->get_field(MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } +}; + +class vp_maestro_wiu_icr_1 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_1_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } + inline uint8_t seq_sel_irq_1_get() { return this->get_field(MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } +}; + +class vp_maestro_wiu_icr_2 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_2_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } + inline uint8_t seq_sel_irq_2_get() { return this->get_field(MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } +}; + +class vp_maestro_wiu_icr_3 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_3_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } + inline uint8_t seq_sel_irq_3_get() { return this->get_field(MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } +}; + +class vp_maestro_wiu_icr_4 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_4_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } + inline uint8_t seq_sel_irq_4_get() { return this->get_field(MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } +}; + +class vp_maestro_wiu_icr_5 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_5_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } + inline uint8_t seq_sel_irq_5_get() { return this->get_field(MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } +}; + +class vp_maestro_wiu_icr_6 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_6_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } + inline uint8_t seq_sel_irq_6_get() { return this->get_field(MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } +}; + +class vp_maestro_wiu_icr_7 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_7_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } + inline uint8_t seq_sel_irq_7_get() { return this->get_field(MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } +}; + +class vp_maestro_wiu_icr_8 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_8_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } + inline uint8_t seq_sel_irq_8_get() { return this->get_field(MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } +}; + +class vp_maestro_wiu_icr_9 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_9_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } + inline uint8_t seq_sel_irq_9_get() { return this->get_field(MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } +}; + +class vp_maestro_wiu_icr_10 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_10_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } + inline uint8_t seq_sel_irq_10_get() { return this->get_field(MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } +}; + +class vp_maestro_wiu_icr_11 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_11_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } + inline uint8_t seq_sel_irq_11_get() { return this->get_field(MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } +}; + +class vp_maestro_wiu_icr_12 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_12_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } + inline uint8_t seq_sel_irq_12_get() { return this->get_field(MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } +}; + +class vp_maestro_wiu_icr_13 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_13_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } + inline uint8_t seq_sel_irq_13_get() { return this->get_field(MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } +}; + +class vp_maestro_wiu_icr_14 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_14_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } + inline uint8_t seq_sel_irq_14_get() { return this->get_field(MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } +}; + +class vp_maestro_wiu_icr_15 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_15_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } + inline uint8_t seq_sel_irq_15_get() { return this->get_field(MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int wiu_ispmr_0 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ispmr_1 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ifr_0 ; // Interrupt Flag register + unsigned int wiu_ifr_1 ; // Interrupt Flag register + unsigned int wiu_icr_0 ; // Interrupt Control registers + unsigned int wiu_icr_1 ; // Interrupt Control registers + unsigned int wiu_icr_2 ; // Interrupt Control registers + unsigned int wiu_icr_3 ; // Interrupt Control registers + unsigned int wiu_icr_4 ; // Interrupt Control registers + unsigned int wiu_icr_5 ; // Interrupt Control registers + unsigned int wiu_icr_6 ; // Interrupt Control registers + unsigned int wiu_icr_7 ; // Interrupt Control registers + unsigned int wiu_icr_8 ; // Interrupt Control registers + unsigned int wiu_icr_9 ; // Interrupt Control registers + unsigned int wiu_icr_10 ; // Interrupt Control registers + unsigned int wiu_icr_11 ; // Interrupt Control registers + unsigned int wiu_icr_12 ; // Interrupt Control registers + unsigned int wiu_icr_13 ; // Interrupt Control registers + unsigned int wiu_icr_14 ; // Interrupt Control registers + unsigned int wiu_icr_15 ; // Interrupt Control registers +} __attribute__((packed)) maestro_wiu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_wiu_ispmr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_0_OFFSET); } +static inline void maestro_wiu_ispmr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ispmr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_1_OFFSET); } +static inline void maestro_wiu_ispmr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_0_OFFSET); } +static inline void maestro_wiu_ifr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_1_OFFSET); } +static inline void maestro_wiu_ifr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_0_OFFSET); } +static inline void maestro_wiu_icr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_1_OFFSET); } +static inline void maestro_wiu_icr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_2_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_2_OFFSET); } +static inline void maestro_wiu_icr_2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_2_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_3_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_3_OFFSET); } +static inline void maestro_wiu_icr_3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_3_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_4_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_4_OFFSET); } +static inline void maestro_wiu_icr_4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_4_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_5_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_5_OFFSET); } +static inline void maestro_wiu_icr_5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_5_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_6_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_6_OFFSET); } +static inline void maestro_wiu_icr_6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_6_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_7_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_7_OFFSET); } +static inline void maestro_wiu_icr_7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_7_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_8_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_8_OFFSET); } +static inline void maestro_wiu_icr_8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_8_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_9_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_9_OFFSET); } +static inline void maestro_wiu_icr_9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_9_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_10_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_10_OFFSET); } +static inline void maestro_wiu_icr_10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_10_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_11_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_11_OFFSET); } +static inline void maestro_wiu_icr_11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_11_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_12_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_12_OFFSET); } +static inline void maestro_wiu_icr_12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_12_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_13_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_13_OFFSET); } +static inline void maestro_wiu_icr_13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_13_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_14_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_14_OFFSET); } +static inline void maestro_wiu_icr_14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_14_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_15_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_15_OFFSET); } +static inline void maestro_wiu_icr_15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_15_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15(val) ((val) << 0) + +#endif + + + +// +// GROUP icu +// + + + +// +// REGISTERS +// + +// ICU control register +#define MAESTRO_ICU_CTRL_OFFSET 0x0 + +// ICU mode register +#define MAESTRO_ICU_MODE_OFFSET 0x1 + +// Island mode register +#define MAESTRO_ISLAND_MODE_OFFSET 0x2 + +// DMU mode register 0 +#define MAESTRO_DMU_MODE_OFFSET 0x3 + + + +// +// REGISTERS FIELDS +// + +// When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. (access: R/W) +#define MAESTRO_ICU_CTRL_ICU_CTRL_BIT 0 +#define MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH 4 +#define MAESTRO_ICU_CTRL_ICU_CTRL_MASK 0xf +#define MAESTRO_ICU_CTRL_ICU_CTRL_RESET 0x0 + +// Returns the current mode of the ICU when icu_mode_defined is low. (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_BIT 0 +#define MAESTRO_ICU_MODE_ICU_MODE_WIDTH 4 +#define MAESTRO_ICU_MODE_ICU_MODE_MASK 0xf +#define MAESTRO_ICU_MODE_ICU_MODE_RESET 0xf + +// When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT 4 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH 1 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_MASK 0x10 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_RESET 0x1 + +// Mode of the island. (access: R) +#define MAESTRO_ISLAND_MODE_ISL_MODE_BIT 0 +#define MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_ISLAND_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_ISLAND_MODE_ISL_MODE_RESET 0x0 + +// Mode of the DMU 0. (access: R) +#define MAESTRO_DMU_MODE_ISL_MODE_BIT 0 +#define MAESTRO_DMU_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_DMU_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_DMU_MODE_ISL_MODE_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int icu_ctrl :4 ; // When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_ctrl_t; + +typedef union { + struct { + unsigned int icu_mode :4 ; // Returns the current mode of the ICU when icu_mode_defined is low. + unsigned int icu_mode_defined:1 ; // When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the island. + }; + unsigned int raw; +} __attribute__((packed)) maestro_island_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the DMU 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dmu_mode_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_icu_ctrl : public vp::reg_8 +{ +public: + inline void icu_ctrl_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } + inline uint8_t icu_ctrl_get() { return this->get_field(MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } +}; + +class vp_maestro_icu_mode : public vp::reg_8 +{ +public: + inline void icu_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline uint8_t icu_mode_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline void icu_mode_defined_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } + inline uint8_t icu_mode_defined_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } +}; + +class vp_maestro_island_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } +}; + +class vp_maestro_dmu_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int icu_ctrl ; // ICU control register + unsigned int icu_mode ; // ICU mode register + unsigned int island_mode ; // Island mode register + unsigned int dmu_mode ; // DMU mode register 0 +} __attribute__((packed)) maestro_icu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_icu_ctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_CTRL_OFFSET); } +static inline void maestro_icu_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_CTRL_OFFSET, value); } + +static inline uint32_t maestro_icu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_MODE_OFFSET); } +static inline void maestro_icu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_MODE_OFFSET, value); } + +static inline uint32_t maestro_island_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ISLAND_MODE_OFFSET); } +static inline void maestro_island_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ISLAND_MODE_OFFSET, value); } + +static inline uint32_t maestro_dmu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DMU_MODE_OFFSET); } +static inline void maestro_dmu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DMU_MODE_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_ICU_CTRL_ICU_CTRL_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED(val) ((val) << 4) + +#define MAESTRO_ISLAND_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE(val) ((val) << 0) + +#define MAESTRO_DMU_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE(val) ((val) << 0) + +#endif + + + +// +// CUSTOM FIELDS +// +#define MAESTRO_ICU_SUPPLY_EXT 0x0 +#define MAESTRO_ICU_SUPPLY_RET 0x1 +#define MAESTRO_ICU_SUPPLY_CKOFF 0x2 +#define MAESTRO_ICU_SUPPLY_ON 0x3 +#define MAESTRO_ICU_REGU_NONE 0x7 +#define MAESTRO_ICU_REGU_OFF 0x0 +#define MAESTRO_ICU_REGU_RV 0x1 +#define MAESTRO_ICU_REGU_LV 0x2 +#define MAESTRO_ICU_REGU_MV 0x3 +#define MAESTRO_ICU_REGU_NV 0x4 +#define MAESTRO_ICU_CLK_FNONE 0x7 +#define MAESTRO_ICU_CLK_FOFF 0x0 +#define MAESTRO_ICU_CLK_LF 0x1 +#define MAESTRO_ICU_CLK_MF 0x2 +#define MAESTRO_ICU_CLK_NF 0x3 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2.h b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2.h new file mode 100644 index 0000000..bafa8ca --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_MAESTRO_MAESTRO_V2_H__ +#define __ARCHI_MAESTRO_MAESTRO_V2_H__ + +#define ARCHI_PMU_BYPASS_ENABLE_BIT 0 +#define ARCHI_PMU_BYPASS_CLUSTER_POWER_BIT 1 +#define ARCHI_PMU_BYPASS_CLUSTER_CLOCK_BIT 2 +#define ARCHI_PMU_BYPASS_FLL_RETENTIVE_BIT 3 +#define ARCHI_PMU_BYPASS_FLL_OFF_BIT 4 +#define ARCHI_PMU_BYPASS_CLUSTER_RESET_BIT 5 +#define ARCHI_PMU_BYPASS_CLUSTER_ISOLATE_BIT 6 +#define ARCHI_PMU_BYPASS_CLUSTER_RETENTIVE_BIT 7 +#define ARCHI_PMU_BYPASS_POWER_OK_BIT 8 +#define ARCHI_PMU_BYPASS_CLOCK_OK_BIT 9 +#define ARCHI_PMU_BYPASS_POWER_DOWN_BIT 10 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2_new.h b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2_new.h new file mode 100644 index 0000000..afeeb83 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v2_new.h @@ -0,0 +1,1472 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_MAESTRO_MAESTRO_V2_NEW_H__ +#define __INCLUDE_ARCHI_MAESTRO_MAESTRO_V2_NEW_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// PICL control register +#define MAESTRO_DLC_PCTRL_OFFSET 0x0 + +// PICL data read register +#define MAESTRO_PRDATA_OFFSET 0x4 + +// Status register +#define MAESTRO_DLC_SR_OFFSET 0x8 + +// Interrupt Mask register +#define MAESTRO_DLC_IMR_OFFSET 0xc + +// Interrupt flag register +#define MAESTRO_DLC_IFR_OFFSET 0x10 + +// icu_ok interrupt flag register +#define MAESTRO_DLC_IOIFR_OFFSET 0x14 + +// icu_delayed interrupt flag register +#define MAESTRO_DLC_IDIFR_OFFSET 0x18 + +// icu_mode_changed interrupt flags register +#define MAESTRO_DLC_IMCIFR_OFFSET 0x1c + + + +// +// REGISTERS FIELDS +// + +// Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. (access: R/W) +#define MAESTRO_DLC_PCTRL_START_BIT 0 +#define MAESTRO_DLC_PCTRL_START_WIDTH 1 +#define MAESTRO_DLC_PCTRL_START_MASK 0x1 +#define MAESTRO_DLC_PCTRL_START_RESET 0x0 + +// Address of the transfer on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PADDR_BIT 1 +#define MAESTRO_DLC_PCTRL_PADDR_WIDTH 14 +#define MAESTRO_DLC_PCTRL_PADDR_MASK 0x7ffe +#define MAESTRO_DLC_PCTRL_PADDR_RESET 0x0 + +// Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. (access: R/W) +#define MAESTRO_DLC_PCTRL_DIR_BIT 15 +#define MAESTRO_DLC_PCTRL_DIR_WIDTH 1 +#define MAESTRO_DLC_PCTRL_DIR_MASK 0x8000 +#define MAESTRO_DLC_PCTRL_DIR_RESET 0x0 + +// Data to write on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PWDATA_BIT 16 +#define MAESTRO_DLC_PCTRL_PWDATA_WIDTH 16 +#define MAESTRO_DLC_PCTRL_PWDATA_MASK 0xffff0000 +#define MAESTRO_DLC_PCTRL_PWDATA_RESET 0x0 + +// Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. (access: R) +#define MAESTRO_PRDATA_PRDATA_BIT 0 +#define MAESTRO_PRDATA_PRDATA_WIDTH 8 +#define MAESTRO_PRDATA_PRDATA_MASK 0xff +#define MAESTRO_PRDATA_PRDATA_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_PICL_BUSY_BIT 0 +#define MAESTRO_DLC_SR_PICL_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_PICL_BUSY_MASK 0x1 +#define MAESTRO_DLC_SR_PICL_BUSY_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_SCU_BUSY_BIT 1 +#define MAESTRO_DLC_SR_SCU_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_SCU_BUSY_MASK 0x2 +#define MAESTRO_DLC_SR_SCU_BUSY_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_BIT 0 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_MASK 0x1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_MASK 0x2 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT 2 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_MASK 0x4 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_BIT 3 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_MASK 0x8 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_BIT 4 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_MASK 0x10 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT 0 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_MASK 0x1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_MASK 0x2 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT 2 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_MASK 0x4 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_RESET 0x0 + +// Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT 3 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_MASK 0x8 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_RESET 0x0 + +// Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT 4 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_MASK 0x10 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT 1 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT 1 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT 1 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int start :1 ; // Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. + unsigned int paddr :14; // Address of the transfer on the PICL bus. + unsigned int dir :1 ; // Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. + unsigned int pwdata :16; // Data to write on the PICL bus. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_pctrl_t; + +typedef union { + struct { + unsigned int prdata :8 ; // Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. + }; + unsigned int raw; +} __attribute__((packed)) maestro_prdata_t; + +typedef union { + struct { + unsigned int picl_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + unsigned int scu_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_sr_t; + +typedef union { + struct { + unsigned int icu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_delayed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_mode_changed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int picl_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int scu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imr_t; + +typedef union { + struct { + unsigned int icu_ok_flag :1 ; // Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. + unsigned int icu_delayed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. + unsigned int icu_mode_changed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. + unsigned int picl_ok_flag :1 ; // Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. + unsigned int scu_ok_flag :1 ; // Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_ok_flags :31; // Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ioifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_delayed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_idifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_mode_changed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imcifr_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_dlc_pctrl : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline void paddr_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline uint32_t paddr_get() { return this->get_field(MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline void dir_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline void pwdata_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } + inline uint32_t pwdata_get() { return this->get_field(MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } +}; + +class vp_maestro_prdata : public vp::reg_32 +{ +public: + inline void prdata_set(uint32_t value) { this->set_field(value, MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } + inline uint32_t prdata_get() { return this->get_field(MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } +}; + +class vp_maestro_dlc_sr : public vp::reg_32 +{ +public: + inline void picl_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline uint32_t picl_busy_get() { return this->get_field(MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline void scu_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } + inline uint32_t scu_busy_get() { return this->get_field(MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } +}; + +class vp_maestro_dlc_imr : public vp::reg_32 +{ +public: + inline void icu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline uint32_t icu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline void icu_delayed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline uint32_t icu_delayed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline void icu_mode_changed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline uint32_t icu_mode_changed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline void picl_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline uint32_t picl_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline void scu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } + inline uint32_t scu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } +}; + +class vp_maestro_dlc_ifr : public vp::reg_32 +{ +public: + inline void icu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline uint32_t icu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline void icu_delayed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline uint32_t icu_delayed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline void icu_mode_changed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline uint32_t icu_mode_changed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline void picl_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline uint32_t picl_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline void scu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } + inline uint32_t scu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } +}; + +class vp_maestro_dlc_ioifr : public vp::reg_32 +{ +public: + inline void icu_ok_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } + inline uint32_t icu_ok_flags_get() { return this->get_field(MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_idifr : public vp::reg_32 +{ +public: + inline void icu_delayed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } + inline uint32_t icu_delayed_flags_get() { return this->get_field(MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_imcifr : public vp::reg_32 +{ +public: + inline void icu_mode_changed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } + inline uint32_t icu_mode_changed_flags_get() { return this->get_field(MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int dlc_pctrl ; // PICL control register + unsigned int prdata ; // PICL data read register + unsigned int dlc_sr ; // Status register + unsigned int dlc_imr ; // Interrupt Mask register + unsigned int dlc_ifr ; // Interrupt flag register + unsigned int dlc_ioifr ; // icu_ok interrupt flag register + unsigned int dlc_idifr ; // icu_delayed interrupt flag register + unsigned int dlc_imcifr ; // icu_mode_changed interrupt flags register +} __attribute__((packed)) maestro_maestro_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_dlc_pctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_PCTRL_OFFSET); } +static inline void maestro_dlc_pctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_PCTRL_OFFSET, value); } + +static inline uint32_t maestro_prdata_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_PRDATA_OFFSET); } +static inline void maestro_prdata_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_PRDATA_OFFSET, value); } + +static inline uint32_t maestro_dlc_sr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_SR_OFFSET); } +static inline void maestro_dlc_sr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_SR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMR_OFFSET); } +static inline void maestro_dlc_imr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IFR_OFFSET); } +static inline void maestro_dlc_ifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ioifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IOIFR_OFFSET); } +static inline void maestro_dlc_ioifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IOIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_idifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IDIFR_OFFSET); } +static inline void maestro_dlc_idifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IDIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imcifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMCIFR_OFFSET); } +static inline void maestro_dlc_imcifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMCIFR_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_DLC_PCTRL_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_PCTRL_START(val) ((val) << 0) + +#define MAESTRO_DLC_PCTRL_PADDR_GET(value) (ARCHI_BEXTRACTU((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_GETS(value) (ARCHI_BEXTRACT((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_SET(value,field) (ARCHI_BINSERT((value),(field),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR(val) ((val) << 1) + +#define MAESTRO_DLC_PCTRL_DIR_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define MAESTRO_DLC_PCTRL_DIR(val) ((val) << 15) + +#define MAESTRO_DLC_PCTRL_PWDATA_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA(val) ((val) << 16) + +#define MAESTRO_PRDATA_PRDATA_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_PRDATA_PRDATA(val) ((val) << 0) + +#define MAESTRO_DLC_SR_PICL_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY(val) ((val) << 0) + +#define MAESTRO_DLC_SR_SCU_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK(val) ((val) << 0) + +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK(val) ((val) << 2) + +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK(val) ((val) << 3) + +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK(val) ((val) << 4) + +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG(val) ((val) << 0) + +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG(val) ((val) << 1) + +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG(val) ((val) << 2) + +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG(val) ((val) << 3) + +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG(val) ((val) << 4) + +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS(val) ((val) << 1) + +#endif + + + +// +// GROUP wiu +// + +#define MAESTRO_WIU_OFFSET 0x1 + + + +// +// REGISTERS +// + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_0_OFFSET 0x0 + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_1_OFFSET 0x1 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_0_OFFSET 0x2 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_1_OFFSET 0x3 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_0_OFFSET 0x4 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_1_OFFSET 0x5 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_2_OFFSET 0x6 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_3_OFFSET 0x7 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_4_OFFSET 0x8 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_5_OFFSET 0x9 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_6_OFFSET 0xa + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_7_OFFSET 0xb + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_8_OFFSET 0xc + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_9_OFFSET 0xd + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_10_OFFSET 0xe + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_11_OFFSET 0xf + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_12_OFFSET 0x10 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_13_OFFSET 0x11 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_14_OFFSET 0x12 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_15_OFFSET 0x13 + + + +// +// REGISTERS FIELDS +// + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT 0 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH 5 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_MASK 0x1f +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT 0 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH 5 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_MASK 0x1f +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT 0 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH 5 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_MASK 0x1f +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT 0 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH 5 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_MASK 0x1f +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT 0 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH 5 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_MASK 0x1f +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT 0 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH 5 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_MASK 0x1f +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT 0 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH 5 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_MASK 0x1f +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT 0 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH 5 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_MASK 0x1f +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT 0 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH 5 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_MASK 0x1f +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT 0 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH 5 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_MASK 0x1f +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT 0 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH 5 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_MASK 0x1f +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT 0 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH 5 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_MASK 0x1f +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT 0 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH 5 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_MASK 0x1f +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT 0 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH 5 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_MASK 0x1f +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT 0 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH 5 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_MASK 0x1f +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT 0 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH 5 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_MASK 0x1f +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_0_t; + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_1_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_0_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_0 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_0_t; + +typedef union { + struct { + unsigned int seq_sel_irq_1 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_2 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_2_t; + +typedef union { + struct { + unsigned int seq_sel_irq_3 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_3_t; + +typedef union { + struct { + unsigned int seq_sel_irq_4 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_4_t; + +typedef union { + struct { + unsigned int seq_sel_irq_5 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_5_t; + +typedef union { + struct { + unsigned int seq_sel_irq_6 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_6_t; + +typedef union { + struct { + unsigned int seq_sel_irq_7 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_7_t; + +typedef union { + struct { + unsigned int seq_sel_irq_8 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_8_t; + +typedef union { + struct { + unsigned int seq_sel_irq_9 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_9_t; + +typedef union { + struct { + unsigned int seq_sel_irq_10 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_10_t; + +typedef union { + struct { + unsigned int seq_sel_irq_11 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_11_t; + +typedef union { + struct { + unsigned int seq_sel_irq_12 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_12_t; + +typedef union { + struct { + unsigned int seq_sel_irq_13 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_13_t; + +typedef union { + struct { + unsigned int seq_sel_irq_14 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_14_t; + +typedef union { + struct { + unsigned int seq_sel_irq_15 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_15_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_wiu_ispmr_0 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ispmr_1 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_0 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_1 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_icr_0 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_0_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } + inline uint8_t seq_sel_irq_0_get() { return this->get_field(MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } +}; + +class vp_maestro_wiu_icr_1 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_1_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } + inline uint8_t seq_sel_irq_1_get() { return this->get_field(MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } +}; + +class vp_maestro_wiu_icr_2 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_2_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } + inline uint8_t seq_sel_irq_2_get() { return this->get_field(MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } +}; + +class vp_maestro_wiu_icr_3 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_3_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } + inline uint8_t seq_sel_irq_3_get() { return this->get_field(MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } +}; + +class vp_maestro_wiu_icr_4 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_4_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } + inline uint8_t seq_sel_irq_4_get() { return this->get_field(MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } +}; + +class vp_maestro_wiu_icr_5 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_5_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } + inline uint8_t seq_sel_irq_5_get() { return this->get_field(MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } +}; + +class vp_maestro_wiu_icr_6 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_6_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } + inline uint8_t seq_sel_irq_6_get() { return this->get_field(MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } +}; + +class vp_maestro_wiu_icr_7 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_7_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } + inline uint8_t seq_sel_irq_7_get() { return this->get_field(MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } +}; + +class vp_maestro_wiu_icr_8 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_8_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } + inline uint8_t seq_sel_irq_8_get() { return this->get_field(MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } +}; + +class vp_maestro_wiu_icr_9 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_9_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } + inline uint8_t seq_sel_irq_9_get() { return this->get_field(MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } +}; + +class vp_maestro_wiu_icr_10 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_10_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } + inline uint8_t seq_sel_irq_10_get() { return this->get_field(MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } +}; + +class vp_maestro_wiu_icr_11 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_11_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } + inline uint8_t seq_sel_irq_11_get() { return this->get_field(MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } +}; + +class vp_maestro_wiu_icr_12 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_12_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } + inline uint8_t seq_sel_irq_12_get() { return this->get_field(MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } +}; + +class vp_maestro_wiu_icr_13 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_13_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } + inline uint8_t seq_sel_irq_13_get() { return this->get_field(MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } +}; + +class vp_maestro_wiu_icr_14 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_14_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } + inline uint8_t seq_sel_irq_14_get() { return this->get_field(MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } +}; + +class vp_maestro_wiu_icr_15 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_15_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } + inline uint8_t seq_sel_irq_15_get() { return this->get_field(MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int wiu_ispmr_0 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ispmr_1 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ifr_0 ; // Interrupt Flag register + unsigned int wiu_ifr_1 ; // Interrupt Flag register + unsigned int wiu_icr_0 ; // Interrupt Control registers + unsigned int wiu_icr_1 ; // Interrupt Control registers + unsigned int wiu_icr_2 ; // Interrupt Control registers + unsigned int wiu_icr_3 ; // Interrupt Control registers + unsigned int wiu_icr_4 ; // Interrupt Control registers + unsigned int wiu_icr_5 ; // Interrupt Control registers + unsigned int wiu_icr_6 ; // Interrupt Control registers + unsigned int wiu_icr_7 ; // Interrupt Control registers + unsigned int wiu_icr_8 ; // Interrupt Control registers + unsigned int wiu_icr_9 ; // Interrupt Control registers + unsigned int wiu_icr_10 ; // Interrupt Control registers + unsigned int wiu_icr_11 ; // Interrupt Control registers + unsigned int wiu_icr_12 ; // Interrupt Control registers + unsigned int wiu_icr_13 ; // Interrupt Control registers + unsigned int wiu_icr_14 ; // Interrupt Control registers + unsigned int wiu_icr_15 ; // Interrupt Control registers +} __attribute__((packed)) maestro_wiu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_wiu_ispmr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_0_OFFSET); } +static inline void maestro_wiu_ispmr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ispmr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_1_OFFSET); } +static inline void maestro_wiu_ispmr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_0_OFFSET); } +static inline void maestro_wiu_ifr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_1_OFFSET); } +static inline void maestro_wiu_ifr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_0_OFFSET); } +static inline void maestro_wiu_icr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_1_OFFSET); } +static inline void maestro_wiu_icr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_2_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_2_OFFSET); } +static inline void maestro_wiu_icr_2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_2_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_3_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_3_OFFSET); } +static inline void maestro_wiu_icr_3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_3_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_4_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_4_OFFSET); } +static inline void maestro_wiu_icr_4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_4_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_5_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_5_OFFSET); } +static inline void maestro_wiu_icr_5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_5_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_6_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_6_OFFSET); } +static inline void maestro_wiu_icr_6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_6_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_7_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_7_OFFSET); } +static inline void maestro_wiu_icr_7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_7_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_8_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_8_OFFSET); } +static inline void maestro_wiu_icr_8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_8_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_9_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_9_OFFSET); } +static inline void maestro_wiu_icr_9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_9_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_10_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_10_OFFSET); } +static inline void maestro_wiu_icr_10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_10_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_11_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_11_OFFSET); } +static inline void maestro_wiu_icr_11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_11_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_12_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_12_OFFSET); } +static inline void maestro_wiu_icr_12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_12_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_13_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_13_OFFSET); } +static inline void maestro_wiu_icr_13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_13_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_14_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_14_OFFSET); } +static inline void maestro_wiu_icr_14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_14_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_15_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_15_OFFSET); } +static inline void maestro_wiu_icr_15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_15_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15(val) ((val) << 0) + +#endif + + + +// +// GROUP icu +// + + + +// +// REGISTERS +// + +// ICU control register +#define MAESTRO_ICU_CTRL_OFFSET 0x0 + +// ICU mode register +#define MAESTRO_ICU_MODE_OFFSET 0x1 + +// Island mode register +#define MAESTRO_ISLAND_MODE_OFFSET 0x2 + +// DMU mode register 0 +#define MAESTRO_DMU_MODE_OFFSET 0x3 + + + +// +// REGISTERS FIELDS +// + +// When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. (access: R/W) +#define MAESTRO_ICU_CTRL_ICU_CTRL_BIT 0 +#define MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH 4 +#define MAESTRO_ICU_CTRL_ICU_CTRL_MASK 0xf +#define MAESTRO_ICU_CTRL_ICU_CTRL_RESET 0x0 + +// Returns the current mode of the ICU when icu_mode_defined is low. (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_BIT 0 +#define MAESTRO_ICU_MODE_ICU_MODE_WIDTH 4 +#define MAESTRO_ICU_MODE_ICU_MODE_MASK 0xf +#define MAESTRO_ICU_MODE_ICU_MODE_RESET 0xf + +// When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT 4 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH 1 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_MASK 0x10 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_RESET 0x1 + +// Mode of the island. (access: R) +#define MAESTRO_ISLAND_MODE_ISL_MODE_BIT 0 +#define MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_ISLAND_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_ISLAND_MODE_ISL_MODE_RESET 0x0 + +// Mode of the DMU 0. (access: R) +#define MAESTRO_DMU_MODE_ISL_MODE_BIT 0 +#define MAESTRO_DMU_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_DMU_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_DMU_MODE_ISL_MODE_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int icu_ctrl :4 ; // When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_ctrl_t; + +typedef union { + struct { + unsigned int icu_mode :4 ; // Returns the current mode of the ICU when icu_mode_defined is low. + unsigned int icu_mode_defined:1 ; // When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the island. + }; + unsigned int raw; +} __attribute__((packed)) maestro_island_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the DMU 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dmu_mode_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_icu_ctrl : public vp::reg_8 +{ +public: + inline void icu_ctrl_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } + inline uint8_t icu_ctrl_get() { return this->get_field(MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } +}; + +class vp_maestro_icu_mode : public vp::reg_8 +{ +public: + inline void icu_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline uint8_t icu_mode_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline void icu_mode_defined_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } + inline uint8_t icu_mode_defined_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } +}; + +class vp_maestro_island_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } +}; + +class vp_maestro_dmu_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int icu_ctrl ; // ICU control register + unsigned int icu_mode ; // ICU mode register + unsigned int island_mode ; // Island mode register + unsigned int dmu_mode ; // DMU mode register 0 +} __attribute__((packed)) maestro_icu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_icu_ctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_CTRL_OFFSET); } +static inline void maestro_icu_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_CTRL_OFFSET, value); } + +static inline uint32_t maestro_icu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_MODE_OFFSET); } +static inline void maestro_icu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_MODE_OFFSET, value); } + +static inline uint32_t maestro_island_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ISLAND_MODE_OFFSET); } +static inline void maestro_island_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ISLAND_MODE_OFFSET, value); } + +static inline uint32_t maestro_dmu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DMU_MODE_OFFSET); } +static inline void maestro_dmu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DMU_MODE_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_ICU_CTRL_ICU_CTRL_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED(val) ((val) << 4) + +#define MAESTRO_ISLAND_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE(val) ((val) << 0) + +#define MAESTRO_DMU_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE(val) ((val) << 0) + +#endif + + + +// +// CUSTOM FIELDS +// +#define MAESTRO_ICU_SUPPLY_EXT 0x0 +#define MAESTRO_ICU_SUPPLY_RET 0x1 +#define MAESTRO_ICU_SUPPLY_CKOFF 0x2 +#define MAESTRO_ICU_SUPPLY_ON 0x3 +#define MAESTRO_ICU_REGU_NONE 0x7 +#define MAESTRO_ICU_REGU_OFF 0x0 +#define MAESTRO_ICU_REGU_RV 0x1 +#define MAESTRO_ICU_REGU_LV 0x2 +#define MAESTRO_ICU_REGU_MV 0x3 +#define MAESTRO_ICU_REGU_NV 0x4 +#define MAESTRO_ICU_CLK_FNONE 0x7 +#define MAESTRO_ICU_CLK_FOFF 0x0 +#define MAESTRO_ICU_CLK_LF 0x1 +#define MAESTRO_ICU_CLK_MF 0x2 +#define MAESTRO_ICU_CLK_NF 0x3 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/maestro/maestro_v3.h b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v3.h new file mode 100644 index 0000000..0bca3ac --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/maestro/maestro_v3.h @@ -0,0 +1,1545 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_MAESTRO_MAESTRO_V3_H__ +#define __INCLUDE_ARCHI_MAESTRO_MAESTRO_V3_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// PICL control register +#define MAESTRO_DLC_PCTRL_OFFSET 0x0 + +// PICL data read register +#define MAESTRO_PRDATA_OFFSET 0x4 + +// Status register +#define MAESTRO_DLC_SR_OFFSET 0x8 + +// Interrupt Mask register +#define MAESTRO_DLC_IMR_OFFSET 0xc + +// Interrupt flag register +#define MAESTRO_DLC_IFR_OFFSET 0x10 + +// icu_ok interrupt flag register +#define MAESTRO_DLC_IOIFR_OFFSET 0x14 + +// icu_delayed interrupt flag register +#define MAESTRO_DLC_IDIFR_OFFSET 0x18 + +// icu_mode_changed interrupt flags register +#define MAESTRO_DLC_IMCIFR_OFFSET 0x1c + + + +// +// REGISTERS FIELDS +// + +// Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. (access: R/W) +#define MAESTRO_DLC_PCTRL_START_BIT 0 +#define MAESTRO_DLC_PCTRL_START_WIDTH 1 +#define MAESTRO_DLC_PCTRL_START_MASK 0x1 +#define MAESTRO_DLC_PCTRL_START_RESET 0x0 + +// Address of the transfer on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PADDR_BIT 1 +#define MAESTRO_DLC_PCTRL_PADDR_WIDTH 14 +#define MAESTRO_DLC_PCTRL_PADDR_MASK 0x7ffe +#define MAESTRO_DLC_PCTRL_PADDR_RESET 0x0 + +// Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. (access: R/W) +#define MAESTRO_DLC_PCTRL_DIR_BIT 15 +#define MAESTRO_DLC_PCTRL_DIR_WIDTH 1 +#define MAESTRO_DLC_PCTRL_DIR_MASK 0x8000 +#define MAESTRO_DLC_PCTRL_DIR_RESET 0x0 + +// Data to write on the PICL bus. (access: R/W) +#define MAESTRO_DLC_PCTRL_PWDATA_BIT 16 +#define MAESTRO_DLC_PCTRL_PWDATA_WIDTH 16 +#define MAESTRO_DLC_PCTRL_PWDATA_MASK 0xffff0000 +#define MAESTRO_DLC_PCTRL_PWDATA_RESET 0x0 + +// Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. (access: R) +#define MAESTRO_PRDATA_PRDATA_BIT 0 +#define MAESTRO_PRDATA_PRDATA_WIDTH 8 +#define MAESTRO_PRDATA_PRDATA_MASK 0xff +#define MAESTRO_PRDATA_PRDATA_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_PICL_BUSY_BIT 0 +#define MAESTRO_DLC_SR_PICL_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_PICL_BUSY_MASK 0x1 +#define MAESTRO_DLC_SR_PICL_BUSY_RESET 0x0 + +// This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. (access: R) +#define MAESTRO_DLC_SR_SCU_BUSY_BIT 1 +#define MAESTRO_DLC_SR_SCU_BUSY_WIDTH 1 +#define MAESTRO_DLC_SR_SCU_BUSY_MASK 0x2 +#define MAESTRO_DLC_SR_SCU_BUSY_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_BIT 0 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_MASK 0x1 +#define MAESTRO_DLC_IMR_ICU_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_MASK 0x2 +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT 2 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_MASK 0x4 +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_BIT 3 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_MASK 0x8 +#define MAESTRO_DLC_IMR_PICL_OK_MASK_RESET 0x0 + +// A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. (access: R/W) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_BIT 4 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH 1 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_MASK 0x10 +#define MAESTRO_DLC_IMR_SCU_OK_MASK_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT 0 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_MASK 0x1 +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_MASK 0x2 +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_RESET 0x0 + +// Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. (access: R) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT 2 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_MASK 0x4 +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_RESET 0x0 + +// Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT 3 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_MASK 0x8 +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_RESET 0x0 + +// Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT 4 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH 1 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_MASK 0x10 +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT 1 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT 1 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_RESET 0x0 + +// Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. (access: R) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT 1 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH 31 +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_MASK 0xfffffffe +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int start :1 ; // Start of PICL access sequence. A rising edge of the start bit starts a PICL picl transfer. Start bit remains high until the end of the sequence, which means that no new access can be performed if an access is on going. + unsigned int paddr :14; // Address of the transfer on the PICL bus. + unsigned int dir :1 ; // Direction of the transfer on the PICL bus. dir = 1 means read operation, dir = 0 means write operation. + unsigned int pwdata :16; // Data to write on the PICL bus. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_pctrl_t; + +typedef union { + struct { + unsigned int prdata :8 ; // Data read on the PICL bus. This data is valid after a PICL read operation, when the picl_busy bit of the DLC_SR register becomes low. + }; + unsigned int raw; +} __attribute__((packed)) maestro_prdata_t; + +typedef union { + struct { + unsigned int picl_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + unsigned int scu_busy :1 ; // This bit is set to 1 if when a SCU sequence is on going. This bit is cleared at the end of the sequence. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_sr_t; + +typedef union { + struct { + unsigned int icu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_delayed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int icu_mode_changed_mask:1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int picl_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + unsigned int scu_ok_mask :1 ; // A read return the current value of the mask. Writing 1 set the mask, writing 0 clears the mask. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imr_t; + +typedef union { + struct { + unsigned int icu_ok_flag :1 ; // Set to 1 when at least one of the bit of the DLC_IOIFR register is set. Cleared when reading DCL_IOIFR register. + unsigned int icu_delayed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IDIFR register is set. Cleared when reading DCL_IDIFR register. + unsigned int icu_mode_changed_flag:1 ; // Set to 1 when at least one of the bit of the DLC_IMCIFR register is set. Cleared when reading DCL_IMCIFR register. + unsigned int picl_ok_flag :1 ; // Set to 1 when PICL transfer is finish. Cleared writting 1 to the bit 3 of the DLC_IFR register. + unsigned int scu_ok_flag :1 ; // Set to 1 when SCU sequence is finished. Cleared when writting 1 to the bit 4 of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_ok_flags :31; // Bit set to 1 when a rising edge of the signal i_icu_ok_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_ok_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_ioifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_delayed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_delayed_irq[ ] occurs and MSP is requester of the change mode order of the ICU . A read this register clears the register and the bit icu_delayed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_idifr_t; + +typedef union { + struct { + unsigned int padding0:1 ; + unsigned int icu_mode_changed_flags:31; // Bit set to 1 when a rising edge of the signal i_icu_mode_changed_irq[ ] occurs. A read this register clears the register and the bit icu_mode_changed_flag of the DLC_IFR register. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dlc_imcifr_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_dlc_pctrl : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(MAESTRO_DLC_PCTRL_START_BIT, MAESTRO_DLC_PCTRL_START_WIDTH); } + inline void paddr_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline uint32_t paddr_get() { return this->get_field(MAESTRO_DLC_PCTRL_PADDR_BIT, MAESTRO_DLC_PCTRL_PADDR_WIDTH); } + inline void dir_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline uint32_t dir_get() { return this->get_field(MAESTRO_DLC_PCTRL_DIR_BIT, MAESTRO_DLC_PCTRL_DIR_WIDTH); } + inline void pwdata_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } + inline uint32_t pwdata_get() { return this->get_field(MAESTRO_DLC_PCTRL_PWDATA_BIT, MAESTRO_DLC_PCTRL_PWDATA_WIDTH); } +}; + +class vp_maestro_prdata : public vp::reg_32 +{ +public: + inline void prdata_set(uint32_t value) { this->set_field(value, MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } + inline uint32_t prdata_get() { return this->get_field(MAESTRO_PRDATA_PRDATA_BIT, MAESTRO_PRDATA_PRDATA_WIDTH); } +}; + +class vp_maestro_dlc_sr : public vp::reg_32 +{ +public: + inline void picl_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline uint32_t picl_busy_get() { return this->get_field(MAESTRO_DLC_SR_PICL_BUSY_BIT, MAESTRO_DLC_SR_PICL_BUSY_WIDTH); } + inline void scu_busy_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } + inline uint32_t scu_busy_get() { return this->get_field(MAESTRO_DLC_SR_SCU_BUSY_BIT, MAESTRO_DLC_SR_SCU_BUSY_WIDTH); } +}; + +class vp_maestro_dlc_imr : public vp::reg_32 +{ +public: + inline void icu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline uint32_t icu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_OK_MASK_BIT, MAESTRO_DLC_IMR_ICU_OK_MASK_WIDTH); } + inline void icu_delayed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline uint32_t icu_delayed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_DELAYED_MASK_BIT, MAESTRO_DLC_IMR_ICU_DELAYED_MASK_WIDTH); } + inline void icu_mode_changed_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline uint32_t icu_mode_changed_mask_get() { return this->get_field(MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_BIT, MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_WIDTH); } + inline void picl_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline uint32_t picl_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_PICL_OK_MASK_BIT, MAESTRO_DLC_IMR_PICL_OK_MASK_WIDTH); } + inline void scu_ok_mask_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } + inline uint32_t scu_ok_mask_get() { return this->get_field(MAESTRO_DLC_IMR_SCU_OK_MASK_BIT, MAESTRO_DLC_IMR_SCU_OK_MASK_WIDTH); } +}; + +class vp_maestro_dlc_ifr : public vp::reg_32 +{ +public: + inline void icu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline uint32_t icu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_OK_FLAG_BIT, MAESTRO_DLC_IFR_ICU_OK_FLAG_WIDTH); } + inline void icu_delayed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline uint32_t icu_delayed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_WIDTH); } + inline void icu_mode_changed_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline uint32_t icu_mode_changed_flag_get() { return this->get_field(MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_BIT, MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_WIDTH); } + inline void picl_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline uint32_t picl_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_PICL_OK_FLAG_BIT, MAESTRO_DLC_IFR_PICL_OK_FLAG_WIDTH); } + inline void scu_ok_flag_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } + inline uint32_t scu_ok_flag_get() { return this->get_field(MAESTRO_DLC_IFR_SCU_OK_FLAG_BIT, MAESTRO_DLC_IFR_SCU_OK_FLAG_WIDTH); } +}; + +class vp_maestro_dlc_ioifr : public vp::reg_32 +{ +public: + inline void icu_ok_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } + inline uint32_t icu_ok_flags_get() { return this->get_field(MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_BIT, MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_idifr : public vp::reg_32 +{ +public: + inline void icu_delayed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } + inline uint32_t icu_delayed_flags_get() { return this->get_field(MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_BIT, MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_WIDTH); } +}; + +class vp_maestro_dlc_imcifr : public vp::reg_32 +{ +public: + inline void icu_mode_changed_flags_set(uint32_t value) { this->set_field(value, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } + inline uint32_t icu_mode_changed_flags_get() { return this->get_field(MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_BIT, MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int dlc_pctrl ; // PICL control register + unsigned int prdata ; // PICL data read register + unsigned int dlc_sr ; // Status register + unsigned int dlc_imr ; // Interrupt Mask register + unsigned int dlc_ifr ; // Interrupt flag register + unsigned int dlc_ioifr ; // icu_ok interrupt flag register + unsigned int dlc_idifr ; // icu_delayed interrupt flag register + unsigned int dlc_imcifr ; // icu_mode_changed interrupt flags register +} __attribute__((packed)) maestro_maestro_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_dlc_pctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_PCTRL_OFFSET); } +static inline void maestro_dlc_pctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_PCTRL_OFFSET, value); } + +static inline uint32_t maestro_prdata_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_PRDATA_OFFSET); } +static inline void maestro_prdata_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_PRDATA_OFFSET, value); } + +static inline uint32_t maestro_dlc_sr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_SR_OFFSET); } +static inline void maestro_dlc_sr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_SR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMR_OFFSET); } +static inline void maestro_dlc_imr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IFR_OFFSET); } +static inline void maestro_dlc_ifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_ioifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IOIFR_OFFSET); } +static inline void maestro_dlc_ioifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IOIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_idifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IDIFR_OFFSET); } +static inline void maestro_dlc_idifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IDIFR_OFFSET, value); } + +static inline uint32_t maestro_dlc_imcifr_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DLC_IMCIFR_OFFSET); } +static inline void maestro_dlc_imcifr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DLC_IMCIFR_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_DLC_PCTRL_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_PCTRL_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_PCTRL_START(val) ((val) << 0) + +#define MAESTRO_DLC_PCTRL_PADDR_GET(value) (ARCHI_BEXTRACTU((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_GETS(value) (ARCHI_BEXTRACT((value),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR_SET(value,field) (ARCHI_BINSERT((value),(field),14,1)) +#define MAESTRO_DLC_PCTRL_PADDR(val) ((val) << 1) + +#define MAESTRO_DLC_PCTRL_DIR_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define MAESTRO_DLC_PCTRL_DIR_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define MAESTRO_DLC_PCTRL_DIR(val) ((val) << 15) + +#define MAESTRO_DLC_PCTRL_PWDATA_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define MAESTRO_DLC_PCTRL_PWDATA(val) ((val) << 16) + +#define MAESTRO_PRDATA_PRDATA_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_PRDATA_PRDATA_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_PRDATA_PRDATA(val) ((val) << 0) + +#define MAESTRO_DLC_SR_PICL_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_SR_PICL_BUSY(val) ((val) << 0) + +#define MAESTRO_DLC_SR_SCU_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_SR_SCU_BUSY(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IMR_ICU_OK_MASK(val) ((val) << 0) + +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IMR_ICU_DELAYED_MASK(val) ((val) << 1) + +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IMR_ICU_MODE_CHANGED_MASK(val) ((val) << 2) + +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IMR_PICL_OK_MASK(val) ((val) << 3) + +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IMR_SCU_OK_MASK(val) ((val) << 4) + +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define MAESTRO_DLC_IFR_ICU_OK_FLAG(val) ((val) << 0) + +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define MAESTRO_DLC_IFR_ICU_DELAYED_FLAG(val) ((val) << 1) + +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define MAESTRO_DLC_IFR_ICU_MODE_CHANGED_FLAG(val) ((val) << 2) + +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define MAESTRO_DLC_IFR_PICL_OK_FLAG(val) ((val) << 3) + +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_DLC_IFR_SCU_OK_FLAG(val) ((val) << 4) + +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IOIFR_ICU_OK_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IDIFR_ICU_DELAYED_FLAGS(val) ((val) << 1) + +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GET(value) (ARCHI_BEXTRACTU((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_GETS(value) (ARCHI_BEXTRACT((value),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS_SET(value,field) (ARCHI_BINSERT((value),(field),31,1)) +#define MAESTRO_DLC_IMCIFR_ICU_MODE_CHANGED_FLAGS(val) ((val) << 1) + +#endif + + + +// +// GROUP dlc +// + +#define MAESTRO_DLC_OFFSET 0x0 + + + +// +// REGISTERS +// + + + +// +// REGISTERS FIELDS +// + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { +} __attribute__((packed)) maestro_dlc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#endif + + + +// +// GROUP wiu +// + +#define MAESTRO_WIU_OFFSET 0x1 + + + +// +// REGISTERS +// + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_0_OFFSET 0x0 + +// Interrupt Sequence Processing Mask registers +#define MAESTRO_WIU_ISPMR_1_OFFSET 0x1 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_0_OFFSET 0x2 + +// Interrupt Flag register +#define MAESTRO_WIU_IFR_1_OFFSET 0x3 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_0_OFFSET 0x4 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_1_OFFSET 0x5 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_2_OFFSET 0x6 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_3_OFFSET 0x7 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_4_OFFSET 0x8 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_5_OFFSET 0x9 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_6_OFFSET 0xa + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_7_OFFSET 0xb + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_8_OFFSET 0xc + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_9_OFFSET 0xd + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_10_OFFSET 0xe + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_11_OFFSET 0xf + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_12_OFFSET 0x10 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_13_OFFSET 0x11 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_14_OFFSET 0x12 + +// Interrupt Control registers +#define MAESTRO_WIU_ICR_15_OFFSET 0x13 + + + +// +// REGISTERS FIELDS +// + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] (access: R/W) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT 0 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH 8 +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_MASK 0xff +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_RESET 0x0 + +// Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. (access: R/W) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT 0 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH 8 +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_MASK 0xff +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT 0 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH 5 +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_MASK 0x1f +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT 0 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH 5 +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_MASK 0x1f +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT 0 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH 5 +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_MASK 0x1f +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT 0 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH 5 +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_MASK 0x1f +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT 0 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH 5 +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_MASK 0x1f +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT 0 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH 5 +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_MASK 0x1f +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT 0 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH 5 +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_MASK 0x1f +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT 0 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH 5 +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_MASK 0x1f +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT 0 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH 5 +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_MASK 0x1f +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT 0 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH 5 +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_MASK 0x1f +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT 0 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH 5 +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_MASK 0x1f +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT 0 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH 5 +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_MASK 0x1f +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT 0 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH 5 +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_MASK 0x1f +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT 0 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH 5 +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_MASK 0x1f +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT 0 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH 5 +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_MASK 0x1f +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_RESET 0x0 + +// Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active (access: R/W) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT 0 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH 5 +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_MASK 0x1f +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_0_t; + +typedef union { + struct { + unsigned int mask_modechg_en_irq:8 ; // A read of this register return the value of the mask. Writing 1 to the bit , set the mask of the interrupt i_irq[ ] + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ispmr_1_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_0_t; + +typedef union { + struct { + unsigned int flag_irq :8 ; // Bit is set when a rising egde of the signal i_irq [ 8 * + ] occurs or when writing the bit to 1. Bit is cleared when the associated SCU sequence is finished or when writing 0 to the bit of the WIU_ISPMR_m register or when writing the bit to 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_ifr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_0 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_0_t; + +typedef union { + struct { + unsigned int seq_sel_irq_1 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_1_t; + +typedef union { + struct { + unsigned int seq_sel_irq_2 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_2_t; + +typedef union { + struct { + unsigned int seq_sel_irq_3 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_3_t; + +typedef union { + struct { + unsigned int seq_sel_irq_4 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_4_t; + +typedef union { + struct { + unsigned int seq_sel_irq_5 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_5_t; + +typedef union { + struct { + unsigned int seq_sel_irq_6 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_6_t; + +typedef union { + struct { + unsigned int seq_sel_irq_7 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_7_t; + +typedef union { + struct { + unsigned int seq_sel_irq_8 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_8_t; + +typedef union { + struct { + unsigned int seq_sel_irq_9 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_9_t; + +typedef union { + struct { + unsigned int seq_sel_irq_10 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_10_t; + +typedef union { + struct { + unsigned int seq_sel_irq_11 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_11_t; + +typedef union { + struct { + unsigned int seq_sel_irq_12 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_12_t; + +typedef union { + struct { + unsigned int seq_sel_irq_13 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_13_t; + +typedef union { + struct { + unsigned int seq_sel_irq_14 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_14_t; + +typedef union { + struct { + unsigned int seq_sel_irq_15 :5 ; // Defines the sequence which has to be executed when the interrupt i_irq[

] becomes active + }; + unsigned int raw; +} __attribute__((packed)) maestro_wiu_icr_15_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_wiu_ispmr_0 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ispmr_1 : public vp::reg_8 +{ +public: + inline void mask_modechg_en_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } + inline uint8_t mask_modechg_en_irq_get() { return this->get_field(MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_BIT, MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_0 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_0_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_0_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_ifr_1 : public vp::reg_8 +{ +public: + inline void flag_irq_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } + inline uint8_t flag_irq_get() { return this->get_field(MAESTRO_WIU_IFR_1_FLAG_IRQ_BIT, MAESTRO_WIU_IFR_1_FLAG_IRQ_WIDTH); } +}; + +class vp_maestro_wiu_icr_0 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_0_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } + inline uint8_t seq_sel_irq_0_get() { return this->get_field(MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_BIT, MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_WIDTH); } +}; + +class vp_maestro_wiu_icr_1 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_1_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } + inline uint8_t seq_sel_irq_1_get() { return this->get_field(MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_BIT, MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_WIDTH); } +}; + +class vp_maestro_wiu_icr_2 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_2_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } + inline uint8_t seq_sel_irq_2_get() { return this->get_field(MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_BIT, MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_WIDTH); } +}; + +class vp_maestro_wiu_icr_3 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_3_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } + inline uint8_t seq_sel_irq_3_get() { return this->get_field(MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_BIT, MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_WIDTH); } +}; + +class vp_maestro_wiu_icr_4 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_4_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } + inline uint8_t seq_sel_irq_4_get() { return this->get_field(MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_BIT, MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_WIDTH); } +}; + +class vp_maestro_wiu_icr_5 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_5_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } + inline uint8_t seq_sel_irq_5_get() { return this->get_field(MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_BIT, MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_WIDTH); } +}; + +class vp_maestro_wiu_icr_6 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_6_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } + inline uint8_t seq_sel_irq_6_get() { return this->get_field(MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_BIT, MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_WIDTH); } +}; + +class vp_maestro_wiu_icr_7 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_7_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } + inline uint8_t seq_sel_irq_7_get() { return this->get_field(MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_BIT, MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_WIDTH); } +}; + +class vp_maestro_wiu_icr_8 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_8_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } + inline uint8_t seq_sel_irq_8_get() { return this->get_field(MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_BIT, MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_WIDTH); } +}; + +class vp_maestro_wiu_icr_9 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_9_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } + inline uint8_t seq_sel_irq_9_get() { return this->get_field(MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_BIT, MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_WIDTH); } +}; + +class vp_maestro_wiu_icr_10 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_10_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } + inline uint8_t seq_sel_irq_10_get() { return this->get_field(MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_BIT, MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_WIDTH); } +}; + +class vp_maestro_wiu_icr_11 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_11_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } + inline uint8_t seq_sel_irq_11_get() { return this->get_field(MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_BIT, MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_WIDTH); } +}; + +class vp_maestro_wiu_icr_12 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_12_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } + inline uint8_t seq_sel_irq_12_get() { return this->get_field(MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_BIT, MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_WIDTH); } +}; + +class vp_maestro_wiu_icr_13 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_13_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } + inline uint8_t seq_sel_irq_13_get() { return this->get_field(MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_BIT, MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_WIDTH); } +}; + +class vp_maestro_wiu_icr_14 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_14_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } + inline uint8_t seq_sel_irq_14_get() { return this->get_field(MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_BIT, MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_WIDTH); } +}; + +class vp_maestro_wiu_icr_15 : public vp::reg_8 +{ +public: + inline void seq_sel_irq_15_set(uint8_t value) { this->set_field(value, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } + inline uint8_t seq_sel_irq_15_get() { return this->get_field(MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_BIT, MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int wiu_ispmr_0 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ispmr_1 ; // Interrupt Sequence Processing Mask registers + unsigned int wiu_ifr_0 ; // Interrupt Flag register + unsigned int wiu_ifr_1 ; // Interrupt Flag register + unsigned int wiu_icr_0 ; // Interrupt Control registers + unsigned int wiu_icr_1 ; // Interrupt Control registers + unsigned int wiu_icr_2 ; // Interrupt Control registers + unsigned int wiu_icr_3 ; // Interrupt Control registers + unsigned int wiu_icr_4 ; // Interrupt Control registers + unsigned int wiu_icr_5 ; // Interrupt Control registers + unsigned int wiu_icr_6 ; // Interrupt Control registers + unsigned int wiu_icr_7 ; // Interrupt Control registers + unsigned int wiu_icr_8 ; // Interrupt Control registers + unsigned int wiu_icr_9 ; // Interrupt Control registers + unsigned int wiu_icr_10 ; // Interrupt Control registers + unsigned int wiu_icr_11 ; // Interrupt Control registers + unsigned int wiu_icr_12 ; // Interrupt Control registers + unsigned int wiu_icr_13 ; // Interrupt Control registers + unsigned int wiu_icr_14 ; // Interrupt Control registers + unsigned int wiu_icr_15 ; // Interrupt Control registers +} __attribute__((packed)) maestro_wiu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_wiu_ispmr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_0_OFFSET); } +static inline void maestro_wiu_ispmr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ispmr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ISPMR_1_OFFSET); } +static inline void maestro_wiu_ispmr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ISPMR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_0_OFFSET); } +static inline void maestro_wiu_ifr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_ifr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_IFR_1_OFFSET); } +static inline void maestro_wiu_ifr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_IFR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_0_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_0_OFFSET); } +static inline void maestro_wiu_icr_0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_0_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_1_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_1_OFFSET); } +static inline void maestro_wiu_icr_1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_1_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_2_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_2_OFFSET); } +static inline void maestro_wiu_icr_2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_2_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_3_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_3_OFFSET); } +static inline void maestro_wiu_icr_3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_3_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_4_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_4_OFFSET); } +static inline void maestro_wiu_icr_4_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_4_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_5_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_5_OFFSET); } +static inline void maestro_wiu_icr_5_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_5_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_6_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_6_OFFSET); } +static inline void maestro_wiu_icr_6_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_6_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_7_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_7_OFFSET); } +static inline void maestro_wiu_icr_7_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_7_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_8_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_8_OFFSET); } +static inline void maestro_wiu_icr_8_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_8_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_9_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_9_OFFSET); } +static inline void maestro_wiu_icr_9_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_9_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_10_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_10_OFFSET); } +static inline void maestro_wiu_icr_10_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_10_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_11_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_11_OFFSET); } +static inline void maestro_wiu_icr_11_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_11_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_12_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_12_OFFSET); } +static inline void maestro_wiu_icr_12_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_12_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_13_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_13_OFFSET); } +static inline void maestro_wiu_icr_13_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_13_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_14_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_14_OFFSET); } +static inline void maestro_wiu_icr_14_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_14_OFFSET, value); } + +static inline uint32_t maestro_wiu_icr_15_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_WIU_ICR_15_OFFSET); } +static inline void maestro_wiu_icr_15_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_WIU_ICR_15_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_0_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_ISPMR_1_MASK_MODECHG_EN_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_0_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define MAESTRO_WIU_IFR_1_FLAG_IRQ(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_0_SEQ_SEL_IRQ_0(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_1_SEQ_SEL_IRQ_1(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_2_SEQ_SEL_IRQ_2(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_3_SEQ_SEL_IRQ_3(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_4_SEQ_SEL_IRQ_4(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_5_SEQ_SEL_IRQ_5(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_6_SEQ_SEL_IRQ_6(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_7_SEQ_SEL_IRQ_7(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_8_SEQ_SEL_IRQ_8(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_9_SEQ_SEL_IRQ_9(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_10_SEQ_SEL_IRQ_10(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_11_SEQ_SEL_IRQ_11(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_12_SEQ_SEL_IRQ_12(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_13_SEQ_SEL_IRQ_13(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_14_SEQ_SEL_IRQ_14(val) ((val) << 0) + +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define MAESTRO_WIU_ICR_15_SEQ_SEL_IRQ_15(val) ((val) << 0) + +#endif + + + +// +// GROUP icu +// + + + +// +// REGISTERS +// + +// ICU control register +#define MAESTRO_ICU_CTRL_OFFSET 0x0 + +// ICU mode register +#define MAESTRO_ICU_MODE_OFFSET 0x1 + +// Island mode register +#define MAESTRO_ISLAND_MODE_OFFSET 0x2 + +// DMU mode register 0 +#define MAESTRO_DMU_MODE_OFFSET 0x3 + + + +// +// REGISTERS FIELDS +// + +// When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. (access: R/W) +#define MAESTRO_ICU_CTRL_ICU_CTRL_BIT 0 +#define MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH 4 +#define MAESTRO_ICU_CTRL_ICU_CTRL_MASK 0xf +#define MAESTRO_ICU_CTRL_ICU_CTRL_RESET 0x0 + +// Returns the current mode of the ICU when icu_mode_defined is low. (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_BIT 0 +#define MAESTRO_ICU_MODE_ICU_MODE_WIDTH 4 +#define MAESTRO_ICU_MODE_ICU_MODE_MASK 0xf +#define MAESTRO_ICU_MODE_ICU_MODE_RESET 0xf + +// When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits (access: R) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT 4 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH 1 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_MASK 0x10 +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_RESET 0x1 + +// Mode of the island. (access: R) +#define MAESTRO_ISLAND_MODE_ISL_MODE_BIT 0 +#define MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_ISLAND_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_ISLAND_MODE_ISL_MODE_RESET 0x0 + +// Mode of the DMU 0. (access: R) +#define MAESTRO_DMU_MODE_ISL_MODE_BIT 0 +#define MAESTRO_DMU_MODE_ISL_MODE_WIDTH 2 +#define MAESTRO_DMU_MODE_ISL_MODE_MASK 0x3 +#define MAESTRO_DMU_MODE_ISL_MODE_RESET 0x0 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int icu_ctrl :4 ; // When a new mode corresponding to one of sixteen mode of the island mode table of the ICU is written as mode transition sequence is started to reach the written mode. + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_ctrl_t; + +typedef union { + struct { + unsigned int icu_mode :4 ; // Returns the current mode of the ICU when icu_mode_defined is low. + unsigned int icu_mode_defined:1 ; // When high, indicates that the current mode of the ICU is not defined in the mode table of the ICU When low, the value of the current mode is given by the icu_mode bits + }; + unsigned int raw; +} __attribute__((packed)) maestro_icu_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the island. + }; + unsigned int raw; +} __attribute__((packed)) maestro_island_mode_t; + +typedef union { + struct { + unsigned int isl_mode :2 ; // Mode of the DMU 0. + }; + unsigned int raw; +} __attribute__((packed)) maestro_dmu_mode_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_maestro_icu_ctrl : public vp::reg_8 +{ +public: + inline void icu_ctrl_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } + inline uint8_t icu_ctrl_get() { return this->get_field(MAESTRO_ICU_CTRL_ICU_CTRL_BIT, MAESTRO_ICU_CTRL_ICU_CTRL_WIDTH); } +}; + +class vp_maestro_icu_mode : public vp::reg_8 +{ +public: + inline void icu_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline uint8_t icu_mode_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_BIT, MAESTRO_ICU_MODE_ICU_MODE_WIDTH); } + inline void icu_mode_defined_set(uint8_t value) { this->set_field(value, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } + inline uint8_t icu_mode_defined_get() { return this->get_field(MAESTRO_ICU_MODE_ICU_MODE_DEFINED_BIT, MAESTRO_ICU_MODE_ICU_MODE_DEFINED_WIDTH); } +}; + +class vp_maestro_island_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_ISLAND_MODE_ISL_MODE_BIT, MAESTRO_ISLAND_MODE_ISL_MODE_WIDTH); } +}; + +class vp_maestro_dmu_mode : public vp::reg_8 +{ +public: + inline void isl_mode_set(uint8_t value) { this->set_field(value, MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } + inline uint8_t isl_mode_get() { return this->get_field(MAESTRO_DMU_MODE_ISL_MODE_BIT, MAESTRO_DMU_MODE_ISL_MODE_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int icu_ctrl ; // ICU control register + unsigned int icu_mode ; // ICU mode register + unsigned int island_mode ; // Island mode register + unsigned int dmu_mode ; // DMU mode register 0 +} __attribute__((packed)) maestro_icu_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t maestro_icu_ctrl_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_CTRL_OFFSET); } +static inline void maestro_icu_ctrl_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_CTRL_OFFSET, value); } + +static inline uint32_t maestro_icu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ICU_MODE_OFFSET); } +static inline void maestro_icu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ICU_MODE_OFFSET, value); } + +static inline uint32_t maestro_island_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_ISLAND_MODE_OFFSET); } +static inline void maestro_island_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_ISLAND_MODE_OFFSET, value); } + +static inline uint32_t maestro_dmu_mode_get(uint32_t base) { return ARCHI_READ(base, MAESTRO_DMU_MODE_OFFSET); } +static inline void maestro_dmu_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, MAESTRO_DMU_MODE_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define MAESTRO_ICU_CTRL_ICU_CTRL_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_CTRL_ICU_CTRL(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define MAESTRO_ICU_MODE_ICU_MODE(val) ((val) << 0) + +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define MAESTRO_ICU_MODE_ICU_MODE_DEFINED(val) ((val) << 4) + +#define MAESTRO_ISLAND_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_ISLAND_MODE_ISL_MODE(val) ((val) << 0) + +#define MAESTRO_DMU_MODE_ISL_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define MAESTRO_DMU_MODE_ISL_MODE(val) ((val) << 0) + +#endif + + + +// +// CUSTOM FIELDS +// +#define MAESTRO_ICU_SUPPLY_EXT 0x0 +#define MAESTRO_ICU_SUPPLY_RET 0x1 +#define MAESTRO_ICU_SUPPLY_CKOFF 0x2 +#define MAESTRO_ICU_SUPPLY_ON 0x3 +#define MAESTRO_ICU_REGU_NONE 0x7 +#define MAESTRO_ICU_REGU_OFF 0x0 +#define MAESTRO_ICU_REGU_RV 0x1 +#define MAESTRO_ICU_REGU_LV 0x2 +#define MAESTRO_ICU_REGU_MV 0x3 +#define MAESTRO_ICU_REGU_NV 0x4 +#define MAESTRO_ICU_CLK_FNONE 0x7 +#define MAESTRO_ICU_CLK_FOFF 0x0 +#define MAESTRO_ICU_CLK_LF 0x1 +#define MAESTRO_ICU_CLK_MF 0x2 +#define MAESTRO_ICU_CLK_NF 0x3 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/mailbox/mailbox_v0.h b/sw/pulp-sdk/archi/include/archi/mailbox/mailbox_v0.h new file mode 100644 index 0000000..8013c9f --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/mailbox/mailbox_v0.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_MAILBOX_V0_H__ +#define __ARCHI_MAILBOX_V0_H__ + +#if PULP_CHIP_FAMILY != CHIP_BIGPULP +#error This file must be included only for bigpulp chip +#endif + +/* MAILBOX REGISTERS */ +#define MAILBOX_REG_WRDATA ( ARCHI_MAILBOX_BASE_ADDR + 0x0 ) +#define MAILBOX_REG_RDDATA ( ARCHI_MAILBOX_BASE_ADDR + 0x8 ) +#define MAILBOX_REG_STATUS ( ARCHI_MAILBOX_BASE_ADDR + 0x10) +#define MAILBOX_REG_ERROR ( ARCHI_MAILBOX_BASE_ADDR + 0x14) +#define MAILBOX_REG_IS ( ARCHI_MAILBOX_BASE_ADDR + 0x20) +#define MAILBOX_REG_IE ( ARCHI_MAILBOX_BASE_ADDR + 0x24) + +/* SIGNALING */ +#define PULP_READY ( 0x01U ) +#define PULP_START ( 0x02U ) +#define PULP_BUSY ( 0x03U ) +#define PULP_DONE ( 0x04U ) +#define PULP_STOP ( 0x0FU ) + +#define HOST_READY ( 0x1000U ) +#define HOST_DONE ( 0x3000U ) + +#define MBOX_N_BITS_REQ_TYPE ( 4U ) // number of MSBs to specify the type +#define RAB_UPDATE_N_BITS_ELEM ( 8U ) // number of bits to specify the mask of elements to be updated +#define RAB_UPDATE_N_BITS_TYPE ( 2U ) // number of bits to specify the update type + +#define TO_RUNTIME ( 0x10000000U ) // bypass PULP driver +#define RAB_UPDATE ( 0x20000000U ) // handled by PULP driver +#define RAB_SWITCH ( 0x30000000U ) // handled by PULP driver + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/or1k/spr-defs.h b/sw/pulp-sdk/archi/include/archi/or1k/spr-defs.h new file mode 100644 index 0000000..ec4c6ec --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/or1k/spr-defs.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_OR1K_SPR_DEFS_H +#define _ARCHI_OR1K_SPR_DEFS_H + +/* Definition of special-purpose registers (SPRs). */ +#define MAX_GRPS (32) +#define MAX_SPRS_PER_GRP_BITS (11) +#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS) +#define MAX_SPRS (0x10000) + +/* Base addresses for the groups */ +#define SPRGROUP_SYS (0<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PC (7<< MAX_SPRS_PER_GRP_BITS) + +/* System control and status group */ +#define SPR_SR (SPRGROUP_SYS + 17) +#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) + +/* PULP registers */ +#define SPR_CORE_ID (SPRGROUP_SYS + 0x680) +#define SPR_CLUSTER_ID (SPRGROUP_SYS + 0x681) + +/* Performance counters group */ +#define SPR_PCCR(N) (SPRGROUP_PC + (N)) +#define SPR_PCER (SPRGROUP_PC + 32) +#define SPR_PCMR (SPRGROUP_PC + 33) + + +/* + * Bit definitions for the Supervision Register + * + */ + + +#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */ + +#define SPR_PCER_CYCLES 0 /* Count the number of cycles the core was running */ +#define SPR_PCER_INSTR 1 /* Count the number of instructions executed */ +#define SPR_PCER_LD_STALL 2 /* Number of load data hazards */ +#define SPR_PCER_JMP_STALL 3 /* Number of jump register data hazards */ +#define SPR_PCER_IMISS 4 /* Cycles waiting for instruction fetches. i.e. the number of instructions wasted due to non-ideal caches */ +#define SPR_PCER_WBRANCH 5 /* Number of wrong predicted branches */ +#define SPR_PCER_WBRANCH_CYC 6 /* Cycles wasted due to wrong predicted branches */ +#define SPR_PCER_LD 7 /* Number of memory loads executed. Misaligned accesses are counted twice */ +#define SPR_PCER_ST 8 /* Number of memory stores executed. Misaligned accesses are counted twice */ +#define SPR_PCER_JUMP 9 /* Number of jump instructions seen, i.e. j, jr, jal, jalr */ +#define SPR_PCER_BRANCH 10 /* Number of jump instructions seen, i.e. bf, bnf */ +#define SPR_PCER_DELAY_NOP 11 /* Number of empty delay slots, i.e. delay slots filled with a nop */ +#define SPR_PCER_LD_EXT 12 /* Number of memory loads to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define SPR_PCER_ST_EXT 13 /* Number of memory stores to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define SPR_PCER_LD_EXT_CYC 14 /* Cycles used for memory loads to EXT. Every non-TCDM access is considered external */ +#define SPR_PCER_ST_EXT_CYC 15 /* Cycles used for memory stores to EXT. Every non-TCDM access is considered external */ +#define SPR_PCER_TCDM_CONT 16 /* Cycles wasted due to TCDM/log-interconnect contention */ + +#define CSR_PCER_NB_EVENTS 17 +#define SPR_PCER_NB_EVENTS 17 +#define CSR_PCER_NB_INTERNAL_EVENTS 12 + +#define CSR_NB_PCCR 31 + +// Gives from the event ID, the HW mask that can be stored (with an OR with other events mask) to the PCER +#define SPR_PCER_EVENT_MASK(eventId) (1<<(eventId)) +#define SPR_PCER_ALL_EVENTS_MASK 0xffffffff + +#define SPR_PCMR_ACTIVE 0x1 /* Activate counting */ +#define SPR_PCMR_SATURATE 0x2 /* Activate saturation */ + + + + +#endif /* SPR_DEFS__H */ diff --git a/sw/pulp-sdk/archi/include/archi/pulp.h b/sw/pulp-sdk/archi/include/archi/pulp.h new file mode 100644 index 0000000..baac01e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pulp.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULP_H__ +#define __ARCHI_PULP_H__ + +#include "archi/pulp_defs.h" +#include "archi/utils.h" + +#define __A_PULP_CHIP_INC(x) #x +#define _A_PULP_CHIP_INC(x) __A_PULP_CHIP_INC(archi/chips/x/pulp.h) +#define A_PULP_CHIP_INC(x) _A_PULP_CHIP_INC(x) + +#if defined(PULP_CHIP_FAMILY) +#include A_PULP_CHIP_INC(PULP_CHIP_FAMILY_STR) +#else +#include A_PULP_CHIP_INC(PULP_CHIP_STR) +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/pulp_defs.h b/sw/pulp-sdk/archi/include/archi/pulp_defs.h new file mode 100644 index 0000000..167a139 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pulp_defs.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_PULP_DEFS_H__ +#define __ARCHI_PULP_DEFS_H__ + +#define CHIP_MIA 0 +#define CHIP_HONEY 1 +#define CHIP_FULMINE 2 +#define CHIP_PULP4 3 +#define CHIP_PULPEVO 4 +#define CHIP_PULP4Z 5 +#define CHIP_PULP3 6 +#define CHIP_BIGPULP 7 +#define CHIP_BIGPULP_Z_7020 8 +#define CHIP_BIGPULP_Z_7045 9 +#define CHIP_BIGPULP_Z_7045_O 19 +#define CHIP_BIGPULP_Z_7045_RISCV 20 +#define CHIP_GAP 10 +#define CHIP_GAP8 10 +#define CHIP_VIVOSOC2 11 +#define CHIP_FULMINE8 12 +#define CHIP_EXACONV 13 +#define CHIP_WOLFE 14 +#define CHIP_NEURAGHE 15 +#define CHIP_PATRONUS 16 +#define CHIP_VIVOSOC3 17 +#define CHIP_VIVOSOC2_1 18 +#define CHIP_PULPINO 21 +#define CHIP_QUENTIN 22 +#define CHIP_KERBIN 23 +#define CHIP_OPRECOMPKW 24 +#define CHIP_LUPO 25 +#define CHIP_DEVCHIP 26 +#define CHIP_PULPISSIMO 27 +#define CHIP_BIGPULP_ZUX 28 +#define CHIP_PULP 29 +#define CHIP_MULTINO 30 +#define CHIP_VEGA 31 +#define CHIP_HERO_Z_7045 32 +#define CHIP_OPRECOMPKW_SA 33 +#define CHIP_OPRECOMPKW_SFLOAT 34 +#define CHIP_OPRECOMPKW_SFLOAT_SA 35 +#define CHIP_ARNOLD 36 +#define CHIP_BIGPULP_STANDALONE 37 +#define CHIP_GAP_REV1 38 +#define CHIP_USOC_V1 39 +#define CHIP_BIGPULP_JUNO 40 +#define CHIP_BIGPULP_ZU9EG 41 +#define CHIP_PULPISSIMO_V1 42 +#define CHIP_VIVOSOC3_5 43 +#define CHIP_PULP_V1 44 +#define CHIP_VIVOSOC3_1 45 +#define CHIP_GAP8_REVC 46 +#define CHIP_GAP9 47 +#define CHIP_VIVOSOC4 48 +#define CHIP_WOLFE_16 49 + +#define CORE_OR1K_V1 0 +#define CORE_OR1K_V2 1 +#define CORE_OR1K_V3 2 +#define CORE_OR1K_V4 3 +#define CORE_OR1K_V5 4 + +#define CORE_RISCV_V1 100 +#define CORE_RISCV_V2 101 +#define CORE_RISCV_V3 102 +#define CORE_RISCV_V4 103 + +#define ARCHI_PLATFORM_OTHER 0 +#define ARCHI_PLATFORM_FPGA 1 +#define ARCHI_PLATFORM_RTL 2 +#define ARCHI_PLATFORM_GVSOC 3 +#define ARCHI_PLATFORM_BOARD 4 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/pwm/pwm_v1.h b/sw/pulp-sdk/archi/include/archi/pwm/pwm_v1.h new file mode 100644 index 0000000..2b14c62 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/pwm_v1.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna and + * GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_PWM_PWM_V1_H__ +#define __ARCHI_PWM_PWM_V1_H__ + +#include "archi/pulp.h" + +#define PWM_TIMER_TO_TIMER_OFFSET 0x40 + +#define PWM_TIMER_CMD_OFFSET 0x00 +#define PWM_TIMER_CONFIG_OFFSET 0x04 +#define PWM_TIMER_THRESHOLD_OFFSET 0x08 +#define PWM_TIMER_TH_CHANNEL_OFFSET 0x0C +#define PWM_TIMER_LUT_CHANNEL_OFFSET 0x1C +#define PWM_TIMER_COUNTER_OFFSET 0x2C + +#define PWM_CHANNEL_TO_CHANNEL_OFFSET 0x04 + +/* Timer Base: PWM_BASE_ADDR + Timer*PWM_TIMER_TO_TIMER_OFFSET + Config: + PWM_TIMER_CONFIG_OFFSET + Threhsold: + PWM_TIMER_THRESHOLD_OFFSET + Channel Thresh: + PWM_TIMER_TH_CHANNEL_OFFSET + Channel*PWM_CHANNEL_TO_CHANNEL_OFFSET + Channel LUT: + PWM_TIMER_LUT_CHANNEL_OFFSET + Channel*PWM_CHANNEL_TO_CHANNEL_OFFSET +*/ +#define PWM_TIMER_BASE_ADDR(timer) (ARCHI_PWM_ADDR + timer*PWM_TIMER_TO_TIMER_OFFSET) +#define PWM_TIMER_CMD_ADDR(timer) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_CMD_OFFSET) +#define PWM_TIMER_CONFIG_ADDR(timer) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_CONFIG_OFFSET) +#define PWM_TIMER_THRESHOLD_ADDR(timer) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_THRESHOLD_OFFSET) +#define PWM_TIMER_TH_CHANNEL_ADDR(timer, channel) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_TH_CHANNEL_OFFSET + (channel*PWM_CHANNEL_TO_CHANNEL_OFFSET)) +#define PWM_TIMER_LUT_CHANNEL_ADDR(timer, channel) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_LUT_CHANNEL_OFFSET + (channel*PWM_CHANNEL_TO_CHANNEL_OFFSET)) +#define PWM_TIMER_COUNTER_ADDR(timer) (PWM_TIMER_BASE_ADDR(timer) + PWM_TIMER_COUNTER_OFFSET) + +#define REG_EVENT_CFG (ARCHI_PWM_ADDR + 0x100) +#define REG_PWM_TIMER_EN (ARCHI_PWM_ADDR + 0X104) + +#define PWM_TIMER_EN(timer) (0x1< +#include "archi/utils.h" + +#endif + +#include "pwm_v1_regs.h" +#include "pwm_v1_regfields.h" +#include "pwm_v1_structs.h" +#include "pwm_v1_regmap.h" +#include "pwm_v1_accessors.h" +#include "pwm_v1_macros.h" +#include "pwm_v1_groups.h" +#include "pwm_v1_constants.h" + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_accessors.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_accessors.h new file mode 100644 index 0000000..02e793e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_accessors.h @@ -0,0 +1,145 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_ACCESSORS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_ACCESSORS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +static inline uint32_t pwm_t0_cmd_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_CMD_OFFSET); } +static inline void pwm_t0_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_CMD_OFFSET, value); } + +static inline uint32_t pwm_t0_config_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_CONFIG_OFFSET); } +static inline void pwm_t0_config_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_CONFIG_OFFSET, value); } + +static inline uint32_t pwm_t0_threshold_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_THRESHOLD_OFFSET); } +static inline void pwm_t0_threshold_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_THRESHOLD_OFFSET, value); } + +static inline uint32_t pwm_t0_th_channel0_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_TH_CHANNEL0_OFFSET); } +static inline void pwm_t0_th_channel0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_TH_CHANNEL0_OFFSET, value); } + +static inline uint32_t pwm_t0_th_channel1_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_TH_CHANNEL1_OFFSET); } +static inline void pwm_t0_th_channel1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_TH_CHANNEL1_OFFSET, value); } + +static inline uint32_t pwm_t0_th_channel2_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_TH_CHANNEL2_OFFSET); } +static inline void pwm_t0_th_channel2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_TH_CHANNEL2_OFFSET, value); } + +static inline uint32_t pwm_t0_th_channel3_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_TH_CHANNEL3_OFFSET); } +static inline void pwm_t0_th_channel3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_TH_CHANNEL3_OFFSET, value); } + +static inline uint32_t pwm_t0_counter_get(uint32_t base) { return ARCHI_READ(base, PWM_T0_COUNTER_OFFSET); } +static inline void pwm_t0_counter_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T0_COUNTER_OFFSET, value); } + +static inline uint32_t pwm_t1_cmd_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_CMD_OFFSET); } +static inline void pwm_t1_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_CMD_OFFSET, value); } + +static inline uint32_t pwm_t1_config_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_CONFIG_OFFSET); } +static inline void pwm_t1_config_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_CONFIG_OFFSET, value); } + +static inline uint32_t pwm_t1_threshold_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_THRESHOLD_OFFSET); } +static inline void pwm_t1_threshold_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_THRESHOLD_OFFSET, value); } + +static inline uint32_t pwm_t1_th_channel0_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_TH_CHANNEL0_OFFSET); } +static inline void pwm_t1_th_channel0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_TH_CHANNEL0_OFFSET, value); } + +static inline uint32_t pwm_t1_th_channel1_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_TH_CHANNEL1_OFFSET); } +static inline void pwm_t1_th_channel1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_TH_CHANNEL1_OFFSET, value); } + +static inline uint32_t pwm_t1_th_channel2_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_TH_CHANNEL2_OFFSET); } +static inline void pwm_t1_th_channel2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_TH_CHANNEL2_OFFSET, value); } + +static inline uint32_t pwm_t1_th_channel3_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_TH_CHANNEL3_OFFSET); } +static inline void pwm_t1_th_channel3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_TH_CHANNEL3_OFFSET, value); } + +static inline uint32_t pwm_t1_counter_get(uint32_t base) { return ARCHI_READ(base, PWM_T1_COUNTER_OFFSET); } +static inline void pwm_t1_counter_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T1_COUNTER_OFFSET, value); } + +static inline uint32_t pwm_t2_cmd_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_CMD_OFFSET); } +static inline void pwm_t2_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_CMD_OFFSET, value); } + +static inline uint32_t pwm_t2_config_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_CONFIG_OFFSET); } +static inline void pwm_t2_config_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_CONFIG_OFFSET, value); } + +static inline uint32_t pwm_t2_threshold_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_THRESHOLD_OFFSET); } +static inline void pwm_t2_threshold_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_THRESHOLD_OFFSET, value); } + +static inline uint32_t pwm_t2_th_channel0_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_TH_CHANNEL0_OFFSET); } +static inline void pwm_t2_th_channel0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_TH_CHANNEL0_OFFSET, value); } + +static inline uint32_t pwm_t2_th_channel1_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_TH_CHANNEL1_OFFSET); } +static inline void pwm_t2_th_channel1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_TH_CHANNEL1_OFFSET, value); } + +static inline uint32_t pwm_t2_th_channel2_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_TH_CHANNEL2_OFFSET); } +static inline void pwm_t2_th_channel2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_TH_CHANNEL2_OFFSET, value); } + +static inline uint32_t pwm_t2_th_channel3_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_TH_CHANNEL3_OFFSET); } +static inline void pwm_t2_th_channel3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_TH_CHANNEL3_OFFSET, value); } + +static inline uint32_t pwm_t2_counter_get(uint32_t base) { return ARCHI_READ(base, PWM_T2_COUNTER_OFFSET); } +static inline void pwm_t2_counter_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T2_COUNTER_OFFSET, value); } + +static inline uint32_t pwm_t3_cmd_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_CMD_OFFSET); } +static inline void pwm_t3_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_CMD_OFFSET, value); } + +static inline uint32_t pwm_t3_config_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_CONFIG_OFFSET); } +static inline void pwm_t3_config_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_CONFIG_OFFSET, value); } + +static inline uint32_t pwm_t3_threshold_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_THRESHOLD_OFFSET); } +static inline void pwm_t3_threshold_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_THRESHOLD_OFFSET, value); } + +static inline uint32_t pwm_t3_th_channel0_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_TH_CHANNEL0_OFFSET); } +static inline void pwm_t3_th_channel0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_TH_CHANNEL0_OFFSET, value); } + +static inline uint32_t pwm_t3_th_channel1_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_TH_CHANNEL1_OFFSET); } +static inline void pwm_t3_th_channel1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_TH_CHANNEL1_OFFSET, value); } + +static inline uint32_t pwm_t3_th_channel2_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_TH_CHANNEL2_OFFSET); } +static inline void pwm_t3_th_channel2_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_TH_CHANNEL2_OFFSET, value); } + +static inline uint32_t pwm_t3_th_channel3_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_TH_CHANNEL3_OFFSET); } +static inline void pwm_t3_th_channel3_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_TH_CHANNEL3_OFFSET, value); } + +static inline uint32_t pwm_t3_counter_get(uint32_t base) { return ARCHI_READ(base, PWM_T3_COUNTER_OFFSET); } +static inline void pwm_t3_counter_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_T3_COUNTER_OFFSET, value); } + +static inline uint32_t pwm_event_cfg_get(uint32_t base) { return ARCHI_READ(base, PWM_EVENT_CFG_OFFSET); } +static inline void pwm_event_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_EVENT_CFG_OFFSET, value); } + +static inline uint32_t pwm_cg_get(uint32_t base) { return ARCHI_READ(base, PWM_CG_OFFSET); } +static inline void pwm_cg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, PWM_CG_OFFSET, value); } + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_constants.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_constants.h new file mode 100644 index 0000000..7942869 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_constants.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_CONSTANTS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_CONSTANTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_groups.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_groups.h new file mode 100644 index 0000000..072d56c --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_groups.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_GROUPS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_GROUPS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_gvsoc.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_gvsoc.h new file mode 100644 index 0000000..da2d7b2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_gvsoc.h @@ -0,0 +1,385 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_GVSOC_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_GVSOC_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_pwm_t0_cmd : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, PWM_T0_CMD_START_BIT, PWM_T0_CMD_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(PWM_T0_CMD_START_BIT, PWM_T0_CMD_START_WIDTH); } + inline void stop_set(uint32_t value) { this->set_field(value, PWM_T0_CMD_STOP_BIT, PWM_T0_CMD_STOP_WIDTH); } + inline uint32_t stop_get() { return this->get_field(PWM_T0_CMD_STOP_BIT, PWM_T0_CMD_STOP_WIDTH); } + inline void update_set(uint32_t value) { this->set_field(value, PWM_T0_CMD_UPDATE_BIT, PWM_T0_CMD_UPDATE_WIDTH); } + inline uint32_t update_get() { return this->get_field(PWM_T0_CMD_UPDATE_BIT, PWM_T0_CMD_UPDATE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, PWM_T0_CMD_RESET_BIT, PWM_T0_CMD_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(PWM_T0_CMD_RESET_BIT, PWM_T0_CMD_RESET_WIDTH); } + inline void arm_set(uint32_t value) { this->set_field(value, PWM_T0_CMD_ARM_BIT, PWM_T0_CMD_ARM_WIDTH); } + inline uint32_t arm_get() { return this->get_field(PWM_T0_CMD_ARM_BIT, PWM_T0_CMD_ARM_WIDTH); } +}; + +class vp_pwm_t0_config : public vp::reg_32 +{ +public: + inline void insel_set(uint32_t value) { this->set_field(value, PWM_T0_CONFIG_INSEL_BIT, PWM_T0_CONFIG_INSEL_WIDTH); } + inline uint32_t insel_get() { return this->get_field(PWM_T0_CONFIG_INSEL_BIT, PWM_T0_CONFIG_INSEL_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T0_CONFIG_MODE_BIT, PWM_T0_CONFIG_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T0_CONFIG_MODE_BIT, PWM_T0_CONFIG_MODE_WIDTH); } + inline void clksel_set(uint32_t value) { this->set_field(value, PWM_T0_CONFIG_CLKSEL_BIT, PWM_T0_CONFIG_CLKSEL_WIDTH); } + inline uint32_t clksel_get() { return this->get_field(PWM_T0_CONFIG_CLKSEL_BIT, PWM_T0_CONFIG_CLKSEL_WIDTH); } + inline void updownsel_set(uint32_t value) { this->set_field(value, PWM_T0_CONFIG_UPDOWNSEL_BIT, PWM_T0_CONFIG_UPDOWNSEL_WIDTH); } + inline uint32_t updownsel_get() { return this->get_field(PWM_T0_CONFIG_UPDOWNSEL_BIT, PWM_T0_CONFIG_UPDOWNSEL_WIDTH); } + inline void presc_set(uint32_t value) { this->set_field(value, PWM_T0_CONFIG_PRESC_BIT, PWM_T0_CONFIG_PRESC_WIDTH); } + inline uint32_t presc_get() { return this->get_field(PWM_T0_CONFIG_PRESC_BIT, PWM_T0_CONFIG_PRESC_WIDTH); } +}; + +class vp_pwm_t0_threshold : public vp::reg_32 +{ +public: + inline void th_lo_set(uint32_t value) { this->set_field(value, PWM_T0_THRESHOLD_TH_LO_BIT, PWM_T0_THRESHOLD_TH_LO_WIDTH); } + inline uint32_t th_lo_get() { return this->get_field(PWM_T0_THRESHOLD_TH_LO_BIT, PWM_T0_THRESHOLD_TH_LO_WIDTH); } + inline void th_hi_set(uint32_t value) { this->set_field(value, PWM_T0_THRESHOLD_TH_HI_BIT, PWM_T0_THRESHOLD_TH_HI_WIDTH); } + inline uint32_t th_hi_get() { return this->get_field(PWM_T0_THRESHOLD_TH_HI_BIT, PWM_T0_THRESHOLD_TH_HI_WIDTH); } +}; + +class vp_pwm_t0_th_channel0 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL0_TH_BIT, PWM_T0_TH_CHANNEL0_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T0_TH_CHANNEL0_TH_BIT, PWM_T0_TH_CHANNEL0_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL0_MODE_BIT, PWM_T0_TH_CHANNEL0_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T0_TH_CHANNEL0_MODE_BIT, PWM_T0_TH_CHANNEL0_MODE_WIDTH); } +}; + +class vp_pwm_t0_th_channel1 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL1_TH_BIT, PWM_T0_TH_CHANNEL1_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T0_TH_CHANNEL1_TH_BIT, PWM_T0_TH_CHANNEL1_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL1_MODE_BIT, PWM_T0_TH_CHANNEL1_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T0_TH_CHANNEL1_MODE_BIT, PWM_T0_TH_CHANNEL1_MODE_WIDTH); } +}; + +class vp_pwm_t0_th_channel2 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL2_TH_BIT, PWM_T0_TH_CHANNEL2_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T0_TH_CHANNEL2_TH_BIT, PWM_T0_TH_CHANNEL2_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL2_MODE_BIT, PWM_T0_TH_CHANNEL2_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T0_TH_CHANNEL2_MODE_BIT, PWM_T0_TH_CHANNEL2_MODE_WIDTH); } +}; + +class vp_pwm_t0_th_channel3 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL3_TH_BIT, PWM_T0_TH_CHANNEL3_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T0_TH_CHANNEL3_TH_BIT, PWM_T0_TH_CHANNEL3_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T0_TH_CHANNEL3_MODE_BIT, PWM_T0_TH_CHANNEL3_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T0_TH_CHANNEL3_MODE_BIT, PWM_T0_TH_CHANNEL3_MODE_WIDTH); } +}; + +class vp_pwm_t0_counter : public vp::reg_32 +{ +public: +}; + +class vp_pwm_t1_cmd : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, PWM_T1_CMD_START_BIT, PWM_T1_CMD_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(PWM_T1_CMD_START_BIT, PWM_T1_CMD_START_WIDTH); } + inline void stop_set(uint32_t value) { this->set_field(value, PWM_T1_CMD_STOP_BIT, PWM_T1_CMD_STOP_WIDTH); } + inline uint32_t stop_get() { return this->get_field(PWM_T1_CMD_STOP_BIT, PWM_T1_CMD_STOP_WIDTH); } + inline void update_set(uint32_t value) { this->set_field(value, PWM_T1_CMD_UPDATE_BIT, PWM_T1_CMD_UPDATE_WIDTH); } + inline uint32_t update_get() { return this->get_field(PWM_T1_CMD_UPDATE_BIT, PWM_T1_CMD_UPDATE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, PWM_T1_CMD_RESET_BIT, PWM_T1_CMD_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(PWM_T1_CMD_RESET_BIT, PWM_T1_CMD_RESET_WIDTH); } + inline void arm_set(uint32_t value) { this->set_field(value, PWM_T1_CMD_ARM_BIT, PWM_T1_CMD_ARM_WIDTH); } + inline uint32_t arm_get() { return this->get_field(PWM_T1_CMD_ARM_BIT, PWM_T1_CMD_ARM_WIDTH); } +}; + +class vp_pwm_t1_config : public vp::reg_32 +{ +public: + inline void insel_set(uint32_t value) { this->set_field(value, PWM_T1_CONFIG_INSEL_BIT, PWM_T1_CONFIG_INSEL_WIDTH); } + inline uint32_t insel_get() { return this->get_field(PWM_T1_CONFIG_INSEL_BIT, PWM_T1_CONFIG_INSEL_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T1_CONFIG_MODE_BIT, PWM_T1_CONFIG_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T1_CONFIG_MODE_BIT, PWM_T1_CONFIG_MODE_WIDTH); } + inline void clksel_set(uint32_t value) { this->set_field(value, PWM_T1_CONFIG_CLKSEL_BIT, PWM_T1_CONFIG_CLKSEL_WIDTH); } + inline uint32_t clksel_get() { return this->get_field(PWM_T1_CONFIG_CLKSEL_BIT, PWM_T1_CONFIG_CLKSEL_WIDTH); } + inline void updownsel_set(uint32_t value) { this->set_field(value, PWM_T1_CONFIG_UPDOWNSEL_BIT, PWM_T1_CONFIG_UPDOWNSEL_WIDTH); } + inline uint32_t updownsel_get() { return this->get_field(PWM_T1_CONFIG_UPDOWNSEL_BIT, PWM_T1_CONFIG_UPDOWNSEL_WIDTH); } + inline void presc_set(uint32_t value) { this->set_field(value, PWM_T1_CONFIG_PRESC_BIT, PWM_T1_CONFIG_PRESC_WIDTH); } + inline uint32_t presc_get() { return this->get_field(PWM_T1_CONFIG_PRESC_BIT, PWM_T1_CONFIG_PRESC_WIDTH); } +}; + +class vp_pwm_t1_threshold : public vp::reg_32 +{ +public: + inline void th_lo_set(uint32_t value) { this->set_field(value, PWM_T1_THRESHOLD_TH_LO_BIT, PWM_T1_THRESHOLD_TH_LO_WIDTH); } + inline uint32_t th_lo_get() { return this->get_field(PWM_T1_THRESHOLD_TH_LO_BIT, PWM_T1_THRESHOLD_TH_LO_WIDTH); } + inline void th_hi_set(uint32_t value) { this->set_field(value, PWM_T1_THRESHOLD_TH_HI_BIT, PWM_T1_THRESHOLD_TH_HI_WIDTH); } + inline uint32_t th_hi_get() { return this->get_field(PWM_T1_THRESHOLD_TH_HI_BIT, PWM_T1_THRESHOLD_TH_HI_WIDTH); } +}; + +class vp_pwm_t1_th_channel0 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL0_TH_BIT, PWM_T1_TH_CHANNEL0_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T1_TH_CHANNEL0_TH_BIT, PWM_T1_TH_CHANNEL0_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL0_MODE_BIT, PWM_T1_TH_CHANNEL0_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T1_TH_CHANNEL0_MODE_BIT, PWM_T1_TH_CHANNEL0_MODE_WIDTH); } +}; + +class vp_pwm_t1_th_channel1 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL1_TH_BIT, PWM_T1_TH_CHANNEL1_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T1_TH_CHANNEL1_TH_BIT, PWM_T1_TH_CHANNEL1_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL1_MODE_BIT, PWM_T1_TH_CHANNEL1_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T1_TH_CHANNEL1_MODE_BIT, PWM_T1_TH_CHANNEL1_MODE_WIDTH); } +}; + +class vp_pwm_t1_th_channel2 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL2_TH_BIT, PWM_T1_TH_CHANNEL2_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T1_TH_CHANNEL2_TH_BIT, PWM_T1_TH_CHANNEL2_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL2_MODE_BIT, PWM_T1_TH_CHANNEL2_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T1_TH_CHANNEL2_MODE_BIT, PWM_T1_TH_CHANNEL2_MODE_WIDTH); } +}; + +class vp_pwm_t1_th_channel3 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL3_TH_BIT, PWM_T1_TH_CHANNEL3_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T1_TH_CHANNEL3_TH_BIT, PWM_T1_TH_CHANNEL3_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T1_TH_CHANNEL3_MODE_BIT, PWM_T1_TH_CHANNEL3_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T1_TH_CHANNEL3_MODE_BIT, PWM_T1_TH_CHANNEL3_MODE_WIDTH); } +}; + +class vp_pwm_t1_counter : public vp::reg_32 +{ +public: +}; + +class vp_pwm_t2_cmd : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, PWM_T2_CMD_START_BIT, PWM_T2_CMD_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(PWM_T2_CMD_START_BIT, PWM_T2_CMD_START_WIDTH); } + inline void stop_set(uint32_t value) { this->set_field(value, PWM_T2_CMD_STOP_BIT, PWM_T2_CMD_STOP_WIDTH); } + inline uint32_t stop_get() { return this->get_field(PWM_T2_CMD_STOP_BIT, PWM_T2_CMD_STOP_WIDTH); } + inline void update_set(uint32_t value) { this->set_field(value, PWM_T2_CMD_UPDATE_BIT, PWM_T2_CMD_UPDATE_WIDTH); } + inline uint32_t update_get() { return this->get_field(PWM_T2_CMD_UPDATE_BIT, PWM_T2_CMD_UPDATE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, PWM_T2_CMD_RESET_BIT, PWM_T2_CMD_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(PWM_T2_CMD_RESET_BIT, PWM_T2_CMD_RESET_WIDTH); } + inline void arm_set(uint32_t value) { this->set_field(value, PWM_T2_CMD_ARM_BIT, PWM_T2_CMD_ARM_WIDTH); } + inline uint32_t arm_get() { return this->get_field(PWM_T2_CMD_ARM_BIT, PWM_T2_CMD_ARM_WIDTH); } +}; + +class vp_pwm_t2_config : public vp::reg_32 +{ +public: + inline void insel_set(uint32_t value) { this->set_field(value, PWM_T2_CONFIG_INSEL_BIT, PWM_T2_CONFIG_INSEL_WIDTH); } + inline uint32_t insel_get() { return this->get_field(PWM_T2_CONFIG_INSEL_BIT, PWM_T2_CONFIG_INSEL_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T2_CONFIG_MODE_BIT, PWM_T2_CONFIG_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T2_CONFIG_MODE_BIT, PWM_T2_CONFIG_MODE_WIDTH); } + inline void clksel_set(uint32_t value) { this->set_field(value, PWM_T2_CONFIG_CLKSEL_BIT, PWM_T2_CONFIG_CLKSEL_WIDTH); } + inline uint32_t clksel_get() { return this->get_field(PWM_T2_CONFIG_CLKSEL_BIT, PWM_T2_CONFIG_CLKSEL_WIDTH); } + inline void updownsel_set(uint32_t value) { this->set_field(value, PWM_T2_CONFIG_UPDOWNSEL_BIT, PWM_T2_CONFIG_UPDOWNSEL_WIDTH); } + inline uint32_t updownsel_get() { return this->get_field(PWM_T2_CONFIG_UPDOWNSEL_BIT, PWM_T2_CONFIG_UPDOWNSEL_WIDTH); } + inline void presc_set(uint32_t value) { this->set_field(value, PWM_T2_CONFIG_PRESC_BIT, PWM_T2_CONFIG_PRESC_WIDTH); } + inline uint32_t presc_get() { return this->get_field(PWM_T2_CONFIG_PRESC_BIT, PWM_T2_CONFIG_PRESC_WIDTH); } +}; + +class vp_pwm_t2_threshold : public vp::reg_32 +{ +public: + inline void th_lo_set(uint32_t value) { this->set_field(value, PWM_T2_THRESHOLD_TH_LO_BIT, PWM_T2_THRESHOLD_TH_LO_WIDTH); } + inline uint32_t th_lo_get() { return this->get_field(PWM_T2_THRESHOLD_TH_LO_BIT, PWM_T2_THRESHOLD_TH_LO_WIDTH); } + inline void th_hi_set(uint32_t value) { this->set_field(value, PWM_T2_THRESHOLD_TH_HI_BIT, PWM_T2_THRESHOLD_TH_HI_WIDTH); } + inline uint32_t th_hi_get() { return this->get_field(PWM_T2_THRESHOLD_TH_HI_BIT, PWM_T2_THRESHOLD_TH_HI_WIDTH); } +}; + +class vp_pwm_t2_th_channel0 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL0_TH_BIT, PWM_T2_TH_CHANNEL0_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T2_TH_CHANNEL0_TH_BIT, PWM_T2_TH_CHANNEL0_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL0_MODE_BIT, PWM_T2_TH_CHANNEL0_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T2_TH_CHANNEL0_MODE_BIT, PWM_T2_TH_CHANNEL0_MODE_WIDTH); } +}; + +class vp_pwm_t2_th_channel1 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL1_TH_BIT, PWM_T2_TH_CHANNEL1_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T2_TH_CHANNEL1_TH_BIT, PWM_T2_TH_CHANNEL1_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL1_MODE_BIT, PWM_T2_TH_CHANNEL1_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T2_TH_CHANNEL1_MODE_BIT, PWM_T2_TH_CHANNEL1_MODE_WIDTH); } +}; + +class vp_pwm_t2_th_channel2 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL2_TH_BIT, PWM_T2_TH_CHANNEL2_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T2_TH_CHANNEL2_TH_BIT, PWM_T2_TH_CHANNEL2_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL2_MODE_BIT, PWM_T2_TH_CHANNEL2_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T2_TH_CHANNEL2_MODE_BIT, PWM_T2_TH_CHANNEL2_MODE_WIDTH); } +}; + +class vp_pwm_t2_th_channel3 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL3_TH_BIT, PWM_T2_TH_CHANNEL3_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T2_TH_CHANNEL3_TH_BIT, PWM_T2_TH_CHANNEL3_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T2_TH_CHANNEL3_MODE_BIT, PWM_T2_TH_CHANNEL3_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T2_TH_CHANNEL3_MODE_BIT, PWM_T2_TH_CHANNEL3_MODE_WIDTH); } +}; + +class vp_pwm_t2_counter : public vp::reg_32 +{ +public: +}; + +class vp_pwm_t3_cmd : public vp::reg_32 +{ +public: + inline void start_set(uint32_t value) { this->set_field(value, PWM_T3_CMD_START_BIT, PWM_T3_CMD_START_WIDTH); } + inline uint32_t start_get() { return this->get_field(PWM_T3_CMD_START_BIT, PWM_T3_CMD_START_WIDTH); } + inline void stop_set(uint32_t value) { this->set_field(value, PWM_T3_CMD_STOP_BIT, PWM_T3_CMD_STOP_WIDTH); } + inline uint32_t stop_get() { return this->get_field(PWM_T3_CMD_STOP_BIT, PWM_T3_CMD_STOP_WIDTH); } + inline void update_set(uint32_t value) { this->set_field(value, PWM_T3_CMD_UPDATE_BIT, PWM_T3_CMD_UPDATE_WIDTH); } + inline uint32_t update_get() { return this->get_field(PWM_T3_CMD_UPDATE_BIT, PWM_T3_CMD_UPDATE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, PWM_T3_CMD_RESET_BIT, PWM_T3_CMD_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(PWM_T3_CMD_RESET_BIT, PWM_T3_CMD_RESET_WIDTH); } + inline void arm_set(uint32_t value) { this->set_field(value, PWM_T3_CMD_ARM_BIT, PWM_T3_CMD_ARM_WIDTH); } + inline uint32_t arm_get() { return this->get_field(PWM_T3_CMD_ARM_BIT, PWM_T3_CMD_ARM_WIDTH); } +}; + +class vp_pwm_t3_config : public vp::reg_32 +{ +public: + inline void insel_set(uint32_t value) { this->set_field(value, PWM_T3_CONFIG_INSEL_BIT, PWM_T3_CONFIG_INSEL_WIDTH); } + inline uint32_t insel_get() { return this->get_field(PWM_T3_CONFIG_INSEL_BIT, PWM_T3_CONFIG_INSEL_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T3_CONFIG_MODE_BIT, PWM_T3_CONFIG_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T3_CONFIG_MODE_BIT, PWM_T3_CONFIG_MODE_WIDTH); } + inline void clksel_set(uint32_t value) { this->set_field(value, PWM_T3_CONFIG_CLKSEL_BIT, PWM_T3_CONFIG_CLKSEL_WIDTH); } + inline uint32_t clksel_get() { return this->get_field(PWM_T3_CONFIG_CLKSEL_BIT, PWM_T3_CONFIG_CLKSEL_WIDTH); } + inline void updownsel_set(uint32_t value) { this->set_field(value, PWM_T3_CONFIG_UPDOWNSEL_BIT, PWM_T3_CONFIG_UPDOWNSEL_WIDTH); } + inline uint32_t updownsel_get() { return this->get_field(PWM_T3_CONFIG_UPDOWNSEL_BIT, PWM_T3_CONFIG_UPDOWNSEL_WIDTH); } + inline void presc_set(uint32_t value) { this->set_field(value, PWM_T3_CONFIG_PRESC_BIT, PWM_T3_CONFIG_PRESC_WIDTH); } + inline uint32_t presc_get() { return this->get_field(PWM_T3_CONFIG_PRESC_BIT, PWM_T3_CONFIG_PRESC_WIDTH); } +}; + +class vp_pwm_t3_threshold : public vp::reg_32 +{ +public: + inline void th_lo_set(uint32_t value) { this->set_field(value, PWM_T3_THRESHOLD_TH_LO_BIT, PWM_T3_THRESHOLD_TH_LO_WIDTH); } + inline uint32_t th_lo_get() { return this->get_field(PWM_T3_THRESHOLD_TH_LO_BIT, PWM_T3_THRESHOLD_TH_LO_WIDTH); } + inline void th_hi_set(uint32_t value) { this->set_field(value, PWM_T3_THRESHOLD_TH_HI_BIT, PWM_T3_THRESHOLD_TH_HI_WIDTH); } + inline uint32_t th_hi_get() { return this->get_field(PWM_T3_THRESHOLD_TH_HI_BIT, PWM_T3_THRESHOLD_TH_HI_WIDTH); } +}; + +class vp_pwm_t3_th_channel0 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL0_TH_BIT, PWM_T3_TH_CHANNEL0_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T3_TH_CHANNEL0_TH_BIT, PWM_T3_TH_CHANNEL0_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL0_MODE_BIT, PWM_T3_TH_CHANNEL0_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T3_TH_CHANNEL0_MODE_BIT, PWM_T3_TH_CHANNEL0_MODE_WIDTH); } +}; + +class vp_pwm_t3_th_channel1 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL1_TH_BIT, PWM_T3_TH_CHANNEL1_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T3_TH_CHANNEL1_TH_BIT, PWM_T3_TH_CHANNEL1_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL1_MODE_BIT, PWM_T3_TH_CHANNEL1_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T3_TH_CHANNEL1_MODE_BIT, PWM_T3_TH_CHANNEL1_MODE_WIDTH); } +}; + +class vp_pwm_t3_th_channel2 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL2_TH_BIT, PWM_T3_TH_CHANNEL2_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T3_TH_CHANNEL2_TH_BIT, PWM_T3_TH_CHANNEL2_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL2_MODE_BIT, PWM_T3_TH_CHANNEL2_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T3_TH_CHANNEL2_MODE_BIT, PWM_T3_TH_CHANNEL2_MODE_WIDTH); } +}; + +class vp_pwm_t3_th_channel3 : public vp::reg_32 +{ +public: + inline void th_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL3_TH_BIT, PWM_T3_TH_CHANNEL3_TH_WIDTH); } + inline uint32_t th_get() { return this->get_field(PWM_T3_TH_CHANNEL3_TH_BIT, PWM_T3_TH_CHANNEL3_TH_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, PWM_T3_TH_CHANNEL3_MODE_BIT, PWM_T3_TH_CHANNEL3_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(PWM_T3_TH_CHANNEL3_MODE_BIT, PWM_T3_TH_CHANNEL3_MODE_WIDTH); } +}; + +class vp_pwm_t3_counter : public vp::reg_32 +{ +public: +}; + +class vp_pwm_event_cfg : public vp::reg_32 +{ +public: + inline void sel0_set(uint32_t value) { this->set_field(value, PWM_EVENT_CFG_SEL0_BIT, PWM_EVENT_CFG_SEL0_WIDTH); } + inline uint32_t sel0_get() { return this->get_field(PWM_EVENT_CFG_SEL0_BIT, PWM_EVENT_CFG_SEL0_WIDTH); } + inline void sel1_set(uint32_t value) { this->set_field(value, PWM_EVENT_CFG_SEL1_BIT, PWM_EVENT_CFG_SEL1_WIDTH); } + inline uint32_t sel1_get() { return this->get_field(PWM_EVENT_CFG_SEL1_BIT, PWM_EVENT_CFG_SEL1_WIDTH); } + inline void sel2_set(uint32_t value) { this->set_field(value, PWM_EVENT_CFG_SEL2_BIT, PWM_EVENT_CFG_SEL2_WIDTH); } + inline uint32_t sel2_get() { return this->get_field(PWM_EVENT_CFG_SEL2_BIT, PWM_EVENT_CFG_SEL2_WIDTH); } + inline void sel3_set(uint32_t value) { this->set_field(value, PWM_EVENT_CFG_SEL3_BIT, PWM_EVENT_CFG_SEL3_WIDTH); } + inline uint32_t sel3_get() { return this->get_field(PWM_EVENT_CFG_SEL3_BIT, PWM_EVENT_CFG_SEL3_WIDTH); } + inline void ena_set(uint32_t value) { this->set_field(value, PWM_EVENT_CFG_ENA_BIT, PWM_EVENT_CFG_ENA_WIDTH); } + inline uint32_t ena_get() { return this->get_field(PWM_EVENT_CFG_ENA_BIT, PWM_EVENT_CFG_ENA_WIDTH); } +}; + +class vp_pwm_cg : public vp::reg_32 +{ +public: + inline void ena_set(uint32_t value) { this->set_field(value, PWM_CG_ENA_BIT, PWM_CG_ENA_WIDTH); } + inline uint32_t ena_get() { return this->get_field(PWM_CG_ENA_BIT, PWM_CG_ENA_WIDTH); } +}; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_macros.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_macros.h new file mode 100644 index 0000000..2602cab --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_macros.h @@ -0,0 +1,473 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_MACROS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_MACROS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS MACROS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#define PWM_T0_CMD_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define PWM_T0_CMD_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define PWM_T0_CMD_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define PWM_T0_CMD_START(val) ((val) << 0) + +#define PWM_T0_CMD_STOP_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define PWM_T0_CMD_STOP_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define PWM_T0_CMD_STOP_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define PWM_T0_CMD_STOP(val) ((val) << 1) + +#define PWM_T0_CMD_UPDATE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define PWM_T0_CMD_UPDATE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define PWM_T0_CMD_UPDATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define PWM_T0_CMD_UPDATE(val) ((val) << 2) + +#define PWM_T0_CMD_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define PWM_T0_CMD_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define PWM_T0_CMD_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define PWM_T0_CMD_RESET(val) ((val) << 3) + +#define PWM_T0_CMD_ARM_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define PWM_T0_CMD_ARM_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define PWM_T0_CMD_ARM_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define PWM_T0_CMD_ARM(val) ((val) << 4) + +#define PWM_T0_CONFIG_INSEL_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define PWM_T0_CONFIG_INSEL_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define PWM_T0_CONFIG_INSEL_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define PWM_T0_CONFIG_INSEL(val) ((val) << 0) + +#define PWM_T0_CONFIG_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,8)) +#define PWM_T0_CONFIG_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,8)) +#define PWM_T0_CONFIG_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,8)) +#define PWM_T0_CONFIG_MODE(val) ((val) << 8) + +#define PWM_T0_CONFIG_CLKSEL_GET(value) (ARCHI_BEXTRACTU((value),1,11)) +#define PWM_T0_CONFIG_CLKSEL_GETS(value) (ARCHI_BEXTRACT((value),1,11)) +#define PWM_T0_CONFIG_CLKSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,11)) +#define PWM_T0_CONFIG_CLKSEL(val) ((val) << 11) + +#define PWM_T0_CONFIG_UPDOWNSEL_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define PWM_T0_CONFIG_UPDOWNSEL_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define PWM_T0_CONFIG_UPDOWNSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define PWM_T0_CONFIG_UPDOWNSEL(val) ((val) << 12) + +#define PWM_T0_CONFIG_PRESC_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define PWM_T0_CONFIG_PRESC_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define PWM_T0_CONFIG_PRESC_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define PWM_T0_CONFIG_PRESC(val) ((val) << 16) + +#define PWM_T0_THRESHOLD_TH_LO_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T0_THRESHOLD_TH_LO_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T0_THRESHOLD_TH_LO_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T0_THRESHOLD_TH_LO(val) ((val) << 0) + +#define PWM_T0_THRESHOLD_TH_HI_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define PWM_T0_THRESHOLD_TH_HI_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define PWM_T0_THRESHOLD_TH_HI_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define PWM_T0_THRESHOLD_TH_HI(val) ((val) << 16) + +#define PWM_T0_TH_CHANNEL0_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T0_TH_CHANNEL0_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T0_TH_CHANNEL0_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T0_TH_CHANNEL0_TH(val) ((val) << 0) + +#define PWM_T0_TH_CHANNEL0_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T0_TH_CHANNEL0_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T0_TH_CHANNEL0_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T0_TH_CHANNEL0_MODE(val) ((val) << 16) + +#define PWM_T0_TH_CHANNEL1_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T0_TH_CHANNEL1_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T0_TH_CHANNEL1_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T0_TH_CHANNEL1_TH(val) ((val) << 0) + +#define PWM_T0_TH_CHANNEL1_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T0_TH_CHANNEL1_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T0_TH_CHANNEL1_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T0_TH_CHANNEL1_MODE(val) ((val) << 16) + +#define PWM_T0_TH_CHANNEL2_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T0_TH_CHANNEL2_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T0_TH_CHANNEL2_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T0_TH_CHANNEL2_TH(val) ((val) << 0) + +#define PWM_T0_TH_CHANNEL2_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T0_TH_CHANNEL2_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T0_TH_CHANNEL2_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T0_TH_CHANNEL2_MODE(val) ((val) << 16) + +#define PWM_T0_TH_CHANNEL3_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T0_TH_CHANNEL3_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T0_TH_CHANNEL3_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T0_TH_CHANNEL3_TH(val) ((val) << 0) + +#define PWM_T0_TH_CHANNEL3_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T0_TH_CHANNEL3_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T0_TH_CHANNEL3_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T0_TH_CHANNEL3_MODE(val) ((val) << 16) + +#define PWM_T1_CMD_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define PWM_T1_CMD_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define PWM_T1_CMD_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define PWM_T1_CMD_START(val) ((val) << 0) + +#define PWM_T1_CMD_STOP_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define PWM_T1_CMD_STOP_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define PWM_T1_CMD_STOP_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define PWM_T1_CMD_STOP(val) ((val) << 1) + +#define PWM_T1_CMD_UPDATE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define PWM_T1_CMD_UPDATE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define PWM_T1_CMD_UPDATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define PWM_T1_CMD_UPDATE(val) ((val) << 2) + +#define PWM_T1_CMD_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define PWM_T1_CMD_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define PWM_T1_CMD_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define PWM_T1_CMD_RESET(val) ((val) << 3) + +#define PWM_T1_CMD_ARM_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define PWM_T1_CMD_ARM_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define PWM_T1_CMD_ARM_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define PWM_T1_CMD_ARM(val) ((val) << 4) + +#define PWM_T1_CONFIG_INSEL_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define PWM_T1_CONFIG_INSEL_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define PWM_T1_CONFIG_INSEL_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define PWM_T1_CONFIG_INSEL(val) ((val) << 0) + +#define PWM_T1_CONFIG_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,8)) +#define PWM_T1_CONFIG_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,8)) +#define PWM_T1_CONFIG_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,8)) +#define PWM_T1_CONFIG_MODE(val) ((val) << 8) + +#define PWM_T1_CONFIG_CLKSEL_GET(value) (ARCHI_BEXTRACTU((value),1,11)) +#define PWM_T1_CONFIG_CLKSEL_GETS(value) (ARCHI_BEXTRACT((value),1,11)) +#define PWM_T1_CONFIG_CLKSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,11)) +#define PWM_T1_CONFIG_CLKSEL(val) ((val) << 11) + +#define PWM_T1_CONFIG_UPDOWNSEL_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define PWM_T1_CONFIG_UPDOWNSEL_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define PWM_T1_CONFIG_UPDOWNSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define PWM_T1_CONFIG_UPDOWNSEL(val) ((val) << 12) + +#define PWM_T1_CONFIG_PRESC_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define PWM_T1_CONFIG_PRESC_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define PWM_T1_CONFIG_PRESC_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define PWM_T1_CONFIG_PRESC(val) ((val) << 16) + +#define PWM_T1_THRESHOLD_TH_LO_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T1_THRESHOLD_TH_LO_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T1_THRESHOLD_TH_LO_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T1_THRESHOLD_TH_LO(val) ((val) << 0) + +#define PWM_T1_THRESHOLD_TH_HI_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define PWM_T1_THRESHOLD_TH_HI_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define PWM_T1_THRESHOLD_TH_HI_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define PWM_T1_THRESHOLD_TH_HI(val) ((val) << 16) + +#define PWM_T1_TH_CHANNEL0_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T1_TH_CHANNEL0_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T1_TH_CHANNEL0_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T1_TH_CHANNEL0_TH(val) ((val) << 0) + +#define PWM_T1_TH_CHANNEL0_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T1_TH_CHANNEL0_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T1_TH_CHANNEL0_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T1_TH_CHANNEL0_MODE(val) ((val) << 16) + +#define PWM_T1_TH_CHANNEL1_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T1_TH_CHANNEL1_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T1_TH_CHANNEL1_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T1_TH_CHANNEL1_TH(val) ((val) << 0) + +#define PWM_T1_TH_CHANNEL1_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T1_TH_CHANNEL1_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T1_TH_CHANNEL1_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T1_TH_CHANNEL1_MODE(val) ((val) << 16) + +#define PWM_T1_TH_CHANNEL2_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T1_TH_CHANNEL2_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T1_TH_CHANNEL2_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T1_TH_CHANNEL2_TH(val) ((val) << 0) + +#define PWM_T1_TH_CHANNEL2_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T1_TH_CHANNEL2_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T1_TH_CHANNEL2_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T1_TH_CHANNEL2_MODE(val) ((val) << 16) + +#define PWM_T1_TH_CHANNEL3_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T1_TH_CHANNEL3_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T1_TH_CHANNEL3_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T1_TH_CHANNEL3_TH(val) ((val) << 0) + +#define PWM_T1_TH_CHANNEL3_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T1_TH_CHANNEL3_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T1_TH_CHANNEL3_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T1_TH_CHANNEL3_MODE(val) ((val) << 16) + +#define PWM_T2_CMD_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define PWM_T2_CMD_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define PWM_T2_CMD_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define PWM_T2_CMD_START(val) ((val) << 0) + +#define PWM_T2_CMD_STOP_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define PWM_T2_CMD_STOP_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define PWM_T2_CMD_STOP_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define PWM_T2_CMD_STOP(val) ((val) << 1) + +#define PWM_T2_CMD_UPDATE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define PWM_T2_CMD_UPDATE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define PWM_T2_CMD_UPDATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define PWM_T2_CMD_UPDATE(val) ((val) << 2) + +#define PWM_T2_CMD_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define PWM_T2_CMD_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define PWM_T2_CMD_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define PWM_T2_CMD_RESET(val) ((val) << 3) + +#define PWM_T2_CMD_ARM_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define PWM_T2_CMD_ARM_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define PWM_T2_CMD_ARM_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define PWM_T2_CMD_ARM(val) ((val) << 4) + +#define PWM_T2_CONFIG_INSEL_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define PWM_T2_CONFIG_INSEL_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define PWM_T2_CONFIG_INSEL_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define PWM_T2_CONFIG_INSEL(val) ((val) << 0) + +#define PWM_T2_CONFIG_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,8)) +#define PWM_T2_CONFIG_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,8)) +#define PWM_T2_CONFIG_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,8)) +#define PWM_T2_CONFIG_MODE(val) ((val) << 8) + +#define PWM_T2_CONFIG_CLKSEL_GET(value) (ARCHI_BEXTRACTU((value),1,11)) +#define PWM_T2_CONFIG_CLKSEL_GETS(value) (ARCHI_BEXTRACT((value),1,11)) +#define PWM_T2_CONFIG_CLKSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,11)) +#define PWM_T2_CONFIG_CLKSEL(val) ((val) << 11) + +#define PWM_T2_CONFIG_UPDOWNSEL_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define PWM_T2_CONFIG_UPDOWNSEL_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define PWM_T2_CONFIG_UPDOWNSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define PWM_T2_CONFIG_UPDOWNSEL(val) ((val) << 12) + +#define PWM_T2_CONFIG_PRESC_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define PWM_T2_CONFIG_PRESC_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define PWM_T2_CONFIG_PRESC_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define PWM_T2_CONFIG_PRESC(val) ((val) << 16) + +#define PWM_T2_THRESHOLD_TH_LO_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T2_THRESHOLD_TH_LO_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T2_THRESHOLD_TH_LO_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T2_THRESHOLD_TH_LO(val) ((val) << 0) + +#define PWM_T2_THRESHOLD_TH_HI_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define PWM_T2_THRESHOLD_TH_HI_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define PWM_T2_THRESHOLD_TH_HI_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define PWM_T2_THRESHOLD_TH_HI(val) ((val) << 16) + +#define PWM_T2_TH_CHANNEL0_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T2_TH_CHANNEL0_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T2_TH_CHANNEL0_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T2_TH_CHANNEL0_TH(val) ((val) << 0) + +#define PWM_T2_TH_CHANNEL0_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T2_TH_CHANNEL0_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T2_TH_CHANNEL0_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T2_TH_CHANNEL0_MODE(val) ((val) << 16) + +#define PWM_T2_TH_CHANNEL1_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T2_TH_CHANNEL1_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T2_TH_CHANNEL1_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T2_TH_CHANNEL1_TH(val) ((val) << 0) + +#define PWM_T2_TH_CHANNEL1_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T2_TH_CHANNEL1_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T2_TH_CHANNEL1_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T2_TH_CHANNEL1_MODE(val) ((val) << 16) + +#define PWM_T2_TH_CHANNEL2_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T2_TH_CHANNEL2_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T2_TH_CHANNEL2_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T2_TH_CHANNEL2_TH(val) ((val) << 0) + +#define PWM_T2_TH_CHANNEL2_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T2_TH_CHANNEL2_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T2_TH_CHANNEL2_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T2_TH_CHANNEL2_MODE(val) ((val) << 16) + +#define PWM_T2_TH_CHANNEL3_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T2_TH_CHANNEL3_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T2_TH_CHANNEL3_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T2_TH_CHANNEL3_TH(val) ((val) << 0) + +#define PWM_T2_TH_CHANNEL3_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T2_TH_CHANNEL3_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T2_TH_CHANNEL3_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T2_TH_CHANNEL3_MODE(val) ((val) << 16) + +#define PWM_T3_CMD_START_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define PWM_T3_CMD_START_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define PWM_T3_CMD_START_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define PWM_T3_CMD_START(val) ((val) << 0) + +#define PWM_T3_CMD_STOP_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define PWM_T3_CMD_STOP_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define PWM_T3_CMD_STOP_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define PWM_T3_CMD_STOP(val) ((val) << 1) + +#define PWM_T3_CMD_UPDATE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define PWM_T3_CMD_UPDATE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define PWM_T3_CMD_UPDATE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define PWM_T3_CMD_UPDATE(val) ((val) << 2) + +#define PWM_T3_CMD_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define PWM_T3_CMD_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define PWM_T3_CMD_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define PWM_T3_CMD_RESET(val) ((val) << 3) + +#define PWM_T3_CMD_ARM_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define PWM_T3_CMD_ARM_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define PWM_T3_CMD_ARM_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define PWM_T3_CMD_ARM(val) ((val) << 4) + +#define PWM_T3_CONFIG_INSEL_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define PWM_T3_CONFIG_INSEL_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define PWM_T3_CONFIG_INSEL_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define PWM_T3_CONFIG_INSEL(val) ((val) << 0) + +#define PWM_T3_CONFIG_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,8)) +#define PWM_T3_CONFIG_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,8)) +#define PWM_T3_CONFIG_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,8)) +#define PWM_T3_CONFIG_MODE(val) ((val) << 8) + +#define PWM_T3_CONFIG_CLKSEL_GET(value) (ARCHI_BEXTRACTU((value),1,11)) +#define PWM_T3_CONFIG_CLKSEL_GETS(value) (ARCHI_BEXTRACT((value),1,11)) +#define PWM_T3_CONFIG_CLKSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,11)) +#define PWM_T3_CONFIG_CLKSEL(val) ((val) << 11) + +#define PWM_T3_CONFIG_UPDOWNSEL_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define PWM_T3_CONFIG_UPDOWNSEL_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define PWM_T3_CONFIG_UPDOWNSEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define PWM_T3_CONFIG_UPDOWNSEL(val) ((val) << 12) + +#define PWM_T3_CONFIG_PRESC_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define PWM_T3_CONFIG_PRESC_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define PWM_T3_CONFIG_PRESC_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define PWM_T3_CONFIG_PRESC(val) ((val) << 16) + +#define PWM_T3_THRESHOLD_TH_LO_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T3_THRESHOLD_TH_LO_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T3_THRESHOLD_TH_LO_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T3_THRESHOLD_TH_LO(val) ((val) << 0) + +#define PWM_T3_THRESHOLD_TH_HI_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define PWM_T3_THRESHOLD_TH_HI_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define PWM_T3_THRESHOLD_TH_HI_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define PWM_T3_THRESHOLD_TH_HI(val) ((val) << 16) + +#define PWM_T3_TH_CHANNEL0_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T3_TH_CHANNEL0_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T3_TH_CHANNEL0_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T3_TH_CHANNEL0_TH(val) ((val) << 0) + +#define PWM_T3_TH_CHANNEL0_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T3_TH_CHANNEL0_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T3_TH_CHANNEL0_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T3_TH_CHANNEL0_MODE(val) ((val) << 16) + +#define PWM_T3_TH_CHANNEL1_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T3_TH_CHANNEL1_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T3_TH_CHANNEL1_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T3_TH_CHANNEL1_TH(val) ((val) << 0) + +#define PWM_T3_TH_CHANNEL1_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T3_TH_CHANNEL1_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T3_TH_CHANNEL1_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T3_TH_CHANNEL1_MODE(val) ((val) << 16) + +#define PWM_T3_TH_CHANNEL2_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T3_TH_CHANNEL2_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T3_TH_CHANNEL2_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T3_TH_CHANNEL2_TH(val) ((val) << 0) + +#define PWM_T3_TH_CHANNEL2_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T3_TH_CHANNEL2_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T3_TH_CHANNEL2_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T3_TH_CHANNEL2_MODE(val) ((val) << 16) + +#define PWM_T3_TH_CHANNEL3_TH_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_T3_TH_CHANNEL3_TH_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_T3_TH_CHANNEL3_TH_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_T3_TH_CHANNEL3_TH(val) ((val) << 0) + +#define PWM_T3_TH_CHANNEL3_MODE_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define PWM_T3_TH_CHANNEL3_MODE_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define PWM_T3_TH_CHANNEL3_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define PWM_T3_TH_CHANNEL3_MODE(val) ((val) << 16) + +#define PWM_EVENT_CFG_SEL0_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define PWM_EVENT_CFG_SEL0_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define PWM_EVENT_CFG_SEL0_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define PWM_EVENT_CFG_SEL0(val) ((val) << 0) + +#define PWM_EVENT_CFG_SEL1_GET(value) (ARCHI_BEXTRACTU((value),4,4)) +#define PWM_EVENT_CFG_SEL1_GETS(value) (ARCHI_BEXTRACT((value),4,4)) +#define PWM_EVENT_CFG_SEL1_SET(value,field) (ARCHI_BINSERT((value),(field),4,4)) +#define PWM_EVENT_CFG_SEL1(val) ((val) << 4) + +#define PWM_EVENT_CFG_SEL2_GET(value) (ARCHI_BEXTRACTU((value),4,8)) +#define PWM_EVENT_CFG_SEL2_GETS(value) (ARCHI_BEXTRACT((value),4,8)) +#define PWM_EVENT_CFG_SEL2_SET(value,field) (ARCHI_BINSERT((value),(field),4,8)) +#define PWM_EVENT_CFG_SEL2(val) ((val) << 8) + +#define PWM_EVENT_CFG_SEL3_GET(value) (ARCHI_BEXTRACTU((value),4,12)) +#define PWM_EVENT_CFG_SEL3_GETS(value) (ARCHI_BEXTRACT((value),4,12)) +#define PWM_EVENT_CFG_SEL3_SET(value,field) (ARCHI_BINSERT((value),(field),4,12)) +#define PWM_EVENT_CFG_SEL3(val) ((val) << 12) + +#define PWM_EVENT_CFG_ENA_GET(value) (ARCHI_BEXTRACTU((value),4,16)) +#define PWM_EVENT_CFG_ENA_GETS(value) (ARCHI_BEXTRACT((value),4,16)) +#define PWM_EVENT_CFG_ENA_SET(value,field) (ARCHI_BINSERT((value),(field),4,16)) +#define PWM_EVENT_CFG_ENA(val) ((val) << 16) + +#define PWM_CG_ENA_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define PWM_CG_ENA_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define PWM_CG_ENA_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define PWM_CG_ENA(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regfields.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regfields.h new file mode 100644 index 0000000..a0abc45 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regfields.h @@ -0,0 +1,469 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGFIELDS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGFIELDS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS +// + +// ADV_TIMER0 start command bitfield. (access: R/W) +#define PWM_T0_CMD_START_BIT 0 +#define PWM_T0_CMD_START_WIDTH 1 +#define PWM_T0_CMD_START_MASK 0x1 + +// ADV_TIMER0 stop command bitfield. (access: R/W) +#define PWM_T0_CMD_STOP_BIT 1 +#define PWM_T0_CMD_STOP_WIDTH 1 +#define PWM_T0_CMD_STOP_MASK 0x2 + +// ADV_TIMER0 update command bitfield. (access: R/W) +#define PWM_T0_CMD_UPDATE_BIT 2 +#define PWM_T0_CMD_UPDATE_WIDTH 1 +#define PWM_T0_CMD_UPDATE_MASK 0x4 + +// ADV_TIMER0 reset command bitfield. (access: R/W) +#define PWM_T0_CMD_RESET_BIT 3 +#define PWM_T0_CMD_RESET_WIDTH 1 +#define PWM_T0_CMD_RESET_MASK 0x8 + +// ADV_TIMER0 arm command bitfield. (access: R/W) +#define PWM_T0_CMD_ARM_BIT 4 +#define PWM_T0_CMD_ARM_WIDTH 1 +#define PWM_T0_CMD_ARM_MASK 0x10 + +// ADV_TIMER0 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 (access: R/W) +#define PWM_T0_CONFIG_INSEL_BIT 0 +#define PWM_T0_CONFIG_INSEL_WIDTH 8 +#define PWM_T0_CONFIG_INSEL_MASK 0xff + +// ADV_TIMER0 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed (access: R/W) +#define PWM_T0_CONFIG_MODE_BIT 8 +#define PWM_T0_CONFIG_MODE_WIDTH 3 +#define PWM_T0_CONFIG_MODE_MASK 0x700 + +// ADV_TIMER0 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz (access: R/W) +#define PWM_T0_CONFIG_CLKSEL_BIT 11 +#define PWM_T0_CONFIG_CLKSEL_WIDTH 1 +#define PWM_T0_CONFIG_CLKSEL_MASK 0x800 + +// ADV_TIMER0 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. (access: R/W) +#define PWM_T0_CONFIG_UPDOWNSEL_BIT 12 +#define PWM_T0_CONFIG_UPDOWNSEL_WIDTH 1 +#define PWM_T0_CONFIG_UPDOWNSEL_MASK 0x1000 + +// ADV_TIMER0 prescaler value configuration bitfield. (access: R/W) +#define PWM_T0_CONFIG_PRESC_BIT 16 +#define PWM_T0_CONFIG_PRESC_WIDTH 8 +#define PWM_T0_CONFIG_PRESC_MASK 0xff0000 + +// ADV_TIMER0 threshold low part configuration bitfield. It defines start counter value. (access: R/W) +#define PWM_T0_THRESHOLD_TH_LO_BIT 0 +#define PWM_T0_THRESHOLD_TH_LO_WIDTH 16 +#define PWM_T0_THRESHOLD_TH_LO_MASK 0xffff + +// ADV_TIMER0 threshold high part configuration bitfield. It defines end counter value. (access: R/W) +#define PWM_T0_THRESHOLD_TH_HI_BIT 16 +#define PWM_T0_THRESHOLD_TH_HI_WIDTH 16 +#define PWM_T0_THRESHOLD_TH_HI_MASK 0xffff0000 + +// ADV_TIMER0 channel 0 threshold configuration bitfield. (access: R/W) +#define PWM_T0_TH_CHANNEL0_TH_BIT 0 +#define PWM_T0_TH_CHANNEL0_TH_WIDTH 16 +#define PWM_T0_TH_CHANNEL0_TH_MASK 0xffff + +// ADV_TIMER0 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T0_TH_CHANNEL0_MODE_BIT 16 +#define PWM_T0_TH_CHANNEL0_MODE_WIDTH 3 +#define PWM_T0_TH_CHANNEL0_MODE_MASK 0x70000 + +// ADV_TIMER0 channel 1 threshold configuration bitfield. (access: R/W) +#define PWM_T0_TH_CHANNEL1_TH_BIT 0 +#define PWM_T0_TH_CHANNEL1_TH_WIDTH 16 +#define PWM_T0_TH_CHANNEL1_TH_MASK 0xffff + +// ADV_TIMER0 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T0_TH_CHANNEL1_MODE_BIT 16 +#define PWM_T0_TH_CHANNEL1_MODE_WIDTH 3 +#define PWM_T0_TH_CHANNEL1_MODE_MASK 0x70000 + +// ADV_TIMER0 channel 2 threshold configuration bitfield. (access: R/W) +#define PWM_T0_TH_CHANNEL2_TH_BIT 0 +#define PWM_T0_TH_CHANNEL2_TH_WIDTH 16 +#define PWM_T0_TH_CHANNEL2_TH_MASK 0xffff + +// ADV_TIMER0 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T0_TH_CHANNEL2_MODE_BIT 16 +#define PWM_T0_TH_CHANNEL2_MODE_WIDTH 3 +#define PWM_T0_TH_CHANNEL2_MODE_MASK 0x70000 + +// ADV_TIMER0 channel 3 threshold configuration bitfield. (access: R/W) +#define PWM_T0_TH_CHANNEL3_TH_BIT 0 +#define PWM_T0_TH_CHANNEL3_TH_WIDTH 16 +#define PWM_T0_TH_CHANNEL3_TH_MASK 0xffff + +// ADV_TIMER0 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T0_TH_CHANNEL3_MODE_BIT 16 +#define PWM_T0_TH_CHANNEL3_MODE_WIDTH 3 +#define PWM_T0_TH_CHANNEL3_MODE_MASK 0x70000 + +// ADV_TIMER1 start command bitfield. (access: R/W) +#define PWM_T1_CMD_START_BIT 0 +#define PWM_T1_CMD_START_WIDTH 1 +#define PWM_T1_CMD_START_MASK 0x1 + +// ADV_TIMER1 stop command bitfield. (access: R/W) +#define PWM_T1_CMD_STOP_BIT 1 +#define PWM_T1_CMD_STOP_WIDTH 1 +#define PWM_T1_CMD_STOP_MASK 0x2 + +// ADV_TIMER1 update command bitfield. (access: R/W) +#define PWM_T1_CMD_UPDATE_BIT 2 +#define PWM_T1_CMD_UPDATE_WIDTH 1 +#define PWM_T1_CMD_UPDATE_MASK 0x4 + +// ADV_TIMER1 reset command bitfield. (access: R/W) +#define PWM_T1_CMD_RESET_BIT 3 +#define PWM_T1_CMD_RESET_WIDTH 1 +#define PWM_T1_CMD_RESET_MASK 0x8 + +// ADV_TIMER1 arm command bitfield. (access: R/W) +#define PWM_T1_CMD_ARM_BIT 4 +#define PWM_T1_CMD_ARM_WIDTH 1 +#define PWM_T1_CMD_ARM_MASK 0x10 + +// ADV_TIMER1 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 (access: R/W) +#define PWM_T1_CONFIG_INSEL_BIT 0 +#define PWM_T1_CONFIG_INSEL_WIDTH 8 +#define PWM_T1_CONFIG_INSEL_MASK 0xff + +// ADV_TIMER1 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed (access: R/W) +#define PWM_T1_CONFIG_MODE_BIT 8 +#define PWM_T1_CONFIG_MODE_WIDTH 3 +#define PWM_T1_CONFIG_MODE_MASK 0x700 + +// ADV_TIMER1 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz (access: R/W) +#define PWM_T1_CONFIG_CLKSEL_BIT 11 +#define PWM_T1_CONFIG_CLKSEL_WIDTH 1 +#define PWM_T1_CONFIG_CLKSEL_MASK 0x800 + +// ADV_TIMER1 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. (access: R/W) +#define PWM_T1_CONFIG_UPDOWNSEL_BIT 12 +#define PWM_T1_CONFIG_UPDOWNSEL_WIDTH 1 +#define PWM_T1_CONFIG_UPDOWNSEL_MASK 0x1000 + +// ADV_TIMER1 prescaler value configuration bitfield. (access: R/W) +#define PWM_T1_CONFIG_PRESC_BIT 16 +#define PWM_T1_CONFIG_PRESC_WIDTH 8 +#define PWM_T1_CONFIG_PRESC_MASK 0xff0000 + +// ADV_TIMER1 threshold low part configuration bitfield. It defines start counter value. (access: R/W) +#define PWM_T1_THRESHOLD_TH_LO_BIT 0 +#define PWM_T1_THRESHOLD_TH_LO_WIDTH 16 +#define PWM_T1_THRESHOLD_TH_LO_MASK 0xffff + +// ADV_TIMER1 threshold high part configuration bitfield. It defines end counter value. (access: R/W) +#define PWM_T1_THRESHOLD_TH_HI_BIT 16 +#define PWM_T1_THRESHOLD_TH_HI_WIDTH 16 +#define PWM_T1_THRESHOLD_TH_HI_MASK 0xffff0000 + +// ADV_TIMER1 channel 0 threshold configuration bitfield. (access: R/W) +#define PWM_T1_TH_CHANNEL0_TH_BIT 0 +#define PWM_T1_TH_CHANNEL0_TH_WIDTH 16 +#define PWM_T1_TH_CHANNEL0_TH_MASK 0xffff + +// ADV_TIMER1 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T1_TH_CHANNEL0_MODE_BIT 16 +#define PWM_T1_TH_CHANNEL0_MODE_WIDTH 3 +#define PWM_T1_TH_CHANNEL0_MODE_MASK 0x70000 + +// ADV_TIMER1 channel 1 threshold configuration bitfield. (access: R/W) +#define PWM_T1_TH_CHANNEL1_TH_BIT 0 +#define PWM_T1_TH_CHANNEL1_TH_WIDTH 16 +#define PWM_T1_TH_CHANNEL1_TH_MASK 0xffff + +// ADV_TIMER1 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T1_TH_CHANNEL1_MODE_BIT 16 +#define PWM_T1_TH_CHANNEL1_MODE_WIDTH 3 +#define PWM_T1_TH_CHANNEL1_MODE_MASK 0x70000 + +// ADV_TIMER1 channel 2 threshold configuration bitfield. (access: R/W) +#define PWM_T1_TH_CHANNEL2_TH_BIT 0 +#define PWM_T1_TH_CHANNEL2_TH_WIDTH 16 +#define PWM_T1_TH_CHANNEL2_TH_MASK 0xffff + +// ADV_TIMER1 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T1_TH_CHANNEL2_MODE_BIT 16 +#define PWM_T1_TH_CHANNEL2_MODE_WIDTH 3 +#define PWM_T1_TH_CHANNEL2_MODE_MASK 0x70000 + +// ADV_TIMER1 channel 3 threshold configuration bitfield. (access: R/W) +#define PWM_T1_TH_CHANNEL3_TH_BIT 0 +#define PWM_T1_TH_CHANNEL3_TH_WIDTH 16 +#define PWM_T1_TH_CHANNEL3_TH_MASK 0xffff + +// ADV_TIMER1 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T1_TH_CHANNEL3_MODE_BIT 16 +#define PWM_T1_TH_CHANNEL3_MODE_WIDTH 3 +#define PWM_T1_TH_CHANNEL3_MODE_MASK 0x70000 + +// ADV_TIMER2 start command bitfield. (access: R/W) +#define PWM_T2_CMD_START_BIT 0 +#define PWM_T2_CMD_START_WIDTH 1 +#define PWM_T2_CMD_START_MASK 0x1 + +// ADV_TIMER2 stop command bitfield. (access: R/W) +#define PWM_T2_CMD_STOP_BIT 1 +#define PWM_T2_CMD_STOP_WIDTH 1 +#define PWM_T2_CMD_STOP_MASK 0x2 + +// ADV_TIMER2 update command bitfield. (access: R/W) +#define PWM_T2_CMD_UPDATE_BIT 2 +#define PWM_T2_CMD_UPDATE_WIDTH 1 +#define PWM_T2_CMD_UPDATE_MASK 0x4 + +// ADV_TIMER2 reset command bitfield. (access: R/W) +#define PWM_T2_CMD_RESET_BIT 3 +#define PWM_T2_CMD_RESET_WIDTH 1 +#define PWM_T2_CMD_RESET_MASK 0x8 + +// ADV_TIMER2 arm command bitfield. (access: R/W) +#define PWM_T2_CMD_ARM_BIT 4 +#define PWM_T2_CMD_ARM_WIDTH 1 +#define PWM_T2_CMD_ARM_MASK 0x10 + +// ADV_TIMER2 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 (access: R/W) +#define PWM_T2_CONFIG_INSEL_BIT 0 +#define PWM_T2_CONFIG_INSEL_WIDTH 8 +#define PWM_T2_CONFIG_INSEL_MASK 0xff + +// ADV_TIMER2 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed (access: R/W) +#define PWM_T2_CONFIG_MODE_BIT 8 +#define PWM_T2_CONFIG_MODE_WIDTH 3 +#define PWM_T2_CONFIG_MODE_MASK 0x700 + +// ADV_TIMER2 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz (access: R/W) +#define PWM_T2_CONFIG_CLKSEL_BIT 11 +#define PWM_T2_CONFIG_CLKSEL_WIDTH 1 +#define PWM_T2_CONFIG_CLKSEL_MASK 0x800 + +// ADV_TIMER2 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. (access: R/W) +#define PWM_T2_CONFIG_UPDOWNSEL_BIT 12 +#define PWM_T2_CONFIG_UPDOWNSEL_WIDTH 1 +#define PWM_T2_CONFIG_UPDOWNSEL_MASK 0x1000 + +// ADV_TIMER2 prescaler value configuration bitfield. (access: R/W) +#define PWM_T2_CONFIG_PRESC_BIT 16 +#define PWM_T2_CONFIG_PRESC_WIDTH 8 +#define PWM_T2_CONFIG_PRESC_MASK 0xff0000 + +// ADV_TIMER2 threshold low part configuration bitfield. It defines start counter value. (access: R/W) +#define PWM_T2_THRESHOLD_TH_LO_BIT 0 +#define PWM_T2_THRESHOLD_TH_LO_WIDTH 16 +#define PWM_T2_THRESHOLD_TH_LO_MASK 0xffff + +// ADV_TIMER2 threshold high part configuration bitfield. It defines end counter value. (access: R/W) +#define PWM_T2_THRESHOLD_TH_HI_BIT 16 +#define PWM_T2_THRESHOLD_TH_HI_WIDTH 16 +#define PWM_T2_THRESHOLD_TH_HI_MASK 0xffff0000 + +// ADV_TIMER2 channel 0 threshold configuration bitfield. (access: R/W) +#define PWM_T2_TH_CHANNEL0_TH_BIT 0 +#define PWM_T2_TH_CHANNEL0_TH_WIDTH 16 +#define PWM_T2_TH_CHANNEL0_TH_MASK 0xffff + +// ADV_TIMER2 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T2_TH_CHANNEL0_MODE_BIT 16 +#define PWM_T2_TH_CHANNEL0_MODE_WIDTH 3 +#define PWM_T2_TH_CHANNEL0_MODE_MASK 0x70000 + +// ADV_TIMER2 channel 1 threshold configuration bitfield. (access: R/W) +#define PWM_T2_TH_CHANNEL1_TH_BIT 0 +#define PWM_T2_TH_CHANNEL1_TH_WIDTH 16 +#define PWM_T2_TH_CHANNEL1_TH_MASK 0xffff + +// ADV_TIMER2 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T2_TH_CHANNEL1_MODE_BIT 16 +#define PWM_T2_TH_CHANNEL1_MODE_WIDTH 3 +#define PWM_T2_TH_CHANNEL1_MODE_MASK 0x70000 + +// ADV_TIMER2 channel 2 threshold configuration bitfield. (access: R/W) +#define PWM_T2_TH_CHANNEL2_TH_BIT 0 +#define PWM_T2_TH_CHANNEL2_TH_WIDTH 16 +#define PWM_T2_TH_CHANNEL2_TH_MASK 0xffff + +// ADV_TIMER2 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T2_TH_CHANNEL2_MODE_BIT 16 +#define PWM_T2_TH_CHANNEL2_MODE_WIDTH 3 +#define PWM_T2_TH_CHANNEL2_MODE_MASK 0x70000 + +// ADV_TIMER2 channel 3 threshold configuration bitfield. (access: R/W) +#define PWM_T2_TH_CHANNEL3_TH_BIT 0 +#define PWM_T2_TH_CHANNEL3_TH_WIDTH 16 +#define PWM_T2_TH_CHANNEL3_TH_MASK 0xffff + +// ADV_TIMER2 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T2_TH_CHANNEL3_MODE_BIT 16 +#define PWM_T2_TH_CHANNEL3_MODE_WIDTH 3 +#define PWM_T2_TH_CHANNEL3_MODE_MASK 0x70000 + +// ADV_TIMER3 start command bitfield. (access: R/W) +#define PWM_T3_CMD_START_BIT 0 +#define PWM_T3_CMD_START_WIDTH 1 +#define PWM_T3_CMD_START_MASK 0x1 + +// ADV_TIMER3 stop command bitfield. (access: R/W) +#define PWM_T3_CMD_STOP_BIT 1 +#define PWM_T3_CMD_STOP_WIDTH 1 +#define PWM_T3_CMD_STOP_MASK 0x2 + +// ADV_TIMER3 update command bitfield. (access: R/W) +#define PWM_T3_CMD_UPDATE_BIT 2 +#define PWM_T3_CMD_UPDATE_WIDTH 1 +#define PWM_T3_CMD_UPDATE_MASK 0x4 + +// ADV_TIMER3 reset command bitfield. (access: R/W) +#define PWM_T3_CMD_RESET_BIT 3 +#define PWM_T3_CMD_RESET_WIDTH 1 +#define PWM_T3_CMD_RESET_MASK 0x8 + +// ADV_TIMER3 arm command bitfield. (access: R/W) +#define PWM_T3_CMD_ARM_BIT 4 +#define PWM_T3_CMD_ARM_WIDTH 1 +#define PWM_T3_CMD_ARM_MASK 0x10 + +// ADV_TIMER3 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 (access: R/W) +#define PWM_T3_CONFIG_INSEL_BIT 0 +#define PWM_T3_CONFIG_INSEL_WIDTH 8 +#define PWM_T3_CONFIG_INSEL_MASK 0xff + +// ADV_TIMER3 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed (access: R/W) +#define PWM_T3_CONFIG_MODE_BIT 8 +#define PWM_T3_CONFIG_MODE_WIDTH 3 +#define PWM_T3_CONFIG_MODE_MASK 0x700 + +// ADV_TIMER3 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz (access: R/W) +#define PWM_T3_CONFIG_CLKSEL_BIT 11 +#define PWM_T3_CONFIG_CLKSEL_WIDTH 1 +#define PWM_T3_CONFIG_CLKSEL_MASK 0x800 + +// ADV_TIMER3 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. (access: R/W) +#define PWM_T3_CONFIG_UPDOWNSEL_BIT 12 +#define PWM_T3_CONFIG_UPDOWNSEL_WIDTH 1 +#define PWM_T3_CONFIG_UPDOWNSEL_MASK 0x1000 + +// ADV_TIMER3 prescaler value configuration bitfield. (access: R/W) +#define PWM_T3_CONFIG_PRESC_BIT 16 +#define PWM_T3_CONFIG_PRESC_WIDTH 8 +#define PWM_T3_CONFIG_PRESC_MASK 0xff0000 + +// ADV_TIMER3 threshold low part configuration bitfield. It defines start counter value. (access: R/W) +#define PWM_T3_THRESHOLD_TH_LO_BIT 0 +#define PWM_T3_THRESHOLD_TH_LO_WIDTH 16 +#define PWM_T3_THRESHOLD_TH_LO_MASK 0xffff + +// ADV_TIMER3 threshold high part configuration bitfield. It defines end counter value. (access: R/W) +#define PWM_T3_THRESHOLD_TH_HI_BIT 16 +#define PWM_T3_THRESHOLD_TH_HI_WIDTH 16 +#define PWM_T3_THRESHOLD_TH_HI_MASK 0xffff0000 + +// ADV_TIMER3 channel 0 threshold configuration bitfield. (access: R/W) +#define PWM_T3_TH_CHANNEL0_TH_BIT 0 +#define PWM_T3_TH_CHANNEL0_TH_WIDTH 16 +#define PWM_T3_TH_CHANNEL0_TH_MASK 0xffff + +// ADV_TIMER3 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T3_TH_CHANNEL0_MODE_BIT 16 +#define PWM_T3_TH_CHANNEL0_MODE_WIDTH 3 +#define PWM_T3_TH_CHANNEL0_MODE_MASK 0x70000 + +// ADV_TIMER3 channel 1 threshold configuration bitfield. (access: R/W) +#define PWM_T3_TH_CHANNEL1_TH_BIT 0 +#define PWM_T3_TH_CHANNEL1_TH_WIDTH 16 +#define PWM_T3_TH_CHANNEL1_TH_MASK 0xffff + +// ADV_TIMER3 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T3_TH_CHANNEL1_MODE_BIT 16 +#define PWM_T3_TH_CHANNEL1_MODE_WIDTH 3 +#define PWM_T3_TH_CHANNEL1_MODE_MASK 0x70000 + +// ADV_TIMER3 channel 2 threshold configuration bitfield. (access: R/W) +#define PWM_T3_TH_CHANNEL2_TH_BIT 0 +#define PWM_T3_TH_CHANNEL2_TH_WIDTH 16 +#define PWM_T3_TH_CHANNEL2_TH_MASK 0xffff + +// ADV_TIMER3 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T3_TH_CHANNEL2_MODE_BIT 16 +#define PWM_T3_TH_CHANNEL2_MODE_WIDTH 3 +#define PWM_T3_TH_CHANNEL2_MODE_MASK 0x70000 + +// ADV_TIMER3 channel 3 threshold configuration bitfield. (access: R/W) +#define PWM_T3_TH_CHANNEL3_TH_BIT 0 +#define PWM_T3_TH_CHANNEL3_TH_WIDTH 16 +#define PWM_T3_TH_CHANNEL3_TH_MASK 0xffff + +// ADV_TIMER3 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. (access: R/W) +#define PWM_T3_TH_CHANNEL3_MODE_BIT 16 +#define PWM_T3_TH_CHANNEL3_MODE_WIDTH 3 +#define PWM_T3_TH_CHANNEL3_MODE_MASK 0x70000 + +// ADV_TIMER output event 0 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. (access: R/W) +#define PWM_EVENT_CFG_SEL0_BIT 0 +#define PWM_EVENT_CFG_SEL0_WIDTH 4 +#define PWM_EVENT_CFG_SEL0_MASK 0xf + +// ADV_TIMER output event 1 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. (access: R/W) +#define PWM_EVENT_CFG_SEL1_BIT 4 +#define PWM_EVENT_CFG_SEL1_WIDTH 4 +#define PWM_EVENT_CFG_SEL1_MASK 0xf0 + +// ADV_TIMER output event 2 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. (access: R/W) +#define PWM_EVENT_CFG_SEL2_BIT 8 +#define PWM_EVENT_CFG_SEL2_WIDTH 4 +#define PWM_EVENT_CFG_SEL2_MASK 0xf00 + +// ADV_TIMER output event 3 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. (access: R/W) +#define PWM_EVENT_CFG_SEL3_BIT 12 +#define PWM_EVENT_CFG_SEL3_WIDTH 4 +#define PWM_EVENT_CFG_SEL3_MASK 0xf000 + +// ADV_TIMER output event enable configuration bitfield. ENA[i]=1 enables output event i generation. (access: R/W) +#define PWM_EVENT_CFG_ENA_BIT 16 +#define PWM_EVENT_CFG_ENA_WIDTH 4 +#define PWM_EVENT_CFG_ENA_MASK 0xf0000 + +// ADV_TIMER clock gating configuration bitfield. - ENA[i]=0: clock gate ADV_TIMERi. - ENA[i]=1: enable ADV_TIMERi. (access: R/W) +#define PWM_CG_ENA_BIT 0 +#define PWM_CG_ENA_WIDTH 16 +#define PWM_CG_ENA_MASK 0xffff + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regmap.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regmap.h new file mode 100644 index 0000000..c2dedfe --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regmap.h @@ -0,0 +1,80 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGMAP_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGMAP_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS GLOBAL STRUCT +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef struct { + unsigned int t0_cmd ; // ADV_TIMER0 command register. + unsigned int t0_config ; // ADV_TIMER0 configuration register. + unsigned int t0_threshold ; // ADV_TIMER0 threshold configuration register. + unsigned int t0_th_channel0 ; // ADV_TIMER0 channel 0 threshold configuration register. + unsigned int t0_th_channel1 ; // ADV_TIMER0 channel 1 threshold configuration register. + unsigned int t0_th_channel2 ; // ADV_TIMER0 channel 2 threshold configuration register. + unsigned int t0_th_channel3 ; // ADV_TIMER0 channel 3 threshold configuration register. + unsigned int t0_counter ; // ADV_TIMER0 counter register. + unsigned int t1_cmd ; // ADV_TIMER1 command register. + unsigned int t1_config ; // ADV_TIMER1 configuration register. + unsigned int t1_threshold ; // ADV_TIMER1 threshold configuration register. + unsigned int t1_th_channel0 ; // ADV_TIMER1 channel 0 threshold configuration register. + unsigned int t1_th_channel1 ; // ADV_TIMER1 channel 1 threshold configuration register. + unsigned int t1_th_channel2 ; // ADV_TIMER1 channel 2 threshold configuration register. + unsigned int t1_th_channel3 ; // ADV_TIMER1 channel 3 threshold configuration register. + unsigned int t1_counter ; // ADV_TIMER1 counter register. + unsigned int t2_cmd ; // ADV_TIMER2 command register. + unsigned int t2_config ; // ADV_TIMER2 configuration register. + unsigned int t2_threshold ; // ADV_TIMER2 threshold configuration register. + unsigned int t2_th_channel0 ; // ADV_TIMER2 channel 0 threshold configuration register. + unsigned int t2_th_channel1 ; // ADV_TIMER2 channel 1 threshold configuration register. + unsigned int t2_th_channel2 ; // ADV_TIMER2 channel 2 threshold configuration register. + unsigned int t2_th_channel3 ; // ADV_TIMER2 channel 3 threshold configuration register. + unsigned int t2_counter ; // ADV_TIMER2 counter register. + unsigned int t3_cmd ; // ADV_TIMER3 command register. + unsigned int t3_config ; // ADV_TIMER3 configuration register. + unsigned int t3_threshold ; // ADV_TIMER3 threshold configuration register. + unsigned int t3_th_channel0 ; // ADV_TIMER3 channel 0 threshold configuration register. + unsigned int t3_th_channel1 ; // ADV_TIMER3 channel 1 threshold configuration register. + unsigned int t3_th_channel2 ; // ADV_TIMER3 channel 2 threshold configuration register. + unsigned int t3_th_channel3 ; // ADV_TIMER3 channel 3 threshold configuration register. + unsigned int t3_counter ; // ADV_TIMER3 counter register. + unsigned int event_cfg ; // ADV_TIMERS events configuration register. + unsigned int cg ; // ADV_TIMERS channels clock gating configuration register. +} __attribute__((packed)) pwm_pwm_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regs.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regs.h new file mode 100644 index 0000000..bd43cd8 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_regs.h @@ -0,0 +1,141 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_REGS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// ADV_TIMER0 command register. +#define PWM_T0_CMD_OFFSET 0x0 + +// ADV_TIMER0 configuration register. +#define PWM_T0_CONFIG_OFFSET 0x4 + +// ADV_TIMER0 threshold configuration register. +#define PWM_T0_THRESHOLD_OFFSET 0x8 + +// ADV_TIMER0 channel 0 threshold configuration register. +#define PWM_T0_TH_CHANNEL0_OFFSET 0xc + +// ADV_TIMER0 channel 1 threshold configuration register. +#define PWM_T0_TH_CHANNEL1_OFFSET 0x10 + +// ADV_TIMER0 channel 2 threshold configuration register. +#define PWM_T0_TH_CHANNEL2_OFFSET 0x14 + +// ADV_TIMER0 channel 3 threshold configuration register. +#define PWM_T0_TH_CHANNEL3_OFFSET 0x18 + +// ADV_TIMER0 counter register. +#define PWM_T0_COUNTER_OFFSET 0x2c + +// ADV_TIMER1 command register. +#define PWM_T1_CMD_OFFSET 0x40 + +// ADV_TIMER1 configuration register. +#define PWM_T1_CONFIG_OFFSET 0x44 + +// ADV_TIMER1 threshold configuration register. +#define PWM_T1_THRESHOLD_OFFSET 0x48 + +// ADV_TIMER1 channel 0 threshold configuration register. +#define PWM_T1_TH_CHANNEL0_OFFSET 0x4c + +// ADV_TIMER1 channel 1 threshold configuration register. +#define PWM_T1_TH_CHANNEL1_OFFSET 0x50 + +// ADV_TIMER1 channel 2 threshold configuration register. +#define PWM_T1_TH_CHANNEL2_OFFSET 0x54 + +// ADV_TIMER1 channel 3 threshold configuration register. +#define PWM_T1_TH_CHANNEL3_OFFSET 0x58 + +// ADV_TIMER1 counter register. +#define PWM_T1_COUNTER_OFFSET 0x6c + +// ADV_TIMER2 command register. +#define PWM_T2_CMD_OFFSET 0x80 + +// ADV_TIMER2 configuration register. +#define PWM_T2_CONFIG_OFFSET 0x84 + +// ADV_TIMER2 threshold configuration register. +#define PWM_T2_THRESHOLD_OFFSET 0x88 + +// ADV_TIMER2 channel 0 threshold configuration register. +#define PWM_T2_TH_CHANNEL0_OFFSET 0x8c + +// ADV_TIMER2 channel 1 threshold configuration register. +#define PWM_T2_TH_CHANNEL1_OFFSET 0x90 + +// ADV_TIMER2 channel 2 threshold configuration register. +#define PWM_T2_TH_CHANNEL2_OFFSET 0x94 + +// ADV_TIMER2 channel 3 threshold configuration register. +#define PWM_T2_TH_CHANNEL3_OFFSET 0x98 + +// ADV_TIMER2 counter register. +#define PWM_T2_COUNTER_OFFSET 0xac + +// ADV_TIMER3 command register. +#define PWM_T3_CMD_OFFSET 0xc0 + +// ADV_TIMER3 configuration register. +#define PWM_T3_CONFIG_OFFSET 0xc4 + +// ADV_TIMER3 threshold configuration register. +#define PWM_T3_THRESHOLD_OFFSET 0xc8 + +// ADV_TIMER3 channel 0 threshold configuration register. +#define PWM_T3_TH_CHANNEL0_OFFSET 0xcc + +// ADV_TIMER3 channel 1 threshold configuration register. +#define PWM_T3_TH_CHANNEL1_OFFSET 0xd0 + +// ADV_TIMER3 channel 2 threshold configuration register. +#define PWM_T3_TH_CHANNEL2_OFFSET 0xd4 + +// ADV_TIMER3 channel 3 threshold configuration register. +#define PWM_T3_TH_CHANNEL3_OFFSET 0xd8 + +// ADV_TIMER3 counter register. +#define PWM_T3_COUNTER_OFFSET 0xec + +// ADV_TIMERS events configuration register. +#define PWM_EVENT_CFG_OFFSET 0x100 + +// ADV_TIMERS channels clock gating configuration register. +#define PWM_CG_OFFSET 0x104 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_structs.h b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_structs.h new file mode 100644 index 0000000..5076808 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/pwm/v1/pwm_v1_structs.h @@ -0,0 +1,337 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_PWM_V1_PWM_V1_STRUCTS_H__ +#define __INCLUDE_ARCHI_PWM_V1_PWM_V1_STRUCTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef union { + struct { + unsigned int start :1 ; // ADV_TIMER0 start command bitfield. + unsigned int stop :1 ; // ADV_TIMER0 stop command bitfield. + unsigned int update :1 ; // ADV_TIMER0 update command bitfield. + unsigned int reset :1 ; // ADV_TIMER0 reset command bitfield. + unsigned int arm :1 ; // ADV_TIMER0 arm command bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_cmd_t; + +typedef union { + struct { + unsigned int insel :8 ; // ADV_TIMER0 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 + unsigned int mode :3 ; // ADV_TIMER0 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed + unsigned int clksel :1 ; // ADV_TIMER0 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz + unsigned int updownsel :1 ; // ADV_TIMER0 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. + unsigned int padding0:3 ; + unsigned int presc :8 ; // ADV_TIMER0 prescaler value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_config_t; + +typedef union { + struct { + unsigned int th_lo :16; // ADV_TIMER0 threshold low part configuration bitfield. It defines start counter value. + unsigned int th_hi :16; // ADV_TIMER0 threshold high part configuration bitfield. It defines end counter value. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_threshold_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER0 channel 0 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER0 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_th_channel0_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER0 channel 1 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER0 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_th_channel1_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER0 channel 2 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER0 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_th_channel2_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER0 channel 3 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER0 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_th_channel3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) pwm_t0_counter_t; + +typedef union { + struct { + unsigned int start :1 ; // ADV_TIMER1 start command bitfield. + unsigned int stop :1 ; // ADV_TIMER1 stop command bitfield. + unsigned int update :1 ; // ADV_TIMER1 update command bitfield. + unsigned int reset :1 ; // ADV_TIMER1 reset command bitfield. + unsigned int arm :1 ; // ADV_TIMER1 arm command bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_cmd_t; + +typedef union { + struct { + unsigned int insel :8 ; // ADV_TIMER1 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 + unsigned int mode :3 ; // ADV_TIMER1 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed + unsigned int clksel :1 ; // ADV_TIMER1 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz + unsigned int updownsel :1 ; // ADV_TIMER1 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. + unsigned int padding0:3 ; + unsigned int presc :8 ; // ADV_TIMER1 prescaler value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_config_t; + +typedef union { + struct { + unsigned int th_lo :16; // ADV_TIMER1 threshold low part configuration bitfield. It defines start counter value. + unsigned int th_hi :16; // ADV_TIMER1 threshold high part configuration bitfield. It defines end counter value. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_threshold_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER1 channel 0 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER1 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_th_channel0_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER1 channel 1 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER1 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_th_channel1_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER1 channel 2 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER1 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_th_channel2_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER1 channel 3 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER1 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_th_channel3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) pwm_t1_counter_t; + +typedef union { + struct { + unsigned int start :1 ; // ADV_TIMER2 start command bitfield. + unsigned int stop :1 ; // ADV_TIMER2 stop command bitfield. + unsigned int update :1 ; // ADV_TIMER2 update command bitfield. + unsigned int reset :1 ; // ADV_TIMER2 reset command bitfield. + unsigned int arm :1 ; // ADV_TIMER2 arm command bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_cmd_t; + +typedef union { + struct { + unsigned int insel :8 ; // ADV_TIMER2 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 + unsigned int mode :3 ; // ADV_TIMER2 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed + unsigned int clksel :1 ; // ADV_TIMER2 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz + unsigned int updownsel :1 ; // ADV_TIMER2 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. + unsigned int padding0:3 ; + unsigned int presc :8 ; // ADV_TIMER2 prescaler value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_config_t; + +typedef union { + struct { + unsigned int th_lo :16; // ADV_TIMER2 threshold low part configuration bitfield. It defines start counter value. + unsigned int th_hi :16; // ADV_TIMER2 threshold high part configuration bitfield. It defines end counter value. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_threshold_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER2 channel 0 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER2 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_th_channel0_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER2 channel 1 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER2 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_th_channel1_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER2 channel 2 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER2 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_th_channel2_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER2 channel 3 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER2 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_th_channel3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) pwm_t2_counter_t; + +typedef union { + struct { + unsigned int start :1 ; // ADV_TIMER3 start command bitfield. + unsigned int stop :1 ; // ADV_TIMER3 stop command bitfield. + unsigned int update :1 ; // ADV_TIMER3 update command bitfield. + unsigned int reset :1 ; // ADV_TIMER3 reset command bitfield. + unsigned int arm :1 ; // ADV_TIMER3 arm command bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_cmd_t; + +typedef union { + struct { + unsigned int insel :8 ; // ADV_TIMER3 input source configuration bitfield: - 0-31: GPIO[0] to GPIO[31] - 32-35: Channel 0 to 3 of ADV_TIMER0 - 36-39: Channel 0 to 3 of ADV_TIMER1 - 40-43: Channel 0 to 3 of ADV_TIMER2 - 44-47: Channel 0 to 3 of ADV_TIMER3 + unsigned int mode :3 ; // ADV_TIMER3 trigger mode configuration bitfield: - 3'h0: trigger event at each clock cycle. - 3'h1: trigger event if input source is 0 - 3'h2: trigger event if input source is 1 - 3'h3: trigger event on input source rising edge - 3'h4: trigger event on input source falling edge - 3'h5: trigger event on input source falling or rising edge - 3'h6: trigger event on input source rising edge when armed - 3'h7: trigger event on input source falling edge when armed + unsigned int clksel :1 ; // ADV_TIMER3 clock source configuration bitfield: - 1'b0: FLL - 1'b1: reference clock at 32kHz + unsigned int updownsel :1 ; // ADV_TIMER3 center-aligned mode configuration bitfield: - 1'b0: The counter counts up and down alternatively. - 1'b1: The counter counts up and resets to 0 when reach threshold. + unsigned int padding0:3 ; + unsigned int presc :8 ; // ADV_TIMER3 prescaler value configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_config_t; + +typedef union { + struct { + unsigned int th_lo :16; // ADV_TIMER3 threshold low part configuration bitfield. It defines start counter value. + unsigned int th_hi :16; // ADV_TIMER3 threshold high part configuration bitfield. It defines end counter value. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_threshold_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER3 channel 0 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER3 channel 0 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_th_channel0_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER3 channel 1 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER3 channel 1 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_th_channel1_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER3 channel 2 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER3 channel 2 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_th_channel2_t; + +typedef union { + struct { + unsigned int th :16; // ADV_TIMER3 channel 3 threshold configuration bitfield. + unsigned int mode :3 ; // ADV_TIMER3 channel 3 threshold match action on channel output signal configuration bitfield: - 3'h0: set. - 3'h1: toggle then next threshold match action is clear. - 3'h2: set then next threshold match action is clear. - 3'h3: toggle. - 3'h4: clear. - 3'h5: toggle then next threshold match action is set. - 3'h6: clear then next threshold match action is set. + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_th_channel3_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) pwm_t3_counter_t; + +typedef union { + struct { + unsigned int sel0 :4 ; // ADV_TIMER output event 0 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. + unsigned int sel1 :4 ; // ADV_TIMER output event 1 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. + unsigned int sel2 :4 ; // ADV_TIMER output event 2 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. + unsigned int sel3 :4 ; // ADV_TIMER output event 3 source configuration bitfiled: - 4'h0: ADV_TIMER0 channel 0. - 4'h1: ADV_TIMER0 channel 1. - 4'h2: ADV_TIMER0 channel 2. - 4'h3: ADV_TIMER0 channel 3. - 4'h4: ADV_TIMER1 channel 0. - 4'h5: ADV_TIMER1 channel 1. - 4'h6: ADV_TIMER1 channel 2. - 4'h7: ADV_TIMER1 channel 3. - 4'h8: ADV_TIMER2 channel 0. - 4'h9: ADV_TIMER2 channel 1. - 4'hA: ADV_TIMER2 channel 2. - 4'hB: ADV_TIMER2 channel 3. - 4'hC: ADV_TIMER3 channel 0. - 4'hD: ADV_TIMER3 channel 1. - 4'hE: ADV_TIMER3 channel 2. - 4'hF: ADV_TIMER3 channel 3. + unsigned int ena :4 ; // ADV_TIMER output event enable configuration bitfield. ENA[i]=1 enables output event i generation. + }; + unsigned int raw; +} __attribute__((packed)) pwm_event_cfg_t; + +typedef union { + struct { + unsigned int ena :16; // ADV_TIMER clock gating configuration bitfield. - ENA[i]=0: clock gate ADV_TIMERi. - ENA[i]=1: enable ADV_TIMERi. + }; + unsigned int raw; +} __attribute__((packed)) pwm_cg_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/rab/rab_v1.h b/sw/pulp-sdk/archi/include/archi/rab/rab_v1.h new file mode 100644 index 0000000..5fd5e6e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/rab/rab_v1.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_RAB_V1_H__ +#define __ARCHI_RAB_V1_H__ + +#include "archi/pulp.h" // for ARCHI_RAB_CFG_ADDR, RAB_L1_N_SLICES_PORT_0, + // RAB_L1_N_SLICES_PORT_1, RAB_L2_N_ENTRIES_PER_SET, RAB_L2_N_SETS + +// This struct represents the information in the L1 TLB hardware. +typedef struct { + volatile uint32_t word[8]; +} rab_cfg_t; + +// L1 addresses and pointers +#define RAB_CFG_L1_ADDR ((unsigned)(ARCHI_RAB_CFG_ADDR) + 4*8) +#define RAB_CFG_BPTR ((rab_cfg_t*)(RAB_CFG_L1_ADDR) + (RAB_L1_N_SLICES_PORT_0)) +#define RAB_CFG_EPTR ((RAB_CFG_BPTR) + (RAB_L1_N_SLICES_PORT_1)) + +#define RAB_CFG_FLAG_EN ((unsigned)(1 << 0)) +#define RAB_CFG_FLAG_RDEN ((unsigned)(1 << 1)) +#define RAB_CFG_FLAG_WREN ((unsigned)(1 << 2)) +#define RAB_CFG_FLAG_COHERENT ((unsigned)(1 << 3)) // cache-coherent with host + +// These types represents the information in the L2 TLB hardware. +typedef volatile uint32_t rab_cfg_l2_varam_t; +typedef volatile uint32_t rab_cfg_l2_param_t; + +// L2 addresses and pointers +#define RAB_CFG_L2_ADDR ((unsigned)(ARCHI_RAB_CFG_ADDR) + 2*0x4000) +#define RAB_CFG_L2_VARAM_PTR(i_set, i_entry) \ + ((rab_cfg_l2_varam_t*)(RAB_CFG_L2_ADDR + i_set*RAB_L2_N_ENTRIES_PER_SET*4 + i_entry*4)) +#define RAB_CFG_L2_PARAM_PTR(i_set, i_entry) \ + ((rab_cfg_l2_param_t*)(RAB_CFG_L2_ADDR + i_set*RAB_L2_N_ENTRIES_PER_SET*4 + i_entry*4 \ + + RAB_L2_N_SETS*RAB_L2_N_ENTRIES_PER_SET*4)) + +#define RAB_CFG_L2_SET_PFN_MASK ((unsigned)(RAB_L2_N_SETS-1)) + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/builtins_v2.h b/sw/pulp-sdk/archi/include/archi/riscv/builtins_v2.h new file mode 100644 index 0000000..529a937 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/builtins_v2.h @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + +#ifndef __HAL_RISCV_BUILTINS_V2_H__ +#define __HAL_RISCV_BUILTINS_V2_H__ +#ifdef ARCHI_CORE_HAS_PULPV2 +/* ARITHMETIC SECTION */ +typedef signed short v2s __attribute__((vector_size (4))); +typedef unsigned short v2u __attribute__((vector_size (4))); + +typedef signed char v4s __attribute__((vector_size (4))); +typedef unsigned char v4u __attribute__((vector_size (4))); + +#ifdef __EMUL__ +typedef void * rt_pointerT; +#else +typedef unsigned int rt_pointerT; +#endif +/* Packing of scalars into vectors */ +#define __PACK2(x, y) __builtin_pulp_pack2((signed short) (x), (signed short) (y)) +#define __PACKU2(x, y) __builtin_pulp_pack2((unsigned short) (x), (unsigned short) (y)) + +#define __PACK4(x, y, z, t) __builtin_pulp_pack4((signed char) (x), (signed char) (y), (signed char) (z), (signed char) (t)) +#define __PACKU4(x, y, z, t) __builtin_pulp_pack4((unsigned char) (x), (unsigned char) (y), (unsigned char) (z), (unsigned char) (t)) + +/* Max */ +#define __MAX(a, b) __builtin_pulp_maxsi((a), (b)) + +#define __MAX2(x, y) __builtin_pulp_max2((x), (y)) +#define __MAX4(x, y) __builtin_pulp_max4((x), (y)) + +#define __MAXU2(x, y) __builtin_pulp_maxu2((x), (y)) +#define __MAXU4(x, y) __builtin_pulp_maxu4((x), (y)) + +/* Min */ +#define __MIN2(x, y) __builtin_pulp_min2((x), (y)) +#define __MIN4(x, y) __builtin_pulp_min4((x), (y)) + +#define __MINU2(x, y) __builtin_pulp_minu2((x), (y)) +#define __MINU4(x, y) __builtin_pulp_minu4((x), (y)) + +/* Clip */ +#define __CLIP(x, precision) __builtin_pulp_clip((x), -(1<<(precision)), (1<(y)?(x):(y)) +#define __MAX2(x, y) ((v2s) {((signed short)(x)[0]>(signed short)(y)[0])?((signed short)(x)[0]):((signed short)(y)[0]), \ + ((signed short)(x)[1]>(signed short)(y)[1])?((signed short)(x)[1]):((signed short)(y)[1])}) +#define __MAX4(x, y) ((v4s) {((signed char)(x)[0]>(signed char)(y)[0])?(signed char)(x)[0]:(signed char)(y)[0], \ + ((signed char)(x)[1]>(signed char)(y)[1])?(signed char)(x)[1]:(signed char)(y)[1], \ + ((signed char)(x)[2]>(signed char)(y)[2])?(signed char)(x)[2]:(signed char)(y)[2], \ + ((signed char)(x)[3]>(signed char)(y)[3])?(signed char)(x)[3]:(signed char)(y)[3]}) + +#define __MAXU2(x, y) ((v2u) {((unsigned short)(x)[0]>(unsigned short)(y)[0])?(unsigned short)(x)[0]:(unsigned short)(y)[0], \ + ((unsigned short)(x)[1]>(unsigned short)(y)[1])?(unsigned short)(x)[1]:(unsigned short)(y)[1]}) +#define __MAXU4(x, y) ((v4u) {((unsigned char)(x)[0]>(unsigned char)(y)[0])?(unsigned char)(x)[0]:(unsigned char)(y)[0], \ + ((unsigned char)(x)[1]>(unsigned char)(y)[1])?(unsigned char)(x)[1]:(unsigned char)(y)[1], \ + ((unsigned char)(x)[2]>(unsigned char)(y)[2])?(unsigned char)(x)[2]:(unsigned char)(y)[2], \ + ((unsigned char)(x)[3]>(unsigned char)(y)[3])?(unsigned char)(x)[3]:(unsigned char)(y)[3]}) + +/* Min */ +#define __MIN2(x, y) ((v2s) {((signed short)(x)[0]<(signed short)(y)[0])?((signed short)(x)[0]):((signed short)(y)[0]), \ + ((signed short)(x)[1]<(signed short)(y)[1])?((signed short)(x)[1]):((signed short)(y)[1])}) +#define __MIN4(x, y) ((v4s) {((signed char)(x)[0]<(signed char)(y)[0])?(signed char)(x)[0]:(signed char)(y)[0], \ + ((signed char)(x)[1]<(signed char)(y)[1])?(signed char)(x)[1]:(signed char)(y)[1], \ + ((signed char)(x)[2]<(signed char)(y)[2])?(signed char)(x)[2]:(signed char)(y)[2], \ + ((signed char)(x)[3]<(signed char)(y)[3])?(signed char)(x)[3]:(signed char)(y)[3]}) + +#define __MINU2(x, y) ((v2u) {((unsigned short)(x)[0]<(unsigned short)(y)[0])?(unsigned short)(x)[0]:(unsigned short)(y)[0], \ + ((unsigned short)(x)[1]<(unsigned short)(y)[1])?(unsigned short)(x)[1]:(unsigned short)(y)[1]}) +#define __MINU4(x, y) ((v4u) {((unsigned char)(x)[0]<(unsigned char)(y)[0])?(unsigned char)(x)[0]:(unsigned char)(y)[0], \ + ((unsigned char)(x)[1]<(unsigned char)(y)[1])?(unsigned char)(x)[1]:(unsigned char)(y)[1], \ + ((unsigned char)(x)[2]<(unsigned char)(y)[2])?(unsigned char)(x)[2]:(unsigned char)(y)[2], \ + ((unsigned char)(x)[3]<(unsigned char)(y)[3])?(unsigned char)(x)[3]:(unsigned char)(y)[3]}) + +/* Clip */ +#define __CLIP(x, precision) ((x)<(-(1<<(precision)))?(-(1<<(precision))):(((x)>((1<<(precision))-1))?((1<<(precision))-1):(x))) +#define __CLIP_R(x, bound) (((x)<=-((bound)+1))?(-((bound)+1)):(((x)>=(bound))?(bound):(x))) + +#define __CLIPU(x, precision) ((x)<0)?0:(((x)>((1<<(precision))-1))?((1<<(precision))-1):(x)) +#define __CLIPU_R(x, bound) (((x)<=0)?(0):(((x)>=(bound))?(bound):(x))) + +/* Abs */ +#define __ABS2(x) ((v2u) {((x)[0]<0)?-(x)[0]:(x)[0], ((x)[1]<0)?-(x)[1]:(x)[1]}) +#define __ABS4(x) ((v4u) {((x)[0]<0)?-(x)[0]:(x)[0], ((x)[1]<0)?-(x)[1]:(x)[1], \ + ((x)[2]<0)?-(x)[2]:(x)[2], ((x)[3]<0)?-(x)[3]:(x)[3]}) + +/* Unary minus */ +#define __NEG2(x) ((v2s) {-(x)[0], -(x)[1]} +#define __NEG4(x) ((v4s) {-(x)[0], -(x)[1], -(x)[2], -(x)[3]} + +/* Addition */ +#define __ADD2(x, y) ((v2s) {(x)[0]+(y)[0], (x)[1]+(y)[1]} +#define __ADD4(x, y) ((v4s) {(x)[0]+(y)[0], (x)[1]+(y)[1], (x)[2]+(y)[2], (x)[3]+(y)[3]} + +/* Substraction */ +#define __SUB2(x, y) ((v2s) {(x)[0]-(y)[0], (x)[1]-(y)[1]} +#define __SUB4(x, y) ((v4s) {(x)[0]-(y)[0], (x)[1]-(y)[1], (x)[2]-(y)[2], (x)[3]-(y)[3]} + +/* Average */ +#define __AVG2(x, y) ((v2s) {((x)[0]+(y)[0])>>1, ((x)[1]+(y)[1])>>1} +#define __AVG4(x, y) ((v4s) {((x)[0]+(y)[0])>>1, ((x)[1]+(y)[1])>>1, ((x)[2]+(y)[2])>>1, ((x)[3]+(y)[3])>>1} + +/* Average unsigned */ +#define __AVGU2(x, y) ((v2u) {((unsigned short)(x)[0]+(unsigned short)(y)[0])>>1, ((unsigned short)(x)[1]+(unsigned short)(y)[1])>>1} +#define __AVGU4(x, y) ((v4u) {((unsigned char)(x)[0]+(unsigned char)(y)[0])>>1, ((unsigned char)(x)[1]+(unsigned char)(y)[1])>>1, \ + ((unsigned char)(x)[2]+(unsigned char)(y)[2])>>1, ((unsigned char)(x)[3]+(unsigned char)(y)[3])>>1} + +/* Bitwise and */ +#define __AND2(x, y) ((v2s) {(x)[0]&(y)[0], (x)[1]&(y)[1]} +#define __AND4(x, y) ((v4s) {(x)[0]&(y)[0], (x)[1]&(y)[1], (x)[2]&(y)[2], (x)[3]&(y)[3]} + +/* Bitwise or */ +#define __OR2(x, y) ((v2s) {(x)[0]|(y)[0], (x)[1]|(y)[1]} +#define __OR4(x, y) ((v4s) {(x)[0]|(y)[0], (x)[1]|(y)[1], (x)[2]|(y)[2], (x)[3]|(y)[3]} + +/* Bitwise exor */ +#define __EXOR2(x, y) ((v2s) {(x)[0]^(y)[0], (x)[1]^(y)[1]} +#define __EXOR4(x, y) ((v4s) {(x)[0]^(y)[0], (x)[1]^(y)[1], (x)[2]^(y)[2], (x)[3]^(y)[3]} + +/* Logical shift right */ +#define __SRL2(x, y) ((v2u) {((unsigned short)(x)[0]>>(unsigned short)(y)[0]), ((unsigned short)(x)[1]>>(unsigned short)(y)[1])} +#define __SRL4(x, y) ((v4u) {((unsigned char)(x)[0]>>(unsigned char)(y)[0]), ((unsigned char)(x)[1]>>(unsigned char)(y)[1]), \ + ((unsigned char)(x)[2]>>(unsigned char)(y)[2]), ((unsigned char)(x)[3]>>(unsigned char)(y)[3])} + +/* Arithmetic shift right */ +#define __SRA2(x, y) ((v2s) {((signed short)(x)[0]>>(signed short)(y)[0]), ((signed short)(x)[1]>>(signed short)(y)[1])} +#define __SRA4(x, y) ((v4s) {((signed char)(x)[0]>>(signed char)(y)[0]), ((signed char)(x)[1]>>(signed char)(y)[1]), \ + ((signed char)(x)[2]>>(signed char)(y)[2]), ((signed char)(x)[3]>>(signed char)(y)[3])} + +/* Logical shift left */ +#define __SLL2(x, y) ((v2s) {(x)[0]<<(y)[0], (x)[1]<<(y)[1]} +#define __SLL4(x, y) ((v4s) {(x)[0]<<(y)[0], (x)[1]<<(y)[1], (x)[2]<<(y)[2], (x)[3]<<(y)[3]} + +/* Mac */ +#define __MAC(Acc, x, y) ((Acc) + ((x) * (y))) +#define __MSU(Acc, x, y) ((Acc) - ((x) * (y))) + +#define __MACS(Acc, x, y) ((Acc) + ((short int) (x) * (short int) (y))) +#define __MACHHS(Acc, x, y) ((Acc) + ((short int) ((x)>>16) * (short int) ((y)>>16))) +#define __MACU(Acc, x, y) ((Acc) + ((unsigned short int) (x) * (unsigned short int) (y))) +#define __MACHHU(Acc, x, y) ((Acc) + ((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16))) + +#define __MACSN(Acc, x, y, n) (((Acc) + ((short int) (x) * (short int) (y)))>>(n)) +#define __MACUN(Acc, x, y, n) (((Acc) + ((unsigned short int) (x) * (unsigned short int) (y)))>>(n)) +#define __MACSRN(Acc, x, y, n) ((((Acc) + ((short int) (x) * (short int) (y))) + (1<<((n)-1))) >> (n)) +#define __MACURN(Acc, x, y, n) ((((Acc) + ((unsigned short int) (x) * (unsigned short int) (y))) + (1<<((n)-1))) >> (n)) + +#define __MACHHSN(Acc, x, y, n) (((Acc) + ((short int) ((x)>>16) * (short int) ((y)>>16))) >> (n)) +#define __MACHHUN(Acc, x, y, n) (((Acc) + ((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16))) >> (n)) +#define __MACHHSRN(Acc, x, y, n) ((((Acc) + ((short int) ((x)>>16) * (short int) ((y)>>16))) + (1<<((n)-1))) >> (n)) +#define __MACHHURN(Acc, x, y, n) ((((Acc) + ((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16))) + (n))) + +/* Multiplications */ +#define __MULS(x, y) (((short int) (x) * (short int) (y))) +#define __MULU(x, y) (((unsigned short int) (x) * (unsigned short int) (y))) +#define __MULHHS(x, y) (((short int) ((x)>>16) * (short int) ((y)>>16))) +#define __MULHHU(x, y) (((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16))) + +#define __MULSN(x, y, n) (((short int) (x) * (short int) (y))>>(n)) +#define __MULSRN(x, y, n) ((((short int) (x) * (short int) (y)) + (1<<((n)-1)))>>(n)) +#define __MULUN(x, y, n) (((unsigned short int) (x) * (unsigned short int) (y))>>(n)) +#define __MULURN(x, y, n) ((((unsigned short int) (x) * (unsigned short int) (y)) + (1<<((n)-1)))>>(n)) + +#define __MULHHSN(x, y, n) ((((short int) ((x)>>16) * (short int) ((y)>>16)))>>(n)) +#define __MULHHSRN(x, y, n) (((((short int) ((x)>>16) * (short int) ((y)>>16)))+(1<<((n)-1)))>>(n)) +#define __MULHHUN(x, y, n) ((((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16)))>>(n)) +#define __MULHHURN(x, y, n) (((((unsigned short int) ((x)>>16) * (unsigned short int) ((y)>>16)))+(1<<((n)-1)))>>(n)) + +/* Vectorial product and sum of products */ +#define __DOTP2(x, y) ( (short)(x)[0]*(short)(y)[0] + (short)(x)[1]*(short)(y)[1]) +#define __DOTPU2(x, y) ( (unsigned short)(x)[0]*(unsigned short)(y)[0] + (unsigned short)(x)[1]*(unsigned short)(y)[1]) +#define __DOTPUS2(x, y) ( (unsigned short)(x)[0]*(short)(y)[0] + (unsigned short)(x)[1]*(short)(y)[1]) + +#define __DOTPSC2(x, y) ( (short)(x)[0]*(short)(y) + (short)(x)[1]*(short)(y)) +#define __DOTPUSC2(x, y) ( (unsigned short)(x)[0]*(unsigned short)(y) + (unsigned short)(x)[1]*(unsigned short)(y)) +#define __DOTPUSSC2(x, y) ( (unsigned short)(x)[0]*(short)(y) + (unsigned short)(x)[1]*(short)(y)) + +#define __SUMDOTP2(x, y, z) ((z)+(short)(x)[0]*(short)(y)[0] + (short)(x)[1]*(short)(y)[1]) +#define __SUMDOTPU2(x, y, z) ((z)+(unsigned short)(x)[0]*(unsigned short)(y)[0] + (unsigned short)(x)[1]*(unsigned short)(y)[1]) +#define __SUMDOTPUS2(x, y, z) ((z)+(unsigned short)(x)[0]*(short)(y)[0] + (unsigned short)(x)[1]*(short)(y)[1]) + +#define __SUMDOTPSC2(x, y, z) ((z)+(short)(x)[0]*(short)(y) + (short)(x)[1]*(short)(y)) +#define __SUMDOTPUSC2(x, y, z) ((z)+(unsigned short)(x)[0]*(unsigned short)(y) + (unsigned short)(x)[1]*(unsigned short)(y)) +#define __SUMDOTPUSSC2(x, y, z) ((z)+(unsigned short)(x)[0]*(short)(y) + (unsigned short)(x)[1]*(short)(y)) + +#define __DOTP4(x, y) ( (char)(x)[0]*(char)(y)[0] + (char)(x)[1]*(char)(y)[1] + (char)(x)[2]*(char)(y)[2] + (char)(x)[3]*(char)(y)[3]) +#define __DOTPU4(x, y) ( (unsigned char)(x)[0]*(unsigned char)(y)[0] + (unsigned char)(x)[1]*(unsigned char)(y)[1] + \ + (unsigned char)(x)[2]*(unsigned char)(y)[2] + (unsigned char)(x)[3]*(unsigned char)(y)[3]) +#define __DOTPUS4(x, y) ( (unsigned char)(x)[0]*(char)(y)[0] + (unsigned char)(x)[1]*(char)(y)[1] + \ + (unsigned char)(x)[2]*(char)(y)[2] + (unsigned char)(x)[3]*(char)(y)[3]) + +#define __DOTPSC4(x, y) ( (char)(x)[0]*(char)(y) + (char)(x)[1]*(char)(y) + (char)(x)[2]*(char)(y) + (char)(x)[3]*(char)(y)) +#define __DOTPUSC4(x, y) ( (unsigned char)(x)[0]*(unsigned char)(y) + (unsigned char)(x)[1]*(unsigned char)(y) + \ + (unsigned char)(x)[2]*(unsigned char)(y) + (unsigned char)(x)[3]*(unsigned char)(y)) +#define __DOTPUSSC4(x, y) ( (unsigned char)(x)[0]*(char)(y) + (unsigned char)(x)[1]*(char)(y) + \ + (unsigned char)(x)[2]*(char)(y) + (unsigned char)(x)[3]*(char)(y)) + +#define __SUMDOTP4(x, y, z) ((z)+(char)(x)[0]*(char)(y)[0] + (char)(x)[1]*(char)(y)[1] + (char)(x)[2]*(char)(y)[2] + (char)(x)[3]*(char)(y)[3]) +#define __SUMDOTPU4(x, y, z) ((z)+(unsigned char)(x)[0]*(unsigned char)(y)[0] + (unsigned char)(x)[1]*(unsigned char)(y)[1] + \ + (unsigned char)(x)[2]*(unsigned char)(y)[2] + (unsigned char)(x)[3]*(unsigned char)(y)[3]) +#define __SUMDOTPUS4(x, y, z) ((z)+(unsigned char)(x)[0]*(char)(y)[0] + (unsigned char)(x)[1]*(char)(y)[1] + \ + (unsigned char)(x)[2]*(char)(y)[2] + (unsigned char)(x)[3]*(char)(y)[3]) + +#define __SUMDOTPSC4(x, y, z) ((z)+(char)(x)[0]*(char)(y) + (char)(x)[1]*(char)(y) + (char)(x)[2]*(char)(y) + (char)(x)[3]*(char)(y)) +#define __SUMDOTPUSC4(x, y, z) ((z)+(unsigned char)(x)[0]*(unsigned char)(y) + (unsigned char)(x)[1]*(unsigned char)(y) + \ + (unsigned char)(x)[2]*(unsigned char)(y) + (unsigned char)(x)[3]*(unsigned char)(y)) +#define __SUMDOTPUSSC4(x, y, z) ((z)+(unsigned char)(x)[0]*(char)(y) + (unsigned char)(x)[1]*(char)(y) + \ + (unsigned char)(x)[2]*(char)(y) + (unsigned char)(x)[3]*(char)(y)) + +#ifdef ARCHI_CORE_HAS_CPLX + +/* Complex Multiplication, Q15x15 into Q15, with optional post scaling by 1 or 2 */ +#define __CPLXMULS(x, y) ((v2s) {(signed short) ((((long long) (x)[0]*(long long) (y)[0]) - ((long long) (x)[1]*(long long) (y)[1]))>>15), \ + (signed short) ((((long long) (x)[0]*(long long) (y)[1]) + ((long long) (x)[1]*(long long) (y)[0]))>>15)}) +#define __CPLXMULSDIV2(x, y) (__CPLXMULS(x, y)>>(v2s){1,1}) +#define __CPLXMULSDIV4(x, y) (__CPLXMULS(x, y)>>(v2s){2,2}) + +/* Complex conjugate */ +#define __CPLXCONJ(x) ((v2s) {(x)[0], -(x)[1]}) + +/* Complex substration, result rotated by -pi/2 */ +#define __SUB2ROTMJ(x, y) ((v2s) {(x)[1]-(y)[1], (y)[0]-(x)[0]}) + +/* Complex addition with post scaling by 1 or 2 */ +#define __ADD2DIV2(x, y) (((x)+(y))>>(v2s) {1, 1}) +#define __ADD2DIV4(x, y) (((x)+(y))>>(v2s) {2, 2}) + +#define __ADD4DIV2(x, y) (((x)+(y))>>(v4s) {1, 1, 1, 1}) +#define __ADD4DIV4(x, y) (((x)+(y))>>(v4s) {2, 2, 2, 2}) + +/* Complex substraction with post scaling by 1 or 2 */ +#define __SUB2DIV2(x, y) (((x)-(y))>>(v2s) {1, 1}) +#define __SUB2DIV4(x, y) (((x)-(y))>>(v2s) {2, 2}) + +#define __SUB4DIV2(x, y) (((x)-(y))>>(v4s) {1, 1, 1, 1}) +#define __SUB4DIV4(x, y) (((x)-(y))>>(v4s) {2, 2, 2, 2}) + +/* Complex subtraction with post scaling by 1 or 2 */ +#define __SUB2DIV2(x, y) (((x)-(y))>>(v2s) {1, 1}) +#define __SUB2DIV4(x, y) (((x)-(y))>>(v2s) {2, 2}) + +/* Viterbi Max and Viterbi Select, pair of Q15 */ +#define __VITMAX(x, y) (_VitT1_Flag=((x)[1]<=(y)[1])?1:0, _VitT0_Flag=((x)[0]<=(y)[0])?1:0,\ + (v2s) {((x)[0]>(y)[0])?(x)[0]:(y)[0], ((x)[1]>(y)[1])?(x)[1]:(y)[1]}) +#define __VITSEL(x, y) (v2s) {(_VitT0_Flag?(y)[0]:(x)[0])<<1|_VitT0_Flag, (_VitT1_Flag?(y)[1]:(x)[1])<<1|_VitT1_Flag} + +#endif + +/* Position of the most significant bit of x */ +#define __FL1(x) (31 - __builtin_clz((x))) + +/* Number of sign bits */ +#define __CLB(x) (__builtin_clrsb((x))) + +/* Bit set */ +#define __BITSET(x, size, off) ((x) | (((1<<(size))-1)<<(off))) +#define __BITSET_R(x, size, off) ((x) | (((1<<(size))-1)<<(off))) +#define __BITSET_R_SAFE(x, size, off) ((x) | (((1<<((size)&0x1F))-1)<<((off)&0x1F))) + +/* Bit clr */ +#define __BITCLR(x, size, off) ((x) & ~(((1<<(size))-1)<<(off))) +#define __BITCLR_R(x, size, off) ((x) & ~(((1<<(size))-1)<<(off))) +#define __BITCLR_R_SAFE(x, size, off) ((x) & ~(((1<<((size)&0x1F))-1)<<((off)&0x1F))) + +/* Bit Extraction */ +#define __BITEXTRACT(x, size, off) (((((x)>>(off))&((unsigned int)(1<<(size))-1))<<(32-(size)))>>(32-(size))) +#define __BITEXTRACTU(x, size, off) (((x)>>(off))&((unsigned int)(1<<(size))-1)) + +#define __BITEXTRACT_R(x, size, off) (((((x)>>(off))&((unsigned int)(1<<(size))-1))<<(32-(size)))>>(32-(size))) +#define __BITEXTRACTU_R(x, size, off) (((x)>>(off))&((unsigned int)(1<<(size))-1)) + +#define __BITEXTRACT_R_SAFE(x, size, off) (((((x)>>((off)&0x1F))&((unsigned int)(1<<((((size)>32)?32:(size))))-1))<<(32-((((size)>32)?32:(size)))))>>(32-((((size)>32)?32:(size))))) +#define __BITEXTRACTU_R_SAFE(x, size, off) (((x)>>((off)&0x1F))&((unsigned int)(1<<((((size)>32)?32:(size))))-1)) + +/* Bit insertion */ +#define __BITINSERT(dst, src, size, off) (((dst) & ~(((1<<(size))-1)<<(off))) | (((src) & ((1<<(size))-1))<<(off))) +#define __BITINSERT_R(dst, src, size, off) (((dst) & ~(((1<<(size))-1)<<(off))) | (((src) & ((1<<(size))-1))<<(off))) +#define __BITINSERT_R_SAFE(dst, src, size, off) (((dst) & ~(((1<<(((size)>32)?32:(size)))-1)<<((off)&0x1F))) | (((src) & ((1<<(((size)>32)?32:(size)))-1))<<((off)&0x1F))) + +/* 1 bit rotation to the right, 32 bits input */ +#define __ROTR(x) ((((x)>>1)&0x7FFFFFFF) | ((x)<<31)) + +/* Add with normalization */ +#define __ADDNORMU(x, y, scale) ((unsigned int)((x) + (y))>>(scale)) +#define __ADDNORMU_REG(x, y, scale) ((unsigned int)((x) + (y))>>(scale)) +#define __ADDNORM(x, y, scale) ((int)((x) + (y))>>(scale)) +#define __ADDNORM_REG(x, y, scale) ((int)((x) + (y))>>(scale)) + +/* Add with normalization and rounding */ +#define __ADDROUNDNORMU(x, y, scale) ((unsigned int)((x) + (y) + (1<<((scale)-1)))>>(scale)) +#define __ADDROUNDNORMU_REG(x, y, scale) ((unsigned int)((x) + (y) + (1<<((scale)-1)))>>(scale)) +#define __ADDROUNDNORM(x, y, scale) ((int)((x) + (y) + (1<<((scale)-1)))>>(scale)) +#define __ADDROUNDNORM_REG(x, y, scale) ((int)((x) + (y) + (1<<((scale)-1)))>>(scale)) + +/* Sub with normalization */ +#define __SUBNORMU(x, y, scale) ((unsigned int)((x) - (y))>>(scale)) +#define __SUBNORMU_REG(x, y, scale) ((unsigned int)((x) - (y))>>(scale)) +#define __SUBNORM(x, y, scale) ((int)((x) - (y))>>(scale)) +#define __SUBNORM_REG(x, y, scale) ((int)((x) - (y))>>(scale)) + +/* Sub with normalization and rounding */ +#define __SUBROUNDNORMU(x, y, scale) ((unsigned int)((x) - (y) + (1<<((scale)-1)))>>(scale)) +#define __SUBROUNDNORMU_REG(x, y, scale) ((unsigned int)((x) - (y) + (1<<((scale)-1)))>>(scale)) +#define __SUBROUNDNORM(x, y, scale) ((int)((x) - (y) + (1<<((scale)-1)))>>(scale)) +#define __SUBROUNDNORM_REG(x, y, scale) ((int)((x) - (y) + (1<<((scale)-1)))>>(scale)) + +/* Normalization and rounding */ +#define __ROUNDNORMU(x, scale) ((unsigned int)((x) + (1<<((scale)-1)))>>(scale)) +#define __ROUNDNORMU_REG(x, scale) ((unsigned int)((x) + (1<<((scale)-1)))>>(scale)) +#define __ROUNDNORM(x, scale) ((int)((x) + (1<<((scale)-1)))>>(scale)) +#define __ROUNDNORM_REG(x, scale) ((int)((x) + (1<<((scale)-1)))>>(scale)) +#define __COREID() 0 +#define __CLUSTERID() 0 +#define __NCORE() 1 + +#define __SPRWRITE(x, y) +#define __SPRREAD(x) ((int) 0) +#define __SPRREAD_VOL(x) ((int) 0) + +#define __READ_BASE_OFF(base, off) ((int) 0) +#define __WRITE_BASE_OFF(base, off, val) + +#define __READ_BASE_OFF_VOL(base, off) ((int) 0) +#define __READ_BASE_OFF_HALF_VOL(base, off) ((int) 0) +#define __READ_BASE_OFF_BYTE_VOL(base, off) ((int) 0) + +#define __WRITE_BASE_OFF_VOL(x, base, off) +#define __WRITE_BASE_OFF_HALF_VOL(x, base, off) +#define __WRITE_BASE_OFF_BYTE_VOL(x, base, off) +/* Utilities, Target independant */ +#define FIX2FP(Val, Precision) ((float) (Val) / (float) (1<<(Precision))) +#define FP2FIXR(Val, Precision) ((int)((Val)*((1 << (Precision))-1) + 0.5)) +#define FP2FIX(Val, Precision) ((int)((Val)*((1 << (Precision))-1))) +#endif +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/pcer_v1.h b/sw/pulp-sdk/archi/include/archi/riscv/pcer_v1.h new file mode 100644 index 0000000..c9f92bf --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/pcer_v1.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PCER_V1_H +#define _ARCHI_RISCV_PCER_V1_H + +/* + * Bit definitions for Performance counters mode registers + * + */ +#define CSR_PCER_CYCLES 0 /* Count the number of cycles the core was running */ +#define CSR_PCER_INSTR 1 /* Count the number of instructions executed */ +#define CSR_PCER_LD_STALL 2 /* Number of load use hazards */ +#define CSR_PCER_JMP_STALL 3 /* Number of jump register hazards */ +#define CSR_PCER_IMISS 4 /* Cycles waiting for instruction fetches. i.e. the number of instructions wasted due to non-ideal caches */ +#define CSR_PCER_LD 5 /* Number of memory loads executed. Misaligned accesses are counted twice */ +#define CSR_PCER_ST 6 /* Number of memory stores executed. Misaligned accesses are counted twice */ +#define CSR_PCER_JUMP 7 /* Number of jump instructions seen, i.e. j, jr, jal, jalr */ +#define CSR_PCER_BRANCH 8 /* Number of branch instructions seen, i.e. bf, bnf */ +#define CSR_PCER_TAKEN_BRANCH 9 /* Number of taken branch instructions seen, i.e. bf, bnf */ +#define CSR_PCER_RVC 10 /* Number of compressed instructions */ +#define CSR_PCER_LD_EXT 11 /* Number of memory loads to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define CSR_PCER_ST_EXT 12 /* Number of memory stores to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define CSR_PCER_LD_EXT_CYC 13 /* Cycles used for memory loads to EXT. Every non-TCDM access is considered external */ +#define CSR_PCER_ST_EXT_CYC 14 /* Cycles used for memory stores to EXT. Every non-TCDM access is considered external */ +#define CSR_PCER_TCDM_CONT 15 /* Cycles wasted due to TCDM/log-interconnect contention */ +#define CSR_PCER_CSR_HAZARD 16 +#define CSR_PCER_APU_TY_CONF 17 +#define CSR_PCER_APU_CONT 18 +#define CSR_PCER_APU_DEP 19 +#define CSR_PCER_APU_WB 20 + + +#define CSR_PCER_NB_EVENTS 16 +#define CSR_PCER_NB_INTERNAL_EVENTS 11 +#define CSR_NB_PCCR 31 + +// Gives from the event ID, the HW mask that can be stored (with an OR with other events mask) to the PCER +#define CSR_PCER_EVENT_MASK(eventId) (1<<(eventId)) +#define CSR_PCER_ALL_EVENTS_MASK 0xffffffff + +#define CSR_PCMR_ACTIVE 0x1 /* Activate counting */ +#define CSR_PCMR_SATURATE 0x2 /* Activate saturation */ + +#define CSR_PCER_NAME(id) (id == 0 ? "Cycles" : id == 1 ? "Instructions" : id == 2 ? "LD_Stall" : id == 3 ? "Jmp_Stall" : id == 4 ? "IMISS" : id == 5 ? "LD" : id == 6 ? "ST" : id == 7 ? "JUMP" : id == 8 ? "BRANCH" : id == 9 ? "TAKEN_BRANCH" : id == 10 ? "RVC" : id == 11 ? "LD_EXT" : id == 12 ? "ST_EXT" : id == 13 ? "LD_EXT_CYC" : id == 14 ? "ST_EXT_CYC" : id == 15 ? "TCDM_CONT" : "NA") + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/pcer_v2.h b/sw/pulp-sdk/archi/include/archi/riscv/pcer_v2.h new file mode 100644 index 0000000..c329258 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/pcer_v2.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PCER_V1_H +#define _ARCHI_RISCV_PCER_V1_H + +/* + * Bit definitions for Performance counters mode registers + * + */ +#define CSR_PCER_CYCLES 0 /* Count the number of cycles the core was running */ +#define CSR_PCER_INSTR 1 /* Count the number of instructions executed */ +#define CSR_PCER_LD_STALL 2 /* Number of load use hazards */ +#define CSR_PCER_JMP_STALL 3 /* Number of jump register hazards */ +#define CSR_PCER_IMISS 4 /* Cycles waiting for instruction fetches. i.e. the number of instructions wasted due to non-ideal caches */ +#define CSR_PCER_LD 5 /* Number of memory loads executed. Misaligned accesses are counted twice */ +#define CSR_PCER_ST 6 /* Number of memory stores executed. Misaligned accesses are counted twice */ +#define CSR_PCER_JUMP 7 /* Number of jump instructions seen, i.e. j, jr, jal, jalr */ +#define CSR_PCER_BRANCH 8 /* Number of branch instructions seen, i.e. bf, bnf */ +#define CSR_PCER_TAKEN_BRANCH 9 /* Number of taken branch instructions seen, i.e. bf, bnf */ +#define CSR_PCER_RVC 10 /* Number of compressed instructions */ +#define CSR_PCER_ELW 11 /* Cycles wasted due to ELW instruction */ +#define CSR_PCER_LD_EXT 12 /* Number of memory loads to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define CSR_PCER_ST_EXT 13 /* Number of memory stores to EXT executed. Misaligned accesses are counted twice. Every non-TCDM access is considered external */ +#define CSR_PCER_LD_EXT_CYC 14 /* Cycles used for memory loads to EXT. Every non-TCDM access is considered external */ +#define CSR_PCER_ST_EXT_CYC 15 /* Cycles used for memory stores to EXT. Every non-TCDM access is considered external */ +#define CSR_PCER_TCDM_CONT 16 /* Cycles wasted due to TCDM/log-interconnect contention */ + + +#define CSR_PCER_NB_EVENTS 17 +#define CSR_PCER_NB_INTERNAL_EVENTS 12 +#define CSR_NB_PCCR 31 + +// Gives from the event ID, the HW mask that can be stored (with an OR with other events mask) to the PCER +#define CSR_PCER_EVENT_MASK(eventId) (1<<(eventId)) +#define CSR_PCER_ALL_EVENTS_MASK 0xffffffff + +#define CSR_PCMR_ACTIVE 0x1 /* Activate counting */ +#define CSR_PCMR_SATURATE 0x2 /* Activate saturation */ + +#define CSR_PCER_NAME(id) (id == 0 ? "Cycles" : id == 1 ? "Instructions" : id == 2 ? "LD_Stall" : id == 3 ? "Jmp_Stall" : id == 4 ? "IMISS" : id == 5 ? "LD" : id == 6 ? "ST" : id == 7 ? "JUMP" : id == 8 ? "BRANCH" : id == 9 ? "TAKEN_BRANCH" : id == 10 ? "RVC" : id == 11 ? "ELW" : id == 12 ? "LD_EXT" : id == 13 ? "ST_EXT" : id == 14 ? "LD_EXT_CYC" : id == 15 ? "ST_EXT_CYC" : id == 16 ? "TCDM_CONT" : "NA") + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/priv_1.9.h b/sw/pulp-sdk/archi/include/archi/riscv/priv_1.9.h new file mode 100644 index 0000000..ac03cbb --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/priv_1.9.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PRIV_1_9_H +#define _ARCHI_RISCV_PRIV_1_9_H + +#define RV_CSR_MSTATUS 0x300 +#define RV_CSR_MEPC 0x341 +#define RV_CSR_MCAUSE 0x342 +#define RV_CSR_MTVAL 0x343 +#define RV_CSR_MESTATUS 0x7C0 +#define RV_CSR_MISA 0xF10 +#define RV_CSR_MIMPID 0xF13 +#define RV_CSR_MHARTID 0xF14 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/priv_1_10.h b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_10.h new file mode 100644 index 0000000..df6a5ff --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_10.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PRIV_1_9_H +#define _ARCHI_RISCV_PRIV_1_9_H + +#define RV_CSR_MSTATUS 0x300 +#define RV_CSR_MEPC 0x341 +#define RV_CSR_MCAUSE 0x342 +#define RV_CSR_MTVAL 0x343 +#define RV_CSR_MESTATUS 0x7C0 +#ifdef RISCV_1_7 +#define RV_CSR_MCPUID 0xF00 +#define RV_CSR_MIMPID 0xF01 +#define RV_CSR_MHARTID 0xF10 +#else +#define RV_CSR_MISA 0xF10 +#define RV_CSR_MIMPID 0xF13 +#define RV_CSR_MHARTID 0xF14 +#endif + +#define CSR_PCCR(N) (0x780 + (N)) +#define CSR_PCER 0xCC0 +#define CSR_PCMR 0xCC1 + +#define CSR_STACK_CONF 0x7D0 +#define CSR_STACK_START 0x7D1 +#define CSR_STACK_END 0x7D2 + +#define CSR_MESTATUS_INTEN_BIT 0 +#define CSR_MESTATUS_PRV_BIT 1 + +#define CSR_MESTATUS_PRV_MACH 3 + +#define CSR_HWLOOP0_START 0x7C0 +#define CSR_HWLOOP0_END 0x7C1 +#define CSR_HWLOOP0_COUNTER 0x7C2 +#define CSR_HWLOOP1_START 0x7C4 +#define CSR_HWLOOP1_END 0x7C5 +#define CSR_HWLOOP1_COUNTER 0x7C6 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/priv_1_7.h b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_7.h new file mode 100644 index 0000000..f3c9180 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_7.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PRIV_1_7_H +#define _ARCHI_RISCV_PRIV_1_7_H + +#define CSR_MSTATUS 0x300 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MESTATUS 0x7C0 +#define CSR_MCPUID 0xF00 +#define CSR_MIMPID 0xF01 +#define CSR_MHARTID 0xF10 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/riscv/priv_1_9.h b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_9.h new file mode 100644 index 0000000..d06f85f --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/riscv/priv_1_9.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef _ARCHI_RISCV_PRIV_1_9_H +#define _ARCHI_RISCV_PRIV_1_9_H + +#define RV_CSR_MSTATUS 0x300 +#define RV_CSR_MEPC 0x341 +#define RV_CSR_MCAUSE 0x342 +#define RV_CSR_MTVAL 0x343 +#define RV_CSR_MESTATUS 0x7C0 +#ifdef RISCV_1_7 +#define RV_CSR_MCPUID 0xF00 +#define RV_CSR_MIMPID 0xF01 +#define RV_CSR_MHARTID 0xF10 +#else +#define RV_CSR_MISA 0xF10 +#define RV_CSR_MIMPID 0xF13 +#define RV_CSR_MHARTID 0xF14 +#endif + +#define CSR_PCCR(N) (0x780 + (N)) +#define CSR_PCER 0x7A0 +#define CSR_PCMR 0x7A1 + +#define CSR_STACK_CONF 0x7D0 +#define CSR_STACK_START 0x7D1 +#define CSR_STACK_END 0x7D2 + +#define CSR_MESTATUS_INTEN_BIT 0 +#define CSR_MESTATUS_PRV_BIT 1 + +#define CSR_MESTATUS_PRV_MACH 3 + +#define CSR_HWLOOP0_START 0x7B0 +#define CSR_HWLOOP0_END 0x7B1 +#define CSR_HWLOOP0_COUNTER 0x7B2 +#define CSR_HWLOOP1_START 0x7B4 +#define CSR_HWLOOP1_END 0x7B5 +#define CSR_HWLOOP1_COUNTER 0x7B6 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/rtc/rtc_v2.h b/sw/pulp-sdk/archi/include/archi/rtc/rtc_v2.h new file mode 100644 index 0000000..1c341c8 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/rtc/rtc_v2.h @@ -0,0 +1,473 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_RTC_RTC_V2_H__ +#define __INCLUDE_ARCHI_RTC_RTC_V2_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Clock register +#define RTC_CLOCK_OFFSET 0x0 + +// Alarm register +#define RTC_ALARM_OFFSET 0x4 + +// Timer register +#define RTC_TIMER_OFFSET 0x8 + +// Date register +#define RTC_DATE_OFFSET 0xc + + + +// +// REGISTERS FIELDS +// + +// First digit of clock seconds. (access: R/W) +#define RTC_CLOCK_SECONDS_0_BIT 0 +#define RTC_CLOCK_SECONDS_0_WIDTH 4 +#define RTC_CLOCK_SECONDS_0_MASK 0xf + +// Second digit of clock seconds. (access: R/W) +#define RTC_CLOCK_SECONDS_1_BIT 4 +#define RTC_CLOCK_SECONDS_1_WIDTH 4 +#define RTC_CLOCK_SECONDS_1_MASK 0xf0 + +// First digit of clock minutes. (access: R/W) +#define RTC_CLOCK_MINUTES_0_BIT 8 +#define RTC_CLOCK_MINUTES_0_WIDTH 4 +#define RTC_CLOCK_MINUTES_0_MASK 0xf00 + +// Second digit of clock minutes. (access: R/W) +#define RTC_CLOCK_MINUTES_1_BIT 12 +#define RTC_CLOCK_MINUTES_1_WIDTH 4 +#define RTC_CLOCK_MINUTES_1_MASK 0xf000 + +// First digit of clock hours. (access: R/W) +#define RTC_CLOCK_HOURS_0_BIT 16 +#define RTC_CLOCK_HOURS_0_WIDTH 4 +#define RTC_CLOCK_HOURS_0_MASK 0xf0000 + +// Second digit of clock hours. (access: R/W) +#define RTC_CLOCK_HOURS_1_BIT 20 +#define RTC_CLOCK_HOURS_1_WIDTH 2 +#define RTC_CLOCK_HOURS_1_MASK 0x300000 + +// MSB part of second counter initial value. The second counter is incremented every 1/32768 seconds and is incrementing by 1 the number of seconds when it reaches 32768. When the clock is written, bits 0 to 4 are set to 0 and bits 5 to 14 are set to the value of this field. (access: R/W) +#define RTC_CLOCK_INIT_SEC_COUNT_BIT 22 +#define RTC_CLOCK_INIT_SEC_COUNT_WIDTH 10 +#define RTC_CLOCK_INIT_SEC_COUNT_MASK 0xffc00000 + +// First digit of alarm seconds. (access: R/W) +#define RTC_ALARM_SECONDS_0_BIT 0 +#define RTC_ALARM_SECONDS_0_WIDTH 8 +#define RTC_ALARM_SECONDS_0_MASK 0xff + +// Second digit of alarm seconds. (access: R/W) +#define RTC_ALARM_SECONDS_1_BIT 0 +#define RTC_ALARM_SECONDS_1_WIDTH 8 +#define RTC_ALARM_SECONDS_1_MASK 0xff + +// First digit of alarm minutes. (access: R/W) +#define RTC_ALARM_MINUTES_0_BIT 8 +#define RTC_ALARM_MINUTES_0_WIDTH 8 +#define RTC_ALARM_MINUTES_0_MASK 0xff00 + +// Second digit of alarm minutes. (access: R/W) +#define RTC_ALARM_MINUTES_1_BIT 8 +#define RTC_ALARM_MINUTES_1_WIDTH 8 +#define RTC_ALARM_MINUTES_1_MASK 0xff00 + +// First digit of alarm hours. (access: R/W) +#define RTC_ALARM_HOURS_0_BIT 16 +#define RTC_ALARM_HOURS_0_WIDTH 6 +#define RTC_ALARM_HOURS_0_MASK 0x3f0000 + +// Second digit of alarm hours. (access: R/W) +#define RTC_ALARM_HOURS_1_BIT 16 +#define RTC_ALARM_HOURS_1_WIDTH 6 +#define RTC_ALARM_HOURS_1_MASK 0x3f0000 + +// Alarm enable. When set to 1, an event is generated when the alarm is matching the clock. (access: R/W) +#define RTC_ALARM_ENABLE_BIT 31 +#define RTC_ALARM_ENABLE_WIDTH 1 +#define RTC_ALARM_ENABLE_MASK 0x80000000 + +// Timer target. When the timer is enabled, an event is generated when the timer counter is matching this field. (access: R/W) +#define RTC_TIMER_TARGET_BIT 0 +#define RTC_TIMER_TARGET_WIDTH 17 +#define RTC_TIMER_TARGET_MASK 0x1ffff + +// Timer retrig. When set to 1, the timer is still enabled after an event is generated when the timer counter is matching the timer target. If it is set to 0, the timer is disabled after the event is generated. (access: R/W) +#define RTC_TIMER_RETRIG_BIT 30 +#define RTC_TIMER_RETRIG_WIDTH 1 +#define RTC_TIMER_RETRIG_MASK 0x40000000 + +// Timer enable. When set to 1, the timer counter is incremented every 1/32768 seconds and an event is generated when the timer counter is matching the timer target. (access: R/W) +#define RTC_TIMER_ENABLE_BIT 31 +#define RTC_TIMER_ENABLE_WIDTH 1 +#define RTC_TIMER_ENABLE_MASK 0x80000000 + +// First digit of date day. (access: R/W) +#define RTC_DATE_DAY_0_BIT 0 +#define RTC_DATE_DAY_0_WIDTH 6 +#define RTC_DATE_DAY_0_MASK 0x3f + +// Second digit of date day. (access: R/W) +#define RTC_DATE_DAY_1_BIT 0 +#define RTC_DATE_DAY_1_WIDTH 6 +#define RTC_DATE_DAY_1_MASK 0x3f + +// First digit of date month. (access: R/W) +#define RTC_DATE_MONTH_0_BIT 8 +#define RTC_DATE_MONTH_0_WIDTH 5 +#define RTC_DATE_MONTH_0_MASK 0x1f00 + +// Second digit of date month. (access: R/W) +#define RTC_DATE_MONTH_1_BIT 8 +#define RTC_DATE_MONTH_1_WIDTH 5 +#define RTC_DATE_MONTH_1_MASK 0x1f00 + +// First digit of date year. (access: R/W) +#define RTC_DATE_YEAR_0_BIT 16 +#define RTC_DATE_YEAR_0_WIDTH 14 +#define RTC_DATE_YEAR_0_MASK 0x3fff0000 + +// Second digit of date year. (access: R/W) +#define RTC_DATE_YEAR_1_BIT 16 +#define RTC_DATE_YEAR_1_WIDTH 14 +#define RTC_DATE_YEAR_1_MASK 0x3fff0000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int seconds_0 :4 ; // First digit of clock seconds. + unsigned int seconds_1 :4 ; // Second digit of clock seconds. + unsigned int minutes_0 :4 ; // First digit of clock minutes. + unsigned int minutes_1 :4 ; // Second digit of clock minutes. + unsigned int hours_0 :4 ; // First digit of clock hours. + unsigned int hours_1 :2 ; // Second digit of clock hours. + unsigned int init_sec_count :10; // MSB part of second counter initial value. The second counter is incremented every 1/32768 seconds and is incrementing by 1 the number of seconds when it reaches 32768. When the clock is written, bits 0 to 4 are set to 0 and bits 5 to 14 are set to the value of this field. + }; + unsigned int raw; +} __attribute__((packed)) rtc_clock_t; + +typedef union { + struct { + unsigned int seconds_0 :8 ; // First digit of alarm seconds. + unsigned int seconds_1 :8 ; // Second digit of alarm seconds. + unsigned int minutes_0 :8 ; // First digit of alarm minutes. + unsigned int minutes_1 :8 ; // Second digit of alarm minutes. + unsigned int hours_0 :6 ; // First digit of alarm hours. + unsigned int hours_1 :6 ; // Second digit of alarm hours. + unsigned int padding0:9 ; + unsigned int enable :1 ; // Alarm enable. When set to 1, an event is generated when the alarm is matching the clock. + }; + unsigned int raw; +} __attribute__((packed)) rtc_alarm_t; + +typedef union { + struct { + unsigned int target :17; // Timer target. When the timer is enabled, an event is generated when the timer counter is matching this field. + unsigned int padding0:13; + unsigned int retrig :1 ; // Timer retrig. When set to 1, the timer is still enabled after an event is generated when the timer counter is matching the timer target. If it is set to 0, the timer is disabled after the event is generated. + unsigned int enable :1 ; // Timer enable. When set to 1, the timer counter is incremented every 1/32768 seconds and an event is generated when the timer counter is matching the timer target. + }; + unsigned int raw; +} __attribute__((packed)) rtc_timer_t; + +typedef union { + struct { + unsigned int day_0 :6 ; // First digit of date day. + unsigned int day_1 :6 ; // Second digit of date day. + unsigned int padding0:2 ; + unsigned int month_0 :5 ; // First digit of date month. + unsigned int month_1 :5 ; // Second digit of date month. + unsigned int padding1:3 ; + unsigned int year_0 :14; // First digit of date year. + unsigned int year_1 :14; // Second digit of date year. + }; + unsigned int raw; +} __attribute__((packed)) rtc_date_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_rtc_clock : public vp::reg_32 +{ +public: + inline void seconds_0_set(uint32_t value) { this->set_field(value, RTC_CLOCK_SECONDS_0_BIT, RTC_CLOCK_SECONDS_0_WIDTH); } + inline uint32_t seconds_0_get() { return this->get_field(RTC_CLOCK_SECONDS_0_BIT, RTC_CLOCK_SECONDS_0_WIDTH); } + inline void seconds_1_set(uint32_t value) { this->set_field(value, RTC_CLOCK_SECONDS_1_BIT, RTC_CLOCK_SECONDS_1_WIDTH); } + inline uint32_t seconds_1_get() { return this->get_field(RTC_CLOCK_SECONDS_1_BIT, RTC_CLOCK_SECONDS_1_WIDTH); } + inline void minutes_0_set(uint32_t value) { this->set_field(value, RTC_CLOCK_MINUTES_0_BIT, RTC_CLOCK_MINUTES_0_WIDTH); } + inline uint32_t minutes_0_get() { return this->get_field(RTC_CLOCK_MINUTES_0_BIT, RTC_CLOCK_MINUTES_0_WIDTH); } + inline void minutes_1_set(uint32_t value) { this->set_field(value, RTC_CLOCK_MINUTES_1_BIT, RTC_CLOCK_MINUTES_1_WIDTH); } + inline uint32_t minutes_1_get() { return this->get_field(RTC_CLOCK_MINUTES_1_BIT, RTC_CLOCK_MINUTES_1_WIDTH); } + inline void hours_0_set(uint32_t value) { this->set_field(value, RTC_CLOCK_HOURS_0_BIT, RTC_CLOCK_HOURS_0_WIDTH); } + inline uint32_t hours_0_get() { return this->get_field(RTC_CLOCK_HOURS_0_BIT, RTC_CLOCK_HOURS_0_WIDTH); } + inline void hours_1_set(uint32_t value) { this->set_field(value, RTC_CLOCK_HOURS_1_BIT, RTC_CLOCK_HOURS_1_WIDTH); } + inline uint32_t hours_1_get() { return this->get_field(RTC_CLOCK_HOURS_1_BIT, RTC_CLOCK_HOURS_1_WIDTH); } + inline void init_sec_count_set(uint32_t value) { this->set_field(value, RTC_CLOCK_INIT_SEC_COUNT_BIT, RTC_CLOCK_INIT_SEC_COUNT_WIDTH); } + inline uint32_t init_sec_count_get() { return this->get_field(RTC_CLOCK_INIT_SEC_COUNT_BIT, RTC_CLOCK_INIT_SEC_COUNT_WIDTH); } +}; + +class vp_rtc_alarm : public vp::reg_32 +{ +public: + inline void seconds_0_set(uint32_t value) { this->set_field(value, RTC_ALARM_SECONDS_0_BIT, RTC_ALARM_SECONDS_0_WIDTH); } + inline uint32_t seconds_0_get() { return this->get_field(RTC_ALARM_SECONDS_0_BIT, RTC_ALARM_SECONDS_0_WIDTH); } + inline void seconds_1_set(uint32_t value) { this->set_field(value, RTC_ALARM_SECONDS_1_BIT, RTC_ALARM_SECONDS_1_WIDTH); } + inline uint32_t seconds_1_get() { return this->get_field(RTC_ALARM_SECONDS_1_BIT, RTC_ALARM_SECONDS_1_WIDTH); } + inline void minutes_0_set(uint32_t value) { this->set_field(value, RTC_ALARM_MINUTES_0_BIT, RTC_ALARM_MINUTES_0_WIDTH); } + inline uint32_t minutes_0_get() { return this->get_field(RTC_ALARM_MINUTES_0_BIT, RTC_ALARM_MINUTES_0_WIDTH); } + inline void minutes_1_set(uint32_t value) { this->set_field(value, RTC_ALARM_MINUTES_1_BIT, RTC_ALARM_MINUTES_1_WIDTH); } + inline uint32_t minutes_1_get() { return this->get_field(RTC_ALARM_MINUTES_1_BIT, RTC_ALARM_MINUTES_1_WIDTH); } + inline void hours_0_set(uint32_t value) { this->set_field(value, RTC_ALARM_HOURS_0_BIT, RTC_ALARM_HOURS_0_WIDTH); } + inline uint32_t hours_0_get() { return this->get_field(RTC_ALARM_HOURS_0_BIT, RTC_ALARM_HOURS_0_WIDTH); } + inline void hours_1_set(uint32_t value) { this->set_field(value, RTC_ALARM_HOURS_1_BIT, RTC_ALARM_HOURS_1_WIDTH); } + inline uint32_t hours_1_get() { return this->get_field(RTC_ALARM_HOURS_1_BIT, RTC_ALARM_HOURS_1_WIDTH); } + inline void enable_set(uint32_t value) { this->set_field(value, RTC_ALARM_ENABLE_BIT, RTC_ALARM_ENABLE_WIDTH); } + inline uint32_t enable_get() { return this->get_field(RTC_ALARM_ENABLE_BIT, RTC_ALARM_ENABLE_WIDTH); } +}; + +class vp_rtc_timer : public vp::reg_32 +{ +public: + inline void target_set(uint32_t value) { this->set_field(value, RTC_TIMER_TARGET_BIT, RTC_TIMER_TARGET_WIDTH); } + inline uint32_t target_get() { return this->get_field(RTC_TIMER_TARGET_BIT, RTC_TIMER_TARGET_WIDTH); } + inline void retrig_set(uint32_t value) { this->set_field(value, RTC_TIMER_RETRIG_BIT, RTC_TIMER_RETRIG_WIDTH); } + inline uint32_t retrig_get() { return this->get_field(RTC_TIMER_RETRIG_BIT, RTC_TIMER_RETRIG_WIDTH); } + inline void enable_set(uint32_t value) { this->set_field(value, RTC_TIMER_ENABLE_BIT, RTC_TIMER_ENABLE_WIDTH); } + inline uint32_t enable_get() { return this->get_field(RTC_TIMER_ENABLE_BIT, RTC_TIMER_ENABLE_WIDTH); } +}; + +class vp_rtc_date : public vp::reg_32 +{ +public: + inline void day_0_set(uint32_t value) { this->set_field(value, RTC_DATE_DAY_0_BIT, RTC_DATE_DAY_0_WIDTH); } + inline uint32_t day_0_get() { return this->get_field(RTC_DATE_DAY_0_BIT, RTC_DATE_DAY_0_WIDTH); } + inline void day_1_set(uint32_t value) { this->set_field(value, RTC_DATE_DAY_1_BIT, RTC_DATE_DAY_1_WIDTH); } + inline uint32_t day_1_get() { return this->get_field(RTC_DATE_DAY_1_BIT, RTC_DATE_DAY_1_WIDTH); } + inline void month_0_set(uint32_t value) { this->set_field(value, RTC_DATE_MONTH_0_BIT, RTC_DATE_MONTH_0_WIDTH); } + inline uint32_t month_0_get() { return this->get_field(RTC_DATE_MONTH_0_BIT, RTC_DATE_MONTH_0_WIDTH); } + inline void month_1_set(uint32_t value) { this->set_field(value, RTC_DATE_MONTH_1_BIT, RTC_DATE_MONTH_1_WIDTH); } + inline uint32_t month_1_get() { return this->get_field(RTC_DATE_MONTH_1_BIT, RTC_DATE_MONTH_1_WIDTH); } + inline void year_0_set(uint32_t value) { this->set_field(value, RTC_DATE_YEAR_0_BIT, RTC_DATE_YEAR_0_WIDTH); } + inline uint32_t year_0_get() { return this->get_field(RTC_DATE_YEAR_0_BIT, RTC_DATE_YEAR_0_WIDTH); } + inline void year_1_set(uint32_t value) { this->set_field(value, RTC_DATE_YEAR_1_BIT, RTC_DATE_YEAR_1_WIDTH); } + inline uint32_t year_1_get() { return this->get_field(RTC_DATE_YEAR_1_BIT, RTC_DATE_YEAR_1_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int clock ; // Clock register + unsigned int alarm ; // Alarm register + unsigned int timer ; // Timer register + unsigned int date ; // Date register +} __attribute__((packed)) rtc_rtc_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t rtc_clock_get(uint32_t base) { return ARCHI_READ(base, RTC_CLOCK_OFFSET); } +static inline void rtc_clock_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, RTC_CLOCK_OFFSET, value); } + +static inline uint32_t rtc_alarm_get(uint32_t base) { return ARCHI_READ(base, RTC_ALARM_OFFSET); } +static inline void rtc_alarm_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, RTC_ALARM_OFFSET, value); } + +static inline uint32_t rtc_timer_get(uint32_t base) { return ARCHI_READ(base, RTC_TIMER_OFFSET); } +static inline void rtc_timer_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, RTC_TIMER_OFFSET, value); } + +static inline uint32_t rtc_date_get(uint32_t base) { return ARCHI_READ(base, RTC_DATE_OFFSET); } +static inline void rtc_date_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, RTC_DATE_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define RTC_CLOCK_SECONDS_0_GET(value) (ARCHI_BEXTRACTU((value),4,0)) +#define RTC_CLOCK_SECONDS_0_GETS(value) (ARCHI_BEXTRACT((value),4,0)) +#define RTC_CLOCK_SECONDS_0_SET(value,field) (ARCHI_BINSERT((value),(field),4,0)) +#define RTC_CLOCK_SECONDS_0(val) ((val) << 0) + +#define RTC_CLOCK_SECONDS_1_GET(value) (ARCHI_BEXTRACTU((value),4,4)) +#define RTC_CLOCK_SECONDS_1_GETS(value) (ARCHI_BEXTRACT((value),4,4)) +#define RTC_CLOCK_SECONDS_1_SET(value,field) (ARCHI_BINSERT((value),(field),4,4)) +#define RTC_CLOCK_SECONDS_1(val) ((val) << 4) + +#define RTC_CLOCK_MINUTES_0_GET(value) (ARCHI_BEXTRACTU((value),4,8)) +#define RTC_CLOCK_MINUTES_0_GETS(value) (ARCHI_BEXTRACT((value),4,8)) +#define RTC_CLOCK_MINUTES_0_SET(value,field) (ARCHI_BINSERT((value),(field),4,8)) +#define RTC_CLOCK_MINUTES_0(val) ((val) << 8) + +#define RTC_CLOCK_MINUTES_1_GET(value) (ARCHI_BEXTRACTU((value),4,12)) +#define RTC_CLOCK_MINUTES_1_GETS(value) (ARCHI_BEXTRACT((value),4,12)) +#define RTC_CLOCK_MINUTES_1_SET(value,field) (ARCHI_BINSERT((value),(field),4,12)) +#define RTC_CLOCK_MINUTES_1(val) ((val) << 12) + +#define RTC_CLOCK_HOURS_0_GET(value) (ARCHI_BEXTRACTU((value),4,16)) +#define RTC_CLOCK_HOURS_0_GETS(value) (ARCHI_BEXTRACT((value),4,16)) +#define RTC_CLOCK_HOURS_0_SET(value,field) (ARCHI_BINSERT((value),(field),4,16)) +#define RTC_CLOCK_HOURS_0(val) ((val) << 16) + +#define RTC_CLOCK_HOURS_1_GET(value) (ARCHI_BEXTRACTU((value),2,20)) +#define RTC_CLOCK_HOURS_1_GETS(value) (ARCHI_BEXTRACT((value),2,20)) +#define RTC_CLOCK_HOURS_1_SET(value,field) (ARCHI_BINSERT((value),(field),2,20)) +#define RTC_CLOCK_HOURS_1(val) ((val) << 20) + +#define RTC_CLOCK_INIT_SEC_COUNT_GET(value) (ARCHI_BEXTRACTU((value),10,22)) +#define RTC_CLOCK_INIT_SEC_COUNT_GETS(value) (ARCHI_BEXTRACT((value),10,22)) +#define RTC_CLOCK_INIT_SEC_COUNT_SET(value,field) (ARCHI_BINSERT((value),(field),10,22)) +#define RTC_CLOCK_INIT_SEC_COUNT(val) ((val) << 22) + +#define RTC_ALARM_SECONDS_0_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define RTC_ALARM_SECONDS_0_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define RTC_ALARM_SECONDS_0_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define RTC_ALARM_SECONDS_0(val) ((val) << 0) + +#define RTC_ALARM_SECONDS_1_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define RTC_ALARM_SECONDS_1_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define RTC_ALARM_SECONDS_1_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define RTC_ALARM_SECONDS_1(val) ((val) << 0) + +#define RTC_ALARM_MINUTES_0_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define RTC_ALARM_MINUTES_0_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define RTC_ALARM_MINUTES_0_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define RTC_ALARM_MINUTES_0(val) ((val) << 8) + +#define RTC_ALARM_MINUTES_1_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define RTC_ALARM_MINUTES_1_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define RTC_ALARM_MINUTES_1_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define RTC_ALARM_MINUTES_1(val) ((val) << 8) + +#define RTC_ALARM_HOURS_0_GET(value) (ARCHI_BEXTRACTU((value),6,16)) +#define RTC_ALARM_HOURS_0_GETS(value) (ARCHI_BEXTRACT((value),6,16)) +#define RTC_ALARM_HOURS_0_SET(value,field) (ARCHI_BINSERT((value),(field),6,16)) +#define RTC_ALARM_HOURS_0(val) ((val) << 16) + +#define RTC_ALARM_HOURS_1_GET(value) (ARCHI_BEXTRACTU((value),6,16)) +#define RTC_ALARM_HOURS_1_GETS(value) (ARCHI_BEXTRACT((value),6,16)) +#define RTC_ALARM_HOURS_1_SET(value,field) (ARCHI_BINSERT((value),(field),6,16)) +#define RTC_ALARM_HOURS_1(val) ((val) << 16) + +#define RTC_ALARM_ENABLE_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define RTC_ALARM_ENABLE_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define RTC_ALARM_ENABLE_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define RTC_ALARM_ENABLE(val) ((val) << 31) + +#define RTC_TIMER_TARGET_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define RTC_TIMER_TARGET_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define RTC_TIMER_TARGET_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define RTC_TIMER_TARGET(val) ((val) << 0) + +#define RTC_TIMER_RETRIG_GET(value) (ARCHI_BEXTRACTU((value),1,30)) +#define RTC_TIMER_RETRIG_GETS(value) (ARCHI_BEXTRACT((value),1,30)) +#define RTC_TIMER_RETRIG_SET(value,field) (ARCHI_BINSERT((value),(field),1,30)) +#define RTC_TIMER_RETRIG(val) ((val) << 30) + +#define RTC_TIMER_ENABLE_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define RTC_TIMER_ENABLE_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define RTC_TIMER_ENABLE_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define RTC_TIMER_ENABLE(val) ((val) << 31) + +#define RTC_DATE_DAY_0_GET(value) (ARCHI_BEXTRACTU((value),6,0)) +#define RTC_DATE_DAY_0_GETS(value) (ARCHI_BEXTRACT((value),6,0)) +#define RTC_DATE_DAY_0_SET(value,field) (ARCHI_BINSERT((value),(field),6,0)) +#define RTC_DATE_DAY_0(val) ((val) << 0) + +#define RTC_DATE_DAY_1_GET(value) (ARCHI_BEXTRACTU((value),6,0)) +#define RTC_DATE_DAY_1_GETS(value) (ARCHI_BEXTRACT((value),6,0)) +#define RTC_DATE_DAY_1_SET(value,field) (ARCHI_BINSERT((value),(field),6,0)) +#define RTC_DATE_DAY_1(val) ((val) << 0) + +#define RTC_DATE_MONTH_0_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define RTC_DATE_MONTH_0_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define RTC_DATE_MONTH_0_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define RTC_DATE_MONTH_0(val) ((val) << 8) + +#define RTC_DATE_MONTH_1_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define RTC_DATE_MONTH_1_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define RTC_DATE_MONTH_1_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define RTC_DATE_MONTH_1(val) ((val) << 8) + +#define RTC_DATE_YEAR_0_GET(value) (ARCHI_BEXTRACTU((value),14,16)) +#define RTC_DATE_YEAR_0_GETS(value) (ARCHI_BEXTRACT((value),14,16)) +#define RTC_DATE_YEAR_0_SET(value,field) (ARCHI_BINSERT((value),(field),14,16)) +#define RTC_DATE_YEAR_0(val) ((val) << 16) + +#define RTC_DATE_YEAR_1_GET(value) (ARCHI_BEXTRACTU((value),14,16)) +#define RTC_DATE_YEAR_1_GETS(value) (ARCHI_BEXTRACT((value),14,16)) +#define RTC_DATE_YEAR_1_SET(value,field) (ARCHI_BINSERT((value),(field),14,16)) +#define RTC_DATE_YEAR_1(val) ((val) << 16) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v1.h b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v1.h new file mode 100644 index 0000000..7edbdcc --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v1.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_SOC_EU_SOC_EU_V1_H__ +#define __ARCHI_SOC_EU_SOC_EU_V1_H__ + +#define SOC_EU_EVENT 0x00 +#define SOC_FC_FIRST_MASK 0x04 +#define SOC_FC_MASK_MSB 0x04 +#define SOC_FC_MASK_LSB 0x08 +#define SOC_CL_FIRST_MASK 0x0c +#define SOC_CL_MASK_MSB 0x0c +#define SOC_CL_MASK_LSB 0x10 +#define SOC_PR_FIRST_MASK 0x14 +#define SOC_PR_MASK_MSB 0x14 +#define SOC_PR_MASK_LSB 0x18 +#define SOC_ERR_MASK_MSB 0x1c +#define SOC_ERR_MASK_LSB 0x20 +#define SOC_TIMER_SEL_HI 0x24 +#define SOC_TIMER_SEL_LO 0x28 + +#define SOC_NB_EVENT_REGS 2 + +#define SOC_FC_MASK(x) (SOC_FC_FIRST_MASK + (x)*4) +#define SOC_CL_MASK(x) (SOC_CL_FIRST_MASK + (x)*4) +#define SOC_PR_MASK(x) (SOC_PR_FIRST_MASK + (x)*4) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v2.h b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v2.h new file mode 100644 index 0000000..768497a --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v2.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_SOC_EU_SOC_EU_V2_H__ +#define __ARCHI_SOC_EU_SOC_EU_V2_H__ + +#define SOC_EU_EVENT 0x00 +#define SOC_FC_FIRST_MASK 0x04 +#define SOC_CL_FIRST_MASK 0x24 +#define SOC_PR_FIRST_MASK 0x44 +#define SOC_ERR_FIRST_MASK 0x64 +#define SOC_TIMER_SEL_HI 0x84 +#define SOC_TIMER_SEL_LO 0x88 + +#define SOC_EU_EVENT_0 0x1 +#define SOC_EU_EVENT_1 0x2 +#define SOC_EU_EVENT_2 0x4 +#define SOC_EU_EVENT_3 0x8 +#define SOC_EU_EVENT_4 0x10 +#define SOC_EU_EVENT_5 0x20 +#define SOC_EU_EVENT_6 0x40 +#define SOC_EU_EVENT_7 0x80 + +#define SOC_TIMER_SEL_ENABLE_SHIFT 31 +#define SOC_TIMER_SEL_EVT_SHIFT 0 +#define SOC_TIMER_SEL_EVT_WIDTH 8 +#define SOC_TIMER_SEL_EVT_MASK ((~0U) >> (32 - SOC_TIMER_SEL_EVT_WIDTH)) +// #define SOC_TIMER_SEL_EVT_MASK 0xff + +#define SOC_TIMER_SEL_ENABLE_DISABLED 0 +#define SOC_TIMER_SEL_ENABLE_ENABLED 1 + +#define SOC_TIMER_SEL_ENABLE_DIS (0 << SOC_TIMER_SEL_ENABLE_SHIFT) +#define SOC_TIMER_SEL_ENABLE_ENA (1 << SOC_TIMER_SEL_ENABLE_SHIFT) +#define SOC_TIMER_SEL_EVT_VAL(val) ((val) << SOC_TIMER_SEL_EVT_SHIFT) + +// related to XX_FIRST_MASK registers +#define SOC_NB_EVENT_REGS 8 +#define SOC_NB_EVENT_TARGETS 3 + +#define SOC_FC_MASK(x) (SOC_FC_FIRST_MASK + (x)*4) +#define SOC_CL_MASK(x) (SOC_CL_FIRST_MASK + (x)*4) +#define SOC_PR_MASK(x) (SOC_PR_FIRST_MASK + (x)*4) + +#define ARCHI_SOC_EVENT_PERIPH_EVT_BASE(periph) ((periph)*ARCHI_SOC_EVENT_UDMA_NB_CHANNEL_EVT) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v3.h b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v3.h new file mode 100644 index 0000000..5bbc569 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/soc_eu/soc_eu_v3.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + + +#ifndef __ARCHI_SOC_EU_SOC_EU_V3_H__ +#define __ARCHI_SOC_EU_SOC_EU_V3_H__ + + +#define SOC_EU_EVENT 0x00 +#define SOC_FC_FIRST_MASK 0x10 +#define SOC_CL_FIRST_MASK 0x20 +#define SOC_PR_FIRST_MASK 0x30 +#define SOC_ERR_FIRST_MASK 0x40 +#define SOC_TIMER_SEL_HI 0x08 +#define SOC_TIMER_SEL_LO 0x0C + +// compatibility definitions +#define SOC_FC_MASK_LSB SOC_FC_FIRST_MASK +#define SOC_FC_MASK_MSB (SOC_FC_FIRST_MASK + 0x4) +#define SOC_CL_MASK_LSB SOC_CL_FIRST_MASK +#define SOC_CL_MASK_MSB (SOC_CL_FIRST_MASK + 0x4) +#define SOC_PR_MASK_LSB SOC_PR_FIRST_MASK +#define SOC_PR_MASK_MSB (SOC_PR_FIRST_MASK + 0x4) + +#define SOC_EU_EVENT_0 0x1 +#define SOC_EU_EVENT_1 0x2 +#define SOC_EU_EVENT_2 0x4 +#define SOC_EU_EVENT_3 0x8 +#define SOC_EU_EVENT_4 0x10 +#define SOC_EU_EVENT_5 0x20 +#define SOC_EU_EVENT_6 0x40 +#define SOC_EU_EVENT_7 0x80 + +#define SOC_TIMER_SEL_ENABLE_SHIFT 31 +#define SOC_TIMER_SEL_EVT_SHIFT 0 +#define SOC_TIMER_SEL_EVT_WIDTH 8 +#define SOC_TIMER_SEL_EVT_MASK ((~0U) >> (32 - SOC_TIMER_SEL_EVT_WIDTH)) +// #define SOC_TIMER_SEL_EVT_MASK 0xff + +#define SOC_TIMER_SEL_ENABLE_DISABLED 0 +#define SOC_TIMER_SEL_ENABLE_ENABLED 1 + +#define SOC_TIMER_SEL_ENABLE_DIS (0 << SOC_TIMER_SEL_ENABLE_SHIFT) +#define SOC_TIMER_SEL_ENABLE_ENA (1 << SOC_TIMER_SEL_ENABLE_SHIFT) +#define SOC_TIMER_SEL_EVT_VAL(val) ((val) << SOC_TIMER_SEL_EVT_SHIFT) + +// related to XX_FIRST_MASK registers +#define SOC_NB_EVENT_REGS 4 +#define SOC_NB_EVENT_TARGETS 3 + +#define SOC_FC_MASK(x) (SOC_FC_FIRST_MASK + (x)*4) +#define SOC_CL_MASK(x) (SOC_CL_FIRST_MASK + (x)*4) +#define SOC_PR_MASK(x) (SOC_PR_FIRST_MASK + (x)*4) + +#define ARCHI_SOC_EVENT_PERIPH_EVT_BASE(periph) ((periph)*ARCHI_SOC_EVENT_UDMA_NB_CHANNEL_EVT) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/spim/spi_v1.h b/sw/pulp-sdk/archi/include/archi/spim/spi_v1.h new file mode 100644 index 0000000..c172881 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/spim/spi_v1.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_SPIM_SPI_V1_H__ +#define __ARCHI_SPIM_SPI_V1_H__ + +#define PULP_SPI_OFFSET 0xA102000 + +#define PULP_SPI_FIFO_SIZE 8 + +#define PULP_SPI_QPI 1 +#define PULP_SPI_NO_QPI 0 + +#define PULP_SPI_CMD_RD 0 +#define PULP_SPI_CMD_WR 1 +#define PULP_SPI_CMD_QRD 2 +#define PULP_SPI_CMD_QWR 3 +#define PULP_SPI_CMD_SWRST 4 + +#define PULP_SPI_CSN0 0 +#define PULP_SPI_CSN1 1 +#define PULP_SPI_CSN2 2 +#define PULP_SPI_CSN3 3 + +#define PULP_SPI_REG_STATUS ( 0x00 ) +#define PULP_SPI_REG_CLKDIV ( 0x04 ) +#define PULP_SPI_REG_SPICMD ( 0x08 ) +#define PULP_SPI_REG_SPIADR ( 0x0C ) +#define PULP_SPI_REG_SPILEN ( 0x10 ) +#define PULP_SPI_REG_SPIDUM ( 0x14 ) +#define PULP_SPI_REG_TXFIFO ( 0x18 ) +#define PULP_SPI_REG_RXFIFO ( 0x20 ) +#define PULP_SPI_REG_INTCFG ( 0x24 ) +#define PULP_SPI_REG_INTSTA ( 0x28 ) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/stdout/stdout_v2.h b/sw/pulp-sdk/archi/include/archi/stdout/stdout_v2.h new file mode 100644 index 0000000..f7c8aff --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/stdout/stdout_v2.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef ARCHI_STDOUT_STDOUT_V2_H +#define ARCHI_STDOUT_STDOUT_V2_H + +#define STDOUT_PUTC_OFFSET 0x0 +#define STDOUT_OPEN_OFFSET 0x2000 +#define STDOUT_OPEN_END_OFFSET 0x3000 +#define STDOUT_READ_OFFSET 0x4000 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/stdout/stdout_v3.h b/sw/pulp-sdk/archi/include/archi/stdout/stdout_v3.h new file mode 100644 index 0000000..f7c8aff --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/stdout/stdout_v3.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef ARCHI_STDOUT_STDOUT_V2_H +#define ARCHI_STDOUT_STDOUT_V2_H + +#define STDOUT_PUTC_OFFSET 0x0 +#define STDOUT_OPEN_OFFSET 0x2000 +#define STDOUT_OPEN_END_OFFSET 0x3000 +#define STDOUT_READ_OFFSET 0x4000 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/timer/timer_v2.h b/sw/pulp-sdk/archi/include/archi/timer/timer_v2.h new file mode 100644 index 0000000..d695564 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/timer/timer_v2.h @@ -0,0 +1,617 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_TIMER_TIMER_V2_H__ +#define __INCLUDE_ARCHI_TIMER_TIMER_V2_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// Timer Low Configuration register. +#define TIMER_CFG_LO_OFFSET 0x0 + +// Timer High Configuration register. +#define TIMER_CFG_HI_OFFSET 0x4 + +// Timer Low counter value register. +#define TIMER_CNT_LO_OFFSET 0x8 + +// Timer High counter value register. +#define TIMER_CNT_HI_OFFSET 0xc + +// Timer Low comparator value register. +#define TIMER_CMP_LO_OFFSET 0x10 + +// Timer High comparator value register. +#define TIMER_CMP_HI_OFFSET 0x14 + +// Start Timer Low counting register. +#define TIMER_START_LO_OFFSET 0x18 + +// Start Timer High counting register. +#define TIMER_START_HI_OFFSET 0x1c + +// Reset Timer Low counter register. +#define TIMER_RESET_LO_OFFSET 0x20 + +// Reset Timer High counter register. +#define TIMER_RESET_HI_OFFSET 0x24 + + + +// +// REGISTERS FIELDS +// + +// Timer low enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_LO_ENABLE_BIT 0 +#define TIMER_CFG_LO_ENABLE_WIDTH 1 +#define TIMER_CFG_LO_ENABLE_MASK 0x1 + +// Timer low counter reset command bitfield. Cleared after Timer Low reset execution. (access: R/W) +#define TIMER_CFG_LO_RESET_BIT 1 +#define TIMER_CFG_LO_RESET_WIDTH 1 +#define TIMER_CFG_LO_RESET_MASK 0x2 + +// Timer low compare match interrupt enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_LO_IRQEN_BIT 2 +#define TIMER_CFG_LO_IRQEN_WIDTH 1 +#define TIMER_CFG_LO_IRQEN_MASK 0x4 + +// Timer low input event mask configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_LO_IEM_BIT 3 +#define TIMER_CFG_LO_IEM_WIDTH 1 +#define TIMER_CFG_LO_IEM_MASK 0x8 + +// Timer low continuous mode configuration bitfield: - 1'b0: Continue mode - continue incrementing Timer low counter when compare match with CMP_LO occurs. - 1'b1: Cycle mode - reset Timer low counter when compare match with CMP_LO occurs. (access: R/W) +#define TIMER_CFG_LO_MODE_BIT 4 +#define TIMER_CFG_LO_MODE_WIDTH 1 +#define TIMER_CFG_LO_MODE_MASK 0x10 + +// Timer low one shot configuration bitfield: - 1'b0: let Timer low enabled counting when compare match with CMP_LO occurs. - 1'b1: disable Timer low when compare match with CMP_LO occurs. (access: R/W) +#define TIMER_CFG_LO_ONE_S_BIT 5 +#define TIMER_CFG_LO_ONE_S_WIDTH 1 +#define TIMER_CFG_LO_ONE_S_MASK 0x20 + +// Timer low prescaler enable configuration bitfield:- 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_LO_PEN_BIT 6 +#define TIMER_CFG_LO_PEN_WIDTH 1 +#define TIMER_CFG_LO_PEN_MASK 0x40 + +// Timer low clock source configuration bitfield: - 1'b0: FLL or FLL+Prescaler - 1'b1: Reference clock at 32kHz (access: R/W) +#define TIMER_CFG_LO_CCFG_BIT 7 +#define TIMER_CFG_LO_CCFG_WIDTH 1 +#define TIMER_CFG_LO_CCFG_MASK 0x80 + +// Timer low prescaler value bitfield. Ftimer = Fclk / (1 + PRESC_VAL) (access: R/W) +#define TIMER_CFG_LO_PVAL_BIT 8 +#define TIMER_CFG_LO_PVAL_WIDTH 8 +#define TIMER_CFG_LO_PVAL_MASK 0xff00 + +// Timer low + Timer high 64bit cascaded mode configuration bitfield. (access: R/W) +#define TIMER_CFG_LO_CASC_BIT 31 +#define TIMER_CFG_LO_CASC_WIDTH 1 +#define TIMER_CFG_LO_CASC_MASK 0x80000000 + +// Timer high enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_HI_ENABLE_BIT 0 +#define TIMER_CFG_HI_ENABLE_WIDTH 1 +#define TIMER_CFG_HI_ENABLE_MASK 0x1 + +// Timer high counter reset command bitfield. Cleared after Timer high reset execution. (access: W) +#define TIMER_CFG_HI_RESET_BIT 1 +#define TIMER_CFG_HI_RESET_WIDTH 1 +#define TIMER_CFG_HI_RESET_MASK 0x2 + +// Timer high compare match interrupt enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_HI_IRQEN_BIT 2 +#define TIMER_CFG_HI_IRQEN_WIDTH 1 +#define TIMER_CFG_HI_IRQEN_MASK 0x4 + +// Timer high input event mask configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_HI_IEM_BIT 3 +#define TIMER_CFG_HI_IEM_WIDTH 1 +#define TIMER_CFG_HI_IEM_MASK 0x8 + +// Timer high continuous mode configuration bitfield: - 1'b0: Continue mode - continue incrementing Timer high counter when compare match with CMP_LO occurs. - 1'b1: Cycle mode - reset Timer high counter when compare match with CMP_LO occurs. (access: R/W) +#define TIMER_CFG_HI_MODE_BIT 4 +#define TIMER_CFG_HI_MODE_WIDTH 1 +#define TIMER_CFG_HI_MODE_MASK 0x10 + +// Timer high one shot configuration bitfield: - 1'b0: let Timer high enabled counting when compare match with CMP_LO occurs. - 1'b1: disable Timer high when compare match with CMP_LO occurs. (access: R/W) +#define TIMER_CFG_HI_ONE_S_BIT 5 +#define TIMER_CFG_HI_ONE_S_WIDTH 1 +#define TIMER_CFG_HI_ONE_S_MASK 0x20 + +// Timer high prescaler enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define TIMER_CFG_HI_PEN_BIT 6 +#define TIMER_CFG_HI_PEN_WIDTH 1 +#define TIMER_CFG_HI_PEN_MASK 0x40 + +// Timer high clock source configuration bitfield: - 1'b0: FLL or FLL+Prescaler - 1'b1: Reference clock at 32kHz (access: R/W) +#define TIMER_CFG_HI_CLKCFG_BIT 7 +#define TIMER_CFG_HI_CLKCFG_WIDTH 1 +#define TIMER_CFG_HI_CLKCFG_MASK 0x80 + +// Timer Low counter value bitfield. (access: R/W) +#define TIMER_CNT_LO_CNT_LO_BIT 0 +#define TIMER_CNT_LO_CNT_LO_WIDTH 32 +#define TIMER_CNT_LO_CNT_LO_MASK 0xffffffff + +// Timer High counter value bitfield. (access: R/W) +#define TIMER_CNT_HI_CNT_HI_BIT 0 +#define TIMER_CNT_HI_CNT_HI_WIDTH 32 +#define TIMER_CNT_HI_CNT_HI_MASK 0xffffffff + +// Timer Low comparator value bitfield. (access: R/W) +#define TIMER_CMP_LO_CMP_LO_BIT 0 +#define TIMER_CMP_LO_CMP_LO_WIDTH 32 +#define TIMER_CMP_LO_CMP_LO_MASK 0xffffffff + +// Timer High comparator value bitfield. (access: R/W) +#define TIMER_CMP_HI_CMP_HI_BIT 0 +#define TIMER_CMP_HI_CMP_HI_WIDTH 32 +#define TIMER_CMP_HI_CMP_HI_MASK 0xffffffff + +// Timer Low start command bitfield. When executed, CFG_LO.ENABLE is set. (access: W) +#define TIMER_START_LO_STRT_LO_BIT 0 +#define TIMER_START_LO_STRT_LO_WIDTH 1 +#define TIMER_START_LO_STRT_LO_MASK 0x1 + +// Timer High start command bitfield. When executed, CFG_HI.ENABLE is set. (access: W) +#define TIMER_START_HI_STRT_HI_BIT 0 +#define TIMER_START_HI_STRT_HI_WIDTH 1 +#define TIMER_START_HI_STRT_HI_MASK 0x1 + +// Timer Low counter reset command bitfield. When executed, CFG_LO.RESET is set. (access: W) +#define TIMER_RESET_LO_RST_LO_BIT 0 +#define TIMER_RESET_LO_RST_LO_WIDTH 1 +#define TIMER_RESET_LO_RST_LO_MASK 0x1 + +// Timer High counter reset command bitfield. When executed, CFG_HI.RESET is set. (access: W) +#define TIMER_RESET_HI_RST_HI_BIT 0 +#define TIMER_RESET_HI_RST_HI_WIDTH 1 +#define TIMER_RESET_HI_RST_HI_MASK 0x1 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int enable :1 ; // Timer low enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int reset :1 ; // Timer low counter reset command bitfield. Cleared after Timer Low reset execution. + unsigned int irqen :1 ; // Timer low compare match interrupt enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int iem :1 ; // Timer low input event mask configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int mode :1 ; // Timer low continuous mode configuration bitfield: - 1'b0: Continue mode - continue incrementing Timer low counter when compare match with CMP_LO occurs. - 1'b1: Cycle mode - reset Timer low counter when compare match with CMP_LO occurs. + unsigned int one_s :1 ; // Timer low one shot configuration bitfield: - 1'b0: let Timer low enabled counting when compare match with CMP_LO occurs. - 1'b1: disable Timer low when compare match with CMP_LO occurs. + unsigned int pen :1 ; // Timer low prescaler enable configuration bitfield:- 1'b0: disabled - 1'b1: enabled + unsigned int ccfg :1 ; // Timer low clock source configuration bitfield: - 1'b0: FLL or FLL+Prescaler - 1'b1: Reference clock at 32kHz + unsigned int pval :8 ; // Timer low prescaler value bitfield. Ftimer = Fclk / (1 + PRESC_VAL) + unsigned int padding0:15; + unsigned int casc :1 ; // Timer low + Timer high 64bit cascaded mode configuration bitfield. + }; + unsigned int raw; +} __attribute__((packed)) timer_cfg_lo_t; + +typedef union { + struct { + unsigned int enable :1 ; // Timer high enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int reset :1 ; // Timer high counter reset command bitfield. Cleared after Timer high reset execution. + unsigned int irqen :1 ; // Timer high compare match interrupt enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int iem :1 ; // Timer high input event mask configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int mode :1 ; // Timer high continuous mode configuration bitfield: - 1'b0: Continue mode - continue incrementing Timer high counter when compare match with CMP_LO occurs. - 1'b1: Cycle mode - reset Timer high counter when compare match with CMP_LO occurs. + unsigned int one_s :1 ; // Timer high one shot configuration bitfield: - 1'b0: let Timer high enabled counting when compare match with CMP_LO occurs. - 1'b1: disable Timer high when compare match with CMP_LO occurs. + unsigned int pen :1 ; // Timer high prescaler enable configuration bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int clkcfg :1 ; // Timer high clock source configuration bitfield: - 1'b0: FLL or FLL+Prescaler - 1'b1: Reference clock at 32kHz + }; + unsigned int raw; +} __attribute__((packed)) timer_cfg_hi_t; + +typedef union { + struct { + unsigned int cnt_lo :32; // Timer Low counter value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) timer_cnt_lo_t; + +typedef union { + struct { + unsigned int cnt_hi :32; // Timer High counter value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) timer_cnt_hi_t; + +typedef union { + struct { + unsigned int cmp_lo :32; // Timer Low comparator value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) timer_cmp_lo_t; + +typedef union { + struct { + unsigned int cmp_hi :32; // Timer High comparator value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) timer_cmp_hi_t; + +typedef union { + struct { + unsigned int strt_lo :1 ; // Timer Low start command bitfield. When executed, CFG_LO.ENABLE is set. + }; + unsigned int raw; +} __attribute__((packed)) timer_start_lo_t; + +typedef union { + struct { + unsigned int strt_hi :1 ; // Timer High start command bitfield. When executed, CFG_HI.ENABLE is set. + }; + unsigned int raw; +} __attribute__((packed)) timer_start_hi_t; + +typedef union { + struct { + unsigned int rst_lo :1 ; // Timer Low counter reset command bitfield. When executed, CFG_LO.RESET is set. + }; + unsigned int raw; +} __attribute__((packed)) timer_reset_lo_t; + +typedef union { + struct { + unsigned int rst_hi :1 ; // Timer High counter reset command bitfield. When executed, CFG_HI.RESET is set. + }; + unsigned int raw; +} __attribute__((packed)) timer_reset_hi_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_timer_cfg_lo : public vp::reg_32 +{ +public: + inline void enable_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_ENABLE_BIT, TIMER_CFG_LO_ENABLE_WIDTH); } + inline uint32_t enable_get() { return this->get_field(TIMER_CFG_LO_ENABLE_BIT, TIMER_CFG_LO_ENABLE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_RESET_BIT, TIMER_CFG_LO_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(TIMER_CFG_LO_RESET_BIT, TIMER_CFG_LO_RESET_WIDTH); } + inline void irqen_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_IRQEN_BIT, TIMER_CFG_LO_IRQEN_WIDTH); } + inline uint32_t irqen_get() { return this->get_field(TIMER_CFG_LO_IRQEN_BIT, TIMER_CFG_LO_IRQEN_WIDTH); } + inline void iem_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_IEM_BIT, TIMER_CFG_LO_IEM_WIDTH); } + inline uint32_t iem_get() { return this->get_field(TIMER_CFG_LO_IEM_BIT, TIMER_CFG_LO_IEM_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_MODE_BIT, TIMER_CFG_LO_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(TIMER_CFG_LO_MODE_BIT, TIMER_CFG_LO_MODE_WIDTH); } + inline void one_s_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_ONE_S_BIT, TIMER_CFG_LO_ONE_S_WIDTH); } + inline uint32_t one_s_get() { return this->get_field(TIMER_CFG_LO_ONE_S_BIT, TIMER_CFG_LO_ONE_S_WIDTH); } + inline void pen_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_PEN_BIT, TIMER_CFG_LO_PEN_WIDTH); } + inline uint32_t pen_get() { return this->get_field(TIMER_CFG_LO_PEN_BIT, TIMER_CFG_LO_PEN_WIDTH); } + inline void ccfg_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_CCFG_BIT, TIMER_CFG_LO_CCFG_WIDTH); } + inline uint32_t ccfg_get() { return this->get_field(TIMER_CFG_LO_CCFG_BIT, TIMER_CFG_LO_CCFG_WIDTH); } + inline void pval_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_PVAL_BIT, TIMER_CFG_LO_PVAL_WIDTH); } + inline uint32_t pval_get() { return this->get_field(TIMER_CFG_LO_PVAL_BIT, TIMER_CFG_LO_PVAL_WIDTH); } + inline void casc_set(uint32_t value) { this->set_field(value, TIMER_CFG_LO_CASC_BIT, TIMER_CFG_LO_CASC_WIDTH); } + inline uint32_t casc_get() { return this->get_field(TIMER_CFG_LO_CASC_BIT, TIMER_CFG_LO_CASC_WIDTH); } +}; + +class vp_timer_cfg_hi : public vp::reg_32 +{ +public: + inline void enable_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_ENABLE_BIT, TIMER_CFG_HI_ENABLE_WIDTH); } + inline uint32_t enable_get() { return this->get_field(TIMER_CFG_HI_ENABLE_BIT, TIMER_CFG_HI_ENABLE_WIDTH); } + inline void reset_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_RESET_BIT, TIMER_CFG_HI_RESET_WIDTH); } + inline uint32_t reset_get() { return this->get_field(TIMER_CFG_HI_RESET_BIT, TIMER_CFG_HI_RESET_WIDTH); } + inline void irqen_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_IRQEN_BIT, TIMER_CFG_HI_IRQEN_WIDTH); } + inline uint32_t irqen_get() { return this->get_field(TIMER_CFG_HI_IRQEN_BIT, TIMER_CFG_HI_IRQEN_WIDTH); } + inline void iem_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_IEM_BIT, TIMER_CFG_HI_IEM_WIDTH); } + inline uint32_t iem_get() { return this->get_field(TIMER_CFG_HI_IEM_BIT, TIMER_CFG_HI_IEM_WIDTH); } + inline void mode_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_MODE_BIT, TIMER_CFG_HI_MODE_WIDTH); } + inline uint32_t mode_get() { return this->get_field(TIMER_CFG_HI_MODE_BIT, TIMER_CFG_HI_MODE_WIDTH); } + inline void one_s_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_ONE_S_BIT, TIMER_CFG_HI_ONE_S_WIDTH); } + inline uint32_t one_s_get() { return this->get_field(TIMER_CFG_HI_ONE_S_BIT, TIMER_CFG_HI_ONE_S_WIDTH); } + inline void pen_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_PEN_BIT, TIMER_CFG_HI_PEN_WIDTH); } + inline uint32_t pen_get() { return this->get_field(TIMER_CFG_HI_PEN_BIT, TIMER_CFG_HI_PEN_WIDTH); } + inline void clkcfg_set(uint32_t value) { this->set_field(value, TIMER_CFG_HI_CLKCFG_BIT, TIMER_CFG_HI_CLKCFG_WIDTH); } + inline uint32_t clkcfg_get() { return this->get_field(TIMER_CFG_HI_CLKCFG_BIT, TIMER_CFG_HI_CLKCFG_WIDTH); } +}; + +class vp_timer_cnt_lo : public vp::reg_32 +{ +public: + inline void cnt_lo_set(uint32_t value) { this->set_field(value, TIMER_CNT_LO_CNT_LO_BIT, TIMER_CNT_LO_CNT_LO_WIDTH); } + inline uint32_t cnt_lo_get() { return this->get_field(TIMER_CNT_LO_CNT_LO_BIT, TIMER_CNT_LO_CNT_LO_WIDTH); } +}; + +class vp_timer_cnt_hi : public vp::reg_32 +{ +public: + inline void cnt_hi_set(uint32_t value) { this->set_field(value, TIMER_CNT_HI_CNT_HI_BIT, TIMER_CNT_HI_CNT_HI_WIDTH); } + inline uint32_t cnt_hi_get() { return this->get_field(TIMER_CNT_HI_CNT_HI_BIT, TIMER_CNT_HI_CNT_HI_WIDTH); } +}; + +class vp_timer_cmp_lo : public vp::reg_32 +{ +public: + inline void cmp_lo_set(uint32_t value) { this->set_field(value, TIMER_CMP_LO_CMP_LO_BIT, TIMER_CMP_LO_CMP_LO_WIDTH); } + inline uint32_t cmp_lo_get() { return this->get_field(TIMER_CMP_LO_CMP_LO_BIT, TIMER_CMP_LO_CMP_LO_WIDTH); } +}; + +class vp_timer_cmp_hi : public vp::reg_32 +{ +public: + inline void cmp_hi_set(uint32_t value) { this->set_field(value, TIMER_CMP_HI_CMP_HI_BIT, TIMER_CMP_HI_CMP_HI_WIDTH); } + inline uint32_t cmp_hi_get() { return this->get_field(TIMER_CMP_HI_CMP_HI_BIT, TIMER_CMP_HI_CMP_HI_WIDTH); } +}; + +class vp_timer_start_lo : public vp::reg_32 +{ +public: + inline void strt_lo_set(uint32_t value) { this->set_field(value, TIMER_START_LO_STRT_LO_BIT, TIMER_START_LO_STRT_LO_WIDTH); } + inline uint32_t strt_lo_get() { return this->get_field(TIMER_START_LO_STRT_LO_BIT, TIMER_START_LO_STRT_LO_WIDTH); } +}; + +class vp_timer_start_hi : public vp::reg_32 +{ +public: + inline void strt_hi_set(uint32_t value) { this->set_field(value, TIMER_START_HI_STRT_HI_BIT, TIMER_START_HI_STRT_HI_WIDTH); } + inline uint32_t strt_hi_get() { return this->get_field(TIMER_START_HI_STRT_HI_BIT, TIMER_START_HI_STRT_HI_WIDTH); } +}; + +class vp_timer_reset_lo : public vp::reg_32 +{ +public: + inline void rst_lo_set(uint32_t value) { this->set_field(value, TIMER_RESET_LO_RST_LO_BIT, TIMER_RESET_LO_RST_LO_WIDTH); } + inline uint32_t rst_lo_get() { return this->get_field(TIMER_RESET_LO_RST_LO_BIT, TIMER_RESET_LO_RST_LO_WIDTH); } +}; + +class vp_timer_reset_hi : public vp::reg_32 +{ +public: + inline void rst_hi_set(uint32_t value) { this->set_field(value, TIMER_RESET_HI_RST_HI_BIT, TIMER_RESET_HI_RST_HI_WIDTH); } + inline uint32_t rst_hi_get() { return this->get_field(TIMER_RESET_HI_RST_HI_BIT, TIMER_RESET_HI_RST_HI_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int cfg_lo ; // Timer Low Configuration register. + unsigned int cfg_hi ; // Timer High Configuration register. + unsigned int cnt_lo ; // Timer Low counter value register. + unsigned int cnt_hi ; // Timer High counter value register. + unsigned int cmp_lo ; // Timer Low comparator value register. + unsigned int cmp_hi ; // Timer High comparator value register. + unsigned int start_lo ; // Start Timer Low counting register. + unsigned int start_hi ; // Start Timer High counting register. + unsigned int reset_lo ; // Reset Timer Low counter register. + unsigned int reset_hi ; // Reset Timer High counter register. +} __attribute__((packed)) timer_timer_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t timer_cfg_lo_get(uint32_t base) { return ARCHI_READ(base, TIMER_CFG_LO_OFFSET); } +static inline void timer_cfg_lo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CFG_LO_OFFSET, value); } + +static inline uint32_t timer_cfg_hi_get(uint32_t base) { return ARCHI_READ(base, TIMER_CFG_HI_OFFSET); } +static inline void timer_cfg_hi_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CFG_HI_OFFSET, value); } + +static inline uint32_t timer_cnt_lo_get(uint32_t base) { return ARCHI_READ(base, TIMER_CNT_LO_OFFSET); } +static inline void timer_cnt_lo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CNT_LO_OFFSET, value); } + +static inline uint32_t timer_cnt_hi_get(uint32_t base) { return ARCHI_READ(base, TIMER_CNT_HI_OFFSET); } +static inline void timer_cnt_hi_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CNT_HI_OFFSET, value); } + +static inline uint32_t timer_cmp_lo_get(uint32_t base) { return ARCHI_READ(base, TIMER_CMP_LO_OFFSET); } +static inline void timer_cmp_lo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CMP_LO_OFFSET, value); } + +static inline uint32_t timer_cmp_hi_get(uint32_t base) { return ARCHI_READ(base, TIMER_CMP_HI_OFFSET); } +static inline void timer_cmp_hi_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_CMP_HI_OFFSET, value); } + +static inline uint32_t timer_start_lo_get(uint32_t base) { return ARCHI_READ(base, TIMER_START_LO_OFFSET); } +static inline void timer_start_lo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_START_LO_OFFSET, value); } + +static inline uint32_t timer_start_hi_get(uint32_t base) { return ARCHI_READ(base, TIMER_START_HI_OFFSET); } +static inline void timer_start_hi_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_START_HI_OFFSET, value); } + +static inline uint32_t timer_reset_lo_get(uint32_t base) { return ARCHI_READ(base, TIMER_RESET_LO_OFFSET); } +static inline void timer_reset_lo_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_RESET_LO_OFFSET, value); } + +static inline uint32_t timer_reset_hi_get(uint32_t base) { return ARCHI_READ(base, TIMER_RESET_HI_OFFSET); } +static inline void timer_reset_hi_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, TIMER_RESET_HI_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define TIMER_CFG_LO_ENABLE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_CFG_LO_ENABLE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_CFG_LO_ENABLE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_CFG_LO_ENABLE(val) ((val) << 0) + +#define TIMER_CFG_LO_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define TIMER_CFG_LO_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define TIMER_CFG_LO_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define TIMER_CFG_LO_RESET(val) ((val) << 1) + +#define TIMER_CFG_LO_IRQEN_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define TIMER_CFG_LO_IRQEN_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define TIMER_CFG_LO_IRQEN_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define TIMER_CFG_LO_IRQEN(val) ((val) << 2) + +#define TIMER_CFG_LO_IEM_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define TIMER_CFG_LO_IEM_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define TIMER_CFG_LO_IEM_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define TIMER_CFG_LO_IEM(val) ((val) << 3) + +#define TIMER_CFG_LO_MODE_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define TIMER_CFG_LO_MODE_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define TIMER_CFG_LO_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define TIMER_CFG_LO_MODE(val) ((val) << 4) + +#define TIMER_CFG_LO_ONE_S_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define TIMER_CFG_LO_ONE_S_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define TIMER_CFG_LO_ONE_S_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define TIMER_CFG_LO_ONE_S(val) ((val) << 5) + +#define TIMER_CFG_LO_PEN_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define TIMER_CFG_LO_PEN_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define TIMER_CFG_LO_PEN_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define TIMER_CFG_LO_PEN(val) ((val) << 6) + +#define TIMER_CFG_LO_CCFG_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define TIMER_CFG_LO_CCFG_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define TIMER_CFG_LO_CCFG_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define TIMER_CFG_LO_CCFG(val) ((val) << 7) + +#define TIMER_CFG_LO_PVAL_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define TIMER_CFG_LO_PVAL_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define TIMER_CFG_LO_PVAL_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define TIMER_CFG_LO_PVAL(val) ((val) << 8) + +#define TIMER_CFG_LO_CASC_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define TIMER_CFG_LO_CASC_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define TIMER_CFG_LO_CASC_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define TIMER_CFG_LO_CASC(val) ((val) << 31) + +#define TIMER_CFG_HI_ENABLE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_CFG_HI_ENABLE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_CFG_HI_ENABLE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_CFG_HI_ENABLE(val) ((val) << 0) + +#define TIMER_CFG_HI_RESET_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define TIMER_CFG_HI_RESET_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define TIMER_CFG_HI_RESET_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define TIMER_CFG_HI_RESET(val) ((val) << 1) + +#define TIMER_CFG_HI_IRQEN_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define TIMER_CFG_HI_IRQEN_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define TIMER_CFG_HI_IRQEN_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define TIMER_CFG_HI_IRQEN(val) ((val) << 2) + +#define TIMER_CFG_HI_IEM_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define TIMER_CFG_HI_IEM_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define TIMER_CFG_HI_IEM_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define TIMER_CFG_HI_IEM(val) ((val) << 3) + +#define TIMER_CFG_HI_MODE_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define TIMER_CFG_HI_MODE_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define TIMER_CFG_HI_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define TIMER_CFG_HI_MODE(val) ((val) << 4) + +#define TIMER_CFG_HI_ONE_S_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define TIMER_CFG_HI_ONE_S_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define TIMER_CFG_HI_ONE_S_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define TIMER_CFG_HI_ONE_S(val) ((val) << 5) + +#define TIMER_CFG_HI_PEN_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define TIMER_CFG_HI_PEN_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define TIMER_CFG_HI_PEN_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define TIMER_CFG_HI_PEN(val) ((val) << 6) + +#define TIMER_CFG_HI_CLKCFG_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define TIMER_CFG_HI_CLKCFG_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define TIMER_CFG_HI_CLKCFG_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define TIMER_CFG_HI_CLKCFG(val) ((val) << 7) + +#define TIMER_CNT_LO_CNT_LO_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define TIMER_CNT_LO_CNT_LO_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define TIMER_CNT_LO_CNT_LO_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define TIMER_CNT_LO_CNT_LO(val) ((val) << 0) + +#define TIMER_CNT_HI_CNT_HI_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define TIMER_CNT_HI_CNT_HI_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define TIMER_CNT_HI_CNT_HI_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define TIMER_CNT_HI_CNT_HI(val) ((val) << 0) + +#define TIMER_CMP_LO_CMP_LO_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define TIMER_CMP_LO_CMP_LO_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define TIMER_CMP_LO_CMP_LO_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define TIMER_CMP_LO_CMP_LO(val) ((val) << 0) + +#define TIMER_CMP_HI_CMP_HI_GET(value) (ARCHI_BEXTRACTU((value),32,0)) +#define TIMER_CMP_HI_CMP_HI_GETS(value) (ARCHI_BEXTRACT((value),32,0)) +#define TIMER_CMP_HI_CMP_HI_SET(value,field) (ARCHI_BINSERT((value),(field),32,0)) +#define TIMER_CMP_HI_CMP_HI(val) ((val) << 0) + +#define TIMER_START_LO_STRT_LO_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_START_LO_STRT_LO_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_START_LO_STRT_LO_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_START_LO_STRT_LO(val) ((val) << 0) + +#define TIMER_START_HI_STRT_HI_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_START_HI_STRT_HI_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_START_HI_STRT_HI_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_START_HI_STRT_HI(val) ((val) << 0) + +#define TIMER_RESET_LO_RST_LO_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_RESET_LO_RST_LO_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_RESET_LO_RST_LO_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_RESET_LO_RST_LO(val) ((val) << 0) + +#define TIMER_RESET_HI_RST_HI_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define TIMER_RESET_HI_RST_HI_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define TIMER_RESET_HI_RST_HI_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define TIMER_RESET_HI_RST_HI(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1.h b/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1.h new file mode 100644 index 0000000..be08c8a --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1.h @@ -0,0 +1,614 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_CPI_UDMA_CPI_V1_H__ +#define __INCLUDE_ARCHI_UDMA_CPI_UDMA_CPI_V1_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// RX Camera uDMA transfer address of associated buffer register +#define UDMA_CPI_CAM_RX_SADDR_OFFSET 0x0 + +// RX Camera uDMA transfer size of buffer register +#define UDMA_CPI_CAM_RX_SIZE_OFFSET 0x4 + +// RX Camera uDMA transfer configuration register +#define UDMA_CPI_CAM_RX_CFG_OFFSET 0x8 + +// - +#define UDMA_CPI_CAM_RX_INITCFG_OFFSET 0xc + +// - +#define UDMA_CPI_CAM_TX_SADDR_OFFSET 0x10 + +// - +#define UDMA_CPI_CAM_TX_SIZE_OFFSET 0x14 + +// - +#define UDMA_CPI_CAM_TX_CFG_OFFSET 0x18 + +// - +#define UDMA_CPI_CAM_TX_INITCFG_OFFSET 0x1c + +// Global configuration register +#define UDMA_CPI_CAM_CFG_GLOB_OFFSET 0x20 + +// Lower Left corner configuration register +#define UDMA_CPI_CAM_CFG_LL_OFFSET 0x24 + +// Upper Right corner configuration register +#define UDMA_CPI_CAM_CFG_UR_OFFSET 0x28 + +// Horizontal Resolution configuration register +#define UDMA_CPI_CAM_CFG_SIZE_OFFSET 0x2c + +// RGB coefficients configuration register +#define UDMA_CPI_CAM_CFG_FILTER_OFFSET 0x30 + +// VSYNC Polarity register +#define UDMA_CPI_CAM_VSYNC_POLARITY_OFFSET 0x34 + + + +// +// REGISTERS FIELDS +// + +// Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address (access: R/W) +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_BIT 0 +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_WIDTH 16 +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_MASK 0xffff + +// Buffer size in bytes. (128kBytes maximum) - Read: buffer size left - Write: set buffer size NOTE: Careful with size in byte. If you use uncompressed pixel data mapped on 16 bits, you have to declare buffer size in bytes even if buffer type is short. (access: R/W) +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_BIT 0 +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_WIDTH 17 +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. (access: R/W) +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_BIT 0 +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_MASK 0x1 + +// Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 (access: R/W) +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_BIT 1 +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_WIDTH 2 +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_MASK 0x6 + +// Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_CPI_CAM_RX_CFG_EN_BIT 4 +#define UDMA_CPI_CAM_RX_CFG_EN_WIDTH 1 +#define UDMA_CPI_CAM_RX_CFG_EN_MASK 0x10 + +// Transfer pending in queue status flag: -1'b0: free -1'b1: pending (access: R) +#define UDMA_CPI_CAM_RX_CFG_PENDING_BIT 5 +#define UDMA_CPI_CAM_RX_CFG_PENDING_WIDTH 1 +#define UDMA_CPI_CAM_RX_CFG_PENDING_MASK 0x20 + +// Channel clear and stop transfer: -1'b0: disable -1'b1: enable (access: W) +#define UDMA_CPI_CAM_RX_CFG_CLR_BIT 6 +#define UDMA_CPI_CAM_RX_CFG_CLR_WIDTH 1 +#define UDMA_CPI_CAM_RX_CFG_CLR_MASK 0x40 + +// Frame dropping: - 1'b0: disable - 1'b1: enable (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_BIT 0 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_WIDTH 1 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_MASK 0x1 + +// Sets how many frames should be dropped after each received. (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_BIT 1 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_WIDTH 6 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_MASK 0x7e + +// Input frame slicing: - 1'b0: disable - 1'b1: enable (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_BIT 7 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_WIDTH 1 +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_MASK 0x80 + +// Input frame format: - 3'b000: RGB565 - 3'b001: RGB555 - 3'b010: RGB444 - 3'b100: BYPASS_LITEND - 3’b101: BYPASS_BIGEND (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_BIT 8 +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_WIDTH 3 +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_MASK 0x700 + +// Right shift of final pixel value (DivFactor) NOTE: not used if FORMAT == BYPASS (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_BIT 11 +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_WIDTH 4 +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_MASK 0x7800 + +// Enable data rx from camera interface. The enable/disable happens only at the start of a frame. - 1'b0: disable - 1'b1: enable (access: R/W) +#define UDMA_CPI_CAM_CFG_GLOB_EN_BIT 31 +#define UDMA_CPI_CAM_CFG_GLOB_EN_WIDTH 1 +#define UDMA_CPI_CAM_CFG_GLOB_EN_MASK 0x80000000 + +// X coordinate of lower left corner of slice (access: R/W) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_BIT 0 +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_WIDTH 16 +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_MASK 0xffff + +// Y coordinate of lower left corner of slice (access: R/W) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_BIT 16 +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_WIDTH 16 +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_MASK 0xffff0000 + +// X coordinate of upper right corner of slice (access: R/W) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_BIT 0 +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_WIDTH 16 +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_MASK 0xffff + +// Y coordinate of upper right corner of slice (access: R/W) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_BIT 16 +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_WIDTH 16 +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_MASK 0xffff0000 + +// Horizontal Resolution. It is used for slice mode. Value set into the bitfield must be equal to (rowlen-1). (access: R/W) +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_BIT 16 +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_WIDTH 16 +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_MASK 0xffff0000 + +// Coefficient that multiplies the B component NOTE: not used if FORMAT == BYPASS (access: R/W) +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_BIT 0 +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_WIDTH 8 +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_MASK 0xff + +// Coefficient that multiplies the G component NOTE: not used if FORMAT == BYPASS (access: R/W) +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_BIT 8 +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_WIDTH 8 +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_MASK 0xff00 + +// Coefficient that multiplies the R component NOTE: not used if FORMAT == BYPASS (access: R/W) +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_BIT 16 +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_WIDTH 8 +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_MASK 0xff0000 + +// Set vsync polarity of CPI. - 1'b0: Active 0 - 1'b1: Active 1 (access: R/W) +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_BIT 0 +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_WIDTH 1 +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_MASK 0x1 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rx_saddr :16; // Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // Buffer size in bytes. (128kBytes maximum) - Read: buffer size left - Write: set buffer size NOTE: Careful with size in byte. If you use uncompressed pixel data mapped on 16 bits, you have to declare buffer size in bytes even if buffer type is short. + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. + unsigned int datasize :2 ; // Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. + unsigned int pending :1 ; // Transfer pending in queue status flag: -1'b0: free -1'b1: pending + unsigned int clr :1 ; // Channel clear and stop transfer: -1'b0: disable -1'b1: enable + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_rx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_rx_initcfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_tx_saddr_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_tx_size_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_tx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_tx_initcfg_t; + +typedef union { + struct { + unsigned int framedrop_en :1 ; // Frame dropping: - 1'b0: disable - 1'b1: enable + unsigned int framedrop_val :6 ; // Sets how many frames should be dropped after each received. + unsigned int frameslice_en :1 ; // Input frame slicing: - 1'b0: disable - 1'b1: enable + unsigned int format :3 ; // Input frame format: - 3'b000: RGB565 - 3'b001: RGB555 - 3'b010: RGB444 - 3'b100: BYPASS_LITEND - 3’b101: BYPASS_BIGEND + unsigned int shift :4 ; // Right shift of final pixel value (DivFactor) NOTE: not used if FORMAT == BYPASS + unsigned int padding0:16; + unsigned int en :1 ; // Enable data rx from camera interface. The enable/disable happens only at the start of a frame. - 1'b0: disable - 1'b1: enable + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_cfg_glob_t; + +typedef union { + struct { + unsigned int frameslice_llx :16; // X coordinate of lower left corner of slice + unsigned int frameslice_lly :16; // Y coordinate of lower left corner of slice + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_cfg_ll_t; + +typedef union { + struct { + unsigned int frameslice_urx :16; // X coordinate of upper right corner of slice + unsigned int frameslice_ury :16; // Y coordinate of upper right corner of slice + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_cfg_ur_t; + +typedef union { + struct { + unsigned int padding0:16; + unsigned int rowlen :16; // Horizontal Resolution. It is used for slice mode. Value set into the bitfield must be equal to (rowlen-1). + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_cfg_size_t; + +typedef union { + struct { + unsigned int b_coeff :8 ; // Coefficient that multiplies the B component NOTE: not used if FORMAT == BYPASS + unsigned int g_coeff :8 ; // Coefficient that multiplies the G component NOTE: not used if FORMAT == BYPASS + unsigned int r_coeff :8 ; // Coefficient that multiplies the R component NOTE: not used if FORMAT == BYPASS + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_cfg_filter_t; + +typedef union { + struct { + unsigned int vsync_polarity :1 ; // Set vsync polarity of CPI. - 1'b0: Active 0 - 1'b1: Active 1 + }; + unsigned int raw; +} __attribute__((packed)) udma_cpi_cam_vsync_polarity_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_cpi_cam_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_SADDR_RX_SADDR_BIT, UDMA_CPI_CAM_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_CPI_CAM_RX_SADDR_RX_SADDR_BIT, UDMA_CPI_CAM_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_udma_cpi_cam_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_SIZE_RX_SIZE_BIT, UDMA_CPI_CAM_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_CPI_CAM_RX_SIZE_RX_SIZE_BIT, UDMA_CPI_CAM_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_udma_cpi_cam_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_CFG_CONTINOUS_BIT, UDMA_CPI_CAM_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_CPI_CAM_RX_CFG_CONTINOUS_BIT, UDMA_CPI_CAM_RX_CFG_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_CFG_DATASIZE_BIT, UDMA_CPI_CAM_RX_CFG_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_CPI_CAM_RX_CFG_DATASIZE_BIT, UDMA_CPI_CAM_RX_CFG_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_CFG_EN_BIT, UDMA_CPI_CAM_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_CPI_CAM_RX_CFG_EN_BIT, UDMA_CPI_CAM_RX_CFG_EN_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_CFG_PENDING_BIT, UDMA_CPI_CAM_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_CPI_CAM_RX_CFG_PENDING_BIT, UDMA_CPI_CAM_RX_CFG_PENDING_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_RX_CFG_CLR_BIT, UDMA_CPI_CAM_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_CPI_CAM_RX_CFG_CLR_BIT, UDMA_CPI_CAM_RX_CFG_CLR_WIDTH); } +}; + +class vp_udma_cpi_cam_cfg_glob : public vp::reg_32 +{ +public: + inline void framedrop_en_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_WIDTH); } + inline uint32_t framedrop_en_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_WIDTH); } + inline void framedrop_val_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_WIDTH); } + inline uint32_t framedrop_val_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_WIDTH); } + inline void frameslice_en_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_WIDTH); } + inline uint32_t frameslice_en_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_WIDTH); } + inline void format_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_FORMAT_BIT, UDMA_CPI_CAM_CFG_GLOB_FORMAT_WIDTH); } + inline uint32_t format_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_FORMAT_BIT, UDMA_CPI_CAM_CFG_GLOB_FORMAT_WIDTH); } + inline void shift_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_SHIFT_BIT, UDMA_CPI_CAM_CFG_GLOB_SHIFT_WIDTH); } + inline uint32_t shift_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_SHIFT_BIT, UDMA_CPI_CAM_CFG_GLOB_SHIFT_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_GLOB_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_CPI_CAM_CFG_GLOB_EN_BIT, UDMA_CPI_CAM_CFG_GLOB_EN_WIDTH); } +}; + +class vp_udma_cpi_cam_cfg_ll : public vp::reg_32 +{ +public: + inline void frameslice_llx_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_BIT, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_WIDTH); } + inline uint32_t frameslice_llx_get() { return this->get_field(UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_BIT, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_WIDTH); } + inline void frameslice_lly_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_BIT, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_WIDTH); } + inline uint32_t frameslice_lly_get() { return this->get_field(UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_BIT, UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_WIDTH); } +}; + +class vp_udma_cpi_cam_cfg_ur : public vp::reg_32 +{ +public: + inline void frameslice_urx_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_BIT, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_WIDTH); } + inline uint32_t frameslice_urx_get() { return this->get_field(UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_BIT, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_WIDTH); } + inline void frameslice_ury_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_BIT, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_WIDTH); } + inline uint32_t frameslice_ury_get() { return this->get_field(UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_BIT, UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_WIDTH); } +}; + +class vp_udma_cpi_cam_cfg_size : public vp::reg_32 +{ +public: + inline void rowlen_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_SIZE_ROWLEN_BIT, UDMA_CPI_CAM_CFG_SIZE_ROWLEN_WIDTH); } + inline uint32_t rowlen_get() { return this->get_field(UDMA_CPI_CAM_CFG_SIZE_ROWLEN_BIT, UDMA_CPI_CAM_CFG_SIZE_ROWLEN_WIDTH); } +}; + +class vp_udma_cpi_cam_cfg_filter : public vp::reg_32 +{ +public: + inline void b_coeff_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_FILTER_B_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_B_COEFF_WIDTH); } + inline uint32_t b_coeff_get() { return this->get_field(UDMA_CPI_CAM_CFG_FILTER_B_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_B_COEFF_WIDTH); } + inline void g_coeff_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_FILTER_G_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_G_COEFF_WIDTH); } + inline uint32_t g_coeff_get() { return this->get_field(UDMA_CPI_CAM_CFG_FILTER_G_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_G_COEFF_WIDTH); } + inline void r_coeff_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_CFG_FILTER_R_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_R_COEFF_WIDTH); } + inline uint32_t r_coeff_get() { return this->get_field(UDMA_CPI_CAM_CFG_FILTER_R_COEFF_BIT, UDMA_CPI_CAM_CFG_FILTER_R_COEFF_WIDTH); } +}; + +class vp_udma_cpi_cam_vsync_polarity : public vp::reg_32 +{ +public: + inline void vsync_polarity_set(uint32_t value) { this->set_field(value, UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_BIT, UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_WIDTH); } + inline uint32_t vsync_polarity_get() { return this->get_field(UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_BIT, UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int cam_rx_saddr ; // RX Camera uDMA transfer address of associated buffer register + unsigned int cam_rx_size ; // RX Camera uDMA transfer size of buffer register + unsigned int cam_rx_cfg ; // RX Camera uDMA transfer configuration register + unsigned int cam_rx_initcfg ; // - + unsigned int cam_tx_saddr ; // - + unsigned int cam_tx_size ; // - + unsigned int cam_tx_cfg ; // - + unsigned int cam_tx_initcfg ; // - + unsigned int cam_cfg_glob ; // Global configuration register + unsigned int cam_cfg_ll ; // Lower Left corner configuration register + unsigned int cam_cfg_ur ; // Upper Right corner configuration register + unsigned int cam_cfg_size ; // Horizontal Resolution configuration register + unsigned int cam_cfg_filter ; // RGB coefficients configuration register + unsigned int cam_vsync_polarity; // VSYNC Polarity register +} __attribute__((packed)) udma_cpi_udma_cpi_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t udma_cpi_cam_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_RX_SADDR_OFFSET); } +static inline void udma_cpi_cam_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_RX_SADDR_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_rx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_RX_SIZE_OFFSET); } +static inline void udma_cpi_cam_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_RX_SIZE_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_RX_CFG_OFFSET); } +static inline void udma_cpi_cam_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_RX_CFG_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_rx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_RX_INITCFG_OFFSET); } +static inline void udma_cpi_cam_rx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_RX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_TX_SADDR_OFFSET); } +static inline void udma_cpi_cam_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_TX_SADDR_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_tx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_TX_SIZE_OFFSET); } +static inline void udma_cpi_cam_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_TX_SIZE_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_TX_CFG_OFFSET); } +static inline void udma_cpi_cam_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_TX_CFG_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_tx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_TX_INITCFG_OFFSET); } +static inline void udma_cpi_cam_tx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_TX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_cfg_glob_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_CFG_GLOB_OFFSET); } +static inline void udma_cpi_cam_cfg_glob_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_CFG_GLOB_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_cfg_ll_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_CFG_LL_OFFSET); } +static inline void udma_cpi_cam_cfg_ll_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_CFG_LL_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_cfg_ur_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_CFG_UR_OFFSET); } +static inline void udma_cpi_cam_cfg_ur_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_CFG_UR_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_cfg_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_CFG_SIZE_OFFSET); } +static inline void udma_cpi_cam_cfg_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_CFG_SIZE_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_cfg_filter_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_CFG_FILTER_OFFSET); } +static inline void udma_cpi_cam_cfg_filter_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_CFG_FILTER_OFFSET, value); } + +static inline uint32_t udma_cpi_cam_vsync_polarity_get(uint32_t base) { return ARCHI_READ(base, UDMA_CPI_CAM_VSYNC_POLARITY_OFFSET); } +static inline void udma_cpi_cam_vsync_polarity_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_CPI_CAM_VSYNC_POLARITY_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_CPI_CAM_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_CPI_CAM_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_CPI_CAM_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_CPI_CAM_RX_CFG_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_CPI_CAM_RX_CFG_DATASIZE(val) ((val) << 1) + +#define UDMA_CPI_CAM_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_CPI_CAM_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_CPI_CAM_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_CPI_CAM_RX_CFG_EN(val) ((val) << 4) + +#define UDMA_CPI_CAM_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_CPI_CAM_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_CPI_CAM_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_CPI_CAM_RX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_CPI_CAM_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define UDMA_CPI_CAM_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define UDMA_CPI_CAM_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define UDMA_CPI_CAM_RX_CFG_CLR(val) ((val) << 6) + +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_EN(val) ((val) << 0) + +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_GET(value) (ARCHI_BEXTRACTU((value),6,1)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_GETS(value) (ARCHI_BEXTRACT((value),6,1)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL_SET(value,field) (ARCHI_BINSERT((value),(field),6,1)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMEDROP_VAL(val) ((val) << 1) + +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define UDMA_CPI_CAM_CFG_GLOB_FRAMESLICE_EN(val) ((val) << 7) + +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_GET(value) (ARCHI_BEXTRACTU((value),3,8)) +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_GETS(value) (ARCHI_BEXTRACT((value),3,8)) +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT_SET(value,field) (ARCHI_BINSERT((value),(field),3,8)) +#define UDMA_CPI_CAM_CFG_GLOB_FORMAT(val) ((val) << 8) + +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_GET(value) (ARCHI_BEXTRACTU((value),4,11)) +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_GETS(value) (ARCHI_BEXTRACT((value),4,11)) +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT_SET(value,field) (ARCHI_BINSERT((value),(field),4,11)) +#define UDMA_CPI_CAM_CFG_GLOB_SHIFT(val) ((val) << 11) + +#define UDMA_CPI_CAM_CFG_GLOB_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_CPI_CAM_CFG_GLOB_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_CPI_CAM_CFG_GLOB_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_CPI_CAM_CFG_GLOB_EN(val) ((val) << 31) + +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLX(val) ((val) << 0) + +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define UDMA_CPI_CAM_CFG_LL_FRAMESLICE_LLY(val) ((val) << 16) + +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URX(val) ((val) << 0) + +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define UDMA_CPI_CAM_CFG_UR_FRAMESLICE_URY(val) ((val) << 16) + +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define UDMA_CPI_CAM_CFG_SIZE_ROWLEN(val) ((val) << 16) + +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define UDMA_CPI_CAM_CFG_FILTER_B_COEFF(val) ((val) << 0) + +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define UDMA_CPI_CAM_CFG_FILTER_G_COEFF(val) ((val) << 8) + +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define UDMA_CPI_CAM_CFG_FILTER_R_COEFF(val) ((val) << 16) + +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_CPI_CAM_VSYNC_POLARITY_VSYNC_POLARITY(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1_old.h b/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1_old.h new file mode 100644 index 0000000..b2817ec --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/cpi/udma_cpi_v1_old.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_CPI_V1_H__ +#define __ARCHI_UDMA_UDMA_CPI_V1_H__ + +// CAM custom registers offset definition +#define CAM_GLOB_OFFSET (0x00) +#define CAM_LL_OFFSET (0x04) +#define CAM_UR_OFFSET (0x08) +#define CAM_SIZE_OFFSET (0x0C) +#define CAM_FILTER_OFFSET (0x10) + +// CAM custom registers bitfields offset, mask, value definition +#define CAM_CFG_GLOB_FRAMEDROP_EN_OFFSET 0 +#define CAM_CFG_GLOB_FRAMEDROP_EN_WIDTH 1 +#define CAM_CFG_GLOB_FRAMEDROP_EN_MASK (0x1 << CAM_CFG_GLOB_FRAMEDROP_EN_OFFSET) +#define CAM_CFG_GLOB_FRAMEDROP_EN_ENA (1 << CAM_CFG_GLOB_FRAMEDROP_EN_OFFSET) +#define CAM_CFG_GLOB_FRAMEDROP_EN_DIS (0 << CAM_CFG_GLOB_FRAMEDROP_EN_OFFSET) + +#define CAM_CFG_GLOB_FRAMEDROP_VAL_OFFSET 1 +#define CAM_CFG_GLOB_FRAMEDROP_VAL_WIDTH 6 +#define CAM_CFG_GLOB_FRAMEDROP_VAL_MASK (0x3f << CAM_CFG_GLOB_FRAMEDROP_VAL_OFFSET) +#define CAM_CFG_GLOB_FRAMEDROP_VAL(val) (val << CAM_CFG_GLOB_FRAMEDROP_VAL_OFFSET) + +#define CAM_CFG_GLOB_FRAMESLICE_EN_OFFSET 7 +#define CAM_CFG_GLOB_FRAMESLICE_EN_WIDTH 1 +#define CAM_CFG_GLOB_FRAMESLICE_EN_MASK (0x1 << CAM_CFG_GLOB_FRAMESLICE_EN_OFFSET) +#define CAM_CFG_GLOB_FRAMESLICE_EN_ENA (1 << CAM_CFG_GLOB_FRAMESLICE_EN_OFFSET) +#define CAM_CFG_GLOB_FRAMESLICE_EN_DIS (0 << CAM_CFG_GLOB_FRAMESLICE_EN_OFFSET) + +#define CAM_CFG_GLOB_FORMAT_OFFSET 8 +#define CAM_CFG_GLOB_FORMAT_WIDTH 2 +#define CAM_CFG_GLOB_FORMAT_MASK (0x7 << CAM_CFG_GLOB_FORMAT_OFFSET) +#define CAM_CFG_GLOB_FORMAT_RGB565 (0 << CAM_CFG_GLOB_FORMAT_OFFSET) +#define CAM_CFG_GLOB_FORMAT_RGB555 (1 << CAM_CFG_GLOB_FORMAT_OFFSET) +#define CAM_CFG_GLOB_FORMAT_RGB444 (2 << CAM_CFG_GLOB_FORMAT_OFFSET) +#define CAM_CFG_GLOB_FORMAT_BYPASS_LITEND (4 << CAM_CFG_GLOB_FORMAT_OFFSET) +#define CAM_CFG_GLOB_FORMAT_BYPASS_BIGEND (5 << CAM_CFG_GLOB_FORMAT_OFFSET) + +#define ARCHI_CAM_CFG_GLOB_FORMAT_RGB565 0 +#define ARCHI_CAM_CFG_GLOB_FORMAT_RGB555 1 +#define ARCHI_CAM_CFG_GLOB_FORMAT_RGB444 2 +#define ARCHI_CAM_CFG_GLOB_FORMAT_BYPASS_LITEND 4 +#define ARCHI_CAM_CFG_GLOB_FORMAT_BYPASS_BIGEND 5 + +#define CAM_CFG_GLOB_SHIFT_OFFSET 11 +#define CAM_CFG_GLOB_SHIFT_WIDTH 4 +#define CAM_CFG_GLOB_SHIFT_MASK (0xf << CAM_CFG_GLOB_SHIFT_OFFSET) +#define CAM_CFG_GLOB_SHIFT(val) (val << CAM_CFG_GLOB_SHIFT_OFFSET) + +#define CAM_CFG_GLOB_EN_OFFSET 31 +#define CAM_CFG_GLOB_EN_WIDTH 1 +#define CAM_CFG_GLOB_EN_MASK (0x1 << CAM_CFG_GLOB_EN_OFFSET) +#define CAM_CFG_GLOB_EN_ENA (1 << CAM_CFG_GLOB_EN_OFFSET) +#define CAM_CFG_GLOB_EN_DIS (0 << CAM_CFG_GLOB_EN_OFFSET) + +#define CAM_CFG_LL_FRAMESLICE_LLX_OFFSET 0 +#define CAM_CFG_LL_FRAMESLICE_LLX_WIDTH 16 +#define CAM_CFG_LL_FRAMESLICE_LLX_MASK (0xffff << CAM_CFG_LL_FRAMESLICE_LLX_OFFSET) +#define CAM_CFG_LL_FRAMESLICE_LLX(val) (val << CAM_CFG_LL_FRAMESLICE_LLX_OFFSET) + +#define CAM_CFG_LL_FRAMESLICE_LLY_OFFSET 16 +#define CAM_CFG_LL_FRAMESLICE_LLY_WIDTH 16 +#define CAM_CFG_LL_FRAMESLICE_LLY_MASK (0xffff << CAM_CFG_LL_FRAMESLICE_LLY_OFFSET) +#define CAM_CFG_LL_FRAMESLICE_LLY(val) (val << CAM_CFG_LL_FRAMESLICE_LLY_OFFSET) + +#define CAM_CFG_UR_FRAMESLICE_URX_OFFSET 0 +#define CAM_CFG_UR_FRAMESLICE_URX_WIDTH 16 +#define CAM_CFG_UR_FRAMESLICE_URX_MASK (0xffff << CAM_CFG_UR_FRAMESLICE_URX_OFFSET) +#define CAM_CFG_UR_FRAMESLICE_URX(val) (val << CAM_CFG_UR_FRAMESLICE_URX_OFFSET) + +#define CAM_CFG_UR_FRAMESLICE_URY_OFFSET 16 +#define CAM_CFG_UR_FRAMESLICE_URY_WIDTH 16 +#define CAM_CFG_UR_FRAMESLICE_URY_MASK (0xffff << CAM_CFG_UR_FRAMESLICE_URY_OFFSET) +#define CAM_CFG_UR_FRAMESLICE_URY(val) (val << CAM_CFG_UR_FRAMESLICE_URY_OFFSET) + +#define CAM_CFG_SIZE_ROWLEN_OFFSET 16 +#define CAM_CFG_SIZE_ROWLEN_WIDTH 16 +#define CAM_CFG_SIZE_ROWLEN_MASK (0xffff << CAM_CFG_SIZE_ROWLEN_OFFSET) +#define CAM_CFG_SIZE_ROWLEN(val) ((val - 1) << CAM_CFG_SIZE_ROWLEN_OFFSET) + +#define CAM_CFG_FILTER_B_COEFF_OFFSET 0 +#define CAM_CFG_FILTER_B_COEFF_WIDTH 8 +#define CAM_CFG_FILTER_B_COEFF_MASK (0xff << CAM_CFG_FILTER_B_COEFF_OFFSET) +#define CAM_CFG_FILTER_B_COEFF(val) (val << CAM_CFG_FILTER_B_COEFF_OFFSET) + +#define CAM_CFG_FILTER_G_COEFF_OFFSET 8 +#define CAM_CFG_FILTER_G_COEFF_WIDTH 8 +#define CAM_CFG_FILTER_G_COEFF_MASK (0xff << CAM_CFG_FILTER_G_COEFF_OFFSET) +#define CAM_CFG_FILTER_G_COEFF(val) (val << CAM_CFG_FILTER_G_COEFF_OFFSET) + +#define CAM_CFG_FILTER_R_COEFF_OFFSET 16 +#define CAM_CFG_FILTER_R_COEFF_WIDTH 8 +#define CAM_CFG_FILTER_R_COEFF_MASK (0xff << CAM_CFG_FILTER_R_COEFF_OFFSET) +#define CAM_CFG_FILTER_R_COEFF(val) (val << CAM_CFG_FILTER_R_COEFF_OFFSET) + +// TODO Add enum definitions of CAM register bitfields + +/////////////////////////////////////////////////// +// TODO Obsolete : to be removed cause deprecated +#define CAM_CFG_GLOB_FRAMEDROP_EN_BIT 0 +#define CAM_CFG_GLOB_FRAMEDROP_VAL_BIT 1 +#define CAM_CFG_GLOB_FRAMEDROP_VAL_SIZE 6 +#define CAM_CFG_GLOB_FRAMESLICE_EN_BIT 7 +#define CAM_CFG_GLOB_FORMAT_BIT 8 +#define CAM_CFG_GLOB_FORMAT_SIZE 3 +#define CAM_CFG_GLOB_SHIFT_BIT 11 +#define CAM_CFG_GLOB_SHIFT_SIZE 4 +#define CAM_CFG_GLOB_EN_BIT 31 + +//+ #define CAM_CFG_GLOB_FORMAT_RGB565 0 +//+ #define CAM_CFG_GLOB_FORMAT_RGB555 1 +//+ #define CAM_CFG_GLOB_FORMAT_RGB444 2 +//+ #define CAM_CFG_GLOB_FORMAT_BYPASS 3 + +#define CAM_CFG_LL_FRAMESLICE_LLX_BIT 0 +#define CAM_CFG_LL_FRAMESLICE_LLX_SIZE 16 +#define CAM_CFG_LL_FRAMESLICE_LLY_BIT 16 +#define CAM_CFG_LL_FRAMESLICE_LLY_SIZE 16 + +#define CAM_CFG_UR_FRAMESLICE_URX_BIT 0 +#define CAM_CFG_UR_FRAMESLICE_URX_SIZE 16 +#define CAM_CFG_UR_FRAMESLICE_URY_BIT 16 +#define CAM_CFG_UR_FRAMESLICE_URY_SIZE 16 + +#define CAM_CFG_SIZE_ROWLEN_BIT 16 +#define CAM_CFG_SIZE_ROWLEN_SIZE 16 + +#define CAM_CFG_FILTER_B_COEFF_BIT 0 +#define CAM_CFG_FILTER_B_COEFF_SIZE 8 +#define CAM_CFG_FILTER_G_COEFF_BIT 8 +#define CAM_CFG_FILTER_G_COEFF_SIZE 8 +#define CAM_CFG_FILTER_R_COEFF_BIT 16 +#define CAM_CFG_FILTER_R_COEFF_SIZE 8 +/////////////////////////////////////////////////// + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/csi2/udma_csi2_v1.h b/sw/pulp-sdk/archi/include/archi/udma/csi2/udma_csi2_v1.h new file mode 100644 index 0000000..e135f80 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/csi2/udma_csi2_v1.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_CSI2_V1_H__ +#define __ARCHI_UDMA_UDMA_CSI2_V1_H__ + +// CSI2 custom registers offset definition + +#define CSI2_CLK_CFG_OFFSET (0x00) + +// CSI2 custom registers bitfields offset, mask, value definition +#define CSI2_CLK_CFG_CCI_BIT 0 +#define CSI2_CLK_CFG_CCI_BITS 8 +#define CSI2_CLK_CFG_CCI_MASK ARCHI_REG_MASK(CSI2_CLK_CFG_CCI_BIT, CSI2_CLK_CFG_CCI_BITS) +#define CSI2_CLK_CFG_CCI(val) (val << CSI2_CLK_CFG_CCI_BIT) + +#define CSI2_CLK_CFG_PIXEL_BIT 8 +#define CSI2_CLK_CFG_PIXEL_BITS 8 +#define CSI2_CLK_CFG_PIXEL_MASK ARCHI_REG_MASK(CSI2_CLK_CFG_PIXEL_BIT, CSI2_CLK_CFG_PIXEL_BITS) +#define CSI2_CLK_CFG_PIXEL(val) (val << CSI2_CLK_CFG_PIXEL_BIT) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v1.h b/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v1.h new file mode 100644 index 0000000..a604937 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v1.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_HYPER_H__ +#define __ARCHI_HYPER_H__ + +#define REG_ACCESS 0x1 +#define MEM_ACCESS 0x0 + +// Memory base address +#define REG_MBR0 0 +// HYPER RAM 8 Mbytes / 2 = 4M address, here is 16M +#define REG_MBR1 0x01000000 + +#define REG_MBR_WIDTH 24 + +#define HYPER_EXT_ADDR_CHANNEL_OFFSET 0x00 +#define HYPER_EXT_CFG_CHANNEL_OFFSET 0x04 +#define HYPER_MEM_CFG0_CHANNEL_OFFSET 0x08 +#define HYPER_MEM_CFG1_CHANNEL_OFFSET 0x0C +#define HYPER_MEM_CFG2_CHANNEL_OFFSET 0x10 +#define HYPER_MEM_CFG3_CHANNEL_OFFSET 0x14 +#define HYPER_MEM_CFG4_CHANNEL_OFFSET 0x18 +#define HYPER_MEM_CFG5_CHANNEL_OFFSET 0x1C +#define HYPER_MEM_CFG6_CHANNEL_OFFSET 0x20 +#define HYPER_MEM_CFG7_CHANNEL_OFFSET 0x24 +#define HYPER_NB_REGS 10 + +#define HYPER_EXT_ADDR_CHANNEL_CUSTOM_OFFSET 0x20 +#define HYPER_EXT_CFG_CHANNEL_CUSTOM_OFFSET 0x24 +#define HYPER_MEM_CFG0_CHANNEL_CUSTOM_OFFSET 0x28 +#define HYPER_MEM_CFG1_CHANNEL_CUSTOM_OFFSET 0x2C +#define HYPER_MEM_CFG2_CHANNEL_CUSTOM_OFFSET 0x30 +#define HYPER_MEM_CFG3_CHANNEL_CUSTOM_OFFSET 0x34 +#define HYPER_MEM_CFG4_CHANNEL_CUSTOM_OFFSET 0x38 +#define HYPER_MEM_CFG5_CHANNEL_CUSTOM_OFFSET 0x3C +#define HYPER_MEM_CFG6_CHANNEL_CUSTOM_OFFSET 0x40 +#define HYPER_MEM_CFG7_CHANNEL_CUSTOM_OFFSET 0x44 + +#define HYPER_EXT_ADDR_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_EXT_ADDR_CHANNEL_CUSTOM_OFFSET) +#define HYPER_EXT_CFG_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_EXT_CFG_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG0_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG0_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG1_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG1_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG2_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG2_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG3_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG3_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG4_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG4_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG5_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG5_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG6_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG6_CHANNEL_CUSTOM_OFFSET) +#define HYPER_MEM_CFG7_OFFSET (UDMA_HYPER_OFFSET(0) + HYPER_MEM_CFG7_CHANNEL_CUSTOM_OFFSET) + +#define HYPER_EXT_ADDR (ARCHI_UDMA_ADDR + HYPER_EXT_ADDR_OFFSET) +#define HYPER_EXT_CFG (ARCHI_UDMA_ADDR + HYPER_EXT_CFG_OFFSET) +#define HYPER_MEM_CFG0 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG0_OFFSET) +#define HYPER_MEM_CFG1 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG1_OFFSET) +#define HYPER_MEM_CFG2 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG2_OFFSET) +#define HYPER_MEM_CFG3 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG3_OFFSET) +#define HYPER_MEM_CFG4 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG4_OFFSET) +#define HYPER_MEM_CFG5 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG5_OFFSET) +#define HYPER_MEM_CFG6 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG6_OFFSET) +#define HYPER_MEM_CFG7 (ARCHI_UDMA_ADDR + HYPER_MEM_CFG7_OFFSET) + +#define HYPER_EXT_ADDR_MASK 0xFFFFFFFF +#define HYPER_EXT_CFG_MASK 0x0000 // Not use +#define HYPER_MEM_CFG0_MASK 0x3FFF +#define HYPER_MEM_CFG1_MASK 0xFFFFFF +#define HYPER_MEM_CFG2_MASK 0x01FF01FF +#define HYPER_MEM_CFG3_MASK 0x73F +#define HYPER_MEM_CFG4_MASK 0x3FFF +#define HYPER_MEM_CFG5_MASK 0x00FFFFFF +#define HYPER_MEM_CFG6_MASK 0x01FF01FF +#define HYPER_MEM_CFG7_MASK 0x3F + +// HYPER RAM CONFIG +#define HYPER_MEM_CFG0_MBR0_OFFSET 0 // HyperRam base address, default = 0x0 +#define HYPER_MEM_CFG0_LATENCY0_OFFSET 8 +#define HYPER_MEM_CFG0_WRAP_SIZE0_OFFSET 12 + +#define HYPER_MEM_CFG1_RD_CSHI0_OFFSET 0 +#define HYPER_MEM_CFG1_RD_CSS0_OFFSET 4 +#define HYPER_MEM_CFG1_RD_CSH0_OFFSET 8 +#define HYPER_MEM_CFG1_WR_CSHI0_OFFSET 12 +#define HYPER_MEM_CFG1_WR_CSS0_OFFSET 16 +#define HYPER_MEM_CFG1_WR_CSH0_OFFSET 20 + +#define HYPER_MEM_CFG2_RD_MAX_LENGTH0_OFFSET 0 +#define HYPER_MEM_CFG2_WR_MAX_LENGTH0_OFFSET 16 + +#define HYPER_MEM_CFG3_ACS0_OFFSET 0 +#define HYPER_MEM_CFG3_TCO0_OFFSET 1 +#define HYPER_MEM_CFG3_DT0_OFFSET 2 +#define HYPER_MEM_CFG3_CRT0_OFFSET 3 // HyperRAM memory access 0, for register access 1 +#define HYPER_MEM_CFG3_RD_MAX_LEN_EN0_OFFSET 4 +#define HYPER_MEM_CFG3_WR_MAX_LEN_EN0_OFFSET 5 +#define HYPER_MEM_CFG3_RDS_DELAY_ADJ_OFFSET 8 + +// HYPER FLASH CONFIG +#define HYPER_MEM_CFG4_MBR1_OFFSET 0// Hyperflash base address, default = MBR0 + HYPERRAM SIZE +#define HYPER_MEM_CFG4_LATENCY1_OFFSET 8 +#define HYPER_MEM_CFG4_WRAP_SIZE1_OFFSET 12 + +#define HYPER_MEM_CFG5_RD_CSHI1_OFFSET 0 +#define HYPER_MEM_CFG5_RD_CSS1_OFFSET 4 +#define HYPER_MEM_CFG5_RD_CSH1_OFFSET 8 +#define HYPER_MEM_CFG5_WR_CSHI1_OFFSET 12 +#define HYPER_MEM_CFG5_WR_CSS1_OFFSET 16 +#define HYPER_MEM_CFG5_WR_CSH1_OFFSET 20 + +#define HYPER_MEM_CFG6_RD_MAX_LENGTH1_OFFSET 0 +#define HYPER_MEM_CFG6_WR_MAX_LENGTH1_OFFSET 16 + +#define HYPER_MEM_CFG7_ACS1_OFFSET 0 +#define HYPER_MEM_CFG7_TCO1_OFFSET 1 +#define HYPER_MEM_CFG7_DT1_OFFSET 2 +#define HYPER_MEM_CFG7_CRT1_OFFSET 3 // HyperFlash memory access 0, for register access 1 +#define HYPER_MEM_CFG7_RD_MAX_LEN_EN1_OFFSET 4 +#define HYPER_MEM_CFG7_WR_MAX_LEN_EN1_OFFSET 5 + +// BITS +#define HYPER_MEM_CFG3_MASK_GEN_B(offset) ((~(1 << offset)) & HYPER_MEM_CFG3_MASK) +#define HYPER_MEM_CFG7_MASK_GEN_B(offset) ((~(1 << offset)) & HYPER_MEM_CFG7_MASK) +// TWO BITS +#define HYPER_MEM_CFG0_MASK_GEN_TB(offset) ((~(0x3 << offset)) & HYPER_MEM_CFG0_MASK) +#define HYPER_MEM_CFG4_MASK_GEN_TB(offset) ((~(0x3 << offset)) & HYPER_MEM_CFG4_MASK) +// THREE BITS +#define HYPER_MEM_CFG3_MASK_GEN_THB(offset) ((~(0x7 << offset)) & HYPER_MEM_CFG3_MASK) +// HALF BYTES +#define HYPER_MEM_CFG0_MASK_GEN_HB(offset) ((~(0xF << offset)) & HYPER_MEM_CFG0_MASK) +#define HYPER_MEM_CFG1_MASK_GEN_HB(offset) ((~(0xF << offset)) & HYPER_MEM_CFG1_MASK) +#define HYPER_MEM_CFG4_MASK_GEN_HB(offset) ((~(0xF << offset)) & HYPER_MEM_CFG4_MASK) +#define HYPER_MEM_CFG5_MASK_GEN_HB(offset) ((~(0xF << offset)) & HYPER_MEM_CFG5_MASK) +// BYTES +#define HYPER_MEM_CFG0_MASK_GEN_BYTE(offset) ((~(0xFF << offset)) & HYPER_MEM_CFG0_MASK) +#define HYPER_MEM_CFG4_MASK_GEN_BYTE(offset) ((~(0xFF << offset)) & HYPER_MEM_CFG4_MASK) +// NINE BITS +#define HYPER_MEM_CFG2_MASK_GEN_NB(offset) ((~(0x1FF << offset)) & HYPER_MEM_CFG2_MASK) +#define HYPER_MEM_CFG6_MASK_GEN_NB(offset) ((~(0x1FF << offset)) & HYPER_MEM_CFG6_MASK) + +// MASK +#define HYPER_MEM_CFG0_MBR0_MASK_BYTE HYPER_MEM_CFG0_MASK_GEN_BYTE(HYPER_MEM_CFG0_MBR0_OFFSET) +#define HYPER_MEM_CFG0_LATENCY0_MASK_HB HYPER_MEM_CFG0_MASK_GEN_HB(HYPER_MEM_CFG0_LATENCY0_OFFSET) +#define HYPER_MEM_CFG0_WRAP_SIZE0_MASK_TB HYPER_MEM_CFG0_MASK_GEN_TB(HYPER_MEM_CFG0_WRAP_SIZE0_OFFSET) +#define HYPER_MEM_CFG1_RD_CSHI0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_RD_CSHI0_OFFSET) +#define HYPER_MEM_CFG1_RD_CSS0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_RD_CSS0_OFFSET) +#define HYPER_MEM_CFG1_RD_CSH0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_RD_CSH0_OFFSET) +#define HYPER_MEM_CFG1_WR_CSHI0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_WR_CSHI0_OFFSET) +#define HYPER_MEM_CFG1_WR_CSS0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_WR_CSS0_OFFSET) +#define HYPER_MEM_CFG1_WR_CSH0_MASK_HB HYPER_MEM_CFG1_MASK_GEN_HB(HYPER_MEM_CFG1_WR_CSH0_OFFSET) +#define HYPER_MEM_CFG2_RD_MAX_LENGTH0_MASK_NB HYPER_MEM_CFG2_MASK_GEN_NB(HYPER_MEM_CFG2_RD_MAX_LENGTH0_OFFSET) +#define HYPER_MEM_CFG2_WR_MAX_LENGTH0_MASK_NB HYPER_MEM_CFG2_MASK_GEN_NB(HYPER_MEM_CFG2_WR_MAX_LENGTH0_OFFSET) +#define HYPER_MEM_CFG3_ACS0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_ACS0_OFFSET) +#define HYPER_MEM_CFG3_TCO0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_TCO0_OFFSET) +#define HYPER_MEM_CFG3_DT0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_DT0_OFFSET) +#define HYPER_MEM_CFG3_CRT0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_CRT0_OFFSET) +#define HYPER_MEM_CFG3_RD_MAX_LEN_EN0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_RD_MAX_LEN_EN0_OFFSET) +#define HYPER_MEM_CFG3_WR_MAX_LEN_EN0_MASK_B HYPER_MEM_CFG3_MASK_GEN_B(HYPER_MEM_CFG3_WR_MAX_LEN_EN0_OFFSET) +#define HYPER_MEM_CFG3_RDS_DELAY_ADJ_MASK_THB HYPER_MEM_CFG3_MASK_GEN_THB(HYPER_MEM_CFG3_RDS_DELAY_ADJ_OFFSET) + +#define HYPER_MEM_CFG4_MBR1_MASK_BYTE HYPER_MEM_CFG4_MASK_GEN_BYTE(HYPER_MEM_CFG4_MBR1_OFFSET) +// This bit is ignored when the DEVTYPE = 1 is chosen to the HyperFlash memory. +//#define HYPER_MEM_CFG4_LATENCY1_MASK_HB HYPER_MEM_CFG4_MASK_GEN_HB(HYPER_MEM_CFG4_LATENCY1_OFFSET) +#define HYPER_MEM_CFG4_WRAP_SIZE1_MASK_TB HYPER_MEM_CFG4_MASK_GEN_TB(HYPER_MEM_CFG4_WRAP_SIZE1_OFFSET) +#define HYPER_MEM_CFG5_RD_CSHI1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_RD_CSHI1_OFFSET) +#define HYPER_MEM_CFG5_RD_CSS1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_RD_CSS1_OFFSET) +#define HYPER_MEM_CFG5_RD_CSH1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_RD_CSH1_OFFSET) +#define HYPER_MEM_CFG5_WR_CSHI1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_WR_CSHI1_OFFSET) +#define HYPER_MEM_CFG5_WR_CSS1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_WR_CSS1_OFFSET) +#define HYPER_MEM_CFG5_WR_CSH1_MASK_HB HYPER_MEM_CFG5_MASK_GEN_HB(HYPER_MEM_CFG5_WR_CSH1_OFFSET) +#define HYPER_MEM_CFG6_RD_MAX_LENGTH1_MASK_NB HYPER_MEM_CFG6_MASK_GEN_NB(HYPER_MEM_CFG6_RD_MAX_LENGTH1_OFFSET) +#define HYPER_MEM_CFG6_WR_MAX_LENGTH1_MASK_NB HYPER_MEM_CFG6_MASK_GEN_NB(HYPER_MEM_CFG6_WR_MAX_LENGTH1_OFFSET) +#define HYPER_MEM_CFG7_ACS1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_ACS1_OFFSET) +#define HYPER_MEM_CFG7_TCO1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_TCO1_OFFSET) +#define HYPER_MEM_CFG7_DT1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_DT1_OFFSET) +#define HYPER_MEM_CFG7_CRT1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_CRT1_OFFSET) +#define HYPER_MEM_CFG7_RD_MAX_LEN_EN1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_RD_MAX_LEN_EN1_OFFSET) +#define HYPER_MEM_CFG7_WR_MAX_LEN_EN1_MASK_B HYPER_MEM_CFG7_MASK_GEN_B(HYPER_MEM_CFG7_WR_MAX_LEN_EN1_OFFSET) + + +#define ARCHI_UDMA_HYPER_RX_EVT 0 +#define ARCHI_UDMA_HYPER_TX_EVT 1 + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v2.h b/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v2.h new file mode 100644 index 0000000..cccf3b5 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/hyper/udma_hyper_v2.h @@ -0,0 +1,999 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_HYPER_UDMA_HYPER_V2_H__ +#define __INCLUDE_ARCHI_UDMA_HYPER_UDMA_HYPER_V2_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// uDMA RX HYPERBUS buffer base address configuration register. +#define HYPER_RX_SADDR_OFFSET 0x0 + +// uDMA RX HYPERBUS buffer size configuration register. +#define HYPER_RX_SIZE_OFFSET 0x4 + +// uDMA RX HYPERBUS stream configuration register. +#define HYPER_RX_CFG_OFFSET 0x8 + +// uDMA TX HYPERBUS buffer base address configuration register. +#define HYPER_TX_SADDR_OFFSET 0x10 + +// uDMA TX HYPERBUS buffer size configuration register. +#define HYPER_TX_SIZE_OFFSET 0x14 + +// uDMA TX HYPERBUS stream configuration register. +#define HYPER_TX_CFG_OFFSET 0x18 + +// Memory access address register. +#define HYPER_EXT_ADDR_OFFSET 0x20 + +// HYPERBUS and Octo SPI Memory Timing configuration register. +#define HYPER_TIMING_CFG_OFFSET 0x24 + +// Device start address register. +#define HYPER_MBA0_OFFSET 0x28 + +// Device start address register. +#define HYPER_MBA1_OFFSET 0x2c + +// Device type register(RAM or FLASH). +#define HYPER_DEVICE_OFFSET 0x30 + +// OSPI command +#define HYPER_OSPI_CMD_OFFSET 0x34 + +// OSPI address +#define HYPER_OSPI_ADDR_OFFSET 0x38 + +// OSPI configuration +#define HYPER_OSPI_CFG_OFFSET 0x3c + +// OSPI chip select configuration +#define HYPER_OSPI_CSN_OFFSET 0x40 + +// - +#define HYPER__RESERVED0_OFFSET 0x44 + +// - +#define HYPER__RESERVED1_OFFSET 0x48 + +// OSPI interrupt enable register +#define HYPER_IRQ_EN_OFFSET 0x4c + +// Clock divide. +#define HYPER_CLK_DIV_OFFSET 0x50 + +// Transfer status for error. +#define HYPER_STATUS_OFFSET 0x54 + + + +// +// REGISTERS FIELDS +// + +// RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address (access: R/W) +#define HYPER_RX_SADDR_RX_SADDR_BIT 0 +#define HYPER_RX_SADDR_RX_SADDR_WIDTH 16 +#define HYPER_RX_SADDR_RX_SADDR_MASK 0xffff + +// RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define HYPER_RX_SIZE_RX_SIZE_BIT 0 +#define HYPER_RX_SIZE_RX_SIZE_WIDTH 17 +#define HYPER_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define HYPER_RX_CFG_CONTINOUS_BIT 0 +#define HYPER_RX_CFG_CONTINOUS_WIDTH 1 +#define HYPER_RX_CFG_CONTINOUS_MASK 0x1 + +// RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define HYPER_RX_CFG_EN_BIT 4 +#define HYPER_RX_CFG_EN_WIDTH 1 +#define HYPER_RX_CFG_EN_MASK 0x10 + +// RX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue (access: R) +#define HYPER_RX_CFG_PENDING_BIT 5 +#define HYPER_RX_CFG_PENDING_WIDTH 1 +#define HYPER_RX_CFG_PENDING_MASK 0x20 + +// RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear the on-going transfer (access: W) +#define HYPER_RX_CFG_CLR_BIT 6 +#define HYPER_RX_CFG_CLR_WIDTH 1 +#define HYPER_RX_CFG_CLR_MASK 0x40 + +// TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address (access: R/W) +#define HYPER_TX_SADDR_TX_SADDR_BIT 0 +#define HYPER_TX_SADDR_TX_SADDR_WIDTH 16 +#define HYPER_TX_SADDR_TX_SADDR_MASK 0xffff + +// TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define HYPER_TX_SIZE_TX_SIZE_BIT 0 +#define HYPER_TX_SIZE_TX_SIZE_WIDTH 17 +#define HYPER_TX_SIZE_TX_SIZE_MASK 0x1ffff + +// TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define HYPER_TX_CFG_CONTINOUS_BIT 0 +#define HYPER_TX_CFG_CONTINOUS_WIDTH 1 +#define HYPER_TX_CFG_CONTINOUS_MASK 0x1 + +// TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define HYPER_TX_CFG_EN_BIT 4 +#define HYPER_TX_CFG_EN_WIDTH 1 +#define HYPER_TX_CFG_EN_MASK 0x10 + +// TX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue (access: R) +#define HYPER_TX_CFG_PENDING_BIT 5 +#define HYPER_TX_CFG_PENDING_WIDTH 1 +#define HYPER_TX_CFG_PENDING_MASK 0x20 + +// TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear the on-going transfer (access: W) +#define HYPER_TX_CFG_CLR_BIT 6 +#define HYPER_TX_CFG_CLR_WIDTH 1 +#define HYPER_TX_CFG_CLR_MASK 0x40 + +// Memory access address bitfield. (access: R/W) +#define HYPER_EXT_ADDR_SADDR_BIT 0 +#define HYPER_EXT_ADDR_SADDR_WIDTH 31 +#define HYPER_EXT_ADDR_SADDR_MASK 0x7fffffff + +// Register access flag bitfield. (access: R/W) +#define HYPER_EXT_ADDR_REG_ACCESS_BIT 31 +#define HYPER_EXT_ADDR_REG_ACCESS_WIDTH 1 +#define HYPER_EXT_ADDR_REG_ACCESS_MASK 0x80000000 + +// Latency Cycle value for both HyperRAM and HyperFLASH for chip select 0. When using HyperRAM memory, this bit should be set to the same value as the read latency in configuration register of HyperRAM memory the read latency in configuration register of HyperRAM memory. For SPI, is the dummy cycle after ADDRESS stage : - 4'b0000: 16 CK - 4'b0001: 1 CK - 4'b0001: 2 CK ... - 4'b1111: 15 CK (access: R/W) +#define HYPER_TIMING_CFG_LATENCY0_BIT 0 +#define HYPER_TIMING_CFG_LATENCY0_WIDTH 5 +#define HYPER_TIMING_CFG_LATENCY0_MASK 0x1f + +// Latency Cycle value for both HyperRAM and HyperFLASH for chip select 1. When using HyperRAM memory, this bit should be set to the same value as the read latency in configuration register of HyperRAM memory the read latency in configuration register of HyperRAM memory. For SPI, is the dummy cycle after ADDRESS stage : - 5'b00000: 0 CK - 5'b00001: 1 CK - 5'b000001: 2 CK ... - 5'b11111: 31 CK (access: R/W) +#define HYPER_TIMING_CFG_LATENCY1_BIT 5 +#define HYPER_TIMING_CFG_LATENCY1_WIDTH 5 +#define HYPER_TIMING_CFG_LATENCY1_MASK 0x3e0 + +// Some HyperBus devices may require a minimum time between the end of a prior transaction and the start of a new access. This time is referred to as Read-Write-Recovery time (tRWR). The master interface must start driving CS# Low only at a time when the CA1 transfer will complete after tRWR is satisfied. - 5'b00000: 0 CK - 5'b00001: 1 CK - 5'b000001: 2 CK ... - 5'b11111: 31 CK (access: R/W) +#define HYPER_TIMING_CFG_RW_RECOVERY_BIT 10 +#define HYPER_TIMING_CFG_RW_RECOVERY_WIDTH 4 +#define HYPER_TIMING_CFG_RW_RECOVERY_MASK 0x3c00 + +// Delay of RWDS for center aligned read: - 3'b000: 0 logic delay - 3'b001: 1 logic delay - 3'b010: 2 logic delay - 3'b111: 7 logic delay (access: R/W) +#define HYPER_TIMING_CFG_RWDS_DELAY_BIT 14 +#define HYPER_TIMING_CFG_RWDS_DELAY_WIDTH 3 +#define HYPER_TIMING_CFG_RWDS_DELAY_MASK 0x1c000 + +// Auto check for RWDS high or low for additional latency : - 1'b0: additional latency no autocheck - 1'b1: additional latency autocheck (access: R/W) +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_BIT 17 +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_WIDTH 1 +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_MASK 0x20000 + +// Maximum chip select low time for self-refresh HYPERRAM to valid the data transfer : - 14'h0000: 1 CK - 14'h0001: 2 CK - 14'h0011: 3 CK - - 14'h3FFF: 16383 CK (access: R/W) +#define HYPER_TIMING_CFG_CS_MAX_BIT 18 +#define HYPER_TIMING_CFG_CS_MAX_WIDTH 16 +#define HYPER_TIMING_CFG_CS_MAX_MASK 0x3fffc0000 + +// Memory Base Address 0 for both RAM and FLASH bitfield. The base address of addressable region to each memory is set up. Since register can be set in 16M bytes boundary, lower 24 bit is fixed to 0. MBA0 can be greater than MBA1, the chip select which decided by the relationship among MBA0, MBA1, and EXT_ADDR. - MBA0 < MBA1, if (MBA1 <= EXT_ADDR) CS1 = 0; else CS0 = 0; - MBA0 > MBA1, if (MBA0 <= EXT_ADDR) CS0 = 0; else CS1 = 0; (access: R/W) +#define HYPER_MBA0_MBA0_BIT 24 +#define HYPER_MBA0_MBA0_WIDTH 7 +#define HYPER_MBA0_MBA0_MASK 0x7f000000 + +// Memory Base Address for both RAM and FLASH bitfield. The base address of addressable region to each memory is set up. Since register can be set in 16M bytes boundary, lower 24 bit is fixed to 0. MBA0 can be greater than MBA1, the chip select which decided by the relationship among MBA0, MBA1, and EXT_ADDR. - MBA0 < MBA1, if (MBA1 <= EXT_ADDR) CSn1 = 0; else CSn0 = 0; - MBA0 > MBA1, if (MBA0 <= EXT_ADDR) CSn0 = 0; else CSn1 = 0; (access: R/W) +#define HYPER_MBA1_MBA1_BIT 24 +#define HYPER_MBA1_MBA1_WIDTH 7 +#define HYPER_MBA1_MBA1_MASK 0x7f000000 + +// Device type : - 1'b00: Octo/ Single SPI - 1'b01: HYPERBUS (access: R/W) +#define HYPER_DEVICE_TYPE_BIT 0 +#define HYPER_DEVICE_TYPE_WIDTH 1 +#define HYPER_DEVICE_TYPE_MASK 0x1 + +// When in HYPERBUS mode : - 1'b0: HYPERRAM - 1'b1: HYPERLASH (access: R/W) +#define HYPER_DEVICE_DT0_BIT 1 +#define HYPER_DEVICE_DT0_WIDTH 1 +#define HYPER_DEVICE_DT0_MASK 0x2 + +// When in HYPERBUS mode : - 1'b0: HYPERRAM - 1'b1: HYPERLASH (access: R/W) +#define HYPER_DEVICE_DT1_BIT 2 +#define HYPER_DEVICE_DT1_WIDTH 1 +#define HYPER_DEVICE_DT1_MASK 0x4 + +// Octo SPI command size : - 2b0: 0 byte - 2'b1: 1 byte - 2'b2: 2 byte (access: R/W) +#define HYPER_OSPI_CFG_CMD_SIZE_BIT 0 +#define HYPER_OSPI_CFG_CMD_SIZE_WIDTH 2 +#define HYPER_OSPI_CFG_CMD_SIZE_MASK 0x3 + +// Octo SPI address size : - 3'b000: 0 byte (Jump ADDRESS stage) - 3'b001: 1 byte - 3'b010: 2 byte - 3'b011: 3 byte - 3'b100: 4 byte (access: R/W) +#define HYPER_OSPI_CFG_ADDR_SIZE_BIT 4 +#define HYPER_OSPI_CFG_ADDR_SIZE_WIDTH 3 +#define HYPER_OSPI_CFG_ADDR_SIZE_MASK 0x70 + +// Octo SPI line number for Single SPI or Octo SPI: - 1'b0: 8 line for Octo SPI - 1'b1: 1 line for Single SPI (SI : dq[0] SO: dq[1]) (access: R/W) +#define HYPER_OSPI_CFG_LINE_BIT 8 +#define HYPER_OSPI_CFG_LINE_WIDTH 1 +#define HYPER_OSPI_CFG_LINE_MASK 0x100 + +// Octo SPI command ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode (access: R/W) +#define HYPER_OSPI_CFG_CMD_DTR_STR_BIT 12 +#define HYPER_OSPI_CFG_CMD_DTR_STR_WIDTH 1 +#define HYPER_OSPI_CFG_CMD_DTR_STR_MASK 0x1000 + +// Octo SPI address ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode (access: R/W) +#define HYPER_OSPI_CFG_ADDR_DTR_STR_BIT 13 +#define HYPER_OSPI_CFG_ADDR_DTR_STR_WIDTH 1 +#define HYPER_OSPI_CFG_ADDR_DTR_STR_MASK 0x2000 + +// Octo SPI data ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode (access: R/W) +#define HYPER_OSPI_CFG_DATA_DTR_STR_BIT 14 +#define HYPER_OSPI_CFG_DATA_DTR_STR_WIDTH 1 +#define HYPER_OSPI_CFG_DATA_DTR_STR_MASK 0x4000 + +// Octo SPI data ddr mode data MSB: - 1'b0: LSB - 1'b1: MSB (access: R/W) +#define HYPER_OSPI_CFG_DATA_DTR_MSB_BIT 15 +#define HYPER_OSPI_CFG_DATA_DTR_MSB_WIDTH 1 +#define HYPER_OSPI_CFG_DATA_DTR_MSB_MASK 0x8000 + +// Octo SPI chip select index : - 1'b0: CSN0 - 1'b1: CSN1 (access: R/W) +#define HYPER_OSPI_CSN_INDEX_BIT 0 +#define HYPER_OSPI_CSN_INDEX_WIDTH 1 +#define HYPER_OSPI_CSN_INDEX_MASK 0x1 + +// Octo SPI chip select controlled by user : - 1'b0: IP control CSN - 1'b1: USER control CSN (access: R/W) +#define HYPER_OSPI_CSN_USER_CTRL_CSN_BIT 4 +#define HYPER_OSPI_CSN_USER_CTRL_CSN_WIDTH 1 +#define HYPER_OSPI_CSN_USER_CTRL_CSN_MASK 0x10 + +// Octo SPI chip select user control value : - 1'b0: CSN low - 1'b1: CSN high (access: R/W) +#define HYPER_OSPI_CSN_CSN_VAL_BIT 5 +#define HYPER_OSPI_CSN_CSN_VAL_WIDTH 1 +#define HYPER_OSPI_CSN_CSN_VAL_MASK 0x20 + +// Octo SPI interrupt enable control : - 1'b0: interrupt disable - 1'b1: Interrupt enable (access: R/W) +#define HYPER_IRQ_EN_EN_BIT 0 +#define HYPER_IRQ_EN_EN_WIDTH 1 +#define HYPER_IRQ_EN_EN_MASK 0x1 + +// Clock divide data, form 0 255, frequency divide table is : -8h0 IO_FREQUENCY / 1 -8h1 IO_FREQUENCY / 2 -8h2 IO_FREQUENCY / 4 (access: R/W) +#define HYPER_CLK_DIV_DATA_BIT 0 +#define HYPER_CLK_DIV_DATA_WIDTH 8 +#define HYPER_CLK_DIV_DATA_MASK 0xff + +// Clock divide valid, user can not control. Every time there is clock divide write access, set 1 by default, then when clock divide is finished, set 0. (access: W) +#define HYPER_CLK_DIV_VALID_BIT 8 +#define HYPER_CLK_DIV_VALID_WIDTH 1 +#define HYPER_CLK_DIV_VALID_MASK 0x100 + +// TX transfer error because of tcsm, write 1 to clear: - 1'b0: no error - 1'b1: error (access: R/W) +#define HYPER_STATUS_TX_ERROR_BIT 0 +#define HYPER_STATUS_TX_ERROR_WIDTH 1 +#define HYPER_STATUS_TX_ERROR_MASK 0x1 + +// RX transfer error because of tcsm, write 1 to clear: - 1'b0: no error - 1'b1: error (access: R/W) +#define HYPER_STATUS_RX_ERROR_BIT 1 +#define HYPER_STATUS_RX_ERROR_WIDTH 1 +#define HYPER_STATUS_RX_ERROR_MASK 0x2 + +// RX TX transfer end flag, can be polling by user, write 1 to clear: - 1'b0: not end - 1'b1: end (access: R/W) +#define HYPER_STATUS_RX_TX_END_BIT 2 +#define HYPER_STATUS_RX_TX_END_WIDTH 1 +#define HYPER_STATUS_RX_TX_END_MASK 0x4 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rx_saddr :16; // RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address + }; + unsigned int raw; +} __attribute__((packed)) hyper_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) hyper_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int pending :1 ; // RX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue + unsigned int clr :1 ; // RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear the on-going transfer + }; + unsigned int raw; +} __attribute__((packed)) hyper_rx_cfg_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address + }; + unsigned int raw; +} __attribute__((packed)) hyper_tx_saddr_t; + +typedef union { + struct { + unsigned int tx_size :17; // TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) hyper_tx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int pending :1 ; // TX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue + unsigned int clr :1 ; // TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear the on-going transfer + }; + unsigned int raw; +} __attribute__((packed)) hyper_tx_cfg_t; + +typedef union { + struct { + unsigned int saddr :31; // Memory access address bitfield. + unsigned int reg_access :1 ; // Register access flag bitfield. + }; + unsigned int raw; +} __attribute__((packed)) hyper_ext_addr_t; + +typedef union { + struct { + unsigned int latency0 :5 ; // Latency Cycle value for both HyperRAM and HyperFLASH for chip select 0. When using HyperRAM memory, this bit should be set to the same value as the read latency in configuration register of HyperRAM memory the read latency in configuration register of HyperRAM memory. For SPI, is the dummy cycle after ADDRESS stage : - 4'b0000: 16 CK - 4'b0001: 1 CK - 4'b0001: 2 CK ... - 4'b1111: 15 CK + unsigned int latency1 :5 ; // Latency Cycle value for both HyperRAM and HyperFLASH for chip select 1. When using HyperRAM memory, this bit should be set to the same value as the read latency in configuration register of HyperRAM memory the read latency in configuration register of HyperRAM memory. For SPI, is the dummy cycle after ADDRESS stage : - 5'b00000: 0 CK - 5'b00001: 1 CK - 5'b000001: 2 CK ... - 5'b11111: 31 CK + unsigned int rw_recovery :4 ; // Some HyperBus devices may require a minimum time between the end of a prior transaction and the start of a new access. This time is referred to as Read-Write-Recovery time (tRWR). The master interface must start driving CS# Low only at a time when the CA1 transfer will complete after tRWR is satisfied. - 5'b00000: 0 CK - 5'b00001: 1 CK - 5'b000001: 2 CK ... - 5'b11111: 31 CK + unsigned int rwds_delay :3 ; // Delay of RWDS for center aligned read: - 3'b000: 0 logic delay - 3'b001: 1 logic delay - 3'b010: 2 logic delay - 3'b111: 7 logic delay + unsigned int additional_latency_autocheck_en:1 ; // Auto check for RWDS high or low for additional latency : - 1'b0: additional latency no autocheck - 1'b1: additional latency autocheck + unsigned int cs_max :16; // Maximum chip select low time for self-refresh HYPERRAM to valid the data transfer : - 14'h0000: 1 CK - 14'h0001: 2 CK - 14'h0011: 3 CK - - 14'h3FFF: 16383 CK + }; + unsigned int raw; +} __attribute__((packed)) hyper_timing_cfg_t; + +typedef union { + struct { + unsigned int padding0:24; + unsigned int mba0 :7 ; // Memory Base Address 0 for both RAM and FLASH bitfield. The base address of addressable region to each memory is set up. Since register can be set in 16M bytes boundary, lower 24 bit is fixed to 0. MBA0 can be greater than MBA1, the chip select which decided by the relationship among MBA0, MBA1, and EXT_ADDR. - MBA0 < MBA1, if (MBA1 <= EXT_ADDR) CS1 = 0; else CS0 = 0; - MBA0 > MBA1, if (MBA0 <= EXT_ADDR) CS0 = 0; else CS1 = 0; + }; + unsigned int raw; +} __attribute__((packed)) hyper_mba0_t; + +typedef union { + struct { + unsigned int padding0:24; + unsigned int mba1 :7 ; // Memory Base Address for both RAM and FLASH bitfield. The base address of addressable region to each memory is set up. Since register can be set in 16M bytes boundary, lower 24 bit is fixed to 0. MBA0 can be greater than MBA1, the chip select which decided by the relationship among MBA0, MBA1, and EXT_ADDR. - MBA0 < MBA1, if (MBA1 <= EXT_ADDR) CSn1 = 0; else CSn0 = 0; - MBA0 > MBA1, if (MBA0 <= EXT_ADDR) CSn0 = 0; else CSn1 = 0; + }; + unsigned int raw; +} __attribute__((packed)) hyper_mba1_t; + +typedef union { + struct { + unsigned int type :1 ; // Device type : - 1'b00: Octo/ Single SPI - 1'b01: HYPERBUS + unsigned int dt0 :1 ; // When in HYPERBUS mode : - 1'b0: HYPERRAM - 1'b1: HYPERLASH + unsigned int dt1 :1 ; // When in HYPERBUS mode : - 1'b0: HYPERRAM - 1'b1: HYPERLASH + }; + unsigned int raw; +} __attribute__((packed)) hyper_device_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hyper_ospi_cmd_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hyper_ospi_addr_t; + +typedef union { + struct { + unsigned int cmd_size :2 ; // Octo SPI command size : - 2b0: 0 byte - 2'b1: 1 byte - 2'b2: 2 byte + unsigned int padding0:2 ; + unsigned int addr_size :3 ; // Octo SPI address size : - 3'b000: 0 byte (Jump ADDRESS stage) - 3'b001: 1 byte - 3'b010: 2 byte - 3'b011: 3 byte - 3'b100: 4 byte + unsigned int padding1:1 ; + unsigned int line :1 ; // Octo SPI line number for Single SPI or Octo SPI: - 1'b0: 8 line for Octo SPI - 1'b1: 1 line for Single SPI (SI : dq[0] SO: dq[1]) + unsigned int padding2:3 ; + unsigned int cmd_dtr_str :1 ; // Octo SPI command ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode + unsigned int addr_dtr_str :1 ; // Octo SPI address ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode + unsigned int data_dtr_str :1 ; // Octo SPI data ddr mode or single mode : - 1'b0: DTR mode - 1'b1: STR mode + unsigned int data_dtr_msb :1 ; // Octo SPI data ddr mode data MSB: - 1'b0: LSB - 1'b1: MSB + }; + unsigned int raw; +} __attribute__((packed)) hyper_ospi_cfg_t; + +typedef union { + struct { + unsigned int index :1 ; // Octo SPI chip select index : - 1'b0: CSN0 - 1'b1: CSN1 + unsigned int padding0:3 ; + unsigned int user_ctrl_csn :1 ; // Octo SPI chip select controlled by user : - 1'b0: IP control CSN - 1'b1: USER control CSN + unsigned int csn_val :1 ; // Octo SPI chip select user control value : - 1'b0: CSN low - 1'b1: CSN high + }; + unsigned int raw; +} __attribute__((packed)) hyper_ospi_csn_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hyper__reserved0_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) hyper__reserved1_t; + +typedef union { + struct { + unsigned int en :1 ; // Octo SPI interrupt enable control : - 1'b0: interrupt disable - 1'b1: Interrupt enable + }; + unsigned int raw; +} __attribute__((packed)) hyper_irq_en_t; + +typedef union { + struct { + unsigned int data :8 ; // Clock divide data, form 0 255, frequency divide table is : -8h0 IO_FREQUENCY / 1 -8h1 IO_FREQUENCY / 2 -8h2 IO_FREQUENCY / 4 + unsigned int valid :1 ; // Clock divide valid, user can not control. Every time there is clock divide write access, set 1 by default, then when clock divide is finished, set 0. + }; + unsigned int raw; +} __attribute__((packed)) hyper_clk_div_t; + +typedef union { + struct { + unsigned int tx_error :1 ; // TX transfer error because of tcsm, write 1 to clear: - 1'b0: no error - 1'b1: error + unsigned int rx_error :1 ; // RX transfer error because of tcsm, write 1 to clear: - 1'b0: no error - 1'b1: error + unsigned int rx_tx_end :1 ; // RX TX transfer end flag, can be polling by user, write 1 to clear: - 1'b0: not end - 1'b1: end + }; + unsigned int raw; +} __attribute__((packed)) hyper_status_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_hyper_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, HYPER_RX_SADDR_RX_SADDR_BIT, HYPER_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(HYPER_RX_SADDR_RX_SADDR_BIT, HYPER_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_hyper_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, HYPER_RX_SIZE_RX_SIZE_BIT, HYPER_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(HYPER_RX_SIZE_RX_SIZE_BIT, HYPER_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_hyper_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, HYPER_RX_CFG_CONTINOUS_BIT, HYPER_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(HYPER_RX_CFG_CONTINOUS_BIT, HYPER_RX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, HYPER_RX_CFG_EN_BIT, HYPER_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(HYPER_RX_CFG_EN_BIT, HYPER_RX_CFG_EN_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, HYPER_RX_CFG_PENDING_BIT, HYPER_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(HYPER_RX_CFG_PENDING_BIT, HYPER_RX_CFG_PENDING_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, HYPER_RX_CFG_CLR_BIT, HYPER_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(HYPER_RX_CFG_CLR_BIT, HYPER_RX_CFG_CLR_WIDTH); } +}; + +class vp_hyper_tx_saddr : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, HYPER_TX_SADDR_TX_SADDR_BIT, HYPER_TX_SADDR_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(HYPER_TX_SADDR_TX_SADDR_BIT, HYPER_TX_SADDR_TX_SADDR_WIDTH); } +}; + +class vp_hyper_tx_size : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, HYPER_TX_SIZE_TX_SIZE_BIT, HYPER_TX_SIZE_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(HYPER_TX_SIZE_TX_SIZE_BIT, HYPER_TX_SIZE_TX_SIZE_WIDTH); } +}; + +class vp_hyper_tx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, HYPER_TX_CFG_CONTINOUS_BIT, HYPER_TX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(HYPER_TX_CFG_CONTINOUS_BIT, HYPER_TX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, HYPER_TX_CFG_EN_BIT, HYPER_TX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(HYPER_TX_CFG_EN_BIT, HYPER_TX_CFG_EN_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, HYPER_TX_CFG_PENDING_BIT, HYPER_TX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(HYPER_TX_CFG_PENDING_BIT, HYPER_TX_CFG_PENDING_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, HYPER_TX_CFG_CLR_BIT, HYPER_TX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(HYPER_TX_CFG_CLR_BIT, HYPER_TX_CFG_CLR_WIDTH); } +}; + +class vp_hyper_ext_addr : public vp::reg_32 +{ +public: + inline void saddr_set(uint32_t value) { this->set_field(value, HYPER_EXT_ADDR_SADDR_BIT, HYPER_EXT_ADDR_SADDR_WIDTH); } + inline uint32_t saddr_get() { return this->get_field(HYPER_EXT_ADDR_SADDR_BIT, HYPER_EXT_ADDR_SADDR_WIDTH); } + inline void reg_access_set(uint32_t value) { this->set_field(value, HYPER_EXT_ADDR_REG_ACCESS_BIT, HYPER_EXT_ADDR_REG_ACCESS_WIDTH); } + inline uint32_t reg_access_get() { return this->get_field(HYPER_EXT_ADDR_REG_ACCESS_BIT, HYPER_EXT_ADDR_REG_ACCESS_WIDTH); } +}; + +class vp_hyper_timing_cfg : public vp::reg_32 +{ +public: + inline void latency0_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_LATENCY0_BIT, HYPER_TIMING_CFG_LATENCY0_WIDTH); } + inline uint32_t latency0_get() { return this->get_field(HYPER_TIMING_CFG_LATENCY0_BIT, HYPER_TIMING_CFG_LATENCY0_WIDTH); } + inline void latency1_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_LATENCY1_BIT, HYPER_TIMING_CFG_LATENCY1_WIDTH); } + inline uint32_t latency1_get() { return this->get_field(HYPER_TIMING_CFG_LATENCY1_BIT, HYPER_TIMING_CFG_LATENCY1_WIDTH); } + inline void rw_recovery_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_RW_RECOVERY_BIT, HYPER_TIMING_CFG_RW_RECOVERY_WIDTH); } + inline uint32_t rw_recovery_get() { return this->get_field(HYPER_TIMING_CFG_RW_RECOVERY_BIT, HYPER_TIMING_CFG_RW_RECOVERY_WIDTH); } + inline void rwds_delay_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_RWDS_DELAY_BIT, HYPER_TIMING_CFG_RWDS_DELAY_WIDTH); } + inline uint32_t rwds_delay_get() { return this->get_field(HYPER_TIMING_CFG_RWDS_DELAY_BIT, HYPER_TIMING_CFG_RWDS_DELAY_WIDTH); } + inline void additional_latency_autocheck_en_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_BIT, HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_WIDTH); } + inline uint32_t additional_latency_autocheck_en_get() { return this->get_field(HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_BIT, HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_WIDTH); } + inline void cs_max_set(uint32_t value) { this->set_field(value, HYPER_TIMING_CFG_CS_MAX_BIT, HYPER_TIMING_CFG_CS_MAX_WIDTH); } + inline uint32_t cs_max_get() { return this->get_field(HYPER_TIMING_CFG_CS_MAX_BIT, HYPER_TIMING_CFG_CS_MAX_WIDTH); } +}; + +class vp_hyper_mba0 : public vp::reg_32 +{ +public: + inline void mba0_set(uint32_t value) { this->set_field(value, HYPER_MBA0_MBA0_BIT, HYPER_MBA0_MBA0_WIDTH); } + inline uint32_t mba0_get() { return this->get_field(HYPER_MBA0_MBA0_BIT, HYPER_MBA0_MBA0_WIDTH); } +}; + +class vp_hyper_mba1 : public vp::reg_32 +{ +public: + inline void mba1_set(uint32_t value) { this->set_field(value, HYPER_MBA1_MBA1_BIT, HYPER_MBA1_MBA1_WIDTH); } + inline uint32_t mba1_get() { return this->get_field(HYPER_MBA1_MBA1_BIT, HYPER_MBA1_MBA1_WIDTH); } +}; + +class vp_hyper_device : public vp::reg_32 +{ +public: + inline void type_set(uint32_t value) { this->set_field(value, HYPER_DEVICE_TYPE_BIT, HYPER_DEVICE_TYPE_WIDTH); } + inline uint32_t type_get() { return this->get_field(HYPER_DEVICE_TYPE_BIT, HYPER_DEVICE_TYPE_WIDTH); } + inline void dt0_set(uint32_t value) { this->set_field(value, HYPER_DEVICE_DT0_BIT, HYPER_DEVICE_DT0_WIDTH); } + inline uint32_t dt0_get() { return this->get_field(HYPER_DEVICE_DT0_BIT, HYPER_DEVICE_DT0_WIDTH); } + inline void dt1_set(uint32_t value) { this->set_field(value, HYPER_DEVICE_DT1_BIT, HYPER_DEVICE_DT1_WIDTH); } + inline uint32_t dt1_get() { return this->get_field(HYPER_DEVICE_DT1_BIT, HYPER_DEVICE_DT1_WIDTH); } +}; + +class vp_hyper_ospi_cmd : public vp::reg_16 +{ +public: +}; + +class vp_hyper_ospi_addr : public vp::reg_32 +{ +public: +}; + +class vp_hyper_ospi_cfg : public vp::reg_32 +{ +public: + inline void cmd_size_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_CMD_SIZE_BIT, HYPER_OSPI_CFG_CMD_SIZE_WIDTH); } + inline uint32_t cmd_size_get() { return this->get_field(HYPER_OSPI_CFG_CMD_SIZE_BIT, HYPER_OSPI_CFG_CMD_SIZE_WIDTH); } + inline void addr_size_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_ADDR_SIZE_BIT, HYPER_OSPI_CFG_ADDR_SIZE_WIDTH); } + inline uint32_t addr_size_get() { return this->get_field(HYPER_OSPI_CFG_ADDR_SIZE_BIT, HYPER_OSPI_CFG_ADDR_SIZE_WIDTH); } + inline void line_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_LINE_BIT, HYPER_OSPI_CFG_LINE_WIDTH); } + inline uint32_t line_get() { return this->get_field(HYPER_OSPI_CFG_LINE_BIT, HYPER_OSPI_CFG_LINE_WIDTH); } + inline void cmd_dtr_str_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_CMD_DTR_STR_BIT, HYPER_OSPI_CFG_CMD_DTR_STR_WIDTH); } + inline uint32_t cmd_dtr_str_get() { return this->get_field(HYPER_OSPI_CFG_CMD_DTR_STR_BIT, HYPER_OSPI_CFG_CMD_DTR_STR_WIDTH); } + inline void addr_dtr_str_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_ADDR_DTR_STR_BIT, HYPER_OSPI_CFG_ADDR_DTR_STR_WIDTH); } + inline uint32_t addr_dtr_str_get() { return this->get_field(HYPER_OSPI_CFG_ADDR_DTR_STR_BIT, HYPER_OSPI_CFG_ADDR_DTR_STR_WIDTH); } + inline void data_dtr_str_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_DATA_DTR_STR_BIT, HYPER_OSPI_CFG_DATA_DTR_STR_WIDTH); } + inline uint32_t data_dtr_str_get() { return this->get_field(HYPER_OSPI_CFG_DATA_DTR_STR_BIT, HYPER_OSPI_CFG_DATA_DTR_STR_WIDTH); } + inline void data_dtr_msb_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CFG_DATA_DTR_MSB_BIT, HYPER_OSPI_CFG_DATA_DTR_MSB_WIDTH); } + inline uint32_t data_dtr_msb_get() { return this->get_field(HYPER_OSPI_CFG_DATA_DTR_MSB_BIT, HYPER_OSPI_CFG_DATA_DTR_MSB_WIDTH); } +}; + +class vp_hyper_ospi_csn : public vp::reg_32 +{ +public: + inline void index_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CSN_INDEX_BIT, HYPER_OSPI_CSN_INDEX_WIDTH); } + inline uint32_t index_get() { return this->get_field(HYPER_OSPI_CSN_INDEX_BIT, HYPER_OSPI_CSN_INDEX_WIDTH); } + inline void user_ctrl_csn_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CSN_USER_CTRL_CSN_BIT, HYPER_OSPI_CSN_USER_CTRL_CSN_WIDTH); } + inline uint32_t user_ctrl_csn_get() { return this->get_field(HYPER_OSPI_CSN_USER_CTRL_CSN_BIT, HYPER_OSPI_CSN_USER_CTRL_CSN_WIDTH); } + inline void csn_val_set(uint32_t value) { this->set_field(value, HYPER_OSPI_CSN_CSN_VAL_BIT, HYPER_OSPI_CSN_CSN_VAL_WIDTH); } + inline uint32_t csn_val_get() { return this->get_field(HYPER_OSPI_CSN_CSN_VAL_BIT, HYPER_OSPI_CSN_CSN_VAL_WIDTH); } +}; + +class vp_hyper__reserved0 : public vp::reg_32 +{ +public: +}; + +class vp_hyper__reserved1 : public vp::reg_32 +{ +public: +}; + +class vp_hyper_irq_en : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, HYPER_IRQ_EN_EN_BIT, HYPER_IRQ_EN_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(HYPER_IRQ_EN_EN_BIT, HYPER_IRQ_EN_EN_WIDTH); } +}; + +class vp_hyper_clk_div : public vp::reg_32 +{ +public: + inline void data_set(uint32_t value) { this->set_field(value, HYPER_CLK_DIV_DATA_BIT, HYPER_CLK_DIV_DATA_WIDTH); } + inline uint32_t data_get() { return this->get_field(HYPER_CLK_DIV_DATA_BIT, HYPER_CLK_DIV_DATA_WIDTH); } + inline void valid_set(uint32_t value) { this->set_field(value, HYPER_CLK_DIV_VALID_BIT, HYPER_CLK_DIV_VALID_WIDTH); } + inline uint32_t valid_get() { return this->get_field(HYPER_CLK_DIV_VALID_BIT, HYPER_CLK_DIV_VALID_WIDTH); } +}; + +class vp_hyper_status : public vp::reg_32 +{ +public: + inline void tx_error_set(uint32_t value) { this->set_field(value, HYPER_STATUS_TX_ERROR_BIT, HYPER_STATUS_TX_ERROR_WIDTH); } + inline uint32_t tx_error_get() { return this->get_field(HYPER_STATUS_TX_ERROR_BIT, HYPER_STATUS_TX_ERROR_WIDTH); } + inline void rx_error_set(uint32_t value) { this->set_field(value, HYPER_STATUS_RX_ERROR_BIT, HYPER_STATUS_RX_ERROR_WIDTH); } + inline uint32_t rx_error_get() { return this->get_field(HYPER_STATUS_RX_ERROR_BIT, HYPER_STATUS_RX_ERROR_WIDTH); } + inline void rx_tx_end_set(uint32_t value) { this->set_field(value, HYPER_STATUS_RX_TX_END_BIT, HYPER_STATUS_RX_TX_END_WIDTH); } + inline uint32_t rx_tx_end_get() { return this->get_field(HYPER_STATUS_RX_TX_END_BIT, HYPER_STATUS_RX_TX_END_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int rx_saddr ; // uDMA RX HYPERBUS buffer base address configuration register. + unsigned int rx_size ; // uDMA RX HYPERBUS buffer size configuration register. + unsigned int rx_cfg ; // uDMA RX HYPERBUS stream configuration register. + unsigned int tx_saddr ; // uDMA TX HYPERBUS buffer base address configuration register. + unsigned int tx_size ; // uDMA TX HYPERBUS buffer size configuration register. + unsigned int tx_cfg ; // uDMA TX HYPERBUS stream configuration register. + unsigned int ext_addr ; // Memory access address register. + unsigned int timing_cfg ; // HYPERBUS and Octo SPI Memory Timing configuration register. + unsigned int mba0 ; // Device start address register. + unsigned int mba1 ; // Device start address register. + unsigned int device ; // Device type register(RAM or FLASH). + unsigned int ospi_cmd ; // OSPI command + unsigned int ospi_addr ; // OSPI address + unsigned int ospi_cfg ; // OSPI configuration + unsigned int ospi_csn ; // OSPI chip select configuration + unsigned int _reserved0 ; // - + unsigned int _reserved1 ; // - + unsigned int irq_en ; // OSPI interrupt enable register + unsigned int clk_div ; // Clock divide. + unsigned int status ; // Transfer status for error. +} __attribute__((packed)) hyper_hyper_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t hyper_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, HYPER_RX_SADDR_OFFSET); } +static inline void hyper_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_RX_SADDR_OFFSET, value); } + +static inline uint32_t hyper_rx_size_get(uint32_t base) { return ARCHI_READ(base, HYPER_RX_SIZE_OFFSET); } +static inline void hyper_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_RX_SIZE_OFFSET, value); } + +static inline uint32_t hyper_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, HYPER_RX_CFG_OFFSET); } +static inline void hyper_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_RX_CFG_OFFSET, value); } + +static inline uint32_t hyper_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, HYPER_TX_SADDR_OFFSET); } +static inline void hyper_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_TX_SADDR_OFFSET, value); } + +static inline uint32_t hyper_tx_size_get(uint32_t base) { return ARCHI_READ(base, HYPER_TX_SIZE_OFFSET); } +static inline void hyper_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_TX_SIZE_OFFSET, value); } + +static inline uint32_t hyper_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, HYPER_TX_CFG_OFFSET); } +static inline void hyper_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_TX_CFG_OFFSET, value); } + +static inline uint32_t hyper_ext_addr_get(uint32_t base) { return ARCHI_READ(base, HYPER_EXT_ADDR_OFFSET); } +static inline void hyper_ext_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_EXT_ADDR_OFFSET, value); } + +static inline uint32_t hyper_timing_cfg_get(uint32_t base) { return ARCHI_READ(base, HYPER_TIMING_CFG_OFFSET); } +static inline void hyper_timing_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_TIMING_CFG_OFFSET, value); } + +static inline uint32_t hyper_mba0_get(uint32_t base) { return ARCHI_READ(base, HYPER_MBA0_OFFSET); } +static inline void hyper_mba0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_MBA0_OFFSET, value); } + +static inline uint32_t hyper_mba1_get(uint32_t base) { return ARCHI_READ(base, HYPER_MBA1_OFFSET); } +static inline void hyper_mba1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_MBA1_OFFSET, value); } + +static inline uint32_t hyper_device_get(uint32_t base) { return ARCHI_READ(base, HYPER_DEVICE_OFFSET); } +static inline void hyper_device_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_DEVICE_OFFSET, value); } + +static inline uint32_t hyper_ospi_cmd_get(uint32_t base) { return ARCHI_READ(base, HYPER_OSPI_CMD_OFFSET); } +static inline void hyper_ospi_cmd_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_OSPI_CMD_OFFSET, value); } + +static inline uint32_t hyper_ospi_addr_get(uint32_t base) { return ARCHI_READ(base, HYPER_OSPI_ADDR_OFFSET); } +static inline void hyper_ospi_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_OSPI_ADDR_OFFSET, value); } + +static inline uint32_t hyper_ospi_cfg_get(uint32_t base) { return ARCHI_READ(base, HYPER_OSPI_CFG_OFFSET); } +static inline void hyper_ospi_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_OSPI_CFG_OFFSET, value); } + +static inline uint32_t hyper_ospi_csn_get(uint32_t base) { return ARCHI_READ(base, HYPER_OSPI_CSN_OFFSET); } +static inline void hyper_ospi_csn_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_OSPI_CSN_OFFSET, value); } + +static inline uint32_t hyper__reserved0_get(uint32_t base) { return ARCHI_READ(base, HYPER__RESERVED0_OFFSET); } +static inline void hyper__reserved0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER__RESERVED0_OFFSET, value); } + +static inline uint32_t hyper__reserved1_get(uint32_t base) { return ARCHI_READ(base, HYPER__RESERVED1_OFFSET); } +static inline void hyper__reserved1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER__RESERVED1_OFFSET, value); } + +static inline uint32_t hyper_irq_en_get(uint32_t base) { return ARCHI_READ(base, HYPER_IRQ_EN_OFFSET); } +static inline void hyper_irq_en_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_IRQ_EN_OFFSET, value); } + +static inline uint32_t hyper_clk_div_get(uint32_t base) { return ARCHI_READ(base, HYPER_CLK_DIV_OFFSET); } +static inline void hyper_clk_div_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_CLK_DIV_OFFSET, value); } + +static inline uint32_t hyper_status_get(uint32_t base) { return ARCHI_READ(base, HYPER_STATUS_OFFSET); } +static inline void hyper_status_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, HYPER_STATUS_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define HYPER_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HYPER_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HYPER_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HYPER_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define HYPER_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define HYPER_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define HYPER_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define HYPER_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define HYPER_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define HYPER_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define HYPER_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define HYPER_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define HYPER_RX_CFG_EN(val) ((val) << 4) + +#define HYPER_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define HYPER_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define HYPER_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define HYPER_RX_CFG_PENDING(val) ((val) << 5) + +#define HYPER_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define HYPER_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define HYPER_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define HYPER_RX_CFG_CLR(val) ((val) << 6) + +#define HYPER_TX_SADDR_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define HYPER_TX_SADDR_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define HYPER_TX_SADDR_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define HYPER_TX_SADDR_TX_SADDR(val) ((val) << 0) + +#define HYPER_TX_SIZE_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define HYPER_TX_SIZE_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define HYPER_TX_SIZE_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define HYPER_TX_SIZE_TX_SIZE(val) ((val) << 0) + +#define HYPER_TX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_TX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_TX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_TX_CFG_CONTINOUS(val) ((val) << 0) + +#define HYPER_TX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define HYPER_TX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define HYPER_TX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define HYPER_TX_CFG_EN(val) ((val) << 4) + +#define HYPER_TX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define HYPER_TX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define HYPER_TX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define HYPER_TX_CFG_PENDING(val) ((val) << 5) + +#define HYPER_TX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define HYPER_TX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define HYPER_TX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define HYPER_TX_CFG_CLR(val) ((val) << 6) + +#define HYPER_EXT_ADDR_SADDR_GET(value) (ARCHI_BEXTRACTU((value),31,0)) +#define HYPER_EXT_ADDR_SADDR_GETS(value) (ARCHI_BEXTRACT((value),31,0)) +#define HYPER_EXT_ADDR_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),31,0)) +#define HYPER_EXT_ADDR_SADDR(val) ((val) << 0) + +#define HYPER_EXT_ADDR_REG_ACCESS_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define HYPER_EXT_ADDR_REG_ACCESS_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define HYPER_EXT_ADDR_REG_ACCESS_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define HYPER_EXT_ADDR_REG_ACCESS(val) ((val) << 31) + +#define HYPER_TIMING_CFG_LATENCY0_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define HYPER_TIMING_CFG_LATENCY0_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define HYPER_TIMING_CFG_LATENCY0_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define HYPER_TIMING_CFG_LATENCY0(val) ((val) << 0) + +#define HYPER_TIMING_CFG_LATENCY1_GET(value) (ARCHI_BEXTRACTU((value),5,5)) +#define HYPER_TIMING_CFG_LATENCY1_GETS(value) (ARCHI_BEXTRACT((value),5,5)) +#define HYPER_TIMING_CFG_LATENCY1_SET(value,field) (ARCHI_BINSERT((value),(field),5,5)) +#define HYPER_TIMING_CFG_LATENCY1(val) ((val) << 5) + +#define HYPER_TIMING_CFG_RW_RECOVERY_GET(value) (ARCHI_BEXTRACTU((value),4,10)) +#define HYPER_TIMING_CFG_RW_RECOVERY_GETS(value) (ARCHI_BEXTRACT((value),4,10)) +#define HYPER_TIMING_CFG_RW_RECOVERY_SET(value,field) (ARCHI_BINSERT((value),(field),4,10)) +#define HYPER_TIMING_CFG_RW_RECOVERY(val) ((val) << 10) + +#define HYPER_TIMING_CFG_RWDS_DELAY_GET(value) (ARCHI_BEXTRACTU((value),3,14)) +#define HYPER_TIMING_CFG_RWDS_DELAY_GETS(value) (ARCHI_BEXTRACT((value),3,14)) +#define HYPER_TIMING_CFG_RWDS_DELAY_SET(value,field) (ARCHI_BINSERT((value),(field),3,14)) +#define HYPER_TIMING_CFG_RWDS_DELAY(val) ((val) << 14) + +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define HYPER_TIMING_CFG_ADDITIONAL_LATENCY_AUTOCHECK_EN(val) ((val) << 17) + +#define HYPER_TIMING_CFG_CS_MAX_GET(value) (ARCHI_BEXTRACTU((value),16,18)) +#define HYPER_TIMING_CFG_CS_MAX_GETS(value) (ARCHI_BEXTRACT((value),16,18)) +#define HYPER_TIMING_CFG_CS_MAX_SET(value,field) (ARCHI_BINSERT((value),(field),16,18)) +#define HYPER_TIMING_CFG_CS_MAX(val) ((val) << 18) + +#define HYPER_MBA0_MBA0_GET(value) (ARCHI_BEXTRACTU((value),7,24)) +#define HYPER_MBA0_MBA0_GETS(value) (ARCHI_BEXTRACT((value),7,24)) +#define HYPER_MBA0_MBA0_SET(value,field) (ARCHI_BINSERT((value),(field),7,24)) +#define HYPER_MBA0_MBA0(val) ((val) << 24) + +#define HYPER_MBA1_MBA1_GET(value) (ARCHI_BEXTRACTU((value),7,24)) +#define HYPER_MBA1_MBA1_GETS(value) (ARCHI_BEXTRACT((value),7,24)) +#define HYPER_MBA1_MBA1_SET(value,field) (ARCHI_BINSERT((value),(field),7,24)) +#define HYPER_MBA1_MBA1(val) ((val) << 24) + +#define HYPER_DEVICE_TYPE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_DEVICE_TYPE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_DEVICE_TYPE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_DEVICE_TYPE(val) ((val) << 0) + +#define HYPER_DEVICE_DT0_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define HYPER_DEVICE_DT0_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define HYPER_DEVICE_DT0_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define HYPER_DEVICE_DT0(val) ((val) << 1) + +#define HYPER_DEVICE_DT1_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define HYPER_DEVICE_DT1_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define HYPER_DEVICE_DT1_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define HYPER_DEVICE_DT1(val) ((val) << 2) + +#define HYPER_OSPI_CFG_CMD_SIZE_GET(value) (ARCHI_BEXTRACTU((value),2,0)) +#define HYPER_OSPI_CFG_CMD_SIZE_GETS(value) (ARCHI_BEXTRACT((value),2,0)) +#define HYPER_OSPI_CFG_CMD_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,0)) +#define HYPER_OSPI_CFG_CMD_SIZE(val) ((val) << 0) + +#define HYPER_OSPI_CFG_ADDR_SIZE_GET(value) (ARCHI_BEXTRACTU((value),3,4)) +#define HYPER_OSPI_CFG_ADDR_SIZE_GETS(value) (ARCHI_BEXTRACT((value),3,4)) +#define HYPER_OSPI_CFG_ADDR_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),3,4)) +#define HYPER_OSPI_CFG_ADDR_SIZE(val) ((val) << 4) + +#define HYPER_OSPI_CFG_LINE_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define HYPER_OSPI_CFG_LINE_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define HYPER_OSPI_CFG_LINE_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define HYPER_OSPI_CFG_LINE(val) ((val) << 8) + +#define HYPER_OSPI_CFG_CMD_DTR_STR_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define HYPER_OSPI_CFG_CMD_DTR_STR_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define HYPER_OSPI_CFG_CMD_DTR_STR_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define HYPER_OSPI_CFG_CMD_DTR_STR(val) ((val) << 12) + +#define HYPER_OSPI_CFG_ADDR_DTR_STR_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define HYPER_OSPI_CFG_ADDR_DTR_STR_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define HYPER_OSPI_CFG_ADDR_DTR_STR_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define HYPER_OSPI_CFG_ADDR_DTR_STR(val) ((val) << 13) + +#define HYPER_OSPI_CFG_DATA_DTR_STR_GET(value) (ARCHI_BEXTRACTU((value),1,14)) +#define HYPER_OSPI_CFG_DATA_DTR_STR_GETS(value) (ARCHI_BEXTRACT((value),1,14)) +#define HYPER_OSPI_CFG_DATA_DTR_STR_SET(value,field) (ARCHI_BINSERT((value),(field),1,14)) +#define HYPER_OSPI_CFG_DATA_DTR_STR(val) ((val) << 14) + +#define HYPER_OSPI_CFG_DATA_DTR_MSB_GET(value) (ARCHI_BEXTRACTU((value),1,15)) +#define HYPER_OSPI_CFG_DATA_DTR_MSB_GETS(value) (ARCHI_BEXTRACT((value),1,15)) +#define HYPER_OSPI_CFG_DATA_DTR_MSB_SET(value,field) (ARCHI_BINSERT((value),(field),1,15)) +#define HYPER_OSPI_CFG_DATA_DTR_MSB(val) ((val) << 15) + +#define HYPER_OSPI_CSN_INDEX_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_OSPI_CSN_INDEX_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_OSPI_CSN_INDEX_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_OSPI_CSN_INDEX(val) ((val) << 0) + +#define HYPER_OSPI_CSN_USER_CTRL_CSN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define HYPER_OSPI_CSN_USER_CTRL_CSN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define HYPER_OSPI_CSN_USER_CTRL_CSN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define HYPER_OSPI_CSN_USER_CTRL_CSN(val) ((val) << 4) + +#define HYPER_OSPI_CSN_CSN_VAL_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define HYPER_OSPI_CSN_CSN_VAL_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define HYPER_OSPI_CSN_CSN_VAL_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define HYPER_OSPI_CSN_CSN_VAL(val) ((val) << 5) + +#define HYPER_IRQ_EN_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_IRQ_EN_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_IRQ_EN_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_IRQ_EN_EN(val) ((val) << 0) + +#define HYPER_CLK_DIV_DATA_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define HYPER_CLK_DIV_DATA_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define HYPER_CLK_DIV_DATA_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define HYPER_CLK_DIV_DATA(val) ((val) << 0) + +#define HYPER_CLK_DIV_VALID_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define HYPER_CLK_DIV_VALID_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define HYPER_CLK_DIV_VALID_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define HYPER_CLK_DIV_VALID(val) ((val) << 8) + +#define HYPER_STATUS_TX_ERROR_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define HYPER_STATUS_TX_ERROR_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define HYPER_STATUS_TX_ERROR_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define HYPER_STATUS_TX_ERROR(val) ((val) << 0) + +#define HYPER_STATUS_RX_ERROR_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define HYPER_STATUS_RX_ERROR_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define HYPER_STATUS_RX_ERROR_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define HYPER_STATUS_RX_ERROR(val) ((val) << 1) + +#define HYPER_STATUS_RX_TX_END_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define HYPER_STATUS_RX_TX_END_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define HYPER_STATUS_RX_TX_END_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define HYPER_STATUS_RX_TX_END(val) ((val) << 2) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v1.h b/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v1.h new file mode 100644 index 0000000..ac7b90f --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v1.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_I2C_V1_H__ +#define __ARCHI_UDMA_UDMA_I2C_V1_H__ + +#define ARCHI_I2C_SETUP_OFFSET 0x0 + +#define I2C_CMD_START 0x02 +#define I2C_CMD_STOP 0x04 +#define I2C_CMD_RD_ACK 0x08 +#define I2C_CMD_RD_NACK 0x10 +#define I2C_CMD_WR 0x20 +#define I2C_CMD_WAIT 0x40 +#define I2C_CMD_RPT 0x80 + +#define I2C_CMD_SETUP_ENABLE_BIT 8 +#define I2C_CMD_SETUP_DIV_BIT 16 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v2.h b/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v2.h new file mode 100644 index 0000000..f148255 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2c/udma_i2c_v2.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_I2C_V2_H__ +#define __ARCHI_UDMA_UDMA_I2C_V2_H__ + +// I2C command IDS definition +#define I2C_CMD_OFFSET 4 +#define I2C_CMD_START (0x0 << I2C_CMD_OFFSET) +#define I2C_CMD_STOP (0x2 << I2C_CMD_OFFSET) +#define I2C_CMD_RD_ACK (0x4 << I2C_CMD_OFFSET) +#define I2C_CMD_RD_NACK (0x6 << I2C_CMD_OFFSET) +#define I2C_CMD_WR (0x8 << I2C_CMD_OFFSET) +#define I2C_CMD_WAIT (0xA << I2C_CMD_OFFSET) +#define I2C_CMD_RPT (0xC << I2C_CMD_OFFSET) +#define I2C_CMD_CFG (0xE << I2C_CMD_OFFSET) +#define I2C_CMD_WAIT_EV (0x1 << I2C_CMD_OFFSET) + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1.h new file mode 100644 index 0000000..bbf18e0 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_I2S_V1_H__ +#define __ARCHI_UDMA_UDMA_I2S_V1_H__ + +#include "archi/udma/udma_v2.h" + +#define UDMA_I2S_ADDR(id) (ARCHI_UDMA_ADDR + UDMA_I2S_OFFSET(id)) //FIXME shall be removed because deprecated +#define UDMA_I2S_RX0_ADDR(id) (ARCHI_UDMA_ADDR + UDMA_I2S_OFFSET(id) + UDMA_CHANNEL_RX_OFFSET) +#define UDMA_I2S_RX1_ADDR(id) (ARCHI_UDMA_ADDR + UDMA_I2S_OFFSET(id) + UDMA_CHANNEL_TX_OFFSET) +#define UDMA_I2S_CUSTOM_ADDR(id) (ARCHI_UDMA_ADDR + UDMA_I2S_OFFSET(id) + UDMA_CHANNEL_CUSTOM_OFFSET) + + +#define UDMA_I2S_OFFSET(id) UDMA_PERIPH_OFFSET(ARCHI_UDMA_I2S_ID(id)) + +// I2S custom registers offset definition +#define I2S_EXT_OFFSET (0x00) +#define I2S_CFG_CLKGEN0_OFFSET (0x04) +#define I2S_CFG_CLKGEN1_OFFSET (0x08) +#define I2S_CFG_CLKGEN_OFFSET(clk) (I2S_CFG_CLKGEN0_OFFSET + (clk)*4) +#define I2S_CHMODE_OFFSET (0x0C) +#define I2S_FILT_CH0_OFFSET (0x10) +#define I2S_FILT_CH1_OFFSET (0x14) +#define I2S_FILT_CH_OFFSET(clk) (I2S_FILT_CH0_OFFSET + (clk)*4) + +// I2S custom registers bitfields offset, mask, value definition +#define I2S_EXT_BITS_WORD_OFFSET 0 +#define I2S_EXT_BITS_WORD_WIDTH 5 +#define I2S_EXT_BITS_WORD_MASK (0x1f << I2S_EXT_BITS_WORD_OFFSET) +#define I2S_EXT_BITS_WORD(val) ((val-1) << I2S_EXT_BITS_WORD_OFFSET) + + +#define I2S_CFG_CLKGEN_BITS_WORD_OFFSET 0 +#define I2S_CFG_CLKGEN_BITS_WORD_WIDTH 5 +#define I2S_CFG_CLKGEN_BITS_WORD_MASK (0x1f << I2S_CFG_CLKGEN_BITS_WORD_OFFSET) +#define I2S_CFG_CLKGEN_BITS_WORD(val) ((val-1) << I2S_CFG_CLKGEN_BITS_WORD_OFFSET) + +#define I2S_CFG_CLKGEN_CLK_EN_OFFSET 8 +#define I2S_CFG_CLKGEN_CLK_EN_WIDTH 1 +#define I2S_CFG_CLKGEN_CLK_EN_MASK (0x1 << I2S_CFG_CLKGEN_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN_CLK_EN (1 << I2S_CFG_CLKGEN_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN_CLK_DIS (0 << I2S_CFG_CLKGEN_CLK_EN_OFFSET) + +#define I2S_CFG_CLKGEN_CLKDIV_OFFSET 16 +#define I2S_CFG_CLKGEN_CLKDIV_WIDTH 16 +#define I2S_CFG_CLKGEN_CLKDIV_MASK (0xffff << I2S_CFG_CLKGEN_CLKDIV_OFFSET) +#define I2S_CFG_CLKGEN_CLKDIV(val) (val << I2S_CFG_CLKGEN_CLKDIV_OFFSET) + + +#define I2S_CFG_CLKGEN0_BITS_WORD_OFFSET 0 +#define I2S_CFG_CLKGEN0_BITS_WORD_WIDTH 5 +#define I2S_CFG_CLKGEN0_BITS_WORD_MASK (0x1f << I2S_CFG_CLKGEN0_BITS_WORD_OFFSET) +#define I2S_CFG_CLKGEN0_BITS_WORD(val) ((val-1) << I2S_CFG_CLKGEN0_BITS_WORD_OFFSET) + +#define I2S_CFG_CLKGEN0_CLK_EN_OFFSET 8 +#define I2S_CFG_CLKGEN0_CLK_EN_WIDTH 1 +#define I2S_CFG_CLKGEN0_CLK_EN_MASK (0x1 << I2S_CFG_CLKGEN0_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN0_CLK_EN (1 << I2S_CFG_CLKGEN0_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN0_CLK_DIS (0 << I2S_CFG_CLKGEN0_CLK_EN_OFFSET) + +#define I2S_CFG_CLKGEN0_CLKDIV_OFFSET 16 +#define I2S_CFG_CLKGEN0_CLKDIV_WIDTH 16 +#define I2S_CFG_CLKGEN0_CLKDIV_MASK (0xffff << I2S_CFG_CLKGEN0_CLKDIV_OFFSET) +#define I2S_CFG_CLKGEN0_CLKDIV(val) (val << I2S_CFG_CLKGEN0_CLKDIV_OFFSET) + +#define I2S_CFG_CLKGEN1_BITS_WORD_OFFSET 0 +#define I2S_CFG_CLKGEN1_BITS_WORD_WIDTH 5 +#define I2S_CFG_CLKGEN1_BITS_WORD_MASK (0x1f << I2S_CFG_CLKGEN1_BITS_WORD_OFFSET) +#define I2S_CFG_CLKGEN1_BITS_WORD(val) ((val-1) << I2S_CFG_CLKGEN1_BITS_WORD_OFFSET) + +#define I2S_CFG_CLKGEN1_CLK_EN_OFFSET 8 +#define I2S_CFG_CLKGEN1_CLK_EN_WIDTH 1 +#define I2S_CFG_CLKGEN1_CLK_EN_MASK (0x1 << I2S_CFG_CLKGEN1_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN1_CLK_EN (1 << I2S_CFG_CLKGEN1_CLK_EN_OFFSET) +#define I2S_CFG_CLKGEN1_CLK_DIS (0 << I2S_CFG_CLKGEN1_CLK_EN_OFFSET) + +#define I2S_CFG_CLKGEN1_CLKDIV_OFFSET 16 +#define I2S_CFG_CLKGEN1_CLKDIV_WIDTH 16 +#define I2S_CFG_CLKGEN1_CLKDIV_MASK (0xffff << I2S_CFG_CLKGEN1_CLKDIV_OFFSET) +#define I2S_CFG_CLKGEN1_CLKDIV(val) (val << I2S_CFG_CLKGEN1_CLKDIV_OFFSET) + + + +#define I2S_CHMODE_CH_SNAPCAM_OFFSET(x) (0 + (x)) +#define I2S_CHMODE_CH_SNAPCAM_WIDTH(x) (1) +#define I2S_CHMODE_CH_SNAPCAM_MASK(x) (0x1 << I2S_CHMODE_CH_SNAPCAM_OFFSET(x)) +#define I2S_CHMODE_CH_SNAPCAM_ENA(x) (0x1 << I2S_CHMODE_CH_SNAPCAM_OFFSET(x)) +#define I2S_CHMODE_CH_SNAPCAM_DIS(x) (0x0 << I2S_CHMODE_CH_SNAPCAM_OFFSET(x)) + +#define I2S_CHMODE_CH_LSBFIRST_OFFSET(x) (4 + (x)) +#define I2S_CHMODE_CH_LSBFIRST_WIDTH(x) (1) +#define I2S_CHMODE_CH_LSBFIRST_MASK(x) (0x1 << I2S_CHMODE_CH_LSBFIRST_OFFSET(x)) +#define I2S_CHMODE_CH_LSBFIRST_ENA(x) (1 << I2S_CHMODE_CH_LSBFIRST_OFFSET(x)) +#define I2S_CHMODE_CH_LSBFIRST_DIS(x) (0 << I2S_CHMODE_CH_LSBFIRST_OFFSET(x)) + +#define I2S_CHMODE_CH_PDM_USEFILTER_OFFSET(x) (8 + (x)) +#define I2S_CHMODE_CH_PDM_USEFILTER_WIDTH(x) (1) +#define I2S_CHMODE_CH_PDM_USEFILTER_MASK(x) (0x1 << I2S_CHMODE_CH_PDM_USEFILTER_OFFSET(x)) +#define I2S_CHMODE_CH_PDM_USEFILTER_ENA(x) (1 << I2S_CHMODE_CH_PDM_USEFILTER_OFFSET(x)) +#define I2S_CHMODE_CH_PDM_USEFILTER_DIS(x) (0 << I2S_CHMODE_CH_PDM_USEFILTER_OFFSET(x)) + +#define I2S_CHMODE_CH_PDM_EN_OFFSET(x) (12 + (x)) +#define I2S_CHMODE_CH_PDM_EN_WIDTH(x) (1) +#define I2S_CHMODE_CH_PDM_EN_MASK(x) (0x1 << I2S_CHMODE_CH_PDM_EN_OFFSET(x)) +#define I2S_CHMODE_CH_PDM_EN_ENA(x) (1 << I2S_CHMODE_CH_PDM_EN_OFFSET(x)) +#define I2S_CHMODE_CH_PDM_EN_DIS(x) (0 << I2S_CHMODE_CH_PDM_EN_OFFSET(x)) + +#define I2S_CHMODE_CH_USEDDR_OFFSET(x) (16 + (x)) +#define I2S_CHMODE_CH_USEDDR_WIDTH(x) (1) +#define I2S_CHMODE_CH_USEDDR_MASK(x) (0x1 << I2S_CHMODE_CH_USEDDR_OFFSET(x)) +#define I2S_CHMODE_CH_USEDDR_ENA(x) (1 << I2S_CHMODE_CH_USEDDR_OFFSET(x)) +#define I2S_CHMODE_CH_USEDDR_DIS(x) (0 << I2S_CHMODE_CH_USEDDR_OFFSET(x)) + +#define I2S_CHMODE_CH_MODE_OFFSET(x) (24 + (x*2)) +#define I2S_CHMODE_CH_MODE_WIDTH(x) (2) +#define I2S_CHMODE_CH_MODE_MASK(x) (0x3 << I2S_CHMODE_CH_MODE_OFFSET(x)) +#define I2S_CHMODE_CH_MODE_CLK(x,clk) (clk << I2S_CHMODE_CH_MODE_OFFSET(x)) +#define I2S_CHMODE_CH_MODE_EXTCLK_INTWS(x) (2 << I2S_CHMODE_CH_MODE_OFFSET(x)) +#define I2S_CHMODE_CH_MODE_EXTCLK_EXTWS(x) (2 << I2S_CHMODE_CH_MODE_OFFSET(x)) + + + +#define I2S_CHMODE_CH0_SNAPCAM_OFFSET 0 +#define I2S_CHMODE_CH0_SNAPCAM_WIDTH 1 +#define I2S_CHMODE_CH0_SNAPCAM_MASK (0x1 << I2S_CHMODE_CH0_SNAPCAM_OFFSET) +#define I2S_CHMODE_CH0_SNAPCAM_ENA (0x1 << I2S_CHMODE_CH0_SNAPCAM_OFFSET) +#define I2S_CHMODE_CH0_SNAPCAM_DIS (0x0 << I2S_CHMODE_CH0_SNAPCAM_OFFSET) + +#define I2S_CHMODE_CH0_LSBFIRST_OFFSET 4 +#define I2S_CHMODE_CH0_LSBFIRST_WIDTH 1 +#define I2S_CHMODE_CH0_LSBFIRST_MASK (0x1 << I2S_CHMODE_CH0_LSBFIRST_OFFSET) +#define I2S_CHMODE_CH0_LSBFIRST_ENA (1 << I2S_CHMODE_CH0_LSBFIRST_OFFSET) +#define I2S_CHMODE_CH0_LSBFIRST_DIS (0 << I2S_CHMODE_CH0_LSBFIRST_OFFSET) + +#define I2S_CHMODE_CH0_PDM_USEFILTER_OFFSET 8 +#define I2S_CHMODE_CH0_PDM_USEFILTER_WIDTH 1 +#define I2S_CHMODE_CH0_PDM_USEFILTER_MASK (0x1 << I2S_CHMODE_CH0_PDM_USEFILTER_OFFSET) +#define I2S_CHMODE_CH0_PDM_USEFILTER_ENA (1 << I2S_CHMODE_CH0_PDM_USEFILTER_OFFSET) +#define I2S_CHMODE_CH0_PDM_USEFILTER_DIS (0 << I2S_CHMODE_CH0_PDM_USEFILTER_OFFSET) + +#define I2S_CHMODE_CH0_PDM_EN_OFFSET 12 +#define I2S_CHMODE_CH0_PDM_EN_WIDTH 1 +#define I2S_CHMODE_CH0_PDM_EN_MASK (0x1 << I2S_CHMODE_CH0_PDM_EN_OFFSET) +#define I2S_CHMODE_CH0_PDM_EN_ENA (1 << I2S_CHMODE_CH0_PDM_EN_OFFSET) +#define I2S_CHMODE_CH0_PDM_EN_DIS (0 << I2S_CHMODE_CH0_PDM_EN_OFFSET) + +#define I2S_CHMODE_CH0_USEDDR_OFFSET 16 +#define I2S_CHMODE_CH0_USEDDR_WIDTH 1 +#define I2S_CHMODE_CH0_USEDDR_MASK (0x1 << I2S_CHMODE_CH0_USEDDR_OFFSET) +#define I2S_CHMODE_CH0_USEDDR_ENA (1 << I2S_CHMODE_CH0_USEDDR_OFFSET) +#define I2S_CHMODE_CH0_USEDDR_DIS (0 << I2S_CHMODE_CH0_USEDDR_OFFSET) + +#define I2S_CHMODE_CH0_MODE_OFFSET 24 +#define I2S_CHMODE_CH0_MODE_WIDTH 2 +#define I2S_CHMODE_CH0_MODE_MASK (0x3 << I2S_CHMODE_CH0_MODE_OFFSET) +#define I2S_CHMODE_CH0_MODE_CLK0 (0 << I2S_CHMODE_CH0_MODE_OFFSET) +#define I2S_CHMODE_CH0_MODE_CLK1 (1 << I2S_CHMODE_CH0_MODE_OFFSET) +#define I2S_CHMODE_CH0_MODE_EXTCLK_INTWS (2 << I2S_CHMODE_CH0_MODE_OFFSET) +#define I2S_CHMODE_CH0_MODE_EXTCLK_EXTWS (2 << I2S_CHMODE_CH0_MODE_OFFSET) + +#define I2S_CHMODE_CH1_SNAPCAM_OFFSET 1 +#define I2S_CHMODE_CH1_SNAPCAM_WIDTH 1 +#define I2S_CHMODE_CH1_SNAPCAM_MASK (0x1 << I2S_CHMODE_CH1_SNAPCAM_OFFSET) +#define I2S_CHMODE_CH1_SNAPCAM_ENA (0x1 << I2S_CHMODE_CH1_SNAPCAM_OFFSET) +#define I2S_CHMODE_CH1_SNAPCAM_DIS (0x0 << I2S_CHMODE_CH1_SNAPCAM_OFFSET) + +#define I2S_CHMODE_CH1_LSBFIRST_OFFSET 5 +#define I2S_CHMODE_CH1_LSBFIRST_WIDTH 1 +#define I2S_CHMODE_CH1_LSBFIRST_MASK (0x1 << I2S_CHMODE_CH1_LSBFIRST_OFFSET) +#define I2S_CHMODE_CH1_LSBFIRST_ENA (1 << I2S_CHMODE_CH1_LSBFIRST_OFFSET) +#define I2S_CHMODE_CH1_LSBFIRST_DIS (0 << I2S_CHMODE_CH1_LSBFIRST_OFFSET) + +#define I2S_CHMODE_CH1_PDM_USEFILTER_OFFSET 9 +#define I2S_CHMODE_CH1_PDM_USEFILTER_WIDTH 1 +#define I2S_CHMODE_CH1_PDM_USEFILTER_MASK (0x1 << I2S_CHMODE_CH1_PDM_USEFILTER_OFFSET) +#define I2S_CHMODE_CH1_PDM_USEFILTER_ENA (1 << I2S_CHMODE_CH1_PDM_USEFILTER_OFFSET) +#define I2S_CHMODE_CH1_PDM_USEFILTER_DIS (0 << I2S_CHMODE_CH1_PDM_USEFILTER_OFFSET) + +#define I2S_CHMODE_CH1_PDM_EN_OFFSET 13 +#define I2S_CHMODE_CH1_PDM_EN_WIDTH 1 +#define I2S_CHMODE_CH1_PDM_EN_MASK (0x1 << I2S_CHMODE_CH1_PDM_EN_OFFSET) +#define I2S_CHMODE_CH1_PDM_EN_ENA (1 << I2S_CHMODE_CH1_PDM_EN_OFFSET) +#define I2S_CHMODE_CH1_PDM_EN_DIS (0 << I2S_CHMODE_CH1_PDM_EN_OFFSET) + +#define I2S_CHMODE_CH1_USEDDR_OFFSET 17 +#define I2S_CHMODE_CH1_USEDDR_WIDTH 1 +#define I2S_CHMODE_CH1_USEDDR_MASK (0x1 << I2S_CHMODE_CH1_USEDDR_OFFSET) +#define I2S_CHMODE_CH1_USEDDR_ENA (1 << I2S_CHMODE_CH1_USEDDR_OFFSET) +#define I2S_CHMODE_CH1_USEDDR_DIS (0 << I2S_CHMODE_CH1_USEDDR_OFFSET) + +#define I2S_CHMODE_CH1_MODE_OFFSET 26 +#define I2S_CHMODE_CH1_MODE_WIDTH 2 +#define I2S_CHMODE_CH1_MODE_MASK (0x3 << I2S_CHMODE_CH1_MODE_OFFSET) +#define I2S_CHMODE_CH1_MODE_CLK0 (0 << I2S_CHMODE_CH1_MODE_OFFSET) +#define I2S_CHMODE_CH1_MODE_CLK1 (1 << I2S_CHMODE_CH1_MODE_OFFSET) +#define I2S_CHMODE_CH1_MODE_EXTCLK_INTWS (2 << I2S_CHMODE_CH1_MODE_OFFSET) +#define I2S_CHMODE_CH1_MODE_EXTCLK_EXTWS (2 << I2S_CHMODE_CH1_MODE_OFFSET) + +// Channel clock modes +// Write strobe is the clock for switching left/right channels +#define I2S_CHMODE_INT_CLOCK0 0 // Internal clock 0 +#define I2S_CHMODE_INT_CLOCK1 1 // Internal clock 1 +#define I2S_CHMODE_EXT_CLOCK_INT_WS 2 // External clock internal write strobe +#define I2S_CHMODE_EXT_CLOCK_EXT_WS 3 // External clock external write strobe + + +#define I2S_FILT_CH0_DECIMATION_OFFSET 0 +#define I2S_FILT_CH0_DECIMATION_WIDTH 10 +#define I2S_FILT_CH0_DECIMATION_MASK (0x3ff << I2S_FILT_CH0_DECIMATION_OFFSET) +#define I2S_FILT_CH0_DECIMATION(val) (val << I2S_FILT_CH0_DECIMATION_OFFSET) + +#define I2S_FILT_CH0_SHIFT_OFFSET 16 +#define I2S_FILT_CH0_SHIFT_WIDTH 3 +#define I2S_FILT_CH0_SHIFT_MASK (0x7 << I2S_FILT_CH0_SHIFT_OFFSET) +#define I2S_FILT_CH0_SHIFT(val) (val << I2S_FILT_CH0_SHIFT_OFFSET) + +#define I2S_FILT_CH1_DECIMATION_OFFSET 0 +#define I2S_FILT_CH1_DECIMATION_WIDTH 10 +#define I2S_FILT_CH1_DECIMATION_MASK (0x3ff << I2S_FILT_CH1_DECIMATION_OFFSET) +#define I2S_FILT_CH1_DECIMATION(val) (val << I2S_FILT_CH1_DECIMATION_OFFSET) + +#define I2S_FILT_CH1_SHIFT_OFFSET 16 +#define I2S_FILT_CH1_SHIFT_WIDTH 3 +#define I2S_FILT_CH1_SHIFT_MASK (0x7 << I2S_FILT_CH1_SHIFT_OFFSET) +#define I2S_FILT_CH1_SHIFT(val) (val << I2S_FILT_CH1_SHIFT_OFFSET) +/////////////////////////////////////////////////// + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1_new.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1_new.h new file mode 100644 index 0000000..1227baa --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v1_new.h @@ -0,0 +1,786 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_UDMA_I2S_V1_NEW_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_UDMA_I2S_V1_NEW_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// uDMA RX I2S channel 0 buffer base address configuration register. +#define UDMA_I2S_RX_SADDR_CH0_OFFSET 0x0 + +// uDMA RX I2S channel 0 buffer size configuration register. +#define UDMA_I2S_RX_SIZE_CH0_OFFSET 0x4 + +// uDMA RX I2S channel 0 stream configuration register. +#define UDMA_I2S_RX_CFG_CH0_OFFSET 0x8 + +// uDMA RX I2S channel 1 buffer base address configuration register. +#define UDMA_I2S_RX_SADDR_CH1_OFFSET 0x10 + +// uDMA RX I2S channel 1 buffer size configuration register. +#define UDMA_I2S_RX_SIZE_CH1_OFFSET 0x14 + +// uDMA RX I2S channel 1 stream configuration register. +#define UDMA_I2S_RX_CFG_CH1_OFFSET 0x18 + +// I2S external clock configuration register. +#define UDMA_I2S_CFG_EXT_OFFSET 0x20 + +// I2S clock and WS generator 0 configuration register. +#define UDMA_I2S_CFG_CLKGEN0_OFFSET 0x24 + +// I2S clock and WS generator 1 configuration register. +#define UDMA_I2S_CFG_CLKGEN1_OFFSET 0x28 + +// I2S channels mode configuration register. +#define UDMA_I2S_CHMODE_OFFSET 0x2c + +// I2S channel 0 filtering configuration register. +#define UDMA_I2S_FILT_CH0_OFFSET 0x30 + +// I2S channel 1 filtering configuration register. +#define UDMA_I2S_FILT_CH1_OFFSET 0x34 + + + +// +// REGISTERS FIELDS +// + +// I2S channel 0 RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address (access: R/W) +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_BIT 0 +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_WIDTH 16 +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_MASK 0xffff + +// I2S channel 0 RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_BIT 0 +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_WIDTH 17 +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_MASK 0x1ffff + +// I2S channel 0 RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_BIT 0 +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_MASK 0x1 + +// RX channel transfer size used to increment uDMA I2S channel 0 RX buffer address pointer: - 2'b00: plus 1 - +1 (8 bits) - 2'b01: plus 2 - +2 (16 bits) - 2'b10: plus 4 - +4 (32 bits) - 2'b11: plus 0 - +0 (access: R/W) +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_BIT 1 +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_WIDTH 2 +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_MASK 0x6 + +// I2S channel 0 RX Channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_RX_CFG_CH0_EN_BIT 4 +#define UDMA_I2S_RX_CFG_CH0_EN_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH0_EN_MASK 0x10 + +// I2S channel 0 RX Channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer (access: W) +#define UDMA_I2S_RX_CFG_CH0_CLR_BIT 5 +#define UDMA_I2S_RX_CFG_CH0_CLR_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH0_CLR_MASK 0x20 + +// I2S channel 0 RX Transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1:pending - pending transfer in the queue (access: R) +#define UDMA_I2S_RX_CFG_CH0_PENDING_BIT 5 +#define UDMA_I2S_RX_CFG_CH0_PENDING_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH0_PENDING_MASK 0x20 + +// I2S channel 1 RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address (access: R/W) +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_BIT 0 +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_WIDTH 16 +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_MASK 0xffff + +// I2S channel 1 RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_BIT 0 +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_WIDTH 17 +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_MASK 0x1ffff + +// I2S channel 1 RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_BIT 0 +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_MASK 0x1 + +// RX channel transfer size used to increment uDMA I2S channel 1 RX buffer address pointer: - 2'b00: plus 1 - +1 (8 bits) - 2'b01: plus 2 - +2 (16 bits) - 2'b10: plus 4 - +4 (32 bits) - 2'b11: plus 0 - +0 (access: R/W) +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_BIT 1 +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_WIDTH 2 +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_MASK 0x6 + +// I2S channel 1 RX Channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_RX_CFG_CH1_EN_BIT 4 +#define UDMA_I2S_RX_CFG_CH1_EN_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH1_EN_MASK 0x10 + +// I2S channel 1 RX Channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer (access: W) +#define UDMA_I2S_RX_CFG_CH1_CLR_BIT 5 +#define UDMA_I2S_RX_CFG_CH1_CLR_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH1_CLR_MASK 0x20 + +// I2S channel 1 RX Transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue (access: R) +#define UDMA_I2S_RX_CFG_CH1_PENDING_BIT 5 +#define UDMA_I2S_RX_CFG_CH1_PENDING_WIDTH 1 +#define UDMA_I2S_RX_CFG_CH1_PENDING_MASK 0x20 + +// External clock word length in bits bitfield. The value is (num bits - 1). (access: R/W) +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_BIT 0 +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_WIDTH 5 +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_MASK 0x1f + +// Clock generator 0 word length in bits bitfield. The value is (num bits - 1). (access: R/W) +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_BIT 0 +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_WIDTH 5 +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_MASK 0x1f + +// Clock generator 0 enable bitfield: - 1'b0: disabled - 1'b1: enabled - enabled. Clock and WS signal are generated. (access: R/W) +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_BIT 8 +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_WIDTH 1 +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_MASK 0x100 + +// Clock generator 0 clock divider related to SoC clock frequency. (access: R/W) +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_BIT 16 +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_WIDTH 16 +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_MASK 0xffff0000 + +// Clock generator 1 word length in bits bitfield. The value is (num bits - 1). (access: R/W) +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_BIT 0 +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_WIDTH 5 +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_MASK 0x1f + +// Clock generator 1 enable bitfield: - 1'b0: disabled - 1'b1: enabled - enabled. Clock and WS signal are generated. (access: R/W) +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_BIT 8 +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_WIDTH 1 +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_MASK 0x100 + +// Clock generator 1 clock divider related to SoC clock frequency. (access: R/W) +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_BIT 16 +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_WIDTH 16 +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_MASK 0xffff0000 + +// I2S channel 0 LSB first configuration for word serialization bitfield: - 1'b0: MSB first - 1'b1: LSB first (access: R/W) +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_BIT 4 +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_WIDTH 1 +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_MASK 0x10 + +// I2S channel 0 PDM filter activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_BIT 8 +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_WIDTH 1 +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_MASK 0x100 + +// I2S channel 0 PDM demodulation activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH0_PDM_EN_BIT 12 +#define UDMA_I2S_CHMODE_CH0_PDM_EN_WIDTH 1 +#define UDMA_I2S_CHMODE_CH0_PDM_EN_MASK 0x1000 + +// I2S channel 0 DDR mode activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH0_USEDDR_BIT 16 +#define UDMA_I2S_CHMODE_CH0_USEDDR_WIDTH 1 +#define UDMA_I2S_CHMODE_CH0_USEDDR_MASK 0x10000 + +// I2S channel 0 clock/WS mode configuration bitfield: - 2'b00: clock gen 0 - use clock generator 0 (clock and WS generated by clkgen) - 2'b01: clock gen 1 - use clock generator 1 (clock and WS generated by clkgen) - 2'b10: ext clock int ws - use external clock but internal generated WS by clock generator 0 - 2'b11: ext clock ext ws - use external clock and external WS (access: R/W) +#define UDMA_I2S_CHMODE_CH0_MODE_BIT 24 +#define UDMA_I2S_CHMODE_CH0_MODE_WIDTH 2 +#define UDMA_I2S_CHMODE_CH0_MODE_MASK 0x3000000 + +// I2S channel 1 LSB first configuration for word serialization bitfield: - 1'b0: MSB first - 1'b1: LSB first (access: R/W) +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_BIT 5 +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_WIDTH 1 +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_MASK 0x20 + +// I2S channel 1 PDM filter activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_BIT 9 +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_WIDTH 1 +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_MASK 0x200 + +// I2S channel 1 PDM demodulation activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH1_PDM_EN_BIT 13 +#define UDMA_I2S_CHMODE_CH1_PDM_EN_WIDTH 1 +#define UDMA_I2S_CHMODE_CH1_PDM_EN_MASK 0x2000 + +// I2S channel 1 DDR mode activation bitfield: - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_I2S_CHMODE_CH1_USEDDR_BIT 17 +#define UDMA_I2S_CHMODE_CH1_USEDDR_WIDTH 1 +#define UDMA_I2S_CHMODE_CH1_USEDDR_MASK 0x20000 + +// I2S channel 1 clock/WS mode configuration bitfield: - 2'b00: clock gen 0 - use clock generator 0 (clock and WS generated by clkgen) - 2'b01: clock gen 1 - use clock generator 1 (clock and WS generated by clkgen) - 2'b10: ext clock int ws - use external clock but internal generated WS by clock generator 0 - 2'b11: ext clock ext ws - use external clock and external WS (access: R/W) +#define UDMA_I2S_CHMODE_CH1_MODE_BIT 26 +#define UDMA_I2S_CHMODE_CH1_MODE_WIDTH 2 +#define UDMA_I2S_CHMODE_CH1_MODE_MASK 0xc000000 + +// I2S channel 0 PDM filter decimation value bitfield. (access: R/W) +#define UDMA_I2S_FILT_CH0_DECIMATION_BIT 0 +#define UDMA_I2S_FILT_CH0_DECIMATION_WIDTH 10 +#define UDMA_I2S_FILT_CH0_DECIMATION_MASK 0x3ff + +// I2S channel 0 PDM filter normalisation right shift value bitfield. (access: R/W) +#define UDMA_I2S_FILT_CH0_SHIFT_BIT 16 +#define UDMA_I2S_FILT_CH0_SHIFT_WIDTH 3 +#define UDMA_I2S_FILT_CH0_SHIFT_MASK 0x70000 + +// I2S channel 1 PDM filter decimation value bitfield. (access: R/W) +#define UDMA_I2S_FILT_CH1_DECIMATION_BIT 0 +#define UDMA_I2S_FILT_CH1_DECIMATION_WIDTH 10 +#define UDMA_I2S_FILT_CH1_DECIMATION_MASK 0x3ff + +// I2S channel 1 PDM filter normalisation right shift value bitfield. (access: R/W) +#define UDMA_I2S_FILT_CH1_SHIFT_BIT 16 +#define UDMA_I2S_FILT_CH1_SHIFT_WIDTH 3 +#define UDMA_I2S_FILT_CH1_SHIFT_MASK 0x70000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rx_saddr :16; // I2S channel 0 RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_saddr_ch0_t; + +typedef union { + struct { + unsigned int rx_size :17; // I2S channel 0 RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_size_ch0_t; + +typedef union { + struct { + unsigned int continous :1 ; // I2S channel 0 RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int datasize :2 ; // RX channel transfer size used to increment uDMA I2S channel 0 RX buffer address pointer: - 2'b00: plus 1 - +1 (8 bits) - 2'b01: plus 2 - +2 (16 bits) - 2'b10: plus 4 - +4 (32 bits) - 2'b11: plus 0 - +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // I2S channel 0 RX Channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // I2S channel 0 RX Channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer + unsigned int pending :1 ; // I2S channel 0 RX Transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1:pending - pending transfer in the queue + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_cfg_ch0_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // I2S channel 1 RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_saddr_ch1_t; + +typedef union { + struct { + unsigned int tx_size :17; // I2S channel 1 RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_size_ch1_t; + +typedef union { + struct { + unsigned int continous :1 ; // I2S channel 1 RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int datasize :2 ; // RX channel transfer size used to increment uDMA I2S channel 1 RX buffer address pointer: - 2'b00: plus 1 - +1 (8 bits) - 2'b01: plus 2 - +2 (16 bits) - 2'b10: plus 4 - +4 (32 bits) - 2'b11: plus 0 - +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // I2S channel 1 RX Channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // I2S channel 1 RX Channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer + unsigned int pending :1 ; // I2S channel 1 RX Transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_rx_cfg_ch1_t; + +typedef union { + struct { + unsigned int ext_bits_word :5 ; // External clock word length in bits bitfield. The value is (num bits - 1). + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_cfg_ext_t; + +typedef union { + struct { + unsigned int bits_word :5 ; // Clock generator 0 word length in bits bitfield. The value is (num bits - 1). + unsigned int padding0:3 ; + unsigned int clk_en :1 ; // Clock generator 0 enable bitfield: - 1'b0: disabled - 1'b1: enabled - enabled. Clock and WS signal are generated. + unsigned int padding1:7 ; + unsigned int clk_div :16; // Clock generator 0 clock divider related to SoC clock frequency. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_cfg_clkgen0_t; + +typedef union { + struct { + unsigned int bits_word :5 ; // Clock generator 1 word length in bits bitfield. The value is (num bits - 1). + unsigned int padding0:3 ; + unsigned int clk_en :1 ; // Clock generator 1 enable bitfield: - 1'b0: disabled - 1'b1: enabled - enabled. Clock and WS signal are generated. + unsigned int padding1:7 ; + unsigned int clk_div :16; // Clock generator 1 clock divider related to SoC clock frequency. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_cfg_clkgen1_t; + +typedef union { + struct { + unsigned int padding0:4 ; + unsigned int ch0_lsb_first :1 ; // I2S channel 0 LSB first configuration for word serialization bitfield: - 1'b0: MSB first - 1'b1: LSB first + unsigned int padding1:3 ; + unsigned int ch0_pdm_usefilter:1 ; // I2S channel 0 PDM filter activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding2:3 ; + unsigned int ch0_pdm_en :1 ; // I2S channel 0 PDM demodulation activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding3:3 ; + unsigned int ch0_useddr :1 ; // I2S channel 0 DDR mode activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding4:7 ; + unsigned int ch0_mode :2 ; // I2S channel 0 clock/WS mode configuration bitfield: - 2'b00: clock gen 0 - use clock generator 0 (clock and WS generated by clkgen) - 2'b01: clock gen 1 - use clock generator 1 (clock and WS generated by clkgen) - 2'b10: ext clock int ws - use external clock but internal generated WS by clock generator 0 - 2'b11: ext clock ext ws - use external clock and external WS + unsigned int ch1_lsb_first :1 ; // I2S channel 1 LSB first configuration for word serialization bitfield: - 1'b0: MSB first - 1'b1: LSB first + unsigned int padding5:3 ; + unsigned int ch1_pdm_usefilter:1 ; // I2S channel 1 PDM filter activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding6:3 ; + unsigned int ch1_pdm_en :1 ; // I2S channel 1 PDM demodulation activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding7:3 ; + unsigned int ch1_useddr :1 ; // I2S channel 1 DDR mode activation bitfield: - 1'b0: disabled - 1'b1: enabled + unsigned int padding8:8 ; + unsigned int ch1_mode :2 ; // I2S channel 1 clock/WS mode configuration bitfield: - 2'b00: clock gen 0 - use clock generator 0 (clock and WS generated by clkgen) - 2'b01: clock gen 1 - use clock generator 1 (clock and WS generated by clkgen) - 2'b10: ext clock int ws - use external clock but internal generated WS by clock generator 0 - 2'b11: ext clock ext ws - use external clock and external WS + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_chmode_t; + +typedef union { + struct { + unsigned int decimation :10; // I2S channel 0 PDM filter decimation value bitfield. + unsigned int padding0:6 ; + unsigned int shift :3 ; // I2S channel 0 PDM filter normalisation right shift value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_filt_ch0_t; + +typedef union { + struct { + unsigned int decimation :10; // I2S channel 1 PDM filter decimation value bitfield. + unsigned int padding0:6 ; + unsigned int shift :3 ; // I2S channel 1 PDM filter normalisation right shift value bitfield. + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_filt_ch1_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_i2s_rx_saddr_ch0 : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_SADDR_CH0_RX_SADDR_BIT, UDMA_I2S_RX_SADDR_CH0_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_I2S_RX_SADDR_CH0_RX_SADDR_BIT, UDMA_I2S_RX_SADDR_CH0_RX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_rx_size_ch0 : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_SIZE_CH0_RX_SIZE_BIT, UDMA_I2S_RX_SIZE_CH0_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_I2S_RX_SIZE_CH0_RX_SIZE_BIT, UDMA_I2S_RX_SIZE_CH0_RX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_rx_cfg_ch0 : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH0_CONTINOUS_BIT, UDMA_I2S_RX_CFG_CH0_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_RX_CFG_CH0_CONTINOUS_BIT, UDMA_I2S_RX_CFG_CH0_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH0_DATASIZE_BIT, UDMA_I2S_RX_CFG_CH0_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_RX_CFG_CH0_DATASIZE_BIT, UDMA_I2S_RX_CFG_CH0_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH0_EN_BIT, UDMA_I2S_RX_CFG_CH0_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_RX_CFG_CH0_EN_BIT, UDMA_I2S_RX_CFG_CH0_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH0_CLR_BIT, UDMA_I2S_RX_CFG_CH0_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_RX_CFG_CH0_CLR_BIT, UDMA_I2S_RX_CFG_CH0_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH0_PENDING_BIT, UDMA_I2S_RX_CFG_CH0_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_RX_CFG_CH0_PENDING_BIT, UDMA_I2S_RX_CFG_CH0_PENDING_WIDTH); } +}; + +class vp_udma_i2s_rx_saddr_ch1 : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_SADDR_CH1_TX_SADDR_BIT, UDMA_I2S_RX_SADDR_CH1_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(UDMA_I2S_RX_SADDR_CH1_TX_SADDR_BIT, UDMA_I2S_RX_SADDR_CH1_TX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_rx_size_ch1 : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_SIZE_CH1_TX_SIZE_BIT, UDMA_I2S_RX_SIZE_CH1_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(UDMA_I2S_RX_SIZE_CH1_TX_SIZE_BIT, UDMA_I2S_RX_SIZE_CH1_TX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_rx_cfg_ch1 : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH1_CONTINOUS_BIT, UDMA_I2S_RX_CFG_CH1_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_RX_CFG_CH1_CONTINOUS_BIT, UDMA_I2S_RX_CFG_CH1_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH1_DATASIZE_BIT, UDMA_I2S_RX_CFG_CH1_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_RX_CFG_CH1_DATASIZE_BIT, UDMA_I2S_RX_CFG_CH1_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH1_EN_BIT, UDMA_I2S_RX_CFG_CH1_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_RX_CFG_CH1_EN_BIT, UDMA_I2S_RX_CFG_CH1_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH1_CLR_BIT, UDMA_I2S_RX_CFG_CH1_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_RX_CFG_CH1_CLR_BIT, UDMA_I2S_RX_CFG_CH1_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_RX_CFG_CH1_PENDING_BIT, UDMA_I2S_RX_CFG_CH1_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_RX_CFG_CH1_PENDING_BIT, UDMA_I2S_RX_CFG_CH1_PENDING_WIDTH); } +}; + +class vp_udma_i2s_cfg_ext : public vp::reg_32 +{ +public: + inline void ext_bits_word_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_EXT_EXT_BITS_WORD_BIT, UDMA_I2S_CFG_EXT_EXT_BITS_WORD_WIDTH); } + inline uint32_t ext_bits_word_get() { return this->get_field(UDMA_I2S_CFG_EXT_EXT_BITS_WORD_BIT, UDMA_I2S_CFG_EXT_EXT_BITS_WORD_WIDTH); } +}; + +class vp_udma_i2s_cfg_clkgen0 : public vp::reg_32 +{ +public: + inline void bits_word_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN0_BITS_WORD_BIT, UDMA_I2S_CFG_CLKGEN0_BITS_WORD_WIDTH); } + inline uint32_t bits_word_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN0_BITS_WORD_BIT, UDMA_I2S_CFG_CLKGEN0_BITS_WORD_WIDTH); } + inline void clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN0_CLK_EN_BIT, UDMA_I2S_CFG_CLKGEN0_CLK_EN_WIDTH); } + inline uint32_t clk_en_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN0_CLK_EN_BIT, UDMA_I2S_CFG_CLKGEN0_CLK_EN_WIDTH); } + inline void clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN0_CLK_DIV_BIT, UDMA_I2S_CFG_CLKGEN0_CLK_DIV_WIDTH); } + inline uint32_t clk_div_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN0_CLK_DIV_BIT, UDMA_I2S_CFG_CLKGEN0_CLK_DIV_WIDTH); } +}; + +class vp_udma_i2s_cfg_clkgen1 : public vp::reg_32 +{ +public: + inline void bits_word_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN1_BITS_WORD_BIT, UDMA_I2S_CFG_CLKGEN1_BITS_WORD_WIDTH); } + inline uint32_t bits_word_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN1_BITS_WORD_BIT, UDMA_I2S_CFG_CLKGEN1_BITS_WORD_WIDTH); } + inline void clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN1_CLK_EN_BIT, UDMA_I2S_CFG_CLKGEN1_CLK_EN_WIDTH); } + inline uint32_t clk_en_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN1_CLK_EN_BIT, UDMA_I2S_CFG_CLKGEN1_CLK_EN_WIDTH); } + inline void clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_CFG_CLKGEN1_CLK_DIV_BIT, UDMA_I2S_CFG_CLKGEN1_CLK_DIV_WIDTH); } + inline uint32_t clk_div_get() { return this->get_field(UDMA_I2S_CFG_CLKGEN1_CLK_DIV_BIT, UDMA_I2S_CFG_CLKGEN1_CLK_DIV_WIDTH); } +}; + +class vp_udma_i2s_chmode : public vp::reg_32 +{ +public: + inline void ch0_lsb_first_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH0_LSB_FIRST_BIT, UDMA_I2S_CHMODE_CH0_LSB_FIRST_WIDTH); } + inline uint32_t ch0_lsb_first_get() { return this->get_field(UDMA_I2S_CHMODE_CH0_LSB_FIRST_BIT, UDMA_I2S_CHMODE_CH0_LSB_FIRST_WIDTH); } + inline void ch0_pdm_usefilter_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_BIT, UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_WIDTH); } + inline uint32_t ch0_pdm_usefilter_get() { return this->get_field(UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_BIT, UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_WIDTH); } + inline void ch0_pdm_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH0_PDM_EN_BIT, UDMA_I2S_CHMODE_CH0_PDM_EN_WIDTH); } + inline uint32_t ch0_pdm_en_get() { return this->get_field(UDMA_I2S_CHMODE_CH0_PDM_EN_BIT, UDMA_I2S_CHMODE_CH0_PDM_EN_WIDTH); } + inline void ch0_useddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH0_USEDDR_BIT, UDMA_I2S_CHMODE_CH0_USEDDR_WIDTH); } + inline uint32_t ch0_useddr_get() { return this->get_field(UDMA_I2S_CHMODE_CH0_USEDDR_BIT, UDMA_I2S_CHMODE_CH0_USEDDR_WIDTH); } + inline void ch0_mode_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH0_MODE_BIT, UDMA_I2S_CHMODE_CH0_MODE_WIDTH); } + inline uint32_t ch0_mode_get() { return this->get_field(UDMA_I2S_CHMODE_CH0_MODE_BIT, UDMA_I2S_CHMODE_CH0_MODE_WIDTH); } + inline void ch1_lsb_first_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH1_LSB_FIRST_BIT, UDMA_I2S_CHMODE_CH1_LSB_FIRST_WIDTH); } + inline uint32_t ch1_lsb_first_get() { return this->get_field(UDMA_I2S_CHMODE_CH1_LSB_FIRST_BIT, UDMA_I2S_CHMODE_CH1_LSB_FIRST_WIDTH); } + inline void ch1_pdm_usefilter_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_BIT, UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_WIDTH); } + inline uint32_t ch1_pdm_usefilter_get() { return this->get_field(UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_BIT, UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_WIDTH); } + inline void ch1_pdm_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH1_PDM_EN_BIT, UDMA_I2S_CHMODE_CH1_PDM_EN_WIDTH); } + inline uint32_t ch1_pdm_en_get() { return this->get_field(UDMA_I2S_CHMODE_CH1_PDM_EN_BIT, UDMA_I2S_CHMODE_CH1_PDM_EN_WIDTH); } + inline void ch1_useddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH1_USEDDR_BIT, UDMA_I2S_CHMODE_CH1_USEDDR_WIDTH); } + inline uint32_t ch1_useddr_get() { return this->get_field(UDMA_I2S_CHMODE_CH1_USEDDR_BIT, UDMA_I2S_CHMODE_CH1_USEDDR_WIDTH); } + inline void ch1_mode_set(uint32_t value) { this->set_field(value, UDMA_I2S_CHMODE_CH1_MODE_BIT, UDMA_I2S_CHMODE_CH1_MODE_WIDTH); } + inline uint32_t ch1_mode_get() { return this->get_field(UDMA_I2S_CHMODE_CH1_MODE_BIT, UDMA_I2S_CHMODE_CH1_MODE_WIDTH); } +}; + +class vp_udma_i2s_filt_ch0 : public vp::reg_32 +{ +public: + inline void decimation_set(uint32_t value) { this->set_field(value, UDMA_I2S_FILT_CH0_DECIMATION_BIT, UDMA_I2S_FILT_CH0_DECIMATION_WIDTH); } + inline uint32_t decimation_get() { return this->get_field(UDMA_I2S_FILT_CH0_DECIMATION_BIT, UDMA_I2S_FILT_CH0_DECIMATION_WIDTH); } + inline void shift_set(uint32_t value) { this->set_field(value, UDMA_I2S_FILT_CH0_SHIFT_BIT, UDMA_I2S_FILT_CH0_SHIFT_WIDTH); } + inline uint32_t shift_get() { return this->get_field(UDMA_I2S_FILT_CH0_SHIFT_BIT, UDMA_I2S_FILT_CH0_SHIFT_WIDTH); } +}; + +class vp_udma_i2s_filt_ch1 : public vp::reg_32 +{ +public: + inline void decimation_set(uint32_t value) { this->set_field(value, UDMA_I2S_FILT_CH1_DECIMATION_BIT, UDMA_I2S_FILT_CH1_DECIMATION_WIDTH); } + inline uint32_t decimation_get() { return this->get_field(UDMA_I2S_FILT_CH1_DECIMATION_BIT, UDMA_I2S_FILT_CH1_DECIMATION_WIDTH); } + inline void shift_set(uint32_t value) { this->set_field(value, UDMA_I2S_FILT_CH1_SHIFT_BIT, UDMA_I2S_FILT_CH1_SHIFT_WIDTH); } + inline uint32_t shift_get() { return this->get_field(UDMA_I2S_FILT_CH1_SHIFT_BIT, UDMA_I2S_FILT_CH1_SHIFT_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int rx_saddr_ch0 ; // uDMA RX I2S channel 0 buffer base address configuration register. + unsigned int rx_size_ch0 ; // uDMA RX I2S channel 0 buffer size configuration register. + unsigned int rx_cfg_ch0 ; // uDMA RX I2S channel 0 stream configuration register. + unsigned int rx_saddr_ch1 ; // uDMA RX I2S channel 1 buffer base address configuration register. + unsigned int rx_size_ch1 ; // uDMA RX I2S channel 1 buffer size configuration register. + unsigned int rx_cfg_ch1 ; // uDMA RX I2S channel 1 stream configuration register. + unsigned int cfg_ext ; // I2S external clock configuration register. + unsigned int cfg_clkgen0 ; // I2S clock and WS generator 0 configuration register. + unsigned int cfg_clkgen1 ; // I2S clock and WS generator 1 configuration register. + unsigned int chmode ; // I2S channels mode configuration register. + unsigned int filt_ch0 ; // I2S channel 0 filtering configuration register. + unsigned int filt_ch1 ; // I2S channel 1 filtering configuration register. +} __attribute__((packed)) udma_i2s_udma_i2s_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t udma_i2s_rx_saddr_ch0_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_SADDR_CH0_OFFSET); } +static inline void udma_i2s_rx_saddr_ch0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_SADDR_CH0_OFFSET, value); } + +static inline uint32_t udma_i2s_rx_size_ch0_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_SIZE_CH0_OFFSET); } +static inline void udma_i2s_rx_size_ch0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_SIZE_CH0_OFFSET, value); } + +static inline uint32_t udma_i2s_rx_cfg_ch0_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_CFG_CH0_OFFSET); } +static inline void udma_i2s_rx_cfg_ch0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_CFG_CH0_OFFSET, value); } + +static inline uint32_t udma_i2s_rx_saddr_ch1_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_SADDR_CH1_OFFSET); } +static inline void udma_i2s_rx_saddr_ch1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_SADDR_CH1_OFFSET, value); } + +static inline uint32_t udma_i2s_rx_size_ch1_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_SIZE_CH1_OFFSET); } +static inline void udma_i2s_rx_size_ch1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_SIZE_CH1_OFFSET, value); } + +static inline uint32_t udma_i2s_rx_cfg_ch1_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_RX_CFG_CH1_OFFSET); } +static inline void udma_i2s_rx_cfg_ch1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_RX_CFG_CH1_OFFSET, value); } + +static inline uint32_t udma_i2s_cfg_ext_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_CFG_EXT_OFFSET); } +static inline void udma_i2s_cfg_ext_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_CFG_EXT_OFFSET, value); } + +static inline uint32_t udma_i2s_cfg_clkgen0_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_CFG_CLKGEN0_OFFSET); } +static inline void udma_i2s_cfg_clkgen0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_CFG_CLKGEN0_OFFSET, value); } + +static inline uint32_t udma_i2s_cfg_clkgen1_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_CFG_CLKGEN1_OFFSET); } +static inline void udma_i2s_cfg_clkgen1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_CFG_CLKGEN1_OFFSET, value); } + +static inline uint32_t udma_i2s_chmode_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_CHMODE_OFFSET); } +static inline void udma_i2s_chmode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_CHMODE_OFFSET, value); } + +static inline uint32_t udma_i2s_filt_ch0_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_FILT_CH0_OFFSET); } +static inline void udma_i2s_filt_ch0_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_FILT_CH0_OFFSET, value); } + +static inline uint32_t udma_i2s_filt_ch1_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_FILT_CH1_OFFSET); } +static inline void udma_i2s_filt_ch1_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_FILT_CH1_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_RX_SADDR_CH0_RX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_RX_SIZE_CH0_RX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_RX_CFG_CH0_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_RX_CFG_CH0_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_RX_CFG_CH0_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_RX_CFG_CH0_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_RX_CFG_CH0_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_RX_CFG_CH0_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_RX_CFG_CH0_EN(val) ((val) << 4) + +#define UDMA_I2S_RX_CFG_CH0_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_RX_CFG_CH0_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_RX_CFG_CH0_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_RX_CFG_CH0_CLR(val) ((val) << 5) + +#define UDMA_I2S_RX_CFG_CH0_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_RX_CFG_CH0_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_RX_CFG_CH0_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_RX_CFG_CH0_PENDING(val) ((val) << 5) + +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_RX_SADDR_CH1_TX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_RX_SIZE_CH1_TX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_RX_CFG_CH1_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_RX_CFG_CH1_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_RX_CFG_CH1_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_RX_CFG_CH1_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_RX_CFG_CH1_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_RX_CFG_CH1_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_RX_CFG_CH1_EN(val) ((val) << 4) + +#define UDMA_I2S_RX_CFG_CH1_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_RX_CFG_CH1_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_RX_CFG_CH1_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_RX_CFG_CH1_CLR(val) ((val) << 5) + +#define UDMA_I2S_RX_CFG_CH1_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_RX_CFG_CH1_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_RX_CFG_CH1_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_RX_CFG_CH1_PENDING(val) ((val) << 5) + +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define UDMA_I2S_CFG_EXT_EXT_BITS_WORD(val) ((val) << 0) + +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define UDMA_I2S_CFG_CLKGEN0_BITS_WORD(val) ((val) << 0) + +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_EN(val) ((val) << 8) + +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define UDMA_I2S_CFG_CLKGEN0_CLK_DIV(val) ((val) << 16) + +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_GET(value) (ARCHI_BEXTRACTU((value),5,0)) +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_GETS(value) (ARCHI_BEXTRACT((value),5,0)) +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD_SET(value,field) (ARCHI_BINSERT((value),(field),5,0)) +#define UDMA_I2S_CFG_CLKGEN1_BITS_WORD(val) ((val) << 0) + +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_EN(val) ((val) << 8) + +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),16,16)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),16,16)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),16,16)) +#define UDMA_I2S_CFG_CLKGEN1_CLK_DIV(val) ((val) << 16) + +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_CHMODE_CH0_LSB_FIRST(val) ((val) << 4) + +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define UDMA_I2S_CHMODE_CH0_PDM_USEFILTER(val) ((val) << 8) + +#define UDMA_I2S_CHMODE_CH0_PDM_EN_GET(value) (ARCHI_BEXTRACTU((value),1,12)) +#define UDMA_I2S_CHMODE_CH0_PDM_EN_GETS(value) (ARCHI_BEXTRACT((value),1,12)) +#define UDMA_I2S_CHMODE_CH0_PDM_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,12)) +#define UDMA_I2S_CHMODE_CH0_PDM_EN(val) ((val) << 12) + +#define UDMA_I2S_CHMODE_CH0_USEDDR_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define UDMA_I2S_CHMODE_CH0_USEDDR_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define UDMA_I2S_CHMODE_CH0_USEDDR_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define UDMA_I2S_CHMODE_CH0_USEDDR(val) ((val) << 16) + +#define UDMA_I2S_CHMODE_CH0_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,24)) +#define UDMA_I2S_CHMODE_CH0_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,24)) +#define UDMA_I2S_CHMODE_CH0_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,24)) +#define UDMA_I2S_CHMODE_CH0_MODE(val) ((val) << 24) + +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_CHMODE_CH1_LSB_FIRST(val) ((val) << 5) + +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_GET(value) (ARCHI_BEXTRACTU((value),1,9)) +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_GETS(value) (ARCHI_BEXTRACT((value),1,9)) +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER_SET(value,field) (ARCHI_BINSERT((value),(field),1,9)) +#define UDMA_I2S_CHMODE_CH1_PDM_USEFILTER(val) ((val) << 9) + +#define UDMA_I2S_CHMODE_CH1_PDM_EN_GET(value) (ARCHI_BEXTRACTU((value),1,13)) +#define UDMA_I2S_CHMODE_CH1_PDM_EN_GETS(value) (ARCHI_BEXTRACT((value),1,13)) +#define UDMA_I2S_CHMODE_CH1_PDM_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,13)) +#define UDMA_I2S_CHMODE_CH1_PDM_EN(val) ((val) << 13) + +#define UDMA_I2S_CHMODE_CH1_USEDDR_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define UDMA_I2S_CHMODE_CH1_USEDDR_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define UDMA_I2S_CHMODE_CH1_USEDDR_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define UDMA_I2S_CHMODE_CH1_USEDDR(val) ((val) << 17) + +#define UDMA_I2S_CHMODE_CH1_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,26)) +#define UDMA_I2S_CHMODE_CH1_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,26)) +#define UDMA_I2S_CHMODE_CH1_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,26)) +#define UDMA_I2S_CHMODE_CH1_MODE(val) ((val) << 26) + +#define UDMA_I2S_FILT_CH0_DECIMATION_GET(value) (ARCHI_BEXTRACTU((value),10,0)) +#define UDMA_I2S_FILT_CH0_DECIMATION_GETS(value) (ARCHI_BEXTRACT((value),10,0)) +#define UDMA_I2S_FILT_CH0_DECIMATION_SET(value,field) (ARCHI_BINSERT((value),(field),10,0)) +#define UDMA_I2S_FILT_CH0_DECIMATION(val) ((val) << 0) + +#define UDMA_I2S_FILT_CH0_SHIFT_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define UDMA_I2S_FILT_CH0_SHIFT_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define UDMA_I2S_FILT_CH0_SHIFT_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define UDMA_I2S_FILT_CH0_SHIFT(val) ((val) << 16) + +#define UDMA_I2S_FILT_CH1_DECIMATION_GET(value) (ARCHI_BEXTRACTU((value),10,0)) +#define UDMA_I2S_FILT_CH1_DECIMATION_GETS(value) (ARCHI_BEXTRACT((value),10,0)) +#define UDMA_I2S_FILT_CH1_DECIMATION_SET(value,field) (ARCHI_BINSERT((value),(field),10,0)) +#define UDMA_I2S_FILT_CH1_DECIMATION(val) ((val) << 0) + +#define UDMA_I2S_FILT_CH1_SHIFT_GET(value) (ARCHI_BEXTRACTU((value),3,16)) +#define UDMA_I2S_FILT_CH1_SHIFT_GETS(value) (ARCHI_BEXTRACT((value),3,16)) +#define UDMA_I2S_FILT_CH1_SHIFT_SET(value,field) (ARCHI_BINSERT((value),(field),3,16)) +#define UDMA_I2S_FILT_CH1_SHIFT(val) ((val) << 16) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v2.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v2.h new file mode 100644 index 0000000..1ee0cef --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/udma_i2s_v2.h @@ -0,0 +1,808 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_UDMA_I2S_V2_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_UDMA_I2S_V2_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// RX Channel 0 I2S uDMA transfer address of associated buffer +#define UDMA_I2S_I2S_RX_SADDR_OFFSET 0x0 + +// RX Channel 0 I2S uDMA transfer size of buffer +#define UDMA_I2S_I2S_RX_SIZE_OFFSET 0x4 + +// RX Channel 0 I2S uDMA transfer configuration +#define UDMA_I2S_I2S_RX_CFG_OFFSET 0x8 + +// - +#define UDMA_I2S_I2S_RX_INITCFG_OFFSET 0xc + +// TX Channel I2S uDMA transfer address of associated buffer +#define UDMA_I2S_I2S_TX_SADDR_OFFSET 0x10 + +// TX Channel I2S uDMA transfer size of buffer +#define UDMA_I2S_I2S_TX_SIZE_OFFSET 0x14 + +// TX Channel I2S uDMA transfer configuration +#define UDMA_I2S_I2S_TX_CFG_OFFSET 0x18 + +// - +#define UDMA_I2S_I2S_TX_INITCFG_OFFSET 0x1c + +// Clock configuration for both master, slave and pdm +#define UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET 0x20 + +// Configuration of I2S slave +#define UDMA_I2S_I2S_SLV_SETUP_OFFSET 0x24 + +// Configuration of I2S master +#define UDMA_I2S_I2S_MST_SETUP_OFFSET 0x28 + +// Configuration of PDM module +#define UDMA_I2S_I2S_PDM_SETUP_OFFSET 0x2c + + + +// +// REGISTERS FIELDS +// + +// Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address (access: R/W) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT 0 +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH 16 +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_MASK 0xffff + +// Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size (access: R/W) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT 0 +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH 17 +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT 0 +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_MASK 0x1 + +// Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT 1 +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH 2 +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_MASK 0x6 + +// Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_EN_BIT 4 +#define UDMA_I2S_I2S_RX_CFG_EN_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_EN_MASK 0x10 + +// Channel clear and stop transfer: -1'b0: disable -1'b1: enable (access: W) +#define UDMA_I2S_I2S_RX_CFG_CLR_BIT 5 +#define UDMA_I2S_I2S_RX_CFG_CLR_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_CLR_MASK 0x20 + +// Transfer pending in queue status flag: -1'b0: free -1'b1: pending (access: R) +#define UDMA_I2S_I2S_RX_CFG_PENDING_BIT 5 +#define UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_PENDING_MASK 0x20 + +// Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address (access: R/W) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT 0 +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH 16 +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_MASK 0xffff + +// Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size (access: R/W) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT 0 +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH 17 +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_MASK 0x1ffff + +// Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT 0 +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_MASK 0x1 + +// Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT 1 +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH 2 +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_MASK 0x6 + +// Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_EN_BIT 4 +#define UDMA_I2S_I2S_TX_CFG_EN_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_EN_MASK 0x10 + +// Channel clear and stop transfer: -1'b0: disable -1'b1: enable (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_CLR_BIT 5 +#define UDMA_I2S_I2S_TX_CFG_CLR_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_CLR_MASK 0x20 + +// Transfer pending in queue status flag: -1'b0: free -1'b1: pending (access: R) +#define UDMA_I2S_I2S_TX_CFG_PENDING_BIT 5 +#define UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_PENDING_MASK 0x20 + +// LSB of master clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT 0 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_MASK 0xff + +// LSB of slave clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_MASK 0xff00 + +// MSBs of both master and slave clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT 16 +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_MASK 0xff0000 + +// Enables Slave clock (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT 24 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_MASK 0x1000000 + +// Enables Master clock (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT 25 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_MASK 0x2000000 + +// When enabled slave output clock is taken from PDM module (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT 26 +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_MASK 0x4000000 + +// When set uses external clock for slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT 28 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_MASK 0x10000000 + +// Selects slave clock source(either ext or generated): -1’b0:selects master -1’b1:selects slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT 29 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_MASK 0x20000000 + +// When set uses external clock for master (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT 30 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_MASK 0x40000000 + +// Selects master clock source(either ext or generated): -1’b0:selects master -1’b1:selects slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT 31 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_MASK 0x80000000 + +// Sets how many words for each I2S phase (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT 0 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH 3 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_MASK 0x7 + +// Sets how many bits per word (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT 8 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH 5 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_MASK 0x1f00 + +// Enables LSB shifting (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT 16 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_MASK 0x10000 + +// Enables both channels (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT 17 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_MASK 0x20000 + +// Enables the Slave (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT 31 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_MASK 0x80000000 + +// Sets how many words for each I2S phase (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT 0 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH 3 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_MASK 0x7 + +// Sets how many bits per word (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT 8 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH 5 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_MASK 0x1f00 + +// Enables LSB shifting (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT 16 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_MASK 0x10000 + +// Enables both channels (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT 17 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_MASK 0x20000 + +// Enables the Master (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT 31 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_MASK 0x80000000 + +// Shifts the output of the filter (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT 0 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH 3 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_MASK 0x7 + +// Sets the decimation ratio of the filter (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT 3 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH 10 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_MASK 0x1ff8 + +// nan (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT 13 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH 2 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_MASK 0x6000 + +// nan (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT 31 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH 1 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_MASK 0x80000000 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rx_saddr :16; // Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. + unsigned int datasize :2 ; // Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // Channel clear and stop transfer: -1'b0: disable -1'b1: enable + unsigned int pending :1 ; // Transfer pending in queue status flag: -1'b0: free -1'b1: pending + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_initcfg_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_saddr_t; + +typedef union { + struct { + unsigned int tx_size :17; // Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. + unsigned int datasize :2 ; // Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // Channel clear and stop transfer: -1'b0: disable -1'b1: enable + unsigned int pending :1 ; // Transfer pending in queue status flag: -1'b0: free -1'b1: pending + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_initcfg_t; + +typedef union { + struct { + unsigned int master_clk_div :8 ; // LSB of master clock divider + unsigned int slave_clk_div :8 ; // LSB of slave clock divider + unsigned int common_clk_div :8 ; // MSBs of both master and slave clock divider + unsigned int slave_clk_en :1 ; // Enables Slave clock + unsigned int master_clk_en :1 ; // Enables Master clock + unsigned int pdm_clk_en :1 ; // When enabled slave output clock is taken from PDM module + unsigned int padding0:1 ; + unsigned int slave_ext :1 ; // When set uses external clock for slave + unsigned int slave_num :1 ; // Selects slave clock source(either ext or generated): -1’b0:selects master -1’b1:selects slave + unsigned int master_ext :1 ; // When set uses external clock for master + unsigned int master_num :1 ; // Selects master clock source(either ext or generated): -1’b0:selects master -1’b1:selects slave + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_clkcfg_setup_t; + +typedef union { + struct { + unsigned int slave_words :3 ; // Sets how many words for each I2S phase + unsigned int padding0:5 ; + unsigned int slave_bits :5 ; // Sets how many bits per word + unsigned int padding1:3 ; + unsigned int slave_lsb :1 ; // Enables LSB shifting + unsigned int slave_2ch :1 ; // Enables both channels + unsigned int padding2:13; + unsigned int slave_en :1 ; // Enables the Slave + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_slv_setup_t; + +typedef union { + struct { + unsigned int master_words :3 ; // Sets how many words for each I2S phase + unsigned int padding0:5 ; + unsigned int master_bits :5 ; // Sets how many bits per word + unsigned int padding1:3 ; + unsigned int master_lsb :1 ; // Enables LSB shifting + unsigned int master_2ch :1 ; // Enables both channels + unsigned int padding2:13; + unsigned int master_en :1 ; // Enables the Master + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_mst_setup_t; + +typedef union { + struct { + unsigned int pdm_shift :3 ; // Shifts the output of the filter + unsigned int pdm_decimation :10; // Sets the decimation ratio of the filter + unsigned int pdm_mode :2 ; // nan + unsigned int padding0:16; + unsigned int pdm_en :1 ; // nan + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_pdm_setup_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_i2s_i2s_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_i2s_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_i2s_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_EN_BIT, UDMA_I2S_I2S_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_EN_BIT, UDMA_I2S_I2S_RX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_CLR_BIT, UDMA_I2S_I2S_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_CLR_BIT, UDMA_I2S_I2S_RX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_PENDING_BIT, UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_PENDING_BIT, UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_saddr : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_size : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_EN_BIT, UDMA_I2S_I2S_TX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_EN_BIT, UDMA_I2S_I2S_TX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_CLR_BIT, UDMA_I2S_I2S_TX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_CLR_BIT, UDMA_I2S_I2S_TX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_PENDING_BIT, UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_PENDING_BIT, UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_i2s_i2s_clkcfg_setup : public vp::reg_32 +{ +public: + inline void master_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH); } + inline uint32_t master_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH); } + inline void slave_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH); } + inline uint32_t slave_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH); } + inline void common_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH); } + inline uint32_t common_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH); } + inline void slave_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH); } + inline uint32_t slave_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH); } + inline void master_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH); } + inline uint32_t master_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH); } + inline void pdm_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH); } + inline uint32_t pdm_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH); } + inline void slave_ext_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH); } + inline uint32_t slave_ext_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH); } + inline void slave_num_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH); } + inline uint32_t slave_num_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH); } + inline void master_ext_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH); } + inline uint32_t master_ext_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH); } + inline void master_num_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH); } + inline uint32_t master_num_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH); } +}; + +class vp_udma_i2s_i2s_slv_setup : public vp::reg_32 +{ +public: + inline void slave_words_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH); } + inline uint32_t slave_words_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH); } + inline void slave_bits_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH); } + inline uint32_t slave_bits_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH); } + inline void slave_lsb_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH); } + inline uint32_t slave_lsb_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH); } + inline void slave_2ch_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH); } + inline uint32_t slave_2ch_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH); } + inline void slave_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH); } + inline uint32_t slave_en_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH); } +}; + +class vp_udma_i2s_i2s_mst_setup : public vp::reg_32 +{ +public: + inline void master_words_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH); } + inline uint32_t master_words_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH); } + inline void master_bits_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH); } + inline uint32_t master_bits_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH); } + inline void master_lsb_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH); } + inline uint32_t master_lsb_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH); } + inline void master_2ch_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH); } + inline uint32_t master_2ch_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH); } + inline void master_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH); } + inline uint32_t master_en_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH); } +}; + +class vp_udma_i2s_i2s_pdm_setup : public vp::reg_32 +{ +public: + inline void pdm_shift_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH); } + inline uint32_t pdm_shift_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH); } + inline void pdm_decimation_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH); } + inline uint32_t pdm_decimation_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH); } + inline void pdm_mode_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH); } + inline uint32_t pdm_mode_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH); } + inline void pdm_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH); } + inline uint32_t pdm_en_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int i2s_rx_saddr ; // RX Channel 0 I2S uDMA transfer address of associated buffer + unsigned int i2s_rx_size ; // RX Channel 0 I2S uDMA transfer size of buffer + unsigned int i2s_rx_cfg ; // RX Channel 0 I2S uDMA transfer configuration + unsigned int i2s_rx_initcfg ; // - + unsigned int i2s_tx_saddr ; // TX Channel I2S uDMA transfer address of associated buffer + unsigned int i2s_tx_size ; // TX Channel I2S uDMA transfer size of buffer + unsigned int i2s_tx_cfg ; // TX Channel I2S uDMA transfer configuration + unsigned int i2s_tx_initcfg ; // - + unsigned int i2s_clkcfg_setup; // Clock configuration for both master, slave and pdm + unsigned int i2s_slv_setup ; // Configuration of I2S slave + unsigned int i2s_mst_setup ; // Configuration of I2S master + unsigned int i2s_pdm_setup ; // Configuration of PDM module +} __attribute__((packed)) udma_i2s_udma_i2s_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t udma_i2s_i2s_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_SADDR_OFFSET); } +static inline void udma_i2s_i2s_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_SADDR_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_SIZE_OFFSET); } +static inline void udma_i2s_i2s_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_SIZE_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_CFG_OFFSET); } +static inline void udma_i2s_i2s_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_CFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_INITCFG_OFFSET); } +static inline void udma_i2s_i2s_rx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_SADDR_OFFSET); } +static inline void udma_i2s_i2s_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_SADDR_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_SIZE_OFFSET); } +static inline void udma_i2s_i2s_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_SIZE_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_CFG_OFFSET); } +static inline void udma_i2s_i2s_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_CFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_INITCFG_OFFSET); } +static inline void udma_i2s_i2s_tx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_clkcfg_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET); } +static inline void udma_i2s_i2s_clkcfg_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_slv_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_SLV_SETUP_OFFSET); } +static inline void udma_i2s_i2s_slv_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_SLV_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_mst_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_MST_SETUP_OFFSET); } +static inline void udma_i2s_i2s_mst_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_MST_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_pdm_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_PDM_SETUP_OFFSET); } +static inline void udma_i2s_i2s_pdm_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_PDM_SETUP_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_I2S_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN(val) ((val) << 4) + +#define UDMA_I2S_I2S_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR(val) ((val) << 5) + +#define UDMA_I2S_I2S_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_I2S_TX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN(val) ((val) << 4) + +#define UDMA_I2S_I2S_TX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR(val) ((val) << 5) + +#define UDMA_I2S_I2S_TX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV(val) ((val) << 0) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV(val) ((val) << 8) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV(val) ((val) << 16) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN(val) ((val) << 24) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN(val) ((val) << 25) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN(val) ((val) << 26) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_GET(value) (ARCHI_BEXTRACTU((value),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_GETS(value) (ARCHI_BEXTRACT((value),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_SET(value,field) (ARCHI_BINSERT((value),(field),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT(val) ((val) << 28) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_GET(value) (ARCHI_BEXTRACTU((value),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_GETS(value) (ARCHI_BEXTRACT((value),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_SET(value,field) (ARCHI_BINSERT((value),(field),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM(val) ((val) << 29) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_GET(value) (ARCHI_BEXTRACTU((value),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_GETS(value) (ARCHI_BEXTRACT((value),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_SET(value,field) (ARCHI_BINSERT((value),(field),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT(val) ((val) << 30) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM(val) ((val) << 31) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS(val) ((val) << 0) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS(val) ((val) << 8) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB(val) ((val) << 16) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH(val) ((val) << 17) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN(val) ((val) << 31) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS(val) ((val) << 0) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS(val) ((val) << 8) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB(val) ((val) << 16) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH(val) ((val) << 17) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN(val) ((val) << 31) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT(val) ((val) << 0) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_GET(value) (ARCHI_BEXTRACTU((value),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_GETS(value) (ARCHI_BEXTRACT((value),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_SET(value,field) (ARCHI_BINSERT((value),(field),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION(val) ((val) << 3) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE(val) ((val) << 13) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN(val) ((val) << 31) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3.h new file mode 100644 index 0000000..f057ada --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3.h @@ -0,0 +1,41 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + +#include "udma_i2s_v3_regs.h" +#include "udma_i2s_v3_regfields.h" +#include "udma_i2s_v3_structs.h" +#include "udma_i2s_v3_regmap.h" +#include "udma_i2s_v3_accessors.h" +#include "udma_i2s_v3_macros.h" +#include "udma_i2s_v3_groups.h" +#include "udma_i2s_v3_constants.h" + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_accessors.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_accessors.h new file mode 100644 index 0000000..52f0c28 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_accessors.h @@ -0,0 +1,79 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_ACCESSORS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_ACCESSORS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +static inline uint32_t udma_i2s_i2s_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_SADDR_OFFSET); } +static inline void udma_i2s_i2s_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_SADDR_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_SIZE_OFFSET); } +static inline void udma_i2s_i2s_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_SIZE_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_CFG_OFFSET); } +static inline void udma_i2s_i2s_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_CFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_rx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_RX_INITCFG_OFFSET); } +static inline void udma_i2s_i2s_rx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_RX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_SADDR_OFFSET); } +static inline void udma_i2s_i2s_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_SADDR_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_SIZE_OFFSET); } +static inline void udma_i2s_i2s_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_SIZE_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_CFG_OFFSET); } +static inline void udma_i2s_i2s_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_CFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_tx_initcfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_TX_INITCFG_OFFSET); } +static inline void udma_i2s_i2s_tx_initcfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_TX_INITCFG_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_clkcfg_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET); } +static inline void udma_i2s_i2s_clkcfg_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_slv_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_SLV_SETUP_OFFSET); } +static inline void udma_i2s_i2s_slv_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_SLV_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_mst_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_MST_SETUP_OFFSET); } +static inline void udma_i2s_i2s_mst_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_MST_SETUP_OFFSET, value); } + +static inline uint32_t udma_i2s_i2s_pdm_setup_get(uint32_t base) { return ARCHI_READ(base, UDMA_I2S_I2S_PDM_SETUP_OFFSET); } +static inline void udma_i2s_i2s_pdm_setup_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_I2S_I2S_PDM_SETUP_OFFSET, value); } + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_constants.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_constants.h new file mode 100644 index 0000000..1757128 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_constants.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_CONSTANTS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_CONSTANTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_groups.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_groups.h new file mode 100644 index 0000000..44ea7c4 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_groups.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_GROUPS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_GROUPS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_gvsoc.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_gvsoc.h new file mode 100644 index 0000000..b0b9920 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_gvsoc.h @@ -0,0 +1,169 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_GVSOC_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_GVSOC_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_i2s_i2s_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT, UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_i2s_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT, UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_i2s_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_EN_BIT, UDMA_I2S_I2S_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_EN_BIT, UDMA_I2S_I2S_RX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_CLR_BIT, UDMA_I2S_I2S_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_CLR_BIT, UDMA_I2S_I2S_RX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_RX_CFG_PENDING_BIT, UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_I2S_RX_CFG_PENDING_BIT, UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_saddr : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT, UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_size : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT, UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH); } +}; + +class vp_udma_i2s_i2s_tx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT, UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH); } + inline void datasize_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH); } + inline uint32_t datasize_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT, UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_EN_BIT, UDMA_I2S_I2S_TX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_EN_BIT, UDMA_I2S_I2S_TX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_CLR_BIT, UDMA_I2S_I2S_TX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_CLR_BIT, UDMA_I2S_I2S_TX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_TX_CFG_PENDING_BIT, UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_I2S_I2S_TX_CFG_PENDING_BIT, UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_i2s_i2s_clkcfg_setup : public vp::reg_32 +{ +public: + inline void master_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH); } + inline uint32_t master_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH); } + inline void slave_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH); } + inline uint32_t slave_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH); } + inline void common_clk_div_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH); } + inline uint32_t common_clk_div_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH); } + inline void slave_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH); } + inline uint32_t slave_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH); } + inline void master_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH); } + inline uint32_t master_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH); } + inline void pdm_clk_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH); } + inline uint32_t pdm_clk_en_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH); } + inline void slave_ext_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH); } + inline uint32_t slave_ext_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH); } + inline void slave_num_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH); } + inline uint32_t slave_num_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH); } + inline void master_ext_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH); } + inline uint32_t master_ext_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH); } + inline void master_num_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH); } + inline uint32_t master_num_get() { return this->get_field(UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT, UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH); } +}; + +class vp_udma_i2s_i2s_slv_setup : public vp::reg_32 +{ +public: + inline void slave_words_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH); } + inline uint32_t slave_words_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH); } + inline void slave_bits_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH); } + inline uint32_t slave_bits_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH); } + inline void slave_lsb_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH); } + inline uint32_t slave_lsb_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH); } + inline void slave_2ch_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH); } + inline uint32_t slave_2ch_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH); } + inline void slave_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH); } + inline uint32_t slave_en_get() { return this->get_field(UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT, UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH); } +}; + +class vp_udma_i2s_i2s_mst_setup : public vp::reg_32 +{ +public: + inline void master_words_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH); } + inline uint32_t master_words_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH); } + inline void master_bits_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH); } + inline uint32_t master_bits_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH); } + inline void master_lsb_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH); } + inline uint32_t master_lsb_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH); } + inline void master_2ch_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH); } + inline uint32_t master_2ch_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH); } + inline void master_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH); } + inline uint32_t master_en_get() { return this->get_field(UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT, UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH); } +}; + +class vp_udma_i2s_i2s_pdm_setup : public vp::reg_32 +{ +public: + inline void pdm_shift_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH); } + inline uint32_t pdm_shift_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH); } + inline void pdm_decimation_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH); } + inline uint32_t pdm_decimation_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH); } + inline void pdm_mode_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH); } + inline uint32_t pdm_mode_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH); } + inline void pdm_en_set(uint32_t value) { this->set_field(value, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH); } + inline uint32_t pdm_en_get() { return this->get_field(UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT, UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH); } +}; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_macros.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_macros.h new file mode 100644 index 0000000..3e94d22 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_macros.h @@ -0,0 +1,233 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_MACROS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_MACROS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS MACROS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_I2S_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_I2S_RX_CFG_EN(val) ((val) << 4) + +#define UDMA_I2S_I2S_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_RX_CFG_CLR(val) ((val) << 5) + +#define UDMA_I2S_I2S_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_RX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_GET(value) (ARCHI_BEXTRACTU((value),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_GETS(value) (ARCHI_BEXTRACT((value),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_SET(value,field) (ARCHI_BINSERT((value),(field),2,1)) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE(val) ((val) << 1) + +#define UDMA_I2S_I2S_TX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_I2S_I2S_TX_CFG_EN(val) ((val) << 4) + +#define UDMA_I2S_I2S_TX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_TX_CFG_CLR(val) ((val) << 5) + +#define UDMA_I2S_I2S_TX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_I2S_I2S_TX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV(val) ((val) << 0) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV(val) ((val) << 8) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_GET(value) (ARCHI_BEXTRACTU((value),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_GETS(value) (ARCHI_BEXTRACT((value),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_SET(value,field) (ARCHI_BINSERT((value),(field),8,16)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV(val) ((val) << 16) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,24)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN(val) ((val) << 24) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,25)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN(val) ((val) << 25) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_GET(value) (ARCHI_BEXTRACTU((value),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_GETS(value) (ARCHI_BEXTRACT((value),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,26)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN(val) ((val) << 26) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_GET(value) (ARCHI_BEXTRACTU((value),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_GETS(value) (ARCHI_BEXTRACT((value),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_SET(value,field) (ARCHI_BINSERT((value),(field),1,28)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT(val) ((val) << 28) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_GET(value) (ARCHI_BEXTRACTU((value),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_GETS(value) (ARCHI_BEXTRACT((value),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_SET(value,field) (ARCHI_BINSERT((value),(field),1,29)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM(val) ((val) << 29) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_GET(value) (ARCHI_BEXTRACTU((value),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_GETS(value) (ARCHI_BEXTRACT((value),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_SET(value,field) (ARCHI_BINSERT((value),(field),1,30)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT(val) ((val) << 30) + +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM(val) ((val) << 31) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS(val) ((val) << 0) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS(val) ((val) << 8) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB(val) ((val) << 16) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH(val) ((val) << 17) + +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN(val) ((val) << 31) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS(val) ((val) << 0) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_GET(value) (ARCHI_BEXTRACTU((value),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_GETS(value) (ARCHI_BEXTRACT((value),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_SET(value,field) (ARCHI_BINSERT((value),(field),5,8)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS(val) ((val) << 8) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_GET(value) (ARCHI_BEXTRACTU((value),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_GETS(value) (ARCHI_BEXTRACT((value),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_SET(value,field) (ARCHI_BINSERT((value),(field),1,16)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB(val) ((val) << 16) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_GET(value) (ARCHI_BEXTRACTU((value),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_GETS(value) (ARCHI_BEXTRACT((value),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_SET(value,field) (ARCHI_BINSERT((value),(field),1,17)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH(val) ((val) << 17) + +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN(val) ((val) << 31) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_GET(value) (ARCHI_BEXTRACTU((value),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_GETS(value) (ARCHI_BEXTRACT((value),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_SET(value,field) (ARCHI_BINSERT((value),(field),3,0)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT(val) ((val) << 0) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_GET(value) (ARCHI_BEXTRACTU((value),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_GETS(value) (ARCHI_BEXTRACT((value),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_SET(value,field) (ARCHI_BINSERT((value),(field),10,3)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION(val) ((val) << 3) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_GET(value) (ARCHI_BEXTRACTU((value),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_GETS(value) (ARCHI_BEXTRACT((value),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_SET(value,field) (ARCHI_BINSERT((value),(field),2,13)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE(val) ((val) << 13) + +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_GET(value) (ARCHI_BEXTRACTU((value),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_GETS(value) (ARCHI_BEXTRACT((value),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,31)) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN(val) ((val) << 31) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regfields.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regfields.h new file mode 100644 index 0000000..678900c --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regfields.h @@ -0,0 +1,229 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGFIELDS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGFIELDS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS +// + +// Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address (access: R/W) +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_BIT 0 +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_WIDTH 16 +#define UDMA_I2S_I2S_RX_SADDR_RX_SADDR_MASK 0xffff + +// Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size (access: R/W) +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_BIT 0 +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_WIDTH 17 +#define UDMA_I2S_I2S_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_BIT 0 +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_CONTINOUS_MASK 0x1 + +// Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_BIT 1 +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_WIDTH 2 +#define UDMA_I2S_I2S_RX_CFG_DATASIZE_MASK 0x6 + +// Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_I2S_RX_CFG_EN_BIT 4 +#define UDMA_I2S_I2S_RX_CFG_EN_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_EN_MASK 0x10 + +// Channel clear and stop transfer: -1'b0: disable -1'b1: enable (access: W) +#define UDMA_I2S_I2S_RX_CFG_CLR_BIT 5 +#define UDMA_I2S_I2S_RX_CFG_CLR_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_CLR_MASK 0x20 + +// Transfer pending in queue status flag: -1'b0: free -1'b1: pending (access: R) +#define UDMA_I2S_I2S_RX_CFG_PENDING_BIT 5 +#define UDMA_I2S_I2S_RX_CFG_PENDING_WIDTH 1 +#define UDMA_I2S_I2S_RX_CFG_PENDING_MASK 0x20 + +// Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address (access: R/W) +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_BIT 0 +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_WIDTH 16 +#define UDMA_I2S_I2S_TX_SADDR_TX_SADDR_MASK 0xffff + +// Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size (access: R/W) +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_BIT 0 +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_WIDTH 17 +#define UDMA_I2S_I2S_TX_SIZE_TX_SIZE_MASK 0x1ffff + +// Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_BIT 0 +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_CONTINOUS_MASK 0x1 + +// Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_BIT 1 +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_WIDTH 2 +#define UDMA_I2S_I2S_TX_CFG_DATASIZE_MASK 0x6 + +// Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_EN_BIT 4 +#define UDMA_I2S_I2S_TX_CFG_EN_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_EN_MASK 0x10 + +// Channel clear and stop transfer: -1'b0: disable -1'b1: enable (access: R/W) +#define UDMA_I2S_I2S_TX_CFG_CLR_BIT 5 +#define UDMA_I2S_I2S_TX_CFG_CLR_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_CLR_MASK 0x20 + +// Transfer pending in queue status flag: -1'b0: free -1'b1: pending (access: R) +#define UDMA_I2S_I2S_TX_CFG_PENDING_BIT 5 +#define UDMA_I2S_I2S_TX_CFG_PENDING_WIDTH 1 +#define UDMA_I2S_I2S_TX_CFG_PENDING_MASK 0x20 + +// LSB of master clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_BIT 0 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_DIV_MASK 0xff + +// LSB of slave clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_BIT 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_DIV_MASK 0xff00 + +// MSBs of both master and slave clock divider (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_BIT 16 +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_WIDTH 8 +#define UDMA_I2S_I2S_CLKCFG_SETUP_COMMON_CLK_DIV_MASK 0xff0000 + +// Enables Slave clock (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_BIT 24 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_CLK_EN_MASK 0x1000000 + +// Enables Master clock (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_BIT 25 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_CLK_EN_MASK 0x2000000 + +// When enabled slave output clock is taken from PDM module (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_BIT 26 +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_PDM_CLK_EN_MASK 0x4000000 + +// When set uses external clock for slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_BIT 28 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_EXT_MASK 0x10000000 + +// Selects slave clock source(either ext or generated): -1b0:selects master -1b1:selects slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_BIT 29 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_SLAVE_NUM_MASK 0x20000000 + +// When set uses external clock for master (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_BIT 30 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_EXT_MASK 0x40000000 + +// Selects master clock source(either ext or generated): -1b0:selects master -1b1:selects slave (access: R/W) +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_BIT 31 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_WIDTH 1 +#define UDMA_I2S_I2S_CLKCFG_SETUP_MASTER_NUM_MASK 0x80000000 + +// Sets how many words for each I2S phase (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_BIT 0 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_WIDTH 3 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_WORDS_MASK 0x7 + +// Sets how many bits per word (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_BIT 8 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_WIDTH 5 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_BITS_MASK 0x1f00 + +// Enables LSB shifting (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_BIT 16 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_LSB_MASK 0x10000 + +// Enables both channels (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_BIT 17 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_2CH_MASK 0x20000 + +// Enables the Slave (access: R/W) +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_BIT 31 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_WIDTH 1 +#define UDMA_I2S_I2S_SLV_SETUP_SLAVE_EN_MASK 0x80000000 + +// Sets how many words for each I2S phase (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_BIT 0 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_WIDTH 3 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_WORDS_MASK 0x7 + +// Sets how many bits per word (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_BIT 8 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_WIDTH 5 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_BITS_MASK 0x1f00 + +// Enables LSB shifting (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_BIT 16 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_LSB_MASK 0x10000 + +// Enables both channels (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_BIT 17 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_2CH_MASK 0x20000 + +// Enables the Master (access: R/W) +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_BIT 31 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_WIDTH 1 +#define UDMA_I2S_I2S_MST_SETUP_MASTER_EN_MASK 0x80000000 + +// Shifts the output of the filter (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_BIT 0 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_WIDTH 3 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_SHIFT_MASK 0x7 + +// Sets the decimation ratio of the filter (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_BIT 3 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_WIDTH 10 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_DECIMATION_MASK 0x1ff8 + +// nan (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_BIT 13 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_WIDTH 2 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_MODE_MASK 0x6000 + +// nan (access: R/W) +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_BIT 31 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_WIDTH 1 +#define UDMA_I2S_I2S_PDM_SETUP_PDM_EN_MASK 0x80000000 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regmap.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regmap.h new file mode 100644 index 0000000..a68e8e8 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regmap.h @@ -0,0 +1,58 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGMAP_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGMAP_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS GLOBAL STRUCT +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef struct { + unsigned int i2s_rx_saddr ; // RX Channel 0 I2S uDMA transfer address of associated buffer + unsigned int i2s_rx_size ; // RX Channel 0 I2S uDMA transfer size of buffer + unsigned int i2s_rx_cfg ; // RX Channel 0 I2S uDMA transfer configuration + unsigned int i2s_rx_initcfg ; // - + unsigned int i2s_tx_saddr ; // TX Channel I2S uDMA transfer address of associated buffer + unsigned int i2s_tx_size ; // TX Channel I2S uDMA transfer size of buffer + unsigned int i2s_tx_cfg ; // TX Channel I2S uDMA transfer configuration + unsigned int i2s_tx_initcfg ; // - + unsigned int i2s_clkcfg_setup; // Clock configuration for both master, slave and pdm + unsigned int i2s_slv_setup ; // Configuration of I2S slave + unsigned int i2s_mst_setup ; // Configuration of I2S master + unsigned int i2s_pdm_setup ; // Configuration of PDM module +} __attribute__((packed)) udma_i2s_udma_i2s_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regs.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regs.h new file mode 100644 index 0000000..3964b54 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_regs.h @@ -0,0 +1,75 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_REGS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// RX Channel 0 I2S uDMA transfer address of associated buffer +#define UDMA_I2S_I2S_RX_SADDR_OFFSET 0x0 + +// RX Channel 0 I2S uDMA transfer size of buffer +#define UDMA_I2S_I2S_RX_SIZE_OFFSET 0x4 + +// RX Channel 0 I2S uDMA transfer configuration +#define UDMA_I2S_I2S_RX_CFG_OFFSET 0x8 + +// - +#define UDMA_I2S_I2S_RX_INITCFG_OFFSET 0xc + +// TX Channel I2S uDMA transfer address of associated buffer +#define UDMA_I2S_I2S_TX_SADDR_OFFSET 0x10 + +// TX Channel I2S uDMA transfer size of buffer +#define UDMA_I2S_I2S_TX_SIZE_OFFSET 0x14 + +// TX Channel I2S uDMA transfer configuration +#define UDMA_I2S_I2S_TX_CFG_OFFSET 0x18 + +// - +#define UDMA_I2S_I2S_TX_INITCFG_OFFSET 0x1c + +// Clock configuration for both master, slave and pdm +#define UDMA_I2S_I2S_CLKCFG_SETUP_OFFSET 0x20 + +// Configuration of I2S slave +#define UDMA_I2S_I2S_SLV_SETUP_OFFSET 0x24 + +// Configuration of I2S master +#define UDMA_I2S_I2S_MST_SETUP_OFFSET 0x28 + +// Configuration of PDM module +#define UDMA_I2S_I2S_PDM_SETUP_OFFSET 0x2c + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_structs.h b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_structs.h new file mode 100644 index 0000000..83f9d72 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/i2s/v3/udma_i2s_v3_structs.h @@ -0,0 +1,163 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_STRUCTS_H__ +#define __INCLUDE_ARCHI_UDMA_I2S_V3_UDMA_I2S_V3_STRUCTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef union { + struct { + unsigned int rx_saddr :16; // Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. + unsigned int datasize :2 ; // Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // Channel clear and stop transfer: -1'b0: disable -1'b1: enable + unsigned int pending :1 ; // Transfer pending in queue status flag: -1'b0: free -1'b1: pending + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_rx_initcfg_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // Configure pointer to memory buffer: - Read: value of the pointer until transfer is over. Else returns 0 - Write: set Address Pointer to memory buffer start address + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_saddr_t; + +typedef union { + struct { + unsigned int tx_size :17; // Buffer size in byte. (128kBytes maximum) - Read: buffer size left - Write: set buffer size + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // Channel continuous mode: -1'b0: disable -1'b1: enable At the end of the buffer the uDMA reloads the address and size and starts a new transfer. + unsigned int datasize :2 ; // Channel transfer size used to increment uDMA buffer address pointer: - 2'b00: +1 (8 bits) - 2'b01: +2 (16 bits) - 2'b10: +4 (32 bits) - 2'b11: +0 + unsigned int padding0:1 ; + unsigned int en :1 ; // Channel enable and start transfer: -1'b0: disable -1'b1: enable This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // Channel clear and stop transfer: -1'b0: disable -1'b1: enable + unsigned int pending :1 ; // Transfer pending in queue status flag: -1'b0: free -1'b1: pending + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_cfg_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_tx_initcfg_t; + +typedef union { + struct { + unsigned int master_clk_div :8 ; // LSB of master clock divider + unsigned int slave_clk_div :8 ; // LSB of slave clock divider + unsigned int common_clk_div :8 ; // MSBs of both master and slave clock divider + unsigned int slave_clk_en :1 ; // Enables Slave clock + unsigned int master_clk_en :1 ; // Enables Master clock + unsigned int pdm_clk_en :1 ; // When enabled slave output clock is taken from PDM module + unsigned int padding0:1 ; + unsigned int slave_ext :1 ; // When set uses external clock for slave + unsigned int slave_num :1 ; // Selects slave clock source(either ext or generated): -1b0:selects master -1b1:selects slave + unsigned int master_ext :1 ; // When set uses external clock for master + unsigned int master_num :1 ; // Selects master clock source(either ext or generated): -1b0:selects master -1b1:selects slave + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_clkcfg_setup_t; + +typedef union { + struct { + unsigned int slave_words :3 ; // Sets how many words for each I2S phase + unsigned int padding0:5 ; + unsigned int slave_bits :5 ; // Sets how many bits per word + unsigned int padding1:3 ; + unsigned int slave_lsb :1 ; // Enables LSB shifting + unsigned int slave_2ch :1 ; // Enables both channels + unsigned int padding2:13; + unsigned int slave_en :1 ; // Enables the Slave + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_slv_setup_t; + +typedef union { + struct { + unsigned int master_words :3 ; // Sets how many words for each I2S phase + unsigned int padding0:5 ; + unsigned int master_bits :5 ; // Sets how many bits per word + unsigned int padding1:3 ; + unsigned int master_lsb :1 ; // Enables LSB shifting + unsigned int master_2ch :1 ; // Enables both channels + unsigned int padding2:13; + unsigned int master_en :1 ; // Enables the Master + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_mst_setup_t; + +typedef union { + struct { + unsigned int pdm_shift :3 ; // Shifts the output of the filter + unsigned int pdm_decimation :10; // Sets the decimation ratio of the filter + unsigned int pdm_mode :2 ; // nan + unsigned int padding0:16; + unsigned int pdm_en :1 ; // nan + }; + unsigned int raw; +} __attribute__((packed)) udma_i2s_i2s_pdm_setup_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1.h new file mode 100644 index 0000000..bae98d4 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1.h @@ -0,0 +1,41 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + +#include "udma_memcpy_v1_regs.h" +#include "udma_memcpy_v1_regfields.h" +#include "udma_memcpy_v1_structs.h" +#include "udma_memcpy_v1_regmap.h" +#include "udma_memcpy_v1_accessors.h" +#include "udma_memcpy_v1_macros.h" +#include "udma_memcpy_v1_groups.h" +#include "udma_memcpy_v1_constants.h" + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_accessors.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_accessors.h new file mode 100644 index 0000000..eccb24f --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_accessors.h @@ -0,0 +1,70 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_ACCESSORS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_ACCESSORS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +static inline uint32_t udma_memcpy_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_RX_SADDR_OFFSET); } +static inline void udma_memcpy_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_RX_SADDR_OFFSET, value); } + +static inline uint32_t udma_memcpy_rx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_RX_SIZE_OFFSET); } +static inline void udma_memcpy_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_RX_SIZE_OFFSET, value); } + +static inline uint32_t udma_memcpy_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_RX_CFG_OFFSET); } +static inline void udma_memcpy_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_RX_CFG_OFFSET, value); } + +static inline uint32_t udma_memcpy_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_TX_SADDR_OFFSET); } +static inline void udma_memcpy_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_TX_SADDR_OFFSET, value); } + +static inline uint32_t udma_memcpy_tx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_TX_SIZE_OFFSET); } +static inline void udma_memcpy_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_TX_SIZE_OFFSET, value); } + +static inline uint32_t udma_memcpy_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_TX_CFG_OFFSET); } +static inline void udma_memcpy_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_TX_CFG_OFFSET, value); } + +static inline uint32_t udma_memcpy_dst_addr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_DST_ADDR_OFFSET); } +static inline void udma_memcpy_dst_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_DST_ADDR_OFFSET, value); } + +static inline uint32_t udma_memcpy_src_addr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_SRC_ADDR_OFFSET); } +static inline void udma_memcpy_src_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_SRC_ADDR_OFFSET, value); } + +static inline uint32_t udma_memcpy_mem_sel_get(uint32_t base) { return ARCHI_READ(base, UDMA_MEMCPY_MEM_SEL_OFFSET); } +static inline void udma_memcpy_mem_sel_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MEMCPY_MEM_SEL_OFFSET, value); } + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_constants.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_constants.h new file mode 100644 index 0000000..a43db45 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_constants.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_CONSTANTS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_CONSTANTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_groups.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_groups.h new file mode 100644 index 0000000..aeb9c55 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_groups.h @@ -0,0 +1,33 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_GROUPS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_GROUPS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_gvsoc.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_gvsoc.h new file mode 100644 index 0000000..a06f55e --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_gvsoc.h @@ -0,0 +1,118 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_GVSOC_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_GVSOC_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_memcpy_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_SADDR_RX_SADDR_BIT, UDMA_MEMCPY_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_MEMCPY_RX_SADDR_RX_SADDR_BIT, UDMA_MEMCPY_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_udma_memcpy_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_SIZE_RX_SIZE_BIT, UDMA_MEMCPY_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_MEMCPY_RX_SIZE_RX_SIZE_BIT, UDMA_MEMCPY_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_udma_memcpy_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_CFG_CONTINOUS_BIT, UDMA_MEMCPY_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_MEMCPY_RX_CFG_CONTINOUS_BIT, UDMA_MEMCPY_RX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_CFG_EN_BIT, UDMA_MEMCPY_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MEMCPY_RX_CFG_EN_BIT, UDMA_MEMCPY_RX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_CFG_CLR_BIT, UDMA_MEMCPY_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_MEMCPY_RX_CFG_CLR_BIT, UDMA_MEMCPY_RX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_RX_CFG_PENDING_BIT, UDMA_MEMCPY_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_MEMCPY_RX_CFG_PENDING_BIT, UDMA_MEMCPY_RX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_memcpy_tx_saddr : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_SADDR_TX_SADDR_BIT, UDMA_MEMCPY_TX_SADDR_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(UDMA_MEMCPY_TX_SADDR_TX_SADDR_BIT, UDMA_MEMCPY_TX_SADDR_TX_SADDR_WIDTH); } +}; + +class vp_udma_memcpy_tx_size : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_SIZE_TX_SIZE_BIT, UDMA_MEMCPY_TX_SIZE_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(UDMA_MEMCPY_TX_SIZE_TX_SIZE_BIT, UDMA_MEMCPY_TX_SIZE_TX_SIZE_WIDTH); } +}; + +class vp_udma_memcpy_tx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_CFG_CONTINOUS_BIT, UDMA_MEMCPY_TX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_MEMCPY_TX_CFG_CONTINOUS_BIT, UDMA_MEMCPY_TX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_CFG_EN_BIT, UDMA_MEMCPY_TX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MEMCPY_TX_CFG_EN_BIT, UDMA_MEMCPY_TX_CFG_EN_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_CFG_CLR_BIT, UDMA_MEMCPY_TX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_MEMCPY_TX_CFG_CLR_BIT, UDMA_MEMCPY_TX_CFG_CLR_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_TX_CFG_PENDING_BIT, UDMA_MEMCPY_TX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_MEMCPY_TX_CFG_PENDING_BIT, UDMA_MEMCPY_TX_CFG_PENDING_WIDTH); } +}; + +class vp_udma_memcpy_dst_addr : public vp::reg_32 +{ +public: + inline void dst_addr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_DST_ADDR_DST_ADDR_BIT, UDMA_MEMCPY_DST_ADDR_DST_ADDR_WIDTH); } + inline uint32_t dst_addr_get() { return this->get_field(UDMA_MEMCPY_DST_ADDR_DST_ADDR_BIT, UDMA_MEMCPY_DST_ADDR_DST_ADDR_WIDTH); } +}; + +class vp_udma_memcpy_src_addr : public vp::reg_32 +{ +public: + inline void src_addr_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_BIT, UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_WIDTH); } + inline uint32_t src_addr_get() { return this->get_field(UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_BIT, UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_WIDTH); } +}; + +class vp_udma_memcpy_mem_sel : public vp::reg_32 +{ +public: + inline void mem_sel_set(uint32_t value) { this->set_field(value, UDMA_MEMCPY_MEM_SEL_MEM_SEL_BIT, UDMA_MEMCPY_MEM_SEL_MEM_SEL_WIDTH); } + inline uint32_t mem_sel_get() { return this->get_field(UDMA_MEMCPY_MEM_SEL_MEM_SEL_BIT, UDMA_MEMCPY_MEM_SEL_MEM_SEL_WIDTH); } +}; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_macros.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_macros.h new file mode 100644 index 0000000..90685c2 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_macros.h @@ -0,0 +1,118 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_MACROS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_MACROS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS MACROS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MEMCPY_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_MEMCPY_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_MEMCPY_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_MEMCPY_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_MEMCPY_RX_CFG_EN(val) ((val) << 4) + +#define UDMA_MEMCPY_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MEMCPY_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MEMCPY_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MEMCPY_RX_CFG_CLR(val) ((val) << 5) + +#define UDMA_MEMCPY_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MEMCPY_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MEMCPY_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MEMCPY_RX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR(val) ((val) << 0) + +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE(val) ((val) << 0) + +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MEMCPY_TX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_MEMCPY_TX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_MEMCPY_TX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_MEMCPY_TX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_MEMCPY_TX_CFG_EN(val) ((val) << 4) + +#define UDMA_MEMCPY_TX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MEMCPY_TX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MEMCPY_TX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MEMCPY_TX_CFG_CLR(val) ((val) << 5) + +#define UDMA_MEMCPY_TX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MEMCPY_TX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MEMCPY_TX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MEMCPY_TX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR(val) ((val) << 0) + +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR(val) ((val) << 0) + +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL(val) ((val) << 0) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regfields.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regfields.h new file mode 100644 index 0000000..701a6e0 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regfields.h @@ -0,0 +1,114 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGFIELDS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGFIELDS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS FIELDS +// + +// RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address (access: R/W) +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_BIT 0 +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_WIDTH 16 +#define UDMA_MEMCPY_RX_SADDR_RX_SADDR_MASK 0xffff + +// RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_BIT 0 +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_WIDTH 17 +#define UDMA_MEMCPY_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_BIT 0 +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_MEMCPY_RX_CFG_CONTINOUS_MASK 0x1 + +// RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_MEMCPY_RX_CFG_EN_BIT 4 +#define UDMA_MEMCPY_RX_CFG_EN_WIDTH 1 +#define UDMA_MEMCPY_RX_CFG_EN_MASK 0x10 + +// RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer (access: W) +#define UDMA_MEMCPY_RX_CFG_CLR_BIT 5 +#define UDMA_MEMCPY_RX_CFG_CLR_WIDTH 1 +#define UDMA_MEMCPY_RX_CFG_CLR_MASK 0x20 + +// RX transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue (access: R) +#define UDMA_MEMCPY_RX_CFG_PENDING_BIT 5 +#define UDMA_MEMCPY_RX_CFG_PENDING_WIDTH 1 +#define UDMA_MEMCPY_RX_CFG_PENDING_MASK 0x20 + +// TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address (access: R/W) +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_BIT 0 +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_WIDTH 16 +#define UDMA_MEMCPY_TX_SADDR_TX_SADDR_MASK 0xffff + +// TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_BIT 0 +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_WIDTH 17 +#define UDMA_MEMCPY_TX_SIZE_TX_SIZE_MASK 0x1ffff + +// TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_BIT 0 +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_MEMCPY_TX_CFG_CONTINOUS_MASK 0x1 + +// TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_MEMCPY_TX_CFG_EN_BIT 4 +#define UDMA_MEMCPY_TX_CFG_EN_WIDTH 1 +#define UDMA_MEMCPY_TX_CFG_EN_MASK 0x10 + +// TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear - stop and clear the on-going transfer (access: W) +#define UDMA_MEMCPY_TX_CFG_CLR_BIT 5 +#define UDMA_MEMCPY_TX_CFG_CLR_WIDTH 1 +#define UDMA_MEMCPY_TX_CFG_CLR_MASK 0x20 + +// TX transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue (access: R) +#define UDMA_MEMCPY_TX_CFG_PENDING_BIT 5 +#define UDMA_MEMCPY_TX_CFG_PENDING_WIDTH 1 +#define UDMA_MEMCPY_TX_CFG_PENDING_MASK 0x20 + +// TX destination start address configuration bitfield. MEMCPY TX transfer copy data from L2 TX_CFG.TX_SADDR address to FC_TCDM or L2 memories DST_ADDR address. (access: R/W) +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_BIT 0 +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_WIDTH 17 +#define UDMA_MEMCPY_DST_ADDR_DST_ADDR_MASK 0x1ffff + +// RX source start address configuration bitfield. MEMCPY RX transfer copy data from FC_TCDM or L2 memories SRC_ADDR address to L2 RX_CFG.RX_SADDR address. (access: R/W) +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_BIT 0 +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_WIDTH 17 +#define UDMA_MEMCPY_SRC_ADDR_SRC_ADDR_MASK 0x1ffff + +// Memory selection configuration bitfield: - 1'b0: L2 from/to FC_TCDM - 1'b1: L2 from/to L2 (access: R/W) +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_BIT 0 +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_WIDTH 1 +#define UDMA_MEMCPY_MEM_SEL_MEM_SEL_MASK 0x1 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regmap.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regmap.h new file mode 100644 index 0000000..6c907e4 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regmap.h @@ -0,0 +1,55 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGMAP_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGMAP_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS GLOBAL STRUCT +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef struct { + unsigned int rx_saddr ; // uDMA RX MEMCPY buffer base address configuration register. + unsigned int rx_size ; // uDMA RX MEMCPY buffer size configuration register. + unsigned int rx_cfg ; // uDMA RX MEMCPY stream configuration register. + unsigned int tx_saddr ; // uDMA TX MEMCPY buffer base address configuration register. + unsigned int tx_size ; // uDMA TX MEMCPY buffer size configuration register. + unsigned int tx_cfg ; // uDMA TX MEMCPY stream configuration register. + unsigned int dst_addr ; // MEMCPY TX destination address configuration register. + unsigned int src_addr ; // MEMCPY RX source address configuration register. + unsigned int mem_sel ; // MEMCPY memory source/destination select configuration register. +} __attribute__((packed)) udma_memcpy_udma_memcpy_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regs.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regs.h new file mode 100644 index 0000000..e946e56 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_regs.h @@ -0,0 +1,66 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_REGS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// uDMA RX MEMCPY buffer base address configuration register. +#define UDMA_MEMCPY_RX_SADDR_OFFSET 0x0 + +// uDMA RX MEMCPY buffer size configuration register. +#define UDMA_MEMCPY_RX_SIZE_OFFSET 0x4 + +// uDMA RX MEMCPY stream configuration register. +#define UDMA_MEMCPY_RX_CFG_OFFSET 0x8 + +// uDMA TX MEMCPY buffer base address configuration register. +#define UDMA_MEMCPY_TX_SADDR_OFFSET 0x10 + +// uDMA TX MEMCPY buffer size configuration register. +#define UDMA_MEMCPY_TX_SIZE_OFFSET 0x14 + +// uDMA TX MEMCPY stream configuration register. +#define UDMA_MEMCPY_TX_CFG_OFFSET 0x18 + +// MEMCPY TX destination address configuration register. +#define UDMA_MEMCPY_DST_ADDR_OFFSET 0x20 + +// MEMCPY RX source address configuration register. +#define UDMA_MEMCPY_SRC_ADDR_OFFSET 0x24 + +// MEMCPY memory source/destination select configuration register. +#define UDMA_MEMCPY_MEM_SEL_OFFSET 0x28 + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_structs.h b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_structs.h new file mode 100644 index 0000000..aaf7004 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/memcpy/v1/udma_memcpy_v1_structs.h @@ -0,0 +1,114 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_STRUCTS_H__ +#define __INCLUDE_ARCHI_UDMA_MEMCPY_V1_UDMA_MEMCPY_V1_STRUCTS_H__ + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS STRUCTS +// + +#if !defined(LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLER__) + +typedef union { + struct { + unsigned int rx_saddr :16; // RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear - stop and clear the on-going transfer + unsigned int pending :1 ; // RX transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_rx_cfg_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_tx_saddr_t; + +typedef union { + struct { + unsigned int tx_size :17; // TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_tx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: start - enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int clr :1 ; // TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear - stop and clear the on-going transfer + unsigned int pending :1 ; // TX transfer pending in queue status flag: -1'b0: no pending - no pending transfer in the queue -1'b1: pending - pending transfer in the queue + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_tx_cfg_t; + +typedef union { + struct { + unsigned int dst_addr :17; // TX destination start address configuration bitfield. MEMCPY TX transfer copy data from L2 TX_CFG.TX_SADDR address to FC_TCDM or L2 memories DST_ADDR address. + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_dst_addr_t; + +typedef union { + struct { + unsigned int src_addr :17; // RX source start address configuration bitfield. MEMCPY RX transfer copy data from FC_TCDM or L2 memories SRC_ADDR address to L2 RX_CFG.RX_SADDR address. + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_src_addr_t; + +typedef union { + struct { + unsigned int mem_sel :1 ; // Memory selection configuration bitfield: - 1'b0: L2 from/to FC_TCDM - 1'b1: L2 from/to L2 + }; + unsigned int raw; +} __attribute__((packed)) udma_memcpy_mem_sel_t; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/mram/udma_mram_v1.h b/sw/pulp-sdk/archi/include/archi/udma/mram/udma_mram_v1.h new file mode 100644 index 0000000..742ab94 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/mram/udma_mram_v1.h @@ -0,0 +1,965 @@ + +/* THIS FILE HAS BEEN GENERATED, DO NOT MODIFY IT. + */ + +/* + * Copyright (C) 2018 ETH Zurich, University of Bologna + * and GreenWaves Technologies + * + * 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. + */ + +#ifndef __INCLUDE_ARCHI_UDMA_MRAM_UDMA_MRAM_V1_H__ +#define __INCLUDE_ARCHI_UDMA_MRAM_UDMA_MRAM_V1_H__ + +#ifndef LANGUAGE_ASSEMBLY + +#include +#include "archi/utils.h" + +#endif + + + + +// +// REGISTERS +// + +// uDMA RX UART buffer base address configuration register. +#define UDMA_MRAM_RX_SADDR_OFFSET 0x0 + +// uDMA RX UART buffer size configuration register. +#define UDMA_MRAM_RX_SIZE_OFFSET 0x4 + +// uDMA RX UART stream configuration register. +#define UDMA_MRAM_RX_CFG_OFFSET 0x8 + +// uDMA TX UART buffer base address configuration register. +#define UDMA_MRAM_TX_SADDR_OFFSET 0x10 + +// uDMA TX UART buffer size configuration register. +#define UDMA_MRAM_TX_SIZE_OFFSET 0x14 + +// uDMA TX UART stream configuration register. +#define UDMA_MRAM_TX_CFG_OFFSET 0x18 + +// Destination Address register for programing. +#define UDMA_MRAM_TX_DADDR_OFFSET 0x20 + +// Destination Address register for reading. +#define UDMA_MRAM_RX_DADDR_OFFSET 0x24 + +// MRAM status for pending operation +#define UDMA_MRAM_STATUS_OFFSET 0x28 + +// MRAM MODE: READ - ERASE - PROG - TRIM_CFG +#define UDMA_MRAM_MRAM_MODE_OFFSET 0x2c + +// Erase Address for word or Sector Erase +#define UDMA_MRAM_ERASE_ADDR_OFFSET 0x30 + +// Size of Words or Sector to erase +#define UDMA_MRAM_ERASE_SIZE_OFFSET 0x34 + +// Set Clock div Enable and Div factor. +#define UDMA_MRAM_CLOCK_DIV_OFFSET 0x38 + +// Trigger ERASE and REF_LINE INIT. +#define UDMA_MRAM_TRIGGER_OFFSET 0x3c + +// Interrupt status register. +#define UDMA_MRAM_ISR_OFFSET 0x40 + +// Interrupt enable register. +#define UDMA_MRAM_IER_OFFSET 0x44 + +// Interrupt clean register. +#define UDMA_MRAM_ICR_OFFSET 0x48 + + + +// +// REGISTERS FIELDS +// + +// RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address (access: R/W) +#define UDMA_MRAM_RX_SADDR_RX_SADDR_BIT 0 +#define UDMA_MRAM_RX_SADDR_RX_SADDR_WIDTH 16 +#define UDMA_MRAM_RX_SADDR_RX_SADDR_MASK 0xffff + +// RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_MRAM_RX_SIZE_RX_SIZE_BIT 0 +#define UDMA_MRAM_RX_SIZE_RX_SIZE_WIDTH 17 +#define UDMA_MRAM_RX_SIZE_RX_SIZE_MASK 0x1ffff + +// RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_MRAM_RX_CFG_CONTINOUS_BIT 0 +#define UDMA_MRAM_RX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_MRAM_RX_CFG_CONTINOUS_MASK 0x1 + +// RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_MRAM_RX_CFG_EN_BIT 4 +#define UDMA_MRAM_RX_CFG_EN_WIDTH 1 +#define UDMA_MRAM_RX_CFG_EN_MASK 0x10 + +// RX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue (access: R) +#define UDMA_MRAM_RX_CFG_PENDING_BIT 5 +#define UDMA_MRAM_RX_CFG_PENDING_WIDTH 1 +#define UDMA_MRAM_RX_CFG_PENDING_MASK 0x20 + +// RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear the on-going transfer (access: W) +#define UDMA_MRAM_RX_CFG_CLR_BIT 6 +#define UDMA_MRAM_RX_CFG_CLR_WIDTH 1 +#define UDMA_MRAM_RX_CFG_CLR_MASK 0x40 + +// TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address (access: R/W) +#define UDMA_MRAM_TX_SADDR_TX_SADDR_BIT 0 +#define UDMA_MRAM_TX_SADDR_TX_SADDR_WIDTH 16 +#define UDMA_MRAM_TX_SADDR_TX_SADDR_MASK 0xffff + +// TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. (access: R/W) +#define UDMA_MRAM_TX_SIZE_TX_SIZE_BIT 0 +#define UDMA_MRAM_TX_SIZE_TX_SIZE_WIDTH 17 +#define UDMA_MRAM_TX_SIZE_TX_SIZE_MASK 0x1ffff + +// TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. (access: R/W) +#define UDMA_MRAM_TX_CFG_CONTINOUS_BIT 0 +#define UDMA_MRAM_TX_CFG_CONTINOUS_WIDTH 1 +#define UDMA_MRAM_TX_CFG_CONTINOUS_MASK 0x1 + +// TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. (access: R/W) +#define UDMA_MRAM_TX_CFG_EN_BIT 4 +#define UDMA_MRAM_TX_CFG_EN_WIDTH 1 +#define UDMA_MRAM_TX_CFG_EN_MASK 0x10 + +// TX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue (access: R) +#define UDMA_MRAM_TX_CFG_PENDING_BIT 5 +#define UDMA_MRAM_TX_CFG_PENDING_WIDTH 1 +#define UDMA_MRAM_TX_CFG_PENDING_MASK 0x20 + +// TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear the on-going transfer (access: W) +#define UDMA_MRAM_TX_CFG_CLR_BIT 6 +#define UDMA_MRAM_TX_CFG_CLR_WIDTH 1 +#define UDMA_MRAM_TX_CFG_CLR_MASK 0x40 + +// TX destination address (access: R/W) +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_BIT 0 +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_WIDTH 19 +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_MASK 0x7ffff + +// RX destination address (access: R/W) +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_BIT 0 +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_WIDTH 19 +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_MASK 0x7ffff + +// Erase pending bit: - 1'b0: not pending - 1'b1: pending (access: R) +#define UDMA_MRAM_STATUS_ERASE_PENDING_BIT 0 +#define UDMA_MRAM_STATUS_ERASE_PENDING_WIDTH 1 +#define UDMA_MRAM_STATUS_ERASE_PENDING_MASK 0x1 + +// Program busy bit: - 1'b0: not busy - 1'b1: busy (access: R) +#define UDMA_MRAM_STATUS_TX_BUSY_BIT 1 +#define UDMA_MRAM_STATUS_TX_BUSY_WIDTH 1 +#define UDMA_MRAM_STATUS_TX_BUSY_MASK 0x2 + +// Read busy bit: - 1'b0: not busy - 1'b1: busy (access: R) +#define UDMA_MRAM_STATUS_RX_BUSY_BIT 2 +#define UDMA_MRAM_STATUS_RX_BUSY_WIDTH 1 +#define UDMA_MRAM_STATUS_RX_BUSY_MASK 0x4 + +// Reference line pending bit: - 1'b0: not pending - 1'b1: pending (access: R) +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_BIT 3 +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_WIDTH 1 +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_MASK 0x8 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_BIT 0 +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_MASK 0x1 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_DPD_BIT 1 +#define UDMA_MRAM_MRAM_MODE_DPD_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_DPD_MASK 0x2 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_AREF_BIT 2 +#define UDMA_MRAM_MRAM_MODE_AREF_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_AREF_MASK 0x4 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_TMEN_BIT 3 +#define UDMA_MRAM_MRAM_MODE_TMEN_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_TMEN_MASK 0x8 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_NVR_BIT 4 +#define UDMA_MRAM_MRAM_MODE_NVR_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_NVR_MASK 0x10 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_RST_B_BIT 5 +#define UDMA_MRAM_MRAM_MODE_RST_B_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_RST_B_MASK 0x20 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_RET_B_BIT 6 +#define UDMA_MRAM_MRAM_MODE_RET_B_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_RET_B_MASK 0x40 + +// nan (access: R/W) +#define UDMA_MRAM_MRAM_MODE_POR_B_BIT 7 +#define UDMA_MRAM_MRAM_MODE_POR_B_WIDTH 1 +#define UDMA_MRAM_MRAM_MODE_POR_B_MASK 0x80 + +// MRAM command: - 8’h1: TRIM_CFG - 8’h2: NORMAL_TX - 8’h4: ERASE_CHIP - 8’h8: ERASE_SECT - 8’h10: ERASE_WORD - 8’h20: PWDN - 8’h40: READ_RX - 8’h80: REF_LINE_P - 8’hC0: REF_LINE_AP (access: R/W) +#define UDMA_MRAM_MRAM_MODE_CMD_BIT 8 +#define UDMA_MRAM_MRAM_MODE_CMD_WIDTH 8 +#define UDMA_MRAM_MRAM_MODE_CMD_MASK 0xff00 + +// Erase address (access: R/W) +#define UDMA_MRAM_ERASE_ADDR_ADDR_BIT 0 +#define UDMA_MRAM_ERASE_ADDR_ADDR_WIDTH 19 +#define UDMA_MRAM_ERASE_ADDR_ADDR_MASK 0x7ffff + +// Clock divide data, form 0 - 255, frequency divide table is : -8’h0 - IO_FREQUENCY / 1 -8’h1 - IO_FREQUENCY / 2 -8’h2 - IO_FREQUENCY / 4 … (access: R/W) +#define UDMA_MRAM_CLOCK_DIV_DATA_BIT 0 +#define UDMA_MRAM_CLOCK_DIV_DATA_WIDTH 8 +#define UDMA_MRAM_CLOCK_DIV_DATA_MASK 0xff + +// Clock divider enable : - 1'b0: disabled - 1'b1: enabled (access: R/W) +#define UDMA_MRAM_CLOCK_DIV_EN_BIT 8 +#define UDMA_MRAM_CLOCK_DIV_EN_WIDTH 1 +#define UDMA_MRAM_CLOCK_DIV_EN_MASK 0x100 + +// Trigger enable bit: - 1'b0: disabled - 1'b1: enabled (access: W) +#define UDMA_MRAM_TRIGGER_EN_BIT 0 +#define UDMA_MRAM_TRIGGER_EN_WIDTH 1 +#define UDMA_MRAM_TRIGGER_EN_MASK 0x1 + +// Erase done bit: - 1'b0: not done - 1'b1: done (access: R) +#define UDMA_MRAM_ISR_ERASE_DONE_BIT 0 +#define UDMA_MRAM_ISR_ERASE_DONE_WIDTH 1 +#define UDMA_MRAM_ISR_ERASE_DONE_MASK 0x1 + +// Program done bit: - 1'b0: not done - 1'b1: done (access: R) +#define UDMA_MRAM_ISR_PROGRAM_DONE_BIT 1 +#define UDMA_MRAM_ISR_PROGRAM_DONE_WIDTH 1 +#define UDMA_MRAM_ISR_PROGRAM_DONE_MASK 0x2 + +// TRIM configuration done bit: - 1'b0: not done - 1'b1: done (access: R) +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_BIT 2 +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_WIDTH 1 +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_MASK 0x4 + +// Reference line done bit: - 1'b0: not done - 1'b1: done (access: R) +#define UDMA_MRAM_ISR_REF_LINE_DONE_BIT 3 +#define UDMA_MRAM_ISR_REF_LINE_DONE_WIDTH 1 +#define UDMA_MRAM_ISR_REF_LINE_DONE_MASK 0x8 + +// Erase IRQ enable bit: - 1'b0: not enable - 1'b1: enable (access: R) +#define UDMA_MRAM_IER_ERASE_EN_BIT 0 +#define UDMA_MRAM_IER_ERASE_EN_WIDTH 1 +#define UDMA_MRAM_IER_ERASE_EN_MASK 0x1 + +// Program IRQ enable bit: - 1'b0: not enable - 1'b1: enable (access: R) +#define UDMA_MRAM_IER_PROGRAM_EN_BIT 1 +#define UDMA_MRAM_IER_PROGRAM_EN_WIDTH 1 +#define UDMA_MRAM_IER_PROGRAM_EN_MASK 0x2 + +// TRIM configuration IRQ enable bit: - 1'b0: not enable - 1'b1: enable (access: R) +#define UDMA_MRAM_IER_TRIM_CFG_EN_BIT 2 +#define UDMA_MRAM_IER_TRIM_CFG_EN_WIDTH 1 +#define UDMA_MRAM_IER_TRIM_CFG_EN_MASK 0x4 + +// Reference line IRQ enable bit: - 1'b0: not enable - 1'b1: enable (access: R) +#define UDMA_MRAM_IER_REF_LINE_EN_BIT 3 +#define UDMA_MRAM_IER_REF_LINE_EN_WIDTH 1 +#define UDMA_MRAM_IER_REF_LINE_EN_MASK 0x8 + +// Erase clean IRQ bit: - 1'b0: not clean - 1'b1: clean (access: R) +#define UDMA_MRAM_ICR_ERASE_DONE_BIT 0 +#define UDMA_MRAM_ICR_ERASE_DONE_WIDTH 1 +#define UDMA_MRAM_ICR_ERASE_DONE_MASK 0x1 + +// Program clean IRQ bit: - 1'b0: not clean - 1'b1: clean (access: R) +#define UDMA_MRAM_ICR_PROGRAM_DONE_BIT 1 +#define UDMA_MRAM_ICR_PROGRAM_DONE_WIDTH 1 +#define UDMA_MRAM_ICR_PROGRAM_DONE_MASK 0x2 + +// TRIM configuration clean IRQ bit: - 1'b0: not clean - 1'b1: clean (access: R) +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_BIT 2 +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_WIDTH 1 +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_MASK 0x4 + +// Reference line clean IRQ bit: - 1'b0: not clean - 1'b1: clean (access: R) +#define UDMA_MRAM_ICR_REF_LINE_DONE_BIT 3 +#define UDMA_MRAM_ICR_REF_LINE_DONE_WIDTH 1 +#define UDMA_MRAM_ICR_REF_LINE_DONE_MASK 0x8 + + + +// +// REGISTERS STRUCTS +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef union { + struct { + unsigned int rx_saddr :16; // RX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets RX buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_rx_saddr_t; + +typedef union { + struct { + unsigned int rx_size :17; // RX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_rx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // RX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // RX channel enable and start transfer bitfield: -1'b0: disable -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int pending :1 ; // RX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue + unsigned int clr :1 ; // RX channel clear and stop transfer: -1'b0: disable -1'b1: stop and clear the on-going transfer + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_rx_cfg_t; + +typedef union { + struct { + unsigned int tx_saddr :16; // TX buffer base address bitfield: - Read: returns value of the buffer pointer until transfer is finished. Else returns 0. - Write: sets buffer base address + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_tx_saddr_t; + +typedef union { + struct { + unsigned int tx_size :17; // TX buffer size bitfield in bytes. (128kBytes maximum) - Read: returns remaining buffer size to transfer. - Write: sets buffer size. + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_tx_size_t; + +typedef union { + struct { + unsigned int continous :1 ; // TX channel continuous mode bitfield: -1'b0: disabled -1'b1: enabled At the end of the buffer transfer, the uDMA reloads the address / buffer size and starts a new transfer. + unsigned int padding0:3 ; + unsigned int en :1 ; // TX channel enable and start transfer bitfield: -1'b0: disabled -1'b1: enable and start the transfer This signal is used also to queue a transfer if one is already ongoing. + unsigned int pending :1 ; // TX transfer pending in queue status flag: -1'b0: no pending transfer in the queue -1'b1: pending transfer in the queue + unsigned int clr :1 ; // TX channel clear and stop transfer bitfield: -1'b0: disabled -1'b1: stop and clear the on-going transfer + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_tx_cfg_t; + +typedef union { + struct { + unsigned int tx_dst_addr :19; // TX destination address + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_tx_daddr_t; + +typedef union { + struct { + unsigned int rx_dst_addr :19; // RX destination address + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_rx_daddr_t; + +typedef union { + struct { + unsigned int erase_pending :1 ; // Erase pending bit: - 1'b0: not pending - 1'b1: pending + unsigned int tx_busy :1 ; // Program busy bit: - 1'b0: not busy - 1'b1: busy + unsigned int rx_busy :1 ; // Read busy bit: - 1'b0: not busy - 1'b1: busy + unsigned int ref_line_pending:1 ; // Reference line pending bit: - 1'b0: not pending - 1'b1: pending + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_status_t; + +typedef union { + struct { + unsigned int ecc_byps :1 ; // nan + unsigned int dpd :1 ; // nan + unsigned int aref :1 ; // nan + unsigned int tmen :1 ; // nan + unsigned int nvr :1 ; // nan + unsigned int rst_b :1 ; // nan + unsigned int ret_b :1 ; // nan + unsigned int por_b :1 ; // nan + unsigned int cmd :8 ; // MRAM command: - 8’h1: TRIM_CFG - 8’h2: NORMAL_TX - 8’h4: ERASE_CHIP - 8’h8: ERASE_SECT - 8’h10: ERASE_WORD - 8’h20: PWDN - 8’h40: READ_RX - 8’h80: REF_LINE_P - 8’hC0: REF_LINE_AP + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_mram_mode_t; + +typedef union { + struct { + unsigned int addr :19; // Erase address + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_erase_addr_t; + +typedef union { + struct { + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_erase_size_t; + +typedef union { + struct { + unsigned int data :8 ; // Clock divide data, form 0 - 255, frequency divide table is : -8’h0 - IO_FREQUENCY / 1 -8’h1 - IO_FREQUENCY / 2 -8’h2 - IO_FREQUENCY / 4 … + unsigned int en :1 ; // Clock divider enable : - 1'b0: disabled - 1'b1: enabled + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_clock_div_t; + +typedef union { + struct { + unsigned int en :1 ; // Trigger enable bit: - 1'b0: disabled - 1'b1: enabled + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_trigger_t; + +typedef union { + struct { + unsigned int erase_done :1 ; // Erase done bit: - 1'b0: not done - 1'b1: done + unsigned int program_done :1 ; // Program done bit: - 1'b0: not done - 1'b1: done + unsigned int trim_cfg_done :1 ; // TRIM configuration done bit: - 1'b0: not done - 1'b1: done + unsigned int ref_line_done :1 ; // Reference line done bit: - 1'b0: not done - 1'b1: done + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_isr_t; + +typedef union { + struct { + unsigned int erase_en :1 ; // Erase IRQ enable bit: - 1'b0: not enable - 1'b1: enable + unsigned int program_en :1 ; // Program IRQ enable bit: - 1'b0: not enable - 1'b1: enable + unsigned int trim_cfg_en :1 ; // TRIM configuration IRQ enable bit: - 1'b0: not enable - 1'b1: enable + unsigned int ref_line_en :1 ; // Reference line IRQ enable bit: - 1'b0: not enable - 1'b1: enable + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_ier_t; + +typedef union { + struct { + unsigned int erase_done :1 ; // Erase clean IRQ bit: - 1'b0: not clean - 1'b1: clean + unsigned int program_done :1 ; // Program clean IRQ bit: - 1'b0: not clean - 1'b1: clean + unsigned int trim_cfg_done :1 ; // TRIM configuration clean IRQ bit: - 1'b0: not clean - 1'b1: clean + unsigned int ref_line_done :1 ; // Reference line clean IRQ bit: - 1'b0: not clean - 1'b1: clean + }; + unsigned int raw; +} __attribute__((packed)) udma_mram_icr_t; + +#endif + + + +// +// REGISTERS STRUCTS +// + +#ifdef __GVSOC__ + +class vp_udma_mram_rx_saddr : public vp::reg_32 +{ +public: + inline void rx_saddr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_SADDR_RX_SADDR_BIT, UDMA_MRAM_RX_SADDR_RX_SADDR_WIDTH); } + inline uint32_t rx_saddr_get() { return this->get_field(UDMA_MRAM_RX_SADDR_RX_SADDR_BIT, UDMA_MRAM_RX_SADDR_RX_SADDR_WIDTH); } +}; + +class vp_udma_mram_rx_size : public vp::reg_32 +{ +public: + inline void rx_size_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_SIZE_RX_SIZE_BIT, UDMA_MRAM_RX_SIZE_RX_SIZE_WIDTH); } + inline uint32_t rx_size_get() { return this->get_field(UDMA_MRAM_RX_SIZE_RX_SIZE_BIT, UDMA_MRAM_RX_SIZE_RX_SIZE_WIDTH); } +}; + +class vp_udma_mram_rx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_CFG_CONTINOUS_BIT, UDMA_MRAM_RX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_MRAM_RX_CFG_CONTINOUS_BIT, UDMA_MRAM_RX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_CFG_EN_BIT, UDMA_MRAM_RX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MRAM_RX_CFG_EN_BIT, UDMA_MRAM_RX_CFG_EN_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_CFG_PENDING_BIT, UDMA_MRAM_RX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_MRAM_RX_CFG_PENDING_BIT, UDMA_MRAM_RX_CFG_PENDING_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_CFG_CLR_BIT, UDMA_MRAM_RX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_MRAM_RX_CFG_CLR_BIT, UDMA_MRAM_RX_CFG_CLR_WIDTH); } +}; + +class vp_udma_mram_tx_saddr : public vp::reg_32 +{ +public: + inline void tx_saddr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_SADDR_TX_SADDR_BIT, UDMA_MRAM_TX_SADDR_TX_SADDR_WIDTH); } + inline uint32_t tx_saddr_get() { return this->get_field(UDMA_MRAM_TX_SADDR_TX_SADDR_BIT, UDMA_MRAM_TX_SADDR_TX_SADDR_WIDTH); } +}; + +class vp_udma_mram_tx_size : public vp::reg_32 +{ +public: + inline void tx_size_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_SIZE_TX_SIZE_BIT, UDMA_MRAM_TX_SIZE_TX_SIZE_WIDTH); } + inline uint32_t tx_size_get() { return this->get_field(UDMA_MRAM_TX_SIZE_TX_SIZE_BIT, UDMA_MRAM_TX_SIZE_TX_SIZE_WIDTH); } +}; + +class vp_udma_mram_tx_cfg : public vp::reg_32 +{ +public: + inline void continous_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_CFG_CONTINOUS_BIT, UDMA_MRAM_TX_CFG_CONTINOUS_WIDTH); } + inline uint32_t continous_get() { return this->get_field(UDMA_MRAM_TX_CFG_CONTINOUS_BIT, UDMA_MRAM_TX_CFG_CONTINOUS_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_CFG_EN_BIT, UDMA_MRAM_TX_CFG_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MRAM_TX_CFG_EN_BIT, UDMA_MRAM_TX_CFG_EN_WIDTH); } + inline void pending_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_CFG_PENDING_BIT, UDMA_MRAM_TX_CFG_PENDING_WIDTH); } + inline uint32_t pending_get() { return this->get_field(UDMA_MRAM_TX_CFG_PENDING_BIT, UDMA_MRAM_TX_CFG_PENDING_WIDTH); } + inline void clr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_CFG_CLR_BIT, UDMA_MRAM_TX_CFG_CLR_WIDTH); } + inline uint32_t clr_get() { return this->get_field(UDMA_MRAM_TX_CFG_CLR_BIT, UDMA_MRAM_TX_CFG_CLR_WIDTH); } +}; + +class vp_udma_mram_tx_daddr : public vp::reg_32 +{ +public: + inline void tx_dst_addr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TX_DADDR_TX_DST_ADDR_BIT, UDMA_MRAM_TX_DADDR_TX_DST_ADDR_WIDTH); } + inline uint32_t tx_dst_addr_get() { return this->get_field(UDMA_MRAM_TX_DADDR_TX_DST_ADDR_BIT, UDMA_MRAM_TX_DADDR_TX_DST_ADDR_WIDTH); } +}; + +class vp_udma_mram_rx_daddr : public vp::reg_32 +{ +public: + inline void rx_dst_addr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_RX_DADDR_RX_DST_ADDR_BIT, UDMA_MRAM_RX_DADDR_RX_DST_ADDR_WIDTH); } + inline uint32_t rx_dst_addr_get() { return this->get_field(UDMA_MRAM_RX_DADDR_RX_DST_ADDR_BIT, UDMA_MRAM_RX_DADDR_RX_DST_ADDR_WIDTH); } +}; + +class vp_udma_mram_status : public vp::reg_32 +{ +public: + inline void erase_pending_set(uint32_t value) { this->set_field(value, UDMA_MRAM_STATUS_ERASE_PENDING_BIT, UDMA_MRAM_STATUS_ERASE_PENDING_WIDTH); } + inline uint32_t erase_pending_get() { return this->get_field(UDMA_MRAM_STATUS_ERASE_PENDING_BIT, UDMA_MRAM_STATUS_ERASE_PENDING_WIDTH); } + inline void tx_busy_set(uint32_t value) { this->set_field(value, UDMA_MRAM_STATUS_TX_BUSY_BIT, UDMA_MRAM_STATUS_TX_BUSY_WIDTH); } + inline uint32_t tx_busy_get() { return this->get_field(UDMA_MRAM_STATUS_TX_BUSY_BIT, UDMA_MRAM_STATUS_TX_BUSY_WIDTH); } + inline void rx_busy_set(uint32_t value) { this->set_field(value, UDMA_MRAM_STATUS_RX_BUSY_BIT, UDMA_MRAM_STATUS_RX_BUSY_WIDTH); } + inline uint32_t rx_busy_get() { return this->get_field(UDMA_MRAM_STATUS_RX_BUSY_BIT, UDMA_MRAM_STATUS_RX_BUSY_WIDTH); } + inline void ref_line_pending_set(uint32_t value) { this->set_field(value, UDMA_MRAM_STATUS_REF_LINE_PENDING_BIT, UDMA_MRAM_STATUS_REF_LINE_PENDING_WIDTH); } + inline uint32_t ref_line_pending_get() { return this->get_field(UDMA_MRAM_STATUS_REF_LINE_PENDING_BIT, UDMA_MRAM_STATUS_REF_LINE_PENDING_WIDTH); } +}; + +class vp_udma_mram_mram_mode : public vp::reg_32 +{ +public: + inline void ecc_byps_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_ECC_BYPS_BIT, UDMA_MRAM_MRAM_MODE_ECC_BYPS_WIDTH); } + inline uint32_t ecc_byps_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_ECC_BYPS_BIT, UDMA_MRAM_MRAM_MODE_ECC_BYPS_WIDTH); } + inline void dpd_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_DPD_BIT, UDMA_MRAM_MRAM_MODE_DPD_WIDTH); } + inline uint32_t dpd_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_DPD_BIT, UDMA_MRAM_MRAM_MODE_DPD_WIDTH); } + inline void aref_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_AREF_BIT, UDMA_MRAM_MRAM_MODE_AREF_WIDTH); } + inline uint32_t aref_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_AREF_BIT, UDMA_MRAM_MRAM_MODE_AREF_WIDTH); } + inline void tmen_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_TMEN_BIT, UDMA_MRAM_MRAM_MODE_TMEN_WIDTH); } + inline uint32_t tmen_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_TMEN_BIT, UDMA_MRAM_MRAM_MODE_TMEN_WIDTH); } + inline void nvr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_NVR_BIT, UDMA_MRAM_MRAM_MODE_NVR_WIDTH); } + inline uint32_t nvr_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_NVR_BIT, UDMA_MRAM_MRAM_MODE_NVR_WIDTH); } + inline void rst_b_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_RST_B_BIT, UDMA_MRAM_MRAM_MODE_RST_B_WIDTH); } + inline uint32_t rst_b_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_RST_B_BIT, UDMA_MRAM_MRAM_MODE_RST_B_WIDTH); } + inline void ret_b_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_RET_B_BIT, UDMA_MRAM_MRAM_MODE_RET_B_WIDTH); } + inline uint32_t ret_b_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_RET_B_BIT, UDMA_MRAM_MRAM_MODE_RET_B_WIDTH); } + inline void por_b_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_POR_B_BIT, UDMA_MRAM_MRAM_MODE_POR_B_WIDTH); } + inline uint32_t por_b_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_POR_B_BIT, UDMA_MRAM_MRAM_MODE_POR_B_WIDTH); } + inline void cmd_set(uint32_t value) { this->set_field(value, UDMA_MRAM_MRAM_MODE_CMD_BIT, UDMA_MRAM_MRAM_MODE_CMD_WIDTH); } + inline uint32_t cmd_get() { return this->get_field(UDMA_MRAM_MRAM_MODE_CMD_BIT, UDMA_MRAM_MRAM_MODE_CMD_WIDTH); } +}; + +class vp_udma_mram_erase_addr : public vp::reg_32 +{ +public: + inline void addr_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ERASE_ADDR_ADDR_BIT, UDMA_MRAM_ERASE_ADDR_ADDR_WIDTH); } + inline uint32_t addr_get() { return this->get_field(UDMA_MRAM_ERASE_ADDR_ADDR_BIT, UDMA_MRAM_ERASE_ADDR_ADDR_WIDTH); } +}; + +class vp_udma_mram_erase_size : public vp::reg_32 +{ +public: +}; + +class vp_udma_mram_clock_div : public vp::reg_32 +{ +public: + inline void data_set(uint32_t value) { this->set_field(value, UDMA_MRAM_CLOCK_DIV_DATA_BIT, UDMA_MRAM_CLOCK_DIV_DATA_WIDTH); } + inline uint32_t data_get() { return this->get_field(UDMA_MRAM_CLOCK_DIV_DATA_BIT, UDMA_MRAM_CLOCK_DIV_DATA_WIDTH); } + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_CLOCK_DIV_EN_BIT, UDMA_MRAM_CLOCK_DIV_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MRAM_CLOCK_DIV_EN_BIT, UDMA_MRAM_CLOCK_DIV_EN_WIDTH); } +}; + +class vp_udma_mram_trigger : public vp::reg_32 +{ +public: + inline void en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_TRIGGER_EN_BIT, UDMA_MRAM_TRIGGER_EN_WIDTH); } + inline uint32_t en_get() { return this->get_field(UDMA_MRAM_TRIGGER_EN_BIT, UDMA_MRAM_TRIGGER_EN_WIDTH); } +}; + +class vp_udma_mram_isr : public vp::reg_32 +{ +public: + inline void erase_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ISR_ERASE_DONE_BIT, UDMA_MRAM_ISR_ERASE_DONE_WIDTH); } + inline uint32_t erase_done_get() { return this->get_field(UDMA_MRAM_ISR_ERASE_DONE_BIT, UDMA_MRAM_ISR_ERASE_DONE_WIDTH); } + inline void program_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ISR_PROGRAM_DONE_BIT, UDMA_MRAM_ISR_PROGRAM_DONE_WIDTH); } + inline uint32_t program_done_get() { return this->get_field(UDMA_MRAM_ISR_PROGRAM_DONE_BIT, UDMA_MRAM_ISR_PROGRAM_DONE_WIDTH); } + inline void trim_cfg_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ISR_TRIM_CFG_DONE_BIT, UDMA_MRAM_ISR_TRIM_CFG_DONE_WIDTH); } + inline uint32_t trim_cfg_done_get() { return this->get_field(UDMA_MRAM_ISR_TRIM_CFG_DONE_BIT, UDMA_MRAM_ISR_TRIM_CFG_DONE_WIDTH); } + inline void ref_line_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ISR_REF_LINE_DONE_BIT, UDMA_MRAM_ISR_REF_LINE_DONE_WIDTH); } + inline uint32_t ref_line_done_get() { return this->get_field(UDMA_MRAM_ISR_REF_LINE_DONE_BIT, UDMA_MRAM_ISR_REF_LINE_DONE_WIDTH); } +}; + +class vp_udma_mram_ier : public vp::reg_32 +{ +public: + inline void erase_en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_IER_ERASE_EN_BIT, UDMA_MRAM_IER_ERASE_EN_WIDTH); } + inline uint32_t erase_en_get() { return this->get_field(UDMA_MRAM_IER_ERASE_EN_BIT, UDMA_MRAM_IER_ERASE_EN_WIDTH); } + inline void program_en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_IER_PROGRAM_EN_BIT, UDMA_MRAM_IER_PROGRAM_EN_WIDTH); } + inline uint32_t program_en_get() { return this->get_field(UDMA_MRAM_IER_PROGRAM_EN_BIT, UDMA_MRAM_IER_PROGRAM_EN_WIDTH); } + inline void trim_cfg_en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_IER_TRIM_CFG_EN_BIT, UDMA_MRAM_IER_TRIM_CFG_EN_WIDTH); } + inline uint32_t trim_cfg_en_get() { return this->get_field(UDMA_MRAM_IER_TRIM_CFG_EN_BIT, UDMA_MRAM_IER_TRIM_CFG_EN_WIDTH); } + inline void ref_line_en_set(uint32_t value) { this->set_field(value, UDMA_MRAM_IER_REF_LINE_EN_BIT, UDMA_MRAM_IER_REF_LINE_EN_WIDTH); } + inline uint32_t ref_line_en_get() { return this->get_field(UDMA_MRAM_IER_REF_LINE_EN_BIT, UDMA_MRAM_IER_REF_LINE_EN_WIDTH); } +}; + +class vp_udma_mram_icr : public vp::reg_32 +{ +public: + inline void erase_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ICR_ERASE_DONE_BIT, UDMA_MRAM_ICR_ERASE_DONE_WIDTH); } + inline uint32_t erase_done_get() { return this->get_field(UDMA_MRAM_ICR_ERASE_DONE_BIT, UDMA_MRAM_ICR_ERASE_DONE_WIDTH); } + inline void program_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ICR_PROGRAM_DONE_BIT, UDMA_MRAM_ICR_PROGRAM_DONE_WIDTH); } + inline uint32_t program_done_get() { return this->get_field(UDMA_MRAM_ICR_PROGRAM_DONE_BIT, UDMA_MRAM_ICR_PROGRAM_DONE_WIDTH); } + inline void trim_cfg_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ICR_TRIM_CFG_DONE_BIT, UDMA_MRAM_ICR_TRIM_CFG_DONE_WIDTH); } + inline uint32_t trim_cfg_done_get() { return this->get_field(UDMA_MRAM_ICR_TRIM_CFG_DONE_BIT, UDMA_MRAM_ICR_TRIM_CFG_DONE_WIDTH); } + inline void ref_line_done_set(uint32_t value) { this->set_field(value, UDMA_MRAM_ICR_REF_LINE_DONE_BIT, UDMA_MRAM_ICR_REF_LINE_DONE_WIDTH); } + inline uint32_t ref_line_done_get() { return this->get_field(UDMA_MRAM_ICR_REF_LINE_DONE_BIT, UDMA_MRAM_ICR_REF_LINE_DONE_WIDTH); } +}; + +#endif + + + +// +// REGISTERS GLOBAL STRUCT +// + +#ifndef LANGUAGE_ASSEMBLY + +typedef struct { + unsigned int rx_saddr ; // uDMA RX UART buffer base address configuration register. + unsigned int rx_size ; // uDMA RX UART buffer size configuration register. + unsigned int rx_cfg ; // uDMA RX UART stream configuration register. + unsigned int tx_saddr ; // uDMA TX UART buffer base address configuration register. + unsigned int tx_size ; // uDMA TX UART buffer size configuration register. + unsigned int tx_cfg ; // uDMA TX UART stream configuration register. + unsigned int tx_daddr ; // Destination Address register for programing. + unsigned int rx_daddr ; // Destination Address register for reading. + unsigned int status ; // MRAM status for pending operation + unsigned int mram_mode ; // MRAM MODE: READ - ERASE - PROG - TRIM_CFG + unsigned int erase_addr ; // Erase Address for word or Sector Erase + unsigned int erase_size ; // Size of Words or Sector to erase + unsigned int clock_div ; // Set Clock div Enable and Div factor. + unsigned int trigger ; // Trigger ERASE and REF_LINE INIT. + unsigned int isr ; // Interrupt status register. + unsigned int ier ; // Interrupt enable register. + unsigned int icr ; // Interrupt clean register. +} __attribute__((packed)) udma_mram_udma_mram_t; + +#endif + + + +// +// REGISTERS ACCESS FUNCTIONS +// + +#ifndef LANGUAGE_ASSEMBLY + +static inline uint32_t udma_mram_rx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_RX_SADDR_OFFSET); } +static inline void udma_mram_rx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_RX_SADDR_OFFSET, value); } + +static inline uint32_t udma_mram_rx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_RX_SIZE_OFFSET); } +static inline void udma_mram_rx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_RX_SIZE_OFFSET, value); } + +static inline uint32_t udma_mram_rx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_RX_CFG_OFFSET); } +static inline void udma_mram_rx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_RX_CFG_OFFSET, value); } + +static inline uint32_t udma_mram_tx_saddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_TX_SADDR_OFFSET); } +static inline void udma_mram_tx_saddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_TX_SADDR_OFFSET, value); } + +static inline uint32_t udma_mram_tx_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_TX_SIZE_OFFSET); } +static inline void udma_mram_tx_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_TX_SIZE_OFFSET, value); } + +static inline uint32_t udma_mram_tx_cfg_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_TX_CFG_OFFSET); } +static inline void udma_mram_tx_cfg_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_TX_CFG_OFFSET, value); } + +static inline uint32_t udma_mram_tx_daddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_TX_DADDR_OFFSET); } +static inline void udma_mram_tx_daddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_TX_DADDR_OFFSET, value); } + +static inline uint32_t udma_mram_rx_daddr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_RX_DADDR_OFFSET); } +static inline void udma_mram_rx_daddr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_RX_DADDR_OFFSET, value); } + +static inline uint32_t udma_mram_status_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_STATUS_OFFSET); } +static inline void udma_mram_status_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_STATUS_OFFSET, value); } + +static inline uint32_t udma_mram_mram_mode_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_MRAM_MODE_OFFSET); } +static inline void udma_mram_mram_mode_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_MRAM_MODE_OFFSET, value); } + +static inline uint32_t udma_mram_erase_addr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_ERASE_ADDR_OFFSET); } +static inline void udma_mram_erase_addr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_ERASE_ADDR_OFFSET, value); } + +static inline uint32_t udma_mram_erase_size_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_ERASE_SIZE_OFFSET); } +static inline void udma_mram_erase_size_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_ERASE_SIZE_OFFSET, value); } + +static inline uint32_t udma_mram_clock_div_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_CLOCK_DIV_OFFSET); } +static inline void udma_mram_clock_div_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_CLOCK_DIV_OFFSET, value); } + +static inline uint32_t udma_mram_trigger_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_TRIGGER_OFFSET); } +static inline void udma_mram_trigger_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_TRIGGER_OFFSET, value); } + +static inline uint32_t udma_mram_isr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_ISR_OFFSET); } +static inline void udma_mram_isr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_ISR_OFFSET, value); } + +static inline uint32_t udma_mram_ier_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_IER_OFFSET); } +static inline void udma_mram_ier_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_IER_OFFSET, value); } + +static inline uint32_t udma_mram_icr_get(uint32_t base) { return ARCHI_READ(base, UDMA_MRAM_ICR_OFFSET); } +static inline void udma_mram_icr_set(uint32_t base, uint32_t value) { ARCHI_WRITE(base, UDMA_MRAM_ICR_OFFSET, value); } + +#endif + + + +// +// REGISTERS FIELDS MACROS +// + +#ifndef LANGUAGE_ASSEMBLY + +#define UDMA_MRAM_RX_SADDR_RX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_MRAM_RX_SADDR_RX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_MRAM_RX_SADDR_RX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_MRAM_RX_SADDR_RX_SADDR(val) ((val) << 0) + +#define UDMA_MRAM_RX_SIZE_RX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MRAM_RX_SIZE_RX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MRAM_RX_SIZE_RX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MRAM_RX_SIZE_RX_SIZE(val) ((val) << 0) + +#define UDMA_MRAM_RX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_RX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_RX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_RX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_MRAM_RX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_MRAM_RX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_MRAM_RX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_MRAM_RX_CFG_EN(val) ((val) << 4) + +#define UDMA_MRAM_RX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MRAM_RX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MRAM_RX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MRAM_RX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_MRAM_RX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define UDMA_MRAM_RX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define UDMA_MRAM_RX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define UDMA_MRAM_RX_CFG_CLR(val) ((val) << 6) + +#define UDMA_MRAM_TX_SADDR_TX_SADDR_GET(value) (ARCHI_BEXTRACTU((value),16,0)) +#define UDMA_MRAM_TX_SADDR_TX_SADDR_GETS(value) (ARCHI_BEXTRACT((value),16,0)) +#define UDMA_MRAM_TX_SADDR_TX_SADDR_SET(value,field) (ARCHI_BINSERT((value),(field),16,0)) +#define UDMA_MRAM_TX_SADDR_TX_SADDR(val) ((val) << 0) + +#define UDMA_MRAM_TX_SIZE_TX_SIZE_GET(value) (ARCHI_BEXTRACTU((value),17,0)) +#define UDMA_MRAM_TX_SIZE_TX_SIZE_GETS(value) (ARCHI_BEXTRACT((value),17,0)) +#define UDMA_MRAM_TX_SIZE_TX_SIZE_SET(value,field) (ARCHI_BINSERT((value),(field),17,0)) +#define UDMA_MRAM_TX_SIZE_TX_SIZE(val) ((val) << 0) + +#define UDMA_MRAM_TX_CFG_CONTINOUS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_TX_CFG_CONTINOUS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_TX_CFG_CONTINOUS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_TX_CFG_CONTINOUS(val) ((val) << 0) + +#define UDMA_MRAM_TX_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_MRAM_TX_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_MRAM_TX_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_MRAM_TX_CFG_EN(val) ((val) << 4) + +#define UDMA_MRAM_TX_CFG_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MRAM_TX_CFG_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MRAM_TX_CFG_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MRAM_TX_CFG_PENDING(val) ((val) << 5) + +#define UDMA_MRAM_TX_CFG_CLR_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define UDMA_MRAM_TX_CFG_CLR_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define UDMA_MRAM_TX_CFG_CLR_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define UDMA_MRAM_TX_CFG_CLR(val) ((val) << 6) + +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_GET(value) (ARCHI_BEXTRACTU((value),19,0)) +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_GETS(value) (ARCHI_BEXTRACT((value),19,0)) +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),19,0)) +#define UDMA_MRAM_TX_DADDR_TX_DST_ADDR(val) ((val) << 0) + +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_GET(value) (ARCHI_BEXTRACTU((value),19,0)) +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_GETS(value) (ARCHI_BEXTRACT((value),19,0)) +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),19,0)) +#define UDMA_MRAM_RX_DADDR_RX_DST_ADDR(val) ((val) << 0) + +#define UDMA_MRAM_STATUS_ERASE_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_STATUS_ERASE_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_STATUS_ERASE_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_STATUS_ERASE_PENDING(val) ((val) << 0) + +#define UDMA_MRAM_STATUS_TX_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define UDMA_MRAM_STATUS_TX_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define UDMA_MRAM_STATUS_TX_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define UDMA_MRAM_STATUS_TX_BUSY(val) ((val) << 1) + +#define UDMA_MRAM_STATUS_RX_BUSY_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define UDMA_MRAM_STATUS_RX_BUSY_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define UDMA_MRAM_STATUS_RX_BUSY_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define UDMA_MRAM_STATUS_RX_BUSY(val) ((val) << 2) + +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define UDMA_MRAM_STATUS_REF_LINE_PENDING_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define UDMA_MRAM_STATUS_REF_LINE_PENDING(val) ((val) << 3) + +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_MRAM_MODE_ECC_BYPS(val) ((val) << 0) + +#define UDMA_MRAM_MRAM_MODE_DPD_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define UDMA_MRAM_MRAM_MODE_DPD_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define UDMA_MRAM_MRAM_MODE_DPD_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define UDMA_MRAM_MRAM_MODE_DPD(val) ((val) << 1) + +#define UDMA_MRAM_MRAM_MODE_AREF_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define UDMA_MRAM_MRAM_MODE_AREF_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define UDMA_MRAM_MRAM_MODE_AREF_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define UDMA_MRAM_MRAM_MODE_AREF(val) ((val) << 2) + +#define UDMA_MRAM_MRAM_MODE_TMEN_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define UDMA_MRAM_MRAM_MODE_TMEN_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define UDMA_MRAM_MRAM_MODE_TMEN_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define UDMA_MRAM_MRAM_MODE_TMEN(val) ((val) << 3) + +#define UDMA_MRAM_MRAM_MODE_NVR_GET(value) (ARCHI_BEXTRACTU((value),1,4)) +#define UDMA_MRAM_MRAM_MODE_NVR_GETS(value) (ARCHI_BEXTRACT((value),1,4)) +#define UDMA_MRAM_MRAM_MODE_NVR_SET(value,field) (ARCHI_BINSERT((value),(field),1,4)) +#define UDMA_MRAM_MRAM_MODE_NVR(val) ((val) << 4) + +#define UDMA_MRAM_MRAM_MODE_RST_B_GET(value) (ARCHI_BEXTRACTU((value),1,5)) +#define UDMA_MRAM_MRAM_MODE_RST_B_GETS(value) (ARCHI_BEXTRACT((value),1,5)) +#define UDMA_MRAM_MRAM_MODE_RST_B_SET(value,field) (ARCHI_BINSERT((value),(field),1,5)) +#define UDMA_MRAM_MRAM_MODE_RST_B(val) ((val) << 5) + +#define UDMA_MRAM_MRAM_MODE_RET_B_GET(value) (ARCHI_BEXTRACTU((value),1,6)) +#define UDMA_MRAM_MRAM_MODE_RET_B_GETS(value) (ARCHI_BEXTRACT((value),1,6)) +#define UDMA_MRAM_MRAM_MODE_RET_B_SET(value,field) (ARCHI_BINSERT((value),(field),1,6)) +#define UDMA_MRAM_MRAM_MODE_RET_B(val) ((val) << 6) + +#define UDMA_MRAM_MRAM_MODE_POR_B_GET(value) (ARCHI_BEXTRACTU((value),1,7)) +#define UDMA_MRAM_MRAM_MODE_POR_B_GETS(value) (ARCHI_BEXTRACT((value),1,7)) +#define UDMA_MRAM_MRAM_MODE_POR_B_SET(value,field) (ARCHI_BINSERT((value),(field),1,7)) +#define UDMA_MRAM_MRAM_MODE_POR_B(val) ((val) << 7) + +#define UDMA_MRAM_MRAM_MODE_CMD_GET(value) (ARCHI_BEXTRACTU((value),8,8)) +#define UDMA_MRAM_MRAM_MODE_CMD_GETS(value) (ARCHI_BEXTRACT((value),8,8)) +#define UDMA_MRAM_MRAM_MODE_CMD_SET(value,field) (ARCHI_BINSERT((value),(field),8,8)) +#define UDMA_MRAM_MRAM_MODE_CMD(val) ((val) << 8) + +#define UDMA_MRAM_ERASE_ADDR_ADDR_GET(value) (ARCHI_BEXTRACTU((value),19,0)) +#define UDMA_MRAM_ERASE_ADDR_ADDR_GETS(value) (ARCHI_BEXTRACT((value),19,0)) +#define UDMA_MRAM_ERASE_ADDR_ADDR_SET(value,field) (ARCHI_BINSERT((value),(field),19,0)) +#define UDMA_MRAM_ERASE_ADDR_ADDR(val) ((val) << 0) + +#define UDMA_MRAM_CLOCK_DIV_DATA_GET(value) (ARCHI_BEXTRACTU((value),8,0)) +#define UDMA_MRAM_CLOCK_DIV_DATA_GETS(value) (ARCHI_BEXTRACT((value),8,0)) +#define UDMA_MRAM_CLOCK_DIV_DATA_SET(value,field) (ARCHI_BINSERT((value),(field),8,0)) +#define UDMA_MRAM_CLOCK_DIV_DATA(val) ((val) << 0) + +#define UDMA_MRAM_CLOCK_DIV_EN_GET(value) (ARCHI_BEXTRACTU((value),1,8)) +#define UDMA_MRAM_CLOCK_DIV_EN_GETS(value) (ARCHI_BEXTRACT((value),1,8)) +#define UDMA_MRAM_CLOCK_DIV_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,8)) +#define UDMA_MRAM_CLOCK_DIV_EN(val) ((val) << 8) + +#define UDMA_MRAM_TRIGGER_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_TRIGGER_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_TRIGGER_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_TRIGGER_EN(val) ((val) << 0) + +#define UDMA_MRAM_ISR_ERASE_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_ISR_ERASE_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_ISR_ERASE_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_ISR_ERASE_DONE(val) ((val) << 0) + +#define UDMA_MRAM_ISR_PROGRAM_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define UDMA_MRAM_ISR_PROGRAM_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define UDMA_MRAM_ISR_PROGRAM_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define UDMA_MRAM_ISR_PROGRAM_DONE(val) ((val) << 1) + +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define UDMA_MRAM_ISR_TRIM_CFG_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define UDMA_MRAM_ISR_TRIM_CFG_DONE(val) ((val) << 2) + +#define UDMA_MRAM_ISR_REF_LINE_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define UDMA_MRAM_ISR_REF_LINE_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define UDMA_MRAM_ISR_REF_LINE_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define UDMA_MRAM_ISR_REF_LINE_DONE(val) ((val) << 3) + +#define UDMA_MRAM_IER_ERASE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_IER_ERASE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_IER_ERASE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_IER_ERASE_EN(val) ((val) << 0) + +#define UDMA_MRAM_IER_PROGRAM_EN_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define UDMA_MRAM_IER_PROGRAM_EN_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define UDMA_MRAM_IER_PROGRAM_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define UDMA_MRAM_IER_PROGRAM_EN(val) ((val) << 1) + +#define UDMA_MRAM_IER_TRIM_CFG_EN_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define UDMA_MRAM_IER_TRIM_CFG_EN_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define UDMA_MRAM_IER_TRIM_CFG_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define UDMA_MRAM_IER_TRIM_CFG_EN(val) ((val) << 2) + +#define UDMA_MRAM_IER_REF_LINE_EN_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define UDMA_MRAM_IER_REF_LINE_EN_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define UDMA_MRAM_IER_REF_LINE_EN_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define UDMA_MRAM_IER_REF_LINE_EN(val) ((val) << 3) + +#define UDMA_MRAM_ICR_ERASE_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,0)) +#define UDMA_MRAM_ICR_ERASE_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,0)) +#define UDMA_MRAM_ICR_ERASE_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,0)) +#define UDMA_MRAM_ICR_ERASE_DONE(val) ((val) << 0) + +#define UDMA_MRAM_ICR_PROGRAM_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,1)) +#define UDMA_MRAM_ICR_PROGRAM_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,1)) +#define UDMA_MRAM_ICR_PROGRAM_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,1)) +#define UDMA_MRAM_ICR_PROGRAM_DONE(val) ((val) << 1) + +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,2)) +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,2)) +#define UDMA_MRAM_ICR_TRIM_CFG_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,2)) +#define UDMA_MRAM_ICR_TRIM_CFG_DONE(val) ((val) << 2) + +#define UDMA_MRAM_ICR_REF_LINE_DONE_GET(value) (ARCHI_BEXTRACTU((value),1,3)) +#define UDMA_MRAM_ICR_REF_LINE_DONE_GETS(value) (ARCHI_BEXTRACT((value),1,3)) +#define UDMA_MRAM_ICR_REF_LINE_DONE_SET(value,field) (ARCHI_BINSERT((value),(field),1,3)) +#define UDMA_MRAM_ICR_REF_LINE_DONE(val) ((val) << 3) + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v1.h b/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v1.h new file mode 100644 index 0000000..9035f60 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v1.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_SPIM_V1_H__ +#define __ARCHI_UDMA_UDMA_SPIM_V1_H__ + +#define SPIM_RX_SADDR_OFFSET 0x000 +#define SPIM_RX_SIZE_OFFSET 0x004 +#define SPIM_RX_CFG_OFFSET 0x008 +#define SPIM_RX_INTCFG_OFFSET 0x00C + +#define SPIM_TX_SADDR_OFFSET 0x010 +#define SPIM_TX_SIZE_OFFSET 0x014 +#define SPIM_TX_CFG_OFFSET 0x018 +#define SPIM_TX_INTCFG_OFFSET 0x01C + +#define SPIM_STATUS_OFFSET 0x000 +#define SPIM_CLKDIV_OFFSET 0x004 +#define SPIM_SPICMD_OFFSET 0x008 +#define SPIM_SPIADR_OFFSET 0x00C +#define SPIM_SPILEN_OFFSET 0x010 +#define SPIM_SPIDUM_OFFSET 0x014 +#define SPIM_TXFIFO_OFFSET 0x018 +#define SPIM_RXFIFO_OFFSET 0x01C + + +#define ARCHI_SPIM_WSTATUS_QWRITE 8 +#define ARCHI_SPIM_WSTATUS_QREAD 4 +#define ARCHI_SPIM_WSTATUS_WRITE 2 +#define ARCHI_SPIM_WSTATUS_READ 1 + +#define ARCHI_SPIM_WSTATUS_CSKEEP_BIT 16 +#define ARCHI_SPIM_WSTATUS_CS_BIT 8 +#define ARCHI_SPIM_WSTATUS_RESET_BIT 4 +#define ARCHI_SPIM_WSTATUS_CMD_BIT 0 + +#define ARCHI_SPIM_RSTATUS_DATA_RX_BIT 6 +#define ARCHI_SPIM_RSTATUS_DATA_TX_BIT 5 +#define ARCHI_SPIM_RSTATUS_DUMMY_BIT 4 +#define ARCHI_SPIM_RSTATUS_MODE_BIT 3 +#define ARCHI_SPIM_RSTATUS_ADDR_BIT 2 +#define ARCHI_SPIM_RSTATUS_CMD_BIT 1 +#define ARCHI_SPIM_RSTATUS_IDLE_BIT 0 + +#define ARCHI_SPIM_CLKDIV_DATASIZE_TX_BIT 18 +#define ARCHI_SPIM_CLKDIV_DATASIZE_RX_BIT 16 +#define ARCHI_SPIM_CLKDIV_CPHA_BIT 9 +#define ARCHI_SPIM_CLKDIV_CPOL_BIT 8 +#define ARCHI_SPIM_CLKDIV_CLKDIV_BIT 0 + +#define SPIM_CMD_RD 0 +#define SPIM_CMD_WR 1 +#define SPIM_CMD_QRD 2 +#define SPIM_CMD_QWR 3 + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v2.h b/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v2.h new file mode 100644 index 0000000..0d5dd87 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/spim/udma_spim_v2.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_SPIM_V2_H__ +#define __ARCHI_UDMA_UDMA_SPIM_V2_H__ + +// SPI commands IDS definition +#define SPI_CMD_CFG_ID 0 +#define SPI_CMD_SOT_ID 1 +#define SPI_CMD_SEND_CMD_ID 2 +#define SPI_CMD_SEND_ADDR_ID 3 +#define SPI_CMD_DUMMY_ID 4 +#define SPI_CMD_WAIT_ID 5 +#define SPI_CMD_TX_DATA_ID 6 +#define SPI_CMD_RX_DATA_ID 7 +#define SPI_CMD_RPT_ID 8 +#define SPI_CMD_EOT_ID 9 +#define SPI_CMD_RPT_END_ID 10 +#define SPI_CMD_RX_CHECK_ID 11 +#define SPI_CMD_FUL_ID 12 + +// SPI command fields offset, mask, value definition +// SPI commands fields offsets +#define SPI_CMD_ID_OFFSET 28 +#define SPI_CMD_ID_WIDTH 4 + +// COMMON definitions +#define SPI_CMD_QPI_ENA 1 +#define SPI_CMD_QPI_DIS 0 +#define SPI_CMD_BYTE_ALIGN_DIS 1 +#define SPI_CMD_BYTE_ALIGN_ENA 0 +#define SPI_CMD_DATA_WITDH(val) (val) +#define SPI_CMD_CMD_SIZE(val) (val) + +// CFG +#define SPI_CMD_CFG_CLK_DIV_OFFSET 0 +#define SPI_CMD_CFG_CLK_DIV_WIDTH 8 +#define SPI_CMD_CFG_CPHA_OFFSET 8 +#define SPI_CMD_CFG_CPOL_OFFSET 9 + +#define SPI_CMD_CFG_CLKDIV(val) (val) +#define SPI_CMD_CFG_CPOL_POS 1 +#define SPI_CMD_CFG_CPOL_NEG 0 +#define SPI_CMD_CFG_CPHA_STD 1 +#define SPI_CMD_CFG_CPHA_OPP 0 + +// SOT +#define SPI_CMD_SOT_CS_OFFSET 0 +#define SPI_CMD_SOT_CS_WIDTH 2 + +#define SPI_CMD_SOT_CS0 0 +#define SPI_CMD_SOT_CS1 1 +#define SPI_CMD_SOT_CS2 2 +#define SPI_CMD_SOT_CS3 3 + +// SEND_CMD +#define SPI_CMD_SEND_CMD_CMD_OFFSET 0 +#define SPI_CMD_SEND_CMD_CMD_WIDTH 16 +#define SPI_CMD_SEND_CMD_SIZE_OFFSET 16 +#define SPI_CMD_SEND_CMD_SIZE_WIDTH 4 +#define SPI_CMD_SEND_CMD_QPI_OFFSET 27 + +// SEND_ADDR +#define SPI_CMD_SEND_ADDR_SIZE_OFFSET 16 +#define SPI_CMD_SEND_ADDR_SIZE_WIDTH 5 +#define SPI_CMD_SEND_ADDR_QPI_OFFSET 27 + +//#define SPI_CMD_SEND_ADDR_VALUE(value) ((((value) & 0xff000000) >> 24) | (((value) & 0xff0000) >> 8) | (((value) & 0xff00) << 8) | (((value) & 0xff) << 24)) +#define SPI_CMD_SEND_ADDR_VALUE(value) (value) + + +// SEND_DUMMY +#define SPI_CMD_DUMMY_CYCLE_OFFSET 16 +#define SPI_CMD_DUMMY_CYCLE_WIDTH 5 + +// TX_DATA +#define SPI_CMD_TX_DATA_SIZE_OFFSET 0 +#define SPI_CMD_TX_DATA_SIZE_WIDTH 16 +#define SPI_CMD_TX_DATA_BYTE_ALIGN_OFFSET 26 +#define SPI_CMD_TX_DATA_QPI_OFFSET 27 + +// RX_DATA +#define SPI_CMD_RX_DATA_SIZE_OFFSET 0 +#define SPI_CMD_RX_DATA_SIZE_WIDTH 16 +#define SPI_CMD_RX_DATA_BYTE_ALIGN_OFFSET 26 +#define SPI_CMD_RX_DATA_BYTE_ALIGN_WIDTH 1 +#define SPI_CMD_RX_DATA_QPI_OFFSET 27 +#define SPI_CMD_RX_DATA_QPI_WIDTH 1 + +// RPT +#define SPI_CMD_RPT_NB_OFFSET 0 +#define SPI_CMD_RPT_NB_WIDTH 16 + +// EOT +#define SPI_CMD_EOT_GEN_EVT_OFFSET 0 + +#define SPI_CMD_EOT_EVENT_ENA 1 +#define SPI_CMD_EOT_EVENT_DIS 0 + +// WAIT +#define SPI_CMD_WAIT_EVENT_OFFSET 0 +#define SPI_CMD_WAIT_EVENT_WIDTH 2 + +// RX_CHECK +#define SPI_CMD_RX_CHECK_VALUE_OFFSET 0 +#define SPI_CMD_RX_CHECK_VALUE_WIDTH 16 + +#define SPI_CMD_RX_CHECK_SIZE_OFFSET 16 +#define SPI_CMD_RX_CHECK_SIZE_WIDTH 4 + +#define SPI_CMD_RX_CHECK_MODE_OFFSET 24 +#define SPI_CMD_RX_CHECK_MODE_WIDTH 2 + +#define SPI_CMD_RX_CHECK_BYTE_ALIGN_OFFSET 26 + +#define SPI_CMD_RX_CHECK_QPI_OFFSET 27 + +#define SPI_CMD_RX_CHECK_MODE_MATCH 0 +#define SPI_CMD_RX_CHECK_MODE_ONES 1 +#define SPI_CMD_RX_CHECK_MODE_ZEROS 2 +#define SPI_CMD_RX_CHECK_MODE_MASK 3 + +// FULL DUPLEX +#define SPI_CMD_FUL_SIZE_OFFSET 0 +#define SPI_CMD_FUL_SIZE_WIDTH 16 +#define SPI_CMD_FUL_BYTE_ALIGN_OFFSET 26 +#define SPI_CMD_FUL_BYTE_ALIGN_WIDTH 1 + +// SPI CMD encoding +#define SPI_CMD_CFG(clockDiv,cpol,cpha) ((SPI_CMD_CFG_ID<>8)<> 24) | (((value) & 0xff0000) >> 8) | (((value) & 0xff00) << 8) | (((value) & 0xff) << 24)) +#define SPI_CMD_SEND_ADDR_VALUE(value) (value) + + +// SEND_DUMMY +#define SPI_CMD_DUMMY_CYCLE_OFFSET 16 +#define SPI_CMD_DUMMY_CYCLE_WIDTH 5 + +// TX_DATA +#define SPI_CMD_TX_DATA_SIZE_OFFSET 0 +#define SPI_CMD_TX_DATA_SIZE_WIDTH 16 +#define SPI_CMD_TX_DATA_QPI_OFFSET 27 +#define SPI_CMD_TX_DATA_WORDTRANS_OFFSET 21 +#define SPI_CMD_TX_DATA_WORDTRANS_WIDTH 2 +#define SPI_CMD_TX_DATA_LSBFIRST_OFFSET 26 +#define SPI_CMD_TX_DATA_BITSWORD_OFFSET 16 +#define SPI_CMD_TX_DATA_BITSWORD_WIDTH 5 + + +// RX_DATA +#define SPI_CMD_RX_DATA_SIZE_OFFSET 0 +#define SPI_CMD_RX_DATA_SIZE_WIDTH 16 +#define SPI_CMD_RX_DATA_QPI_OFFSET 27 +#define SPI_CMD_RX_DATA_WORDTRANS_OFFSET 21 +#define SPI_CMD_RX_DATA_WORDTRANS_WIDTH 2 +#define SPI_CMD_RX_DATA_LSBFIRST_OFFSET 26 +#define SPI_CMD_RX_DATA_BITSWORD_OFFSET 16 +#define SPI_CMD_RX_DATA_BITSWORD_WIDTH 5 + + +// RPT +#define SPI_CMD_RPT_NB_OFFSET 0 +#define SPI_CMD_RPT_NB_WIDTH 16 + +// EOT +#define SPI_CMD_EOT_GEN_EVT_OFFSET 0 +#define SPI_CMD_EOT_CS_KEEP_OFFSET 1 + +#define SPI_CMD_EOT_EVENT_ENA 1 +#define SPI_CMD_EOT_EVENT_DIS 0 + +// WAIT +#define SPI_CMD_WAIT_EVENT_OFFSET 0 +#define SPI_CMD_WAIT_EVENT_WIDTH 2 + +// RX_CHECK +#define SPI_CMD_RX_CHECK_VALUE_OFFSET 0 +#define SPI_CMD_RX_CHECK_VALUE_WIDTH 16 + +#define SPI_CMD_RX_CHECK_SIZE_OFFSET 16 +#define SPI_CMD_RX_CHECK_SIZE_WIDTH 4 + +#define SPI_CMD_RX_CHECK_MODE_OFFSET 24 +#define SPI_CMD_RX_CHECK_MODE_WIDTH 2 + +#define SPI_CMD_RX_CHECK_BYTE_ALIGN_OFFSET 26 + +#define SPI_CMD_RX_CHECK_QPI_OFFSET 27 + +#define SPI_CMD_RX_CHECK_MODE_MATCH 0 +#define SPI_CMD_RX_CHECK_MODE_ONES 1 +#define SPI_CMD_RX_CHECK_MODE_ZEROS 2 +#define SPI_CMD_RX_CHECK_MODE_MASK 3 + +// FULL DUPLEX +#define SPI_CMD_FUL_SIZE_OFFSET 0 +#define SPI_CMD_FUL_SIZE_WIDTH 16 +#define SPI_CMD_FUL_WORDTRANS_OFFSET 21 +#define SPI_CMD_FUL_WORDTRANS_WIDTH 2 +#define SPI_CMD_FUL_LSBFIRST_OFFSET 26 +#define SPI_CMD_FUL_BITSWORD_OFFSET 16 +#define SPI_CMD_FUL_BITSWORD_WIDTH 5 + +#define SPI_CMD_SETUP_UC_TXRXEN_OFFSET 27 +#define SPI_CMD_SETUP_UC_DS_OFFSET 25 + +// SPI CMD encoding +#define SPI_CMD_CFG(clockDiv,cpol,cpha) ((SPI_CMD_CFG_ID<>UDMA_PERIPH_AREA_SIZE_LOG2) + +// Return the offset of a channel from its identifier +#define UDMA_CHANNEL_OFFSET(id) ((id)*UDMA_CHANNEL_SIZE) + +// Returns the identifier of a channel from its offset +#define UDMA_CHANNEL_GET(offset) ((offset)>>UDMA_CHANNEL_SIZE_LOG2) + + + + + + + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/udma/udma_v2.h b/sw/pulp-sdk/archi/include/archi/udma/udma_v2.h new file mode 100644 index 0000000..7633a0d --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/udma/udma_v2.h @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2018 ETH Zurich and University of Bologna + * + * 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. + */ + +#ifndef __ARCHI_UDMA_UDMA_V2_H__ +#define __ARCHI_UDMA_UDMA_V2_H__ + +/* + * Global register map + */ + +// The UDMA register map is made of several channels, each channel area size is defined just below + +// Periph area size in log2 +#define UDMA_PERIPH_AREA_SIZE_LOG2 7 + +// Periph area size +#define UDMA_PERIPH_AREA_SIZE (1<>UDMA_PERIPH_AREA_SIZE_LOG2) + +// Return the offset of a channel from its identifier +#define UDMA_CHANNEL_OFFSET(id) ((id)<>UDMA_CHANNEL_SIZE_LOG2) + +// Return the id of a channel from the peripheral id +#define UDMA_CHANNEL_ID(id) ((id)*2) + +// Return the number of events per peripheral +#define UDMA_NB_PERIPH_EVENTS_LOG2 1 +#define UDMA_NB_PERIPH_EVENTS (1<>UDMA_PERIPH_AREA_SIZE_LOG2) + +// Return the offset of a channel from its identifier +#define UDMA_CHANNEL_OFFSET(id) ((id)<>UDMA_CHANNEL_SIZE_LOG2) + +// Return the id of a channel from the peripheral id +#define UDMA_CHANNEL_ID(id) ((id)*2) + +// Return the number of events per peripheral +#define UDMA_NB_PERIPH_EVENTS_LOG2 2 +#define UDMA_NB_PERIPH_EVENTS (1<> (offset)) + + +#ifndef LANGUAGE_ASSEMBLY + +#define archi_write8(add, val_) (*(volatile unsigned char *)(long)(add) = val_) +#define archi_write16(add, val_) (*(volatile unsigned short *)(long)(add) = val_) +#define archi_write32(add, val_) (*(volatile unsigned int *)(long)(add) = val_) +#define archi_write(add, val_) (*(volatile unsigned int *)(long)(add) = val_) + +#define archi_read8(add) (*(volatile unsigned char *)(long)(add)) +#define archi_read16(add) (*(volatile unsigned short *)(long)(add)) +#define archi_read32(add) (*(volatile unsigned int *)(long)(add)) +#define archi_read(add) (*(volatile unsigned int *)(long)(add)) + + +#if defined(__riscv__) && !defined(__LLVM__) && !defined(RV_ISA_RV32) +#define ARCHI_WRITE_VOL(base, offset, value) __builtin_pulp_write_base_off_v((value), (base), (offset)) +#define ARCHI_WRITE(base, offset, value) __builtin_pulp_OffsetedWrite((value), (int *)(base), (offset)) +#define ARCHI_READ(base, offset) __builtin_pulp_OffsetedRead((int *)(base), (offset)) +#else +#define ARCHI_WRITE_VOL(base, offset, value) archi_write32((base) + (offset), (value)) +#define ARCHI_WRITE(base, offset, value) archi_write32((base) + (offset), (value)) +#define ARCHI_READ(base, offset) archi_read32((base) + (offset)) +#endif + + +#include "archi/riscv/builtins_v2.h" +#include "archi/riscv/builtins_v2_emu.h" + +#define ARCHI_BINSERT(dst,src,size,off) __BITINSERT(dst,src,size,off) +#define ARCHI_BINSERT_R(dst,src,size,off) __BITINSERT_R(dst,src,size,off) +#define ARCHI_BEXTRACTU(src,size,off) __BITEXTRACTU(src,size,off) +#define ARCHI_BEXTRACT(src,size,off) __BITEXTRACT(src,size,off) + +#endif + +#endif \ No newline at end of file diff --git a/sw/pulp-sdk/archi/include/archi/vendors/dolphin/rtc.h b/sw/pulp-sdk/archi/include/archi/vendors/dolphin/rtc.h new file mode 100644 index 0000000..de53751 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/vendors/dolphin/rtc.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_RTC_H__ +#define __ARCHI_RTC_H__ + +/* + * The RTC should be used through the APB interface. In this header file, there are: + * - APB registers which are direct access registers, with ADDR: ( SOC_PERIPHERALS_BASE_ADDR + 0x7000 + APB_RTC_**_OFFSET) + * - RTC registers which are indirect access registers. These regs should be R/W via the APB registers. + * + * For distinguishing these two types of registers: + * - APB registers: All the defines are named in UPPER_CASE + * - RTC registers: All the difines are named in Initial_Capitalization + * + * ARCHI_RTC_ADDR = ( SOC_PERIPHERALS_BASE_ADDR + 0x8000 ) + */ + + +#define RTC_RTC_INT_EVENT ARCHI_SOC_EVENT_RTC_IRQ +#define RTC_RTC_APB_EVENT ARCHI_SOC_EVENT_RTC_APB_IRQ + +// Address of APB registers +#define APB_RTC_STAT_OFFSET 0x00 +#define APB_RTC_CTRL_OFFSET 0x04 +#define APB_RTC_DATA_OFFSET 0x08 +#define APB_RTC_IRQ_CTRL_OFFSET 0x10 +#define APB_RTC_IRQ_MASK_OFFSET 0x14 +#define APB_RTC_IRQ_FLAG_OFFSET 0x18 + +#define APB_RTC_STAT_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_STAT_OFFSET) +#define APB_RTC_CTRL_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_CTRL_OFFSET) +#define APB_RTC_DATA_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_DATA_OFFSET) +#define APB_RTC_IRQ_CTRL_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_IRQ_CTRL_OFFSET) +#define APB_RTC_IRQ_MASK_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_IRQ_MASK_OFFSET) +#define APB_RTC_IRQ_FLAG_REG_ADDR (ARCHI_RTC_ADDR + APB_RTC_IRQ_FLAG_OFFSET) + +// Bit field of APB registers +#define APB_RTC_NOIRQ_REQ 0x00 // APB_RTC_Status [0:1] +#define APB_RTC_IRQ_REQ 0x01 // APB_RTC_Status [0:1] +#define APB_RTC_READ 0x00 +#define APB_RTC_WRITE 0x01 +#define APB_IRQ_HIGH_LEVEL 0x00 // The generated INT_APB is a high level +#define APB_IRQ_LOW_LEVEL 0x01 // The generated INT_APB is a low level +#define APB_IRQ_HIGH_LEVEL_PULSE 0x02 // The generated INT_APB is a high level pulse with a duration of 1 CKIN cycle +#define APB_IRQ_LOW_LEVEL_PULSE 0x03 // The generated INT_APB is a low level pulse with a duration of 1 CKIN cycle +#define APB_WRITE_IRQ_MASKED 0x01 // 0x0 APB Write Operation Irq Enabled +#define APB_READ_IRQ_MASKED 0x01 // 0x0 APB Read Operation Irq Enabled +#define APB_W_Flag 0x02 // b'1 of APB_RTC_IRQ_FLAG_REG_ADDR +#define APB_R_Flag 0x01 // b'0 of APB_RTC_IRQ_FLAG_REG_ADDR +#define APB_SR_MASK 0x03 + +//***************************************************** +// Address of Indirect Access Register +//***************************************************** +#define RTC_Status_Addr 0x00 +#define RTC_Ctrl_Addr 0x01 +#define RTC_Clk_Ctrl_Addr 0x02 +#define RTC_IRQ_Ctrl_Addr 0x08 +#define RTC_IRQ_Mask_Addr 0x09 +#define RTC_IRQ_Flag_Addr 0x0A +#define RTC_Calendar_Ctrl_Addr 0x10 +#define RTC_Calendar_TIME_Addr 0x12 +#define RTC_Calendar_DATE_Addr 0x13 +#define RTC_Alarm_Ctrl_Addr 0x18 +#define RTC_Alarm1_TIME_Addr 0x1A +#define RTC_Alarm1_DATE_Addr 0x1B +#define RTC_CntDown_Ctrl_Addr 0x20 +#define RTC_CntDown1_Init_Addr 0x21 +#define RTC_CntDown1_Timer_Addr 0x22 +#define RTC_CKIN_DIV1_Addr 0x28 +#define RTC_Ref_Clk_Conf_Addr 0x2A +#define RTC_Test_Addr 0x30 + +// Bit field of RTC indirect Access Register +#define RTC_IRQ_REQ 0x01 // RTC_Status [0:1] +#define RTC_Soft_Reset 0x01 // 0x00: No soft reset +#define RTC_Calibration_Enable 0x01 // 0x00: Calibration disable +#define RTC_Active_Mode 0x00 +#define RTC_Standby_Mode 0x01 +#define RTC_CKOUT_Auto_Calibrated 0x01 // 0x00: CKOUT not auto calibrated +#define RTC_CKOUT_Not_Generated 0x01 // 0x00: CKOUT is generated +#define RTC_Irq_High_Level 0x00 // The generated INT_RTC is a high level +#define RTC_Irq_Low_Level 0x01 // The generated INT_RTC is a low level +#define RTC_Irq_High_Level_Pulse 0x02 // The generated INT_RTC is a high level pulse with a duration of 1 CKIN cycle +#define RTC_Irq_Low_Level_Pulse 0x03 // The generated INT_RTC is a low level pulse with a duration of 1 CKIN cycle +#define RTC_Calibration_Irq_Masked 0x01 // Calibration Irq Enabled +#define RTC_Timer1_Irq_Enable 0x00 // Countdown timer 1 irq enabled +#define RTC_Timer1_Irq_Masked 0x01 // Countdown timer 1 irq masked; +#define RTC_Alarm1_Irq_Enable 0x00 // Alarm 1 irq masked; When 0 Alarm 1 irq enabled +#define RTC_Alarm1_Irq_Masked 0x01 // Alarm 1 irq masked; When 0 Alarm 1 irq enabled +#define RTC_Calendar_Inactive 0x01 // 0x0: Calendar is active +#define RTC_Alarm_Rpt_Mode 0x01 // 0x0: Single Mode +#define RTC_Alarm_ON 0x00 // 0x0: Alarm1 is active +#define RTC_Alarm_OFF 0x01 // 0x0: Alarm1 is active +#define RTC_CountDown1_Rpt_Mode 0x01 // 0x0: Single Mode +#define RTC_CountDown1_Active 0x00 // 0x0: Countdown 1 is active +#define RTC_CountDown1_Inactive 0x01 + +#define RTC_Irq_Alarm1_Flag 0x01 +#define RTC_Irq_Timer1_Flag 0x10 +#define RTC_Irq_Calibration_Flag 0x1000 + +#ifndef LANGUAGE_ASSEMBLY + +/* Structure for APB RTC registers */ +typedef union { + struct { + unsigned int apb_addr:6; // Indirect access address, address range [0:3F] + unsigned int pad:10; + unsigned int apb_load:1; /* Indirect access load bit: + 0: APB read operation + 1: APB write operation + */ + unsigned int pad1:15; + }; + unsigned int raw; +}Apb_rtc_ctrlT; + +typedef union { + struct { + unsigned int irq_form:2; + unsigned int pad:30; + }; + unsigned int raw; +}Apb_irq_ctrlT; + +typedef union { + struct { + unsigned int readMask:1; + unsigned int writeMask:1; + unsigned int pad:30; + }; + unsigned int raw; +}Apb_irq_maskT; + +typedef union{ + Apb_rtc_ctrlT rtcCtrl; + Apb_irq_ctrlT irqCtrl; + Apb_irq_maskT irqMask; + unsigned int Raw; +}Apb_rtcT; + +//============================================================= +/* Structure for indirect access registers */ + +typedef union { + struct{ + unsigned int rtc_sb:1; + unsigned int pad:3; + unsigned int cal_En:1; + unsigned int pad1:3; + unsigned int soft_rst:1; + unsigned int pad2:23; + }; + unsigned int raw; +}Rtc_ctrlT; + +typedef union{ + struct{ + unsigned int clkOut_sb:1; + unsigned int pad:11; + unsigned int div1_autoCal:1; + unsigned int pad1:3; + unsigned int div1_comp:5; + unsigned int pad2:11; + }; + unsigned int raw; +}Rtc_clk_ctrlT; + +typedef union{ + struct{ + unsigned int irq_form:2; + unsigned int pad:30; + }; + unsigned int raw; +}Rtc_irq_ctrlT; + +typedef union{ + struct{ + unsigned int alarm1_masked:1; + unsigned int pad:3; + unsigned int timer1_masked:1; + unsigned int pad1:7; + unsigned int cal_masked:1; + unsigned int pad2:19; + }; + unsigned int raw; +}Rtc_irq_maskT; + +typedef union{ + struct{ + unsigned int calend_En:1; + unsigned int pad:31; + }; + unsigned int raw; +}Rtc_calend_ctrlT; + +typedef union{ + struct{ + unsigned int second_0:4; + unsigned int second_1:4; + unsigned int minute_0:4; + unsigned int minute_1:4; + unsigned int hour_0:4; + unsigned int hour_1:4; + }; + unsigned int raw; +}Rtc_calend_timeT; + +typedef union{ + struct{ + unsigned int day_0:4; + unsigned int day_1:4; + unsigned int month_0:4; + unsigned int month_1:4; + unsigned int year_0:4; + unsigned int year_1:4; + }; + unsigned int raw; +}Rtc_calend_dateT; + +typedef union{ + struct{ + unsigned int alarm1_En:1; + unsigned int pad:3; + unsigned int alarm1_mode:1; + unsigned int pad1:11; + unsigned int alarm1_conf:4; + unsigned int pad2:12; + }; + unsigned int raw; +}Rtc_alarm_ctrlT; + +typedef union{ + struct{ + unsigned int cntDwn1_En:1; + unsigned int pad:3; + unsigned int cntDwn1_mode:1; + unsigned int pad1:27; + }; + unsigned int raw; +}Rtc_cntDwn_ctrlT; + +typedef union { + struct{ + unsigned int divVal:16; + unsigned int pad:16; + }; + unsigned int raw; +}Rtc_CKIN_divT; + +typedef union{ + struct{ + unsigned int refClkVal:22; + unsigned int pad:10; + }; + unsigned int raw; +}Rtc_ref_clkT; + +typedef union{ +// unsigned int status; + Rtc_ctrlT conf; + Rtc_clk_ctrlT clkConf; + Rtc_irq_ctrlT irqConf; + Rtc_irq_maskT irqMask; +// unsigned int irqFlag; + Rtc_calend_ctrlT calendConf; +// unsigned int calendTime; +// unsigned int calendDate; + Rtc_alarm_ctrlT alarmCtrl; +// unsigned int alarmTime; +// unsigned int alarmDate; + Rtc_cntDwn_ctrlT cntDwnCtrl; +// unsigned int cntDwn1InitVal; +// unsigned int cntDwn1Val; + Rtc_CKIN_divT ckinDiv; + Rtc_ref_clkT refClk; + unsigned int Raw; +}RtcT; + +#endif + +#endif diff --git a/sw/pulp-sdk/archi/include/archi/vendors/iid/quiddikey_v1.h b/sw/pulp-sdk/archi/include/archi/vendors/iid/quiddikey_v1.h new file mode 100644 index 0000000..5337910 --- /dev/null +++ b/sw/pulp-sdk/archi/include/archi/vendors/iid/quiddikey_v1.h @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2018 GreenWaves Technologies + * + * 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. + */ + +#ifndef __ARCHI_IID_QUIDDIKEY_V1_H__ +#define __ARCHI_IID_QUIDDIKEY_V1_H__ + +// Registers offset definition +#define APB_QK_CR_OFFSET (0x00) +#define APB_QK_SR_OFFSET (0x08) +#define APB_QK_AR_OFFSET (0x0C) +#define APB_QK_IER_OFFSET (0x10) +#define APB_QK_IMR_OFFSET (0x14) +#define APB_QK_ISR_OFFSET (0x18) +#define APB_QK_KEY_DEST_OFFSET (0x20) +#define APB_QK_DIR_OFFSET (0xA0) +#define APB_QK_DOR_OFFSET (0xA8) +#define APB_QK_MISC_OFFSET (0xC0) +#define APB_QK_IF_SR_OFFSET (0xD0) +#define APB_QK_TEST_OFFSET (0xD8) +#define APB_QK_HW_RUC0_OFFSET (0xE0) +#define APB_QK_HW_RUC1_OFFSET (0xE4) +#define APB_QK_HW_SET_OFFSET (0xF0) +#define APB_QK_HW_INFO_OFFSET (0xF4) +#define APB_QK_HW_ID_OFFSET (0xF8) +#define APB_QK_HW_VER_OFFSET (0xFC) + +// Registers bitfields offset, mask, value definition +// Configuration Register +#define APB_QK_CR_ZEROISE_BIT (0) +#define APB_QK_CR_ZEROISE_BITS (1) +#define APB_QK_CR_ZEROISE_MASK ARCHI_REG_MASK(APB_QK_CR_ZEROISE_BIT, APB_QK_CR_ZEROISE_BITS) +#define APB_QK_CR_ZEROISE_ENA (1< + * + * Copyright (C) 2014-2017 ETH Zurich, University of Bologna + * All rights reserved. + */ + +#ifndef __ARCHI_XNE_V1_H__ +#define __ARCHI_XNE_V1_H__ + +/* + * Control and generic configuration register layout + * ================================================================================ + * # reg | offset | bits | bitmask || content + * -------+----------+---------+--------------++----------------------------------- + * 0 | 0x0000 | 31: 0 | 0xffffffff || TRIGGER + * 1 | 0x0004 | 31: 0 | 0xffffffff || ACQUIRE + * 2 | 0x0008 | 31: 0 | 0xffffffff || EVT_ENABLE + * 3 | 0x000c | 31: 0 | 0xffffffff || STATUS + * 4 | 0x0010 | 31: 0 | 0xffffffff || RUNNING_JOB + * 5 | 0x0014 | 31: 0 | 0xffffffff || SOFT_CLEAR + * 6-7 | | | || Reserved + * 8 | 0x0020 | 31: 0 | 0xffffffff || BYTECODE0 [31:0] + * 9 | 0x0024 | 31: 0 | 0xffffffff || BYTECODE1 [63:32] + * 10 | 0x0028 | 31: 0 | 0xffffffff || BYTECODE2 [95:64] + * 11 | 0x002c | 31: 0 | 0xffffffff || BYTECODE3 [127:96] + * 12 | 0x0030 | 31: 0 | 0xffffffff || BYTECODE4 [159:128] + * 13 | 0x0034 | 31:16 | 0xffff0000 || LOOPS0 [15:0] + * | | 15: 0 | 0x0000ffff || BYTECODE5 [175:160] + * 14 | 0x0038 | 31: 0 | 0xffffffff || LOOPS1 [47:16] + * 15 | | 31: 0 | 0xffffffff || Reserved + * ================================================================================ + * + * Job-dependent registers layout + * ================================================================================ + * # reg | offset | bits | bitmask || content + * -------+----------+---------+--------------++----------------------------------- + * 0 | 0x0040 | 31: 0 | 0xffffffff || X_ADDR + * 1 | 0x0044 | 31: 0 | 0xffffffff || W_ADDR + * 2 | 0x0048 | 31: 0 | 0xffffffff || Y_ADDR + * 3 | 0x004c | 31:24 | 0xff000000 || UCODE_STATIC0.w + * | | 23:16 | 0x00ff0000 || UCODE_STATIC0.h + * | | 15: 8 | 0x0000ff00 || UCODE_STATIC0.ow + * | | 7: 0 | 0x000000ff || UCODE_STATIC0.oh + * 4 | 0x0050 | 31:24 | 0xff000000 || UCODE_STATIC1.fs0 + * | | 23:16 | 0x00ff0000 || UCODE_STATIC1.fs1 + * | | 7: 0 | 0x000000ff || UCODE_STATIC1.acc + * 5 | 0x0054 | 27:16 | 0x0fff0000 || UCODE_STATIC2.nif + * | | 11: 0 | 0x00000fff || UCODE_STATIC2.nof + * 6 | 0x0058 | 31: 0 | 0xffffffff || TAU_ADDR + * 7 | 0x005c | 3: 0 | 0x0000000f || TAU_SHIFT + * ================================================================================ + * + */ + +#define XNE_TRIGGER 0x00 +#define XNE_ACQUIRE 0x04 +#define XNE_FINISHED 0x08 +#define XNE_STATUS 0x0c +#define XNE_RUNNING_JOB 0x10 +#define XNE_SOFT_CLEAR 0x14 + +#define XNE_BYTECODE 0x20 +#define XNE_BYTECODE0_OFFS 0x00 +#define XNE_BYTECODE1_OFFS 0x04 +#define XNE_BYTECODE2_OFFS 0x08 +#define XNE_BYTECODE3_OFFS 0x0c +#define XNE_BYTECODE4_OFFS 0x10 +#define XNE_BYTECODE5_LOOPS0_OFFS 0x14 +#define XNE_LOOPS1_OFFS 0x18 + +#define XNE_X_ADDR 0x40 +#define XNE_W_ADDR 0x44 +#define XNE_Y_ADDR 0x48 +#define XNE_UCODE_STATIC0 0x4c +#define XNE_UCODE_STATIC1 0x50 +#define XNE_UCODE_STATIC2 0x54 +#define XNE_TAU_ADDR 0x58 +#define XNE_TAU_SHIFT 0x5c + +#endif diff --git a/sw/pulp-sdk/bin/rename_l2.py b/sw/pulp-sdk/bin/rename_l2.py new file mode 100644 index 0000000..cbde37d --- /dev/null +++ b/sw/pulp-sdk/bin/rename_l2.py @@ -0,0 +1,11 @@ +import glob +import os +from shutil import copyfile +import sys + +for file in glob.glob("./*.slm"): + if "l2" not in file and "tcdm" not in file and "prog_mem" not in file: + dir = os.path.dirname(file) + target = os.path.join(dir, "l2_{}_{}".format(sys.argv[1], os.path.basename(file))) + copyfile(file, target) + diff --git a/sw/pulp-sdk/bin/slm_conv b/sw/pulp-sdk/bin/slm_conv new file mode 100755 index 0000000000000000000000000000000000000000..a342f5d60ba9ce12e06a7afef2527bc1dd73e198 GIT binary patch literal 3186640 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%0Ap*I?ygN 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 ?|CV_tTe3CE^>#zC8cSN2N&UO#jRd>7UVE zZ_PZH$J8?{j?>fqM9HUzNXbmeoU2?|8OEAyoFlz`-jD)$_}$Fl%os1%o`n)r@kl>N zO)bpt*7FkFr~KNj$e-&k5s2}`fkX(5)U~&|PxsrWJWc$U<>N@UegBv8QB35&B_I8| zy2?kTi&MB?*jmd)>z9uszAKiu5&3xLE$fkwKOdsfMdjn+uaw!R`GRIM<>Q`M4f67_ z7TNHBk&l19klHpuKK>gt{V(L>2^^mPhVt=HKr+en!%KMhugb?4$84H>97s3-Uq0R) z7dTq+I{BDo_){;G{{Kuq9=X;3|H#KT2z9p^^6}c2{ulCbHL~LWHTifHo~!>&`B>Vm zz75OAKAQK%;$p$ugIgr^y?QTk1sP;mVnxUa@9rCWUhH4CHWJ6XME^9Q z+;mBuXsO!%J%x*K>HY4-!QHvzZOj%|{Wb~l!;8hO+{(<>*0 z&hHM?SG7fex*L!8O#;d@u=$W>wzf@G>-0*%n&n$HXIGm`Gh3NvVrK>Pyt>c(E_6=L zTUYWck9#d#I6TlqHzY7u@|s;4OWY>$s7{?#Ze8T^2d=PF_vh*Zh7tB~ob*b|$%vvR zP&=Gust{4}S0@O7$x%YtPtOyNa~}RI!78nJ*|773QTAPHRjZLaVR#jwh6D&B zHwJO2BV2tRvva{AySs2?^F;#O9TaN+oe_g)a;AbxM#_!O$Du1wYs{B8{cCc~#KP8= z8z+rVq~maGd54sypWRo=?<+vwWW$u}?(ST&W8GDHs7=?~1-e^*mQ!)0fz#bS1BLA_ z-5vF;@@#f@hn*Yj?hG|x-JNRiZLGT&l8XpAD;d+C=_BPdFZG85CkFjy5YVCBr*?pV zCO)$X1Z079)=NOoo5`Zh*aj#(;v7dnGSu+;oK4~`82#w!Vi*&=+Bu0icrXIMf>9hsd#^2 zm!79(BteT12D=1YfYi#BT0I$Rw;Y!1!!blPksZjpS1bG}NJxKQiNI(mOP2lkOh?5Y z&JU?60^{XRZ7$C9FalfpG0qHZ5XoK8=YjUqc?IN9Q(XkKH=g`PpncttJr3#N&{q_9 zIwTXs-MwdlJBtjwA!_N;5sxu0x8vD4#(2u^MLM!W(T-RJ>!EAI@y0u%ZKPmFKAc2H zu+~7YInMp;!~)KJ@*YJ1ykuoDOm7;1vpC$OIRNUM#Pm6_wad)uE2<6Q5Q|* zW2x(#6l#*;tN3Z_cH zVHc(4`hTj2U6mF$71yJ*cyiL+`V0hY42|QY(qoA80D3R7#&hGJEk?*YSmT=`De~jL zIq0o2O~W~l%ho&`0UK6+-7mT_&^19%PyBFz%*Z z*x?O2u@Ft1%fGSZT(t?TqJtK75JkpV4KO(}DSPjX0*-w~!A!Nuoh+ODc(IA#$fP*O zj!T6(^$ZIZI@;4=bZE|aH+FSln}e1D$!9LuM8Q=mUJvH`|IrO*xBpQnFx_lk?G)dmhUl=1!M4ET6s>E~36JE!Gy`&Btwk+9A*1K^8uLQVWowBJjNr+>FQ4K#l9p$+26`8k_2#24LqMJGcuhR4a9kZS zU>I6wxvfqHQfF^9Om1*)U~eP6&^9>S6pbXXJ3D774S^VinUk}Pjo7;hYy5lEe=S~a zv4g}h773T^MsIMyZeXTuOKNCARA+-e)r@gxg9aKQ!Xu^sS1?(bjk5Oxw8yiPeV@Zm zPp@vw`VQ$|gjZ)C>DF8DqT)re6|l}Z$9zm8T|^FAO#(S1OtSJwyj=hv08SJt|Y zwZtm8oQ%J%&+(v8%-Vf}e_XyB@twaP<${M$n;Z$dB86if;%bfoxP_TGi+j(B*eRS^ zRkm`~kSyDBmmnc}v-CUGsZEywItv!=bE@%`LyfQK^7^$snhB5SskFr>nDD-76RX>V z`r_t-3H7rbg8lF&)DaJBaJu%R_=FMzj&Zz+0227qY)B*fvxp@yrE2K7rj)U8aVCqs zmHtz|^$Zc5l5Hip>MD(cn-XO&o>I`AcmaR#hUJPC->^Fc(6#piFwW4|W$HuMEaQh= zrGcSVZj?ngUM~lD@kB@G;sASYUt}V@zP#H+SRV%vjsx?*Eo+nAd1J-crqz5)-?O{W z=j&(JnqDS-3l+xbw@JTzcfWr6wbiC(g4gHmJJW#QnZ#uGQ)YWP+(ujaRGQ(U3(Zq> zIr55;B<&zo;qsdtp|-6+T^4_@jZd>JPcE2dx9%7uPj5W`vaHy6I?f&x;4wCd9ho4& zZ4>QRKMbxSo3{ZKwk|(gPyUpH@Qbe^Cn#64?+{>;oegu^IqaR#cPvX1<9!d^uE+qF z8ngvkX|Vw|cH^1SM0fUX@_HS?I5oUOXh}zA#K;}RfzBKBf*M`PuQa>~p$|GSowRul zhW9%~s^im!?DeZ`{yEi3j)X(UCeCbJq_EWB2K`ZP9I8r)L<6J-@>i1b!cMCf2c}7?l`Wi)#f*Q}cc- zXo>C@gq+|Go~q?o^GLcmvh`(X;nNQ`Rw&j%c=UNAXAUT z_l+!mttZ#MMI~xQnfHn`&0F=2<7u3$MD|F>y*a1vnSE?|!sb*q{A=c@8N7~B22iF9 z!fcg(Q50+Ro9svBanVbBWd$Z=;D+pbt<;tF(mgB_lSZ_wA++un6R>gh+4oJVe;pe(5I)8#2vZ{#}(Qua-nay3J2E8c_waz4`?aPVyj zm@!4mnWNU5#fDN@2It!-qmA_yP;7Lg6ekbWH;86ScEE)+>vytjlyM}VupG6No!?n( zW>^K?W`-kYBdn(JqMI(XacYh>k~;~2;mJyj5b5+79JaDIJ-mfJH>_q^3k+n!vCntsHLR-Q15BnJAnU=uH6XXG!vL$k4Aq39YNl)%NQE&r-EtP00$ z-So-r{YdcDMHasWdphS_TTbj9nZ|b9E^XAoIwKL^rCj_%_lxdgJ@)PwWtrUknrh~A zCwE8(qs8f1LimK^bmHBSAZPC+u?02m_y~(m>IUX3771pzfb+qAJGKAc_0ebTIhw5a zMFCCz;@d%*RF|R2TkqdAn)DHx4c|D9YP!zi%W|{$w_4DyXBJ<@H<@eX^Gg)P(}1Dq zM8=;Uf2E^5I<;_p%(P;3ipeTdE|Rd19#5|@p3b-_E>97bZX(rZ>7r?mFrT-c-Q`S# zeBU;A5jJ6Bvf+E|vrmt^VzAj6_PL0)BAxmSEmjna7TexCCkI-DWX-kzsH-5&XqiQF zsBJcxBa2_}6(J^~f<=p0uxwus89zG=GEVFV?Q%m8ba1hTEl9hZxOpLUBrBv1(r$o8 zO4NR`?7g2m8u8fubp?FOqmdT2`Ap7>nT@9$1$~7is4n}H+Gbuhe8JHol>8A6lb``~ zPdY{e{9^n-Y=F$B{wLa9>|b88E^q>C4)bYnZaxk6=F@ZLR#2D8&!VObWNzB3pR9O z^B%g6y5}3A>tNA48j1CmI~GS&dt}*QcP|&r4Zq7xP4dPy0xK&Ja1;rRS_8G5bvOM8jbipL*YTwl zsS6gZaID%wQP#J?x=dsuS6{asvV@dusMYvDI_2)VUt!Dd!f67L&Jo?3Zl>Cn!! z-7L3BHuWUBSGQm)fb>LVYA#`Evw#i7Av*DNS2xp>&n7b$r_q+_M> zy-vP|{0hk0NhMS7^9ov_A5!R|$6}@H6m?_cV;%gqzZMcY-5wx)9RAYwToLm zF0Fb@t9@C(<>K%gd<+yIz!WRST|A=uO^tc+=FP>|E(*-Wf^FAq@8Glq+v0Th{(V!Y z<*?stHRWk2&J-TLl}RYxzGho0vsr4Kxb78f6S8y8Sf>v<$|oYoi{}?S=OUi=O4IhlRN*1O4oT; z-8k)B{2tb%&TrAZ^8>B(A=ml%=)#Wgf0)&lN@;M4JrcS8&aPO} z0f{Dwy@@W1Glv*WblHLrs=wZ{pBSu03;F%`i(=B_Jq67ymJgC6v|x6%&YLfOts->y zwbf&JrS$1^KB4g3FD1=r)Hwe3qNg;}R(zpohZhGet7^{UmfuY}&L>zV(>T&T~ z<&i$i(syFo$gdfXfNrH7w7*VRsC@G8Mb2B=42Ao53}QS^LVrO(p@K`Ii#m9yR}yyj zQL@pUqgNST{PRO~cOwZU*W!Fe?G7CEJ(Pn|(FFB&l_+!O3f9_}iGBuH*DgkVOp-zr z=nRIYUZJ)lAQDp#js}zdmd_|M0EzE7Xkl_K0^}D2%avbjJ+$1Dh^-2{Uib2pr_!Ry z&;rhV8tTSXkM<_!In@n@G=c0eCQV07Ld>iEG_L(gPv*~haO2HiLyt#z4nv+h1l=`i zq|Q~=EAM8AnKY2S=p>k()2)A)#B}qg`gfB0_a*y& zlQ9VB)X~_wccwg1prV_?By6iC?(-g#Uy@4svJRp`%~eOC=;!VCrs`GvYL%VRyD;1` zbwEk{AWZjCxavvO9vR`E2L+SnJWSs>aLy1m7k=pELuPzIUM0D_@xjrK=f+|h9%nPn zRQo?cC@!95^C9`v-pC(aKAVTaZ;~2lH5MAR7R_MppCFOYs8!V2e1{k^Ro!G4Qbagr zS+6T@Bl^Q}Ic-xZ{@dT1UC=I+R){_1G**Zm8ixKY9O{}#Z7No`=E5jf7{^LK4$Zjw zTU4CCnAoJ;bJDhvat`mhnz-j7eosPePn#}|#X{36(@Pnn$zFr4P40Kacp@EKgTX<- z)UF;(%spo!3Ds~rT&=eg;H#R=W4u5Jd89Np;#H&X8u&TX*1UVmB?DNahO`e_Fo2dV z)b^GCGiO_lmZ{Yx&HHgVI@{JNQNkWW&zp>D)FzQ~3TF-rHWTQ^T4tKIn6{yR15dOWd0>Vk;{e~FgtyMR6sG;V~t7OeHt z)FU&fWS~Qz>1*M*_$oTnAI z$=UuAw^nxwYA{;QFI_wxb_%UC(Kslo^d>)jqTVKhz>?^L%%c+h)0~_-feoh?UU*Gn z@B^&W@GI$%*0T4KDiXDUU< zIsVh&T7)9NY8< zcXnWQ*`)yDXDyd#!P(gch0su_ZMquqc$~NEETdc}A7hC+ElFSD5y`k!sBH_LbWA$H zL`+{WLumLb;53;!s5;7>ez=wyEGD#}p66)D4P+H4(q-{u>%N|HXWEo4&p#%|ku+l@ zMEFw$3Qk)mlJk6F7(8(gF#tY2h{KIOtQvN6BJ+sD3Uh5~bgw?o5lFnO_y??PO zm(*5mdbMt30Vh!d-{_J0^K>}CmK%jL#to`BbCP{;{JxtpHo200Ti14J9FfdIl$B~JG@vy z5GOy__}*GTSbucjega=Gy;9Zz>Sm5e{7mu)<|h3HAT=ZMeBkhmqtza`E}vg6AK!n7 zm3Q7K^)vTUQ!dHR;-CA@ce8D|U%hz6Tq?+h9~dFagRmCRdT?{Y_}00V*vvhq0qMdJ zfUl>F*e*Z%Fa0rLXtlf;vv?IN{1~f<#aLpi&=XljJT5OYw~C;jrYmS~qKhUz0sta? zUKT1Qs!Ih~9E{s53;kQD?;SO%l0yHv401INR&;n%;9*ThBH@C*7qFB^VJzY{n% zUJF$%ngG1n@b{@Iv}HEDK;I7I+XKJx&%|BI6&IQPN%})BX`+&FUl|!fS`ueQg~Gg+ z*z3D`-69)4i(kf?g`Q_wOHF1Woc_?DwM5ZC>O>{}h9~7j0v)b*5uTM~Mx^SLB5#tk zI9Pfc{n^T^g#tV1^Dn)3nzCBUNX+!~s(ko-a$KTf&r)w%8Pe5$0a{4!mapv}7m#IU3DCstHVd?e0|}?vi;V}wxeas>=&%!D(_qNB_9k* ziCd&bp64omEBHmzJ9Ug#`SZ$ls8_)vKU?O_&@L@xD`_~s;kbrz#}J%vA#ZGoL_6?f z|18R8E`B6?^6ipmSUe!nF_vhp}V@pri zLU8M73q`+y{nz9`ue2-O$U8o0YJnBMxW7y-`$rRFkQF%NDy&Mf@8dt#_-NU~dBHW3 z>;-;k$-bxG927;26}?nZ@=ca>n(C6EG8s*|pitLbY_4cn zz6C4@ zWSJduubj?2AOU$1^=oVi>8#s>C{Ap9j_A&Dh83E9OzoLN5`eX}{9Yg3d^(YeS{3 z&wMN2s5}k?W;F3D&EsgI{RTBHo&QFA|C7X6WK!pN1W7D8q9!u3NoE1&NM&e-LU_fJ z1CF~%Bs=W<4|^0uhmpOlby`KQ=52Iad#r9%e3$9NC!TT6WIV2u57bb05gP|34cUK5 z_cpoQ`oKim>DA0VQtj4amqIP5!ofmcQa;l9Kqu=ZS7<&@U0dQTazP;pcnVdr@8k-V z^VGG_kn+MpSF6zUW$HYq8!+xfMxMfR=&J3}C1Z8#;#2vmK7oisf2p~<(bT!>k4-!B# zosWz-E~{?JT{poqMxhE+$U>YxMp+;J#{{&)>919R?R=~Ur`MmYC7HwN$L|(_|IarR zhkqUog7OtiMRQQ*`L`eJS#bFYgO}`kbFoTK=w7KC=D;Ebemqrzpvnn?sbc?^NM#no z(ptR5Mq_sMU-;Ge`Ij*Cu*DoJeM8HkDi?1Q>(CG}py66;m7wxIPi};BgDy#XiDyNO zA3dwB`W2pMqIXLUG+Dc>#Zoo%ve_1g^P8xCXs17MMkU-Vh_s^jQxx8P4OCV*eBTv4 zs=hA6cNA4clZPTbU7*&&p?o$#iX|F9H8h>9LtLs#vAjYr9qY ze;=!vcI(vnZx_MT zUjK_u{fQ}*mu0t2rbmc0X=KqAE?D=2a~W0J!pw#*-Un$YP3P|#otzei*?AF@+4`~E z{I3b+3&H&d?iii)>U?U0A2rN6V!%RWlWtv!sc`hr_h-(oma-S?c&iQn#<}{);mAv4 z$=g&2l_Nz`kNCM>R7{-JtBH}JTb?201H9mvq;5^BMDxpJ_u^!dx^^Hg=Rit}yuHgC zdD`zGfd&^p&fLkHul<{gN)IGu6I z6xfvag8K1otYFVmp z{)lQx)MkB-e=p}*8=>O4s<>luHr!ib2iOcAoc@&+yemfv%95$|JP%f2kAuK$=Eg0f zw({sor&YxAlkHFpY`t(vFmbHXC|(g8@p0wl&LF>TmYc1zsi`Cp(qU?uGS^2OebrRHKfWtv7GSH+tm) z$A*@#ddADs#1Lg8gSf;T@jnj8@HOVvaeoo}Q0j%hb5Ha}D+;w+&^v-N) zhYy;(uMNUfY|)(FnIg0D0M1y>2oA(7UpYf9qZGKwZk^Sl0J5+m8J z+brk&onSJAI55ffA9qznVN zBr}9R-9TXgQ6BLT zFD%*PHwE^qi4rg{sfhYhu?gYB6MvY=42ezp%?T@Evu7`yD2keFBCdIR;($1NR^eCKt;Fn; zWjlVNDeE)=FTS%_Ch?uwiPkNw+v?(2On{IA{t##piD^(?bA<`R)Y3TtAt*VG1f-yy z#BAJM7fcYRjZ>NZc7a}z_li_tCgG1_xI}F6YnB1YovwIAf&K2UE=LGqrStQp_B@i2 za8{e>^riFIb<}~T_Eiw9LXzkf_D~yPGl3^wU3FOSVuf}`#tec?9m7BPnkys`KUx`dKSZbf zdZtR^N3YU*?M*JubnUg(E%uHz*E!7iJb;>1qe4g%JzAe@yu3AjS-&o??pm*{TCZ(q zzt6$CJ6pCIE~(>+AN?u)FKw>3;qwChIROZI8WH9fc6d9q@WE(;t6`333tK)+7)A~v za`e`jLqw10Y}%OvCn^TI8R-`!ClCXvSO4tx<%(4hYC9DuWNWuL(a3X=?LplGMPH@b z8PzI8dp&-L%TkmJ#FvM*8+}B`HpNq$HF3g{gSNYR1E+}R1 zC1O;nf>CHnO+5}a*SjFRbJ=*8^W}$>GrxkFQ^3D&5UM+#j&^(!?O+t|rh^3l8q1Z%V-sg!s2n4WF>xXM;FuZ+Vc)B4w`Bl7R<^+y zQ0gu=XfP1?!Fm>Hvf}3)YQM{-twbL)v{IgbRiSNAxm{?Uzv!!xTE{Esv%+|8%ZA2= zy2kFlGS?VvMSLYSN*h9uXV-0+Q9G*&uem1ITrDK;b?OY3@aNJgTRKr361UBvv9>u> zC8G+5w`A(@d-9PQw4OL&y1t&gp?tZXj5IL(%_n+tCS72Y>iza^J^ArT#e4GOoi?c_ zGr)*;#EbMqxB3Qp@~l{$^~6+DA4%QDWV!Mc`^s2>d##&RX)w_h%69sJxRBj@Qg+X? z(iF9%3M>%gt#p{gfToyKQIdiSMBmJ*04>K3F`tPpow9@f8lN3(1#^-$fAT5d&TIaF zV$FXt;~O=LCRyJG-+V(6ud4cT$vD*>X{cTxa{ zGKPqA66x=6#$ZhzpC7EPih;Uf`ZvJV1_8Y|2k2?`lw%_qu)=(J#gM}hLcT&Lucpp9 zK_jY(lPqh|9A|We+LN9xg4*qh!n+BmEwUlHB_S=?YMm&lHA#}ul>Nzix&p&`+q(eR zFtfKNhJCpr+HoY?t7A&dwPJn5ijbyTj#&SyiS7|=@~I--iL`tp^cU&O_c@S7XADr= zE|@9wvifP!FY6as-Pl0hxeE(LqsxX%DcrEUchAgst-sD4QiWB>?{%?)59=h<^rezI zL4g^Tnu50eS7~_+aqa!S8cyO(BxY)He{p&GHn==x!8~j0$x~+fy>ZyonO;q=-d8C7 z@K4M8H_WrHBK*v`K_O6{zz#y+%*`7W%sdDuYe1{~O9rJN&!HT_VAYEf9W1k7h7c#r z%cKoyuMh@T<)_!^ZHUpYnKykC=kN)n*HZ`l4l)|WDgyB^KGN}aYP+|&H6ek^Zj3q1 zwD0?`D>U-&xM|=#ms5YcKtqNy&K^D<^S#)u*=7s5@gEpn{7%m!llxtv*jyvO92q>$ zsq?@6-FZ&V)Au*0D7LiGOe&*wuekHSP11O}o~P%$cAxER_=LAEE&=0H%MN$ra_+r_ z7@yOqg)8dXN7yt@z<*%m+04mBctDq=wwa@7;CbD|)+deG@YNavE^KNclRsXKazII( zQm*St*u%K4lfUu(8)hzzE`GBoilPj=U~<2D;u%^bgXD<%XyW_sbOHDHZ42o1YTrod zi>fIvRadLU2b!oZZMUF#A=!Ca4sPaWqyGfn(qUfxq z7J*z}640+&-$QwpM~Tknrv+cfW08($A-GuboN9Q(o9t}&XFoHKf(di%_>2N4u&c~I zzUPd7C8b$GWy818krAO#`+?#c78K`1%pm1Gri{~09>U>$Er=?jtj+MFEzj~a8mlIr zYgh}DeODj2E*rP69CU?n9?w3>@=KDUVo@b+I2+QF(T?|>2CnU*v*>4L@0@*GQY8YF z4HKqo*M??1q@HnTRcj5hA1JhF!+d#9{KK9HmBRy*9Rk=3F1DyYg|guXMNt^gp!=Fd zM9<*mA?&yGQHmJ`SE>nZ)6vl695}R6{Gp=s!tzlBZ+>w9X#H-b-A@|d8V(7aZ4OJo6A#Mmjk0}O%aa+XkSfT zc6WeT9b~Ghw$&1ip+Kx63Z=RMNcQ^ z_|S0-@gJ9F46DM*Kh2y?K08 z)!oNWAd!fqH!h=bj~X<%)SzIAf(8MZk%{6~v7)ArsMw-K$S72lkOXBMM`>&O*t(Rb zF16OSw6#|176b%st-E4fz-AWpL=;s8VQzs(QYo*da4DmkMvGr-n%R%iC* zS3&AOyiYR_;KziIbQf4YG6HfLQJy&SBXOpDkF4Lud*t!CU-Y3fS6n{#i+(t`y=z}&P~rqjKG-fjeY@W%vvtUzyhrLtd#Q_Z zgP#5oAKkbjv3&;{%oQ!dzv@287ukt~=RY55fE>0q?tJ8IVRgr{i6Ft4x@{yhz?+Iy zgPmRgvQ!LYJW6*m$n?>4#e1_|fsiQTdvHuvxTKI_U3%CD&+suru7NN56BKIZl29|R zsbu$N+P-EpUBzb3vSx}5a6vTHUzCCel*6}~mkr!0b(x*{#oEmr|J?0CS8`6oQb%9J zE1n|jH9e;~^Hh|;!PGgJ><9-TtAr0s;V6@H`N%jOFM+5N;VuOnvDBRUhg*Px?>j$$ ze9{`k-*%0qE*q}z-7!07Dg-V+sDcvqxD<-e=b0S#Rc@f((!8aaaU$Y5fG3|(Agu`G zj6XX9X`>;yNB{NFxwbr(sL1|)Kv|!q#nJov$th7C#JepQO0>^ox{*C59w!MTr7 zK%vS*`^PfYLf5HI(;eF7QQVLrdCGBb`ot6WAqJJiMd{^YvY#PqDF&R#uE z2k^N5sw>#`Jz?p+9Qiq5g?~x{2?T z*dd-eoVad4PV`vCsK<^QPOK#Hl*0?G@$~_mJXmu7nCX|N5kYGT%Q!H%tM$m{)c!h3 zg=oJf>12moFtjkgz3O8xIDKq&;tj=usfxW(W=c+DDah3Ppi8QRlaofBWl@^p?uu{N7;j#sR5h> zzkA~A5SQ0UW%@o$pC@e7oj!|GlOMEUJNnDTFR4q71UQ=$K|1J7QkNF|l|_uq4_Zmi z!wodzcj|uo{v)wG(N}Use$c1emLink7wuRJ$087WbKB8n3ADDeD`P7Z+T>!)qwI## z5~Mb}URfzvj;Je3Tp&JPnU8!z3fMa_^p(>aPj~7R$T114MY4UgX;Z!F2A(?FU77k4 z+|Ln++RXxqGa((zYJ?{t!g~QO;1s8voc6$MG`Qw`m{@t+eB~0qX^BM?KEKpoDZs~( zI?R<~isY=^6=91W8{-bhQb#XN)A`;H9r5Nt9V=LW2r+CES1s5=MsBH8<%^Xol?NHrop+Hcfn-T z(lpXyG+i%>-9Oqmu{u#JZqfLGwB`3LZhf|uZ5pgK(}d~Hmbx=`mhL6f)={>fA zzpQubPqD_e-c^^vebIa?V@I7{$$X}cB2Yfs__^2lG`-D7CcoG6`7 zJevJGNhSR^dx>3z;6pxgb^m(8MFq_4ALxzf9ZkQ#R$7_@Kqi;Pk}t+sw~93;Ds__P z$5c<)#pmjNXg7Is)#6&Uuds_(l&52#K)5PBFL}2@Hi6Nx9rtvL4gjIg^D4;B{+U18 z#+a2lAM02aOa+}Ow*dU=c(SD$%cjsffwk5U4Ml<-7eW783jI4>?QWreW(`{ZK(rox zD|3BI49V_J9pTx7U#gqA{mdA)*r9u2KpIG=mV{$TwqhpFs#JGWuU4m62QNpxX>DK( zlN)N-mxd)IQpiVU2H*a9>)%e+x2+8|v5v9T1ow*UaCQtA5J_7BWM1;-bs&m9BOnQS z8k#r)7Is(&)OeA^3kp*2to)!92hcb|4!&xAqDL_qPwgwDy1s8a2#;fGv@dHfdd}6_ zg^{>-!ykV?jEs4K|4kd(i-1L%3C!W-i6UCzWv~kdYc8t5CB=aop|~g!>D6{7;-i^e zu7!}$EU<1_`H#!#UCeA4g4CscB$RRyM^tHujx<8p~iSLDMGCWMxA%g<2sl zXsBIY$9m^G8>G#GXtoNRz6=HaAQ*oru5BM-gz4trh>DctKiim(YM1eh=_u%4f~Qr5GKa*9`G`h4n~SaM#DniwPMLEVia8Z$l>1xB zw;DQT)_@I9s%Q$&eu}#yxZERkv&+?)#sHEN3o_q1Q0wr^xi}0AIk&c%#k+l$$2#8L zJU&&v)*ztz#;14sgoDhOVi`Joz>}OXB-{D6SW6e0loWgr+2pK0ZBg9bXZL znTA~qV+_;Xd-OR5MoUAYPwRFd5d9#IkJKnI)eJE z=srth9q(?ArOIEoVb7!gC#K6c$2z(g_Hqq7?)z(t9nxkEjsFV-3**mDKRM3$N5<22 zuef=iP&xjnQ`b}`h%6KshL2ATU1PH8OMst`Jh+X5_na44*#5RqLi?5X`O5D|;%3nt zR61KTG-)#nj-TV;`8eP+5ISdzkLe1gX@zN zX`;0cxgFU~_ocLgFEJ)m9W4qb>7j6n$9PdZ6Q9+JV(f?x+ymO2xZ9(w@{n5_WpWnL zFL8Bz-9adWmF}$TQjc9F!ER#BM>VJ9fd-rmA4+TGMP!rwMo0mivm700l zsnIW3IJ7qnX92J{$oStt_+Rhm7goCpyv_+~5;aMFWM8zS=Dd_0PWt%N)HRIVK}`S~ zO*mrW=<%sZYf1rp1Vj&>HYeXZG1a;T*mkv^Ww15>?P+~Yye3Y}e#@A{mJ#KB6k8*6 zLy)f48ASxC_A5Cr+m}kVh9G#|U(URIm}c0aEQcp<*gATAMHEad`F{3g2EDba4fn3J zs=q$&-Ad)zIR@Ea*=P#dGEVEsb@g87NkD@0#{b|;lA$&QC6eTFh-QXKk`79t%p-wH zBnj6G79`1uk|gou;fD7}k}h<}^JCt{kLk}-+9hBL4K7M{QhKMq;#Hr=V)sS$UUg!) zSA9j)+kR|4!G6v7pwHsvG{|}EL~r}46yAQa6rtIK>1;3c8%k;uo{GQxD9Z=9Jf|ItnCGWq?pTuhw|gy*}tq zm0%#O)G@#(&~KtJK=}kQ?7YtFG!<|@GpOKvUcs=-N9J(^fMUnxu~j!F*hh%q0`q$% zJUvb5_x}0WM0EM*XXhiw=oB7*$?tVl6ZNa;0#j&O2Q=D0f*8L>KZT`}2(*=MfxKWHuH2yY_(2WMGwaeBi347qhW=1AGO!;t?g z7e$)fsV;MAt&mol&S*59O;IU$YtVFtW+Vz{Az#L)_kfWv#S`?H6rE^lCma}1GS+Bx z@Q3I(iph^RemFfI=bYYeq2Cxq$I8|o-+1ahT6!yg_+gae<9WkyB<_P$i9LPsOOT%Pz}Og z5?RFInkC-fd?Z44bMk1Q-eMm0rQ!Z<_(IeO?Z_Ma*1w6$r6g1`|0#<0+E>ygSnjs5#>e8`vFq)|mq7O3L!KO*Y>Yaq zcr^LtwSI$K0`TdFHnFWIaZfXxWd_7X3ve0w$^qm!V6YTdf}k(~96gv4qZ_o@L6Gao zkr5A_!XLI6{lRC_B)vfrXMlvj`IJiu0r4SAA)dj0efC?KIh$BtVbK2Eo#)~yY(2%! zBT*Nag>IPhYFjDheDax(IX?h)0c!kQbB4qPHQYI1|DRApOsWTJ2ytd=$c6i!+SDkr z-^oa!NL$iS#DZmyno-?4JgcqtP9I_F!Izz$1z(@wR z=QxN!hMTR8@*`r6D?o+~CQ@~nf}ECW-wycvtaY?B2p0S*eMER8A6d&bbn&&LKm>H; z%du?~d#C52I9o^8grP3hRusZN5@G`K<;A4;Nh$^TtCqq#vi%kXpw=@2+3=Nj-?#>( z2fhfd6}(E}W1O3!kut+bGQu-h(f$`)$w`QG#Wwf4OeY!8G@0RwZO^W-FT(Mn2nl^N z!RT33EYg}OQxz44sm@2f{}ELwG4uHAG+=D#oHyA4qtf}vJrIgKgXJO^YMQ1J)AEtq z-}k#WUx&-kMJlcMmUS`U3f6Zzp!jKQ$%>Qy+)JlVJ*&4)&+OjmVMG7uy2(sfx2H0n zf9{7nwE3Dzb+v6eefAm~-pKbSq4E%OK<6*`L@ioeO@qI!l(?G3be)eN_c3(@lz_x~ z8m^}cuA#52*G*)-?o_K(Zb?>%s{153A#9SI>(2rh+AV)(irM9-{UE_gU@nm zGUMOkl}IJu2e|Q#(Cf6!I&#I3e)^M;npl}RVvS3_(vpkV-EF;Urg#t?B-ZPtSn`ut za+4fVQuO06BI);G!PY2@luv1Y7WY^?!=uTO;NUUt(&u#8Z|L-;DwP$d?+Ty3bOEWM z)0e=eo9o(`4*kxzUk)I(rKGW_KDw4zhRHQpGwNtyn$lqu71)_{7qEp_jtWA>;7u`x zI+$2e$g8h-eNY8{9bequx8A3nh2SVVAT!|pNOngYpDO3E>bFLw*E*Ah)7+%wYZX)C zTK0!YT*XjM5z%UL0&Q`4G(8Dqh1d|I6;H_a1ZSZLb&s$6sQ2lL#@}mBv|dH+ZG5gO zQ1h~9R8aZtZU)E_Lspi)hlG8@j*NwcjA5VNPhII?Tk@%OGxL#;-~@8(|3Y2~&>5Xs zMswr)t><{{cax|y6>$uK{IlyCET+MhhT3(uhrs%4eTaszpLFthAkoGBZo@J zXu9l1C!sX7_N#9@T5GfJM$SDGcCT+1>kqsjbIEQpihREsAC(Ysp<|+Aw|)YZ*?qxH ze<@>DFP~hX)S*-@wq=Ak&C#gA+IJMFLwqrpJ&J;5o7zwN2nAnroW|Fu(-5iivHUG`peD`B#FU8Gl-*8TSDJEPMT2i(KF(7F@<74}WVkG~U^q%Kh% zq?{A~E-9epRtf+8g^x^?&|ALbTIfV`WGp|`EfHdi;pFOP7+vQA^)JX5YlF%V|bs|BXYRdtg4pGF=WCUgC-YHk6zYj ztoxBy_)5o}$*#QaWhbX!Oi6rejtSCH#;58na{VF8C<^efe`fC5N@iOp+iQOu0nYBA zV2SVyEt;?!qfG;gAXntwdT65gyGBJkRy}aK@bX%>fB`2Hp9$pMdcGIK6&utE9b$u$ zdg5?_)N6{TZ}$t-;kc}L_Fa7=1WEf^+cZ+g{935t6FsdgpaNAw)`usn1HJG%caMva z9A7Ldd@(HVE1Oh&gOPDQvJvSesrN2iRjjT_+F&%=_tGW4CPu3$5)v*gl?6wL<_!N6qNk7X?cAth5k1waFmxxoou_J+#hP5WXvfKIyN#JwHI6p*xp>@&p;`<61rHI`jqipjTC z+A&4RwQfwY-7rA20|GUnV+i)^taF+?5+_(<@>Bwccx!P*IyQ6wTE`51ps7J@nAkq=xiRAD}=LSh8$st5QpMl(Y)KE6F-s`ev<7 zeN135=%H|y+ffB=42*abb4^Smbu4?3#x|5UCt0(puQ+Y@3POFhAIs+y@5z}hg4j5- zA3_{Cic!at8F;FwJj7Gspr4-@aM0H#83(PQai4?sv$0WV`fcK%lk8Pn# znN!{~ePD!UHfFARNj%VI@V(5g&$(c?QCEv86+Zp1pp4kyAj@NYqa^;I9@LZNAekgK zB-F#179*M>`Kiu@S;$bd7|}vO>E$*2rnokZA7fYIIrAw4T_aNFkE!b)Po3Atwop)A zo2n($2M7^%QkE!>rcSG2Gf_Ft=0nA3SMjM-%9Ot;gW`6(?m`B_ zjVcOvSxAve{x`?3JC{RuOms@m#lGy{chtk8%UH+jeMUW~g1R)#=#c|GsYj$zWY5|k z!Pn6J zE?#n;4Pw+5y0<)2@ZZ;>JeaC$*=KTp2Zf0N;*d4E-G@YekflJ`43<5QSmFj zq>tCuwdq$}mxQ8e%<)co*F0Fdqd~o|QTc+t=v!p4+XhwWFMD9f7H=A>re~WuP*G@G zv}L(K2tr zPu1*Gl^ktgnu+fgJ(P+frC%;8|VOTuKnmQ5TuXFq$|dA z__^?Rk#qusUb^aSV`$g9Rbh;)X_oDrMv&O@XGEIU`u6M%&KBl9s$vuu z<5&I!d#^g~RrflPSLvHAR$Hg@38X9L7`AEJnT+AE5OwrTgrH`qNr_QQM1nh$$`yga z)eKq$Ce?FbLfF#yJ_mvrX8hVPgY9F!n(Na@egYZ=VN5TCJzE$YhwHmije^uPsUeNR z;f@ff$wD~^M#*L_+0JPcBstBiz?|0@g87!|yvMbGzK|Jc{ibi{JVjg=_*o?L62}_3 z-{{eNT$qVxOc#ZwT-Zfs{eVIT%tgY4N~HmhU4Lw&F6>s_f!%Inh{XeOQ9@&~>y10w zgpG5?D9@DWKkBh@4J@5qCSB(@$C<7(u2!OWrXVT9Qu8Y$@wMtnB23!7QA6iuuH<_z z1f2B+yXJM+TV>jVLK#j;Qw2I2?@;@gZKvYr9m{Jtnk+$lfH*%(1*IY2+)MB;HNlN) zt_!lGZ`7kGnqSwYRmCnnZsno2Ui7ot9+vY>DvdjhbNgOt-Pt;(A+~8eIt%1-^0m}4 zcbT-Ju>JW=m@=>~C@F-E-Fp;##AWwT#2kxs;`&3IV0F zN<51&yY!nnu3D@GH{v!%Az;z{RN(uMTcEZPWnSl>DC#zOa!$-0`Yv5@Uermy`Fe%p zN_GSqKpW5f_}^j#9Ir9S&b_ZSELady9;F`y+P?(L5N1v!wxh(Q5!(X znFxSr3nu7_SWK*GLyDg8XU=3zcA?c#(KT-Cout%%=p>UtiJqObuK1mt7gsAiI_Zk^ z-bt5Nb&B=RH!zt*;X@#{7V;cTJ7Ylb+FZCDa#KCBBqRvVph8f3MXq0?7Cd zV6V6Ls>FfL#BH!*Hx&G^P4<4TFSn|0eL=MbV(SJUX>PE!0;RWD@drzN+3AWyAyIWk z>Y#~Xek)zSC;QscDnDyYAXb$#8Um$fg>dfa-y|H;)a9-pQwiVpavr{5z{oY?sDIwt>2F6 zwJios7q-|I(*r)aw$>Odd$i?>s4a)yBU`N{t@nc4ZB*cJTSpF}t4xrVb-z_R>|u8E z=(S6)0Rr*nn=F+fl`5P~W@UbEDS7Od23+7zfD?YAK--VA_Bm-&a41tmgPn%%a zXin41Up937<_N8@q$|?LI_vT+j~i}4Meqej69fmv6W-* zo@#7xC_pTbkO@Q9R|av@Zs$1D0{i|{_1Nv-pbGC92ik>}*DCkby>6+3GK-W56b+TA zugeNm%=oF`9*~stwN;#L5EuT?muW7sxKLBTQ_g4iTDFN3(v+8K}@9OnNztIN0EVP%ZH}`XSMrpv& z!PA#H>5AM>92}hr;KT7}HaAk~>CKb?j%})tX_%(enE?>HtQq)CKJwRpIv_r61sxET z?SQylDG&uK?Vfe}B}@E&5+=mY;Zb6bpmqjg%H6Lz3;LEXIvLJH%9g5C+d{-zmLJu| z+UC)=w#htJ?0Age0hGhv(H)w(+4o)E zUbn{HgA#5jM7pUUXAVT=GoR8JO8h4VT4r1RlZT&FrD6ZcaEg<0$aR8Vsc5$z5Kq+T z`n|y#aCW)NQk{Hbstpq%)y8EEd-q1?KXJ9+U>bwnldN+v)Y~pq#^{7Za;Bu1xKd{d zhnC-@#9kr{MRERx*olpI+Ntp^(D z$LO(IQJ=TGVbD^^u&MrhWrb&d)qH%bXd&7Dpe zgn7&?KrCHRXOtVPpajy@_o9II2BdV=Lq_-4Ixh-p=LD)%Gd23<@-X&g>Qxd=evf*~ z?lhzVODGUu%Nwd9qE{T8e`_3hkBa%nf-h- zpRY69JuGY8x!f{Wsl5q}!He@CiN|Cp__9ssj)~#Q@d3H`g`C-Vg(hasx^MrM&3 z#k8A-I?lXMuVhIwyDVdCzKAA6c;hmL#U-YhHLAYBAd-*7{-G9bHX;`ft<5V+IPo5AVX(Cp zUxL^GQst!j;{=1zIo)98%N7r2srnSb%nFkyxmzS1xSf3Xy0uSio+l44T{_d2)at%RclrkGON+8 z!7`95tp^xPk1qlMIT;4%LO8B26N4@{v(Xd}t20B7Oj651RZQr0d5|>XgXj9&Cu3EV9c*)BYTM zZJ723%V-#u!+U|H0XBf;@GvZ!N@3ZprT~@=+Fj)|8w{*2*l@K}k#uCBe!Ow)3s{L0 z>4xs!uO(#reEWxo3tav(5R6jlP{6khJHQslzkRGrS3Iy$^X}svwlV5l!9+R-E~{5D z;y}CAyUA@Vum<&}%QD?9JM#QZ5f)PDX{D#D{=US$uCmv_mFKp`s#wN8zsE(a(vJ;R zuHxXUg_E#QG_y*#+*C0Eg+N@dT8TAElnAQTTfHmd`|WgI=V-7d?811(adxf!NDK5j zZ?b-(mpy2bVv8XzztV?26tj(_78J7)aQaC?wMpU`L4?a2>z!U^Y@}9gaulK>X^r1P z+e!-*CZ$PX657n?*@e1vnjew{AQ$b@KbE{mn$ZOt%7bVZap#`lE=`5y6c><{kHkep z;QxePO1BhBPxM!h_VPrvVd{y->NG|f!^gLPf9gA`437o88U#-vC7=HNi{y1o(3 zYX-{L&k9MimDEB~MAJ_dkF^r=US{NOAysX{y-rn|$q+Kn{W+wnHDo6Lfmc(}`0B6ZN$Hr7X;v}- zUYg@5D68=%KW|!Q2zk=(&N$cC?s5c4SeeUIH!O;m)tMtLJ2(%jM86ZA+2K|)_Bn6H z_nvX&)JQ~^A9DCFbTyy+qlY^3H+qHq7x8^S{tJ0#Db4GAR}Wz7OvQ<`>7|N<2*NT(#MtHjCjGk(UNnIMsK^XG0#(9KEh!I+d6+?$~sYoG|?nb)(n>URYS| z_b}MCjZ5M%zhs@G{pRG_a3}*PAqz4k9Z<6b<-s1L2`gqX`9|wLrYzWI!6s!u)|9hY zMJHMs^^MEYQ-cbj!BT~u{20X^pV|y3)v69CPgmUXrNHNOLtZa!4}*<)A~OsxK|Ktr z*+36JBmnwEvzwygp3J6aY~AVyDVz>eTXjBNamr_EOx;iWIMGDvrbVKWG4c*irDdKb zlKRWJ>L!f=K;H#iai$?x!2EHP(1JfLP6D_jdHu!y$5?-zR?R8w7B)CDSV^yltr%BB z4UEVI@0W(;*V28CymHIpcFvckH6N)Y-7PtbFiV--vI7DpclS`(m)Orqmy08yOD8+DFF$y#xkxo>X4l%3YMKX&C;FJ@rWP1k$3FH4gC1_;xZ%yjAsK- z`Yz@gjEBdnrwlm$$`_1h0Urd6r_Jg#=uY|%_TmSe5bSV7%m#|&tju$Ns7d$NtV6aR z8+)qvcN=@U1WB@1@=Id@V)(vAGFBBbhV3C;m${rKJ45`D_*Wnz&!ZE^H=BAOqeC%y zrA7yKV_Jzl?Z#W~qYg2jvy{I@i{r7y1szp;e7f6>UFv*F)a%>2kUMO{8N9KMyxEO; z-)^+RjD^g^g90-#?7ATa8TqemwgTcV zTQw6$L#YKb(P&Vj2P!i&(U2*C;X*nUkmCY-_Q~-^UW^=v35K@Loj6~hu`igqQVY-Y z5Q!%z*(aBj)QeTlXQf7CL49$KbnLBZEP!sk6{a%?WURVqkkbZR49=Zqm<3GP%{#QO zJaECrov!%(`|j0Ym2cant4`;VBiU+Vu(AW6wqJjFJg@`T_=y?)Vh1`|a&52`aVdvF zs*Vko%@V7%e1i*%B)yV%X{6PDk81Rru6TPEP)+)(fHU$cqR3kDl%gFdEyig9u84m? zjue5TK#Q;~@m#>ExpIzL%>Jv@BNJQC@0R@YH|e_`X5go!ZrKd9GqV2mX2=X&$mjzz z(4ka-G^KuX^=1OSad&$-T19)=hC`?u*iC$~tibR7+pNIjYQ=QEo)vhUXoS*V&kC&Z zOMh)E@V!4tR&&02FIM1fdj$$o@*v*|Tu?~5R7ox9Oji_=&Q(&06`1@>NRz@XKg-_v zD07Jvt!H^PEAVA|U8+~9VNclWy~U61xc zHDu2IA6^41@Q>sw9G-|$;>Ud#Hn~f8K_t` zO=RIz2I*izY8n#hUb2Te;Cq(HS{P(GOY$z2BAIIaFNV!QV=gFX^GPTE0nsd>{=eUU zHsE(uCVB85_MaWLNCLrP)&GCB|LnTG9ekhm=W!Lk0el5liTd^W4WN^*cq-#w1tf*C z+-SwBX0Fw1;PrF69QAGxN>^?BdzURhi9_G-SK4J?SNy3}7$B6uS_}4{T~w>iAqbWD zANHU996*IR^pHRLfU7X{U$(XVXB8^jgDamyYJn^37*5DmLctKl}O3ZvWYm3F1hFPv2bVm(l*SJ1md*@Z$M9QMzft zC(qeY7A!e;7G%75jO<7evg}9=NqA?%y!7OXQ#iM=C&Ye7Y6xPr0#?2L;P=3v`limY z{Lw2L^Vc}r)I}!JP#X;kb{wDuKVsXEZ>H{v=<@Dc)%I0c>*3rD+E*9DR17wT6zB~` zD}jSSx~TBmX=t21T(OZIg+dLdWE2Wh#uQg8%qS73@|manNF=)C$RqHJJO0L5p{=bV zNKKR`#t~@6@9%c6Pb-=I?H4&xa;l8EXVMi1a*VLys7PtJHAzKQ0o`j-szAf{#j}QL z@qgb9TRY39!#`Ev<$xjDMUQ-2ixRQNo8@M05Lp-b&2FHbs#$SHHCJ<}{B9s9Nhj^AD$Cu$e_KxbTF z(-UV@>8dwxmEhC~i)1*2ilexst7iR1-^S%B@&i41X;B?hsQFx9AlU@b4NWapou+q+ z_0W%{BWq0|OPykb8I>breIdiG4MfvHAn-c2&4;OR-aSB!K;RjQ`)$+bek|}bKkl-L zS>R4Qiv@1rIdDOh;gpgRck>!!9OF>pe0~h7*k%sRh3{Rz{x{+k+Up=li&yAGrf@$l zq8~o}_|QJnQhd#&HghWWM{czLIxX`lJRm@rOhzy0AdBL@iXx^_o7qR7*fxFgZV2a1 z%lyUv}8S&%~2k>mn1U6NdgI6b-dDSs!mz~<)LV7fUGcLGxHoR= z*J!N#wfu@#hHk0JNA4xffmSo-BEhvUN;PrW)-5;bNWLp8GxzeKON9oGcTAfTPCw5) zb)!rC{CFjLdynbU=aiVXUvMW+Y7RGrd>9-2MWTF2*O^PFPiju>*qkmuGFHa+>kaYb z5*J?>Z+r$0nIxRE36vxh=e}Jz;tzfS)rnGbh=(f`5yI@{B?f_x5j#pXL054TJe?mxQ2#?lEq z!7yF!a$;pLj_~;s9c$4&?0A%~*aPQvYSXX@SX~hqO%FXenlArTmtRL0|MqV8PpDeS z>23ndl5BZA*=0w)Nx_Px2Xak2Cy%JkT2U}hk7e%Jg*|D~f)A#QKAZP!GoI0J=r|?9rb7U42H@&LNvVx2N%8?^F|Z4!L5jhKgZ+H@wAgpci5c#KkAD*;&t9m zzHEDj!f9u62C-{rvPkv=yT9SvzlD0r-eE1J+`D>b$QROob5Bg5a|bSpmMzJ@VVB`} zou`w z$3{M4^IiFt`tndVX(gZ_VxZ+R@#g^fpK}iEj4p*woBl3 z&HRN&o2m{qQ`q6Mpn2XpuagxO4acG!X|B)w@O+^mYre|1)XYP)k%;1@B-EFmR?bT zM!spU&+9eD>vQ(HT(3v+y3Ahh(<@r-$iLX@ul1@0^E>VJM!m{a^56EFRa9RZ%?2Ynh`jYkH43*I( z?>lz(uGgkeAYDY^2tUltPT0ZcW`lihrX>{Yiz5S$#XVX1$a*^f;$`&~Znj^L$Nhh| zX%s^LK0}@z@_2SP7@39jxm8ej48*VYii}LR++Tsm?H|p9Hf>2vxbg$JFzOv!0??tX-w9- zHt)P510!cYCa;u%skL?BqRBfB27!NVZ~SXnfqy~cr~2KfRNp(6ihcFom4~v|7{wZQ znZu(E=UQt({A(lp>sgXx9m_)eE7Za=`+TX`SMM!6kd^J>GnPGr77nBZ@vn{WuLZ9D z5dRwO_*bZz%Uv^KU%fYTZ+3}*>i8GyByJ!}p`Ic^z`x%1I*)P975P`FnZsN&Vqd*C z^AJ0H)kf>LHBlqa?Ntn%RVlxo(rD?%y?K4`YnL6D;r}eN04HyY?!?spjWZ7 z{q40zuVQ7p*z2}>6)UT>*Drs`t613=|E1<~dKD}Cx4piqSFy5J?Da{#ik1DtULWSw zSlQs63#{xfL8D}Yc!@DZItvK1|vGm!S z(b3K{DHu-=UGfmP9|FGQG0q2$^q<5B@y4&btC#Qqb)d?B-kiQP!{G(GMj`W=q5z(k z>-?F_;u?cyXI-0qb&~HIJ{t8BNo%8x|5IQ2H2el z{@KAYZLn;G1+rw?^vk>XA+U7iu+hK3b*n~9&GX&1(jTJf=t>#(i&QQheY)rxY+?Y; zI&$a1w2U3X8Q>rKmoR`_*5(8Ud=ttNSOtt2KZe($I}Ndu`Ph{ z72dG1WT@`8;4mcWG}WpbO~qFE+HC~T~+^zdE;~j0*{8{i8f7o29!<}_r~XG?heEsxo9atxmuU-Q}rQe!Y? z2bF`FDJ*8}D^3u)TnDVD#&S2uMPOadjpqd$56)Dg$3DNshP30NvRQ{_@22|VfOI&M z#*=H^Mnlm_KgCSRoAilXskJ=As`rR|;z!x3C10Pv01Sw8YgDaw^;zW5$vFbdd;?6~ z5-6rDKKQF*jSJ%G8F>KXb(*83WAgy7;|M;CrGJn&$>p^lh6jMYH>W4pfo`uy(`S}t z9@~K;$q#bO+6T!mJKijd4t{CKvo=4vs!scLbi=otf=#;XyM}O{`e-sy9qdUVb^EdK zIts>;WLdWRs;2N2;#8F-xQS(~#b?=920DEOOL(*|bHOp8%b$)mzLe+yT&-u1PY-0w zXp+(Nz<-(<_xZEYvZo!Yo%*5SH@z$W(Awbv(4A^%{~_Hg|4{sR0z|OH_LMh~6uMqx zft%c`ZsTaC=E0kV(gWa0+j>_eDl|>A(WGd*MQC3iZ``b<^J(6^tC@ct5oYI54WlHz zIf8pE{d1@mS1Vtv291M><@l4&TKDD9aA%&gU=~kuc>Mi8(LqyYBJQ2VUlW``l}A7P zd64CGR$5QoPChL%-Dr(Z4LXG%Ysngp7K`gx;9M)x6mpIbk zO^FQ`GBtp1-g+zIlx&zC9Q=%-PFaoMS;48*h^C z`o7YJN6SF8b>4N;AWVgjUUz{We81QU>4P^Q3xoNJrmoCrr*Z1y4O}%1FwWUfWZw=? zV5Ymy+5?EgL~ulXmfI}^UkXoWuh3^)&I7ftckQR5_!64s3=-LLhx%sks&_R27!iA# zn;SPyzdEbQI)6cPa^vyA9W@+vV`Gv#CHXJz)37mdpiO8@c7<>wgOm5g%w;}bBjM0s zyQM)Jt`#bFkn_ZwQx{jmFc2;0RW~=jgPcKJJkPyVY!YQ`RkNyN>En<&+1yU_r}3TX z>!azjcz+rG&&^t*Px#Td8Pe(1FsE(g5^hea6OGD}Bb}}0S5UkeN_*@K!(OoQg zY6Z-~dB|hw*%eSpYXu|o@$U1d#fj>5TP~!Uql;U z^l6Pay+)|24>+!Qy7GIR;s|=dB&<@-u0I;k6^ zwdli($YrdhMi}q(>xEgye{1uR z-Bt77{X>V~kbmb>Z#%jKa_1wz)2F{f3*=mJb?8@_ewQ;bH#xPAY8cqh?F$)@SlT-c zlX{x-TremJ{Vc&Oa(^r0|8N6KH0^HE%RH|aioH6t)Iu+bFBd9?ml{dOlb zNmFidV2D?j;dOMn?E=ClmjDLfg5?fh=*sV*}h7F+!JU*(Pwf_ z%uuH!%@5T^az#O}^;KFXi1V)zG^WySr|P$$(u)5n7-_!$Ys}JL)gcL$mK8zz8AN~2 zbbU-mSBZNrPzk@YO-_5QmF|LyCW7b8Md_i#7etesjL^kY4rDtKTd2gWqh6;ip`}mS zTo7fbuVpB!Wei+IlYCk^@zhYrV{%z#yb)izv`Tb*t$P4jX|TFu*GtO#6i*#o7hCd9 zdAuKnS5bX!BEy^nCHgD;#p$p0q2`CW=JBp-xzu!JE@q{%0oGWczgBnCUn!5i$6w)Y zbwPiHWu3@+z^j4&8chvl?Pk5HuXjj&MaQf0uC_;Cca_b~ArdI8^2qtRtBmNZ94>); zU?#lwZ=kmNBjAj0&JwdsK27SZiuGNLY#)i6W1B@M}i!tkC)9lEGs3m$eg90 z2IJYf{t6?0wK@4dD(rRHT~$ZWKj8plm72x)s>nj3#Fo4bWF~VDLi%F#*GgyQhse0^sDTWiIwzBrY z8yf?7L+%ACt>vw^lpqfy%XHCNL?YLfzLfZ@bkSo`+sw<>4`mDPC&n6e+9=qG>N&)k z;-L&RbBMLXLs@uyg~_<;(mR89<$)s zk0nRc*@q>?6VDX1)4o)PR?@3>`mP*<$**7=%^a$VsMx0~uorz4@n6tK$513%_V-xhB-2N?x28I2T`2Z-^wEpaM?c_39W~YXx#nhy zch%2SE8|8fZB9)tQA)>1DP2VO zM04u=%CKG;199p0pjj+@kF7>BDTv)FWa#y|1Hv8ZBYksKEPZLU%$+0}Hd{YjX>kv! znv5MUM|Q?RcA3`lXyemf`=v1C+-|mhgjM~GVvXpZ^mKD<@TakkcbFptBoJB6L`ue7l)Y04XPJ_ZY^MTqmu2Wo zVKMkDE}-_+%%NPLxGIe%HyU4sIa!|2+c4=wfT;#K%%qvBdC3XXB-}>TTt1IPshX2W zw3I)SB2_bW4LMHLM2KIZ$}&Y}b_Kb_ZmIRg5lEStCQ%)0rL9{*ncQO2rAF(^-xGx4 zccVjDw`Ojb#svMhuU!81z;4Rrot9wArNYO?>Bg0`JHIt^q<{BOyOjy)lO1d8Q6l?# z?e8#0*j!u-Z&3&=i`6tEMle?Kfrb20jO!v`4Q}_J`Hk!!_)6ZVjyv^vnxh(gO>Ami zZ8R-sozpAH@KL$E&bZ;U2V`RS>;2FXw`QJ)0{8Fc#syU03tJ%t~$-Z~SWdL%ChT_}{p8`jZk6)j4Qa-q7T7e|?WHI+oRkkim)p z%b9T>mhW{4O8zufX4bD}8qvw4gH0#5^_1S`Pf>HIZfy8u{+PN8>RC{SnN=5+A?z41 zz@ND_nlSX9j+c07PG5j^IgWl3JcAO^Um_k1v#yt;#7@TVBDbz~#gSiL=a|CgeqMVA z-`ixe&hQ*!RPqhROBbeUbwEBXo@!%_9N;W}EQ{nX(TAgE9qlIdvl$m?Qe%P^eiCkI zU^PvR@J=hhi;IC9Kc0SfZl^%sqOR$WTBqFnA}5wfQLimr0l@dV0-$uN?F**5YP_bJ z+Y)ED2UD&6xv#m2UVT8R@xyou@gtm@*rs{YDcBgW(bTavWne>JZ!qmKhFZ;G6AN*F zWn%Rl<+&d%>N&hkvf{XWxh1y9=$HcdP+{~b<)$fVrc074Ph=4%g55!PCApZ@NjO+| za=Tni$Ie6>SIro!-AZMzdhI4ZP>5oU%edoj4a~{wRL`+E+`%PwNWva%>XyzeZk-)X zqKyg8ITV=@bvQH*QctSmWdvCSyVFPi$={Y>yCdrz8mJ=;Vt>KqGuWp)fW%UZ<}OpK z1$19(%c?NDe54JQ<=Rek7E}M_GqOkR*Er34nRSq=VpHlfZ|MnQIBI{v$fuF|%s>3( zx>F)_}nG!qPm zTBF}u(w=9s^bEi&)9nCwE9ZjfJUpNT zIieQ%L4x1Yma1OhHAM*K~jQIa79;}RZi)2t7jPdjAS8SLsrY-0tK5Pm2#@sr6o<7^*+8k$c zOv#ky2mM^-{P`z_3}BDLNLbQ3GM*kb$VN0qm~;|ocM6$}nxuWAsY`6%amdoTZagzj)(@*1hKrpK{*RX>7Ak zKcF@HhgsL@L--9lJ~|b66zzCm3e}hEKBo?AsM|+v7$@P6-V=^@JkW)S=RR7*Q}>ou zVPb|q`jh*p2ET^;sFJ7dA2n2#esqOCn!8kE#%UBCyec~K9F70#-B864a;;~Qt1&Sb z7Z7C4Tr6zttIlPxqg^|zcv3sN_|xE7uOJwkg4R8w=?)d4B8@#-;bvfc;%`H`a(x$- zIUu=U-~gXW^a;-0;&PbhW48bMk@57{XLP8SLV;eWWJIn8kC?e>LoNd*)3h99e2SosOEad?M9ee9b9Yxpv zTM00U(2%^sdH7$msSXXI#_gSBU?>n=T8WEf+3*70p0zYQAKzp?q;&6WzrGA37{(NmwB8JAPxAEsldqv`2PEWXyvV+dbqMZ|^TEYaoP z6Kpk5xh+x=nlf)q=jFv7K}1afIy9_i4z%A?aiBOvp%(MIQ}qq#k7zjo?I6%TNi75p9rV-eaCIa9Jeo% zi?~$V4eXeDGrMnM(n&IT(QS+u*jWJ^0QAfdpq)=$p%O0% zHC&hGT?CoB9J?U&*{?j7N#7pEfsCh^f z6vo~@`b^aPI>iN-Df&~di_4eW#pMlg^d9@%qG&r5m#U#Gc?&0ti?ro}5a%m1Wcj@| z;;F_vtph8LPY*mO*7&5HIPR?CL^vqbF{Cvp=<*eOCJKp1t-UpTXIW+q3f znFUmecKz`vZ;lL_HK?YV=@7_`znCHZdggBoA@}kqyN}!=W4aG!-r=AEM~3B2r{h7- zrXMrpGxkPgHCXnuN;OQ zZCoM$<9t4xvAbvr{l4)ruYCtZysgqk8#g3si1uZ9xP2grb_^Wsh4j|roUT*e6ie^1 z4YGuQ)A!I{51tbpynHNyb?K4M-n=n?{(|FELl2TbsX9J2`=AZJ67>=eLfGZH#2Y%E z?kMK1AM-fbKD$Yu72}nOv-_qgU;|^R5#J2HM;_9PT;dHAOaO=@CBwRxEd>510nuqO zHQKRwC4=nKx@|N)S5Jy)8-)a%Rl|0fF$5}MF;0PvVmgj8d3wKCf^?9^%#4`Aj>|G$ zyWGanktTf~_NDLoko0A8rvUGKBbdtC1>E6XgGUf5VLYE#gE;U@Ag|9SyKqn#Lhs#6{h{3p z4$5aCz9`nx5R)N{@dO);l`S(?@xF0ajq3m#7g|kp?g~>&cV~L@ktqh!`08qnQb7;iXpS@dtTnLG-6&^he;Q%QgR-@hCeEn}c;)I$ z=P=%TSkPzDO-YBvLR^PgXN_F99{sF}t}NCcctK{`uQsv-|3S0DejKAN9!cfsruAg6 zeK)Gbdrn)edk6Dx3nwrCz@M!C*6`BY?iL%ZAq4IKJa+wN8~|bQ`6NkYM5nL>~_kF+|B?DQ_( zZ#ShY6yWDW^jU{qclL{+R&M7P`xqpUA^<+F&K&&_3gI{PB1V~cYCW$U=CoWF@Azr2 z=tdomY&s?46bO8U>Rq|zuo$V%hiDA6ZmfuRA6@o#%<%B0gjd`wq9D^ER zdZCadp1NNON<6h_4L{AvPfRw+)peTyUdbPGHARBaU2Ki4AlUAJSmRT!re=I@>&GM? zV=F<&W2hwWqLR!}e?N!TzjXU=dg>#Op^s=ALabv$!;F^f?fL-0HGzKcUr}&P9HZ}io(LzFAhY%(ADAxO24R=esQ4m zi+a;94mACu9{pmE0})&37t7Hv{+?J7A58GU`{n2xoG1679eA#T=xfz8ex0^x4DRDh z|JT7Pc0mKD8C-x&TtoJcHls*Y@%E^t#nV5m9%TscuIUpJtkMh=q#O7suOwB{4enzZkR!~w^rTK8QaZTz(LNbQ|csMSveCl-P9y;Y9L+q0P?e0KWySnmhr`$~7~ ze|+-beUDF0+L!1*w(l?yw>0%(;uq+e-qknl4}bKI1t005)PRZVkp>o4Pg76r9d7{-&?m(1yM;7X%@*PuAUMA63QIy^~ zCQwn1Pan)m%5qat@T|;<4Sq~+tdR{jn8mxNanmZA+_RvdfEqQdHYV2eP*8?_`IE4M zqJ03SpH$)5Kg1d0Zl_3%6qGd@&G6n76r^jVC|uMUqJYlBrIw<#K*IlH6M5mP^~_(q z?5%iVDi7Iz@69GLqO8w8=mN=cR-GG5IRz0h+P`%Wf6Egm;u;QlI{3%$lQ0S6sTf`4R=S^6y z6|ph`bvDR~K~8IjI@}s7hSU3+s-rAr8aX7N&NUY7qalyS(pR@pMJG#{aei}q{*eWg zLK0`8h6s@LZIpZ&4;!K*wRgt5>L~ukQl}$n4~ny6INtbCg1yMcL>oWg9A(MU0gwc9 zazj^VSL;5by!*yY+DLbEv4_q%cdlbjHTwZsD}L=*Jhm(-5{uB4=TA@ zdOh`2XKxDX$(sM8x$&tsyt0xKT}Nrz@@xrIo>KXo8rICjPg|G zE}A;CQtz?Gb1F4{o51~Oz}VSi7Z-=WXE295W##ZU!NOXoGx1l^#Kb5FZZL0L zDQ!I(B8eUMfF#6J#2zPj^Ir7*8dIbyd4<(y;vX+Wg7oKN2`SUkL^ zb>chrJt07H=OE!fj1JDysd2=B5d_sn8J(%tv2*}ud+#F>8F~b6(YQDIV~uc@#$My= zpBN#N&Z9TBewCP+-4CLsno8{&Ruz?A`%XQp_+hsyb}d#hE4xOn5H&&U?SLFU7x!41 zn^M&LR(>yN)9YNM^3W|Nu!bb#6gOw1d}YG zi-UNU@65yFjsBwPTkfKbA&ML@FLGi>Lz>_ep04UAoO^E2ZYTQY{QT zRLU!9k#l~~0I5jvE9r;W3{OVK8O}@$Ne2qF-(Rgb!`Z4#Bmh}Hc_*1AhUR$@P zHq8P7PKjr;3)KNoJU~Jm@fqaEfEgnT$hUYejYI)u=2H>!9ZO56k&ZaWh^Pea6g6B7-2JAx-EC$0^XX`0p_H0lICFU z(n1T+9Q$b*0%czchq8> zA*oM`^(S+~j{=_AasL!PM|sPzSZK2vPc1YY)mGc*iiwLf)y)^K6>2t@eTug(`7!gE zYu!Db{<9Lb7Dr8e!}G}^2*c9Wy*QC{&tyBOFANVKzQ*lP$q(T^B!XZ7uxBW1Y}UO> zR2N>kDvwGV-|^ZngYRVz>DJ3&1jWvFi9RO|S(j@xv@=gd&E&!q&U*-TrkHavIczRS zkG$oJjl?hC?oQLBxsJEdnr$$-)_uDTJAuYs80qWTzfrPu^iO2(B+aK8jd(VJ$a(D@ zmfpC~ad|+eL=vudGf+tI=KYYdMpK+-G`=#L_Fca4J?ymezy>+PD-8?VC^qz(KFg1AJ`k~I~ITZqoxEToZ|j)v~e zckk<3jEQ}?P!Bz>GJ4c0m5IY~ z{o(^VJjzzEPS$*3Wb*_%_`g1oPi&?A(zL7<9b7W1&0Xc!r}Y?BG{q_!s_3hhpr#LK zm-9@wR?|NyqMD>v_h}s)!#8U!saHghJy_Re?Yf@*((21W>s##EY`;D!(SCjPJX+_h zzFNKcBULnRK62C6>N}Vs=$AI}sKz2tIg97IjmT|M>77|~^__agP}5}hX+0f}Tvb=Xrc;#E78vXDG)y$ktlt97Do+SG2?%UA>8Wgf#+d{HWUvWxRRY(QfWE z?W;U?$SZBLccn$l-BWk1j2#7d6M%KZuCWvWK#iZbewTeb62ztOY&{-{h4u7$qKn0! z>Y(bxZwspUE(PsA3P^;t`N%zIsUk?e!(FL4G5bxeE<-Ic2)s^PYYsMK7C%eyS+<;# z1=@pscabPx#KciLtmWEUX<#U)(U|KF|Hm5M^-t5gMh{-+j}dRUOWSsea!MAt}1g0U2JjK5Y65}bSnq0WavGxzf4*84_YA5d-ziK@wp8jo^zb6io zbBPixXQPiy3G;Ksnin&dg1n{>Jm@F08HIc%7x3;!<|D3AdC{mg03D$5faX ztMPrWeX3YrdgS+3A;r$8O7Fj*YPcd{7A5r;UDM1N{- zv;0%#gt9xcg*=GDg*`2=hx*q zR;}obmV9J^_8`I*>-~298SON7UYyjT`|3zz5%>BIHMj(U#qbR0E3m1}M})6MN}sng zC9=XHL#I}E6dvsb-cSV(q$8I;Umm(8rDpzr0CRzn%=_zCR6mC51I0`zitrVRHedLG zP_()19q=eU>?5v6BKXPccvrJR>~-=jDQ7!EfGSo{&MI;{;dFMY3MDp8e>r=vzHo}R zZ+6Nu+})9r?A{mQcU)j%C8xif z8y;>gA35H(&+Y4o1|7;J+p7ckf?B!Sd2aprUa^TmeYGJjwsx3@)egTs9SpEL( zw@dK!ViiK_)XGIwG(7sxI2P&J-)ld~(-^~6z1Ml8S|}Aa6{k?EFK)Ehl-VO|ZjZD6EZEIisd zrfy8)?CdefxnfHvhg$kUZ!L}PFAicYr6cz`mv$CB%uzjIUTL9z7jL}IayhcZ;!H}Or`*c32(J^L7?3;t=}zVtJfWPd|ubNUVe zvnTlW8f;S&P`h4aAUK2&jP~_Ox>28I{U*3Z}hfs8LEnu@0ya%sm zU!lfQ3;2ob3bit~VD;X1QqZ@=uX;hK3a_JMJ3i=GiYZ$!aCAeesmd)ysznouNOdmR z*}JSv4`kiO>$pap=~%iA=U6atrFFMn*{$A*g?bZLWKZqA&i*q-Q6B_wNzeK&?^a)B zvA!Q>%Y$*`;76!rxl4;E`3U$L*ygX|=Inv|qq&o}fRdF@gOZ?hpT+u<`4S}{H@;Ze z^iXBj_gYyPzwdpj1iybLjY7JHZS~z7*eSZSMfxYpYm;?+&|7T!DN7KXqPQly*?sN~gF3=DG>qW;hhiZc2tLt$sF zxosa%za3HZx{!{(amWZ*k-!=GvGCSw@6?2pU|1^`yq0LlCl|Vun2bjLzmwkeRY>pBQW#3(yVNB=96zRaWxLZ}oCu-DxGaau)v?k! z>F%ICx;YqeV*l)smBE}0E@ItAu^`{Qw5tk)MhgEvKE%I4Ep%8yk2A;2u}B1X(>%rW z^a`=fs%-1MTgZMd*EYSo89wbG7V6#Eq267t0-@gZgv0OuQ38jbUnwagf87tB#$P9y zQe&PmC1UP9bE2~x?v>ZF#>Qdki!Gh9B2&NY9e!CwYKGI(q=zBIV$RE`RB={e;E+3r zAsdH0M4d004X@KvZYd65XPcy4AnO3KvscjvSJ#v3jMbG@TDQ8c=vmjXp}ORU$R5de z594$U#`FxBh>ceB@UF$Qhb+zOyhp}|V-jICqH4w|^nr-2U-!}nX21J*9zH&RFe@`; zXYVt~D>gdPhMryLw_TIf_VOZLPA>3ZuXCC}GZZlL)%Rve1XpUCEd;b!$(?D^e737?`g=B@Yq ztH(=v{?6q-A0P6pdfbp1`U-j_Pc7oB)3!Vc?zHJKisyQc;*iiN{;5$6DvUy}#ZkOn z;HF+@S#P6od*e#=x&zev?h~z0KPjJJjm}%{KGnINot$s`z8n?2t4?aSibEH@7CU)N zsFRaaraO}K*2(rCx=z}HaS)(~^7&t)m#uXERyEKKPloj*yT6YsfPY?t$Zn}wb)bA! zuf@){7kD$f0aT`Y=SLIaSitaApi(hvG4s%@l9_INz4Z*Xp{f=x_+&FviDVqEF3BA- z+?rXQ+fR#myI84*=#z_P$wykC){+}t{FOQs=XwPtnZG1C3RM&NK4mu3BeToM zI^Q6;7;+3NM~&298c}+HrQ{X+78pfs8#U5(HsHg2x316q=iCB=@k(yCvi90*uf6u#YhQ;xDfBb<&3x5^!p6nuq4LdM3A>iB`njB!n)7BkXPWc- za-L((YvpV+XF|>?=A19*iRQdS&ZErvMLBEDd6t|XGiQsOva`ec>2eM>=kaoGXAHUT zBIm2-tda8tb5_auJ9F+S=da9}huUV>nDZZU-fhmToVVdb!3jxSX3R!pKf2J8)!h}- zdU6LlnX@(!^BjR$-B7m}nEFf~FV1AeUS|8kV4q=>GDuvX{jq-jTR%4z(`><+d0{lBwF+6rP)&JKeXinigmNxlY)k*u9kH-qTKl|7VUXjARog^*uud-u%6q!7s*L2m^+d_bXVGEK&snD~NK2);CdN|V1s8wSt z@-0kGJn}$@a8>Ht*rCm;fW|iNP zd|t zosh^>(oD{YQC;byIVc4w3OyUn)^do~w%|p|fY@(2C{-3eI-2@Uy^ssy%yCa!Wk-!{ zq&P3Ukj~a#XXk+MSW7~y_IrsddduRR2z{p-3@>Ip40(rYkET{d3K6~tok;m24pxH_ zt9nRT7C(-Av#bYU-J>W%Ewpzz6zH>y?ep1RPz{MyT3lQsbg)w_L5)S*4XUBz6)SP^cZwqM~33@hV*F? z_qz_E;dVwzhYlD3%=iJm8~>sG&Vu!7BgZ8j4`e5++Zrc#zLNTd%0nX-v;0l8E_Hve z`N4O8V5G(bT{4{&Tl4aeG0*gCkBmWlA`&#X^8zie!X-A%I#&29ON{gp9-u@$VCn#+ z`#)@>qa7C%j6|I>R^ZvWk*LFnj|?f>gZj+3b8Xt(32?8_%m z-$9+!Y6I4sJH``xHrqE%E+!4S?kA^W`k%0v!R_&M!mM#AZ3zZp&2zV&W6p5vSe!Bck^SciTgtw ztr;++SV$gPz|JWe*2Jn?ZEk6b80r-8TiB^4ft}TbN#}7qMz}|glaypPQ$)=kI7PJo z^V#zPaAK8ciJKx@t;(aeT%^ZK#xJ%8>PSDX~gpP!IrSM%qBNyVf=*Hxtakn^V{WwaHE zThR5tLL{3lsoUlNgQ-rxiybeo}wBh^FX( zMdo0zHD9&vQ%KS!I^#8sQh;>XkFTZ=2xp)Ki)+Ua(0zs!HKZa>24 zX?cA@eMnqYUlwob53j>GYgZe00GrMj^Hph||GSp|{w1VzMa(MJuOey;E?3cvlJ>V- z5z~ATpHUGD)(S+?bhql{_F}YQ4U^Hr7W~T;;urtk=KcC+U?YA4HEgW(vNT3So6;3A z0XXD{}Oxq$y8OYrg7%W(N%^=W=Jo6unnxWu2zD4E7swjA7Fn zw+x2sL=k&*9<$r^@cc{P=X_3&vA*rpXyT>Bz1Mp9#}kT^l==L-#$C_n?@TBrMJI!l zA96ltUp2}svRtHz-M3>2IQxv1Iw0n8t^;O&qnHBUQ<`y}GXBU#dzxPwy-c~kYtbQU z7(WwBT~crN5XFwRraHzNXY(T16=OYTe)s249{H*p5uFvt3Yp^oj63;KLCC-AsBko# zDooN}qMjskab{6Ovm3zlui7eU-HCi~)%CFgO%%I4f?&!4c58$7<4IOtkQ zT0b6KH*l>Rz?ZC#aJ0QO=>DV;58=43<-^lJML7Krx|{yNP6wmXa32L;uX{h9$;h5e z;|GL~=bSb>!8-M92+QufGzHTWdh?^0G$+!)>?dfK#DC2qgl%e9qXdCtO{3K8U7cyi zHcu2lXSV748J@Vufle}?#t>@to~Hw9`yXe3=op>7^9XnagAfn;0d6_{LICeW|CW)KgvR zksN9zO|^c`DipO+!Rmr4(Na|K+*<1CE%ihwchdbTtB`m`X;p2do@lA3SsrCnZ8J*C z6n$T%b`*+KIvHc`G8vsS%N!{Ji~Wr34zy8-#&u3Kb*pVK8O0gV*_~0sH9GEsgxh7F zqqJ}e?J_8XV4!5HY4aa;^!@KQFAD%d{z)x}kKp_;`^|dV@P1_AKy+!eQ2eM=x z%F;cb{f{`wuC?!j?l*5LmU2DLf%{Fnrm?&Irj!dgdlghMliKxd#xc}KFYwbG;g#+; zs|PR$@oMXaUFXo4={m>StPrO-TGCh%3bVNOkiVOPBv)=GH1}3OSRt(m2qav9UPViFG_|=UR2UBMl1ZJxSbDlx>fm&HK^$i83 zyXO$(xLP=v+(;LiI_@LlXGk^!3Srd3Q;2q2mEnK!3YC!sPIL&wB)Fpwe)ApDhxfnV zz6v2!NFPid^`Z9L4Yb9V@(G-~BN02>Z~p}(@YyADCHs5^;DheBZ!VVdeVhaL+nz-9 zY7f5C{kAFBK^tzT?jnL~zx4j)QATKgvjHNH5M6y}0p1(F+x#Ij8UYBN}FZ2ufgd z#t{Q-BKIQ#!*)dk9DICNneC1!xGsxGI7;M*gnH!2&W#@AZ=p4c6z-2P;v-w22>W7C(v82_KH>FMOzNNng>vgYZH3jyw&!LECoQq)Tj3sZP1$ z0K^un)W`vhMbI_7nECUT*^3>Ne^&qeHR^S0fY_m-nEw;XKS1X2{7z&JFA2RC_>JY? zJoEu(Ytzf|Q=t%E=&)YzPhO1>%Q+-Ms>Wuq3ZjREd;?saTc(8AiZygqhT=`Mk;eDOjX~cgG@S+C>5-VPaw# zgitZJFPi1{y}edQmHh!frPwjKgk&12ytF_nPp_eoyC9Xv5NCVh0i^Pbex%ZIAdpJ- zdPg4GkGyqE%RX?Bc+h4>bN6k|UEzr&Tjx#v32xB!bqWz(6GJL!6^JCQQ}|ehMc+pM zt@qy=|E>04M;{%@vy6`Ft=AYAS)a*6K z_n$%;8(EfA8(Aiqjcn?6$0?_7tkuZoPAj5L`mlb5@x&`-g{Y%f*2Ib%))cS+X+nV) z7T0N{sE7@_W`rF!`L?kJYS45}>6^=^PT>?vd!men_OI&am=) zU-7#&*7aHVWU%pgrSzSo2Wh+*X*8rSw?{a7Z4?@!z}zfB zQ=1ono$Cc)Psv=~8K%XzpL$WE;8Q9)+)l~5uO_9uZE>Da;WZz0e@bLvANi!AWyhh} zpYI>iL&?7yikSNwPddBOr10`D?BR*rVF4D47X=X*#zBkr{$9|1ho7G<5g5mt3?KxO zGg(K`nl{YCcIG?msxa}fom=4BIj<Ss z2`#bRIDJMz%{|IipiB9x`wyWW8tUNg@6|(Z=Bp5p;fsb0^%|lgGB}80-BHqq;lye0 zu7mhQHR%Rm12$DEYYecgYl;U@^_pF-N@v{>4e*@}wG^L9|`MH(G-jvd|LAGrfJEGo3I?V&Mb#<=7s{q z){b6YNeCAIrw~Jp#D@j3b?W=r2l{B1&4YZ^qkb*udJM?uz2gR052B-xXk*ktf$Q;0 zIH`i>L{oN++?#u1OeEbMVuIbJj$I(efXsjBtQFkj1|sU z2#RQa!-M7sRkJOZ&Liir#Qi?=-7~e&^UPQ3PVpeloO9-HKWA0Fb7!4Nzy85G6T&!b zy!9k`yXyo1R$~V?-q9D@KZ|PsuKhC3?0a5p`_pGw+n?y)_G8rcyOeyh0g5k!7(|>z zQ3%zCUy5l4{q$Yt&s=$zgO5gEP%iVClqiTe=~ob85hp%~+-PtN8g8uJDu2VW+Aa3Q z(5`($@ue$A<*D3IY!TG^boD-8eOOLduCJ%T*Gr>aW5GxRn8Qe3P?!RDSGbj%p73OL zR9W_0BW9xBQ?Gg*BXtpN#WSjN1_lx;X|sC#D3m{Q?<_Oxt5hIl zyip^NGC23h$*k)oBOr38H=N%w3oHuIwG%G>W|n>Ls_nG#8#3t6qpXBJa;bz(z65Uj zp8kDdDI@Qro+?DS(iFGF$7Kp}_gTrjAZjvcg7a11V+oYv(^9)0?oFlwm*vWgQuHOk z!e1x~rD!Y=I9*4lpR5J6W`9rTH!2O*M@MO?<(Uwd@P75zQs=9t9Eg~7h=p)AMrV6f z0|3={>xA0A41?87^XHIR!{XBUZsE6d#0ywj>{bd`)Ox;Z6*<$e3Zlwvg-}VKRpvk# zc0Tj<&)9BrluEJEw4xmcSLr+WT)yg?2XKV=NrH498y4rmj^C=GEmk~!D+T{1Rfm6x zeLa>Tcpi-)T0!a0f~H8TpN=*>#^n@D5FDuu5K~r2m{~AHOWiV;HY}#;!C+CPZIdh) z59B4r$xGvviS<+%`zWh}Ft#~gb*EUe!Nq4vtue``vTMEWR(~?CUI=Iq>rMKmwe}FG z>8|fn76|wSVf)1S=CXl>2cb^;oiGH<_b&wS-mRVVwleX-)ljEQw;X7e)D~%+~bb z6`^)$En(UvVYgB294~>kq^_!LO}-RcutA+h&&KF?Ytw3JiFO=pHdj!%>pFp0#13$L z`KrASata%=Qb9_og?5bQ`l@P+rB<6ZsPgE2nlR7rKjHG|@xRulZ&Y?1N(NQQ)6Y>Q z&I&HRf}i=sTAZms3#?V3wSWo?gv#@al00AYdH$O)fArRx{;_J%N?3_O6#7`I?5SoG zB#k{R;|h4FOaK~ppZAsc34n&Y=Mlg;8jmV;V4{R4ptwKVEHWd5tQA&iywO|t<1nS; zw;?^G9c9_ysE370a_A$yqVl!U8zF@9^^uNLV5OT|#$}k#Qh<)_>O^|Tm#YOKKM_f+ zjPmzd<{`_Ua}?E}L%D*QD|g5{-*FUGel@R>uZt>9^N5cVgW}>Gox{w-Nq?ebkM`E> z2~ZC1AEt-=<0PyN_=yp8HwF~Xlof@L!p>%WVK6TY7CyE&BgutMqqBX48yPYI{mT73 zoqd2b?82}X9kTaIILV$caD;YqZm9E0496Z^@dBkP)bvn=g2;03@ALj%@3(Zs-ztA- z@F9MLvRW3RtO)#;1%IEp5}m9=~ppmT3pax#M`(An2NAS>l?QFJS-XIH>iiPt&L-H;0(>FSX zWViFJlw|?AH?9-`-f_Np4yO4JyPR)nWXQ^?iS$9{n=ARaM>Ug6=i4LIe!g{$E1hpo z($#RjMcL*W?qUu40xo+gic|Cc^9^YO@7a&^^X*bWiuuNapME>t$N24ZzRAj)n{MK6 z22MBYCUZvF)$OhN;t!{rD3PX{!pnlLgZ6aMmW|}rY?50x{C!G}-?HKVP}PxtiIsD^ zV}nZ>lrtQIk}WVO6SkKyC|ll^3E7=6C?8cSB)_mVO`9-y`%I=H@gMLT35=z3W}KG_vMnJ%@qG?`5!SruE=XMPgj zTax%RpIEn`NL){Ks(e+A>Q%|+g^y-#O`1mC`HT z3wM2avdZWcFWRhaCr8KA#+iu68|MZ?+djcB=)M;cnUxv*(EhBG5D4c4P1rDdQf!0Q{7^J+m)WS%+eR`CiHu1`+JxJMK1woq0NJTwnx(ervNb(Uvm4r2-BOf(B7DF)G!mpxbQB*`dvuEXIPGMKYApCe!Fdo$8)y zrGMjj$+3Ncpz}~AXAtb+M%icd@?jp6;=J#qy+lwXVd^+2`&*E$D9;|OMZyc8WWrJl zXs;?r`pqm~YXh>|NHksX8KJIv0*kXYBDsX&(#VRnh%Hb=QYr)&%dLq1fQh@8C%Nk= z6cPs>9p{cqg6=LIkI@@fb#Y}e@&@d-t32Xexek^(G*RV3GK)9jboj5ef>}7orf~Vy zVhJZI)$;B>NxUnAu5VeW_5%nHHOR5_>D3O64{tVpgckrs>#W16NtqxrX{*f}SBzul z3i6_c;>y@Zf>3DV9^j?%S{FLX+W9%(+}`=BpXfU@U-d%^FV5)_zn%Devos#x28hLNUTW#L|mG}F;5-#?gh+mEQq{0`VKh8IM8OtR1 zzva9L7nyJC<^nml{>n0sErcqbp-{LO%}@Q2V$q_)74tLqB;(Om#>2yL9_q@N`jDD8 zMx|D{knYV2IY=S8nN2D4EM$a2UIUYg*WkZRL2BpMRiIuy$X9(;&WFu;p`3l@JX_9R z;4D4qm`Tw}2?Z20A_9HIKhTp0&HL9wDknBd1XMd)j`}K1ZKceZL zCCIE;LYnc+pzJ60vlnQW{V6WeWcL=9m!y4oF=-d8lqEjJEB^bU|Nen*R#$kk59&w4 z(5zUH?4A1ArmP3yDlK%|Jy;abI|%+t-`ecwiz)iZk=aj8G-If)Ef$!kE$T$CQXH*@ zjd0m=Xl1O;ezv3xoS7bKDfD@;3N#&WuAD2mVyx8JYRo!{%-+XOE*i$Eh*uYJ8qe{~ z+8nEx%c9`Rd_!D*JpL6^-?SCV)j@{lUzA%l%5(JBDf|*&O1nZDmGQLPknq-hY3d54 zp6FAH*kpdxozFLSz1nd??kl;E_=sK_oXM)TVI^1QjcTnWRCQb4ndFtHQ|Z5kCwCYn zAaCKPMn50d&qw-Qyw{A(9AO!uW|>30t3LBFxe!x6_CIz7zhE5Q)-!zbvq1f|=b=Cc0q(y?p4 zs&@}He_ScZo~_s!Xd1(&6+rU~(uJTgP4wq7|A}l)&HJR)9$i`S@bR06BsR?A$!zq? zqAM@FZuy+2mqkW8f64o3iC0ig$L2ybbqdI@vvq#J7LH0=QiqM{izQ!-rVl(7m0$^$ zXV{@I6i}AteiKcMuLbpC>99N=R~-fyu$PN%ix}I8K8RWAGUOtpHOUK{+_j=f{aO?6 zlIc6jqWA|8M9^wPxok8a6U?-@YWEo>O{0s+^!~RJae&UNKfkTinCP6oJfr(<-6L2y zvNGhQYinlK!E8MUZ&&F@QoI_m1RO|U8VA+=hS!6IqK47Im_ujP{aU%k3OIFq91TKV z2WXgF+pZ(2qXX{Iw`&7ZojXI7QjXp`vNLKaODHCqJXueh)i%SdW$1^9tjNuNFgdw#@-l(Ge2ZpQ?f`iWF*+(UpEZ;J41Q)dE+fx5 zdrz1H%ike}R53M~5pq#Noh#w@=*zzX=zxk)!Hz=G$8Be!R`SX*kLRnNfjD7UBs`CC z@5TSUC58G6#-LuM)u?jrYwbpB-BYA%fh*PItB$}?j3eb9kcxcWDL}^@=TUko0U+1w z(bO<|)t>h_>!xtUZ>RA(`LE2^)$I_UnwYP<984Y^kJ2+~?C8#f zu~zrW*l6-CO2-0ASy|%Ut1l0lm&9v_-=mVV-{vQ|b-}xN(C6}l)?|j(9yGiUdojbC zJ71dE-1%sy(vG-?Ww|Ujn`C*C9ljOTk5jhaceUB z4Br~293G}D&9--Gwm@<`=GQSoQ*?u-*ACCTka<_nKGqNJsNnhf3q%X*?HVkrT;(+< zSB@WidByla9TQtp7esV?6=QZnPwnFgYMjMyJi@Xz7M&~JWgN6nS5uQ;sJ~2@Xi4)L_^-pA8`~iXwmuEfA{ARdfEWF`cedWg{{831bIa%9ERMx zE09-|!fr@uo}rRrlz`k)h9DnOnr&!lwqf@=kWUouS7esmAnEAY#&7)p2mTx#HDjIs zF8mqy_Kx^-C}9P3u*tb|{8?;fkiefG;3#Ae{#^3I0r9vhP0~E)(t!M@e8Bui4#+>WkpHuy_Q>U$ zpgz$=8EojpXkubnM?*BllAMY{5G>u!FtbU~TfldpS_wiK5HJ+J7+C?QcO zc`UE)OJrYLOfCM6^j9MR&c`u%1Xtn(y%hx+W4^9Ynf!WElG*spf&P;6SYS|YvpqpU zI8yiGzxp+xNAw%&JyDN&C*SJ4x^mFGp^h7GfdIkF$5K;`%1s5Db7&_|kK1h!(YWg< ztUryjtogcc5MdOJ?3Y(&-q0O6(X+kb6NQE^-6%A)`w*&{mR{~#3M}02q3%Srw8!xa zZ)IdWmV<>pNRME}ZYZ(I+%OOQr zNUJaR`pB%e&^zNGmoDd_&GLQ;uN`|M;|lF=84g95q6Sd#j^W+wJ8trM$yRX&&Jrscj|X#0C- zesr5a3aeNXuktHj2Y@!mjcmBYz={1YJBX3MlKzKzJzU1hM(_3gp<(kaHF0%4l{k*8?w|iCCC;2D+RlL4zc(|+6Pm|J19|Nt z7yPViZ%g`ej#gPO&o{}25vM9((0?eeBWKves53Hoqw(&~Whz|TdOl0%A@Ggrv?d?N z$o-#B{jADJT@eivv<*yfv`f$)CSaQOFJYuhz{Jy2e5pG->Bhh`ul`-NnC(C%W2w1Q zc&22L0v%*|TTi-kO2*KwPwrSCq+g;fj&SDdzDxR&#7a9_|Ct~zL_ z&>h|nv4gv3tIf=QJGfg23+gLs3mdq45yBldaI!MXq>f|`#1W*?xVvG83>fh6U+p&M^2@Bh68;qUzZm28jeqQsm50S2cd+^tN$%M*x{Kko~%)Mb&_xXUU#PKkyORhTi< z;?*Mv0?*BmxIm+&c>a?dJrq0gC&eU(#*&|}w6an|o0lBk7)zWIDbN0dxKM79%q)0E z%0Kh^%P9VgjN%bw6c^Wy2sg~=R1cION7Ej-97LrQXdLRo=G58(fDN?~d+qcM)LeIT?EFwuyUEM1K z*2ki}x~(O3)TGXeiRFu zdswV#!`!;q;PWCU)3!RKpuE}k*|2$Cvw@sa$C6WOti$mto^#}epj+C{ophci_<3uI zYc7lLNmnWSlFHnO(1o#s_#=}xOqo>P((q2}U|NU9&mqzD8F}8`JSsmT8cca2_j9Vi z0OZDK!+QG6n7!KZ?3l-M*B4*zOR|t5DeZs$qxBC}oU85vnCYrB^$8|#Cghpfi1dOf z8wb#D<6lw-wde?cBhogYg9LnZ>4E2^e>IeWUrkoGB-xXstKPj+W94{K9W|=1Jyn+v zE6x5RvTN_=`K5yVFQixEcTUhsQ=R!HW`O^F^r}I#8KP4{GODTw3+c~p=+$MW{Q|v8 z;|SAhR-Je4j`Vn9=8Ywe7{f2_xZafXZ{qR)PI?>@Mh@uTafF5K-A(_#hxI_C$3Mdn zrdR*2qQj*)1wXprl}4>j>W0ptrXungia1h|VLK(1W2_+#j%etZ5jtjtj`_~vv~EJT zn99(7Yl*wB#I1di{-mamaZYnbgn0ZZyvDn|66SV-btV*1<7zAs($_{>U+>Oyl2c)> zb)J))S`&<1+-d2j&Iv|NZRdX*|2fy0+8Euq7|zN5Le;Kla`AGdMuA2RCUY+z#ctAf zHT}UT1M`LsM0j0g*U+TCh$dUCPco z{ybfE+H&K-C##_C%=P2{U+6E=e-K6Oi0MVmw=|z;WKRDguSuuwP8F_lNZ-Q;D0Qbm?B+Ea*N#ueuMzbd}=>%a8b$S&s@~A71~`u*_hiC(wjT} zfl5+GliU$WURcXU>_Rlik}sLA=JT1@N2P`UwzeQ_54gNe#m$^T)~HQ3CIr+-?Aa{l zPaN}%d(~DuQCj<|W)w{gMkW;4lC({!CJiAPL&etMR#C~@Z0rn}f<|H6d*0g2YrlS% zxmD~-lD?qIq9eAKGt)Wpa6o&L8~Qpjdp)VCNObPyB8~4kBbxlPu{s8^&7X3UpGq`xmeC1Z)1PYFhz8R2Ir|3BZz z&uKOMT-L_V%w~SRF^8Y8w8L$GuZQG(ukCc-AN0EK-F@!+W7SOjqAl*bTEz?Ot8%&< zu{E0h(pF=gBuXIoW($5JbMBJ<1d>5;=XKvyfij2$tD*zC)QXi>q8+>0x&3tQrADOw zq~UdEZ*SaThjrgnUw3&}_vUlO!@9f4u)|^99$)-Ghjr6f0(W{?7rRY|b?3Y+tSs=` zw%s_ZvLNq>rlz(>Q)kU7?8j3^A)~45dg%oF?-W!sbyjmRek%LTvt|_h3pNUC@^#N_ zp`L@vmY4TqNI2u^@Aoes=IiD`q)0z7exN^P#Iv|xh^CBO(>@Ky+8%yKmP#OKZ-n+$ z7uuJaT7$nn^bagw^w050r112xpFi<{5TPviZXXGn%d|ORmTtB6^X@)kB#Rh_3cn$o zF5aj2Lud>&&TN6G$-YLl$p)DPp^iZ%ItETTpoY_jjVuVl)u-ULO8lrgz({)S$I24@ z#)DrF(uAo~i=QGlZR=7gj$e`d5ArPq%UJT!Sn{_Ng{-YS?f#O&E9P_LWw!)hAV|KxWwU7PDrCd zw3hagMJv6XR7b;5-6v9Ln{u~@p`AW-mO|%;p>r(MDWj^PJ&NE@rMLUI>+usM%vFD+ zoxB{klIyEK1A}v#TXR}})_3PLcVVq2Z(()Dtp!_uNyz3up$*5nFh(js)V5xMO!0z!qt+QkB8 zs&^_Va}H@l5I>s`A?$JMzoAbXcqxSyElDJKIn(wzr~fB3uszgAUmAtJb=@33(uOk- zCSST&U`25V&3n0EUT)`uj`_K27U|mU>#RpvyQO!OSS2Wx$M?h)m8;{l#3O^OzvQ+u z=`SfKC4a7B>9>ki0+oC3+jvY{$$GEd+k$oKftSymhx+`gdMo!fT#dK}&HF*_hkm&} z<1Y>htqc1v2jThHD|2GW-?_y(npo{x`iZcmC@6|Z_u9u+`r>*|vYWON!S_35KqeR&dT)r} zB{)^%g8fIKL1b043$#zP8X?AN^5gI|8Ysa)8hi|6G`+s zpMB~ttZim(pUHKI3v0y zZNz$!bl&COJI8r9dv6clXezNqpN$EH>Tjb3XyuC~ z7xfa@nq2MX{BxOyUvT_RV%;1&jJ2~9=J%Zz{zm4as|~|I#7c-L6OuE%hTI(*8^3MB*{R;7GZ3d##x_b$tG!G71dRR+K0Q7DYC9kM za{2o`A5*C{)?FPQMEk!Qj!t67?;(w>o>*F&DD*p4Rk!=Rr3$f%k_@iY`1Zf3!{PLhA+ zBbNH6kSdnCZVR6%sLBU?5pz+*Boh@>yBLiT(I|S!4j0CYw!xW6qctjInjzKFMj;Y7 zBXwI@{`&{FB>X1E&le>OP@nl|x(x`vf^6Vxlr(k= zz!@-05Bb598f+Dj9NCTHjCuaIoZ*6^hm9hw*%BUS5v= z?M`DS5sS*@f_0icg((RGlb&!46|SC1aK0)5b$7cy>G792gMq(} zZfvfkgU}8cFl(#EU*r5ygrM^qP470EtXw(1H#2 zF%Y~K-ygAXG<8~pm4ReL;t3|Bh}YRfvkK;p)E24NS|ftKN@GNs9cP#B z(z1UdftM(v-!5q)=N=c<))YmGmkpDehb!d6N^#@Llc(I9GUWex+8~7&EM7#cFz(^=8XzZ=pq#+^re| zIl8Y_kkmbBHQO<{G>C;vzRwBo zDY}pF$xAM*4JI$SxOQ)zB2C@YOKJBs5*{L(3~IaaTSAn^uc4a6A%$<*q_ID_`kogUWEx1S5I`%JyJ|z;o*A%qfCzxp< z=>ao6VDa?B^uXA{3*2wdtboA~-vZmMX(5rj<9b|^3QZ=ojmoc?TpLVU@*tnRCoNeE zW^E>rCmo-%4+0G95i(R|?8PGlr&xD%Qm`@z0P2I0Tv`y2+Ji_7?7XixXmFQ|Re)+# zxbPcnj_@gq!za6^O+f!OAatcgzFQt#*Qbj-Gtlt;W96pY9_FE;Bg6wX$C9V9pHy4w zrTkov8Z>PBnKk^JrXA$a;Oy-IM4Qp3RfY>pTh)$w8>;m4GaxNlipDR(%z41E$EP}_b4O(}Pne8SGot-eDVh=Zxa4{-ELQ7DiCU2!WTJwO)HtNH@uSX1YLDw59 zEy?bxe#pV6=%|U*97x_B^KEe#b&?x1$Gi#fC>3sp{fAw;qtIquKdjLO!tdI|ZbsW7 z`0kplTpASN)FwK{?fmtS^mZGqIG&DP1pi44$-N(3Gxi_MHrGlvvlU zQ8NV+wZoU&acl0bQh2li4>x*jsiU=;Cs5$b>c0<3J2}fH$qyj8P{9dfZ1^DP#@aNS*fVz=2CtP3;&ua4vf*oH6enQ zrDnP2$OSJ%73|E`%S<`$vADnW9ZCbmlw0cn1Zl`E;F{w5@5>t%wBx=!16n}PILSf( z2eYMdZK0(&%Pfd`v|q}dN1LScb$LLviGlp}F>1wgnKv%d@VO`039kIL8`Uiq?CDr@ z=C$9t;D;>O>&H5ExB=taXybdj8{ft15x~;2%7K8)>B7g#lDcqdSZpW0W4Ur&(h+ zGBD)HZ)xcI57UtB-Yu|e9i-R7`V3{WK6IpzLQ8lY7c3` z*6cim8?v8}V)sLKcjwZIeCvn_ac<2BXB>nbzo=4firE{W?AYZxnx27RDxew?4z6y`?y2g~a);1=@kp6q_ANOos1!>t;1%6eDq zSpkg-Q}{h;@T8AA#1IW0ajg)eKMg*3(g&cy7lNDbg%_3F66`;ZA-1O;>9Atn%pz70 z-1U&diE}NufD@N^(mch2kw@*6{+?j?aGt}58$JC66^!Gl6krA}u17q;7@q0Yv|T3i zv_1#`C5N`;F&a8{K#=wcx^d{+B1!9Tv=Z_S+BC+qL|uD3a;= zVV_ie=0L(9j3!-YK9)5& zSTS|aXw#Z`h`=ZRnmdAP^bST|(E3AmKgGNIXS%)tTRviPu;QzglkU^vo#UO<7sotf zV6baklk&d{R-C*i&nwNvpxS8T!DBqEL7s~$b3y5juWZb#t0h%(_c~=Fk*rhpkt zDYXAOfi{}@_WS{0^8qwi1|8)@&CWfSIeKe`+a{_y9z(pd@VL|=krzZ;e7pfx=ZHkf){o^ zUwP|RmTgm$hrtCDr|lEYIM}Y|tD5;?=IiD#AI$TP^Oe`sd~*iF(Lb-5E9tOJ+c~Av zwpxegOvDG&4m%&;#eB8+)VJUF=U!Lf&gbietWp2B`Kr?0ZPlu&_kO7Px;ZSt=IbB| z+5LPiq(|ajkFH1--onlP|z)*KsL`$OX?7v>JQh_J?VY|FtAA{ zSn*d2OeO0!>(u00Scvs=TZ$Oc6H6U{mGx)hA63gpa&aveu}b3M8=4UySUI%B=n1R? zPiJfW*Vn^DcE=n{VzRgGU=mBUtaC6yAUk3Up{^u zje&hw6HPonEPnKu$3sw*;xo2;n;sMYusN1^XV|<$a~FiEa%YDw#mp^v4aM@O4AoM} z_x<_4r4(QG;BJR5n!d~W1OnZ0AFASh7z@KE+zLl9eu|B;NhNK_3o=knPLNcZ6il>4 zIFWgy26h8(FX+BRZ_ntAR%pOrN5>s_G%m#$aKyL)TWNN|;jo)0J!m&} z(rRVR?J>zjOI#4?hbq|r{DsIS*2Ya%pE@dJbD%m{)M7kkti4}}#^#jZ2}fiP>$)3k z4)&KFn{zyt_CEhie|3{)8nm{EU`9Wm9Ki1siZ$D$aTU8@ohV_6^j`au5VRd5gj||A znXewI9zU1ac$W4yP9HrrwOLFTrq25ymUtkhSR|_sRdt0hwMK%_eZ^40%^6HGnb1AkgUjbG4=)paLv7`Jju54_D<(-D#D% z!98R8f)z91&m~b8i7BbN>FIgA8%MRSbzw_l$p=xNGrif7gMyLMA}zDm7~M)in2`v} z#xW;xNUu07O+E^--sC1K`1oDKvQoy=4qdpxhW!98kxF+smRR#{4Bdppp9aUrkLhbk zKJ4Ld6OTUYV1W&U@y*5T`_(cqoR6=~$C}pieq6(bSmIxUgN0ITqn~d_)29r^(3_^D z&fedB#|n|OtfUPTl0IcnX|i{BnGAAVER7z~q#aB1N&2M4#lgtHJ|l-w(-QB#9dw@~ zgB2V~Ri2uz800Z1^=at+S)9n0+r_}CZnLpqT_>HAc)Nt&f{yQnpP^PG_}NDR;whua zUE*hTE7X0wP=xJWbLGq_<4zucpyzrlX`$n#2+EN_b|Do=t3mkG!dN+cDyDP@I#>w$ zvD_h|uSNV^8)M_bR5SdXBBJE+Gdd7It-KgdSAd^7h_KmH#Lu+_`~-fnNDOYeCB;$m z&XBWfljCMfk(1@N1Ud6`$syjZ z`Vjbe*skd3elP@^h%^z!hrml&THF=3*#H^gyawm{#LI(oqf6)4{}n%{3qRG!e)w4) zL}HP^)6ZQI&aO?8kuViY2xoDSL^x&fv=lc_Hry;WU;2feeH8M4#ZOqz}j#`lkPQHearCc5fMq7#JEM2 zP-&rFHPO@zc#m0FU%+$$j0&b^GZ%dfeKk?yLde-Z1oal>Nk>`hoSqC1C!pl68Ex zyj200iuw}In)CcY&^2Tab?MyNW+?*J7ZJ8c;)YcC5-l1>vGf`6DtBK}hN*BZ{$uB( zOXpr7%F3i!OVgY2{YcP?cys-r#PbtdlNnUVbCrnplAEPM|Td;E(OTj!3}3-i_SBl<<>YSz3kG`Fv|%zrE-o%h6= z7l!ZgSn`qFfn)MWt=GJ;kKzc};~h+y=nik!(ZdBN_=M>wlr=mU9Xws<Ew+_GBD{2F9Sd0bocaJESAjJxLE=}uuZ1a%A!QE)*Y@F_mfjDdD}8_QsCw6f9O5#g4Qsp^nB=3f;gPzqwle!a zu+{~6ynB?(gr$jhuAckZ1@H7yQ;@iaUz4OxdH`41f_FOk4Hh=S9p#QJ!4Kbk-9K^Y zWH8A74c!(mfz79aCd;4m=pW})TrfyyEPD>qL zds8Pkd22Mi=(}_($}28t*yKi4lr>#^O+_^L)YhiMuZaeykl>VQirq1|Zs)=K?mT#p zod*xuc`$eUc2*_U&fkCV@XJz@uc>I_)Z@uAQ)Q$_mml1enR{S#!MmSf{DZ|WX~w53 zID;LrwGKt2yRTeOX#?&o{>%+DUCPT=Nl7W1cm}!}4&=fU5Y20nbRCH!#Eg$H2)acu z?$%LYORun{YY<__mIqx!NtgX6kMfP#hD2b^^ZTsXGIWnkdu&avpWvqCAq*2JIazbA z=CX$DOJsNcmgJveEZ3qrhu1=L<{ueL{z{cEevmW}r+dmyQafp6aMPL~aXYT;)BF_9 zBXn84>9P3dC}DCfRB7Fy#FmLDawfBh=N$n$U0Ze%y&0bt+|9=F!ScjQ5TM_xm0OJf zeM;I<)j`*I(7#`j?BRsSRQ<0C#m)PFP#owI3P^7jN|?8L&GWVgrzWT!|f!o@lBlT$T~G@W{_kx!zQuek__=ChOG(Pn90zQNQf}Dgeob;KqbF z2O_2F;2PTauf~^i=;i30)(x}a=9{tTYoLi6r}Qaw)hl_k#-MEX45ZRA5z+KzHF&m4 zHJx1*q_a&UHbV?RJXA`fI3wyGut!4#P>s>g}2VTh*YSHs=akO!m~ z7ZFmRWUtNZXvn-8-)xuBqz{E=qiHiY+UQDMughsRgRFh3Vpqen*Nku4&J{WC>mTcB~p{i88K#uxE)uj@yUXdsCYrzV>I6hq;#475Hp92SJQ zB_r|~jmTyx!0d8FG}AO9>V(V=Xb|MLg?{hWrhmlu=sbzpJBON?0WA$LcmQAX0|EGA zZDV!~p8sX7q$AeJu8Ua`HMyGwL*UoRH`J|`rnolDdSWB0M2d_;aY3R+;}A7h=ET3KN3A;5@FuJ$Ii@-2?zW!1qa(*);iWYH)O5u}|D2r2gEtxq5U;nC zNQ!wpbg%znykN~w$fAl^La$&KJ4qH6pPOK;yU7w)YKWx~u%AYUj+I#lZ#QN=mi*g> zifV4puLTr0`db;#O6ea=vl(K1=L|&PK&iZAh?t{x-IH&~v@~s*hiSb`OZk>y;crzUQRCM@nVn|^$-NY*YvBbTva-|PR(MYeKi^@4h-G*w; zCAw_j%Hh4{fH{z=pzEKQ1T_v-vje2&1(9^DMo64mR=Y*@1e2GUENZuaB3SVHnl)^oiiBd}@658=QipF$i8gu=O-7L&I`q_?F>W#vS}OidyL%t1mTB#{ zeRxpsOF5)ceJjp`Nv_M_-H!)dcl&N=7oV@{?j2P&`I?*Eo*w4LIt#JA-cn(E zj7M?o!Sov;IXtUQUgP<=m7bTU2U#p5b4Rkf?v_Xm2X3pGWO?;w?JL6;MuBC_E?^BMpl&5{6kn%KA@*#YcH-TNxvl-+-FfANvc{l0sY=roM|I9G zZ|pd|bN-;lj`KU`4{q%EDk7>1PS@dbpJum=Wro3*Kdh9|rl&gg$xUY!z!h%^`Gd}} zjUBwGpd${Q$gl1AYYy%6jpdVu5I0GP!+c5$2#Z-3x7mnHXh>v`Zq0V`1sDRmE$`HU+32b;rgPv z2IHEI3wgXB01T<3arWlm%O7CX9FMXb=cSaEovKs|{-u|TgQfHE#2PkCOAoJSup+_Y zxg=>#{v-CrA6kQ!mrzFgNbt?i6J~s$U5AO4Kf>uYR59P&`EGefeQr__MXq6UKK_Bu zHJgLGAHwyuXcA*kPb*#gLUv?NJgW5e>BQ^%$NYM}YcD+LNMPML*?QCLLv?jP?65;r!j=yBr zDFohVP3E|uYl5H)1&!FtTrYeZ9%I7ggk838zUpw6mq|;emQUI+tUUXiVCP*?9KbPZ}(Ar;faj8pDEJLvt^H- zaozE~l4~q~iG1E(Mq{7g9@FK)fpPw>P&+BH)`}JTyxz8*S0l#SzY0=yvPG`y)c_KI zP&8%6nzZj5U`M~I+9loOlYW$YuA9wWEbX7V`;<p#=Po zQnbv@Y$ZQCiPrMJ#TKlO09Q0hc_#48d(ne1c}I+eM~nS_Qz@YMp2LCDQeDTnhVAskYiuX_=+L3NAYRdx2AeS7Wo z_=Remhp`Yk;bZ{-nZt`WIeA(5eOsR|?f<+rTaws9Jgzux87U z7R;NBc@;&lpR9xv3-znxqd~N7@sWseM(eEy_r$X4{ara4$x5D$R4P8YQHh2RjBhT) z+il4H@rm{AdZhkFHR@L1?2pIT=Y|a`h>-GC7ju(KkXcDOwb{NvW)uF1DBwZrjXLJw zv$X&p#b!EA2;tM`EAqfstOx!cR1t%Be9BU6Lq&|HY?deNH1^QBprqz*^`%&IGnS@A z;+3zu-_mgmM)3knoyw916J@!#FHnQ5E|S1}T}oG<`h{V6Yn`TwuCUs+L;e!fx>S7{ zl4HKDi>15USgN8;nfSO^!>i0a^OooI>ItnYE?Fw@sbgt}i|{EsGP%JNqt{bM)5zSF zR_1t^8HdFm0jpctZjNnj_@~WaHxupr@wv>{6RkYWIzQ_vZv;hV{S1HSsvcP}Zf9r8ppN5W^pph%@*5-fi-y-IkPIZ*|sR|(-Vr>O(!RYHo)K1!Hg zrNPhGW@N!y8(U=0FCP7cO z=T>!%$3L89p?Wy$^VbRuudXbbGB;aoyjQ6R?s+KtyvoeyhikT6U76{?!J?V@8IJ^& zwx}mu&zQrkSEV>y_pdZ-Rv7QsyW(`I`@NzI`F*^Q%}uAedo8|jeZJ&9p{w0{LeLxk zp3n(*73huL6LRzh`%?#$(wip~;OLDK?LcoV-q9Py??7+#C=vALInkR_DnK!i>Y>d-@QGK#*#a{d1(in^;o-E*=BAmuJ* z2Os=1Wss`E^`_Vp~<47 zgeJDW75fvucl3P9+ScXht<(wKI;yp-xboKBt7HT5L$k%>$A4P9;m7pwjp~-!UycaH ziV%_%tU9(}-2i%i%NR$`-9Xmpb*b4~3&;r_t<+d@Yd&9hH1(7OKvg%Y&_f(QB6>1| z!k~xB?rU=NV530s7R;>Z;=CgTlJLE>%(^y#jJZkQvBTAmhj6v=%QIl`6Y_C|xfvc;PIApYnSyGr+o0lZPk)ciuSbZUaerRAMVd2UhM5KAL8 zu~qRYG^`u`K;PtTDXfZy-;BwoBZ_TsX4lfTW|*$nX9;rqeNL^ zXb%=X%Peb2@ecETn5z6@B$oUmiqY-G8d{nzh;$qR0`gdWOA|WG|4;_Aypyl`8`E6! z{w;*HHqG4B!SgBKSQ)1LWl75QKBX2iQf{%7o5Pg7B`I(4DVMsG+dB@R%#2GJ|9V(+ zhoy@DM@#bWXvDNMY*nl2(fPsRY3vH{^%50L(W|Chd=fouNzFyOxNbZdi@lrK)6z6A z(!qYo_b*;;HN4KI0HoVXWR(Iso*wfmawk9Q{c|gRekWd;Rr9z z_WWb>RcAwhL`*v=0ZO#X_AKb$u|4nnxY(ZWe|jhFS$gpMYtNO+?Ar4X1fkF#cRv{r z{bmUwrt|0%#bo zO&wPHBKA|oXQM_Ga_l|H?vUq>DZYnIy5d_?C7JdvWC|vk)gQgo8cUszhyan%Q)phz zo7hs0`qyp3`hG8M#XG`IBRb4iP3qLR$hcU1ZY+r+$@x|e`-arSY3Yh%V!SaEEoZB1 zFIl~wuWANcIG0Y?V^+L$<}7I+hpV@*1If3+!q84xEoPI@Rxewg23OZspiR*g5^`M-aFM_PGzol5f}^;Zp#Dg`1sL5E-Q7jb?4SxO_bBh!d8KDvJ-* zi^93K2XrOE%o=ebfO`DJDT#2*BjhY-~GdDJiv1OnW8;3{J+*V?$-1}Sd<*VLi z6^tv zmUgLiKpH?Q!)&UlL-a;<#L}m8zzIIJp+k-3LnRrxthV01T9A-1Slx_WqdZDsq)R2$ z_+-tBY4kC04=rv5s#brrsV0bcgQJycWtlm=mRck9o(+OqsDF0mkKnP@~bTQXZVWT$f{igc0$)& zMGa1gBAUM4Anz^O}`ZC=;ys zOl6C2G?(JOPqy602hNw0v^p{fR=^eV!X$!q7!xRmaK?4U2?}+fCD2IYRuT~n%pAdM zD_wKOJb~91Jnr@-aPnZ`0%ZxHtV{r4k$p|t%cNP!8FRl$o1QZmN2_r`%MH&R(yr z4x+Td>_VyqQx7rgkscdKPbp{q=XCEY-C8~~d8+R0nm3yK*v#Z4OusMM&NQQ#vgPHN z+wQ)Gx-~S~3e+6?dpksDms?sQPNt&L9Tp^A3*wRb1*+rtxl?R5#hxAnUCo0jwC35z~` z8Xzn#_|DBPc#9AAskVBrGLuPoqf9<=#Cxr*$f_FewM>y!joxcTM(!)G_hoewPJ`|% zA4|YwYeN_kRg!wpMBkA<3n_(6N@(H4xBGYt$6w?9Vg5GnR}HFZmcHb-aME{bTqxhd ziJ#%)tz6<8eSQlkeu?Q5h>!Sq3n%_oA8+}H-{R}HaN@7`@s^Kx zVTamh;lyw9@s^MHJ|A!4#IN-6mXG+&KHkEK&-i%DM|`i3w{YU0^6{3B_~ky{!im>u zfZ*rybvb{et9-lV^VrV{-(&fFIPrQDseu0@mpVV;)jqt_(l2v!szJT*%GdLE4orp1Fww%9tN2+U%V+7!ioRStBbebhBF|~2j16#!f_mO41cfbuP)->d#@C8p zvCN7WN-3Q9PCCS4`!`TUb@Lq0NjxL-4U8|iTjGkXk*AF|$-|qdwU&Z%$f0_4p z;@2ZT%iY%=)xrP0&G<=wcc1(IV5|FnZ;Sgb^5y;5mve`&|60{+_{y-7e^E1jF36F8}=Gyfm&7Ss+d)fhXridrU(=~j$Q;?f;4X$0h! zRx5EOaY<*Q1mZ@ZOG(^-u2w2VO-RPf_)XN1#Baulnvl^%qtP6KGWYH8Ntu%kz1V3ncf4G<+eKb3ywb+J4P~yosq4v*$^*XI?fCi zk(4mr9in|&k)UTxeeI;!g(OXiT|uy6oaxFHBT08=Ud?|-QKYTr?rDWnsoL8gse5t~ zk@!aXCIz7^^vgg+FIzPwIM8xtnf0a5=V^WA`xACN^AxrrYvsAoCyqWPpSVITEhe~< z8%Kef%Z}wpigS23A>N)hIIr<6x|HS9;XT{{aokXt1$Tb`K7py9{(tHA)4!*tr%EOd z6=}`=Vtu8<6H5)hn_&_teNf2_}pODWmkNmx_8Bx zd-tw=>SpGKU6-kQxd6fY=A|>JA~ylS`&0z)w7sgLOu#YD;@7eIa?YmX*KZjy?nQ2cKH>nQAsylL@X&{<6Vszf8e)x*_q8ihOt}(bD zpbu5%e&U_CQK;1LMe0dp_KR9DP#gsF&C(uP1wXhz>(~;Y-;w_dmrV;~CIb2*KLY&@ zL4B8GX|Gm#3S(|PfFVBhYro$JBK zHA8?olm6=jk^oh`m@I$+fwq#vB66NLshpacL?dN4E6 znfnU->yc#U$)o}*t{FtMnT?n)|3ZrP%U$%6r{x5$a4h~5ud5}<3?uZz{lIyDZHhY~ z@8|sDJ492tnVI74J<8|4N4$!#j-Gdjr$Qw%+q!w7D^^MFd*yg4+;Q>_@c_1wjcve6 zZ7$HkmbLjT@?7tT{kVUNUL()ZJK7ZD;3mJ^0FypvRf@Dvvw+rApfR~A|P4V4f2?V2BgAsa*aT|K0G` z$5av$<{yGLU&n{RTRGbY!&^Dqw&BgPe86)3&%m2{@n3|u4;w%f-YoC`XW&i3#y<*g zzK#!rw{o@*hPQIIZNr;o`Co@O_2Rz>Zyz>*D7;zT|1Ef{RTQ=p@Pp@S`O$aPfnl93 z4<*{!zh9n+9Zd+CO@pWHH#YmJ(RZ*Dg*3q#od-CTuyES2;vs|(Dkz4A-Ma(}4!=!r zI68LwupP!`7WO?iD0u9J#3!Cg^eo#h(cU+Gx1(c!7`(&izEy+x8a%ct@rnD#W*#8h z%;(w?k3FB<>9n?F=Cn3CaM33cwT~t0Qa%7hL zY%Y9(3ywhv#9&T;zs&fi;0|AVPINxqCcL>qhW_f+^Hv)E*?;FVyk`!sWw(%ucf(bhh{}{{YwIi3-VH5h z(INBF=efo?r~L5V=c`;kIwJlF2$EnJ@t3Y3 z#`*Yqx{K0!fQyGv?;fZ#>riOgH^ZbY@Mfg)__9s!tz#9_FLMr*pS1GVICw zp!clFZ@2c{Qo1j7fl#83&;JpDUc)cvcX)xDc)3d=rT94UYO+Gi{=i^^}OGHD!j39Q@@^jwCr-FqYI_kte^giR-qqM;@2$euFcn8@m&w zhFw`dW|}|)o4XIklnA|(rl74(Ms!?u>>H$vsUO2_6>r3bqWJOkxD2UwOWzo#_6^iz zrpTtLQ73f%nR&i=sw@)p>wL}nbmHBN!)bNr^XXkpvbMnC*=5Y?1_HcZ)>|FmmF4|{ zKzV1}sW+LU&gjw;zoDtDEVA=1o9OMQ zbxRo*u}im$)gOzdbYeW#A|pj#2G!ilxocY7ixw3|g);Gb1?B|B=Df}6^uydfh7S5ZjgA_0@z7D*rA{mEv~-Y9 zxM;l&0X9OwMa)Z%q=!cpMAox9s&Ffi5I~e0Bc4DF*OOQTV5nGI->i(?(=pNCePvZ% zRF}UHb=At|d-V&Fv#!P&rtL&}UH*a{T=El^?EKZoNBz+!VoUS><_FT|qIo)$$$^ZB)O%lv+~$q(PJb2&Ub6$ z$Dh4%{?4wyAK>r&oijeb-}yZ1`?&tjE40Yr`5*I%j`%wlnNl&!p3*z=cR$I_G+Yta zgpK1qnO3l@EofO5;-}`XA;`&6aZ)Q31uD`ma7w+z0Tj7Ea9w=Jj!F%`0;<4_4%HS= z+XQNxNNp8(kJdL~V10q=tDFfry)^t3DnwK&yURQO{GR*r3~{>@#&$6T-KX|${ujHt zQ5%G>^j``i01)||G9B(ielJoq0khxN1PnNz;SRr*hClN)1Cb6!A^1tc>TrPCFpIMEXG3*Id!UW#Xzng`G@k~pDw*=<@Kv3D zc(XbknU9m?yvQ20YaM%PfZ;FeG)byO8!tgNU>oBrv0&qq!Tt{hwSOxiPz(xsI$#ML zY3RA4uBKbZTEeV7Z`U~qFg709zJmxs%UPmWka;55_-wHMQWj+KSF8QE%j1`4-bWli zRWMAAKcCYiWbe`jxnSng98s-deFO*G$X+>0r&TTuAFq;r$(gI--jNAANl_+ztw*TV zS&OVzh)NxwG|z(wZMk4Mu;e;RelY9Np=oM=EE4>N3m1@kS#n8{j~ zquiogGTBz;5T+X5vz1jLw_6tFWL;uuH#K8sP)jU*w?<^kd&vyd6zl!9&73*qY`sGA z**dEL6{ao)BxhP7n*XqsE;T%TnnoF(Gfo{_{8qW|A71!+EA0B-J5~nIa!p&DSdLKU zhDj>dbJrbov!?q%3OO7qb#qHl`Rwv;&Oz3}0q0+=jH3erik%H8E}4;kj*~q=#5L5F zU;Q?}XDw32Vl$rtTLlr9zf%nn?!1m@;`hhb!4ijz+OB&CJ5$9q#h1VVzbxleu|lYN zg%y6;vBDcqHNdE^a6&6u8vX-5&?_s>ajY2xWeIc~>j(T$H#WYlZWw=o2LW(>I&(Yl zyk3G@7Df2g`ys#jqC0OlC>fr&>%SB(y5CF&i&)w{%piDYgzsTqV$o4KgrSwG=R!5j zAC;?+sq*evY51e3MEO$%SE~BE<@v#%P;628Jk?-10aob40TKGR*FgQyA^X=TA3=6j zPlQpcH<=Khnzp`8)vIUnfsWE`U-hb?-b7G7Uvf)zNBhC z|Nr6q;wXAwUZV(u8~{I+1uYH#ga#b)Gr|po=lxziiS#nRubwXvX)j+rsBH7X@}3_K z@*i(;b#$=CRq~lUr+k+0Tls$+ZIS z`>=gCA`}P)#y|L*PB~N7^Lv8ortZ+@q&m`JoUu>W$|l*m8W{fIFxUSH$|co^68fE- za#t4*&AviI@`aHZKA@g-wyf?xs}qk2x_Lg_FVfB7(x4iN)zBLDbzn@1#dglg#zdzd;d#SR>VlJfxw<*ETq+FY`pOx;Ck+r` zII>I7F%QnODxMuD7C(H2j2m z$)J`r1>d9c`TA{v7&sVBcnS1-YzEtizks9l2gYBp?;XMsi_Z{9Oo_%{fXFZ5JoI{< zhraSg-;2Ex*?YrYL`2e8POv$+gIsje9#ej^j5ql&MJYZ**=qcSH#tRW^U>!U^7E|n zexAQi8;R^6R#*naJ9@HQzbo3qWXo~o2498xnztNL?XBTxS5KW66EQH}Ya(MrT5K*; z#xqO9cOyT1B$9@@FqU&P5vbXLBWcAQ708SaK^SadMR!Ng@(jr7j+MUP;i`H*0Q<=V z4-8?>Wk%oH-s;i`)9*_55IPtBk4EF$9uY$9PXxj3>$*D>*g@1IjJ+@uFgJd8hl6R6 zh)Vp0p{^n<8vVX4r%4}a@eNSC!x#)-1H~;GUIOic)jM#D{i6iqBYH56w|Le_FUAh=-HOmA`05 zTF>1zN56l1rlF4gjJP28ck!Qa(vS*>^*= zgrfax^t9|1t-@Pr7i|Nzi*F{4`GL+Z!-Rnuj&>Qk!VHrKX4v0lKyfH_?~U9%QWv?_V&ACy18qCRli-_HF; zL>;4_6?p|cE+j8`OkE(gY0vwt#xx~tDm zi8%JbAs74z9QzMyG02W)uzlU18NjHW9P5VwO}hM8qe%$5VH#lz(EUdpynyDDwd?be zCKByyyAMya5bkr>!5Rf8+p%x4zv1vzNt}7tpnz}Uu`H!P>Ji0bAwbBerhKbEXnV~% zgF?q|WFHH4TNidj2At5Yu{wc}SHW=nY0RF6S?;q+O&hofmNlCYI{50j}3WK{7j<2@V)u@+VCS*uBz7dU<4 z_t{Wi(0e>GY65UgWz^-6S;OxSG)1AjT!BCBC&&X3XCsavU05%=Ky)l~kEzTkyG@-f zZ%F>ysHI%T$=!kSR~_<}OOl(GzWvV}dX%Fc$*@sa_ zls+$8YwM#9`HbE^De7FG|D&zY#{6?HR})Wz-^%$~c5Xf!O!@kNcp8fNyC=;_USk)g zGj~IiWU_pkN{i2j>TX=->qvCB2t1XBKX=R)09IK))sL{bMg6y}v-&d@Q{=RQgR%X# z7y(501Qv$9Zkbpm|A9~5zIqyFnJW8gmE|$COpc*<5e(IQ$S11R_zG31?)Lk;zm>!@ zl+%hw-F04c2Lu1OV^IaTzdifKSpCs;<{Aoaw?!O1IdC9=^2J5TAq80<#@5hW%tvTo?)K#+0^t^T)h#Hlgk{(s$|WQG3RJCEm!*h$m6|`zQxn zlDa=?ypdPOM)?cGGg{x;Vi~|ca=ej=EI%M(eV8@S{(i3E=*IjYLLWkZD)eK*%qvD? z*Lzh|J+m1-JI-3Nqec|a*J86DQ*!&bMy^}o7ncdtCu`qgC%%y@SI3rKiBKl$(9<_~@CJjV4~Aq6lU-5Eef~L?7dW&mA@0Ll`bYK8Kq; z!(WP<{ov@O<3`s)O*;pr>WlYLB`yd{6D^AwV@>h57PP>E9Z!JUVl?;sZ^MA|?5`ai zrRNpfU1|6VzIb{AhP4IRv+DooNG-k;?EL>94LifFfQyrm6R~~UT8Hcq_fs%$H!IbV z%aSrAakG-%ou1*2FG#H?-a{kF9CdtM4J5fe05t(NKjVU%%@_UpZQ6 z6R%FVsxu)yi`yhpz$X{wrxDy#XFL|!Zeji;$-MB0>}oFzNWx$@R`T4*q9AU3qUxb% z!v~Eo3DOK0-+z$w;p0;SA2Pmc{{5qj??(q#jqi0dP>t`V7q>A!m^16AX?EkAI^EW; zpG|+Q-2r~>2o*YY3}bV?1Pztc2TA2fjaxn>O;)eY%tZuZw_WlKe3XsoCPz5Yz_dJW zRgAaVs{Fl0y{_<+3jX`^G|B9w`aeo^k>8J?EN?x2H<4N5p=_A%6JflU0-ltW~pIikUl`NbcE#{|Kj< z2jt?Dl0S@yktkp$k-5$hNA)G0)}FOg?;&kI++rv^=S7$rYAX zllf_|3nvAz!Y{i+SpcWh@Lf@;GRj)g6C{;E8jk_PN;%P2?u#v7EK6|cD~QwlCv!B{ zjm72?)L2<+qd$r4p(8r8=Z&bh+n^M7dRUNo-8@z-8toe$g1u*jwgBa%PKhv0vM44+ za1Rhwk(L}}hT*GrUNfF1=QZPRu~a?|jR_>XmwtHoY!s{2u`6f(^=EL-Xz1yj%Rh;!ISzjuc1Ra>IoFyc^HaB2 zrxZ!LSu?s$zYu}84$qpQh*FndH@q62d%vvtm4c>`TBQ!2PyT^}=kqv+C(FT$E4P5> zS!=HmSrC1YNE^=o%QmrFrw_mSlArxQX#%V118#_t5D83ysYoCdG9jhMwFprlcLYN1 zIs(xFfw%_bbn{KTl_Rk3&FWVMAE%;1Ae86{gaw~_$hQEE3JCmUu}mT8HkF#IOMbh5W=7>GlV2wL9A_HmJ!^AXb|xsxpAr5iq3t8_ zzoTqsxj9h`!T9@skW?lX^k02pY6tLlHSi()Z`1W3iT`~@6H(^xUwFpzzh|oWUj=_B zpqwVXUdqkgAfU$InOUD`S>JtTLMNqG=FdcpiRhykGzK?)(00J@+og{F(xf71w@l=I z<7A|j`30*4%P$mvIzXz^fl}2QG5`HoDtjeOLPGvK6qjyEc5lX0h}y%w9nj^DnEsqR z!yvFhst5URJd2#^jE1Sat^eP*T>r}az%PJ8POe^vV{Aqs3q`{SIIcd(?1(51&Vzh6 zPA~uwL!C0SOU>~A@p$(IN6p8G7@J)bINr+sGn(=S2ZET8~m^&U)uI~ zA2#H0;~nkm{3B`9sbN|G;Y4Pg7!+GQ3uY=!k<$og#w^aCs`n}HFVLfQjcD%+1NbSy z!n^kd0+j{N0SQanb?;Ja4(&5=LV5pDkn41&JzDq`87fuiyxB>0i6c*`ORuW&IuLgAuXJ;kBSkrzb2pZ z*mxBA4f5MJkK@dP$(DC8)J#7!QQIGzeZ1BSmwhy6q6coeQ{ZeeD=zz==eGnbO`-52 znDVMVW5P0X9>JdQ-){AcUQV}(%ntbU)^+L_L1sm=WmW7-!?`JsSh+#FW}Y3}g3j`M zu<-%xS*wu7{m*&qn)sg`sGj~O`yt`a`MBr!RPC?1pSAXwwQ#1~$$A!TO8t!K zk%Mws1aPMVOjcfYm>YEOPOMl(XW0L6@!?X#C+r!82IRw!y*_8z`W!M~eWXT)>+{LT z`mEACln+!y7HHHVet{k*$5s|dy0$b36;5n*g@)M*1^u+9xmnoAAy`|Owc)~?!it37 z`$wybtjXwB{|x-I%Rgth=d5{p^2hRtF6oa2?$bjH@S6`=|8v0s6!pY9#ZzkOYzURhjOfxw~@|vwI&5m8F@N)|Yk(V&fhxn)(_idre_yK!htI zv(p1fcU>6B@;fTBDlBBG2t=y{e9pW}iQsg4ye5`@Qme;zjHHCkbEi%D-f^Gi$N;C* za0z7B6qUi$uY6q+h$m~dC7Vt#vDAV_pt$m7s{5jR8F##XvP#wITfM#!Nej>IFvb;5 z-KZAzs2KIA8ZGXk8wJ{%sjMwTG*FMbq}lM#rA-~hR%fruQn`0c4{%NA$Shqsd6{{* zci`Z@OdQIhNe+QN0+%SfhW9o`~X$9h> zShvjxBja{xBAc~XP*)}=XD%u=tfJzm(ZRh(f#c7X!^_$o`P-j@k?&UAMF|MaZGVwm zX)kN?r?1dltjvGL607YI0Y_$Jrw7=_YFk}I9RU#L2E?5KJZc~w9*ZGGzrem~MKaB? z=IswUXAlncQqDqvhMn722ZhZBg=}=x+k%c(P*bg^U8rK-Faoc5aaU&#Jw7u+v6~T) zO8EtlY+D=pq;pK2?JuRij^yOlbulT&|65zjsn+g|)unmZ)l_PDiKhI@Ths16x(t7{9IP#H|r7@auk%ect;1AnX4(wiYYHpENJgzA=_g*%H6bMoTO`MZa^?8)sfpU(@|u zkUdB~8{7b{B~~=-?DP%y)iZ}4OcsC6CN`Fyh*n7^slL zfeNZNvnD^#PZd^BrQ~_FK}sy$PlELU;oSPLTE5T@fVh3WE_FpGx4S`m+};F`LFnTp z2rqd8g1ZB9!gt$1AV>zw$0cjr52~xzaQTTq$aAHJeVc6*+HPu2?Nj)EI6l*>pF6nn zv3r_2FS`kFpdYWgfHNal=zQktT-E$Spz$7kg%wxyTr`f)#~M6zzx& z#ofJUaTHKW4gIuSCJY$$-FtNUe{VTF>MwZ2p?>q9y$X)JQKetbkm)gdOaLZyp8(_2 zeobm0A{zyCg4rHjlWLoJ2|FGKAgtqXTvx<>ybn4tCJ;$kzFPQ+6Hj0FP#~#zkk5rn zOltR_e_UlOWD5V%TSb0-s* za6C58jfNF)72C8a1`~g%Le-#32=D2`9m3hQzIL;E1)ZgDNNAv74d=1GQIoomM^_Cy z($FhNuxyCKs`HmWB-)?p?%@2_H)<0&opA$rtI-DCjV@3xJP)s%G|#g`Vqrh%NNV?2 z4V^Qu6c&;}wrSQ{yS5JK6?i9u34`yAzmv)0bh41)%A8msTd{MSFN*|$jHE!;OB z<4=&icGOHLbtDrx~UP7r-_n63uCcpm&@_h93 zOivuZV!QK9vGl3({feAva`IWEz6k^N?~zbN(f3ukikIVT>MRT)4I^CcxDGbZI|Q;^ zE8LA!_GktNjas;Au<8BWZrtAo1e6R?CFudN{`hg;Sno#A*As=t3UJ)w2x@9bp`Y*N zJ;%7n03;aOZ6NK5_5sB>PNFNg{Tw@E+g)K9Bi-18o0S67Onx?AE_%2GyVb~ zg5zz%@ivib@EjSybQQzc&^`)&o z@nfixwJCL`;+5n;&8sIG?@DW&B>4u~>k9NBH%uwae&{9dZ908;NyzHcdZFPt>1I|xaLLeriWHcglGQfFAc3h$6ttYH`iTpo8dj<6v`mypS<5lg_!b=-e2Q!L1uaV>DuAUs}P&Un;`D!DgLztGPYZc#xxJzq_4xklITSG7hPU*5_Z9eDjmTcZ+3 zG(T`vEOb4W-CsjrFlO5FNX6IMXyW5ScvN_Vg;=lIX0z8e^{L|r`HQu+sb6M4D{y^_ zr6rmNy7oi+96=<$LsZFsMBfw=!(Y_Rgh=V`ZpM=FCO;^6XrfFTE#AnmVQz7U6@J2Z zzxXWri;iH%(mg7ckradCFB^uzg*alC#N5so`DkL^G{RP{Oe5@zo8s8MxoSC2y?;Bl zYIOUrV8T#S69gmTA8#!{9vRH@;9FC58dq0K1I%6v^Fab^DXg~}1$7sh7PM481Z^g=p667&HC#yqBO z5&M~bS<;e25*IE5tW=g(rDwidT{NCU?-)w<(#1=$RQ zKp zzYRGm4p-R+Z3>7o@`mKYHua@Ww3EZ~@y`RlZEd6V%+8qsXTl~lxOapSeCZw_#K5|`W`+MC<1*_~J zLc}EqSd}5n!!T`*G58-WW;;=25G#d9W`}bufTS;}?QCC@Vi&{ewh*xrVd1S-qOEEN z+)u0b)F?H4fewdYn85|ey=!lO4~c=5It?Hbi|PQuzJBh0Y*f#LNQ6tXJ)}?kC@Li9Xkif$CCpSi8cj0M(QJ!c zGaQPJ@@0(|8@zt#WJgV-WJitZ2YI{wJCNv)k=qj7erKgj za65dfg4?BgIQn!@LFBZu;G#YQq_vUzICL{pg+yDVF(8E@6uu-zNv90mLKTf!{l_g? z!)UaOaA<7qJ-S*$EC(o9wq(t`r%aT}T>?D|_d1&O4f|Xfs>wSQf5HDg`c&g+|9=mC zdMNWz=+nBrBhv+aa_^o#U4wogqTO}3p-Pp%NR@mj$t#S4gowxmiS6rRJ=Y0cvS-Dy z!8XrRNaXfKQaQ5=42_OQM0DHKT^je|lvwXYK-s-)&>^ufw14ucU4lJ`LaQurnWyrzfBe1?@(v*&>YYS` z76}OmbzKN`E2%&P46fmXFbNLqt2mh>Y8~&`%hQ2b(sYH+BGyj4L=1BRoWw9M96Cv? zgTYz@ttx_r!hC;3b159xN7=6V|9ISp>raiVbMz3cMcXAEGN!cpLQdY2c?qHOJk%ZP zGB$=7Xha;g#}6aqb;WP1fiCLbmN>3Sj)>#ZQk^5bNf}rB0hyo?j;JDQ)FB}j@fTr8 z#U;rjU0Ci|&tDi&r@|?5`fF~}d|Hsw!`+Cxv#NrOGF0r&zM?gmS(Ir1^RyL(arPA! z#4S`F0D{cjCf1c2(x24H%?r4rCiNrdLx5}|5>;xL!lyKwb7ox^I0WTS$NNub7);#V zG*e%pP%On$`6>S*zz79zgAG5-D0rB3$tbrD9wLiDI~*H_c1c-T#qHJZkQUZH=D0+# zvXjuL4#-|y!*}gL^o(k%>29%{{#1dq(E7?2QE{jv$ioWnQq~x{Z3^G&2z4y|qN+5= z$_#5N9AUknLrRKUz5FnKYZi|{ma_@c6%Ba1C~UwPclWDlITINNMnnyxp2G6*JWO?s zz8(*puI}Q^ma0{CEl{2NA~+e)rQ)1zXQl(zeRaLm(9BTFG#^pGy+<+gQrV?O3voDyVKSN8CGUPOIfJD;^muo;ng--Kf*Mq})>zr==~%JCK~ASNDnNM!Ca zWAg}gf1)O`)uPM?mI1Pib)Y7dEK`R!{I0J_ z4a2MD2*1raDYm}v_0h2_j;Sli@;CD7u!9|?hQ=5zV>m{S_cp^Zi?GN<74C?V5S#fj z6*zONpmIicXg`E$oWDC&p=%E*{GLo@-MT|EU?54Akp%T_cxVl#T2BCV4QI&ZFeT97 zDm&udEC@glG;=eVYm)5zavwm`Onw(zLi?cAe{3e%8a8k=mojiWrZxnYf_;By0xlfK zp@;fTEi^m3r)+(tKQDVBomdz;8fn3~=m9M!T<+5g)9H4F>4wwEdVg2b>DC)U( z_v_u@*ZV)~qY;rD6vfi}P^%cGv8}FwYadJR#`mqSzjT8Z2Lzvw06{ZeM}AqQmdB2k zKA!p#+p~pb(6$gissLigT?PUKr7ESn@3-KV3z>W;7jL;;|9|;L$OxcBHq9pO?H-pq z^z5?kPH6p7L)Xp@SQ-m+$nHroK-4TuK<`Wm9&nsXX5C5`_MpQe7+wqx*>Q15BoW-e zBM`9EDT*MgonVfm0ZzPQHro*7&RG#*(ot(+J?)n1BK>gh`EP96jI~fy3;^{C`?@@8sl&3nf+#ri&(4?&MRy zs?@Tu`Q{LpcZ>-Z6=Aa>TNXCGED_3^Mh&MTZ@x~=6^oV=>73;bkyA2cl(9W5+>}L} z>qX&6qO4JobH3_=K-pDM{PxDbe^BH^poi>vgC=cuRm-5V2z@LWbSee5C4&kSBH+D+ z3_73h-Vex2=Mj6?7BZ;17VCMQ<@Yk^He}B|E3#+u$lJ`uHSMv2oQWl4DvT&XD57B> z^(EU|r~R@@B3(dgso}Lc(@W-*rBRpsv?a%S&kx~6(y05?=RcijK;z81Woh*3IZhg# zPvx5YnLKr_W1gNZVxW*{!Oy|;@&n;VM8wOa&zUqh?7v$kJ#9xv2nWif`-u(R6<4CbtFjl>!(QLw zY*-)LId?<}a0dd$!r<7RQLlqw7u9yZn#^3pX|Ba^$4TfWE!utjhRmNR?W-ipCER{t zGBzfEXFYAe4=k+rc3zarChEj-JM83W5*ih+u;c#&Z8j+UJD8FL$l?;Tnu{phJJwN` znNY{q6=w3eBJs%D=C3^bqu+B`H=VoGXUns9IsH*X2 z+suXhQTn5K2(mNkg7#NZGdeS??L?Lnf#hbSvvc1_)V>*;{hTIy8~#U2^oop_zqod95Z*ypSP^WxiK+f*(O1Lr7k}1d+DVZ5n zM}u{BvfL0rS<}(G1C&j1Io|ZfKXYF)qX$b%+<6ml?3jsB145{AUa{Kp8+Fe(gkE?g zlVI9bYB<zB2-HLtBWcF|uik?6O zQN!k;(A~)n(dv5K#M4N8z z%6>iWV}XbRJAzR!drSKl70kPvi;oH2kfkcF z06q>8ccV@`z}yrJRH~>lEAE=+3{_* zS)Zl~x&U=B|CdDOwASc${Y#1L#X^!;`V(Tq6@Qh#fEfm0O*{3>M`QO;KOev|a>7@_vny@oWjnJf`~&i5mHb=B>?JaPGA~KI!ign*5nA5u zToTvw&X9}0$MKcMMDEa6*w(8jdKb_B#-QcpVBzzFN)7LBk0C5`=_?ouDd5h{z5)rE z>~l`_IoX}TpUG#QJZW^#F+-rL<1{X2co53uIG}wDt2z!<^ZaUqiI`Gq|L_yXjwa`rXU`F5s%Aac_&VBytx8iQEn!my--G4BK_`oBP?$w#dwgsY9=FUu&$t>}V^+lqg7@Q)kyC&vE2x#$ z5Ad67w)p|Fk8AGCT-FL)v}sy8Gv{=O)6QBf2#o-9bn$-;p2T*lg6BNBb!|&{tA~L3 zGy`T`^~EyE0%@ds?wrplriG`yQCl6sP z&`kYmv{pDaehATZ`c!3Z)FDLiS1o4vZ;QKYpr7 z_58X@wqm_>F(5#g23nK3uD5kZM$aoVgWM(94^|u91NPf2BFXktlE~fOs)^6tWdq|I zIL2|c0@w*&j0Z0!jm>`XU-9D69nF;72 zcQ|~3Gpk=Ux0#ey!Q4_CUS#6$LxR37vYed zN^ugc)Nq_H*hv1v=<{GQ_0<*T(`1l&60y*Cq`Qf;a@gB?7J@gA1~@!pt811ss|Y^i zpX=2QJxF_&^o<>*{`o=6gK8z2J#0;lz~l*eNz*fg3T~QE7n#a~!Y<0j(xK*$%Z)lf z#nnmhh|76gPYsWN6OF`mQvHbsnYu|mgR0PKfl|jp5w$R`j&IpVUE=1!> zMa;d-A_x+@>i0Cn^)-z_Zp7)})mo2NJo}q&bwaswz=tod`lz>KXv(1LN%@<$RnLAItIs@{TOE+0- z8DnhYFmH`I-{!e?J?Q%`C_6MeoL63lr^h#CadSy6>&ntBe8_JpDYjlD>H;SMA8x)w5 zDnnp=mh++Sm4R`k2gawsD1gye;|{Elv4B=tS35J4425Bn#~5b>v5#rhl5_|}7N3QRLg@i z1USO%Crlf;Kxlo6=buK;4sD8Ebq1MGQyN*{&88C9z5;~SvecU!=>fqMb<);k#J{~e zyyk>V_hw=9DMM6XvgLS1nWqlO{A)5FmpNneWX<;wbZ-QyaYJIaFDIbgW^qZvF{+%{ zDvfyY(#|DcNKs8l-Eo<;Wwk1T_9d~a=8`*e|JasyxbQi#ak(xg>v?`q_oqj`<^0pd zEV4Vlp3JmN%6u0clC9_V*HVR`ma{gS22F$2&Ry517L{QNEP3ua>r193$eqH4%3rZ0 z>r6WyB`-R2AT%lkRX=ry@qZYeS_4b zhIHmGe+N0$1jp7yF2#vYk(&{3mL*{ryK2b&e!dFkxIBTL!ySF%eEaxyY;N~A zO~}lwr;rw?73wq2h|icI*d2l_0G0j)Sx5IQ-EMTxOM~DbgQo8?vTxG3-nUYd3s>=p z12w#d`XRgdi&S@z*>h5c;Geu|J$TLOersl$6fFlSL2kl!VUpGZhL0?;XSho3{i)xn z9ky9EKD({@a~;|Qt4*zusY%jH?5eXsfCOPGI&+ty?Bx2av7IH@8;q|?Kpuq-7?Aqw zoZy0Veb|GWhD$imG}Lov(rSkk?Cz{V5?B+->oYYf(-z1OWTmkmO5IBp7*cK2dsOh{ zgaoTKCoE~_kYxMAv8y)H6^$ zE5+bjAU}ZKXb%_~BBcS8htOai6!S$Q6kp_5hknKN3;u(BQud)%Wp2BJrGTU8*dN>e zi^UzH>_qB z{km*X@bY0!Y`lP7HFHh`Q$`8mlP#}FTrM@F-W-lRd)_d{WXjdpVbaEQeYXnFTB=F6 zLbLky)0azTj~YcmVr{5c9Hu`^U-iQ9)5A35RD+!4*bqMejN@{{-hlCI8mN+={j%Iv z_>fh{h6#fP1>aCUSBZhhzfh+b(QBQV4G~7v0wanzyw#NX(f-@yM{6afCo^O)ezaB% z@fyMhENZPfMv{jQrOYX30^h3m5n@)B^E!+jl`eoMabI)?#+Rw_kq;Dh++G!#;mcG{ zK*_P83HL3hM!)>OeciL6b=zP=5{6CtTuh--!y`i1^05Xd3k#YgfOauwh?mLS`R^oi zm!W*V6e^#cgnmRV6vv@^uMzKnY9#g!&_2;pUxOxm+tCDNxRJUsX-fLjuiWnI99zQ2 z076ifh{t9wfh%$TR$S>?)~jd9c0H>HC3;GOrtb_7;=Iz?1r3A9@y3$I3TEamvPvub zNb6C}j|@(#`H|LRAU|3HKf=gPXpm>B_+7Mq_>m0VsWmJFGWjM}h1h;q{hI1JVe&}i zbDR3;qN!neafOk#9bTA_jD;7z!-aB#5wRzOTqkuV@&~y*5fjR z$q9DBkG>>{P$dQTMx=~G zH+Y`LGs4rTry8eVYf0ckeC-fW&G?!}s*tZ8>hV)6F%Z8({ubXlf74z~1tE>Ud3>XQ z@i&ie@d$tO_!h75H;-@11inT2+a+3foA>}Z3-T*gmB>7-70_;W9V^4NRkkwk5G70? z&v1_LR)$i;>7juy_jGHcubzE*eCC3+!y=Fh+WKnlE^#~WZsqwGx#vh z8&1#x%tUD>2yw{RRX?OfW;g4FMYW}F@8KAFeeFpN!rQ6_-(fT9&QO2wcq)Ky$EycX;rzV;4 zIW|jv<~0kD$RN9YJNU~H92x3eDO&~=H4}NOjC1A5XM0pE4%wLN3W#2YUid4p2%QiX z+$)4qX)e9#b-i=;u^}hqnl6&cC+vl)OYLinpl+$*1|3m^JON*$r6#VCaZDHMu8HEU zXcocdv5Zx$V->802BY_Xjha|ELtZ?{f-KTOso`W%h5-f^4P%@9*YtLHzeCwjr!-`a zU3EN@w>1VVyS=9eD3%qHIBDL8>6h;@bJ6@#C^dtokUIU+;dhmO>F_(MUpoBWihlW1 z8c5`hH{KhFb!ka7oQYZ&Z#!gp-bqY(!ePknO}0{@>2O&{XG;wm^HqzLUgJ%NtXF!C zOozrAS>(kT4enIiosI8%}?3*b}=jRDgbN|HiE%E;^ow`F)}~MdFSe;89|i z5+}Pv6(wn^k|gPnPtiJ%?I)BPu77?w8nWVvvk?V}V3$MA2y|?NVuiM^m_DvEvo=xt z_t@+^t*C+oEyjCim3bP>R2s6Kc~Y~@TWV-nrEXaSkW00fpgs4xBKuqt0NK5wCq$1_ z^hcB`_Q~?2b}JwE8jriD2^E~aQ3PWwX}kKGIS{wg3v|`yU9FbqeUXoSO?02{t`6Hy zr7NkAkt#2eyX+~OCT_jQh>dC<@}rEQuFM~LW$0XE$-{l}KILRe)%(OcOLX?$lm3VA z?;XsFMd_K{bhG7sK!fd|4fj7iH#~aVNO&I*PG%o)zxI3;3gb;M<^DcyfMhBc301|H z7~Wmoz`OzXONRaEbX9iLg!c{q^(L)5_mJSv!sW1t7y~XJ;cg{v3~rztj#PTFOKo}< z0h=rHzhb*i2S+bYYt^Fj5!Qc$HuNg@H|`f?w|SrQ?*y~62HxjF%j!fxtOR$8N&X*C}D~_ zNN7hwl$(MA6vsMM{*ZT`+Z*%Ut|Q@nt(7~XwsQaRO2(UY0e0x=mbZYSNx2Y=!>|_aCd=$G!j9%9KI8a{uwqb+?qi|9G74Lay9@{09iR!T+pk z@ZwxgQna%S-xHYxM(KbLV|9J&RIT?xXz%6>V`J zE#aAUAMzkH&JItT+LiA^@6-FFx|O{o5XBO-+F7mWo%OH%-7<8A872=PQ4No}3^SBr zTleYRVtMYG=b(i<9kN@$Pp_AJRrl!`K3@T{f581}6DU-sryqJh*{78|Vz2uL@0)t; zX;oJ?30Ld~6D-29PTh%xW!v&Yzh!=mJ1(d#Bqi(M`)qOw(|_Z9Kp@D@T%ZRRpdzGn zAbt`wU6zvAY#rfDW)8&{^c5}?>EjIpyV)xe?binguBrV43!%O~mfqcnNP=5tV zBft8cNlUb!bz^EcTfbe2?B(;5?PT3#)w-;UeAX9LdHY#)sn2=`AL1xm=7%Dg|J7%< z=!NZPO-?nFIj%;smv>q2>ms=)``mKUBr>>$L=^l!%dv`$c!s33;HWG3H+EGE;~}Yo zN0MkV*dPg35KAklo#p`J*dA0E@=wK&2ly2~etq|WI21E*3}>*teK5SznboPM3r|_g zVUe(lvEHxGZ$29~-Lt3z|JEND zUf^^>qW#(KLn>W>-qmme9en1G29GPC0P4km8$4b`h5tA_dH@^%mLClsfB#QghsW!D`apQ> z_2~oQ@qE%hDm;$%b^KT1(cD%no{FQ7uYSYmV*@vGkJV`ovC1+?Bg=jWwH#5VmNgb$~XoyWo%WlkMbv z%V?I%`y-$Cd8M^auM-Wtxk;^YQ-bAQ7Ri0K&wZQAJ((k{4)fW2 zNy7$VfrhH>@t{i(D`YSk(PoPp`^>dqA?Rj-mhn~bO z*V4vX=31=tSWCL8hWGEMn|cV<}U=;SpM z1ksh7Ul3vjg*U%gz!WZqn6=2RVaXmm;crNm?Kia{dlTh1+h$mBGh+uT%|+>PQR$zO zKrTT}3g&;SNLgq5`?2(oEGMonk<6D{=5y;(abo{ku1mL)YqG0y1AVnB^Zc;P+ATs7 zud4D;WzO|jpYgPBS;zo%-%Bv-ZFkj+g;1WgsFh(P+h6GZGFz$_u`JGh5wu4;vtE-n zp#G;dWA6S}il_b@Q_ zaMt^RoKbsbH1l%>KksW+r3NyC+U}*ZY~p{PO45B+Lo9u(^7lKBR2%c3wbKjL3y_edMsVYl>1JQ^#YL&4Zk!aa;`WC#`P9XdL` zbad;^V5j^%=Zrogc6+*MFhB8FJB+&2KxXtv_2fp%q5s5sFQ99MXPUG`w`%2CK|Q#L zf$cdUln^)mPT%@5b||Tp0I`kQ8|p}A&uva-zuC&kHw&cJeH1v{$65tfC#EQ3tRD7BAK^uA+zf8=JjJJ*4))&ebVwmwneq{`k;kA6h6Ni{%8L zI>S=0w^Roe?!zyovDvphnO!^{ujb+Jc)Z&tCdk~}RHt%0>+MMppXUi`pZ~_7$WpMe zBXlb-0~Ar69?;?R3F2Vcb0=2K#;r`Vn~m=9ZbzaPyu94c#Myk-Ol)#udI>3xo`X}+&X z`vd_PG0&&hFaT9@4e!~T^2$}8wZc7j_3>8IeV8Kk!2EC3t4Q*Ep7}3-UsLavL`x*x z7m49`0J)_Y#_D@kkjQBCkUTPo_59<}R>8^e zT*J>p61PHuy(22Jcj+C*s67`t-AaA(LnFkQtGrTi_rKHG_`uHoG;W;*UhDWIV|YkG z=<|(#@_jy>Tu}ki?j|Y%A zLk||N-uiUcJYEH51fjoaKEMCiYP001hfMK684EXuPg=N96<}NcpkKJl$fboFZa_tG z{Q(mUsHK7(3!Kk%g@nGKMfF%(R82UM*~hslrhcGx%-`Th(s&9QwV0 zW)TiFnY!5H^Ni9a2amx6ZTk%SPpP3vL$M9L)Si{p%SnyxH1dJs5%*D?3|m4ZyL*NF zS#Nz_Z+Urhg{yBiAAANPg^?vxLj#cv((EqvtF|`Q}BP z9zACQsl6K2_C4#LXINx^n@AN)4Tm7mZ=Qs%W0;sn^v_efEBB({epQxaC?r2-+%pUfs08 zp4T?j3{p8y8M|W5C*vbR_If3gJ#Npdn_78lU^A&s%i5v$%*{=KrGq<4oWP6N%|xHr zp~NmryrF5bPXxCZkbl7hm~NV3FFwpS?=!8$%}sNBy2Bip0`D5Cuta^l#=qOFHTzi; z%~m?!Z{(Q-)0gp7-`%n^75-hzul83cKlN&sRc@7kx0U661Md_Uu9CaPuZ7mYZ5K=7 z%;(PI6~l$*Imlh>CNLDOS^Rpk$Ld4v*RKyttyR<#&*uqzwUP~vJCX;)$aH|i_&tdi z=>SLYdydxup5wPEEvPq*ob-QDOM@gHR}ZpRTj=&6t1Wkk8B1|;Q)_;YB51)*G_;xv zfx58s&WP)f>i*9rde*#u9Ooq9SpmNq2{>_M$cPzRno-p_|<9_~5>{Obv{wqKft zHPf%60w(w8Bmkkc+Y8f9V;4Vl^a;5UZykH&$?NM+ z_9_&928m2Q|JYNTO}5ZdMHDI27=VK`A#~Mh5B*9!HZ)N$1*@VcnF1REN(eaJU-NDU zI2Bxd|L~gPvD-rJu;Eyx@;RehzdyF=RMXPNHl1uL8hDL<=G$_Hn*5;El8u}Pn0Akt zOZc&X243>X>aDVdUFiigmfx2^$%P&Fz`L^N()ArRsd&(Hx1n@xtoK~g1Uyo+YQ0}m zf+tt`t97|frMc>HgUiJA#a3_F~vZZn&QZ+&4-@L>{4+I6;sb ze18c4NCE-DM_(mT@puC0peRNX>rIv`Qw9JnGMu@soO&O_V=CusP;!^;uvl@i^vfbb zK$Jd+KDeGbdZAvm8kYNXy0%>1(M6v<6y&BVyWNT*TYBw66}g702(3~ahXO8xXd<(6 z^vo;1N*B)-7M_PkQ17QGU3h}J*hbspTma(V=Uh}Js-dIk7-W5t%PU%A zy?d}k#o;z}1LrHf94Z!_kDen5M;R#)XF9#*CGT6;qCBAGAunJ*Xkti=);2h6t# zDv9=Mo6Jf-T%8GyWIbc)&r(bn(P5qjX(+sAeyA!VyP4}-5&(j2J-Q;BH7(^LU-3oO zkeX;egDVpOj8QC?>J(90W!WVt$(P~NKKp}~{aVvAQiPhi+iBUZg&VAhDnMAmeR|!! zu3I`*t_?Sh(5(o=H7mZquYGssjU+STXI580R%^3IvArz+u|775T9YR4sSW8XG0+W3#^_FxwvZ8u>KV;Y4iQ-%Xg+{bI3k zPuWd4C)$`^405})_CmsP+wZU41g>$jOUSnW%vE|D$0^~JZkOXLZGtso79D)Yy@;Ov zZjC2)VDy>4Dt=2W{eWI-*H(t0`{{{4%`Na$qcdy*!F%bX!i8uQo?K7SwNw^g{g7Rm zx9V$o>d7A{w)!Xeh9T7saENAqaUjhmmhaWK(QR5mmuyWPR><#CjWIMDrQevT$2cNy z1!Czt$nS~x8PeL-LycN3acH2`k#2O0dilKc?#nb69^0NaLir&S_EfZ4bKW7<-y#9C zQS{G%o+LmMqY#%Q3rPSpF-l_7H>oQkHraQHO-UW3UBY^L5{-BQ$_w(QIK!tArQD%x z=829;dV_M51Pj zvzCa`iT<}=XO!Ffhe1`{0_chh;=KJax&YT1(QZm)?-7wQxzH_u%lvbn*)0HWSNkW- z?TR{|ut{~ zQnq&eKSH0o&~CRypU3hIaeCYI8JYTx-_Y#}ecqEImF{@@RwZBmGD6T}=>jPAQR(w$ zN1qKCon(yE9P7RFoevU=MR7S7@;iD7on8jypiv`6I|W?gbRTK4-tG;mMf*u2+bbnv zqwUJdD@8^GyEPyx2m(V#aql4Wu&k5|sM|KD=SYK9*HwM{P0M(g{M^S6%j`sQ+%~E6OFpwiaxynlk7bUlLe+eWO3BBQ%tL)<`AtDs zH3|j3z+2NhlA1eIWJL1LI6MjsW3A^Qy_39g~(?=-S@? z76)eO5wxm%4rA$0^Q&-)cy-wsSn%eJGbX&hY3%jtBS zQbPWh(5hT&9#&YXh?i2IS{s4Is=HEe6mDug0C{A3{Wuc%jrE>J`K4*|jpEb>`n9Al zereYO!N~cuH%y`Ug53*Z72&KZa~w`a)LaE8Zp?RzB}V&)blSa_1{BVM4Ny)q%nb2d z$O~0eYhgn+T;io_g}2$4XZVU8djdEn^OfYSkLm=*M0)S9Rg9$K{xY}eMc%P~d+)E8 zcpJ5Q>d0zeo<>sfQ>1xZhA&L?e2GqC7LN5w0)V2(a(HNM_vFHAe#op^16XRuq~4xa zdzVA!7&E}Enr>2?-v33N@%}HX_*r;`@-y#tmPyxSdN%1*E0Mq8WX;3Jn-4#Ym1&tz zwb5z0f%nR^2uS4{B)3iLM|BS_-SdB}2S21IMqbTI-|%w4;Xtrm6OMP(NuP6Z`8Dr? zJ&E9D+j)x@(FLp(||{C9$PLMRp1$?AEitcHL6@oYa)xWW-nZWA(Bta-Iz4jvm-M)@a4axV+`e!i z54NwYuEH4iqR}kpr)%IPT^dhHJwwV*d4SP>p^{CLlwbT1iTj3$5YqgoPjO{d>GLUE zF>2Sa7S|SjVGwE;zD&qp%Ow-4xr-&uU$NA^Owh|T|FVkg`Ee@08=WlvMH_87HSlPs z%N*$=RF1ANYV~uJY!Wkz_uo-9&j%2CeA*2~u(8^#YaBJM=C=_BV9`%fs$8+UDBPdEVtg?nGwLSCEAcB9PA}uhJ$^*lm2J z-K1SC+epHYXvW`8nZ<1BVX=R7h+z0Y9!Df~g5 z<@8K+@_HBPi^9lAK%r$C7;WxJo+Cf-3%KMCE@|Y`J}8oGn+{oJ!{8S)WIS4u55L+} z&s51i97-W%ZdCZ0L4_*Pp-G*ohIwgKsj2$are8B`?J8>y_6aA0=zfQ=PsXI!?BV*v z0U2i=1N*S2|6j9@eI$G%vzf>a0ig4$%2~=j6yIzkX9R_0-?A+fVYcpY*%E+b=|7TA zOB-k)rIzkMr=%roP~}YD-2(7q=~_N)DS56{}X&W|A~JL-|iWMr`|U3?dRtKE(Tl?d^`E5kBx6new%t6zCHU(hi{ML zQlq5;maFmY4Sm=OzMX%q$G6{+0gb-c6`k^};+s*w=$EbGo4E*jeETXm4Zc~D@J*U5 zJ9__he5(_Y_?Y;X%-%B-c)^b|mUhhWmZ^H5vT=bPwXdjW>niw(b+UW!WbPJy4SMd8 z#IRlWF2&~1p1|$E+NhxnmegsF7UbVhDUCf=d!liVLxf)Rcu;B>#8Me8z#y`#RYCc5 z;cm*4TRb3^{;j>FI?Ck#*~bKqj(Bnyn4D+A-=F5DPr3&%;X~Ck-&T^FK3~FMdWTCl zGNh{om~W_4e}wn*OoIC>e5s>==9kXy2MIQZhr4tEbD{pdly3+2pc}(GCleI+o#=!{FCQ*`>=?Hf0%AZ+ve#;MqPy%ND zj?cP7gmN2XKajaT1tjnvf9gNhyN`706ht)t@pAw1ZC7n8AKS_wzrjc1L2@=bmQIOi z_AF^FJm$v}x89d0lCw(Uj!XDQmsTGldpJQIwSEISyOVG7`>LpCNqvIbyPgu;uP1@- zvsq_79c_%V!;Uxz-25$m``X9K;>@Q|d2!}h4Z1Q*(7uah?FLG9YmxTqJmHA51m=0K z_6Z);v*iEb?p?s6tgik4BqT6EV1hCl6(wrWP*D>rN(3Yk0y7$rdZ}1%Se0t4Ekc6y zU^S3L8OEvDYHz1r+S=2bwf0yMuOy-YwBGQBwJM^*jN=7S0Y#nP=ezbhGw&q9%Q-)P z|L6JhJY?Q?@BQw}+H0-7_F8MN4OCn=ZHlUX#S~?Gq?tKS!v_`IoLy^@Q8=D?&q_nV zU-_k>lCtkmPj`mA^2jgFkZnBL4iE?Jmm(79D5g3AjJJz`PBPGG-yryBI9LWW5TGlX z`#yuznJO|e8zN238W|kr`3AtS_d@=%z=^zM^{mP_h$5_lOY14B%Uf;#V+PXTB9p)E z0P=c1C2&K=UiFu5{wteop~kgC`tKW@PW@%2)&9kV`-6y;u$cz@ZY&S@z8TiyW2cp@I!l&p!B*wh0%SY_5Sy_38KBO_t-zR-oK7fe9n`pvHq`BUlw2Fn-XXm z?XCE-|1d-rd+zk%dp>SMZ#Uv_DPcpmo;$)FpiTVx+E0mKCCYz7gMf$K#IH1z9s2b+ zgZzEWhoV9PUKJQ!MSpXS)YE>}nfhbEo_gNlpy#;-E<21l5Ltov~siED+K}>+v~<#|O)#CMqNNug`4ZgmMI#Oe8y$yY<&n`@#oj z@Uc%R4RS0-1APCHOnYKuDU0>%vRcK*&&j4fq14Ao%}IYBXo{r}KKDc^gs1(SmGiIe zyAv#BoKpUil;oeNI4Li|q=XcEHN6{{l{jLVnsPh(#HqJyF?~6)?~$Iq&Cn+Cled@; z?c$R^<`1`yN@=H$M^Zj1aUoTl>d(1i^o_fu&i8bBS|StuRHK!Bl&fM@_d`cy>-JiG z)w|C1FS#65{%bx+?VoKcuGgWdU@DO6OLIjj;J-4fK(xjlwy_}1CYE|t&af)o`j)3J z42Xk8aa8<=g+`Q8&&1R?p&99JUE+o{PFkK}@?YB#jzU*!+R^#dNuCdDil;9RGft@( z1Ij}hjF-yb1;v%F;WfuJ!mS<4@lW4Ej`^oU`17qgzLvHi-XhA@bHLSkP)>>|5HpNV zMk$JuxTNG?P&73pSGn19Cj;PrRNkaobYm?ISf4yiV`F^OYT@sE9LBpXT2teP<18-L z-59;aH(x zI{!6;Ki*3dcU6w_tG^mfBUrYE1k1lVaSdO2)sM!;xv}xhfxd4}^S;?tXq@KrtCQFGz{zX(sUh>zddT<9hd*__`a5Z!Y{rzi5v{igFr{q9 z7um@V4@t4bX^6}Om8|pWN!0!cUqGn(E{S+{R79ZvCXFxk{@(rM2+CkUA@eFY>3#=5(eSB61Fe zNQG7ALv?_>*0L$)M@4Y4y(R3g_=$sDfHzO72rjxn2r3*Ry2(v8Pc0_QWW%({DYAtO z&vV^tD{~^ow2d9i6BnU@zbN+H`HzgWc;jB0ZRgoN!E66_N~=B3!nK_-6U4a5gv6_T zMTdGt7r3Gpedu~MlNGJc_LbgvjT_ihSDFJLk@)o$4(VoE-Cy^WUhb71P8uF@8XJ0l zRc@}+QYc!QFJ2o-F8B~SV+U&{hFElm@r`csJs*dW7AlaZkk8TnzCCU5=FW4B*Xo~0 z1Ne07z2+yAYioFO0t)Pb`yE=%AEHoRR~+Q|guX>$H&*K>{uV&n{<8vE^nAR|gd~_iv1k*zmPJ1*v0l zwY;*}oH>Tu=X>yZB&Kl1d{5y!D9i;sg-t_r-qY1Y@=YXjB9KM2LhIvvTMiOHP=<~Q z0jJtYuL!pC3yx(a#WHsg(525K9a+&9V~`Lrw(S(^h(6DyH&dgpOs_xrOmxc>mp;XtRpXY zg+q8xhRC8r(Xyl@ac*%~FbyL#2(@#u1kE12PFOwAf z)c`-(_7MO|ZsHH{)CyVH9r?kl)p%-cV9KV({vgRl4(hEh^WFmpGdWe-I}rLBN!o$b zJRrOc$TL82c=+*2)L|!49S~mAnSiet2$Cq18sY7b@>{|7*Lh40y?v@8JA{JB6#$QAT?K8}qw5eS7kaimmij&3AUUL=cQ!>4&z% zH!-XpC+neat>cOtvfh5(HX6p*!YjmF4k9R8l89QwJ&gAyjTph5jFgH8sA&dv;#6_PJo|asgmj@zKF$ zqsE5gmvisTpktf+D5>zM;*m`+@O3$dhGG|&<$pej{_6YrJ-;8&?fWYGzM}W<$MpRE z;imld$JqDPy??)*(Rb_rlDzL*J0Y2lM$am6<=ZR>Q)^cT+r~3Tp9jW488Di^g#nUN zWB}6M8UNf%yR|*o*Y?Yi*3Po2wVlmf$tM^k`hCKt*gSWiw9PVIXw5hA(*##%EyC`P zn%zjAJ#OM#cgY47iM|2)Q{&Y3wN1MzV8{^D*0Y&sw~-EA*eV9&=;VGznL(_ZaoTU| zXg=Cd@@o0)%NoVXwLpiiyyur4;_nfO9T|z8LVvXLUo_ZRO|B|YWmg#yg=2-_K5qY= zP4gtQg=16Msh=7QZ+kwx?<3(pT=fU(RQZ}2N;8e9=$Q{fd4l;X;U|rd!cFuMZznpR z_(fQTlniy?a{N&m0}aQ)1vpGu*D~zP*whozudgRlcixj5bY#IB205?(N_Myo_?0d2*s8{k$TCZO?-);8mIAk8BW=4f@O8@NYOcyv?WMp!8_{^#3oe^lN2_oa-Ucs zFBr_6AjbX^4MpljdD6`C1->%Ql(~<`MWM zz4dkxg;4R!@K?>!XBNN;?Ky1YfsQa6sS8XIh8U&@Y+yU;KFRCu-{r53V7-o1}R|1Qd>%q?x)Frt(#goW^XkD(my_0ko}WEECDActK&{ zX`J%)J(1YY4e;%2jR1meUk|{uV^`XsrE&pO%LU2!;YFIIfSy@1ej%X5C#|klff-6f zf7@Zd&L<*;f0=vAxKw!S{gzB)fQ`#9K3pV{B^ocminLd_dvEMPc zcqUSPZCP$Jvu1n&D=v}n2u=M+uchzvO8?u2zo0r(`ubi=U+tB?)s;pJadrQo*V1Qu zrCU_Gb>&Qr+=hfpS?l(*f>%~cGdA|uF0ngs+kR`d_$+kl!to0qLSFKXA12HA3ErPK z{t}JfTzJaEwJ$b5mYhUIZr!cZ6wU{#8RnR{kFEF;TvL*}!emeobw{7}PMK!jfyWAI zm;jFpMO{EdvBmY4j?l!(u74@0TK_+}Fgh;7EKiwr58macxFi3gcZwTMI_9))OWnxH zq{bU7E7GAu=84CA1*^D@JLO4_@0j#>$Pd+?cat8nB?n|3&+|M&29xjXH=5+7hPSN! z{Az31qTi9gzI51L6ig3Y9-x?OrcHS;k+;@`>+E%f=Al{HltF_O-``wW@K2k zl~2FLxcPKsNw`K?0F7h( z&5^cgEPE&INW2sSoLB)jNElsfQS-(3L4jq?VA!YkU?BmM;TYhznG7~01`!ii{zM`5 zDE=die2Bx8eQQC_vab*pR%Mey&^Rt^UfIrG%HH9Xz0Z{mXUbmJOWCMb_8OIKeQ2f- zag6*pjHt&#)Y_Yjy-@t_UXQrD!L{x8-H4mJ4Z9pa^^M=PZRhy18ZmG8IvF4*>gmZjE}6$wK=MTXZW_5s9zRvT34XI`rTi zAqIOSa`HAG!kTSB*xPq>(>h(>+&gD#C%v02@DqejPZl_9j#2pP9cz^Xji`-p(rTW!|79+=zOqks!FiztX59EIO7*!lx-&c&+rdOj#}?r zC+f1IMf44i8qPitY+b5L!hFW9?_sQXt2vaERj^SfBrGA=cB)wkPa7l8)o@|T39sO< zIj@SfPMCLI&dKtfMDZui^Y}NIjx#>1pmyTTk6n7yrB}#ZRq0QA=@+|n^Hf#(y`+Qm zb?AVuO`fDodG0?Vrt0`{*0J-Q#8R)0gH^2cA;SK=*!*(xMzQiZN@yPhoCPR({Z_JC zKf$>2572mO%*E?#gzOeT}-$uG`aTIRcQL9m-;8>R!(Ds!s zjv2>8Olhl``LEoRc6G29`6C4=Bk}vPd^sJu>U<}E>;%a7A)fROD_=l zeM}a}BNPni|B1cw98PC_FqVN~68F`I?bL)b;w%H`nf2vZu-w*{GBZs6{x*+} z+NQySBC+-kYuBl0tfGa!iY`(`@r(%uGtDsAsoy|(`Ygkjwx#MK;+7bA4=bh4G<=?U z4Q*MzmGWz5Tr<03l<&LQ*8Y1&zFn|fAsuCxv=0QRZXYb{_Cb|>fFaU8ke7A052knf zV2pi$<uNFg)*rZl=bO$a!XJJP@dVVOW@z(Fcf@o~{1r6h9z5Bjc)M2Llo& zYBMP#z&d_&hT+YhZDW)~XA>Ehq4C{cXAON`b^kYb+a&T$hR;q^q?qw^7UY6mPL9n$=8EwdJv9&re*O}DkefE zmc@HL%i=H`S}`hK0I_}Dt87 z@j52!(s+;aFEYV}zTZ(r-oY@ca4{BiGv7;n~cc!L%B;+De=|M{7g!>^zHg)E1a z2WY6>EQgOj?uPUwEr+)m?)^Wp9G-D@&T=SRP8Na*4he1orm`l@_mE&M3|&a((tmA8 z=0}1#RMi`)eT(#N0^eDOP?eLa|1lrt@m0{7)+`gDWHvmAp=Fd$Nn!DF{xe@0D~?+a zg{tc<9eP8bz6JF~V&c_b)QWR4)7BdRP9?n?uQ~HzuqECo6VCTe7j1p63Fpf*8qb82 z_8frRb&<4pmfFjiaCYrx!a2_JzZ&CBC9E$JyG|Sr{Y|hf0B zW@}3BxHI0Etrn&D42lu`iPcF@Lf0{7uKB&*x|?grRG=MatC??RSSL?p&9Gs8<}<@` z6bCcxElvV5Tg@tU2tH^sk*7x{YW!??b-tnIqr|yMr-$37PcnuY%1-K~>=>`?Bd)A7 z)KIp(m$Ic^S)CE1UT3JG?3+*r2aSahRK~|Z!u*!Ug%G}yr7wT6`F?2<}y5M0h85bplfS^EG?97Uh8SUtGd^Qik!7e1&1e*QC-pWl}FVd^Iws9dnU$Q{v5hYC((ORqzg{l2C{mdP`` z*ZVmge*gZAg7`(>^3o2sB3+pxpN!NOciO8bAK{=lA(P$LO8+AB`nZ*j`b(p09+Jsk zY}wzm-m?B&J;|UAmL>65seC_$Dow3qqnG za4#oDeexmak&}N`vLbP(F7hh8Nfqv+Pj)CzdK+?*|E-se`tyqZ$eff^0Pf^k{dtW) zlu8}%?^Q&-8t-~Vi+6vl7E@zYZl+i6CcaDjeLkI~z%Q+Uxr%bBG|JC=D z%~$8-zVgO-IFw5L2<*nHZiu?h@pLrZVH^)g}i2~dnn7Zf2m^l8W>7srjA6a2u6>buql$`sf|Z8hJKT#8mnB1IS{q=<_mmv=?VI4_Ev7xUc(Ety1Q zIJqL7Pu%yH2p6E?<$Aa@QhTc}{{B0e@b4~)@#7GlEEd8z3flQaLbc!T4lYtydPOPQ zWo-VfS6J8=sr|m40zBG+GC$)hb*WdX(^VtnSq4CN2U|Xb+~q8@Ac&bw0P;jkO78={hvaTHr>Z%(>im1pn7k`vR%d zFt5tgt~^-y{Q*3vr#dgmS?k5>EA7;Arn-e>Gb7wiVxzkxC33+#w~^df_!hU3bc_E% zcpaS|y;TJwt@jI>+?Rsz!Qs)j6=JH}eJR`r;LGe8k3SOoCd1X3Egruj&^icMJpM}j z?q?XP?WtPobrlI{zazNlT;Wy8tfgQb0zTfUdsS%T*(pEOeR(48{?uT@`;vlexLl+X zFG*WY!|KLh!xoMN2=QTAr=w7bME|LF5g&2*7C)HDJ|WE&Dy%Z1=<8?~1Ej(bMG9Y* z>Sm^jR_F-_ar}I}^O%m_WSNs%Mh9X2!7R;S`qQ2x9jgAKvKG*vQC#fR%iP_(SS6l;L zXKe7UZ{KH?k$25AE{73vFu_K6l9zLj%VCs+jk27hyqw>-97amaD9fqPnq{{5rp3uc z%9h`^QQBvAG{>%W-$bszLtP8>nIp{B!VScsx?S^eY{qB6rC&ihsfUy5>*;KliuZA| zub1B<)$8R?Qbo5Hwd^P&7#B^oyjn<@C?q-$=qau%@`qN(MU`uGrcQO(&+TUiB(GOx zEQ-~snp}+KfhT545MN#esBX4U1svC5Z2r)}hm}$$I>b<vDVNh%6!PA;)aNphkI_azc+F8QulD7W-|&5y6)n2%pv?GR49kNb;uG;gSR zOT->*53*t;hw=w*;!-}@K}r!Rw-?$K0`u_GwexG4cxi_3k0I-U*R|j)6@JqEN^%447~HoU&g&Bls_z6zUBp?cl*A4l{(N3&?j>R+sEVKVv42P3$5UGdZbWm+@#$0 zun^kNOIHUn(baYm5q!%5V5u=L97ddxj z{Ce%%!7DB?{mF@e$k>wu&G!o2oC9!{e=4!m|g8*B^fjEVF6-#VxjdysMyX`pF}PSw*7@} zXK^d}bKdNxCmUoq1~e9LSBdsDQ0)w!?g|J-5JWZA^D`z_BG@Lk2%<=t$Pq7&2oBx_ zjOEFP_|EfBIs=Z?;2psp1;eqBrMRNbJC|)nCeq2H)1@8>wrjf_Hm`UW0p$)az1XG0 zTwMC~UizErUwi?c?k>HZbf7wu#pt@EPV$<&)FSIm3x63*w#`$$I{v8S)|KXszCLwo z4*DkV#Ey_iFf}#{_r&ib_)M-4Ya-#YDgkwRI`n*4oa`ZJvuT(mX%5&Ye8fEt%F=rM z0fHY>S*;5j%bWi!fS)h*gJTsSRsQ`H1jIWHidX1;I+wQt&zoZf&_NpAo{&6{4AKa@ z?C9?5kMsN=5z)RH{sBKuZOt(ay(|57rN5Np%6exrc}Qwh>T9X0)B&l=)PAXo)IP); z-!oO7+Kt#jyQIoegHxrc0eLZmv`)=V9F5zYHjf9qtzDhqm$!e@Zegm7CXKp|>;uIM zS}x$Tx2g-r4j~9d74z(r*YZ5O^VqEB)_1@0Z%ECZb9#?iRI$j7a>#%FWTYJKrwms^)O(#y(BQ zhqp=HoWqD&OM_)a+SLVzfHGWiLdoVg8{-#+u>QJ1+ zR*4^P!bk%%Difm8wGZ)uzC|-0|CSe9+J(1uyhSH^$jpJ8{lV1e`sb_F?n&!T@8BSFSUTndvU+k>D{FUkEu|{f{wlnUWabbXg*3sOr0g^{1pm zdxMkan^uLzAXwF?*cnd8po0}RsaIV4yq;fh)M+iaty;-(Zg#idf4CEA@oTM^^q#@Q zV<;MA8=omSBZpkdW*~O1UYlU`wNMg4YUl16iQ??g6dcW=G{;W)_xjXbO7&m zujHqsHcf;>_W=>=ywxheO3;VfLgz(BcHyucKX~ayGN~MXkWR6ow!ieC?Pi^k}!7aw-HJ{o-*ALV9jX#^i`LhNpBDrM(7%KQFVeGezreLOHeaZ2{l zmog6P(cyK5cInV}I6)&#vj8H^^Ev?r^a0}cI_MB}V~jSPg1qJeM!A-$m;Fmh7AgO4 z((l4<0sbzcX3qxX<0Pk$nlXV*H>}6^(oW5NFh}OEw#pV&hML#0DHo}3x&oxkRHVAu zKFzN*$4{sHc%kkO^bPRFliumqjOga|vA-V(%;rWkaM){VuPmy?HGx)9Yz^9h?pw1Q=6&)1jxR z*A#LH)QQW!gIv`|A~h4BSxGc1Wfx1)y&D&ulP$o=5=ZlD{6FE->e+Wg`OX+aVo#Ov z<}>lhEcd|&o7{rIM*03O!Wmrj8W!4Eac8)Hzm+-cf**MK*S+rL@7pcEuB9to*YfFs zm+V;=T&9{@U!~+Z#S6JjExmrpl#qrz+q$rb8oT;WT^H7v2Q>@PSvp=rsBA4LWFU;1RX~R|BFH=vUH|j!zL1AW8eR9=% z{VvY+#p_+MSN9Z3_#uvbJOy&MQ+^X90dj8BqvjF6JZ40}O5gh5`sVpgi^|a|^tWRI z;FG7ntrLGOvzs@b&|VPAX1AuK_&B!4GYX;7>V~$h!Dvh*rlo<%Fb8%rf@yir|}s@!DV%Yt?MUn<}X)f&cDO8A2oeFxQxa0fx^~}3pTM|LS_;T1(fqHw7Bw-%}^|Z)kfh7;UGM z5dxc?Kq?)XsE%+9Y*O?U>+Hwt=S0+zNUj~CD0;Pjym?N&b>z=1&3OfqirnXoI#bcy zJ2mQE{oVU`^V}6)_Z~zetEH`s$QibNYcng!ATl!DSh!7dOV6nh{1gPFmn_OIF6`bxjfS9TF-S2N4e z2ger_3}NfH3k#z=KQSq~xpn=^tsN^`x9>T37i6d6gPTrDKF2EU^6M9V+5#Bn95@O6 zTWB{H4ECSv?B&CWBMR(;;I*A?oz43sf5TTUq5Wq(*0**&QQ!LMfMDxl-hg4Qp$Pj8 zOmi|Fu!7HMx**Iov*!wTE3_^Kf~`92)G}`Pir|kA*38964cA?Ia99!Om#NjB6d!Pf{X5w03oGi zF>=I8G(YP&-*R^~Rh#DLS7ci-_ccu%gn3289ta0R`om6fN8>?=9w7fDsxEFs z&t4sDABqM+jaEo+gK*-heXI{vO=YPj6YM?e5V?8xO(FBX14HqR5Xfz|;>0Rm6LHqHiddQf1vG_JnHi{}|OP;NFBOvrYn9W{?no_La+ z;J_ZV)a7WY{X_0UP3_$y+atC1AEF3aA*fhW#G_I>EEu!I-x-g`=c8c_sjm%*)A+0E zya9z7Pn{c1v;hlz$w7q84i0JH%LD@V`99ew9on6`Qv(UDrz>%e1rvh<{Y?jKAnDNN zqbc^97yMR2$(Y3G51kxx(aVxUavW`Gn2l2ONV@jDmjvzO1L0Lu$_%>Ey z1BETGcGPTb+0jxLytXS`xEY4s{5mlKBO^N`;ZKOfk55mErdv1lVXf^mcVf+2Vzueg zf%Y31ZnBdnzgf7*r(F1_TQ=e!8V9b8%KU>73F%wetOv+!DaQ< zpSN6p9tsyeQ`u3oc3eyF+6TggZ;)NY`&;AGS!I$yw>pdch1eJuH{Y&nhN^0|=GR|b zRk%WUnY zGd#{v8RAx{LO7N-#}%f4Jw85eT=>bi2v^S)6UfAkVn1fkIh{2a@n;5rVROb7YDCpc z_Fd7JjGwcsZ9XZiOHv+!ANQeRc-|50`C-OM?Jdd;tHd;-$@=uu;hJ?d0{4}OTh)tPYvy!3d_Qg>)gunRArAWQnv(WJRD)IX(Vo{DsHTO zgzFz|T}jak$xypCw5^@LdpP>Yaq)4(ra}Z)-X*tK4uBLIpWn;CLwQib#WYqsdayHL7QaK1NnVi&E-2(AQ?%TN!c5aXu zg{t+D>}PY=bZ#i^|73miVXq^X9F#h_Cf&NBU+0EhRO(5pk3PH*JH2EIoqL|O)GIn~ zl-L_G&WGXP{E;9kM zbI9%R1>u;HRY)R353r6FgIAar$z~5;JDN_Qz-&aZj-q;G-iGL=`qoW=3^5e5AK~yL z9I2l|8B`-3h4lcnzH?*WhW?LH1Yxuh8KJ6ax*Bo$uT4lb$jlkt?yG9<9rc}?`lfbo zs98fVd=<=HK}Kmq|4$pD?@Jb~qKEU2PMwT-m~QkVa~D_o(}w;VDTBZzcv?};m9i}R zM~qnV;U#{3hT09y!AR|+!7I{?v}IhNplKIbg{IbSC$uA=OP%X1 zD;VPc4E|R=xg~h!Gkkz(92}aWz?&q#NCE!O;D6OC6nK?pHt^iJC3t!l@BGeqa7*yi zl95y@O5QU=$y?CzNt1E@Xk+d?v$D`1<*9`mYdV~MKYn6iaM{4NHSnQ&!jBxKI$5|4tYOKd$8GQP5aA3> zA$yj?E9=^}&M#;19$~k4l5752ZaiC>A{3)=r1im~Rz|c9YC`3(eoj4=HPu5X#g*hi zN$V%j_N4v~kh^)#QOcccEhraCOpUKui+(d(0sA&cDAb^}^!?nIbGsm*{vSo3bscIx zJT*ns_de7E@fZvk`?GFzO$YhOrLMqz(-f+Gw|NK}YcA5*5p16#u2WRgF)JMW{_0u5 zZx8yfXAI8=-Dx`2A%mm;}M}a_!_lZ zp1P*4U^)t$Rfta?^L1?8LiA15=DTuT$EnCfdG>+UH)l9WC|EY7LU&D}_S2teaV5SI zPnEj0EWmiTwvm957&Fpn0#B1;qoJLzAN0Cj~aw1rn12>n8;gM9k?cXp|gKD4qd) z>1)6s#Df!W<0VOMz>)Nz9R(%@wH-UAD$MOkEZnR~k1Mk}{e;|_Z!7F+t7=&gU|Bqh zYWY4~WAHZ#NX{zpl3hl*>d)u-v4ZaXh?mUqn$JzL&k005vi|BWCj@wWNvhHB7PhSk zwqqksw=C#S+p_Sg?Zfz`my>B}QjeA>kQwo|r+SRoSAQGg>`>}fH^LgbM$vdsZWMtY zb;nC?@v8jNqqs#hT3XX#BWXXv#x#I2-Rq6%>$x$_PFL=H7We<$F)2b%-k9cdLAA!G znK`^i-SLuj-eI3FJ*IW6xzgfg2XT0A5P$jfGX`;{*P;&?JCOQ)Y)a4{(=+j5(=sBfJ!i7(!Ux7<~%3xBHYC4kh zB-eWHhx71^GPnu5C%;J< z#DN)_f3^-Fw~J-pgKlgg92?j`!X z<~Eg`+r_8<52lt)SEf5(XlmDP^+Cp)+FKv?qvOt|Hm<3SZtvtetqyY{%XGIC;I9B)kn>%p4_$zVG=*w!Rr|nJ}Pvza>-p512Awz?4Aq?k$%i z!w*?9W#E7*r30o68Zc$>fGNSI?=!uZF-h9Qb-Wk6Y|uA2-ZU$CAsf2OrFx2&%>Td# zNt2f2CBxSEA?XsOaL5vgB}LbVy>Rcv2O^obJ{Vq!Hd#M8{lIf<)*{@-B!zeEtg}mkhkMW8Pt|`@x{Xi6vEkv^ zg0ggI)YoW|r~9?R@!U|>Gl|;q$&=w0kRlT6yE(k@eA^&3GmxY2pPnh~dU0lY#4YxX zcEM-*rg+xU?(N;nBz13Zw!V$ct&&nGNM?n>DIJbW@ht ztlep>Pplc*s0FNrQ ztzGAnB>Z1~?$2+V{rt6MLo)9NzcQlk_H%E3JM;ehx32r{Hy1sBp!Y6f!wt0#q^qk- zuNQnV#x=%{1Y^0EV}v&BO}nytmz$8OC77Mv1R;48eo`ULK_-uq{h6@zh({BT$$p=8XNYKt7lR>}t;-Mq=G;BXpbTFQ5#@Bm-om+!zGGXCHB z{Pnu-{k8Hx*gIEV-~WMLdf$8S63Gic1kYaJwVNHlo7|Fhs-n3RC>*EJs%VU(VwiE?aF2(1-;nu}{XQU~Z{w&~x>(BR-Ocv_$dYwOF2 zAq>G?T|cA``kvMYt4~{*d53E!Y97efB^!PJ{{cRUQ@;>=-o?t9fk$uf8PeGcd_W)M zTZkxF);Cx-4e#G?0(-Ps!I6#LEQI5u`)+0>7pZB&ShWs-K$w8=%B5fI`vbatzft_k zzMn196bu=9{HFkhJO$lOMM@WPC!GAc0+jE^fhQI1C>zDjhhuOkw{;n$tl<;!% zEBO19+tD;!-^;g+)!(FqEdNT6`1@XB4yV_j(L?>L3iE6OY(cdx1ZVz zvS^!vv$-TWlFc8BpZnei-_Hl_?)0n|(Eb8_r$F0se|LneV}5(IzlQBbw*8jN1AUqc zaTi(@NEX0>ByW&b(0t6SS+nq9DjuOx%7>_Rc>?LQuz6RWHuF>f5MzD1>dFgKyM_fBbFTK=l|QovCEl*v@mBj^SQNYpp%bAjM-CD?z;^hcxwK|bC5^r zS9wv>j3pEIK!yJe5FCjhaXPx-CB>EF`dm`X%_w7K6-2^3TJxMHm<6-#;pred`Z*n9 zdvXsVrj^q_&u@oigEh5&2%5a3PYyLX62QkMmKgy<#EyWuXJY}$J_^1K{LVu&<pPpm+_TZNuaV#*(4H^H{@+?3Er}E@oY{jzp z-U~fE@6R`UYnf0qx35h-bB!C>S&SbhH?bS*!>8U@UpjOdM|2_pAcs~S;+&_9920yS znL_0f&+s5nK6-aPiY(2a&rjd$KA+~F8#^9y2r#BPqYr1_We)^<96P1FsUDNswd2JS z>sV#NWs&GK?n@XWPoM+Bu^D)Jq|<~W!ZZfD58&i4#<4WMCy+~7WbEYf=7%G(d6v1i zh$iFS?oh&vg6R=g?Uun2XC-8iR3eHT;0yNQ9M<%Z0cw{*`O^4DU)xDsCeWx3e)gdSLR&K6D0(mZN|UxhU{l;)Ci_dU#i zw{ZL$OxP)`ksUPk!vOpg|E$c?yNmXB86c-e9L8YeeCF1NUhwsY@A~jL3*QAC1`vF+ z!vemWhV}yA9_zs`{q;=`#~@|hIfwD|Vt(kIM${jPkT{RKGBG}PI@=G!ozKTtz@#2| zHn6wA`X~(qzK$gWp)RM5z+1D5gm2vil*p7uV_rfU4S6ymZ`Vm^Ch<=lPNfl6;&hj& zx+ph8Ni$v2=u`DELKN3E{+Cwdfg&{6?*-`kMOzo&nNM3bA6iRh)5z(>%v6m|X?BoW zMnNIr9hpqY>1a<0J*c-v76|VB>N}Q1yL504b zsigD05&T>qGlIHw=rtIHi<^Srwn~bAM)J31-A4dl2H5eE;`>|+xG&OKEoON@{~5^X zM&NoaxbO00p^aE@|8!$7aIf)t{dsVIMISr3A7Z`Ek?*ENR^1F$4#AUmtK ze*My$s?Y0JB-gK>!C12RFcN4AAI`p`J2XYF4xT43_rnu;Dj%McbDcIU5Ii?Lo`dJD zulEAaSG+m;ynbJ!j~zT;g7)+2%j;jjn;SRZGAZTF_kSUBb)WCwqUp-Ob#QO}tN()i zd-t_$|Bl{S{|4RTho6y?p9%EM^-msS@sfspU3nqn#i}3D$YTOG-|Gr|9`H`eb?!HC zJ3sJ@-cR<#$LI&Bl$`JX+!I*dSm@>jntzz}`?kvj@>HC`woQPU1<(nDazUO_3XheW z-)qW=_Kif(MA)2HmO30NG<88VvG9`u)YNki&QlG%j%wghR09`Q4!T>kpSlEnTixPO z)sfc8WreAEM0V|=D8M@AQxxQC7<_kkMFAyqiUQwfC<=0)1@A64tU;3@VkmxtBjz2R zOnb)4oX&Ql))9I74nxMzCI6aa9WZXQ-yFrWb|n+<uKDZ>7fdzo_r_ZuQOWy*{lk6$(Ba#g4!R$@DU1 ziT25+awu~unM$c-%7P<{EAurnmwy1@s){Q)-f9Ym3MpjlRr;9U+|~>KV!fV_IFij* zjX7Ykf9tjV5708B68fC>(=uA@wEca1Yv1H$PXRB5TO-p(0FA2fs)?RM4~YjNHbi_I z6-l6pZxh}x9N#;27-AX}li7`>(@*(dQSGjCvh;eR=kD$On`!9L-ko%!M|;NrB-&f> zziaQp-rAeeTYKN$WbF<7!tHTtM{s!qScpP5h+Gi@{(P&ZJtGe~eeOx#miRp&-xxc( zF*Yj@`~Gy(h`umzL_zGh=_p0_YF!hE9yeWqO`3zuM_?D#xJp6c3tHC{lLZqp!qn=6 z!1hu)R5C#N(y@)va{|%t@u_yeCg7iuIS(PcmVFEf3H#Wia6~_W`Zm_-5$98x%t+p5 zf}IB2?-3`Env-vHbDbVB#>(f_-yG;xe?}jG(Pt}>D1%Hs(OuTaqfX?VRes!UA7bme`aXAj7!W%hx9#GZc$C1df`oqH3L;wHY>pZ6n+>N)a6D#sT-(U54lBKZMNE2Nt-7R~(;jK+rl zeJYV2B37~ynIRILvNy*|9^iK;9vqX_>DFS+BrD7UMdGOLMF0 zI9E(#zT(3(#a~i^C}RGgp)Y9>4+pyH%F32BRvxi9ynFD@#>&HIMZ+O^!$-qIEV;3A zH!r=ha;Rl+{(y-rFXE*PKY=}zJ#-dNd-K6=xF8G{j#i{XHEZ#4CCrup1aO0ijs+Ij zv^=By5pXMPPrmb=`qO|kw@bGP=p-q)3|wN8!>wBi8w)hH|)I2n+ zsu`eptx61fRp43|j>W8w_BFx9(}j}DsY?GY57%~b_|>p9((LlxW~9P4R1# zgoW#;nq8LLfTPMxE`xwbtz+I^&qk?M3xe%NXC$n$fvVwf-1R8_QvpIJ4`B;(n{|*W zYO1hq+nBS1Dg~|rLgI)G>GXSQ5gEu%4y_9giOna64zyZ@U_W&gvgyu@y!mX^_*p%G zW$W-xrUzpj;M5>JC@Oow94mLEY;fYV#C#ImL@uBA`L5AU= zTB<*b&A`NKFcv1!OK=jy*ARJH?I%E`s>p}38g8G0(!Q=5uE_F1z|e)lrB**U9BW;tvQ}3tre{;- z(1{_Lanbo6hR{3ya zBD7ryA^h+<61!cMB|ae#S-1MZit@w<3AZPI^!ND);p{zjUL_A14Ein0Jxt(45gmui zX$~DGJW|*V6D;0fJai$eYdUl*xqeJI08~nJw*G&P36trUZ^j99nK#?PDi0aoSp%c6 znP(NB%+aw(bZ}N}=@hVu!?X)ijs81j-K<%QzNVmHb2#|- zZ&Y#0Q#r9=l}^LEhJ#anMxur@#w+%|niaRF8!1aK$HiU9nUAoJvsrgo<3Qt_yqvK(n>e_ z#^B$7Sk-)eig0_|37VHssTjan6TUKxzEYl+2)tp5Pt(z}T=Q3_Qkh|Ko7yb^Ez3?o z`@(|eS`C+gtAa)|{x*6scr*>~s>dd?$4;RYj@1%pU#Hb*Jd05*PMZ=(zW@#{e6WL_ zIdKXWUGsOk5f8OKQ(18T5o9Fx_yr0P2D>?N7D@>_`*y-DL=r!fOxACF{ZnsnLce`Y zUGTcD#8}Ft{zW}EQ-*r}vX**wS3OVuoO(JK=xrov(B+Z^Dm1rxsN$CoN`CbR2L>cu zWObJ)0O5>^URNd7sn@*HFJ8^b@v6$3^g`kvEz$N7ZFV;YADr^4RDs+}Y`=%~`C{^**Wt;G2*G2=7aR@tILM3h?0uge?#k!pci&P<1b#Ul!mubMX`k$b>C z0=OZq+H-m0mvF_@p1g85Lnf{LH4R}?;;-;&F@f`La!kP4i)2qnPcW069A~pkGMcW1 z>`c*?Tpp(D1S6UlDeIye)1hVZq(-`i=-KutTmllR`58-7^swjx97h0=S_5ILO1cf& zPlrCn!&dgv=(DLl(1*@W)#(f@sJZuMD8*{p-4-GojbaBEGt>wn6x~6iNW6h1y5t=d zjF0c&hy4TlB_Fp6JW;&FB+tzHg$2060 z%**h}bm)f+&Jrukahg%GAE_L4%@ipEz#|3V43t((C)*p!DxK6|9=;o1WpTx{2V+q5Za$L3Z0=G% zzk)Ok9?ukN8d6v7O;=qVe0FBeZ2@rI^k*ZGhaZPPbQ~mc+qHZ)&|sG;wNa!>{LL?? zdB|_%I&}_*705#fp%di+HB%?7D5K^dspja0`wvyEAAw@F?g-z;gLf%Tjv~5kO3W1U z35OC}CD!v)mna2Ug^*8QZ=8SWiP)Qrn}x5euhQ6$7BeFpi4N`0ac-Sh?LJ_>{5;+7 zkT6&;vBk#I_dZQRWAE+=I{I#Q;-GmZ;c*I?QDWIakNWKlUes+n*l;Zo@Rf z`2_n=zzmNC;R9E#A^hD2o@4c%zB%Kt0)a`Sy{CYcYK8uIJM|5sCE;sd(#&H(qz0mt zsgNGD(=NE*-eh$9hKCizjYgaB7kSE?eqtS{p%}8@Cc)TN2HPf+5L~pDzq+r}0+*Za zn(xpk5b+@$YL^SK8do%zNc5qk@GBka%L$lRLF@MYg6-l!_4iuiv4fu_9irT16!NOm zzbdXwC0`vE2Q{2Suw8+ZX$qRMcpZDvRBCWegZu{6rQxde9W>&4g-am`?JLx3`k5H1 zuSBB%rYB9;rTQ7{bn+LL=f$UB_f+3CIZ%LZ;K2ID(*{agFk)7HbXx!V=;TtwX?n&8 zUuZfr(;rjzyvWq1j;p^flRG3YcLlkeU)O0F(yT^HONSZ&g5Ratz5CJQ>sG?2Wcaogz(>H#KdsRo zZ2|eIdkw6{wEDR6j`0T)qyFXStLax6`dawrZ2}2y#Bq1`3;R623Aehpf=u9CZ)pRY zVBv1@GcF!G905kM3-miZ9qJiDR!mV`5fyH>sU@Ws7iqpVu_|W@Cwd+N=siv&n3hR(GK^5uH8DQvgO>U}Anob^| zq&}7~!|S1|E7Qrm%4b@0#+Majg=m11o;=pd5Gq_ihv;!!xx!m;2<~suK9bcJJ}BUd z=@`eml}(RW!`5H8m;bmqJ-mhumzG0#NGCrqXZ9w-y{%8|=G;G`p$=7GtN8A<&L z4aca43m*Q(y(^4a%NZ^5wsMQ3?DkTM3GdJ%N*%_ZDnY88dz0Q(l@D6TZL#%}w8Zay zl$J29=hp};D9$p&V);8UL-_GDxP(-_p~E!s(Ul$vb+ClD?qHd|nC5c5F40#OJ2%)i zg&Zz2vim6L;8AoJ1>Rdkb8=BiW~i~5Vt8SjulV@C!RgYW59vpJS8=5x6c7R;=AAQW zjDCv0GCs<}zHnjF*_zjxB1tV*)7cpHMMUj+Y?*5jj71726%HJ}%mE@#Rmo)l2`q<6cP=Jvdo&)euPSdd3=5&w~Dd3i0eUP~K-@?F6 ziJPBgA+~#1csbAn+Lse&{mhtx&%@3i&zJN1VM6)E_ukG-8Ae=g$D>YH0GQEFDUoj1 ziMUMCVcrN8blK#)v|izd3GlbUydMf)(-Ca>0RUXQGTixU9}DS<#E-;SzJiV+Fhhhceh%hh{8JFx$N!u;BaWv*_YB5z9_-`{B)n#5 zR#CA0;RABj<>vf&zVxpmY2h!%*-iYWHf8{xv{YKm;=zjNK@QNQF7f-P-P4#v%v&%f zUMt*Ks`yy3Y31RArV-cl!#?4=|MF+|FC6?EM$O%IW=gancP13l{Hi>DXVc1YlZtz|weK}g z<7ylorwA_k9spISuYI_N#gj|eVc~D^T*^p>fKUo|k?Zu0FmfZMeMyc)`xz$IzSKM= zTcvir$Hyy=Am&(OaN?_?n>HO?@U>v_V6$r>*mjjNqy45vzZ2j(omjs}{LDf^OjVNz zhRc9Y5ER7*h0O4IIE(pJv@+9f(sKWBthh3XLJa}*7XC^CYs|848_WRLRMTun*6b;e z%u*-XsBFbqBd2x=gH7lla>@HKSQs4e!7)1+@7Na(a8#aQ+N&Dsoy~mbpcKxuDp#Jo7H<@NtbFlM2_kw~!eDcQah$6bOH6^Z;`Uik=BW*B*f*gib^2-~lCG3(w2g z^BJ#i_&RUJShoA}Yaas^wa+!}4HPzqqt6;Fx&UwwSa|TZ@*m}w|Ji4hf46x*F>$Yn z=eY2gYg*Ewb9(v2_%IGh#~EMu<1(I97oanxcFQyTue-&kH}53gL}%00$Cd|NwlSz>7Kn7HzhDb~SBWQ=@lXzr zR>CkP6!TEYZ>b2Od4Jvl^}GgnDAhx$O0uKnkJ~s6S79+!~2YXEv5f?Sd zMFzcN|LGXwE?0>mI`=v{ELRkh1Y+!(Ydh!m4aZLmq>gV{P*LcPp~-(<{!n*2OcAO) z0jfMvgHq#dxo&D&i8OE`;vT}k&4q|JIuRLqqKSWKaJadzwrkF}aIX&c!QpqBHs|?! za`^t4D~YSdas#HdZtvf;Q23TzECd9Ny~noR=HwpR>%49BEqzDc`N^>4W1QsC50nUjG7lDYgZ5#n`^o%qFoC&+Nb@WC4}R9 zk^XEn>7eTuim;|{w(KZux`0b~n!hh-RuiAQY+SJUB2wlUVzXoK<;(;e+0IO$?8$S( z;9Z>yNDdl1wQyVGSjZ;0=suJv$z4UdgvS^cZ2C>AH1Vh3is`<^+fQZRs0woV&q!t@ znF3n=WoW(}#5F++sep~il9DTarscRntMT{rNZ?t7)RN=9=e*VRsLa>q8Y*Fc>Dl>W zJTO!IJ$m65-z~_4S#^Wnf;`Auko!BInBd~Z%D!5RNpFN~8!P)qODlz9MX}OK zl7=V~6?9`|h+6tmoS6lk*dA+(F{Y`;j?_1fh#g$W1nv=S=pRJaz4xqW!yxj9FK)oZpxp=_1Kwe{GqibmW0_>7 z_o*rc{y@AJgH5de+68)g>>rSc$QB>}Gb_7VWnc8q%rq;2G@jaBBDqk4BZ5z8dxG|4 zxwlOzOML$^XD9rxE5&Ps|2ck({H0*KInL8q_#wm@fcebBrNNYOFD1s|cY}e8LvGDt zK#jHA=j}rqC@HznC-Le1x*0KRhEM*IF?3Dbqj1T@@^OVt-xR^(Hdf##wdWwU=R8#m z#)E%m7Py1uJ=FO|MYMC_DHx4s~m2f0>Em&U6vEG_B_tQv0 z>qq^Y*mP~E2={+D+<%LyX*%f*Q#M$gbmBx-tOdMh-Jz+tfSLrH7FCkRud2A5hdAsq z9YWWrIvQg~G{(M-VDet$$XA0`{F4v3$_gI4xpCzBaP2yAfU>!x8>6pt$69bvjR?=2 zq91}&Cy)!p;{r__3;L0}=bfOn=}`5{%khS@HsL)+w>-QFSX86oRM zo{^}q4#iU>dNQ)+MQozRRiQ{Knu9{-M4YOG*?8@I@)BR_v&gomrxv~+DST6lU!bvY zlP-Vb0D7uKTa12P{or-Pz>Qu6Lw&O`x}kC87D7};f>RJ=o^34LI_H!~?fY}iXoPW( zd`8`FEZi234+HBTONagd&AQ#PZn}Q=UXTI43NhF=kKYO`FDyp_EbVkt_i}D&(7mjlemPU47dE!{J>mdNydXXOSA2=H4c)rc2 zjCG*J=up(B8=)2qiv|2D4d zl8G?Y#`yRLk-eoP3fx`n3fHHZ@zYt_h~3Z1f{vVgmu*HAh(r5KDQ41DPDYg{b> zbBMDKF0m6SqhGtq`g1Ck(enXb&x@_+l(U|%1W}3;kNu}bdFsO;Zg(FQTMrs5`*bU< zNcV!3yeJl5O|Rpl?^tTh?7|m!_j3awgum5JpC5rpkp~bxDzv|2>yDi1ZSYn=ZSp%J z0)U-)_GG>C#7muyBOkCR%YV)Pa6ZyY1`~!ECQK71c#%8^=#rj3CfR^w6I?c>(A|sJ z+QIdB+slGiis=BZ8(RU_ImL^@g-@i{qZ@tg>Y{?XI3r$=lpAd9l4AH3{&P|?uq6Ec z$C?xr&3zZ`r<_t2a%si|4ETc#qw^i9eYw{=+&LGqEPWN@iI^$F%B% za~2zu&T&QwbHO2mgP=8-@kw^#u~of^zRZP@>Clbq^i1O9=PC>MYBv_V!Kw%UdRQkF zm+>1|5eEET$0lVuCI=MRK=M6Nr1vJ|gDM-mxM8^JDrLj4H&q3q4fu%th>dnbmBz0D z;4#ur-PKT6pn_~+8X97F)il)edEdniQ-~egbTlTr2J?2gY_5L}?)jHNsOc2M8eD*e zY0ch+OBXrzU6uQ!4k`F~29Nzy5+l+ntJ_;hCmB16$uboBOB9c?{TXLER1Z|xuSf%w z+E32T{>l6Y&5}~3%o0Cf{?jr%_EV8K_W|r{8GoxWi3V?>{Nz838|Czw@}IiM;CSa=PoV0 z6a9Q@NW@w&`rf~3dR8SaDg6Sap&t)dCRL6SvapI9woIzrCz~<{ShaC90?dm8S_pkRC&C<5>-wm3#yEK7MY#o zx|t!f*O};@klAm^N{3Dte}K%YePlMq+cH3A-(hvXzmoprrzfc9lUZ)gr_yYW%%<~! z$A1pD43EsJ6XWmlky&-(rTg5X|FcVc@@PJNJ;DtCU#73HkG}Hu*I`|9+xjEIqPJhf z5*CU6lTEwypz#KFjST^5Ive8`vEN2bBMGNkf9hI(R9(9$KJg zb(lCf4zzhHCbG%}rz(c;E}s>Y=HmC8ffA0s9+ae;6O^2-z4k@tNyd#9k&*w-0N5MY z18?OZ@MkJ8D~&sTfr6--r7b0D|WP|hzt z#V-qqR9wVGv9%7uJlqN$twQglXd$a~JFSZb*kMiN*Usq(Y-189-RU%Mqnh#;H0j@@ zj;IUA_6fJ@Mu7I10TV=@3(`+Cqz`Mki`oH5U3Wu`6^Z{&*aTLL>(fjix~ih4GrA^L zqv-C}Ck3z?EBBRNh^77{sW;L5nEFR)yq;8v0lF0I;^e7p9F3LOypKnTG=*q{eL*4_ zC+pniH8B#Uo@pQJek;Hn3qZ0CGS!I%%iMTRoU4H?_2L7decJn7u|i3Ui)~>rJSZvF zvSO><$>QT$?Q|f`zuFC1YxEdwTVR}CtKEaF8i8W?Icck4DMAX*w%#^R{9}R zJXo_4n)OyHI&qI`)osYQ&OG;+o=LpyQIq3r6%u*5bx8yRy~qSKl3!bx4mJr7f;m(& zpWkKq+nEly!<+KXpeI^*JjV`#LwXBSS6zh@8z&y9)>w5Wj-ZjU=)`@yCRVxSX5yjB zf(cAKn5;l_;z%tw;}Frz{qC~aeo$?E!UoT+ha4J>miz(fI5ni^1q7*BdG?E=LD%!h zNr&D6T_v_xNY@8WXH*oXhpuSJE;T;@KAEMa%p^Kbe$!Iw!TklA&Z0p@;{7{(3rj_! z9ds8JjK4S^-E;Bh!1lVCKN_ z=o=w&5gSS^&L^frk27Wtu9)Ukr#x6-4yE-K1S`u3Unf0oGs2x`WXRARE17Y*&J9n3 z`vs7IMNUhq;xyv+ae-TQrK285%(-}C%=9y0H{-hJO|ueJ8t zYpwn7npZdU<<7$9U}Us^Fj6HNu&JMvm~fc$j25$4#=pS?AL8es2RG^uqw9^#J8LWP)4v6X_{uC@YP_%$}y$S~H_^n9+-wQ#s5K z6pzi&L1x@I%pAu0w#+ZjYCnJ6zG0C%Z?4J=B#(Cgx(lpTqf_lXrHAN~rayH;Cm#&e zJ((xz2(SF15Ss+)ojK()=lPbNTYoEDIs5bf{1X0LQjR0_ElJBo~^%)K{?A4D%4!i_G z4R!R-X_lcv)!pe&*zw`PAF=DRW61U5vvlE_z*v&iz|2fxcHD^eZ?1lI8#C_}VWz&s${cbYT z6XtuIS=p^Jw&HgVI^{Ix!$}ln2iEcH`>81HxmAdcGygF%ver9lX z0T2_Le~n>c=DfxP>o_0vn=5n8{p=aolR!MAMrgYlRN*pavw!&z3x*5drVP?ICq{Gm z*=>^Z8t6k)&p9DsUw!npl0f7*F{?^-xm>Le$I~2nPThyT zIAbBjA+jCjS?S@(Hy}@r!i|MKAza)=q z!f2E5idxvDL1J$a-)K_lKF9Rwnn7!vaA$fL!!JvVRB$0y9gfp>gO(zgBqIfL`!75s zO(QtDfl0}tE4G2{bM}0FtsIVw5SS@_sE6?p<9r{O^dcp}|D0D?fYaAt9{-Pd+=tV4 z_!<6710u%ESw~$+MT#-&H=n^w^^-?Uaxv!fekt5Gj9C^72RcLaS9@;#`xL?JmALaE z9&<)4gg3Kmgg3kJ=DvZ9N2=qm)?LK-%2OZx zk%7;*9Qaq%1j78=_!YOi;rm(vU%>ZDW8Vk1|A*=EW5RYc3g+MKZsL>-=oe0m*t3cH zkJVOO!}wyjCOxN!YZ$YbOB8glc1+ePT^K4CWhqf!a7T7K3+4LI6zJj3Q}8G9xAd6o z`2=A$33tza#h4^PVn|6P6p(uQc7rqRZwW%SHpwx4Z}OHu6u-gb*kFakYl{_&BU!At z(LC-m&2#(=U8bfl!-|Q1a>Id4Y?rZ1_rZ$)D?64i7uSq@Rp!Z8RwBxGt702v_CSN+ z2K%DP09v{)ntZfD5RX8Xq_!-#STXCW96j{+uPs7_I48SCwsuMiosx4A^1f}PY6NPz z|BMvjNshTu-G{&$sk$70QRxCR5+zCx5~u*V6r$f6Y#kj{i^ajE&G9ngBfI*4XHT4$s&KxHUE^ zkN^KBQ_t$6N&Cyx7XaK>rnYl_fOtEV^pXkAlYoaCNS*|IH`_QX0msaSE-L|7ASj3u zTziF?`>X<7x{LCh0S4Dh7*_i_@hi++8e7GK#b?`&aA5sz4-}s*uwPY%{~n~itB6th z<@H_vzt;ED@9o<)Q(vBba=}|NGc{&JABfRoXVHq5C3&xLHw!0c4kdK@KR6;xpOVM2 z(F?K;*yU)CiTTnr9pYSCK>d;7H>D|5zUwU(~W+oEa( z%`hHy&VzHuIx8m<+Cl;^Smy;m2v=N>Lhx7}6SX*%q-KA09$VX?{bo{@i!67pk(4A7 zmMDgM@{x+?L3d;a-sGaFH>c#zij?`it74D&{gt`-(iu9PHeW=Wn`v{Skq=tjgcZx7 z-@(?~34;)H+N4W#YkDJB11xSut&N7~BPrd$iz#mM0TTrvQ`(AgJ&V5mAL9A7x$%;M zYKD8JmGUE~rj#pTb78#hwEc+;_^pv$to&}3EImmYvx$#`<}orl$)#24 zBR18IEleN3AJ`;zhEAbhE%eK!Uj@j(n&dnQBG)v74?2Is2%}^iZgTB$`ikX-j&$uY zck#T7ARWK@Uj8w6;)3#~GcPWWT+VqF287tsVS_&~Q~K?0bs>Vz`+_PGR7K7rK_v+| zNct#J(HTgOS~PKJ{kU_6rjI3!E#!#&LjI8{9byW>0$$hEBKu$*zwiAz``~Yf<|cuo z_Po%d%S)o4^lLqmXvAipb2)(v7`OAkE<{5Mf}Fl+(%40p)GRt5OgkCBF=%_oG;kUG z!ktu!Fuootw^THZw^Up%e5?Y?#&%p-Q3F{V7u{P(@7M`W)IzBv8W;OxXb9{l^*f|i z<98U0nA~*|b}%)>fLF$)ZeVx_VZ}fptwV_fhR-@e4E|LBBJYaU^fPww538Kkpoy~C`XguMX&e=DGVpovylP{2 z#a4XT4B^A*2i?HunK#_Txd_hRh7ry|_TK6`4ez^w_h?rL(O2JM-NosV_QI3n4w|^o zm#4yk9d4i(zwsNY8CvaX-pmaxwi+5${Gv`0*@AMou1a) zot1QB9iy1{kghf3cmu4XyEOQ|#=1kx!`Egtl%`##}yPJ}?j0;e~Ua_L7>ze}a zFB%yA_*B+R7$1#yc#QNlcJ!Vd9bY&K;8bkg-{r{7v(FR1scMp^$ewUwxI!;BCkLO_ zDEG{*)tQ-#!|~1T$fv=Yq8q+DIXUbIXXU`^m!cn!a+a)j1Kah`b_@M?R-PN!7v4Gx zSmA!K3xO5o!5GEjrr7#o%84vVpJ7a;+>v{^L_RzJH7`SC8SIJC@kfkmPF@;_yye{0 z9qkS{D?g6y47elzUTyY5cq?@ZLi~JxZyuKo7Cc3tOl1HxQW(!v5tN1S&2j z?^hokcWUIa`bAS97Ddj_*4Cpp2Sg%H7&JwBC8}&;@%>Jyk2`Ax<$N3))hL!ZWc5(I zdX+`-G25pZ6#rK@@V-#I9u#i^#lHoLZzkK**yhoS5Z5W{Tdb=%4e>ijs={>8#PKjD zy4;V!1p=BuV}+$ zMyIJ}v+%3t)X22@MVEQ_)#>5a7A(av1*mld^c z9oswa$?<4i9wWwYs=t@=*Rt>wvYJ20kzZiF%QnlZ@96~ik&;;Nsof8 z<2#@l>gg+rm%D*oSbQetFhiS)`xLGq#}OCXGsU)-fx^_pdcT3FEQSrs#ZnUyvynPW znso?*csEipCpZ$(VMuvXqS*)sRpxRFE><7;v9oZu_)FkSH$EA%kKEVX_frb@`?qOg zO=0wAv5a#BT{)3s_&MJgA8b8gd_RwYqgT+ywUYj>r>tCKrC%UNP5L{AsXFcb5%nlA zfGjkLyVY4vb68Hdv7C0ZoG=R*J(fNfrjcR}_AzAhlOs~9@?{h-A2w*hiRfEcm+ElR ziVeI5c-}a}ufoY8N5nQuS>;9 z&n9U%#*n(PBC5ss7b8IL@ZUJ}(3c_~1Fb59!xdDf9N~;Ldn`mYgg0gtJioY7n*(dF z(5J=gvsWkPN_$gU`;f5S5TJD3!8%>aQK}3~<^@w<)??XXw&7z`kpvzULj|))R zO$50bDv&%UB6&{ElROO;ntcp%D8ob|r977YQ3T5w?~nLxc-@|7*7C9Y^ie$<$)9r+ zVeN~OjW?LBLwArL4EbSGI)XNxAEuu zft}y>kx&-xL^Y}6)b)!LK5%@$Ca3Z7NIA*S zibyw_co0Uk_>m`CyoUhB&ZFDVLV`sc@FTQvT#-4QkQ$xcFlq-w-&ul_S%Md^1an8= zT(M|&dEy2dJ(eJ`qrD}l^%cS>>3>~+eZ#57theNR4$!(Gcn2*=ogJWuEf!#ja9qQ~MJe zcfzPvZKS2$(T>+d(l&?GY|}5SIA23>xX`1Vjc(mc4r=NP3WaAJWU_$7zXB9*L-IrCq_n?@WcwXoC++^Ad8*_ z8%)03bj(~VUSZUF+~))N%f~-SEg#DrqTIhZU9+8^n(@q&*A$N@(SLVA zU=!)u{zW7$dGs_8!fc6O>*S#)IF@()<8h4ts2%eI_i18}ZdY=Su*_janG))-PDrTJ z3uC7(bSM+9T}_rX1?8F)3Ybez6eJFpr4jw_*SW};*;E-$)J`Q`R=z}dA29C->|rp% z+Q}tb=~MGNREH2JXj2@gy-&FG+6dhBs|QkUx}W45@F{W1Q^vSH*vpSe|96Z_EkV)& zqbnUr3$h8)=UiG8PDJQhBLj{vVi+I7rta5^CnpD=Di392Ianv|TW&q7Spl54pw8!X z(*5YA=H$%s=H#urs^8YxyG`|_l|m$)M(8I_o1tK_*J22hhC$7fG@Ia<%L>qn7-P@+vE za4OS;C-1ctdo=zR(M23HS>||5Uqn&3i9P4HDY7{?{w%3FB^#Q(LQD$`h3RuSOBQ?_ zd6y;%;eJF7^T%xd$6w5BCYWdS0SfTRK*k7WD(d8U{(G_QAXW|9D<(@XjDjS`(xue* z&KCOe<%OGMvhmuVM6;xSH|Eu;qI+O1NIILcBceew$d;P)QHyW0D^lq!EUpHCm z?0xXxOkAa*U-j{SN^O}KrQOLudhrap@$^uY7fSuT4fbIDUz_6Z805K|CN`lTaN2Yj z%o7}LH%|@mT`_L{G}6jH)r~(bqqj88Xnx!5@ryONDl=?W}zdv)aopYZBCM}$%xOgC7O+R?QCfkj=`KXi6=m#!T}q2(rsBQ=;NcL&@%2F80e z-V8AY8M<);T3<)IH%i>#S$wN7a+4c-<CBcLWjp$s!VY$0vW3cFGSp! zo?FOlXS4WTQ>#DHcjJJcH_~g8cBF4`HPQz<|5nJNoVdU`I_b}b=w?cP_D4NbfPhC& z048!&3rz?_Xnt)F2yyaQ<1%m7nB`F@;xbA8fJ|{t@>@KSHXDD({PWGX|5GKhC4Ae= zf{ac>JXyCVD0%R4`emXPiY$Z2*bkpMHx#*=xEhMS=0%ml7rm)wL)bZchjA)Jt*$5~ zAHAaWqo{MT1gY=X2tz<_+}%1&G?C*f&rTax_4Z|^9j&;vA@g5BqvvupW<^CB*|JEf z3AYBPXsrslv56((Y4Ak`=DvWrJYnC1X@xe-lpbok7Wp&Qx(4tg0FvUSn&13UxWqub z^XalwL5F5*XDY<3nV`98oN16}6znK8RFHEoiw9B2}jab@?Dt^;*#LK8RF1ENGVx zBGn!X3Ke@zB~=N}G@{%Gk*d;y#`+*q)mc!B4iDO5EVH0WA4IAu3##)$q;f52 ziVq^y3=5j=gGe>sf;xN#=K8PB}T9E65D67SSX80gd&9b2RK8RFN3tH@hNVU|0mir)5by`rD z4gIxPGWIaY^ARc1kz zK8RFR7F6ehNab446dy#Y85T6#2a#&N1$Fo!QZ2TiWj=^h%PnY?4k!rC8E%QO7T5dtB zd=RO+ENF`lBGvO2l=4BO+GRlna;x`RAL3c~<$>JfBNbhIa+AL@JXZ?5oo7q%qz>TW z#3L2G`kuJAVvBxJmqv)^LtrNDU;A#N2I-p4s*h$0=Ztj;QKQYRtX0|Kde*8qJqxVc z>ks=kWN_`|J)s8w)dE0GvCLIYtc}7j(&oZxPyTGtF^!DSCMSz;4<|=&Xj-sIl7Yll zb|pLhhF)V z5}bdMu#w{LGWjul$7Z6XsI`CJOqL|U(ei7$;j7g&>i?!DZXJV|HI3YEr&7T=i16jK zeE?Lm$D!f|H)tl0d0S3{!^sB>%4y&8?dmS9xqh-1^+No&M(Jkt3z)!sEq-rBoBBsK zbIQZ-Qf2o7kT)d=Jp02?s=I&J`sPr1weWP+yAIYcE&Ob@o7Cq$a43l^{Ak+ATXa0S0@ z9*c5vzn^hET$hcCT;F;QcDJIR_U9%o>XIRUyOzfKzEXEqY+~4qY3H348+bIRI5U2(0?)O?2WszGp1vfj zUlMI-(C)&L3O8wSNAJB9srL^3@@}XbiHGaudGk@;1wv9@Qm4@+Xp@{Ys#vgxQ<1q` zg@AMRa+PEG@=dMfay4Qs%dd*V&rgsbMN3UB35L!#gc3!C)dsX8nfxUVShf4$9X#uw zx6*y^E(;ZS505_B5Dc4I%fJU4Gi?i&y`2v(=UM+KL^>KDT$KZl%>&ovz-}H`{-jxz{~T%ojLHTJaAVI+?xm9k^?`V2i}nb zr}DtNa^O9A;DW+z=R-XDBUq9Hm*s)WbKuH6u+fuH4%09;4_uc^tph>7?3Nsu1DGs$ zMh-kH4?H^uo}UMf=D;0!;Ke!c(me389C&#ixHAV{<$+UYqFfbsJjYFXoQ!2_6-4E9 z(U9YpA;+&B!%K3=Bm9_aZ8N1K4LP=U>D6!dtz(pDF8(6@I*%Q)rC%GHvh?fEJbLu& zXXfz$^sC5Z{A%>;?{r52Oo-i*4DR{9NLYPnQ$2UXDuzZqcf%Uz<@!>Vds)1Gr~x-r zoa(_9`$HcZDk|?U>_pZ1DAH3K-S6AWpM3qQp%-h-$c%(hA-j?Q(*JcQc8A&^4tkG3 z-8%`GHhz55f}Sp3!^z)P=y!2b;;0Hq60?aY+6W&*^8)`k=Vw0u_>58XSU>s|XC(@j z_}~hO3dle&G{w6b<9(^$!>jcPVh3S^$0Q19dX@9w*~GkQs2J_6JX<$Moq-{Z)4rW* z6~#5Sp`^KHr_+8DcquNl3^*s@cWn$OECcu0x;SJfpBBN%DWpZW$bTzK-ig~??2-5S zxC6JJ0&zc;_})Y0pmVa~dk=!LSMuB6<)#spBvsLjHl#UGY}t!qVe5-g<}!yY&rX&; zi`Q4CrIO>bE)x6Ak8R>0)srT$y$YZCfDuTX_9REw#24f6u$(D9gZ7#!#e>&QX_cn5 zGZ24lpH4CyeMfTYpaZ!Uj%tf5(ld1fNKyK7N~x;vC{|RKY6T|_2t&rut%iyq-@d8f z>iAT^FXXZuN}pQ4XcE4`cuFTG^*0%?u9`H+X5iZplYvO~hnVzIA1>G+JzAbIscg&D z+rA%ZYI4^uJdfOfHANYpJWr(`gC{^n2m+#@B5gI0HCOT?C28qzO`bL7=Ht)Ji&=aU z=Odxie{*ty(3IL}ez&JqpSG`xocILU`=l1UwTe=3(lfEjKXtjhJ8>RcgvzjX3Fx?W z4?_aSHeJ48XId99jP%w7w>m5uAkOL^a3l?mKJ3#+nxE}sU2zMt@9)=XcVCw~}fkH`(f)XNVr48{9QkKX~P zAS=pDj|G{XQU27l6h)5k+BuLSjL9zAa?{H6z}!N%3rvWcx4?1){6P54PIIf%wi>*U zuR=0-O`RQw%KBADnXa)V#e}q*IMzR~ZF7f#k0yTM9PqpC1O zkZWwFRm?s&Ik=3&rA$+7FT7zo6Y17G?Zk9*u+APhQEsi66;52qmWC%L3SZ{YSoh;Y zgF8WU{Pm`f{yWzJtRI~w=QmHzZEUW2H5`8$7uUy|lA}3$5xY{^-E#?9{+tsFQUS)2 zCv(**CtF;vQ8(`7Z-T|G{|E=tjn!M5;xDDY)f8CIW4b9Ef5Yy7nrhy6Vua+QpP1>_ zY_jFhhht2u2iii9svdWg)A~%fNOve+SW%K|ALrslO1ba?Xjz!G8l_QTdNR8YyRm`> zxWx<&7oCMmD09_$$>O0*p*>H<1h^soSYzAfdaSgyYhG;f-(_}?W|@THCgqY?N}Fod zwU#(PK8bRp;{$7*pL|{IP7Wg|(Yn?%=z0KVbK_}(V32E|*XzYuiEBY@U198v3F#|x zO*i_0)ddAZ3$T!G{}c5t_)Kq3+rKl{#a}HC>N->B!LJg{qy*42|qdnpZ5Ap}3j^P|V5;T}w z36h;;@aoT$4PH$fLNB`m6UQBOl&tDopG!A11vaI}vm$dPV6Vcl*hN`fl7%C=Hne;CmqBeEWXk$W~3IdAkBkSY^8}?iM zaGjNx>Ns)AkIh+T5|te#WQ8{fupyw!1>~h%Upmc;m6B4I%tcnvx%7`I$870`ctzFT zX&}UQ{-j-nFV4&?%XJ@noPGG|9tt%fvMo#HBC5|DV0z;*4TS)oGP~Lm9`0KvKD1h) zCS|sGoJsae$VF8kBYbL!X<+TNGsI7a|AclC=VYpyCqusEkfQI4(;F76)yATk0&Por zG&v+%TViQ#uy?#=nU;@QAOuaTEsu*PeqdN8Oc{?D=tbsP+BLhVb!y*X5Cu`-P~Rau zQOk*6tcB{zXfe(6Jou~3n^!0e&MUNz?sc2)!IC-RL=VUKqS_Vh4F&2~BmNeIoyKd$ zGmn1%Oj_?WLMz?)ugnHL9Ji`ZZ?Lcv-A1S6Lf`fn579G6;jqJlnB8pRn2#HqABSAzVW zZq4;{DN~(Zm*;(a?2Ve9?Wz9!rg7CE`i{k%)bD0mqo%h{*iW99y&!jB)5JB0(}2u~ z1jw1AP>U5^Eo+FagZ;{VBkHiH$Y2WeG=qX<68#${1eteys*NHs51i?l?;{r zO0x8tMWVI$^3_Dtu^-2LxPU+mYvGM})ohBX6n5F@{r@(L$D#)zd67#Wr|tQn{^UYUwdGtSPp2l4O$-fDZYN7!-500UU`2d}vF;iN? z+cXmS(X%L)190ku>sUbbDd&2A#(}!$!9^MNr=~#5PoUz|KUpm4a?nVY{slG~kek{* zjp|j%G4CPBImo3q-q;gd9 zE2y{qY)ak(K4-}zY=)NX%iP{?_f#vn_ zN4)3vae&{(Y#%uxyz3jnHm|);GX)mo)W_=m@{6IEF;XA1dG5A()W?onE#e)aK6;2( z`x>>Xj~k(vd^bnGXljPt#B-u{BVY5|yqfp?Heck|nQb%kvSXwW!)x==sy{m~x9*p} z)X%@qy!0`&DH}i7jd_8c?HycaD*`df)SxZE7PWWY( zh;LD4o+aYsFIXaef)Odx+j@4MCE`J>5be^<#)x7_jh*2yG`tXvH9lYu0Bez&UEOz2 zJ?QGb={$8%{D3uB?yc@qPW)=Cd!tseUEOowiZXY+#?+pV!J2=w?vK47zbZz4pLIW= z;=t>^n>PLL{t@$ydSB;I+4IV9;>2*`dioE+*G;Rjuhg!R zoliLaT2A;9{nnk+gfTDcq|zE4OC`kE^9>v62bq3lxs?LC+RPFX5H{X zo_u#kG=!jI?Lw0V(srN5F)`*Q-kHG=Z)Qp``F0>3%q$$4z|H;!^p_`SnAw1e*hrhA z(+-#onx8Ree6ftjAW&Z@c6eoIS=~xA#e>e)vhqp6^E9IsJv*deI^Wqb&0H); zlh6(MTQoQ+{+njCZ8s{=8tZ?+bsssDhsD$hS+!-@jJ8M5GqM`%S$btJ5d2T96ZA|3 zTM*mB>8T!ml?w=u(J-kb(p3qBB3Pg??_Ee{a2g|==xyyJL_ z*k4xh{9MH&s5o6qPu@B|zbF2ZDW^%aG5B1$E!no;0%>?kN?=x8d}ErR$s5y$8gm21 z&sDclGrr5fB_s)5e65D?-PCzU>?^^bAHwU%Dd|sS6>J$UDVHad5tRLCSd?R2$F%V( zPyOWqFN_ghDyE9nmr-zR!xWtR+te)9%Uj3>vS>~QtGM~w&JOp)c>S}~$Id|T4zF8Q zwlJOcMHMR)SdfH*3ngi0PTQYC6xit0^HbXp2UQmVU0|V=WYp?0s1d_6Co!2Fx?&u3 zw-O}7rFA!=b|y01p-P!3FyU$1yR7EjX?zM{^ax1@PU99y#Fbh|RYD`4>{k7Fw0?SK ztb><(q}3IAwRoNT{mzZe4zQbQzTd>V96P>fUO8U(MTqR}7gL5io6q4;$Obzkf+@jzWIgt5>lc>ZIzWE0t$#@0 z2kCj{xU37vFz8MiHxuId-)yKkqsUCVspH`+=@S@KQ{xSx)S<}Sl8X0U%?DgIydah* z8ToR1>b0*4)fO9PIdgTm#gF~vIj$Jb14&=GwUwX~ljIN6%Aq3~^Wkw$y<(g2(vnv> zfJyipgK$ydn;+keDGqjumy6nE_>dn)>~aW@!3&-LNXkzHH=m5Nd;A=QXM4~*_RHsF zr}`PzQW8P;bPIUT!9yNrM688(R*QtTlsOH)=W0n$#H-aDgF77)%`rIFK2Fpz_<;Dt zp=%WD%u_f(6;GT?4)G#?9*yox^EiYr`)RrM&LMHKRPm;&(Q{XC&Xk@n86zHC&djkW zORNJ+e!n)+P|hz^t9O3+fPv(ABI}n?4_;@A*i#e$5c|Aj-XZAn=W#sy_sod* zuCE|lzEphv589(+Ljw&b6k8Och1C#Zuyad9LDyR%sa}h zd2!y?Xd>rL^n<8d=1S_!h~EjZb5&V$&rIpd*TMX|tGn7aM^2J^j4q)#uBm2w*qQW+ z5m`7!K?nSO@XN68ezd{f7wi|EU5~o|hMlnbc!XQ?^1M=mXxfvSc3hSj5fGZ>x8X(P zg6lj0-%QWXA@PPDm9dtz;AR-`Sb@bAdotf9e(6hu<9_JMpLfoF;jWUQ3Wzu9zsRppU?(w36p9D#*E+u-r3`J-&j^>8iuNC-nr;d z*3lixOcrDTQ5REq1zb=jHpZlYGAlJc9L`=z0{QX|t5DcPxEi|jCLP(DP3IY)ef3M) zgPgvrX@O$(7eug+mhkpL6KwTp2>f5qVb)Z;A#rm8cnCJud6%d zrmo>88WS}k2V86`dO}vE3pQwtc(ed^UF%HHmgDf*VhX8+mr|jVx>-L)0C)kOBM;vm zmCWtKyIa3cja)(~d2BR-NP0FOIV-3)GtAk^8>!C_In$&3_uZ+t_1>g+GfMZI&nt>^ zUTwsH)LSjEua|6>yLhIW$S-UaKT=|}a3*g_>Oc4@H_b(kh^{Yh=FDYcZ_ylX<6(+W z#DR-M!6uNq8!yIuE7&^OifbTu*k?kZX*r*6^gh8yg6)l3BK}69Sa_ZchQ0>w0j!hQ zX3tzOBQhukz?`=ZPnJ|F4wN>eeq??>N?kp~B8WO;?;jL4(52bfU%isa#EUM?@za)r@eB6R-EN{o zY=QVqJRgu-=%m=B(Pm-^jJhRt6Sd~>Q>x(>gOPCai$j=fH6+d%CIlaAjuVSv{!G$8 z54Dq|ZBwAu;vlHY+SV!7ScS4Imqy>U$Vv84YN)9wCklK~KZ=bUao6K;3(;NzXCRqE z)3<1p;b{&eVDOnD0mC5=W~rN52!V854PtJR-kvG#qlq$O=kem1LWGJ6X;nh}*L8x! zj2o|ztDFY$nHqkm8j@q~I9orE3pf6XIkx``^iKO#vsWlfZErU7nR;-Lov{Ywd2`#) z6h;hfj&6r{+V7%NaVA6t;kNN1)&f$Q*s$w5_!5GnmJlR$|K01D)#GdnUX}tDK5aMCR7demF{!G@aB(Gw-V4{mEKvloy#2LheA`F=(re~sA zb*5#&DuLM$QC`vcBKR{`QyjCw1u+~;Ddo^QX1z3451gH}iqEvC+D$8l0$vF-Gdksc;FFJ?Cpb(Sfa*`SeZ9sH)|@t`eL9DoC{(>QQ~CpDFfZPn;@#@L zMUchq;otyNffmy&T` zg=8J+CTP9ZnkJPF*N=$}8a&-G0!mNb<|lhTRDV(Zg*xV4PNU2f_L2nRBKwDj6IX{4 zS3?wjH0)rMXi_*~T(UE|xDb!w^9 z_LVjGo_>Knoib=?q*8&2tkvz-$AryOl~6Gnvpazwd+%j387oQ zDe3JX{c5e4B9eQ7?$bJDFN?!YXYJp3%#_|u(fF4Y&f%0bxXNQJ2SOHzxos^K+h(R- zNvnEjkEt1y#cue!`>qJ9Kg?gOtkO*Bgv-s;v-RP~&7x;Ac<8OU4gXnQOYE@O76)$} zY{$~J!vclb3}n6zK%)G=+NPnu&pQuX@YYx|HN~GYjO!8Op`*A{RY2Dcp|~aCzlOkawAaPE{z;Ym@mTYa{fXoRMsl3c&nBMXLh!hN2o=D*nDh^vu#^H!)u#qmX~rbXpAFY zn5bMG)FZ>KD8H@6T)bQDCWf3PA|N&Ce^Vr`VORlt^d1I`hc}JfhNdp;G`uDQ*^y6} zmK*-pR#8SToS|)ASa$1frS}vi>-Tx@x7Yh!<^3-Aezi$qcvTFwN+SBGjAnYvlYmrR z%vB@TA1CeBY%NZ(rg1N0MZQ)%KrPjanLsgmUpUeD5ePa{dL1*h8{{f%y+|rP8wcxQ zE$WAk<4^r6#J&t+jJe-P49#H6WDOQ0UP5U!h!<0AIS(vrqX8REV(pd)m@;NBOK&Y5 z@X_u?VVF?sJvQY%1=oG|>L2=jl3}HKt<-v6=09g=Z#A>$GCRUE&5}~f@lz@NIX3d- zwMv*gdW1-dB({5n>_jpA z(vW7~CDB^%87}VA?nLl@J6}buBT!lryc-!>ZU2?P$swg<^mCz|tyzo}Lu1A?;n})j zbhwO$t-gvsQvUQ$+-q7&50ThD%AnvN7_0Wy#Jp#k5q5vX>UFQ!$o5+FC%bhqmlm!^ z0|QOJ2QhTbB#KNOg~JRaHCa1%p!ssLzLe`rq4x#WB`iZ?4L)_Ix^H-xk#%S2WfmX) zQbmhUUOz&@>yxfapR;vcaj?41K2Tl%41Kk_ z#;7iZrq5pqb+89B1{;Q(G3Z6ESaYJr;B(@4>Pud`9vgR%G5F)C1B}7+uh_13i85NX znbQ9Ne@$y10+uNqWE$tGD1;iRKOh{WIo9M9K>F0w;ix{OhzMlxdEP&s-@g0FWONxA zjQTcvABo-HAT50YT8uah)}RITkVu$8rlUk9z*$MD%hW?YL)byHIa4G+^YD=HEw-Uj zI|ZZv)E=|kmiSL_KqZEZj?N^1)Q}Fm-jbK9(32<>E2O(>#Est|1$5Gl>vQQUEe;=M z@}6g_Dz_&Il4ng_&dUDgFebLAWZvPdss{ti;}yjVh-^xv=Va+T-qYXV;WnDnC%Vq_ zD{OI%LTj`3x{#01Lpq1(+ipMqM;5Amt&LZlER8DDdF1|~9^iGQgH)HvU7~dVZgV&4 z^I?1*#Y5jh3p|`>n^f^B(l_#Xuf#}`Tj3niGXebrQ2G=eHVb#mw~)S_3+TaYa+y4* zxjd%y7g>SC;hK?@KvXC#KSgyc0=AJqyKkznQfXFviF!x<{E2^C}zed4}sZ);*&X} znFyIx$ZCcZOG?7~*Izb$eSTZ7r!^d_X)wG!=X3*MyzKt;kX44YpLt%%-0KOw&cNxN zNolPp#xH`zI%T4_OS(`{7ZVn*yS&?3+1)e}9}AZJ39NlL!TlQ-lyGh|mj|@;-ES1( zO>+ZM-%w9$KNPLv#86K|iIxVFR}>)JX3TDEVL4+@6M@@$p&FajpBjD3d>tG?4!KYI z8BLhsGV%tD4+g=HKEGI)!-{3|b-PLDiPAUFauQ!F%)HhlwyAvofmUgUX#XLXm~^w1 zZuUOuf{d$I^JZJKFVIr6Us#h8#Wt8zZ`Z0`QBMRrM_blVo?RHwRWUpKEJkVp_&YFR z7{Izhbpw%FnCl(W8!Qxu%`Jd2mDMn<@v1XdSHr>U`uc(D+9opf73$gsckSDv_T}n& z{`7V$T`9F;uYVTLTu=4{R-UR=ywD-PTqANFghx!D)D-dUv{<_?m~b zZEYP`y}SMqt;_Tw)ud5WOx{VSvzZ3=IVU3mRuwo8!sll~C94-rt2ne{TE*$i_2}W` zGh!UV21>w!KDqZ$=us4Y)S~)9i@r4^dgI`N$T)5b8OIr0_l^PShBmz3>^Gi{;LC7x zB9}hJ0vAmk99kcGCi13owr--d0o7Yqb*Y7eY!R{Ey6UYcB#h!zL!{81Wi$~&plh%W zr-}V&;*m7*DAPpDA+XOuK{AuQ+%<)6(2W+Sxu&sW<xU=>fyXbU#w%qTr3|V!l;Cd?)WZo5sT!oSW8Dt(`h_GaU+}{@5BWw%L&cHk z8IEdX+_4{`<9#vIKBTU!Tfxa=@aN);NZKdp?6ma?{uZ`2K)4?L6k#PMm__o`pcFXOm((0>*KHYZ=}6kaH*ynsvBDqT)5*x==d~B|qzYo4hc6ai;WR z`ja3O`gw&N++>OS_#x?1;@cW1?vnik6;oh>;0!tUiI5@ z+Aqmw8tN5u7$Y$Z=fa{$NqzkCV&;?SEa*FlL128iFJO|n%Y7)`>yrimISj}k809eD z2OEybtso^H8mJ$qVtCZ|)@LFYMx|bv3Xjpt_SBUh8sRj1K8~4}z3Ww!9vhnz%-|V^ zp85+Ib@DS%_ORYS{|%@!$V7yuJkIuv1;AAha(3PVU=J{X>NQ^j2_a=Xf{87UD5(Ph zWL8$438mc^R{789sKkgXpoA!Ul~Qo@YR=C$6aRvaR%(aGnXDK2wM0*KQs5yfu>B)H zBJ3?X1$iS=`U@seN=WVqA=taw2Brt1r04F1%eV}uDQ+Bpj7r^DKOkO7evN-n=d47K zXZUV!R?F70M({vh(&dhPk&~gUsO}uwfFLsBI~V8MTVzH&%=*YB^6W2A?yh1g9*MmpLYKY`ISBWkY%P%raNkYDT%M?gCN1}pPWKBdN|%nmLWMB!g3#ct_1 zqG2F(UP9~3Q-7^h$`;P2zz+!|QS$H053uiNZ(;&LC&$eH9Oqt3|1#KhpQ|9PI&trB z)H2)UiC%gZi`GO;c`j4BmtKjwP01>N&4^9OlrGg5uuV2*PTRebNt3b?PL8=}NPxk+ zl5u13%7u(2ZU91J_M^N&mCN8SvcIj;??d_%`?$FExU^&adC5{H0Ecag!Ch+{nA`7? zFkxymMatRf3W0RH7}y=cBe{~01~<-kYaYc4IXRy@Ntj`0WnCb)V?sJ8D*hBCJof6b zT(PlZ&Tw6WMAWx=WM{MItegV9?bfGzd$jfQ5{CmTPC?Kx)NQEOWH#Izp&A$0eO;)OVcXLhXl zA;9$H`q*dFBEg3EJ85V=(Z2?Pn6S)J^Ku#HV1^Lz9pEtygwO5`IIFkB-ao4Q&BECG z{moTd>EN0<6sB0&=fV^Uod;RPGg;xZu8a;rML4Z%h-0t~8#y_sgoPcAn9mh+k7;8m z1B|B!RI~5*{Hfj?d$oV}tB0!3TL$#f8*kK4gekEqs*0Vq-;zcg$(dymD$6a94hoGb z1(HHqRhzv%@rJ)m8L{=4k3`0^UL$vAS2wu&mPo9RtL-yH>XT!x`y_uUY@UR0-JLG< zViwQJ6AaML>+Czv{xVNr&Q8-)khUxePGjZJfVrGDJUv-T%-UBWDqJI%tT>APx2)Ed z!X5eFYtN$bW{M>fyn&yzf@#BgBc&)3OdOoSx<#Ti{j8y%ZeTq@rJWld>>EZ#j(=K9 zVtY>DYD!k!rr_%kx_~R1Qm~TG8lkLqRku43|3PvDriY~u6^YV7I5cV{4{7_JDLwBT z_&6{udQc_t9i?Q`S_vckyS)KTY=s1p!KU@x^n8P>uAS1KuKD)+@i)UYpXt8my$wda zL)>)GKHQkf)|A zPX`owFz4j7U$fgHMmGhiE`RdY9!WKZN^_3GoQP`Qk`LSi5Yj61Drnz}U`qNsNDZS{ zQp2^RPLbp_jN(UXTn%fj?&4!PAPJyfSE6A`G=gly`EsJ@LnRW|9HB6J((*NGL~8gM zhN{Q8LL<0)ZvZuZ-5?%!n8$s*m_CFqYphN(rs%AIx{ylHedPMh-y?6fNh62m11r2f zb=y!HP)(-P8$E$j=ERaz~Gx~`t5mf>WhGsm(zzBi zW`QybW8q88jb_RSY2~RCPer5Xn@kT*Ej0vXd#dxz{S}Hj-!cxuovJ$iL4AB5`^M<1 zIQ=VV?O(mM@0-H^_{Qk!4uOn^@bAH{0*w5UE3AWO?Yo4@U@5t@CR4hIuTq(R_%)-AMt3m;QIn2! zMzOJpG9Qf#sA&(vq$sf|MwM~i{F0$QDYwV;4;bTQ8(J#J!!sx&f_ptf&joU{YA1wkFlk$zoW^XfD_iv9=< z)2_KeM*D_YGo5$4aG16-ta*r%-MCQCHh*WBzc^Vl%XQ{2)68?Z`HR}jo@JRjMYgNA zLS(UDmA%@64MJ+8OG};cqy{|rU*&eWkx^8i&w41g*@I8NoxkoZ5IHv$e?n_GwY5r? zTB##X;|Bw)+S7&$%g2KY>0l}dG`j#xQp2?Xq3~usmZXnML-^L`P1ydkh3U=d-|*Kg zyQ_XXwNka8h)$5QE_QqI0Isqq?_J+n66?vtGC!Pm{C!-!R60E^32OAiZs57h8)DGw zt2guKK8HV@1J~a-Kre&zC!|09^`}^Wiu5O_KST7VAAbx#MPB}CorsC=|6ufYAhXUB zeuap<-+990a6JD!p-RKcG}!Zm<0!@`=dRXl#JuwaBQK22jM$(xMF0HvZ4>PK{`(`N z-;}}S1Q}1A_(gj^?5VH<w)Mv|p)@D;C$47Cv+r5c0^GRH zWk!UQlX%6tYt*O^WHmYB{rU>Lg!j=WUC>e=f380Ic}r`F*%tDci5%A#*7`yoigodS z#~wG1Xe6(a5Kn!l@UbEOUi1|w`tjg-&zL)7OE3OR(>HjL8+bbNiY}v3SmxNqP~SbY ziuVTIO(ZU!8}Y)}%>6IZl_C&-G4|^1?lZ5t@lj0!{?5T?|F)OrzsjX|6Xwl|zE+2F zqh}q9GeZ)-r!Q3D&RSD?VS1upobHqP-^ydZO(UEKy?mHzj0#_2UNE~DMR&UTileXe zk0LMM@tH*Bt)^eKf0aVzioyTK4SY<$;%|cgiQAA6&M8ZyLcXn>CtWMU=90@sFk96A zxa|=N2nY5yw(Y(VWzC^k)pGsi)At{LS#dSRpJdmMCpuOLEcz`Xw;RgLNfJk+iCJ~w z#C#XIppKzrTG{q42FK)R>FEv#Fg(PKpVS;b%i2Y(VNoZM2k=9fs1@KX-%x74QGjeu z&3^5R{L`MdVf@KlV-QR=-=bR}-gBPpTW%x+af-D$HGyeVXVh7C1q)JtrWn@^7xQ2EzRrpxlCB@19*$Z=Yq45KPj!Zt7V~hxnda z&97F~MXy?dmA}8XVMqQZ<#;R;aN6I7-8Q2fh(E#QOJPYfVa>{mwrB{kWNt%11{;&# ze`n!wDvJC)IM5W^&g$KX9nF~x99sT5u@}aG1AD1>rikTM>CX%){`g>y7=o`KsVSEY z8PFCzVcrtV7^qd5$nN}{`bGV?rwi-1(G}zA&z0id*V-Lo$Z1Q`ENA5wlue>;Q&M|A zq4V0>NBK~{Mtk%=c!z98xIKy8AX|xo`rR7?k#l5V+SbK4dt;Okjr(wZJx*FK`oq%5 zJYz)g>aFVDGyFk4f;`^9ZE4cp^*yL8$>0MY2MW$k6nFL!L69Q6&X%M(K7!ZErDdN! zpx8cEtt+UHo>kDCyuoyB{`+}pxFEWE^UTFW`WmjT$DfP60X;zrH@c!}z=wvQY@Po~ zbKpZ1%M9C5Qej{ThDt5B8R7h?x#kTgCZ~j^`0F_28jbHe36!w$H&a{o61U6@k4CHA zL@$cdMcmCl=ktAhHXrUIyUF`3o2B??y2O2n|4m`A)H^O|=FaarMJ7ALwD+UfPTI?8 zjjnJ9ps?=lU)Q#K{tmZDnm=|wV{tEn2r%dXO# zb2Ik*tWB#@4afVMVQGdr`YAFya#OfZeUQ~D*2wpNgtET3L+p0y!3llLgpc6=@yx?w zENsg`Aq0F=TO%hZWHB`D&<2j0JhiBQ-y1v{>Qmz;o42{~TYEk0{&&gJ&bi9cO^N1h zNaS~|t1EvWUDcbQOB_{M0sdm4zG5B-XW0@gRwlp}6 zl+oZcz3Id^YP2vhTdn3{Wc0=Sv;6!{Htfb=)&yYWmi65L-ZE!z{?p7^^;WO2$l#udvLh~3BsR7%60#@d=|KsMqaf99&@Hot^OVMj3V8~4_P1J3$guHe zs3`T^OM7U!XfX=CT3%4K_yWKm` z<4z8`1G?SrS9qM*&mGX~LHp;Rp&WET4m!|->T2LYO#?QXuy^3==2W=KcKu9==CSpI z(fxgBi4~28#dbHxQ>h;Ga^kPkMYR)+%ygBy6^>W-;h=!sWTp?BDemO+<~JMC7?oo< z-n`0?P0*H-*|r4tXdL2=y-Xt_R%2HJO06)F7~^+quN#iv8V$!I9W3=;MryGoM9oY2?c#k|IDXag_AY~uj@!5) z-q;Dnx%vpoN}9cLYRC(FGG?7#7Q1yDe7t!TGH5b59NiU2P?=`qaC2n=&Ygy;5(-f( z6(&gpoMb6Ohu`KF`9ac|cmVA;ZOm8cQPdA8Dt&+I!{-smyzxQI0&VBMk5ZRDWHL`z zcTHz8Mk&s&kL>s%vLUWD$DcG&EFYJ69a-8G|BMRDX>3{S)~W&sh#G~7ss7n9ZQp?$ z_)s115Wo1#59^B^(w5Z2=*DTLf*`fMLeBVfsO0bJXa`yb<(ujJkmzsH1kC82>3o;} zw>L){7R@MLG$lxJ4U1-R^yzZK-n@+8Luba5Q%q(TAuTCoN5ZX&C-L6P@R^{7&7IDJ zb!V9gPp(h}EWAcjgsW)U1mCN{BBeMnfmCbg^B6goc7UzCE5ieL@;h{v6Fx#8Y`K$5_57r zGj{7T!YqHJ@kw0QITK>fZXRfFMp1ARRt2OzkitcTdbyD{8cx`%6IU^AYKu40%OJj< z@!ifuWSc+A7yiZ{WjrVo?MkI;BE=1fS>>jt$dQS<%4A0Y&8(FxvU5&vLruy#TZjxt zTcIpQ{4@jgKPt~QtnW_R4FY|8mpI8sD1jskT&_2@QxLDQ($G)e7W*XAIz;lv=i&JK zshg4Hs$a6A5V)03YLa8lp%8FBIp(SZmqt;M73r@1#)H_pb@j>S41}qlH!8Dj-lG)iV>INz+7TvE`} zKAS@HVy-1BtZ`X#Dns>JzeK|^#pnUO6{ka%L6Ko`aHn0Rr_nQc zH8&(GjtSTNt_-O2<12#nvFLXiAW(~WJ`9mBRklr>-D%SSp#_Ho4tQY2$+6(i-U0mP zGd48{>485K_!$o@^F5n7E$|~AIFw|N$J=4TkGB0XxA*lxOV6}VoI{<^WtOCMn_I!qt73bc`5 zm^OClpt+q+#lTgAQVt$d2I*@H3Xc-uV?y11gJQ1);&%pD3C$9X%Lg@9IqlDo*EZ$` z_MEB5x9&kL#1e+@IPHJsqhSt-3(JrK!ethz6SsC{Nrjti@1VSv)N#Mg;qyzN82GFY z26I$iY<{RHa%F66vFYjM&PsQ1toxzJa2|%ly8jv(!owl4?mtC}d2kSB$GeIm9_ubo zv=k?AlHv;-BE&gJ=yiBd^Yssd$R%!l=G~P;s7889d((9EU`E6ghNqgO5 zC~_|z^GBC8CBjD^aJ)n^TT<`eog1&U%r0@RPf~9gHzm+b3GJH^bey&XO%hGKZgF%x zCJAi|)I{QebND{z?eq=d#8s;BC{=jW0V}LD6SN?&!egkgDOr3Jqk$u7_^1*VVu?YE zq!No%nKzhId%2#H?fQ&-oStBtLIVg;@#?2;@}^?Ogw7*NJmuVxU>A@WToN}bePV0* z6VQIU_790h2G%fHx*BlLG_2QI_?k2zi6x>m?OW{(yNSC+2_l8@7ezMM8%kKPlkT(+ z1i{4LWMvmy2Ss_cUt-$u$}^{TIEsqH8kHMI8ls|e!o2c%$ zP@AqWyeRg0nX~ZURBUo$zv|6WKwO71w&nBat4?%XCb~B;FEkUpcVjOTRDz+8b(Mu{ zUYYZczH3dU6&}ay`%n{^95cDkD6D1My;r(vJfR+Xc1(R3>vV33TK6+II(E?hkmq z?sKTpd#-+|FTmUVvQvf)`zhWAwUyrRU?2EAK%N<0c6WV`@@6MR`U+-EWC?ntc-@TJ z=sMvd;3=kmdqIq7YWDGb61p672oJdQ+q1l~=J@;J#PnWvJkG*4vNuYZMgC>lXjM4H znel;n-2#5*EF(w zPN`co2@<<$F1CA(tkb&Cxrxysw`fHjjcSUwJ{MveQPLD|c&?wBXiYj?IV!}WqgOh>=>o>g5i+MISD{;B zm9$+?HB5d(;?LqOjq!ITCr6(_2(Pb`ksV7XO-sG@b#iJl#*rACG|UMm?lhJK1K_p6 zQ+ejFl)}3XM^0{S(TtemWoPBEf$?X$(#6re%jN{5>n}+cMIWo`DAU5+I}pe^K_0E@ zz_vaPuqg=MT@%4;Y{O>TEhWO4t-A!yo@9P%F zZe`VC5oVhJ?tAO+k)KmhBC-sD5g}7vbEyO>}ur~mYWF% zBbK%P07VKdUD_PLVyMSx8(vM-nEczrft@rE)^gF()Cqvj-c)?L>6SMmX3)%5Wyagy zY^a`>^QL0wu`F8lZ1LN{CDXRmv>s;ZHH~#I)Y(17#|u-=O^!d_jrFj@k1W>iDWXK1icdOlga7NT z{TfUI4DOuaH~2{!Anbu=rUp=!n3&h-lKmR}R~(g1qj#v2W;{D5CyPge)kI~p_5iEC zH;P8mUX&I6-BqI^bLWh@_UiAs@gg^Qv*Y)yt9MVv>xg6K;{DX00l_%M`Zg689k@5I zV03L3gFpO!Z)VXl4S&Zuv@EuIHiaNnZP(Z)muOL$5CfP5rtayHP&hvVsz=3!jl!or zC0hOxTnnV#NwVs#zVvVmPNKf_uu$bC+D*RpuG=oB3}uARn>{@Gm%0@6V`a6o@{{V1 zy3?W4k9ydU)SB)&eIGrOu1c+fmjZGeTn*Pqm!)=8XEvJK!hTwwt=bAR7$udiudqfVttdE7fWS4cv2`s_H zt=sy(&acRZ#Gx$d$no1Z*-8lf5rG*(|$LuFou@~@J? z&C5{tRWi)V%P`}sWa!At5dA6{mgi+y_Ej?U=4I&m@(eoE=mgn~Q1yEeh>@>&E5(z% zj2Z+AmRwCNQ?T(j>xlaY=c8qWG=b z(n0>1@~V_Hv82xYtZ=jG#DATJ=iKDoE&3E+Vt!EI*@QDpLQR5ij1^xo+k9HmVN*m8 zkYce-vD~Iuc7PO}Hbt*Z(RF|nTYy<79>m^o^3N$HMar<2b%_i17~7AP%x^O?;)pd5 z93~tx@`Vwqk3>RMdULZH_haItxCc`+6+<4*H`*)35A-MpMrGs-VFRceMkZ$;tj{g= z7p1nop+UAgMOaS5f(VEQ;ka@9~wwHDDn_a zv}=`x6G>5t>aOS~=slU?cOfs5WszO$FRs6&C9|TEdCaV+GJiwnZ;AP<)tOnLRhYU@ zqm8LKqkz3mW4Ya}7&_87tuIFowy9umbC{(d*LC#`KuGpU#(rt~-rhxTf z^r(2VcHR~rnS&*EpZIZ8{Q1-`O1*uTokX*E2XkR0x9;C)Ry4H6Y z?M)S})qzj;JV$4i$l;uNve~$uKxdiOv+FS?Y#pDtd29@U1oa>rN*sPuFT6^3CyrIG zxl&+&Df#FqYlw7m;_RMoZkpUDFf9-f4PqD2iFD-o;2`XGXmfef6% z83Z*-RVuy^d(~o?Ay`2JlaU<9)0?*1a@%?@*4koQuheZnK`Zi59?~k{gE@{5 zM1=rC{@=CtnO73f-e3Qp59FLVXP>?IT6^ua)?Rz9wG%hTt{l!OhoS4B%33cGHWJfJDDCT>Y3yf~e5IqPC$5vvD z>9CF{PP%b*-j7E8U#}e$=E|h9TJf_oV>b+w?cqyFB)Cq<&%SegdJi}WjXH-G!eQ3O zhp&(g<>oLb_@)FzY)5fj&u((XM$v4VNpsF`aor=4cOX_(%qw=8>3rr!Y5XVDGObDP zt)03pxwp16-L&$j%-Ww#oy4>bOTtCy;;d(tHGhIV$Rh`_!b^;YzJni>-#TF0^Jn*i zVlB06z%Mz8kY7ScL2;mxy%$+f)hx#;MnaVu=V5oSS|U4*$bmv5I+I_#@q6~Qlp4`n z`Nf_td$_l^MTP$o)0UkDhAZ+7S>MN4Qm^In~lLG*0yFRPu)I4wjGF~hx+j+{i8_zSfqdS5nnd3nn%`%(`RFFFqCZJ}ATN(eTW zKi)h=tb|YG4{o7v2CdiPmCv^` zQ4Zh&=J#w95)EChNE&%HWg)9UF$t)tlcWS0rA&H$NG6rymJ}vm?spDBHuCcK`emQUk)q_w&z-m2mruyZ zdhKzHY_D*kK(Sip1H_g+wGXlV1rSMMqigA@jcZ?WY;w{Hwb4~o5Wnv~$m<+^f7!~p5*%S2aR@KS^ z#EH7q_Owm6=NpU#GpRPx+!1N-QDJC+yfrf5 z)}EGlE&<1p_w%d`o8Ctq6)(X}yCeJCmDlX1cRc&qonuR5@YZU(Y&f&5H|JY#ihIiy z3zb&gkfKfk`;mfUG!DTwGl9k?XAQi;J8!ql7B!{9Y*Bj>7pLS=fE8p*yihqpZQ8Ye z1o7Uv3 zr1?W$WAs1Rqd7-IAOD{}VLkW!(_8+J@Y@2p04e|{zSR`;eC)H{RdQUILcrP{zgtRM z+p(ah%Ld^Mx3YDw8;z+hu$)qJp>9H!mT?W8JSut;r=@YL_1nfUJaAyp6SVIHVF!$Of#4uF@Z1uqMPKl(Y` zWajZs3&T;dRv}5A81t9#z;D;?A<)Q-?A{aLkcoixnc&A*mgiaTX)%^v>G7=eY+y$> z*ZrO6{?2!Q7r4KBxW9Y4zYE>pMegrj?(g32?>_GDzV7ei+~0=$_D5FY+%G4}9W+pZ z0U_vFW0oU5_Ii!AK_VVbtJs$wVHNL@f1!LSJ8Gm8sa#q2p|xHS0+?9?Z#?(*W`(Pj zxO8PdX=&M6T!iyzbtSI)7;9dS`CjiD;o#C?Vpq58-^GGSNujIbqm{Y%+34Es{pNc#j zCMDgM6&rE9nPyQ!@6~)-`zStovXoYONBo7S+B>|;K&8JQZ9H4;TO^|TReGvIbE<_? z(z{Bw?}rI9u~t*+VbzS^HsMWc{Vh9-%$tvR70Gxv?UGoP2EJ$h9u!t#EZEPCoOejg z^YUt|t!TaVmhP`NGO~{Oy+vlc*UGOmJx5GE>1*GSF5~nuv$wS#CGlYed9}4Ub3Cm* z8$OP14Yy-Y>5mJ~;I}+$tk1+z;eTQ!mTgtLCY&6Uj%A`si)A6FtUu|d)c8~x%hvcSSBHBBtydDY$TM_}aXzqp z9u(o-->isHr5=Y&T)n-LJ&6T9sM9-dhm1a-;((Ai-#_nwCWhTW#mcoQXb&pl+U&La z6wPaqsvvOLTsL|4%OyZghb6JzMe!~aRJuW>>>=?Y) zv(nm}=$(>p75jqLHfl2F??UHGLgVKx%b|b{V@yj%42KzGTlwlj^~S8+P}|4MyPD)n+!{Y^UX`{F zO6t`dgK~Ou7*S#30!eO! zmnXiCcK$cjplmgbFzFUMrAZ=zLl+*h-VXv6aC0i4__cUHCmZcJo!O-^p zME`hvv0MEFRlOKNIg~3EXp_a?1^>d;Gpc`v&)vF>WUY#l6UWExWYwSjU3xB6GpOB+ zM;89EpALsJ1aMY_#IT*t=EBNbT(`*Uhk7^>wGiuV6=s{oE0x)%7?N`H3`Avr3K!ex z67|_519`}!f#yIz0X$i-+Fr7W~tBpcW( z2#shR+a3PMA?${87aI>W_2(md98Q1AN8BG-^<}_%R2qt`kcM(XrKGxT*)h;qR_AGX zzqn`(tM6PfeC;9kQeNT|iO(K~B}@wBCJT6U0TO{NyO7mP(VkYHtmz~_ooTITqF-Th za;y-*QBvaK;zbGgP);DG8pr=BDsPQqTVOYeACb-&#gA6WrCfRC8s$^!jdG<|3&tk$ z1}MbD;V)lh%-<%E#g;16p>SC0&V`NLnyFG;%%l(0NI`4qLV6XnC*`tQQ19%?YG3EYHfm)DP;GeQfo2a_ z!GysM@mnrF3ymrM$Zr@NI5xALs4=y9*XnDOF=4_ERkbFYrKwc2bRpGju35BR@+}1i z;!|Nnj#ne_h#;oANMMmW<{$-%NvecjRjb-MT2CHEsBsCF>^Ajap(Cb(B!7#{T`wzz zg`5`-#{w-L5v)X51+Dkd16Yj`3w#KB_a^!pB>dUKken?`;i}pR?4gYJiIKur>@9C` z(V${a#Lvkdu#CwK8paCyunW%p8*y{Z@dqDQsF=tepdbu%)R>Abu;#?(waP=Hve}KQ z(dbh&+NFUEJlE(3E)^zX7py}Up@H&b0}9t}aeu7qFmkmH8`jXjI*a z)z)6}IUqpE=ulL%JTW;rKA(Xq1gWrdZOxqy{xb&E?MJ33a%q*A~c6tk(i!_@vGtU=;l7a z9~}68sGECZ(b3^^Tk1zkDq~Tg{6NJ%JOL`2HM~YcB|A*$sT4*Di7UXKGX8kkk;s_US>!Yr7jLll3>U`t7cAMp z-WUIkH>$)FXG|ES->BXav4FKQiL)S*xA7`LTV#bai&(wYG#YNB)8a9HD{-X)vf`Q_ zG1CLq&Y*ou8H`oK0q-1DSCSlkwtv*`fUGfjcV>6TxjkN-CXOV*|Wj5l_1K# zpN2pUa0-Sj@%Z1m(gnKG6Lh7uoho&0R8%?ujw*QdlA(>Y;%entwN3I;L_dejh~XtR zA6+~p;+BKzC9F-#zmTC2-kaJXQO?Nq2;S6W6#m;klmEtoOC)7Z4FfVM4Nli-xb-E4 zn&}#fNg$h%_~Wl!)MQP=;1V?y@BzKu#t(HB(o+2+pXvPS-qD z*Su$$C{sIu$5fTW8$_4Vl?$hXiy>OYav+)O;Zrg%l@0mR_#5KjE_~`4*)+DIJLrKB zsBb+`FCn0nP-GreTW4>zLR)b+U&VBtg2wQX41^G$8!xTo_oK&>-~OUE61S)LSvEh{ z)7iR{U9I;5w(_f0A#DR5TBVRUNP}7csK7b(7s**oxYLJ$*qzJM(mcs8(<0Ak6m3@K zKw@%a?rPZ1t!-iRSR;3WZZwArBiFQ4HJbRZ?77|Qqfaty;@qa`GCiBn4@IB(Ed@Gr zX_;2!7sya+HYaYH)+G2~z{#STt)VIPhxlz(*-f|C_FK{6J3e#V2f(~9WEeerfz-R!W43(7S((jLD)v5 zCFQs#8aLF}|Cf9H^@HN)U5-r@_j?#`o!nxCq&O_vR>!l2a_W&y-`uPJc&|Jqes-M^XERB8PXc&2(FI5u`CkA3( z_~07Mr16_>!Q#|QF||dC^SR4#y+;P~!)Yw^O~37jv$+fO=H!~*_h3chYPCo%K=vdq zORaC!_B4;W&W|@)4$<@~y((Jzh?*GnUDvlS&Q^V$g4X!9+T|wyGPtqeFq}b#Ge)JRtt>?o zy;qTu>57=IYGOxtNc<#GPL(4g>pP?2`Ft@%G$JTFxN~DeV=ER?CFT~fO$4K&y_f_6 z8PTocO1_U2As~fM#CwC8EA}X*eeM#S`blsjqUus*>N*6wAgWY~h|q{V(Z(H!|0z52 z$>=?zF5)-e#CAoa;9BrZ9<2lM9c+OqB!4c=v`UlEpRJ&^aBZ|^6bG!SctP4?%rY&r zl-qiJ3+C+E`gRz%GxY6n&{ImmDy~DgieMkc6+Ran&UJDuSY?@0)i@aUSIs8Eu4=lD z2lO$}l$tEw!)XD6RsK!a3-b%pBBN!&P$_456a#ZEq2nnsDjY5-aB=oga zY)^L=`-`1_9bmKtVt2F@`)!{IyIAgz%r$fTu=~(d(HgLs{1u}cGIL)O5zVKxo3Zmx z!IFbjQ0NOv*b#pihhx#Z{IMESz7(|hD>v7^M!5pWStv$COrkj5y4uenPaL$Ox;>FP z1l8bWxsGK-YZ>vVfMLwP5@LoKaA+K4lwo*hY8Ue=78UEK*E#?r0-=3aM1s&SP`a@h z2DI|3kV*Czi6e%4yd8h-$1=-TRPiOA<$i6;5>u(Rkuq4sRCa4y)JDamCDAo3!eON< zFj%kWjpb{MMFTvtd=KH+FXln2q(@Jca!WFnA#%}tP0zWN@;YgZQ_KorMgaxD3{jUX zvOuZotzhWR66aQ&xI41Kl$MR?le%`nS9MI;N~?$3%4%#6c#~BNjjZC*31bRf@yDCK z5?6^p(ApqcLKg_;>dG%um(CFQRn1ut2vrMpJ7-`RGVKcj(krQ0M}WWXc;tCx?n21> zx55l!Qx-XXZv13d6w(cGSVY4Yfa?-2!<<34YSFIO)PsTWbHF z2xe6$TH#k#_t4R+lbIlZC2o@L(#k+46k4$9&SCsx2n8YNL(eS43XFSV{9;uj5gN=W zvJ=*BQ?rf;)z~A8nHj2Bc%n@EVoEx@F?ry_X(eP{N#&L!PWqqYuAUSpJ)RdCrskbe z#C3^{lwb-t4OA+*xiY$_SPY|jCsVjn7iI1*6jyi=Ow51jWuS6Tc(W)O%zKnzg!&@q zdg)e*TgfBjhclL^@e}_O$MdBApS?e#eEw_N#6>=Qv)ZhJs~+O;>QYH_d7j_;yJ@ol zXpy#Bqy!!|gbxPW=oDT@@fjy0z=E$AwS)(9{5W5PHz=U7iKwm7jv73uCB5}nT}P8i`SiN#wHY+m6sRRo-xaPL9$e&`B?r>9HNSvm6L|d z>0$g&Gt2sn?Y~q$Iyv6DjZskG$hYHAvf6vr^;Ss`PZzD_7Id3J(~=;B=5|Se7rD1I zCv;gbR^d0+CB_C~dDTNND}+Cs%JPb-TPO=kD9Tq1eo8R>A=zCx4lFP5cZF5&(7dLRPS)#6{bc(s_NHsrE+ht(0%+EZD2h0 z#%t)8Qhf&Ti$HA_W=Pa}kjmZ%;#%UeSbV_wd;=xkX1!FY^XR0~LcE@O*4FB4PW@Pt z2~kdL&enWyY{Ecq?CL?j*w|8uP>hLha8h-Qze$Tsn_^MvW=rcd8SAsvo^&{JaA4gi z(Am!Fkkp(5=l8AUjonf0xpW8Z%H*9ZXMy_X#Of)Lb3OXfVC-Jz`m~^)m5znjOd?f z-1()dsu{}q4L>E`&1fK(26r!jhAB(%I8eF2Kq9sek_LKkoq(kh>gpjLwg#QjH{2gH zWj=<={V}M9fC;;gA6eW6|J)QRGVNL%YCa414pfHPim_%*0))^Wpy zdJ;vdHp!o<{7{4;XGk!VrHiQ$0Unz>MC>`GiLGgZll|77;-1o@d+(GC{|d>!iHwTV zq+eES;eqfgP7do~<4@myYF&BIdRanyFyX|)q*CcS?T>(ya#C;YA)R#|gI&#Q?byLg z?kF`DER>BGyWp>?XrJYr6$N)_?ZMJdWmDQkX+&0hOFLM%Rymhq+~hTHnd7V3v-q;7 zv7k;Yo_4`EpYr64zq!w%WF3VR(gHw9Qjf7<1C42O#9Ik)Tm9)0^K8fQ|!y{cO?4ntAdGFL6I?P4OU0*{I?2uyO~8b+3monXv@@1uVge6|p{-S_wu ze7EAvqVzD(nC{31d*w5on;ysPU zMA$cbnq*sw{8B@!NXdh9{?&z!M^mg&UG^ZSnS&ayEPVVEeE(aE6* zzXm>>m-Tq_mx+9s(`zJ8WttP*2^!!8pDxbe1j#8QejY*^Pf(^aX`o|PI0=bYYwZEY zNwWhMv9>LT}-A|}I9o=8B{ze29x^*A%Sts$@O zI5lBI0aA2LqzLupyY+pUQQtbc>DH%Qd8jz)Q=|NQ3Qf*&qn$jbkV?`Mzu@-@?;k%Y z+)gXMsj07*^?$EV4n$hvO^O=lMU8*Kk#i$+$3?->38)jlcoYi!x6sce0Kj~Dm5ZjI z0jX{uV?H?#(!T8T?5o&^-z+g&ZRp>rHGS?L2e*b=rVN(m6JKxp#hqE7b(q_S9Q}Ew{?^l1PfS3X-8sAUcmn4&8;9F!QYkwnB4&I&pLbIat z7!4bt9SJSn=NP)1ji1gB}i$6qD<-`pchg0Y3p1pOR>J}UI=*JY09x2f;n z13yM325|~#aN(c(HQ;wnqJ5w{R*$p#JNMr;UMK7RKE*}%_lr4SqrZteHS7GWRzyWfhN}yA$4!T&3rq8pXmVGv zc82szSKy`+6a+UNDwTK$e7wBa`6Hx@@Qq%FxOIlJE=Z%~zkj2UwSY^vD7o!kmj#H0 zITIx^V}hQ#;z0QxCm>Tp!}~eS%4Vcf!81)UN~uM`%$L6FQf0hE$wc7KH&B?JC!_+< znv^;x5}PZB(K-dp#AGcZ7nLLHLyGpgm0rRYsYum>ti0PJx`(K(e4I@sPdu&w?|(GF z@A_dUz@3m(qvkA-tG)n~EQ?*BZs%4Qg>rV9(y3IRCRa~q>88KIrHdLb zE85TQNzQFYRN`f?XMNeuH(`zt&DK{-DUbX)zszp+)(VC z29A!RD9jK{>Y@7zMd3dvnWo@>Jf?c}5|?g!^~CH>1DV941OAWJnWQK;nBmR6{if}SafE++! zZ4Q#&++BvNX}9omR`(S$=Z?wBC?IoDeR3NtnrCZdW<@P5<5Q$5rMKwDW zT^_q}QFg(v%6h7!iAV*&Hd>tdpJ6xX-u^!C!yzCLD=zz*gtZc!EoKFbKNw~>mZQ9F zR;5^d<#-PJf^Yu>>|*@I^uwxrgP7+qUy-RZxSZVtOj&a=Wht|jvy8_1VwQ}uwN=)d z9qXOnBNm94A~h#&S`9y?i1Q$i*hMrRsN*JSVd3-)W#I}r{~=$n@lZW9xTs>gUSDRK zcYFMg8t+g3oAGXr?+l9>TpiXUhLL91nwYr&s-n6(hvA$_Ov#i|#W*uxS2MX{<4RRz zK9-1j1x4Ryenl%u!w1IF#o%U%T6|0ac}!IClw2(9QbC6hgA?V2ULU8*XE9~>17Zq% zOO)SlgH*+*NuGS8$GKPPXj0(Qrl3F}fGr#r_)C;N`ZoG#F2JM8+^uo&&ydCe#KbP2 zLPO$)G>B54+kbMw)ZLs!ZnrfrepJ=`V=iDf(zRw6!8pV^VvN)Nr}o^1@%^%;WvzDp z##3QrF1TMN!41uIK|LxDgQ{=LlWbx~AN(TSy}gVM-FtUtw}a16zavAPxaeP;Q-ett zr0g+W>7nHpN27;3k46sEUjVGwJKm!`@%2QM*y2<<;7*^pF)#kVOwO zW!{AYNvwBE6+hAS-^&HG-`TZ(mnvNULs*_8M&%^`A(hF(_?CCI#GiLG`WW*y=;Q9Z z1V&h4CEH~0al12ELeBqn&M6#$U9v#Y4x`}+9ZGY6x>_dIXA3h%+duD1+2Id=H_gXh zp>b!W0Kz+7hA&CKds^Q8mUn8)P{J}x(=UG_FD>~n@+CfryU;k*ex$D+6SMejc>JE# ze$N`eM9^SiKZ}i+Y!kb`@^x)u_g8){CiXdEVt><*gDNB4-r6(~9nc0pz5B zMJHxpT%S!8wr`+E<1k<0Fi}*oUHyJ|Rd>c``j@?bJMY7G0AMF@QIM?A_={so=5#Eq z$%xaM_3lcL;63*3t{KQ?msl7ff%PiAS^S0>P$zwwg<(tCL}P63Vdg5wh3#OTe|a(^ zz2A6xy?Y=*(89rJH+#zr+oG9QV4GeqUqn{A@zmys^J+($BWeq0lHPh1wQVuWTg{e^ zJnCpC`koE!l>{WcR=YVdfbP+I$k>@7;wQpMbsYB>yP3{%Y@!l%m8)irNBpffM_d`N zt&;J^@5TeM8{4x!?qQCYw0%LM|k0UwDvg zww6c5Ov6Q7SWR1BaCgFnc$vj4wzT^WyPn*N%M8vxxpD%vIMT(&PIWWaiFDU7b~y6P z;8m+ip(Lb|I+ zGE9-xrP_O4teFvbJdRzHX%s@hk%?mi_J;q!7xHN!Hl0&sKUX0E6Di3w!=D)^a=qD# z7l%%tDZX@nS*@l!xi=_?DMtLea-75bktxF-b|JgK#l&PeAFG;XR8bScpv{O*63oYD z3{zEalr}|MByWA3Wha)_0mhq8%IA%@t89C=(W{*5uO;q-3Wzqvw{1o0Qs+V~$&TMxs zazt-`}5;OlQg1(E~iQdm&Z1o^4qf8E1F#G;NpbeXe+W=2Bc?Q}B2y_h+${(2 zQs!#PDBqHx^$z>`jr6Wrk#m~I8PVPVL}T^hIy%+QF{#so9O^m)4B-+ALlUSN@+FE_ zL|=zt3ugkjGh{1RPba>|J7!PNa%6Y&a=p7*tTG)+{GGKq?HZG~580f!nJEry+REX> zu)VQ`?j-Tz>!QP*vMHEFHR@CwELX0z`k^=TBfR3rT%?gO-IyNOvQp07< zsFET)f}E9Wj<;h2YZMV48EX{AsJN9!!W|Pk;yb_J-qA!ny%L`0h~sKyfJRIxRDtwK zeWJ5G5-j63q^yxJ^DG90mVBnaFk1%hyxU zwX%A$`;OrPhi+|(X8$~a32vRPV zk0KJQH0LEwf|ZYHS}uT5A?VX zD@?`|Ch@;i^UtHsuFK4%Z0mS#b-c%Zm7RWPykE0S5S7gyueMSqGv`6XW)9Krca-Af zfgSM|UX)T-4&%-6>^HwwZ+sj~nZqb@Xcg2Ks~Kooy`Wqnvkc1h+uzM)4UA};NXq=0 zMb(^s<+tzg5TtEd2mQF5_zm9yW7(*d-5gEX&p!VIuXUl_{{-^UP2=1&W5G5E0UfVK zp?CQy~buS6F$FY=?~~8JUoexESY;j1$W; zH>g~XpoEj(CE7E#uP))_UUj@CMq8F;_Y@@VNDpYkf2uy+$%UE&_7f?JhBEb-j(2;8 zFq8FYlA;sk(po{XwTvioW$!3-Tg&wqAtQW^P+1$-Civ5AnOhK^$cLD3QJ}ni=9DNY z*)mDRh`t8kc)vnqI zzB(jOaGTmJCp>o<04ok!_Lw0|e(7@(ii&1$JzH$y^PR`(lww{M z=SPw2(1?DfX);gTDR!~UV|<-&^%TuQeG>|~hctBtZ{Y!9_2^Hie4^7xdx>7k3n!Kv zl$hPKVHc>zq2rak%UeH()tor&G?V&jPwgjiBV#yUGE+{l`wY<~!Y}Z#QnA%}Fh)a9 z8Dcx=@wbi}M(>$GM{i;Vw0j6ZJF zGX84=c0P%Ln>}j!)X!lbR(*TVAk!XHh{l(ze#&~Te$I#vi1>cb>@RRV8cvt;hu?Ds zhj?-JIj8nfRMnC4->#qY4Jm&G<^M|8SQ|ied{lf-sp&Z&W?_%G$>pk-tcU9743zTM zQQq&_Dr-!?RfoNWVBxqi|3ty=4M!P@zU?yEo^m<(NwR{o`{r@!hJbvQE@iI}@g}P- z{GS&nq=g$nnwE1fd@o~~iMx0WRIa`zoJ6{yI-lk+0&~(wYpRUaR2MPfE7I+26;`XW zXtFeXhiKaA*5WuC9uQUJx6aqm_%b z&&7pkVP^d)B`galGZK|mfhWx+AY06V?<3tCnmcobF{C?9j&)@AFxbh5;DQ4X8TMjl zH}}bjY!5h3cjud37l>}}4qlsrUg29-f3LH#orV#hKE#p)4ZOkSsJh-W>597Qnyz4X z91^CaJNJmL_C9sVT7tNpo06_GNes?Kvg>XSkl@jPN}lUZ)!-ry`V>RbZ;L^O4KlP< zP9GxAEFdq-BhzJmSo-uBOAHTUX~3`Bo`7Kp{o9_z>zYNzvL0@aWB2wa^X~%^j4-l~ zv0yt_l8)IYUp5bn+?*dVkwU~NcI;3_(?`L*B){R`yW&}-*7kDXD|I4Aw5Qk!8J=Qn z3pH$?J<)j-U4nq4QNZ0e)YsINY`;HWjle-JdSyTQyE1Nbv34o8yF~eg;R@w zrWVsN_EtrKlGLbzEm^hcR%8{ZnsMz0n$hOzWdHBL3&XvuEAQCLcEn>iDy!`XnQR2G+R6+QuX&oU z#o{SPfWZ6Og$>6DhsqPz|3aRqst5w8wx$>Jb2!aeW`CuKS?ZTFR)4BFs9&^pcKgm} z&5Z;-jdxJc+6?A90zBXU|Tff$NsP6e-)b5G0Fcw?pIhl#6@Fm%+=XgOObyORUMW5WvVKKj**Gh z{S?U2O*!`|gl?}%O#%5h)8ru2;Bnbv5YT_4K=;1L$N8w=u98N03rv-wxi}h zZlcM_Z&S%Jp}&*9z<&2}(a`(cUUixLqp2!Mq=JR4$^Uhr&(%#O<|^p_dDXF?_j%rP zit!!)e;fN%?B^U4`XA62pzq+Kp&#e=stfcIU-thr_W8Q0kLD=o-@fvw(3^HaKF(9F z`N-*oceujBWaNWn2I)NZ@P>-7<_%HW1=0a2NT;|xNJ6T3gXArr$Z81Ngud*^@U7)^mhrbOuXHc|CD41ySPYlXr}6 z>TE7>!&BUL;D((iuX7FcunNf2BD&?U*tO-9U!&nk#?V+cL3!#K%f{w9zu|#&LXb_< zi_kHRh9*!#N>9{=8jk2S5%IxA-Um;tU)5262p`2ZA%uNuvCDy}kjsR7gj`mkGZ4pw z&Y+B9728o9^jae}u@priau7$MamZG_I9q+OhA-GA*drPS%1sdr2I9gzECJNbn1_8d zOT@rzUg*ISC$@^U&RDnC0yz>-Xd&j!kKJ8pZ3}pIlH0rm8qu_13Ngq%eQOdVOG zo!R%Ts#1H8vQ3JoyBl4yIyoxB1bXw0I!;sEHT`yVnJjgbARXZyW<*X9RL8u-$H%I7 zv?r&`YXEulalBVxxBK40g>k%kVrn90GGMlK3AAkAUb$M9Z^9V6E@ z+YnA zARIesQbxl>NcI25F|X83zQaXBG_(^$&r!9G3fo6=x3l>r<1<%<7X+-02_i3%k{pg5 zu*d5qfJB|jI4nDfr6e)CN2+Qs$s$xD=F=vTjVwbT)SEQSPX)8_sTPrC{jW< zwAD0?uH%ua7p~I1CNfLceFGQpImxZN6F!{>q-wh$d^;V{yBUrgcKKCW@FePw`i~P#S<4siHU6X(6xqf@(sp6^t zpTWYjRB9Jrh8etf7767N**=SiGj_Bz_s65d=L)SukhxeYmB%MH{#@roJ`n=LVZD3$ zIzFU^CCUXfemXvz1QHWu^SN${BBasBtmxI5s-k6FsAzGgirl>~^ocEW(v%(FGghz? zS<5egDR6-~lmsSpNfHp{&nfJ^Sm&WmZRH7o`H2zIwa}#%+Y|T67qZo;UGLQfqxu*} z>(s~UJu*T*Mph^xA-TR%7)tvD>-jC_oV~RQwC!8~?Nxtrek(gpazV@~W&nX7iJavl z(l%2pDBXiqsFD$0>kY+D@BgHu19L@Wg)BrFrEJshO*=9BY&RON-K*#8_kED5ZIKJq{OJ$GlKU zwJ-+6OXR#*Tqua3S8U8(H9KRaC$f5S`4&ie^=^fvr3zPBb{uf_UuKG~oLRK025mgj z`G^=evny)Q6>Sh~OSpCB&MH++aH~r0=R1GxT7_3vaTb>@RV2<=#2k@U-E>DXGk~DC z{_1md`YvD5@Eha09d~C$*Y;avSzz~ln+hEn+_ddm`MY)TKN*eT6dzvrRKljz4feHlEg>P>kFS z_(zi5d`;XWm>@O-nhLkE4JC=bteto;HRC%W`zR;VMNTk7@M4b;zq0;ivEC3NQ!7Wj zIy&CaZ!yrL=f%8*escN5yu}tR&S)#eIquZzj{`A zdH+<(oum2xOcu7Q_vpojN5AVq_hL6q1*xr3ZDl7;{L(nkBqmw`#tn!)lT5W8FDsR>q|-6MPg9>we_gs*dAlox#aC@^E9X-6CB ziDE;koHguFOZSpFYjjshKveKE#6kSAYL_5CM2*HRRc&2K&PZ?UdxfagkwfPg3pQch zNea~E;J!4ciU-EyIGoj#s%6S@0FWY68TIGoUOkvO>BS-PT)XlW1INI4^Dm$anE~r* z5MyHG(8*Fuz^JYnqWNdBPPkJl)hzM2l`4(WwAN!rmR&MV1sC4$kK9+BV>G+~2c@t2 zSYvfFnKG@uUr80MzQ4#tJr-R<-OP4xe2vgb69*>ZHaBo|Y)(91a7j9p*u+8Av8qyj z)dyncMEqV%d&=@FJ7!Fd-}eF#xVd$D1B5qnUtvjjgsve!9@$gU+qaw(JvlfOF+#7z z{9UhiBEw})2ZNnSoz+6i2i^BL67yPD)h8Y~Fzmj7J?Xi~!845o4*&!#?vLMxz~D2< zygj%?ass6!mLdPn<9w{ehQ@{40l|jDE?y3*1vExQ>X^>0>ZYF&y@OY(9*$f%i+d4$ zG6z8&e;Gdoh9J-J@*r}cBJ{0!2YQyWVvi1!2XmLRTmLQYR8ip)md81s-=kyI@q9UG zse$cl4htzY8pKkf8q0S({jq97{D4R=N6sJhf5PH1yv(xa#|>?n|oG$ z#*2vT**vL!Nk2V~><36d4xMRa{VWfCjY(-LBX3mGL1mmyged3<-=+FZQ{y?$iOGkH z;E3_8p%bFz$HosgW7RF~BF88@TChQfEN^k*!mb#C>VPyS!FfCd*GyroRNuXY=^>xi zq_&So+$H&h@JvdaDCSg3~QDHB7zU!LNU!+QvyT>tY^`4|XrEUwk+PRe$j0QOr z65VVeHPFIV>83Cad#SFI@HOEdISaKa^0t>^B6I)3T~BrQEBNPO z#rI%l@j%{FGGQPrFpN& zSCUFk*mF6+cFgkN+dziB7`#R@6b^H4qk30A=F6?Le2(^@ffSlLxmj}=h zDy|i*R{|Y5i4jT1zqwYUMQZDidRW`B$;$B}-*PuuIbCFj-e;Mvk3~v3yXpKK8&!N- z(@@{Sqz1KwA=DbwzFXALK5%PNgIYI2Ed!cev&C}l%al=L4z{zIa=r+r;zh8u#cXjJ zQ6Z+t+%|~kL4gOiQ&t`9H4k`1H*lZ2s31($2|cJcx{bN^9z4Rurks=TLoa=x2G9`T zw2_S+8xmoRub~QMcul4gtnXDAZ2kM>wl2-MXj?H~4AE?*Oww4=Nbz#ucz?)&UjG83V`*n}#si~Jn2XZaR0DVIpd z5>Y{f+c4ddvDZw_#2)sDwC1Ahn%o#wd_v{a_cXd#4@rFLMZafsalrqZ2Cr-U@*EemqsA}u z{+_(V4Gt;Z*pwQvy)7(kyD#{;3)9 z%d!Ioc5l7mXyadhwDFe{*t&~fmQ_;s<3Co9e==bUeJAD14}=6VxG(D$g`v#&_JIAA zupG&os}2l1O?qqh{V^8?^6&+EAl-w5ApEzp&qsrgqvRl&B))x?#IkmZXYO48%I~TA z|G2@kxc$#>GRu;n|7ru$&5b=$xOn^nL0BsFG14l^-Q0I zUj6CW2ZS!asBXhBKdVcR^ZR(%;r0Jhe!yIO22zd-d)c-e8mC2 z^0n}3>6Z=ia+G`+5hrsY6h)8Z$1M!x-PsiIe4>=vDy7t(?T?|Fb*I!4aFkMN>qV&z z-R37{t(>%e$kl4K*AWUn38dp+K1f$YCat1HGD*1FY(4ozliDmN_F8Xi@ZLgKb;R2? z-SJoCkt~=|D`yczb$cOJ;znKkY2GF7?0!xQEFWA_!teH2Vw5Wkv>I`DM?MI<7qV@u-XcvbRgUFxa&sF>$U4OZu> zrjmANLa5@; z_0g44qwy^;En8OF=KgI+MZ%Z8!>Cl&bBO&VL<=su%+Bvc`FgGw^GfVq?yXwx+BXez zcd`6-K9W^MD&w>O>D;;)|8R_zzhhoW%HIti&?{oM*HW^VKXRb7_7w3j=E;VDXQRJz zqY?R&z&pZMZ$uVz7vOMDK;7ftzdk5_`g(C6`W7lkqozmHaU%X2OBx5Fp|ju7!hg2F z+2jhp>xZWr^G{NZzh;*2uh=N(y`EoUEE`nZIH;tm@%&Zej z%&$;Mt~|=+QLa4VSEwXU9_8^UPaZL9EAt6t2tVz}k^wH*1Q+z92#M@t_h_l4m7@ z`b)t*MoFI%+O7iH-0-iHvDcv?e3jo%n(0?;6!+)<^~J?})t_f2*Ym6-pZ|g4;$Y=# zMzj_2=+c{nam?%m>;8dymg9W^bisv{D>|C6ve&FPV^h%E!fgqHCN}szo1H}zs@S(r zEvhlb{gaOzIaD0`;`>44=}&{6%>io*%529bnA?vA@t(=MKEUzh!OGRzjDYA{qR2x6 zi8=OMkpV$+e!EXUMI0lUgDS#^nr2iG63D8}1ZeLNIXU6QMwDUy+AkW6(+o_eNeMxMDe zvpM_+6k>%^M;0IQLr{TjqS<*h^?)DE{BS9&Nmy-O4XVQ2g<1LPA(``_sla(cJy%@> zO%-2%5j1rbPfMNRz2}gPO1ZcK(nUkR=b205PN1!@$2O`6=gLB(T``di>=_0Pz4s&ddo| zFS8O{9{&K#oY02Qh$K^r9LhB!Pl(h%Pv(uM9iyJ`WNZe`1|GW#L78uwFuP=lR|ocrZruOy|^^SRwCK4BJG8B-$FHd zxJH!D{CR|m;Us4dxa4Zln657?eC}i_a+HX+2UMq?;>(@m%;yhf5ArQLlbmNGm8g%{ z_RdL6IzvvcAT-a;qDJm^+! z%0t;K;GtAVxykZqs(y6A59MPUn`_5_6CM;WRR3x?itOs7@nb6=v;VEstuG;j)e5(B z$|if4_uy5>fU$gNVz-^`36Sw(V8FViY={vZt>oDqKoa{^*%IjhXZg$s*rTD%J0vg0 zEoD;!*j}fbu|JkAlJ|C>vt+-Pxy{<+YC0IG+-XFHB9a5Khs%V(0#sEmMPm(RvMyE$ zBft&EkdukVzyB>)o+EOq`{wwK$5+m*4pee%&Nja>`W1YK%C$aXR&JO%B2f9h5&0WL zN9lY*K~b9Q`#j!@t1keZM?%{Jp8Xh$t;2~MaSVL}mHxXadI?x>rH5Pc$4Gu}*`QDc zQc1><_l%(L6iI_mVoo)gOvwE zCB_3gIm&M|funyjezcj}@phl#fy$Q9kkK3iJG`o) zuENAplG8xI%O(bS9xKce^u7ahSMA!)>!_zuWBxRNQHL>8qEH^x@IXp?a-Pelgc;eE z<9K-{fwL{vp~yR@R@HaxsQrdCI)Jc{6Qu{<$UCDFeOun?QS?^g0-vl{T3X)kQC;*F zW%tzfm9n^}7DaZBN))xc(}z+9Suft{+44?5$`!p;w9eX3R~w{p=X4=Tp(;szm!v8o z(0b_)IBw!P!9IUz&>nPRdWiib|1p*Y6iK~2b0iTe*5UM9u|J*P8$D(`g5TlLPPFO(awW>3(7B59ev2H$fcb({2pY( z;S|B#1XQM_Cs2R{SlA?)eKNxeo#_B;dRT2dtmjv2gPMmx$i(?1(L3Ndn0)7crM~CW zfYmNjnRWObWy9r7eQlItC1Z?Q8C6MDG;xV}ND^U|@P_ z*Mh6F8F@jC44hF?n91x`oRJ_q;VG3HjL2Hyg7gKu#tSYhe7LMpFzm8I8JtpKrOSCp z##I0QH_{{qC7ypA>~R0gTTSe9`?mxtKk*x551XxW4s(ZDegt|yE?r)d6@|ttLjHYk z8O1>rco!Lw-TV-$t}yNIb$Bn%{|y!(~5KSbE6CmdHP_JT;L4E=B;S+S=r6*a-i`93XO)!5?noIb@0>^8mAQU8vZ2 zU^4+I#OpKce^;R>YeQjU*_^@-VVN^b`|LuKgSSm$x24T&GiTC zjp$E!?6)T!;V3GjLAI&zOY$DBwpQu_;rn@cn3thByzqbNjqL2{ZQ0o)F(VUwRXLjf zvdQ!T1f}_J=m#sf=SMw%jrnJRmK8#VN#1)R4>a#xp?U8=bDRR6ReY2vi@bMg;#41g z{>9$N4kOXa$2k{~9ix0WaklK}5qWP^b*&*MjF&>mSX*;q`5u$fZX z@GAPn|7g$5X|f&0_!S21{>RBpX}~`FIK)Ec2gvV_1D>}+m(s*gX+n|Nj>4Rr%k1+{ zQmOL1Ma*DUw5R&*nH^&;zW!ub;%6bY?DvoYATdg)ceLmWrj_79pz<9fB3Yx=w`2HL zW&z>}XFa7eVM4mx`@aG%Egp@1nw?H`W7CHP4{(M;R=PkmYStYl6 zL?!42p}?Qvx?4n4e?}?ApSOhI&m?uE)O*68cl0S*W&IQW{1GK1J9@V4=qKe@6(y{H z&cnMJ{v3cm``(VU8@1=#zV(szUbSaS!*55L{}yRKsrFRc_e7-q^t#^gvzFQtrLRU_ zS`#_kQyWCEM;Xy?f^A9MKq@%0t-tDz9L6ZD1lv`jdHqU_&a5%s`up;l=Zr;P-aj5Z zRjvsg?=_z7alsAOsu7-$8~Jp?G)^ikgH)=|>9AHdG#ibw(vBSTg$-vR6d_d`(Vg5; zS#GoOP?L94rhXlX*mHoOMRSD(YQ*I0J-VQW+UJI(cnU|GVYAo9ch$|FXDlr@&k`ZDri36qY9A&T}Q=TQQSHo!0OGUUn2g5QQkNH_+mz<6LJ-!Mq|3{nNR3{nrj z9`(N7d6(XB!?hDQqKOw7Lv*nkqC6gUGenAyCWq(}tey-}K0|cK`9mkXT-pUMEZh{v zLuY5<b6 zCUa-nlk!p4zO26|kFIREXN@yjp6<^$4NdGB{>qi1e(1Ou3!6Puc+bbqNtENLN4&7) z1_AXV5*UW|wv;FJM#{D$zu7y(AYFob!AkN?0Xxm`z99_nmpn^<(iEs{7k)QR^Sd3w z?*I=U={RywbG-i4CA=)j@z_F4^cL}$7$VD;L);bZQCyFbhe9VA%f2Jx0p2LPoqZ|U zr@E*a*>buZL$Cv}4(Hp!I;Od3kM+_eit~LZsV^zMS7a;@A9M6r|Ni&!fhozEVOSp{ z&ejvBXha4w{l!T`wid31Kr?YL@1PVnq7Ms-1P6arIJhRs^sz2%aqd?y4~B+jFnYz@ zZx>KcGnSp8*!C^}I3j?}JSlOxEWbLW(9G?L(PG+AZ)z_R9{y&a@`xdk=t!TZqQezKQ^(Cj5$N>A24=0_Tqt0RFe#jNvN9d|)V+YX6tlgmO0PHH+@lo!BOZHJK;Ys!-PjJ&Q;D)=!KE%)e-z9ho3M?ilc)`z7zB@5AB|RiG)ueiiv}Hqj9E_e)x?v#}j&$XU>_3>b%+k10&; zJP(q0Py~-n(4*{9Y;*H|qU`<%DtT-AS$VL!z-Yw__2GB;P`lqCtS8tbhp@dv!YT2c zOYtNmO6ZInR>6ifkC71o4hJiDgi0>6&n9i|OSu%d>I@H~o?Zg?3sfEs^)r@DVf9Ep zspJ}XuuQ?j={4|iZn1EVsA0X63*eJs=iRM-$ySU_6$XB`ELY$qkt4lkVknv;7RNgv z3~YlU1Hlt3E;Dl2!{SE*6;9)`G4*rK@Su(y&%Ga4012Q&w+K}3Fru=)aL(j~%wN&9 zh6vJ_P`99~1L{fQJU2j!K2Ypdl|xne+y}rmtEV~GEo4I*lKK0L)5$?rHU#(d&#|4! zvUr#*izf!k_on-*tc|Ll62$N@OTt|+h{Cp!p73#^_asV_{4`Mch4H{tYLdq&&3$Nj zl2pt#r5b8&Eu%%Lj!v_{XlM>|ZWiC&sJ_dW@ACQX3VxEms;sJGz!{LAi3!s*N09v2 zhz>wBp&>T(<*MQ;^0~R(&OayU*^wfF*~dkWOg9=t0y*yr-^Q5KiecU()S!|m3pE6w zhMl9Vy^&pr9}FTVnV4kC_XNu0f=o2;luq3XT1b>DFGb-gjYR--o;f79ka3Ktn@ff19^ICDE)ywpk4?y5eEVuqWJqz z*2-L2GZYADE7R7&fo@?J54loj1d-hf8H5(oOkvilMK4u}c`&mu!uw)Xc(*J>uoV6i zBiI?_KSf*A=0ZOEXVGEnlX-_l923F-n5uvFIJFKLZ2#bYmOlxhM-HD<+t>cV-N8NIZLSIMCsV?0}ZM$RQSl+l;yD!xD3(0J?bm&tjLs%TAz%yCxKp6<@)rlGvr zUNW6?o9EOfY(=b_*(%Xz(Ijp_-AH$|lHNG?;&hSqv|OGZKncrwdZIkNymQ$idHO14 zUHQ+PkfS{e>*a>EMkAq9EU3=mfJVNP2Pd?N z?VUHO?8=E{MneNXq*$moI1u$77h5TPZnAVjR_v4>Ev4V$M^@v^NqhQ@GSdc8eJz2N( zdtK+!q8U+oiY^^0QhlCS7QQ`eM1s6_9_QQioNE#R)C^RfP#?cNPIm3DQNm|kP?Q(+n2)DKhZQa|>XR0Be?!19Y^1NSjEbOYxN%WmKn-u&4k-zFP4 z))HM|Dx>rxAG<%fESsTUkSijx`Fp9T?{>+YT!G!WH+#=3jkB3fv*^W zmnj2+V#)evr0T!mrtJE!?gGGJo_r+$x9bLmB^wx?ZlDtYr|>3w1b!tAd<6hSy8g|> zT?94aw&0RbCjjo^P4)|Fha5`_Y0oabk>8k)Rb^U{r^?!z6 zfd=3^odDRzn`{8?mHNMG4(z570Ib0?M9t^LsRqvL)WDB;lMTR0Uju*zy8b(K{h^cG z`E_0v`9#+<^|Lsem-30bvL1bi4Cxq9aI==>f98u$Qd)SHQlQd|OX_tQ*Gt?YtI2=6 z=CCuWb9;}d$`{|HE0?otI#tdST{(3WkkKIe2+euxNBzzC&lq>kGzwHSE1R8Ki0>_0 zshI6jzEk>*-~Iu6_pAYqqVa`#k+K=CcQO^hF3|w5l@>&7u(jIw8|qONR`WDV$9d@j z!OKVgA9e2nA61bh{-+^<1OqpWgqH}722E6i2nbOgX$WvzJD5>K92JR>42(!(KM0Nw zI(8yldU}R=xU;kKSa%-3acAe@JXX+ANhgr-7%{+z2#O#IX<9VENC+tX`<}Y@raPds z?)>(%|Ifcaxv9E!>v^i`)TvYFoGLe~{zFiqDu#M;R%8>GLKG?3kaZ9L0RAJe_y<9# z(u8k5ix0q@k6newJYW1m>(|_r^{Z6Yucbn2%d*!)EqfxE#)<%yy+@WkcInXjtW76a z;FC#XM|mZ6)`{3%RP?hJv!AI1YBBp46`941oj(Lj-88HV3rX6UTzqAJLmUCg;`gMT2W<{Uyb zaB6-C223LxLa5>bcq6g~%dzKwBaVB@J3E?p?W z!t92cjXMhysVD2mCfA-er6Uq6Q2xCctc>{m8HofaRa!GEtwpv311b#fwpZ?{}~lWQV( zfK}5*vQMe0?4i5ONfu|V?m=bgy7^peL26|v@#w)u84U~vt zSEO5LFA1G{Ve-GgYL8#tE#hH#Ze?#t&KC5IL~{OsXtvdVTUqfH_RY<(dbB5R{E%^s*$X!Cj5p-56S;F#nf^Di zJrLToGKKM{hbJnjFQX-nz?b3;RXe%5D_n-Ep$*uRcVMOw}8^SgN#3y73R;`6;bFbcVPfDO{DQhpXTa#^m~(0Olhw z=z@sAOpy=ynkTYIbTG8~5;aX1=jFJK4@w=M`0szkoTWz-x!+$XU~3^-U`{gh1fdKA z^fv~AHU0fnw}~>9@Hzh~LrdhM}js|*^ms_K(gC-Y5} zBGW+)bf<94K=~gk)P0GF6Y@zh|B8{a%^NITgMiM>X@1!6KJ2!f_G|9&tYIma-|p=*Z9=`+XU1y@mZ1%8#!A4Ufjw_N6nY9xxjUQQ`