From b66e7e28eff863b928eaf2a76d6c23c775f69bd7 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 16:54:23 +0100 Subject: [PATCH 01/19] schema: Use newer draft validator --- util/clustergen/cluster.py | 4 ++-- util/clustergen/schema/snitch_cluster.schema.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index 7c48ee92b3..34eb8e2dd3 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from enum import Enum -from jsonschema import ValidationError, RefResolver, Draft7Validator, validators +from jsonschema import ValidationError, RefResolver, validators from mako.lookup import TemplateLookup from math import ceil, log2 @@ -38,7 +38,7 @@ def set_defaults(validator, properties, instance, schema): ) -DefaultValidatingDraft7Validator = extend_with_default(Draft7Validator) +DefaultValidator = extend_with_default(validators.Draft202012Validator) class Generator(object): diff --git a/util/clustergen/schema/snitch_cluster.schema.json b/util/clustergen/schema/snitch_cluster.schema.json index 4e017329ae..2fc3ef3817 100644 --- a/util/clustergen/schema/snitch_cluster.schema.json +++ b/util/clustergen/schema/snitch_cluster.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "http://pulp-platform.org/snitch_cluster/snitch_cluster.schema.json", "title": "Snitch Cluster Schema", "description": "Base description of a Snitch cluster and its internal structure and configuration.", From baa48b658354efadebe290696d5fde01d41eff71 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 16:56:32 +0100 Subject: [PATCH 02/19] clustergen: Add `external_addr_regions` in config This allows to specify cacheable regions from the configuration, which was not possible before without writing custom python script which is unnecessary complex. Also gets rid of the `SnitchClusterTB` python class which modeled a simple environment with a DRAM --- .../src/snitch_cluster_wrapper.sv.tpl | 220 +-- hw/snitch_cluster/test/bootdata.cc.tpl | 6 +- hw/snitch_cluster/test/link.ld.tpl | 6 +- .../common/snitch_cluster_addrmap.h.tpl | 2 +- util/clustergen.py | 4 +- util/clustergen/cluster.py | 113 +- .../schema/snitch_cluster.schema.json | 1182 +++++++++-------- 7 files changed, 771 insertions(+), 762 deletions(-) diff --git a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl index 90e10b9851..024c6a836f 100644 --- a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +++ b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl @@ -5,34 +5,34 @@ ${disclaimer} <%def name="icache_cfg(prop)"> - % for lw in cfg['hives']: + % for lw in cfg['cluster']['hives']: ${lw['icache'][prop]}${',' if not loop.last else ''} % endfor <%def name="core_cfg(prop)">\ - % for c in cfg['cores']: + % for c in cfg['cluster']['cores']: ${c[prop]}${', ' if not loop.last else ''}\ % endfor \ <%def name="core_cfg_flat(prop)">\ -${cfg['nr_cores']}'b\ - % for c in cfg['cores'][::-1]: +${cfg['cluster']['nr_cores']}'b\ + % for c in cfg['cluster']['cores'][::-1]: ${int(c[prop])}\ % endfor \ <%def name="core_isa(isa)">\ -${cfg['nr_cores']}'b\ - % for c in cfg['cores'][::-1]: +${cfg['cluster']['nr_cores']}'b\ + % for c in cfg['cluster']['cores'][::-1]: ${int(getattr(c['isa_parsed'], isa))}\ % endfor \ <%def name="ssr_cfg(core, ssr_fmt_str, none_str, inner_sep)">\ -% for core in cfg['cores']: - % for s in list(reversed(core['ssrs'] + [None]*(cfg['num_ssrs_max']-len(core['ssrs'])))): +% for core in cfg['cluster']['cores']: + % for s in list(reversed(core['ssrs'] + [None]*(cfg['cluster']['num_ssrs_max']-len(core['ssrs'])))): ${(" '{" if loop.first else ' ') + \ (ssr_fmt_str.format(**s) if s is not None else none_str) \ + (inner_sep if not loop.last else '}')}\ @@ -46,28 +46,28 @@ ${',' if not loop.last else ''} // verilog_lint: waive-start package-filename package ${cfg['pkg_name']}; - localparam int unsigned NrCores = ${cfg['nr_cores']}; - localparam int unsigned NrHives = ${cfg['nr_hives']}; + localparam int unsigned NrCores = ${cfg['cluster']['nr_cores']}; + localparam int unsigned NrHives = ${cfg['cluster']['nr_hives']}; - localparam int unsigned TcdmSize = ${cfg['tcdm']['size']}; + localparam int unsigned TcdmSize = ${cfg['cluster']['tcdm']['size']}; localparam int unsigned BootromSize = 4; // Fixed size of 4kB - localparam int unsigned ClusterPeriphSize = ${cfg['cluster_periph_size']}; - localparam int unsigned ZeroMemorySize = ${cfg['zero_mem_size']}; + localparam int unsigned ClusterPeriphSize = ${cfg['cluster']['cluster_periph_size']}; + localparam int unsigned ZeroMemorySize = ${cfg['cluster']['zero_mem_size']}; - localparam int unsigned AddrWidth = ${cfg['addr_width']}; - localparam int unsigned NarrowDataWidth = ${cfg['data_width']}; - localparam int unsigned WideDataWidth = ${cfg['dma_data_width']}; + localparam int unsigned AddrWidth = ${cfg['cluster']['addr_width']}; + localparam int unsigned NarrowDataWidth = ${cfg['cluster']['data_width']}; + localparam int unsigned WideDataWidth = ${cfg['cluster']['dma_data_width']}; - localparam int unsigned NarrowIdWidthIn = ${cfg['id_width_in']}; + localparam int unsigned NarrowIdWidthIn = ${cfg['cluster']['id_width_in']}; localparam int unsigned NrNarrowMasters = 3; localparam int unsigned NarrowIdWidthOut = $clog2(NrNarrowMasters) + NarrowIdWidthIn; - localparam int unsigned NrWideMasters = 1 + ${cfg['dma_nr_channels']} + ${cfg['nr_hives']}; - localparam int unsigned WideIdWidthIn = ${cfg['dma_id_width_in']}; + localparam int unsigned NrWideMasters = 1 + ${cfg['cluster']['dma_nr_channels']} + ${cfg['cluster']['nr_hives']}; + localparam int unsigned WideIdWidthIn = ${cfg['cluster']['dma_id_width_in']}; localparam int unsigned WideIdWidthOut = $clog2(NrWideMasters) + WideIdWidthIn; - localparam int unsigned NarrowUserWidth = ${cfg['user_width']}; - localparam int unsigned WideUserWidth = ${cfg['dma_user_width']}; + localparam int unsigned NarrowUserWidth = ${cfg['cluster']['user_width']}; + localparam int unsigned WideUserWidth = ${cfg['cluster']['dma_user_width']}; localparam int unsigned ICacheLineWidth [NrHives] = '{${icache_cfg('cacheline')}}; localparam int unsigned ICacheLineCount [NrHives] = '{${icache_cfg('depth')}}; @@ -76,7 +76,7 @@ package ${cfg['pkg_name']}; localparam int unsigned Hive [NrCores] = '{${core_cfg('hive')}}; typedef struct packed { -% for field, width in cfg['sram_cfg_fields'].items(): +% for field, width in cfg['cluster']['sram_cfg_fields'].items(): logic [${width-1}:0] ${field}; % endfor } sram_cfg_t; @@ -108,7 +108,7 @@ package ${cfg['pkg_name']}; automatic snitch_pma_pkg::rule_t [snitch_pma_pkg::NrMaxRules-1:0] cached_regions; cached_regions = '{default: '0}; % for i, cp in enumerate(cfg['pmas']['cached']): - cached_regions[${i}] = '{base: ${to_sv_hex(cp[0], cfg['addr_width'])}, mask: ${to_sv_hex(cp[1], cfg['addr_width'])}}; + cached_regions[${i}] = '{base: ${to_sv_hex(cp[0], cfg['cluster']['addr_width'])}, mask: ${to_sv_hex(cp[1], cfg['cluster']['addr_width'])}}; % endfor return cached_regions; endfunction @@ -119,37 +119,37 @@ package ${cfg['pkg_name']}; default: 0 }; - localparam fpnew_pkg::fpu_implementation_t FPUImplementation [${cfg['nr_cores']}] = '{ - % for c in cfg['cores']: + localparam fpnew_pkg::fpu_implementation_t FPUImplementation [${cfg['cluster']['nr_cores']}] = '{ + % for c in cfg['cluster']['cores']: '{ PipeRegs: // FMA Block '{ - '{ ${cfg['timing']['lat_comp_fp32']}, // FP32 - ${cfg['timing']['lat_comp_fp64']}, // FP64 - ${cfg['timing']['lat_comp_fp16']}, // FP16 - ${cfg['timing']['lat_comp_fp8']}, // FP8 - ${cfg['timing']['lat_comp_fp16_alt']}, // FP16alt - ${cfg['timing']['lat_comp_fp8_alt']} // FP8alt + '{ ${cfg['cluster']['timing']['lat_comp_fp32']}, // FP32 + ${cfg['cluster']['timing']['lat_comp_fp64']}, // FP64 + ${cfg['cluster']['timing']['lat_comp_fp16']}, // FP16 + ${cfg['cluster']['timing']['lat_comp_fp8']}, // FP8 + ${cfg['cluster']['timing']['lat_comp_fp16_alt']}, // FP16alt + ${cfg['cluster']['timing']['lat_comp_fp8_alt']} // FP8alt }, '{1, 1, 1, 1, 1, 1}, // DIVSQRT - '{${cfg['timing']['lat_noncomp']}, - ${cfg['timing']['lat_noncomp']}, - ${cfg['timing']['lat_noncomp']}, - ${cfg['timing']['lat_noncomp']}, - ${cfg['timing']['lat_noncomp']}, - ${cfg['timing']['lat_noncomp']}}, // NONCOMP - '{${cfg['timing']['lat_conv']}, - ${cfg['timing']['lat_conv']}, - ${cfg['timing']['lat_conv']}, - ${cfg['timing']['lat_conv']}, - ${cfg['timing']['lat_conv']}, - ${cfg['timing']['lat_conv']}}, // CONV - '{${cfg['timing']['lat_sdotp']}, - ${cfg['timing']['lat_sdotp']}, - ${cfg['timing']['lat_sdotp']}, - ${cfg['timing']['lat_sdotp']}, - ${cfg['timing']['lat_sdotp']}, - ${cfg['timing']['lat_sdotp']}} // DOTP + '{${cfg['cluster']['timing']['lat_noncomp']}, + ${cfg['cluster']['timing']['lat_noncomp']}, + ${cfg['cluster']['timing']['lat_noncomp']}, + ${cfg['cluster']['timing']['lat_noncomp']}, + ${cfg['cluster']['timing']['lat_noncomp']}, + ${cfg['cluster']['timing']['lat_noncomp']}}, // NONCOMP + '{${cfg['cluster']['timing']['lat_conv']}, + ${cfg['cluster']['timing']['lat_conv']}, + ${cfg['cluster']['timing']['lat_conv']}, + ${cfg['cluster']['timing']['lat_conv']}, + ${cfg['cluster']['timing']['lat_conv']}, + ${cfg['cluster']['timing']['lat_conv']}}, // CONV + '{${cfg['cluster']['timing']['lat_sdotp']}, + ${cfg['cluster']['timing']['lat_sdotp']}, + ${cfg['cluster']['timing']['lat_sdotp']}, + ${cfg['cluster']['timing']['lat_sdotp']}, + ${cfg['cluster']['timing']['lat_sdotp']}, + ${cfg['cluster']['timing']['lat_sdotp']}} // DOTP }, UnitTypes: '{'{fpnew_pkg::MERGED, fpnew_pkg::MERGED, @@ -199,30 +199,30 @@ package ${cfg['pkg_name']}; fpnew_pkg::DISABLED, fpnew_pkg::DISABLED}}, // DOTP % endif - PipeConfig: fpnew_pkg::${cfg['timing']['fpu_pipe_config']} + PipeConfig: fpnew_pkg::${cfg['cluster']['timing']['fpu_pipe_config']} }${',\n' if not loop.last else '\n'}\ % endfor }; - localparam snitch_ssr_pkg::ssr_cfg_t [${cfg['num_ssrs_max']}-1:0] SsrCfgs [${cfg['nr_cores']}] = '{ + localparam snitch_ssr_pkg::ssr_cfg_t [${cfg['cluster']['num_ssrs_max']}-1:0] SsrCfgs [${cfg['cluster']['nr_cores']}] = '{ ${ssr_cfg(core, "'{{{indirection:d}, {isect_master:d}, {isect_master_idx:d}, {isect_slave:d}, "\ "{isect_slave_spill:d}, {indir_out_spill:d}, {num_loops}, {index_width}, {pointer_width}, "\ "{shift_width}, {rpt_width}, {index_credits}, {isect_slave_credits}, {data_credits}, "\ "{mux_resp_depth}}}", "/*None*/ '0", ',\n ')}\ }; - localparam logic [${cfg['num_ssrs_max']}-1:0][4:0] SsrRegs [${cfg['nr_cores']}] = '{ + localparam logic [${cfg['cluster']['num_ssrs_max']}-1:0][4:0] SsrRegs [${cfg['cluster']['nr_cores']}] = '{ ${ssr_cfg(core, '{reg_idx}', '/*None*/ 0', ',')}\ }; // Forward potentially optional configuration parameters - localparam logic [9:0] CfgBaseHartId = (${to_sv_hex(cfg['cluster_base_hartid'], 10)}); - localparam addr_t CfgClusterBaseAddr = (${to_sv_hex(cfg['cluster_base_addr'], cfg['addr_width'])}); + localparam logic [9:0] CfgBaseHartId = (${to_sv_hex(cfg['cluster']['cluster_base_hartid'], 10)}); + localparam addr_t CfgClusterBaseAddr = (${to_sv_hex(cfg['cluster']['cluster_base_addr'], cfg['cluster']['addr_width'])}); endpackage // verilog_lint: waive-stop package-filename -module ${cfg['name']}_wrapper ( +module ${cfg['cluster']['name']}_wrapper ( input logic clk_i, input logic rst_ni, input logic [${cfg['pkg_name']}::NrCores-1:0] debug_req_i, @@ -230,7 +230,7 @@ module ${cfg['name']}_wrapper ( input logic [${cfg['pkg_name']}::NrCores-1:0] mtip_i, input logic [${cfg['pkg_name']}::NrCores-1:0] msip_i, input logic [9:0] hart_base_id_i, - input logic [${cfg['addr_width']-1}:0] cluster_base_addr_i, + input logic [${cfg['cluster']['addr_width']-1}:0] cluster_base_addr_i, input logic clk_d2_bypass_i, input ${cfg['pkg_name']}::sram_cfgs_t sram_cfgs_i, input ${cfg['pkg_name']}::narrow_in_req_t narrow_in_req_i, @@ -243,27 +243,27 @@ module ${cfg['name']}_wrapper ( output ${cfg['pkg_name']}::wide_in_resp_t wide_in_resp_o ); - localparam int unsigned NumIntOutstandingLoads [${cfg['nr_cores']}] = '{${core_cfg('num_int_outstanding_loads')}}; - localparam int unsigned NumIntOutstandingMem [${cfg['nr_cores']}] = '{${core_cfg('num_int_outstanding_mem')}}; - localparam int unsigned NumFPOutstandingLoads [${cfg['nr_cores']}] = '{${core_cfg('num_fp_outstanding_loads')}}; - localparam int unsigned NumFPOutstandingMem [${cfg['nr_cores']}] = '{${core_cfg('num_fp_outstanding_mem')}}; - localparam int unsigned NumDTLBEntries [${cfg['nr_cores']}] = '{${core_cfg('num_dtlb_entries')}}; - localparam int unsigned NumITLBEntries [${cfg['nr_cores']}] = '{${core_cfg('num_itlb_entries')}}; - localparam int unsigned NumSequencerInstr [${cfg['nr_cores']}] = '{${core_cfg('num_sequencer_instructions')}}; - localparam int unsigned NumSsrs [${cfg['nr_cores']}] = '{${core_cfg('num_ssrs')}}; - localparam int unsigned SsrMuxRespDepth [${cfg['nr_cores']}] = '{${core_cfg('ssr_mux_resp_depth')}}; + localparam int unsigned NumIntOutstandingLoads [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_int_outstanding_loads')}}; + localparam int unsigned NumIntOutstandingMem [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_int_outstanding_mem')}}; + localparam int unsigned NumFPOutstandingLoads [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_fp_outstanding_loads')}}; + localparam int unsigned NumFPOutstandingMem [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_fp_outstanding_mem')}}; + localparam int unsigned NumDTLBEntries [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_dtlb_entries')}}; + localparam int unsigned NumITLBEntries [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_itlb_entries')}}; + localparam int unsigned NumSequencerInstr [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_sequencer_instructions')}}; + localparam int unsigned NumSsrs [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_ssrs')}}; + localparam int unsigned SsrMuxRespDepth [${cfg['cluster']['nr_cores']}] = '{${core_cfg('ssr_mux_resp_depth')}}; // Snitch cluster under test. snitch_cluster #( - .PhysicalAddrWidth (${cfg['addr_width']}), - .NarrowDataWidth (${cfg['data_width']}), - .WideDataWidth (${cfg['dma_data_width']}), + .PhysicalAddrWidth (${cfg['cluster']['addr_width']}), + .NarrowDataWidth (${cfg['cluster']['data_width']}), + .WideDataWidth (${cfg['cluster']['dma_data_width']}), .NarrowIdWidthIn (${cfg['pkg_name']}::NarrowIdWidthIn), .WideIdWidthIn (${cfg['pkg_name']}::WideIdWidthIn), .NarrowUserWidth (${cfg['pkg_name']}::NarrowUserWidth), .WideUserWidth (${cfg['pkg_name']}::WideUserWidth), - .BootAddr (${to_sv_hex(cfg['boot_addr'], 32)}), - .IntBootromEnable (${int(cfg['int_bootrom_enable'])}), + .BootAddr (${to_sv_hex(cfg['cluster']['boot_addr'], 32)}), + .IntBootromEnable (${int(cfg['cluster']['int_bootrom_enable'])}), .narrow_in_req_t (${cfg['pkg_name']}::narrow_in_req_t), .narrow_in_resp_t (${cfg['pkg_name']}::narrow_in_resp_t), .narrow_out_req_t (${cfg['pkg_name']}::narrow_out_req_t), @@ -272,20 +272,20 @@ module ${cfg['name']}_wrapper ( .wide_out_resp_t (${cfg['pkg_name']}::wide_out_resp_t), .wide_in_req_t (${cfg['pkg_name']}::wide_in_req_t), .wide_in_resp_t (${cfg['pkg_name']}::wide_in_resp_t), - .NrHives (${cfg['nr_hives']}), - .NrCores (${cfg['nr_cores']}), - .TCDMDepth (${cfg['tcdm']['depth']}), + .NrHives (${cfg['cluster']['nr_hives']}), + .NrCores (${cfg['cluster']['nr_cores']}), + .TCDMDepth (${cfg['cluster']['tcdm']['depth']}), .ZeroMemorySize (snitch_cluster_pkg::ZeroMemorySize), .BootRomSize (snitch_cluster_pkg::BootromSize), .ClusterPeriphSize (snitch_cluster_pkg::ClusterPeriphSize), - .NrBanks (${cfg['tcdm']['banks']}), - .DMANumAxInFlight (${cfg['dma_axi_req_fifo_depth']}), - .DMAReqFifoDepth (${cfg['dma_req_fifo_depth']}), - .DMANumChannels (${cfg['dma_nr_channels']}), + .NrBanks (${cfg['cluster']['tcdm']['banks']}), + .DMANumAxInFlight (${cfg['cluster']['dma_axi_req_fifo_depth']}), + .DMAReqFifoDepth (${cfg['cluster']['dma_req_fifo_depth']}), + .DMANumChannels (${cfg['cluster']['dma_nr_channels']}), .ICacheLineWidth (${cfg['pkg_name']}::ICacheLineWidth), .ICacheLineCount (${cfg['pkg_name']}::ICacheLineCount), .ICacheSets (${cfg['pkg_name']}::ICacheSets), - .VMSupport (${int(cfg['vm_support'])}), + .VMSupport (${int(cfg['cluster']['vm_support'])}), .RVE (${core_isa('e')}), .RVF (${core_isa('f')}), .RVD (${core_isa('d')}), @@ -307,46 +307,46 @@ module ${cfg['name']}_wrapper ( .NumFPOutstandingMem (NumFPOutstandingMem), .NumDTLBEntries (NumDTLBEntries), .NumITLBEntries (NumITLBEntries), - .NumSsrsMax (${cfg['num_ssrs_max']}), + .NumSsrsMax (${cfg['cluster']['num_ssrs_max']}), .NumSsrs (NumSsrs), .SsrMuxRespDepth (SsrMuxRespDepth), .SsrRegs (${cfg['pkg_name']}::SsrRegs), .SsrCfgs (${cfg['pkg_name']}::SsrCfgs), .NumSequencerInstr (NumSequencerInstr), .Hive (${cfg['pkg_name']}::Hive), - .Topology (snitch_pkg::${cfg['tcdm']['topology']}), - .Radix (${int(cfg['tcdm']['radix'])}), - .NumSwitchNets (${int(cfg['tcdm']['num_switch_nets'])}), - .SwitchLfsrArbiter (${int(cfg['tcdm']['switch_lfsr_arbiter'])}), - .RegisterOffloadReq (${int(cfg['timing']['register_offload_req'])}), - .RegisterOffloadRsp (${int(cfg['timing']['register_offload_rsp'])}), - .RegisterCoreReq (${int(cfg['timing']['register_core_req'])}), - .RegisterCoreRsp (${int(cfg['timing']['register_core_rsp'])}), - .RegisterTCDMCuts (${int(cfg['timing']['register_tcdm_cuts'])}), - .RegisterExtWide (${int(cfg['timing']['register_ext_wide'])}), - .RegisterExtNarrow (${int(cfg['timing']['register_ext_narrow'])}), - .RegisterFPUReq (${int(cfg['timing']['register_fpu_req'])}), - .RegisterFPUIn (${int(cfg['timing']['register_fpu_in'])}), - .RegisterFPUOut (${int(cfg['timing']['register_fpu_out'])}), - .RegisterSequencer (${int(cfg['timing']['register_sequencer'])}), - .IsoCrossing (${int(cfg['timing']['iso_crossings'])}), - .NarrowXbarLatency (axi_pkg::${cfg['timing']['narrow_xbar_latency']}), - .WideXbarLatency (axi_pkg::${cfg['timing']['wide_xbar_latency']}), - .WideMaxMstTrans (${cfg['wide_trans']}), - .WideMaxSlvTrans (${cfg['wide_trans']}), - .NarrowMaxMstTrans (${cfg['narrow_trans']}), - .NarrowMaxSlvTrans (${cfg['narrow_trans']}), + .Topology (snitch_pkg::${cfg['cluster']['tcdm']['topology']}), + .Radix (${int(cfg['cluster']['tcdm']['radix'])}), + .NumSwitchNets (${int(cfg['cluster']['tcdm']['num_switch_nets'])}), + .SwitchLfsrArbiter (${int(cfg['cluster']['tcdm']['switch_lfsr_arbiter'])}), + .RegisterOffloadReq (${int(cfg['cluster']['timing']['register_offload_req'])}), + .RegisterOffloadRsp (${int(cfg['cluster']['timing']['register_offload_rsp'])}), + .RegisterCoreReq (${int(cfg['cluster']['timing']['register_core_req'])}), + .RegisterCoreRsp (${int(cfg['cluster']['timing']['register_core_rsp'])}), + .RegisterTCDMCuts (${int(cfg['cluster']['timing']['register_tcdm_cuts'])}), + .RegisterExtWide (${int(cfg['cluster']['timing']['register_ext_wide'])}), + .RegisterExtNarrow (${int(cfg['cluster']['timing']['register_ext_narrow'])}), + .RegisterFPUReq (${int(cfg['cluster']['timing']['register_fpu_req'])}), + .RegisterFPUIn (${int(cfg['cluster']['timing']['register_fpu_in'])}), + .RegisterFPUOut (${int(cfg['cluster']['timing']['register_fpu_out'])}), + .RegisterSequencer (${int(cfg['cluster']['timing']['register_sequencer'])}), + .IsoCrossing (${int(cfg['cluster']['timing']['iso_crossings'])}), + .NarrowXbarLatency (axi_pkg::${cfg['cluster']['timing']['narrow_xbar_latency']}), + .WideXbarLatency (axi_pkg::${cfg['cluster']['timing']['wide_xbar_latency']}), + .WideMaxMstTrans (${cfg['cluster']['wide_trans']}), + .WideMaxSlvTrans (${cfg['cluster']['wide_trans']}), + .NarrowMaxMstTrans (${cfg['cluster']['narrow_trans']}), + .NarrowMaxSlvTrans (${cfg['cluster']['narrow_trans']}), .sram_cfg_t (${cfg['pkg_name']}::sram_cfg_t), .sram_cfgs_t (${cfg['pkg_name']}::sram_cfgs_t), - .CaqDepth (${int(cfg['caq_depth'])}), - .CaqTagWidth (${int(cfg['caq_tag_width'])}), - .DebugSupport (${int(cfg['enable_debug'])}), - .AliasRegionEnable (${int(cfg['alias_region_enable'])}), - .AliasRegionBase (${int(cfg['alias_region_base'])}) + .CaqDepth (${int(cfg['cluster']['caq_depth'])}), + .CaqTagWidth (${int(cfg['cluster']['caq_tag_width'])}), + .DebugSupport (${int(cfg['cluster']['enable_debug'])}), + .AliasRegionEnable (${int(cfg['cluster']['alias_region_enable'])}), + .AliasRegionBase (${int(cfg['cluster']['alias_region_base'])}) ) i_cluster ( .clk_i, .rst_ni, -% if cfg['enable_debug']: +% if cfg['cluster']['enable_debug']: .debug_req_i, % else: .debug_req_i ('0), @@ -354,19 +354,19 @@ module ${cfg['name']}_wrapper ( .meip_i, .mtip_i, .msip_i, -% if cfg['cluster_base_expose']: +% if cfg['cluster']['cluster_base_expose']: .hart_base_id_i, .cluster_base_addr_i, % else: .hart_base_id_i (snitch_cluster_pkg::CfgBaseHartId), .cluster_base_addr_i (snitch_cluster_pkg::CfgClusterBaseAddr), % endif -% if cfg['timing']['iso_crossings']: +% if cfg['cluster']['timing']['iso_crossings']: .clk_d2_bypass_i, % else: .clk_d2_bypass_i (1'b0), % endif -% if cfg['sram_cfg_expose']: +% if cfg['cluster']['sram_cfg_expose']: .sram_cfgs_i (sram_cfgs_i), % else: .sram_cfgs_i (${cfg['pkg_name']}::sram_cfgs_t'('0)), diff --git a/hw/snitch_cluster/test/bootdata.cc.tpl b/hw/snitch_cluster/test/bootdata.cc.tpl index 32417f56e8..5039b773c1 100644 --- a/hw/snitch_cluster/test/bootdata.cc.tpl +++ b/hw/snitch_cluster/test/bootdata.cc.tpl @@ -12,9 +12,9 @@ const BootData BOOTDATA = {.boot_addr = ${hex(cfg['cluster']['boot_addr'])}, .tcdm_start = ${hex(cfg['cluster']['cluster_base_addr'])}, .tcdm_size = ${hex(cfg['cluster']['tcdm']['size'] * 1024)}, .tcdm_offset = ${hex(cfg['cluster']['cluster_base_offset'])}, - .global_mem_start = ${hex(cfg['dram']['address'])}, - .global_mem_end = ${hex(cfg['dram']['address'] + cfg['dram']['length'])}, + .global_mem_start = ${hex(next(reg['address'] for reg in cfg['external_addr_regions'] if reg['name'] == 'dram'))}, + .global_mem_end = ${hex(next(reg['address'] + reg['length'] for reg in cfg['external_addr_regions'] if reg['name'] == 'dram'))}, .cluster_count = ${cfg['nr_clusters']}, - .clint_base = ${hex(cfg['peripherals']['clint']['address'])}}; + .clint_base = ${hex(next(reg['address'] + reg['length'] for reg in cfg['external_addr_regions'] if reg['name'] == 'clint'))}}; } // namespace sim diff --git a/hw/snitch_cluster/test/link.ld.tpl b/hw/snitch_cluster/test/link.ld.tpl index 52712a3e51..27a84ecbc9 100644 --- a/hw/snitch_cluster/test/link.ld.tpl +++ b/hw/snitch_cluster/test/link.ld.tpl @@ -4,10 +4,12 @@ OUTPUT_ARCH( "riscv" ) ENTRY(_start) -<% dram_address = cfg['dram']['address']; %> +<% dram_address = next(reg['address'] for reg in cfg['external_addr_regions'] if reg['name'] == 'dram'); %> +<% dram_length = next(reg['length'] for reg in cfg['external_addr_regions'] if reg['name'] == 'dram'); %> + MEMORY { - DRAM (rwxai) : ORIGIN = ${dram_address}, LENGTH = ${cfg['dram']['length']} + DRAM (rwxai) : ORIGIN = ${dram_address}, LENGTH = ${dram_length} L1 (rw) : ORIGIN = ${l1_region[0]}, LENGTH = ${l1_region[1]}K } diff --git a/target/snitch_cluster/sw/runtime/common/snitch_cluster_addrmap.h.tpl b/target/snitch_cluster/sw/runtime/common/snitch_cluster_addrmap.h.tpl index dc6950ca29..a7e85d4719 100644 --- a/target/snitch_cluster/sw/runtime/common/snitch_cluster_addrmap.h.tpl +++ b/target/snitch_cluster/sw/runtime/common/snitch_cluster_addrmap.h.tpl @@ -7,7 +7,7 @@ #define CLUSTER_PERIPH_BASE_ADDR (CLUSTER_BOOTROM_BASE_ADDR + 4 * 1024) #define CLUSTER_ZERO_MEM_START_ADDR (CLUSTER_PERIPH_BASE_ADDR + ${hex(cfg['cluster']['cluster_periph_size'] * 1024)}) #define CLUSTER_ZERO_MEM_END_ADDR (CLUSTER_ZERO_MEM_START_ADDR + ${hex(cfg['cluster']['zero_mem_size'] * 1024)}) -#define CLINT_BASE_ADDR ${hex(cfg['peripherals']['clint']['address'])} +#define CLINT_BASE_ADDR ${hex(next(reg['address'] for reg in cfg['external_addr_regions'] if reg['name'] == 'clint'))} #define ALIAS_TCDM_BASE_ADDR ${hex(cfg['cluster']['alias_region_base'])} #define ALIAS_BOOTROM_BASE_ADDR (ALIAS_TCDM_BASE_ADDR + ${hex(cfg['cluster']['tcdm']['size'] * 1024)}) #define ALIAS_PERIPH_BASE_ADDR (ALIAS_BOOTROM_BASE_ADDR + 4 * 1024) diff --git a/util/clustergen.py b/util/clustergen.py index b349747ee8..7ccae24167 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -10,7 +10,7 @@ import re from jsonref import JsonRef -from clustergen.cluster import SnitchClusterTB +from clustergen.cluster import SnitchCluster from mako.template import Template @@ -73,7 +73,7 @@ def main(): except ValueError: raise SystemExit(sys.exc_info()[1]) - cluster_tb = SnitchClusterTB(obj) + cluster_tb = SnitchCluster(obj) if not args.outdir.is_dir(): exit("Out directory is not a valid path.") diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index 34eb8e2dd3..eaf766e05e 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -73,7 +73,7 @@ def __init__(self, root_schema, remote_schemas=[]): def validate(self, cfg): # Validate the schema. This can fail. try: - DefaultValidatingDraft7Validator( + DefaultValidator( self.root_schema, resolver=self.resolver).validate(cfg) except ValidationError as e: print(e) @@ -148,7 +148,7 @@ class SnitchCluster(Generator): 'wrapper': "src/snitch_cluster_wrapper.sv.tpl" } - def __init__(self, cfg, pma_cfg): + def __init__(self, cfg): """ Initialize with a given configuration. The constructor checks conformans to the cluster schema and constructs a `cfg` object. @@ -162,10 +162,10 @@ def __init__(self, cfg, pma_cfg): if self.cfg_validate(): exit("Failed parameter validation.") - self.cfg['pkg_name'] = "{}_pkg".format(self.cfg['name']) + self.cfg['pkg_name'] = "{}_pkg".format(self.cfg['cluster']['name']) self.calc_cache_sizes() - self.parse_pma_cfg(pma_cfg) + self.gen_pma_cfg() self.parse_cores() def l1_region(self): @@ -239,22 +239,27 @@ def memory_cfg(self): def calc_cache_sizes(self): # Calculate TCDM parameters - tcdm_bytes = self.cfg['data_width'] // 8 - self.cfg['tcdm']['depth'] = self.cfg['tcdm']['size'] * 1024 // ( - self.cfg['tcdm']['banks'] * tcdm_bytes) + tcdm_bytes = self.cfg['cluster']['data_width'] // 8 + self.cfg['cluster']['tcdm']['depth'] = self.cfg['cluster']['tcdm']['size'] * 1024 // ( + self.cfg['cluster']['tcdm']['banks'] * tcdm_bytes) # Calc icache parameters - for i, hive in enumerate(self.cfg['hives']): - cl_bytes = self.cfg['hives'][i]['icache']['cacheline'] // 8 - self.cfg['hives'][i]['icache']['depth'] = self.cfg['hives'][i][ - 'icache']['size'] * 1024 // self.cfg['hives'][i]['icache'][ + for i, hive in enumerate(self.cfg['cluster']['hives']): + cl_bytes = self.cfg['cluster']['hives'][i]['icache']['cacheline'] // 8 + self.cfg['cluster']['hives'][i]['icache']['depth'] = self.cfg['cluster']['hives'][i][ + 'icache']['size'] * 1024 // self.cfg['cluster']['hives'][i]['icache'][ 'sets'] // cl_bytes # tag width - self.tag_width = self.cfg['addr_width'] - clog2( + self.tag_width = self.cfg['cluster']['addr_width'] - clog2( hive['icache']['cacheline'] // 8) - clog2(hive['icache']['depth']) + 3 - def parse_pma_cfg(self, pma_cfg): + def gen_pma_cfg(self): + # Check if the configuration has legal cacheable regions + pma_cfg = PMACfg() + for region in self.cfg['external_addr_regions']: + if region["cacheable"]: + pma_cfg.add_region_length(PMA.CACHED, region['address'], region['length'], self.cfg['cluster']['addr_width']) + # Populate the list of cached regions self.cfg['pmas'] = dict() - # print(pma_cfg.regions) self.cfg['pmas']['cached'] = list() for pma in pma_cfg.regions: if pma[0] == PMA.CACHED: @@ -279,7 +284,7 @@ def gen_mask(c, s): return "{}'b{}".format(c, ''.join(reversed(s))) cores = list() - for i, core_list in enumerate(self.cfg['hives']): + for i, core_list in enumerate(self.cfg['cluster']['hives']): for core in core_list['cores']: core['hive'] = i core['isa_parsed'] = parse_isa_string( @@ -299,9 +304,9 @@ def gen_mask(c, s): # Set default SSR parameters for ssr in core['ssrs']: if ssr['pointer_width'] is None: - ssr['pointer_width'] = 10 + clog2(self.cfg['tcdm']['size']) + ssr['pointer_width'] = 10 + clog2(self.cfg['cluster']['tcdm']['size']) if ssr['index_width'] is None: - ssr['index_width'] = ssr['pointer_width'] - clog2(self.cfg['data_width']/8) + ssr['index_width'] = ssr['pointer_width'] - clog2(self.cfg['cluster']['data_width']/8) # Sort SSRs by register indices (required by decoding logic) core['ssrs'].sort(key=lambda x: x['reg_idx']) # Minimum 1 element to avoid illegal ranges (Xssr prevents generation) @@ -309,93 +314,51 @@ def gen_mask(c, s): cores.append(dict(core)) - self.cfg['nr_hives'] = len(self.cfg['hives']) - self.cfg['nr_cores'] = len(cores) + self.cfg['cluster']['nr_hives'] = len(self.cfg['cluster']['hives']) + self.cfg['cluster']['nr_cores'] = len(cores) # Minimum 1 element to avoid illegal ranges - self.cfg['num_ssrs_max'] = max(max(len(core['ssrs']) for core in cores), 1) - self.cfg['cores'] = cores + self.cfg['cluster']['num_ssrs_max'] = max(max(len(core['ssrs']) for core in cores), 1) + self.cfg['cluster']['cores'] = cores def cfg_validate(self): failed = True """Perform more advanced validation, i.e., sanity check parameters.""" - if int(self.cfg['addr_width']) < 30: + if int(self.cfg['cluster']['addr_width']) < 30: log.error("`addr_width` must be greater or equal to 30.") - elif not ((int(self.cfg['data_width']) == 32) or - (int(self.cfg['data_width']) == 64)): + elif not ((int(self.cfg['cluster']['data_width']) == 32) or + (int(self.cfg['cluster']['data_width']) == 64)): log.error("`data_width` must be 32 or 64 bit") - elif int(self.cfg['dma_data_width']) <= 0: + elif int(self.cfg['cluster']['dma_data_width']) <= 0: log.error("`dma_data_width` must be set") - elif int(self.cfg['dma_data_width']) % int( - self.cfg['data_width']) != 0: + elif int(self.cfg['cluster']['dma_data_width']) % int( + self.cfg['cluster']['data_width']) != 0: log.error( "DMA port {} has to be multiple of {} (bank width)".format( - self.cfg['dma_data_width'], self.cfg['data_width'])) - elif is_pow2(self.cfg['dma_data_width']): + self.cfg['cluster']['dma_data_width'], self.cfg['cluster']['data_width'])) + elif is_pow2(self.cfg['cluster']['dma_data_width']): log.error("`dma_data_width` must be a power of two") # elif cfg.en_rvd and not cfg.en_rvf: # log.error("RVD needs RVF") # elif cfg.en_rvd and not cfg.data_width == 64: # log.error("RVD needs 64 bit data buses") - elif (self.cfg['tcdm']['size'] % self.cfg['tcdm']['banks']) != 0: + elif (self.cfg['cluster']['tcdm']['size'] % self.cfg['cluster']['tcdm']['banks']) != 0: log.error( "The total size of the TCDM must be divisible by the requested amount of banks." ) - elif is_pow2(self.cfg['tcdm']['size']): + elif is_pow2(self.cfg['cluster']['tcdm']['size']): log.error("The TCDM size must be a power of two.") - elif is_pow2(self.cfg['tcdm']['banks']): + elif is_pow2(self.cfg['cluster']['tcdm']['banks']): log.error("The amount of banks must be a power of two.") else: failed = False # Warnings - if (int(self.cfg['dma_data_width']) != 512): + if (int(self.cfg['cluster']['dma_data_width']) != 512): log.warn("Design was never tested with this configuration") return failed -class SnitchClusterTB(Generator): - """ - A very simplistic system, which instantiates a single cluster and - surrounding DRAM to test and simulate this system. This can also serve as a - starting point on how to use the `snitchgen` library to generate more - complex systems. - """ - def __init__(self, cfg): - schema = Path(__file__).parent / "schema/snitch_cluster_tb.schema.json" - remote_schemas = [Path(__file__).parent / "schema/snitch_cluster.schema.json"] - super().__init__(schema, remote_schemas) - # Validate the schema. - self.validate(cfg) - # from here we know that we have a valid object. - # and construct a new SnitchClusterTB object. - self.cfg = cfg - pma_cfg = PMACfg() - # For this example system make the entire dram cacheable. - pma_cfg.add_region_length(PMA.CACHED, self.cfg['dram']['address'], - self.cfg['dram']['length'], - self.cfg['cluster']['addr_width']) - # Store Snitch cluster config in separate variable - self.cluster = SnitchCluster(cfg["cluster"], pma_cfg) - - def render_wrapper(self): - return self.cluster.render_wrapper() - - def render_linker_script(self): - """Generate a linker script for the cluster testbench""" - cfg_template = self.templates.get_template("test/link.ld.tpl") - return cfg_template.render_unicode(cfg=self.cfg, - l1_region=self.cluster.l1_region()) - - def render_bootdata(self): - """Generate a C file with boot information for the cluster testbench""" - cfg_template = self.templates.get_template("test/bootdata.cc.tpl") - return cfg_template.render_unicode(cfg=self.cfg) - - def render_deps(self, dep_name): - return self.cluster.render_deps(dep_name) - - def read_schema(path): """Read a single schema file and return the parsed JSON content. Aborts if the JSON file could not be decoed.""" diff --git a/util/clustergen/schema/snitch_cluster.schema.json b/util/clustergen/schema/snitch_cluster.schema.json index 2fc3ef3817..9e97e3c9dd 100644 --- a/util/clustergen/schema/snitch_cluster.schema.json +++ b/util/clustergen/schema/snitch_cluster.schema.json @@ -4,623 +4,624 @@ "title": "Snitch Cluster Schema", "description": "Base description of a Snitch cluster and its internal structure and configuration.", "type": "object", - "required": [ - "addr_width", - "hives" - ], "properties": { - "name": { - "type": "string", - "description": "Optional name for the generated wrapper.", - "default": "snitch_cluster" - }, - "int_bootrom_enable": { - "type": "boolean", - "description": "Whether to use the internal bootrom.", - "default": true - }, - "boot_addr": { - "type": "number", - "description": "Address from which all harts of the cluster start to boot. The default setting is `0x8000_0000`. Unused if `alias_region_enable` and `int_bootrom_enable` are set.", - "default": 2147483648 - }, - "cluster_base_addr": { - "type": "number", - "description": "Base address of this cluster.", - "default": 0 - }, - "tcdm": { - "type": "object", - "description": "Configuration of the Tightly Coupled Data Memory of this cluster.", - "default": { - "size": 128, - "banks": 32 - }, + "cluster": { + "required": ["addr_width","hives"], "properties": { - "size": { + "name": { + "type": "string", + "description": "Optional name for the generated wrapper.", + "default": "snitch_cluster" + }, + "int_bootrom_enable": { + "type": "boolean", + "description": "Whether to use the internal bootrom.", + "default": true + }, + "boot_addr": { "type": "number", - "description": "Size of TCDM in KiByte. Divided in `n` banks. The total size must be divisible by the number of banks.", + "description": "Address from which all harts of the cluster start to boot. The default setting is `0x8000_0000`. Unused if `alias_region_enable` and `int_bootrom_enable` are set.", + "default": 2147483648 + }, + "cluster_base_addr": { + "type": "number", + "description": "Base address of this cluster.", + "default": 0 + }, + "tcdm": { + "type": "object", + "description": "Configuration of the Tightly Coupled Data Memory of this cluster.", + "default": { + "size": 128, + "banks": 32 + }, + "properties": { + "size": { + "type": "number", + "description": "Size of TCDM in KiByte. Divided in `n` banks. The total size must be divisible by the number of banks.", + "examples": [ + 128, + 64 + ] + }, + "banks": { + "type": "number", + "description": "Number of banks.", + "examples": [ + 16, + 32 + ] + }, + "topology": { + "type": "string", + "description": "Network topology used for TCDM interconnect.", + "enum": ["LogarithmicInterconnect", "OmegaNet"], + "default": "LogarithmicInterconnect" + }, + "radix": { + "type": "number", + "description": "Radix of switches in switch-based TCDM interconnect topologies (ignored for logarithmic interconnect).", + "enum": [2, 4], + "default": 2 + }, + "num_switch_nets": { + "type": "number", + "description": "Number of parallel networks in switch-based TCDM interconnect topologies (ignored for logarithmic interconnect).", + "minimum": 1, + "default": 4 + }, + "switch_lfsr_arbiter": { + "type": "boolean", + "description": "Whether to use pseudorandom (LFSR-generated) arbitration in switch-based TCDM interconect topologies instead of pseudo-round-robin (ignored for logarithmic interconnect).", + "default": false + } + } + }, + "cluster_periph_size": { + "type": "number", + "description": "Address region size reserved for cluster peripherals in KiByte.", "examples": [ 128, 64 ] }, - "banks": { + "zero_mem_size": { "type": "number", - "description": "Number of banks.", + "description": "Address region size reserved for the Zero-Memory in KiByte.", "examples": [ - 16, - 32 + 128, + 64 ] }, - "topology": { - "type": "string", - "description": "Network topology used for TCDM interconnect.", - "enum": ["LogarithmicInterconnect", "OmegaNet"], - "default": "LogarithmicInterconnect" + "alias_region_enable": { + "type": "boolean", + "description": "Whether to provide a hardwired alias region for the TCDM (and cluster) address space.", + "default": false }, - "radix": { + "alias_region_base": { "type": "number", - "description": "Radix of switches in switch-based TCDM interconnect topologies (ignored for logarithmic interconnect).", - "enum": [2, 4], - "default": 2 + "description": "Base address of the hardwired alias region for the TCDM (and cluster) if enabled. The default setting is `0x1800_0000`.", + "default": 402653184 }, - "num_switch_nets": { + "addr_width": { "type": "number", - "description": "Number of parallel networks in switch-based TCDM interconnect topologies (ignored for logarithmic interconnect).", - "minimum": 1, - "default": 4 + "description": "Length of the address, should be greater than 30. If the address is larger than 34 the data bus needs to be 64 bits in size.", + "default": 48 }, - "switch_lfsr_arbiter": { - "type": "boolean", - "description": "Whether to use pseudorandom (LFSR-generated) arbitration in switch-based TCDM interconect topologies instead of pseudo-round-robin (ignored for logarithmic interconnect).", - "default": false - } - } - }, - "cluster_periph_size": { - "type": "number", - "description": "Address region size reserved for cluster peripherals in KiByte.", - "examples": [ - 128, - 64 - ] - }, - "zero_mem_size": { - "type": "number", - "description": "Address region size reserved for the Zero-Memory in KiByte.", - "examples": [ - 128, - 64 - ] - }, - "alias_region_enable": { - "type": "boolean", - "description": "Whether to provide a hardwired alias region for the TCDM (and cluster) address space.", - "default": false - }, - "alias_region_base": { - "type": "number", - "description": "Base address of the hardwired alias region for the TCDM (and cluster) if enabled. The default setting is `0x1800_0000`.", - "default": 402653184 - }, - "addr_width": { - "type": "number", - "description": "Length of the address, should be greater than 30. If the address is larger than 34 the data bus needs to be 64 bits in size.", - "default": 48 - }, - "data_width": { - "type": "number", - "description": "Data bus size of the integer core (everything except the DMA), must be 32 or 64. A double precision FPU requires 64 bit data length.", - "default": 64 - }, - "dma_data_width": { - "type": "number", - "description": "Data bus size of DMA. Usually this is larger than the integer core as the DMA is used to efficiently transfer bulk of data.", - "default": 512 - }, - "narrow_trans": { - "type": "number", - "description": "Outstanding transactions on the narrow AXI network", - "default": 4 - }, - "wide_trans": { - "type": "number", - "description": "Outstanding transactions on the wide AXI network", - "default": 4 - }, - "id_width_in": { - "type": "number", - "description": "Id width of the narrower AXI plug into the cluster.", - "default": 2 - }, - "dma_id_width_in": { - "type": "number", - "description": "Id width of the wide AXI plug into the cluster.", - "default": 1 - }, - "dma_nr_channels": { - "type": "number", - "description": "The number of separate DMA channels to instantiate.", - "default": 1 - }, - "user_width": { - "type": "number", - "description": "User width of the narrower AXI plug into the cluster.", - "default": 1 - }, - "dma_user_width": { - "type": "number", - "description": "User width of the wide AXI plug into the cluster.", - "default": 1 - }, - "hart_base_id": { - "type": "number", - "description": "Base hart id of the cluster. All cores get the respective cluster id plus their cluster position as the final `hart_id`.", - "default": 0 - }, - "mode": { - "type": "string", - "description": "Supported mode by the processor, can be msu.", - "$comment": "Currently ignored." - }, - "vm_support": { - "type": "boolean", - "description": "Whether to provide virtual memory support (Sv32).", - "default": true - }, - "dma_axi_req_fifo_depth": { - "type": "number", - "description": "Number of AXI FIFO entries of the DMA engine.", - "default": 3 - }, - "dma_req_fifo_depth": { - "type": "number", - "description": "Number of request entries the DMA can keep", - "default": 3 - }, - "caq_depth": { - "type": "number", - "description": "Depth of consistency address queue (CAQ). Should cover as many FP load-stores as may be deferred in sequencer to prevent pseudo-dual-issue blocking.", - "default": 8 - }, - "caq_tag_width": { - "type": "number", - "description": "Tag width for consistency address queue (CAQ). Reordering of integer/FP loads/stores to words with colliding tags causes stalls. Should cover at least TCDM.", - "default": 16 - }, - "enable_debug": { - "type": "boolean", - "description": "Whether to provide a debug request input and external debug features", - "default": true - }, - "cluster_base_expose": { - "type": "boolean", - "description": "Whether to expose base_addr and base_hart_id", - "default": false - }, - "sram_cfg_expose": { - "type": "boolean", - "description": "Whether to expose memory cut configuration inputs for implementation", - "default": false - }, - "sram_cfg_fields": { - "type": "object", - "description": "The names and widths of memory cut configuration inputs needed for implementation", - "default": {"reserved" : 1}, - "minProperties": 1, - "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, - "additionalProperties": { "type": "number", "minimum": 1 } - }, - "timing": { - "type": "object", - "title": "Timing and Latency Tuning Parameter", - "properties": { - "iso_crossings": { - "type": "boolean", - "description": "Enable isochronous crossings, this clocks the integer core at half the speed of the rest of the system.", - "default": false + "data_width": { + "type": "number", + "description": "Data bus size of the integer core (everything except the DMA), must be 32 or 64. A double precision FPU requires 64 bit data length.", + "default": 64 }, - "narrow_xbar_latency": { - "type": "string", - "description": "Latency mode of the cluster crossbar.", - "enum": [ - "NO_LATENCY", - "CUT_SLV_AX", - "CUT_MST_AX", - "CUT_ALL_AX", - "CUT_SLV_PORTS", - "CUT_MST_PORTS", - "CUT_ALL_PORTS" - ], - "default": "CUT_ALL_PORTS" - }, - "wide_xbar_latency": { - "type": "string", - "description": "Latency mode of the DMA crossbar.", - "enum": [ - "NO_LATENCY", - "CUT_SLV_AX", - "CUT_MST_AX", - "CUT_ALL_AX", - "CUT_SLV_PORTS", - "CUT_MST_PORTS", - "CUT_ALL_PORTS" - ], - "default": "CUT_ALL_PORTS" - }, - "register_offload_req": { - "type": "boolean", - "description": "Insert Pipeline registers into off-loading path (request).", - "default": false + "dma_data_width": { + "type": "number", + "description": "Data bus size of DMA. Usually this is larger than the integer core as the DMA is used to efficiently transfer bulk of data.", + "default": 512 }, - "register_offload_rsp": { - "type": "boolean", - "description": "Insert Pipeline registers into off-loading path (response).", - "default": false + "narrow_trans": { + "type": "number", + "description": "Outstanding transactions on the narrow AXI network", + "default": 4 }, - "register_core_req": { - "type": "boolean", - "description": "Insert Pipeline registers into data memory request path.", - "default": false + "wide_trans": { + "type": "number", + "description": "Outstanding transactions on the wide AXI network", + "default": 4 }, - "register_core_rsp": { - "type": "boolean", - "description": "Insert Pipeline registers into data memory response path.", - "default": false + "id_width_in": { + "type": "number", + "description": "Id width of the narrower AXI plug into the cluster.", + "default": 2 }, - "register_fpu_req": { - "type": "boolean", - "description": "Insert Pipeline register into the FPU request data path", - "default": false + "dma_id_width_in": { + "type": "number", + "description": "Id width of the wide AXI plug into the cluster.", + "default": 1 }, - "register_fpu_in": { - "type": "boolean", - "description": "Insert Pipeline registers immediately before FPU datapath", - "default": false + "dma_nr_channels": { + "type": "number", + "description": "The number of separate DMA channels to instantiate.", + "default": 1 }, - "register_fpu_out": { - "type": "boolean", - "description": "Insert Pipeline registers immediately after FPU datapath", - "default": false + "user_width": { + "type": "number", + "description": "User width of the narrower AXI plug into the cluster.", + "default": 1 }, - "register_tcdm_cuts": { - "type": "boolean", - "description": "Insert Pipeline registers after each memory cut.", - "default": false + "dma_user_width": { + "type": "number", + "description": "User width of the wide AXI plug into the cluster.", + "default": 1 }, - "register_ext_wide": { - "type": "boolean", - "description": "Decouple wide external AXI plug.", - "default": false + "hart_base_id": { + "type": "number", + "description": "Base hart id of the cluster. All cores get the respective cluster id plus their cluster position as the final `hart_id`.", + "default": 0 }, - "register_ext_narrow": { - "type": "boolean", - "description": "Decouple narrow external AXI plug.", - "default": false + "mode": { + "type": "string", + "description": "Supported mode by the processor, can be msu.", + "$comment": "Currently ignored." }, - "register_sequencer": { + "vm_support": { "type": "boolean", - "description": "Insert Pipeline registers after sequencer.", - "default": false + "description": "Whether to provide virtual memory support (Sv32).", + "default": true }, - "lat_comp_fp32": { + "dma_axi_req_fifo_depth": { "type": "number", - "description": "Latency setting (number of pipeline stages) for FP32.", + "description": "Number of AXI FIFO entries of the DMA engine.", "default": 3 }, - "lat_comp_fp64": { + "dma_req_fifo_depth": { "type": "number", - "description": "Latency setting (number of pipeline stages) for FP64.", + "description": "Number of request entries the DMA can keep", "default": 3 }, - "lat_comp_fp16": { + "caq_depth": { "type": "number", - "description": "Latency setting (number of pipeline stages) for FP16.", - "default": 1 + "description": "Depth of consistency address queue (CAQ). Should cover as many FP load-stores as may be deferred in sequencer to prevent pseudo-dual-issue blocking.", + "default": 8 }, - "lat_comp_fp16_alt": { + "caq_tag_width": { "type": "number", - "description": "Latency setting (number of pipeline stages) for FP16alt (brainfloat).", - "default": 2 + "description": "Tag width for consistency address queue (CAQ). Reordering of integer/FP loads/stores to words with colliding tags causes stalls. Should cover at least TCDM.", + "default": 16 }, - "lat_comp_fp8": { - "type": "number", - "description": "Latency setting (number of pipeline stages) for FP8.", - "default": 1 + "enable_debug": { + "type": "boolean", + "description": "Whether to provide a debug request input and external debug features", + "default": true }, - "lat_comp_fp8alt": { - "type": "number", - "description": "Latency setting (number of pipeline stages) for FP8alt.", - "default": 1 + "cluster_base_expose": { + "type": "boolean", + "description": "Whether to expose base_addr and base_hart_id", + "default": false }, - "lat_noncomp": { - "type": "number", - "description": "Latency setting (number of pipeline stages) for floating-point non-computational instructions (except conversions), i.e., `classify`, etc.", - "default": 1 + "sram_cfg_expose": { + "type": "boolean", + "description": "Whether to expose memory cut configuration inputs for implementation", + "default": false }, - "lat_conv": { - "type": "number", - "description": "Latency setting (number of pipeline stages) for floating-point conversion instructions.", - "default": 1 + "sram_cfg_fields": { + "type": "object", + "description": "The names and widths of memory cut configuration inputs needed for implementation", + "default": {"reserved" : 1}, + "minProperties": 1, + "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, + "additionalProperties": { "type": "number", "minimum": 1 } }, - "lat_sdotp": { - "type": "number", - "description": "Latency setting (number of pipeline stages) for floating-point expanding dot product with accumulation.", - "default": 2 + "timing": { + "type": "object", + "title": "Timing and Latency Tuning Parameter", + "properties": { + "iso_crossings": { + "type": "boolean", + "description": "Enable isochronous crossings, this clocks the integer core at half the speed of the rest of the system.", + "default": false + }, + "narrow_xbar_latency": { + "type": "string", + "description": "Latency mode of the cluster crossbar.", + "enum": [ + "NO_LATENCY", + "CUT_SLV_AX", + "CUT_MST_AX", + "CUT_ALL_AX", + "CUT_SLV_PORTS", + "CUT_MST_PORTS", + "CUT_ALL_PORTS" + ], + "default": "CUT_ALL_PORTS" + }, + "wide_xbar_latency": { + "type": "string", + "description": "Latency mode of the DMA crossbar.", + "enum": [ + "NO_LATENCY", + "CUT_SLV_AX", + "CUT_MST_AX", + "CUT_ALL_AX", + "CUT_SLV_PORTS", + "CUT_MST_PORTS", + "CUT_ALL_PORTS" + ], + "default": "CUT_ALL_PORTS" + }, + "register_offload_req": { + "type": "boolean", + "description": "Insert Pipeline registers into off-loading path (request).", + "default": false + }, + "register_offload_rsp": { + "type": "boolean", + "description": "Insert Pipeline registers into off-loading path (response).", + "default": false + }, + "register_core_req": { + "type": "boolean", + "description": "Insert Pipeline registers into data memory request path.", + "default": false + }, + "register_core_rsp": { + "type": "boolean", + "description": "Insert Pipeline registers into data memory response path.", + "default": false + }, + "register_fpu_req": { + "type": "boolean", + "description": "Insert Pipeline register into the FPU request data path", + "default": false + }, + "register_fpu_in": { + "type": "boolean", + "description": "Insert Pipeline registers immediately before FPU datapath", + "default": false + }, + "register_fpu_out": { + "type": "boolean", + "description": "Insert Pipeline registers immediately after FPU datapath", + "default": false + }, + "register_tcdm_cuts": { + "type": "boolean", + "description": "Insert Pipeline registers after each memory cut.", + "default": false + }, + "register_ext_wide": { + "type": "boolean", + "description": "Decouple wide external AXI plug.", + "default": false + }, + "register_ext_narrow": { + "type": "boolean", + "description": "Decouple narrow external AXI plug.", + "default": false + }, + "register_sequencer": { + "type": "boolean", + "description": "Insert Pipeline registers after sequencer.", + "default": false + }, + "lat_comp_fp32": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP32.", + "default": 3 + }, + "lat_comp_fp64": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP64.", + "default": 3 + }, + "lat_comp_fp16": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP16.", + "default": 1 + }, + "lat_comp_fp16_alt": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP16alt (brainfloat).", + "default": 2 + }, + "lat_comp_fp8": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP8.", + "default": 1 + }, + "lat_comp_fp8alt": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for FP8alt.", + "default": 1 + }, + "lat_noncomp": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for floating-point non-computational instructions (except conversions), i.e., `classify`, etc.", + "default": 1 + }, + "lat_conv": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for floating-point conversion instructions.", + "default": 1 + }, + "lat_sdotp": { + "type": "number", + "description": "Latency setting (number of pipeline stages) for floating-point expanding dot product with accumulation.", + "default": 2 + }, + "fpu_pipe_config": { + "type": "string", + "description": "Pipeline configuration (i.e., position of the registers) of the FPU.", + "enum": [ + "BEFORE", + "AFTER", + "INSIDE", + "DISTRIBUTED" + ], + "default": "BEFORE" + } + } }, - "fpu_pipe_config": { - "type": "string", - "description": "Pipeline configuration (i.e., position of the registers) of the FPU.", - "enum": [ - "BEFORE", - "AFTER", - "INSIDE", - "DISTRIBUTED" - ], - "default": "BEFORE" - } - } - }, - "hives": { - "type": "array", - "title": "Hives", - "description": "Cores in a hive share an instruction cache and other shared infrastructure such as the PTW or the multiply/divide unit.", - "minItems": 1, - "items": { - "type": "object", - "title": "Hive Description", - "description": "Configuration of a Hive", - "properties": { - "icache": { + "hives": { + "type": "array", + "title": "Hives", + "description": "Cores in a hive share an instruction cache and other shared infrastructure such as the PTW or the multiply/divide unit.", + "minItems": 1, + "items": { "type": "object", - "title": "Hive's instruction cache configuration.", - "description": "Detailed configuration of the current Hive's instruction cache.", - "default": { - "size": 8, - "sets": 2, - "cacheline": 128 - }, + "title": "Hive Description", + "description": "Configuration of a Hive", "properties": { - "size": { - "type": "number", - "description": "Total instruction cache size in KiByte." - }, - "sets": { - "type": "number", - "description": "Number of ways." - }, - "cacheline": { - "type": "number", - "description": "Cacheline/Word size in bits." - } - } - }, - "cores": { - "type": "array", - "title": "Cores", - "description": "List of all cores in the respective hive.", - "minItems": 1, - "items": { - "type": "object", - "title": "Core Description", - "description": "Description of a single core.", - "properties": { - "isa": { - "type": "string", - "title": "ISA String containing RISC-V standard extensions.", - "description": "ISA string as defined by the RISC-V standard. Only contain the standardized ISA extensions.", - "examples": [ - "rv32imafd" - ], - "default": "rv32imafd" - }, - "Xdiv_sqrt": { - "type": "boolean", - "description": "Enable hardware support for floating-point division and square-root. The iterative floating-point unit is known to produce some rounding inaccuracies so it is disabled by default.", - "default": false - }, - "xssr": { - "type": "boolean", - "title": "Enable Xssr Extension", - "description": "Stream Semantic Registers (Xssr) custom extension.", - "default": true - }, - "xfrep": { - "type": "boolean", - "title": "Enable Xfrep Extension", - "description": "Floating-point repetition buffer (Xfrep) custom extension.", - "default": true - }, - "xdma": { - "type": "boolean", - "title": "Xdma Extension", - "description": "Direct memory access (Xdma) custom extension.", - "default": false - }, - "xf8": { - "type": "boolean", - "title": "Xf8 8-bit Float Extension", - "description": "Enable Smallfloat Xf8 extension (IEEE 8-bit float).", - "default": false - }, - "xf8alt": { - "type": "boolean", - "title": "Xf8 8-bit Float Extension", - "description": "Enable Smallfloat Xf8alt extension.", - "default": false - }, - "xf16": { - "type": "boolean", - "title": "Xf16 16-bit Float Extension", - "description": "Enable Smallfloat Xf16 extension (IEEE 16-bit float).", - "default": false - }, - "xf16alt": { - "type": "boolean", - "title": "Xf16alt 16-bit Brain-Float Extension", - "description": "Enable Smallfloat Xf16alt extension, also known as brain-float.", - "default": false - }, - "xfdotp": { - "type": "boolean", - "title": "Xfdotp Extension", - "description": "Enable DOTP extensions.", - "default": false - }, - "xfvec": { - "type": "boolean", - "title": "Xfvec Extension", - "description": "Enable Smallfloat vector extension (SIMD).", - "default": false - }, - "num_int_outstanding_loads": { - "type": "number", - "description": "Number of outstanding integer loads. Determines the buffer size in the core's load/store unit.", - "default": 1 - }, - "num_int_outstanding_mem": { - "type": "number", - "description": "Number of outstanding memory operations. Determines the buffer size in the core's load/store unit.", - "default": 1 - }, - "num_fp_outstanding_loads": { - "type": "number", - "description": "Number of outstanding floating-point loads. Determines the buffer size in the FPU's load/store unit.", - "default": 4 + "icache": { + "type": "object", + "title": "Hive's instruction cache configuration.", + "description": "Detailed configuration of the current Hive's instruction cache.", + "default": { + "size": 8, + "sets": 2, + "cacheline": 128 }, - "num_fp_outstanding_mem": { - "type": "number", - "description": "Number of outstanding memory operations. Determines the buffer size in the core's load/store unit.", - "default": 1 - }, - "num_sequencer_instructions": { - "type": "number", - "description": "Amount of floating-point instruction the floating-point sequence buffer can hold.", - "default": 16 - }, - "num_itlb_entries": { - "type": "number", - "description": "Number of ITLB entries. Determines the core's size.", - "default": 1 - }, - "num_dtlb_entries": { - "type": "number", - "description": "Number of DTLB entries. Determines the core's size.", - "default": 2 - }, - "ssr_intersection": { - "type": "boolean", - "title": "SSR Intersection Feature", - "description": "Enable intersection between 3 SSRs for sparse-sparse processing.", - "default": false - }, - "ssr_intersection_triple": { - "type": "array", - "title": "SSR Intersection Triple", - "description": "Indices of the SSRs forming an SSR intersection triple.", - "maxItems": 3, - "minItems": 3, - "default": [0, 1, 2], - "items": { - "type": "number" - } - }, - "ssr_mux_resp_depth": { - "type": "number", - "description": "Depth of response buffer in the TCDM multiplexer arbitrating between core and SSR 0.", - "default": 4 - }, - "ssrs": { - "type": "array", - "title": "SSRs", - "description": "List of all SSRs in the respective core.", - "minItems": 0, - "default": [{}, {}, {}], - "items": { - "type": "object", - "title": "SSR Description", - "description": "Description of a single Stream Semantic Register.", - "properties": { - "reg_idx": { - "type": ["number", "null"], - "description": "The floating-point register index this SSR is assigned to. If not assigned, the next available index counting from 0 is chosen.", - "minimum": 0, - "maximum": 31, - "default": null - }, - "indirection": { - "type": "boolean", - "description": "Enable indirection extension.", - "default": false - }, - "indir_out_spill": { - "type": "boolean", - "description": "Whether to cut timing paths with a spill register at the address generator output; added only if indirection extension enabled.", - "default": true - }, - "isect_slave_spill": { - "type": "boolean", - "description": "Whether to cut timing paths with a spill register at the intersector index output; added only if this SSR is an intersection slave.", - "default": true - }, - "isect_slave_credits": { - "type": "number", - "description": "Number of elements by which intersected indices may outrun corresponding data; added only if this SSR is an intersection slave.", - "minimum": 2, - "default": 8 - }, - "num_loops": { - "type": "number", - "description": "Number of nested hardware loops in address generator.", - "minimum": 1, - "maximum": 4, - "default": 4 - }, - "index_credits": { - "type": "number", - "description": "Number of credits and buffer depth of the index word FIFO.", - "minimum": 1, - "default": 3 - }, - "data_credits": { - "type": "number", - "description": "Number of credits and buffer depth of the data word FIFO.", - "minimum": 1, - "default": 4 - }, - "mux_resp_depth": { - "type": "number", - "description": "Depth of response buffer in the TCDM multiplexer arbitrating between data and indices.", - "minimum": 1, - "default": 3 - }, - "index_width": { - "type": ["number", "null"], - "description": "Internal bitwidth of indices in address generator; default covers full TCDM in a unit-stride 1D loop.", - "minimum": 1, - "maximum": 32, - "default": null - }, - "pointer_width": { - "type": ["number", "null"], - "description": "Internal bitwidth of pointers in address generator; default covers full TCDM", - "maximum": 32, - "default": null - }, - "shift_width": { - "type": "number", - "description": "Internal bitwidth of additional left shift amount for indirect indices.", - "minimum": 1, - "maximum": 32, - "default": 3 - }, - "rpt_width": { - "type": "number", - "description": "Internal bitwidth of repetition counter for read streams.", - "minimum": 1, - "maximum": 32, - "default": 4 + "properties": { + "size": { + "type": "number", + "description": "Total instruction cache size in KiByte." + }, + "sets": { + "type": "number", + "description": "Number of ways." + }, + "cacheline": { + "type": "number", + "description": "Cacheline/Word size in bits." + } + } + }, + "cores": { + "type": "array", + "title": "Cores", + "description": "List of all cores in the respective hive.", + "minItems": 1, + "items": { + "type": "object", + "title": "Core Description", + "description": "Description of a single core.", + "properties": { + "isa": { + "type": "string", + "title": "ISA String containing RISC-V standard extensions.", + "description": "ISA string as defined by the RISC-V standard. Only contain the standardized ISA extensions.", + "examples": [ + "rv32imafd" + ], + "default": "rv32imafd" + }, + "Xdiv_sqrt": { + "type": "boolean", + "description": "Enable hardware support for floating-point division and square-root. The iterative floating-point unit is known to produce some rounding inaccuracies so it is disabled by default.", + "default": false + }, + "xssr": { + "type": "boolean", + "title": "Enable Xssr Extension", + "description": "Stream Semantic Registers (Xssr) custom extension.", + "default": true + }, + "xfrep": { + "type": "boolean", + "title": "Enable Xfrep Extension", + "description": "Floating-point repetition buffer (Xfrep) custom extension.", + "default": true + }, + "xdma": { + "type": "boolean", + "title": "Xdma Extension", + "description": "Direct memory access (Xdma) custom extension.", + "default": false + }, + "xf8": { + "type": "boolean", + "title": "Xf8 8-bit Float Extension", + "description": "Enable Smallfloat Xf8 extension (IEEE 8-bit float).", + "default": false + }, + "xf8alt": { + "type": "boolean", + "title": "Xf8 8-bit Float Extension", + "description": "Enable Smallfloat Xf8alt extension.", + "default": false + }, + "xf16": { + "type": "boolean", + "title": "Xf16 16-bit Float Extension", + "description": "Enable Smallfloat Xf16 extension (IEEE 16-bit float).", + "default": false + }, + "xf16alt": { + "type": "boolean", + "title": "Xf16alt 16-bit Brain-Float Extension", + "description": "Enable Smallfloat Xf16alt extension, also known as brain-float.", + "default": false + }, + "xfdotp": { + "type": "boolean", + "title": "Xfdotp Extension", + "description": "Enable DOTP extensions.", + "default": false + }, + "xfvec": { + "type": "boolean", + "title": "Xfvec Extension", + "description": "Enable Smallfloat vector extension (SIMD).", + "default": false + }, + "num_int_outstanding_loads": { + "type": "number", + "description": "Number of outstanding integer loads. Determines the buffer size in the core's load/store unit.", + "default": 1 + }, + "num_int_outstanding_mem": { + "type": "number", + "description": "Number of outstanding memory operations. Determines the buffer size in the core's load/store unit.", + "default": 1 + }, + "num_fp_outstanding_loads": { + "type": "number", + "description": "Number of outstanding floating-point loads. Determines the buffer size in the FPU's load/store unit.", + "default": 4 + }, + "num_fp_outstanding_mem": { + "type": "number", + "description": "Number of outstanding memory operations. Determines the buffer size in the core's load/store unit.", + "default": 1 + }, + "num_sequencer_instructions": { + "type": "number", + "description": "Amount of floating-point instruction the floating-point sequence buffer can hold.", + "default": 16 + }, + "num_itlb_entries": { + "type": "number", + "description": "Number of ITLB entries. Determines the core's size.", + "default": 1 + }, + "num_dtlb_entries": { + "type": "number", + "description": "Number of DTLB entries. Determines the core's size.", + "default": 2 + }, + "ssr_intersection": { + "type": "boolean", + "title": "SSR Intersection Feature", + "description": "Enable intersection between 3 SSRs for sparse-sparse processing.", + "default": false + }, + "ssr_intersection_triple": { + "type": "array", + "title": "SSR Intersection Triple", + "description": "Indices of the SSRs forming an SSR intersection triple.", + "maxItems": 3, + "minItems": 3, + "default": [0, 1, 2], + "items": { + "type": "number" + } + }, + "ssr_mux_resp_depth": { + "type": "number", + "description": "Depth of response buffer in the TCDM multiplexer arbitrating between core and SSR 0.", + "default": 4 + }, + "ssrs": { + "type": "array", + "title": "SSRs", + "description": "List of all SSRs in the respective core.", + "minItems": 0, + "default": [{}, {}, {}], + "items": { + "type": "object", + "title": "SSR Description", + "description": "Description of a single Stream Semantic Register.", + "properties": { + "reg_idx": { + "type": ["number", "null"], + "description": "The floating-point register index this SSR is assigned to. If not assigned, the next available index counting from 0 is chosen.", + "minimum": 0, + "maximum": 31, + "default": null + }, + "indirection": { + "type": "boolean", + "description": "Enable indirection extension.", + "default": false + }, + "indir_out_spill": { + "type": "boolean", + "description": "Whether to cut timing paths with a spill register at the address generator output; added only if indirection extension enabled.", + "default": true + }, + "isect_slave_spill": { + "type": "boolean", + "description": "Whether to cut timing paths with a spill register at the intersector index output; added only if this SSR is an intersection slave.", + "default": true + }, + "isect_slave_credits": { + "type": "number", + "description": "Number of elements by which intersected indices may outrun corresponding data; added only if this SSR is an intersection slave.", + "minimum": 2, + "default": 8 + }, + "num_loops": { + "type": "number", + "description": "Number of nested hardware loops in address generator.", + "minimum": 1, + "maximum": 4, + "default": 4 + }, + "index_credits": { + "type": "number", + "description": "Number of credits and buffer depth of the index word FIFO.", + "minimum": 1, + "default": 3 + }, + "data_credits": { + "type": "number", + "description": "Number of credits and buffer depth of the data word FIFO.", + "minimum": 1, + "default": 4 + }, + "mux_resp_depth": { + "type": "number", + "description": "Depth of response buffer in the TCDM multiplexer arbitrating between data and indices.", + "minimum": 1, + "default": 3 + }, + "index_width": { + "type": ["number", "null"], + "description": "Internal bitwidth of indices in address generator; default covers full TCDM in a unit-stride 1D loop.", + "minimum": 1, + "maximum": 32, + "default": null + }, + "pointer_width": { + "type": ["number", "null"], + "description": "Internal bitwidth of pointers in address generator; default covers full TCDM", + "maximum": 32, + "default": null + }, + "shift_width": { + "type": "number", + "description": "Internal bitwidth of additional left shift amount for indirect indices.", + "minimum": 1, + "maximum": 32, + "default": 3 + }, + "rpt_width": { + "type": "number", + "description": "Internal bitwidth of repetition counter for read streams.", + "minimum": 1, + "maximum": 32, + "default": 4 + } + } } } } @@ -630,6 +631,49 @@ } } } + }, + "nr_clusters": { + "type": "number", + "description": "Number of clusters. Relevant for the SW runtime.", + "default": 1 + }, + "external_addr_regions": { + "type": "array", + "description": "List of external address regions.", + "items": { + "type": "object", + "description": "Description of an external address region.", + "properties": { + "name": { + "description": "Name of the address region.", + "type": "string" + }, + "address": { + "description": "Start address of the address region.", + "type": "integer" + }, + "length": { + "description": "Length of the address region.", + "type": "integer" + }, + "cacheable": { + "description": "Whether the address region is cacheable.", + "type": "boolean", + "default": false + } + }, + "required": ["name", "address", "length"] + }, + "allOf": [ + { + "contains": { "properties": { "name": { "const": "dram" } } }, + "minContains": 1 + }, + { + "contains": { "properties": { "name": { "const": "clint" } } }, + "minContains": 1 + } + ] } } } From 53a329e2e0f037bc46fcd23ec169d1ecba894696 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 16:59:43 +0100 Subject: [PATCH 03/19] cfg: Update configs --- target/snitch_cluster/cfg/default.hjson | 21 ++++++++++----------- target/snitch_cluster/cfg/dma_mchan.hjson | 21 ++++++++++----------- target/snitch_cluster/cfg/fdiv.hjson | 21 ++++++++++----------- target/snitch_cluster/cfg/github-ci.hjson | 21 ++++++++++----------- target/snitch_cluster/cfg/omega.hjson | 21 ++++++++++----------- 5 files changed, 50 insertions(+), 55 deletions(-) diff --git a/target/snitch_cluster/cfg/default.hjson b/target/snitch_cluster/cfg/default.hjson index f24d7dfea5..9697058e32 100644 --- a/target/snitch_cluster/cfg/default.hjson +++ b/target/snitch_cluster/cfg/default.hjson @@ -80,20 +80,19 @@ } ] }, - dram: { - // 0x8000_0000 - address: 2147483648, - // 0x8000_0000 - length: 2147483648 - }, - peripherals: { - clint: { - // 0xffff_0000 + external_addr_regions: [ + { + name: "dram" + address: 2147483648, + length: 2147483648, + cacheable: true + }, + { + name: "clint" address: 4294901760, - // 0x0000_1000 length: 4096 }, - }, + ], // Templates. compute_core_template: { isa: "rv32imafd", diff --git a/target/snitch_cluster/cfg/dma_mchan.hjson b/target/snitch_cluster/cfg/dma_mchan.hjson index 55bad7e249..9b4b1fb338 100644 --- a/target/snitch_cluster/cfg/dma_mchan.hjson +++ b/target/snitch_cluster/cfg/dma_mchan.hjson @@ -81,20 +81,19 @@ } ] }, - dram: { - // 0x8000_0000 - address: 2147483648, - // 0x8000_0000 - length: 2147483648 - }, - peripherals: { - clint: { - // 0xffff_0000 + external_addr_regions: [ + { + name: "dram" + address: 2147483648, + length: 2147483648, + cacheable: true + }, + { + name: "clint" address: 4294901760, - // 0x0000_1000 length: 4096 }, - }, + ], // Templates. compute_core_template: { isa: "rv32imafd", diff --git a/target/snitch_cluster/cfg/fdiv.hjson b/target/snitch_cluster/cfg/fdiv.hjson index d3e574b526..43ba345813 100644 --- a/target/snitch_cluster/cfg/fdiv.hjson +++ b/target/snitch_cluster/cfg/fdiv.hjson @@ -80,20 +80,19 @@ } ] }, - dram: { - // 0x8000_0000 - address: 2147483648, - // 0x8000_0000 - length: 2147483648 - }, - peripherals: { - clint: { - // 0xffff_0000 + external_addr_regions: [ + { + name: "dram" + address: 2147483648, + length: 2147483648, + cacheable: true + }, + { + name: "clint" address: 4294901760, - // 0x0000_1000 length: 4096 }, - }, + ], // Templates. compute_core_template: { isa: "rv32imafd", diff --git a/target/snitch_cluster/cfg/github-ci.hjson b/target/snitch_cluster/cfg/github-ci.hjson index db50e697be..17334916a2 100644 --- a/target/snitch_cluster/cfg/github-ci.hjson +++ b/target/snitch_cluster/cfg/github-ci.hjson @@ -76,20 +76,19 @@ } ] }, - dram: { - // 0x8000_0000 - address: 2147483648, - // 0x8000_0000 - length: 2147483648 - }, - peripherals: { - clint: { - // 0xffff_0000 + external_addr_regions: [ + { + name: "dram" + address: 2147483648, + length: 2147483648, + cacheable: true + }, + { + name: "clint" address: 4294901760, - // 0x0000_1000 length: 4096 }, - }, + ], // Templates. compute_core_template: { isa: "rv32imafd", diff --git a/target/snitch_cluster/cfg/omega.hjson b/target/snitch_cluster/cfg/omega.hjson index 4400dab42d..db317aacb0 100644 --- a/target/snitch_cluster/cfg/omega.hjson +++ b/target/snitch_cluster/cfg/omega.hjson @@ -81,20 +81,19 @@ } ] }, - dram: { - // 0x8000_0000 - address: 2147483648, - // 0x8000_0000 - length: 2147483648 - }, - peripherals: { - clint: { - // 0xffff_0000 + external_addr_regions: [ + { + name: "dram" + address: 2147483648, + length: 2147483648, + cacheable: true + }, + { + name: "clint" address: 4294901760, - // 0x0000_1000 length: 4096 }, - }, + ], // Templates. compute_core_template: { isa: "rv32imafd", From b80638be15ce615585b056479862a4cec0a0e4ad Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 17:39:25 +0100 Subject: [PATCH 04/19] clustergen: Only support generic `template` flag --- .../src/snitch_cluster_wrapper.sv.tpl | 4 +++ target/snitch_cluster/Makefile | 17 +++++++---- util/clustergen.py | 28 +++---------------- util/clustergen/cluster.py | 15 ---------- 4 files changed, 19 insertions(+), 45 deletions(-) diff --git a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl index 024c6a836f..f565591e1a 100644 --- a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +++ b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl @@ -4,6 +4,10 @@ ${disclaimer} +<%def name="to_sv_hex(x, length=None)">\ +${"{}'h{}".format(length or "", hex(x)[2:])}\ + + <%def name="icache_cfg(prop)"> % for lw in cfg['cluster']['hives']: ${lw['icache'][prop]}${',' if not loop.last else ''} diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 33583a34d2..6c056cb8ee 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -161,17 +161,22 @@ clean-rtl: $(GENERATED_DIR): mkdir -p $@ -$(GENERATED_DIR)/snitch_cluster_wrapper.sv: ${CFG} ${CLUSTER_GEN_PREREQ} | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --wrapper +CLUSTER_GEN_TPL = $(ROOT)/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +LINK_LD_TPL = $(ROOT)/hw/snitch_cluster/test/link.ld.tpl +BOOTDATA_TPL = $(ROOT)/hw/snitch_cluster/test/bootdata.cc.tpl -$(GENERATED_DIR)/link.ld: ${CFG} ${CLUSTER_GEN_PREREQ} | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --linker +$(GENERATED_DIR)/snitch_cluster_wrapper.sv: ${CFG} ${CLUSTER_GEN_PREREQ} ${CLUSTER_GEN_TPL} | $(GENERATED_DIR) + $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${CLUSTER_GEN_TPL} + +$(GENERATED_DIR)/link.ld: ${CFG} ${CLUSTER_GEN_PREREQ} ${LINK_LD_TPL}| $(GENERATED_DIR) + $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${LINK_LD_TPL} + +$(GENERATED_DIR)/bootdata.cc: ${CFG} ${CLUSTER_GEN_PREREQ} ${BOOTDATA_TPL}| $(GENERATED_DIR) + $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${BOOTDATA_TPL} $(GENERATED_DIR)/memories.json: ${CFG} ${CLUSTER_GEN_PREREQ} | $(GENERATED_DIR) $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --memories -$(GENERATED_DIR)/bootdata.cc: ${CFG} ${CLUSTER_GEN_PREREQ} | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --bootdata # REGGEN regfile $(PERIPH_DIR)/snitch_cluster_peripheral_reg_pkg.sv: $(PERIPH_DIR)/snitch_cluster_peripheral_reg_top.sv diff --git a/util/clustergen.py b/util/clustergen.py index 7ccae24167..652a708e3e 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -46,15 +46,6 @@ def main(): type=pathlib.Path, required=True, help="Target directory.") - parser.add_argument("--wrapper", - action="store_true", - help="Generate Snitch cluster wrapper") - parser.add_argument("--linker", - action="store_true", - help="Generate linker script") - parser.add_argument("--bootdata", - action="store_true", - help="Generate bootdata") parser.add_argument("--memories", action="store_true", help="Generate memories") @@ -73,7 +64,7 @@ def main(): except ValueError: raise SystemExit(sys.exc_info()[1]) - cluster_tb = SnitchCluster(obj) + cluster = SnitchCluster(obj) if not args.outdir.is_dir(): exit("Out directory is not a valid path.") @@ -85,28 +76,17 @@ def main(): # Misc files # ############## - if args.wrapper: - with open(outdir / "snitch_cluster_wrapper.sv", "w") as f: - f.write(cluster_tb.render_wrapper()) - - if args.linker: - with open(outdir / "link.ld", "w") as f: - f.write(cluster_tb.render_linker_script()) - - if args.bootdata: - with open(outdir / "bootdata.cc", "w") as f: - f.write(cluster_tb.render_bootdata()) - if args.memories: with open(outdir / "memories.json", "w") as f: - f.write(cluster_tb.cluster.memory_cfg()) + f.write(cluster.memory_cfg()) #################### # Generic template # #################### kwargs = { - "cfg": cluster_tb.cfg, + "disclaimer": cluster.DISCLAIMER, + "cfg": cluster.cfg, } if args.template: diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index eaf766e05e..86a8cb5155 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -143,10 +143,6 @@ class SnitchCluster(Generator): """ Instance of a Snitch cluster. """ - files = { - 'cfg': "src/snitch_cfg.sv.tpl", - 'wrapper': "src/snitch_cluster_wrapper.sv.tpl" - } def __init__(self, cfg): """ @@ -172,13 +168,6 @@ def l1_region(self): """Return L1 Region as tuple. Base and length.""" return (self.cfg['cluster_base_addr'], self.cfg['tcdm']['size']) - def render_wrapper(self): - """Render the cluster wrapper""" - cfg_template = self.templates.get_template(self.files['wrapper']) - return cfg_template.render_unicode(cfg=self.cfg, - to_sv_hex=to_sv_hex, - disclaimer=self.DISCLAIMER) - def add_mem(self, words, width, @@ -377,7 +366,3 @@ def clog2(x): def is_pow2(x): return 2**clog2(x) != x - - -def to_sv_hex(x, length=None): - return "{}'h{}".format(length or "", hex(x)[2:]) From 5990548c26bec219e0abee3be5ce843e6a0606c6 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 17:58:10 +0100 Subject: [PATCH 05/19] cfg: Support hex value input --- target/snitch_cluster/cfg/default.hjson | 10 +++++----- target/snitch_cluster/cfg/dma_mchan.hjson | 10 +++++----- target/snitch_cluster/cfg/fdiv.hjson | 10 +++++----- target/snitch_cluster/cfg/github-ci.hjson | 10 +++++----- target/snitch_cluster/cfg/omega.hjson | 10 +++++----- util/clustergen.py | 17 +++++++++++++++-- 6 files changed, 40 insertions(+), 27 deletions(-) diff --git a/target/snitch_cluster/cfg/default.hjson b/target/snitch_cluster/cfg/default.hjson index 9697058e32..d79af54e20 100644 --- a/target/snitch_cluster/cfg/default.hjson +++ b/target/snitch_cluster/cfg/default.hjson @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 268435456, // 0x1000_0000 + cluster_base_addr: 0x1000_0000, cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, addr_width: 48, @@ -83,14 +83,14 @@ external_addr_regions: [ { name: "dram" - address: 2147483648, - length: 2147483648, + address: 0x8000_0000, + length: 0x8000_0000, cacheable: true }, { name: "clint" - address: 4294901760, - length: 4096 + address: 0xFFFF_0000, + length: 0x1000 }, ], // Templates. diff --git a/target/snitch_cluster/cfg/dma_mchan.hjson b/target/snitch_cluster/cfg/dma_mchan.hjson index 9b4b1fb338..96bce71213 100644 --- a/target/snitch_cluster/cfg/dma_mchan.hjson +++ b/target/snitch_cluster/cfg/dma_mchan.hjson @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 268435456, // 0x1000_0000 + cluster_base_addr: 0x1000_0000, cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, addr_width: 48, @@ -84,14 +84,14 @@ external_addr_regions: [ { name: "dram" - address: 2147483648, - length: 2147483648, + address: 0x8000_0000, + length: 0x8000_0000, cacheable: true }, { name: "clint" - address: 4294901760, - length: 4096 + address: 0xFFFF_0000, + length: 0x1000 }, ], // Templates. diff --git a/target/snitch_cluster/cfg/fdiv.hjson b/target/snitch_cluster/cfg/fdiv.hjson index 43ba345813..9e30023214 100644 --- a/target/snitch_cluster/cfg/fdiv.hjson +++ b/target/snitch_cluster/cfg/fdiv.hjson @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 268435456, // 0x1000_0000 + cluster_base_addr: 0x1000_0000, cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, addr_width: 48, @@ -83,14 +83,14 @@ external_addr_regions: [ { name: "dram" - address: 2147483648, - length: 2147483648, + address: 0x8000_0000, + length: 0x8000_0000, cacheable: true }, { name: "clint" - address: 4294901760, - length: 4096 + address: 0xFFFF_0000, + length: 0x1000 }, ], // Templates. diff --git a/target/snitch_cluster/cfg/github-ci.hjson b/target/snitch_cluster/cfg/github-ci.hjson index 17334916a2..b6f1fd6b52 100644 --- a/target/snitch_cluster/cfg/github-ci.hjson +++ b/target/snitch_cluster/cfg/github-ci.hjson @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 268435456, // 0x1000_0000 + cluster_base_addr: 0x1000_0000, cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, addr_width: 48, @@ -79,14 +79,14 @@ external_addr_regions: [ { name: "dram" - address: 2147483648, - length: 2147483648, + address: 0x8000_0000, + length: 0x8000_0000, cacheable: true }, { name: "clint" - address: 4294901760, - length: 4096 + address: 0xFFFF_0000, + length: 0x1000 }, ], // Templates. diff --git a/target/snitch_cluster/cfg/omega.hjson b/target/snitch_cluster/cfg/omega.hjson index db317aacb0..caaf4572cc 100644 --- a/target/snitch_cluster/cfg/omega.hjson +++ b/target/snitch_cluster/cfg/omega.hjson @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 268435456, // 0x1000_0000 + cluster_base_addr: 0x1000_0000, cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, addr_width: 48, @@ -84,14 +84,14 @@ external_addr_regions: [ { name: "dram" - address: 2147483648, - length: 2147483648, + address: 0x8000_0000, + length: 0x8000_0000, cacheable: true }, { name: "clint" - address: 4294901760, - length: 4096 + address: 0xFFFF_0000, + length: 0x1000 }, ], // Templates. diff --git a/util/clustergen.py b/util/clustergen.py index 652a708e3e..59165e3e6b 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -13,6 +13,17 @@ from clustergen.cluster import SnitchCluster from mako.template import Template +# Regex to find hex numbers with optional underscores +HEX_PATTERN = re.compile(r"0x[0-9a-fA-F]+(?:_[0-9a-fA-F]+)*") + +def preprocess_hex_in_hjson(text): + """ Converts hex numbers (e.g., 0x8000_0000) to decimal before parsing HJSON. """ + def hex_to_decimal(match): + hex_str = match.group(0).replace("_", "") # Remove underscores + return str(int(hex_str, 16)) # Convert to decimal and replace + + return HEX_PATTERN.sub(hex_to_decimal, text) + def write_template(tpl_path, outdir, fname=None, **kwargs): @@ -55,12 +66,14 @@ def main(): args = parser.parse_args() - # Read HJSON description + # Read and preprocess HJSON file with args.clustercfg as file: try: srcfull = file.read() - obj = hjson.loads(srcfull, use_decimal=True) + srcfull = preprocess_hex_in_hjson(srcfull) # Convert hex to decimal + obj = hjson.loads(srcfull, use_decimal=True) # Now parse clean HJSON obj = JsonRef.replace_refs(obj) + except ValueError: raise SystemExit(sys.exc_info()[1]) From ca457628a0b2c37d5e3bae409e9c4bc9b46968ef Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 18:02:51 +0100 Subject: [PATCH 06/19] schema: remove TB schema --- .../schema/snitch_cluster_tb.schema.json | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 util/clustergen/schema/snitch_cluster_tb.schema.json diff --git a/util/clustergen/schema/snitch_cluster_tb.schema.json b/util/clustergen/schema/snitch_cluster_tb.schema.json deleted file mode 100644 index 36fd1036ab..0000000000 --- a/util/clustergen/schema/snitch_cluster_tb.schema.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "http://pulp-platform.org/snitch_cluster/snitch_cluster_tb.schema.json", - "title": "Snitch Cluster TB Schema", - "description": "Description for a very simple single-cluster testbench. That is the most minimal system available. Most of the hardware is emulated by the testbench.", - "type": "object", - "required": [ - "cluster", "dram" - ], - "properties": { - "cluster": { - "$ref": "http://pulp-platform.org/snitch_cluster/snitch_cluster.schema.json" - }, - "nr_clusters": { - "type": "number", - "description": "Number of clusters. Relevant for the SW runtime.", - "default": 1 - }, - "dram": { - "title": "DRAM", - "type": "object", - "description": "Main, off-chip DRAM.", - "required": [ - "address", - "length" - ], - "properties": { - "address": { - "type": "number", - "description": "Start address of DRAM.", - "minimum": 0 - }, - "length": { - "type": "number", - "description": "Total size of DRAM in bytes.", - "minimum": 0 - } - } - } - } -} From f9fb1c7ed805ef40803e135f77916230eced1049 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 4 Feb 2025 18:05:29 +0100 Subject: [PATCH 07/19] lint: Python sources --- util/clustergen.py | 1 + util/clustergen/cluster.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/util/clustergen.py b/util/clustergen.py index 59165e3e6b..88c5a71ea4 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -16,6 +16,7 @@ # Regex to find hex numbers with optional underscores HEX_PATTERN = re.compile(r"0x[0-9a-fA-F]+(?:_[0-9a-fA-F]+)*") + def preprocess_hex_in_hjson(text): """ Converts hex numbers (e.g., 0x8000_0000) to decimal before parsing HJSON. """ def hex_to_decimal(match): diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index 86a8cb5155..599f92a261 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -246,7 +246,8 @@ def gen_pma_cfg(self): pma_cfg = PMACfg() for region in self.cfg['external_addr_regions']: if region["cacheable"]: - pma_cfg.add_region_length(PMA.CACHED, region['address'], region['length'], self.cfg['cluster']['addr_width']) + pma_cfg.add_region_length(PMA.CACHED, region['address'], region['length'], + self.cfg['cluster']['addr_width']) # Populate the list of cached regions self.cfg['pmas'] = dict() self.cfg['pmas']['cached'] = list() @@ -295,7 +296,8 @@ def gen_mask(c, s): if ssr['pointer_width'] is None: ssr['pointer_width'] = 10 + clog2(self.cfg['cluster']['tcdm']['size']) if ssr['index_width'] is None: - ssr['index_width'] = ssr['pointer_width'] - clog2(self.cfg['cluster']['data_width']/8) + ssr['index_width'] = ssr['pointer_width'] + - clog2(self.cfg['cluster']['data_width']/8) # Sort SSRs by register indices (required by decoding logic) core['ssrs'].sort(key=lambda x: x['reg_idx']) # Minimum 1 element to avoid illegal ranges (Xssr prevents generation) From 4889465933d9c88c8504accf50729e2ae513b379 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 09:32:03 +0100 Subject: [PATCH 08/19] cfg: Remove stray comments --- target/snitch_cluster/cfg/default.hjson | 2 +- target/snitch_cluster/cfg/dma_mchan.hjson | 2 +- target/snitch_cluster/cfg/fdiv.hjson | 2 +- target/snitch_cluster/cfg/github-ci.hjson | 2 +- target/snitch_cluster/cfg/omega.hjson | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/snitch_cluster/cfg/default.hjson b/target/snitch_cluster/cfg/default.hjson index d79af54e20..0efd50f12d 100644 --- a/target/snitch_cluster/cfg/default.hjson +++ b/target/snitch_cluster/cfg/default.hjson @@ -6,7 +6,7 @@ { cluster: { cluster_base_addr: 0x1000_0000, - cluster_base_offset: 0, // 0x0 + cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, data_width: 64, diff --git a/target/snitch_cluster/cfg/dma_mchan.hjson b/target/snitch_cluster/cfg/dma_mchan.hjson index 96bce71213..7b247e4e35 100644 --- a/target/snitch_cluster/cfg/dma_mchan.hjson +++ b/target/snitch_cluster/cfg/dma_mchan.hjson @@ -6,7 +6,7 @@ { cluster: { cluster_base_addr: 0x1000_0000, - cluster_base_offset: 0, // 0x0 + cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, data_width: 64, diff --git a/target/snitch_cluster/cfg/fdiv.hjson b/target/snitch_cluster/cfg/fdiv.hjson index 9e30023214..b9ef5c90f8 100644 --- a/target/snitch_cluster/cfg/fdiv.hjson +++ b/target/snitch_cluster/cfg/fdiv.hjson @@ -6,7 +6,7 @@ { cluster: { cluster_base_addr: 0x1000_0000, - cluster_base_offset: 0, // 0x0 + cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, data_width: 64, diff --git a/target/snitch_cluster/cfg/github-ci.hjson b/target/snitch_cluster/cfg/github-ci.hjson index b6f1fd6b52..7a7dc81f41 100644 --- a/target/snitch_cluster/cfg/github-ci.hjson +++ b/target/snitch_cluster/cfg/github-ci.hjson @@ -6,7 +6,7 @@ { cluster: { cluster_base_addr: 0x1000_0000, - cluster_base_offset: 0, // 0x0 + cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, data_width: 64, diff --git a/target/snitch_cluster/cfg/omega.hjson b/target/snitch_cluster/cfg/omega.hjson index caaf4572cc..cdcabebcdd 100644 --- a/target/snitch_cluster/cfg/omega.hjson +++ b/target/snitch_cluster/cfg/omega.hjson @@ -6,7 +6,7 @@ { cluster: { cluster_base_addr: 0x1000_0000, - cluster_base_offset: 0, // 0x0 + cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, data_width: 64, From 3725d539498f35077c3eadee4abb278c0d916873 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 09:40:46 +0100 Subject: [PATCH 09/19] make: Use make rule --- target/common/common.mk | 5 +++++ target/snitch_cluster/Makefile | 15 ++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/target/common/common.mk b/target/common/common.mk index 2c1c774a48..f2fd26baf9 100644 --- a/target/common/common.mk +++ b/target/common/common.mk @@ -193,6 +193,11 @@ define BINARY_SIZE_CHECK @[ "$$(stat -c %s $(1))" -lt "$(2)" ] || (echo "Binary exceeds specified size of $(2)B"; exit 1) endef +define cluster_gen_rule +$(1): $(CFG) $(CLUSTER_GEN_PREREQ) $(2) | $(GENERATED_DIR) + $(CLUSTER_GEN) -c $$< -o $(GENERATED_DIR) $(if $(3),$(3),--template $(2)) +endef + ########## # Traces # ########## diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 6c056cb8ee..90100526a6 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -165,17 +165,10 @@ CLUSTER_GEN_TPL = $(ROOT)/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl LINK_LD_TPL = $(ROOT)/hw/snitch_cluster/test/link.ld.tpl BOOTDATA_TPL = $(ROOT)/hw/snitch_cluster/test/bootdata.cc.tpl -$(GENERATED_DIR)/snitch_cluster_wrapper.sv: ${CFG} ${CLUSTER_GEN_PREREQ} ${CLUSTER_GEN_TPL} | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${CLUSTER_GEN_TPL} - -$(GENERATED_DIR)/link.ld: ${CFG} ${CLUSTER_GEN_PREREQ} ${LINK_LD_TPL}| $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${LINK_LD_TPL} - -$(GENERATED_DIR)/bootdata.cc: ${CFG} ${CLUSTER_GEN_PREREQ} ${BOOTDATA_TPL}| $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --template ${BOOTDATA_TPL} - -$(GENERATED_DIR)/memories.json: ${CFG} ${CLUSTER_GEN_PREREQ} | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $< -o $(GENERATED_DIR) --memories +$(eval $(call cluster_gen_rule,$(GENERATED_DIR)/snitch_cluster_wrapper.sv,$(CLUSTER_GEN_TPL))) +$(eval $(call cluster_gen_rule,$(GENERATED_DIR)/link.ld,$(LINK_LD_TPL))) +$(eval $(call cluster_gen_rule,$(GENERATED_DIR)/bootdata.cc,$(BOOTDATA_TPL))) +$(eval $(call cluster_gen_rule,$(GENERATED_DIR)/memories.json,,--memories)) # REGGEN regfile From 60a7c408d9b0a38f526d97d5b70646cf5dfae7d1 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 09:46:06 +0100 Subject: [PATCH 10/19] clustergen: Remove use of `pkg_name` --- .../src/snitch_cluster_wrapper.sv.tpl | 74 +++++++++---------- util/clustergen/cluster.py | 1 - 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl index f565591e1a..f4076014a3 100644 --- a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +++ b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl @@ -48,7 +48,7 @@ ${',' if not loop.last else ''} `include "axi/typedef.svh" // verilog_lint: waive-start package-filename -package ${cfg['pkg_name']}; +package ${cfg['cluster']['name']}_pkg; localparam int unsigned NrCores = ${cfg['cluster']['nr_cores']}; localparam int unsigned NrHives = ${cfg['cluster']['nr_hives']}; @@ -229,22 +229,22 @@ endpackage module ${cfg['cluster']['name']}_wrapper ( input logic clk_i, input logic rst_ni, - input logic [${cfg['pkg_name']}::NrCores-1:0] debug_req_i, - input logic [${cfg['pkg_name']}::NrCores-1:0] meip_i, - input logic [${cfg['pkg_name']}::NrCores-1:0] mtip_i, - input logic [${cfg['pkg_name']}::NrCores-1:0] msip_i, + input logic [${cfg['cluster']['name']}_pkg::NrCores-1:0] debug_req_i, + input logic [${cfg['cluster']['name']}_pkg::NrCores-1:0] meip_i, + input logic [${cfg['cluster']['name']}_pkg::NrCores-1:0] mtip_i, + input logic [${cfg['cluster']['name']}_pkg::NrCores-1:0] msip_i, input logic [9:0] hart_base_id_i, input logic [${cfg['cluster']['addr_width']-1}:0] cluster_base_addr_i, input logic clk_d2_bypass_i, - input ${cfg['pkg_name']}::sram_cfgs_t sram_cfgs_i, - input ${cfg['pkg_name']}::narrow_in_req_t narrow_in_req_i, - output ${cfg['pkg_name']}::narrow_in_resp_t narrow_in_resp_o, - output ${cfg['pkg_name']}::narrow_out_req_t narrow_out_req_o, - input ${cfg['pkg_name']}::narrow_out_resp_t narrow_out_resp_i, - output ${cfg['pkg_name']}::wide_out_req_t wide_out_req_o, - input ${cfg['pkg_name']}::wide_out_resp_t wide_out_resp_i, - input ${cfg['pkg_name']}::wide_in_req_t wide_in_req_i, - output ${cfg['pkg_name']}::wide_in_resp_t wide_in_resp_o + input ${cfg['cluster']['name']}_pkg::sram_cfgs_t sram_cfgs_i, + input ${cfg['cluster']['name']}_pkg::narrow_in_req_t narrow_in_req_i, + output ${cfg['cluster']['name']}_pkg::narrow_in_resp_t narrow_in_resp_o, + output ${cfg['cluster']['name']}_pkg::narrow_out_req_t narrow_out_req_o, + input ${cfg['cluster']['name']}_pkg::narrow_out_resp_t narrow_out_resp_i, + output ${cfg['cluster']['name']}_pkg::wide_out_req_t wide_out_req_o, + input ${cfg['cluster']['name']}_pkg::wide_out_resp_t wide_out_resp_i, + input ${cfg['cluster']['name']}_pkg::wide_in_req_t wide_in_req_i, + output ${cfg['cluster']['name']}_pkg::wide_in_resp_t wide_in_resp_o ); localparam int unsigned NumIntOutstandingLoads [${cfg['cluster']['nr_cores']}] = '{${core_cfg('num_int_outstanding_loads')}}; @@ -262,20 +262,20 @@ module ${cfg['cluster']['name']}_wrapper ( .PhysicalAddrWidth (${cfg['cluster']['addr_width']}), .NarrowDataWidth (${cfg['cluster']['data_width']}), .WideDataWidth (${cfg['cluster']['dma_data_width']}), - .NarrowIdWidthIn (${cfg['pkg_name']}::NarrowIdWidthIn), - .WideIdWidthIn (${cfg['pkg_name']}::WideIdWidthIn), - .NarrowUserWidth (${cfg['pkg_name']}::NarrowUserWidth), - .WideUserWidth (${cfg['pkg_name']}::WideUserWidth), + .NarrowIdWidthIn (${cfg['cluster']['name']}_pkg::NarrowIdWidthIn), + .WideIdWidthIn (${cfg['cluster']['name']}_pkg::WideIdWidthIn), + .NarrowUserWidth (${cfg['cluster']['name']}_pkg::NarrowUserWidth), + .WideUserWidth (${cfg['cluster']['name']}_pkg::WideUserWidth), .BootAddr (${to_sv_hex(cfg['cluster']['boot_addr'], 32)}), .IntBootromEnable (${int(cfg['cluster']['int_bootrom_enable'])}), - .narrow_in_req_t (${cfg['pkg_name']}::narrow_in_req_t), - .narrow_in_resp_t (${cfg['pkg_name']}::narrow_in_resp_t), - .narrow_out_req_t (${cfg['pkg_name']}::narrow_out_req_t), - .narrow_out_resp_t (${cfg['pkg_name']}::narrow_out_resp_t), - .wide_out_req_t (${cfg['pkg_name']}::wide_out_req_t), - .wide_out_resp_t (${cfg['pkg_name']}::wide_out_resp_t), - .wide_in_req_t (${cfg['pkg_name']}::wide_in_req_t), - .wide_in_resp_t (${cfg['pkg_name']}::wide_in_resp_t), + .narrow_in_req_t (${cfg['cluster']['name']}_pkg::narrow_in_req_t), + .narrow_in_resp_t (${cfg['cluster']['name']}_pkg::narrow_in_resp_t), + .narrow_out_req_t (${cfg['cluster']['name']}_pkg::narrow_out_req_t), + .narrow_out_resp_t (${cfg['cluster']['name']}_pkg::narrow_out_resp_t), + .wide_out_req_t (${cfg['cluster']['name']}_pkg::wide_out_req_t), + .wide_out_resp_t (${cfg['cluster']['name']}_pkg::wide_out_resp_t), + .wide_in_req_t (${cfg['cluster']['name']}_pkg::wide_in_req_t), + .wide_in_resp_t (${cfg['cluster']['name']}_pkg::wide_in_resp_t), .NrHives (${cfg['cluster']['nr_hives']}), .NrCores (${cfg['cluster']['nr_cores']}), .TCDMDepth (${cfg['cluster']['tcdm']['depth']}), @@ -286,9 +286,9 @@ module ${cfg['cluster']['name']}_wrapper ( .DMANumAxInFlight (${cfg['cluster']['dma_axi_req_fifo_depth']}), .DMAReqFifoDepth (${cfg['cluster']['dma_req_fifo_depth']}), .DMANumChannels (${cfg['cluster']['dma_nr_channels']}), - .ICacheLineWidth (${cfg['pkg_name']}::ICacheLineWidth), - .ICacheLineCount (${cfg['pkg_name']}::ICacheLineCount), - .ICacheSets (${cfg['pkg_name']}::ICacheSets), + .ICacheLineWidth (${cfg['cluster']['name']}_pkg::ICacheLineWidth), + .ICacheLineCount (${cfg['cluster']['name']}_pkg::ICacheLineCount), + .ICacheSets (${cfg['cluster']['name']}_pkg::ICacheSets), .VMSupport (${int(cfg['cluster']['vm_support'])}), .RVE (${core_isa('e')}), .RVF (${core_isa('f')}), @@ -303,8 +303,8 @@ module ${cfg['cluster']['name']}_wrapper ( .Xdma (${core_cfg_flat('xdma')}), .Xssr (${core_cfg_flat('xssr')}), .Xfrep (${core_cfg_flat('xfrep')}), - .FPUImplementation (${cfg['pkg_name']}::FPUImplementation), - .SnitchPMACfg (${cfg['pkg_name']}::SnitchPMACfg), + .FPUImplementation (${cfg['cluster']['name']}_pkg::FPUImplementation), + .SnitchPMACfg (${cfg['cluster']['name']}_pkg::SnitchPMACfg), .NumIntOutstandingLoads (NumIntOutstandingLoads), .NumIntOutstandingMem (NumIntOutstandingMem), .NumFPOutstandingLoads (NumFPOutstandingLoads), @@ -314,10 +314,10 @@ module ${cfg['cluster']['name']}_wrapper ( .NumSsrsMax (${cfg['cluster']['num_ssrs_max']}), .NumSsrs (NumSsrs), .SsrMuxRespDepth (SsrMuxRespDepth), - .SsrRegs (${cfg['pkg_name']}::SsrRegs), - .SsrCfgs (${cfg['pkg_name']}::SsrCfgs), + .SsrRegs (${cfg['cluster']['name']}_pkg::SsrRegs), + .SsrCfgs (${cfg['cluster']['name']}_pkg::SsrCfgs), .NumSequencerInstr (NumSequencerInstr), - .Hive (${cfg['pkg_name']}::Hive), + .Hive (${cfg['cluster']['name']}_pkg::Hive), .Topology (snitch_pkg::${cfg['cluster']['tcdm']['topology']}), .Radix (${int(cfg['cluster']['tcdm']['radix'])}), .NumSwitchNets (${int(cfg['cluster']['tcdm']['num_switch_nets'])}), @@ -340,8 +340,8 @@ module ${cfg['cluster']['name']}_wrapper ( .WideMaxSlvTrans (${cfg['cluster']['wide_trans']}), .NarrowMaxMstTrans (${cfg['cluster']['narrow_trans']}), .NarrowMaxSlvTrans (${cfg['cluster']['narrow_trans']}), - .sram_cfg_t (${cfg['pkg_name']}::sram_cfg_t), - .sram_cfgs_t (${cfg['pkg_name']}::sram_cfgs_t), + .sram_cfg_t (${cfg['cluster']['name']}_pkg::sram_cfg_t), + .sram_cfgs_t (${cfg['cluster']['name']}_pkg::sram_cfgs_t), .CaqDepth (${int(cfg['cluster']['caq_depth'])}), .CaqTagWidth (${int(cfg['cluster']['caq_tag_width'])}), .DebugSupport (${int(cfg['cluster']['enable_debug'])}), @@ -373,7 +373,7 @@ module ${cfg['cluster']['name']}_wrapper ( % if cfg['cluster']['sram_cfg_expose']: .sram_cfgs_i (sram_cfgs_i), % else: - .sram_cfgs_i (${cfg['pkg_name']}::sram_cfgs_t'('0)), + .sram_cfgs_i (${cfg['cluster']['name']}_pkg::sram_cfgs_t'('0)), %endif .narrow_in_req_i, .narrow_in_resp_o, diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index 599f92a261..40d39b1bd3 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -158,7 +158,6 @@ def __init__(self, cfg): if self.cfg_validate(): exit("Failed parameter validation.") - self.cfg['pkg_name'] = "{}_pkg".format(self.cfg['cluster']['name']) self.calc_cache_sizes() self.gen_pma_cfg() From 71066046182d0a294c02f716f47a25f37b7eed4e Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 10:01:07 +0100 Subject: [PATCH 11/19] clustergen: Move to JSON5 --- pyproject.toml | 1 - .../cfg/{default.hjson => default.json} | 12 +++++------ .../cfg/{dma_mchan.hjson => dma_mchan.json} | 12 +++++------ .../cfg/{fdiv.hjson => fdiv.json} | 12 +++++------ .../cfg/{github-ci.hjson => github-ci.json} | 12 +++++------ target/snitch_cluster/cfg/lru.json | 1 + .../cfg/{omega.hjson => omega.json} | 12 +++++------ util/clustergen.py | 20 +++---------------- 8 files changed, 34 insertions(+), 48 deletions(-) rename target/snitch_cluster/cfg/{default.hjson => default.json} (95%) rename target/snitch_cluster/cfg/{dma_mchan.hjson => dma_mchan.json} (95%) rename target/snitch_cluster/cfg/{fdiv.hjson => fdiv.json} (95%) rename target/snitch_cluster/cfg/{github-ci.hjson => github-ci.json} (95%) create mode 120000 target/snitch_cluster/cfg/lru.json rename target/snitch_cluster/cfg/{omega.hjson => omega.json} (95%) diff --git a/pyproject.toml b/pyproject.toml index 3bba3730f5..c8aac8b053 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,6 @@ dependencies = [ "editorconfig-checker==2.3.51", "flake8", "gitpython", - "hjson", "humanize", "json5", "jsonref", diff --git a/target/snitch_cluster/cfg/default.hjson b/target/snitch_cluster/cfg/default.json similarity index 95% rename from target/snitch_cluster/cfg/default.hjson rename to target/snitch_cluster/cfg/default.json index 0efd50f12d..59c9c5c89e 100644 --- a/target/snitch_cluster/cfg/default.hjson +++ b/target/snitch_cluster/cfg/default.json @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 0x1000_0000, + cluster_base_addr: 0x10000000, cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, @@ -82,14 +82,14 @@ }, external_addr_regions: [ { - name: "dram" - address: 0x8000_0000, - length: 0x8000_0000, + name: "dram", + address: 0x80000000, + length: 0x80000000, cacheable: true }, { - name: "clint" - address: 0xFFFF_0000, + name: "clint", + address: 0xFFFF0000, length: 0x1000 }, ], diff --git a/target/snitch_cluster/cfg/dma_mchan.hjson b/target/snitch_cluster/cfg/dma_mchan.json similarity index 95% rename from target/snitch_cluster/cfg/dma_mchan.hjson rename to target/snitch_cluster/cfg/dma_mchan.json index 7b247e4e35..2a08c1692f 100644 --- a/target/snitch_cluster/cfg/dma_mchan.hjson +++ b/target/snitch_cluster/cfg/dma_mchan.json @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 0x1000_0000, + cluster_base_addr: 0x10000000, cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, @@ -83,14 +83,14 @@ }, external_addr_regions: [ { - name: "dram" - address: 0x8000_0000, - length: 0x8000_0000, + name: "dram", + address: 0x80000000, + length: 0x80000000, cacheable: true }, { - name: "clint" - address: 0xFFFF_0000, + name: "clint", + address: 0xFFFF0000, length: 0x1000 }, ], diff --git a/target/snitch_cluster/cfg/fdiv.hjson b/target/snitch_cluster/cfg/fdiv.json similarity index 95% rename from target/snitch_cluster/cfg/fdiv.hjson rename to target/snitch_cluster/cfg/fdiv.json index b9ef5c90f8..a1ff404469 100644 --- a/target/snitch_cluster/cfg/fdiv.hjson +++ b/target/snitch_cluster/cfg/fdiv.json @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 0x1000_0000, + cluster_base_addr: 0x10000000, cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, @@ -82,14 +82,14 @@ }, external_addr_regions: [ { - name: "dram" - address: 0x8000_0000, - length: 0x8000_0000, + name: "dram", + address: 0x80000000, + length: 0x80000000, cacheable: true }, { - name: "clint" - address: 0xFFFF_0000, + name: "clint", + address: 0xFFFF0000, length: 0x1000 }, ], diff --git a/target/snitch_cluster/cfg/github-ci.hjson b/target/snitch_cluster/cfg/github-ci.json similarity index 95% rename from target/snitch_cluster/cfg/github-ci.hjson rename to target/snitch_cluster/cfg/github-ci.json index 7a7dc81f41..380a7d4bc7 100644 --- a/target/snitch_cluster/cfg/github-ci.hjson +++ b/target/snitch_cluster/cfg/github-ci.json @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 0x1000_0000, + cluster_base_addr: 0x10000000, cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, @@ -78,14 +78,14 @@ }, external_addr_regions: [ { - name: "dram" - address: 0x8000_0000, - length: 0x8000_0000, + name: "dram", + address: 0x80000000, + length: 0x80000000, cacheable: true }, { - name: "clint" - address: 0xFFFF_0000, + name: "clint", + address: 0xFFFF0000, length: 0x1000 }, ], diff --git a/target/snitch_cluster/cfg/lru.json b/target/snitch_cluster/cfg/lru.json new file mode 120000 index 0000000000..9e97a46e34 --- /dev/null +++ b/target/snitch_cluster/cfg/lru.json @@ -0,0 +1 @@ +default.hjson \ No newline at end of file diff --git a/target/snitch_cluster/cfg/omega.hjson b/target/snitch_cluster/cfg/omega.json similarity index 95% rename from target/snitch_cluster/cfg/omega.hjson rename to target/snitch_cluster/cfg/omega.json index cdcabebcdd..f6e0150370 100644 --- a/target/snitch_cluster/cfg/omega.hjson +++ b/target/snitch_cluster/cfg/omega.json @@ -5,7 +5,7 @@ // Cluster configuration for a simple testbench system. { cluster: { - cluster_base_addr: 0x1000_0000, + cluster_base_addr: 0x10000000, cluster_base_offset: 0, cluster_base_hartid: 0, addr_width: 48, @@ -83,14 +83,14 @@ }, external_addr_regions: [ { - name: "dram" - address: 0x8000_0000, - length: 0x8000_0000, + name: "dram", + address: 0x80000000, + length: 0x80000000, cacheable: true }, { - name: "clint" - address: 0xFFFF_0000, + name: "clint", + address: 0xFFFF0000, length: 0x1000 }, ], diff --git a/util/clustergen.py b/util/clustergen.py index 88c5a71ea4..b35f9e21cb 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 import argparse -import hjson +import json5 import pathlib import sys import re @@ -13,18 +13,6 @@ from clustergen.cluster import SnitchCluster from mako.template import Template -# Regex to find hex numbers with optional underscores -HEX_PATTERN = re.compile(r"0x[0-9a-fA-F]+(?:_[0-9a-fA-F]+)*") - - -def preprocess_hex_in_hjson(text): - """ Converts hex numbers (e.g., 0x8000_0000) to decimal before parsing HJSON. """ - def hex_to_decimal(match): - hex_str = match.group(0).replace("_", "") # Remove underscores - return str(int(hex_str, 16)) # Convert to decimal and replace - - return HEX_PATTERN.sub(hex_to_decimal, text) - def write_template(tpl_path, outdir, fname=None, **kwargs): @@ -67,12 +55,10 @@ def main(): args = parser.parse_args() - # Read and preprocess HJSON file + # Read and parse JSON5 file with args.clustercfg as file: try: - srcfull = file.read() - srcfull = preprocess_hex_in_hjson(srcfull) # Convert hex to decimal - obj = hjson.loads(srcfull, use_decimal=True) # Now parse clean HJSON + obj = json5.loads(file.read()) # JSON5 natively supports hex & comments obj = JsonRef.replace_refs(obj) except ValueError: From 77cc09b6dfe1c06c248730e04cbe4dfc3d852a5e Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 12:12:10 +0100 Subject: [PATCH 12/19] clustergen: Untrack `lru.json` --- target/snitch_cluster/.gitignore | 2 +- target/snitch_cluster/cfg/lru.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 target/snitch_cluster/cfg/lru.json diff --git a/target/snitch_cluster/.gitignore b/target/snitch_cluster/.gitignore index ea98bf82cf..537fb65ca4 100644 --- a/target/snitch_cluster/.gitignore +++ b/target/snitch_cluster/.gitignore @@ -1,7 +1,7 @@ /logs/ /generated/ /bin/ -/cfg/lru.hjson +/cfg/lru.json /work/ /work-vsim/ /work-vlt/ diff --git a/target/snitch_cluster/cfg/lru.json b/target/snitch_cluster/cfg/lru.json deleted file mode 120000 index 9e97a46e34..0000000000 --- a/target/snitch_cluster/cfg/lru.json +++ /dev/null @@ -1 +0,0 @@ -default.hjson \ No newline at end of file From 546bbb3556631d27be0675b80ec7faf820c78a75 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 12:13:56 +0100 Subject: [PATCH 13/19] make: Fix default config variables --- target/snitch_cluster/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 90100526a6..74135474da 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -56,8 +56,8 @@ PERIPH_DIR ?= $(ROOT)/hw/snitch_cluster/src/snitch_cluster_peripheral # (LRU) config, all targets depending on the configuration file have # to be rebuilt. This file is used to express this condition as a # prerequisite for other rules. -DEFAULT_CFG = cfg/default.hjson -CFG = cfg/lru.hjson +DEFAULT_CFG = cfg/default.json +CFG = cfg/lru.json # Common dependency for all RTL simulators $(BIN_DIR): From 0f59a4b8db1ce7283d8cc53aa916e90d043c0cdb Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 17 Feb 2025 13:42:41 +0100 Subject: [PATCH 14/19] ci: Fix configs --- .github/workflows/ci.yml | 4 ++-- .gitlab-ci.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05b4fefb24..7d0ea82c85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,11 +113,11 @@ jobs: if: steps.verilator-cache.outputs.cache-hit != 'true' working-directory: target/snitch_cluster run: | - make CFG_OVERRIDE=cfg/github-ci.hjson VLT_JOBS=1 bin/snitch_cluster.vlt + make CFG_OVERRIDE=cfg/github-ci.json VLT_JOBS=1 bin/snitch_cluster.vlt - name: Build Software working-directory: target/snitch_cluster run: | - make CFG_OVERRIDE=cfg/github-ci.hjson sw + make CFG_OVERRIDE=cfg/github-ci.json sw - name: Run Tests working-directory: target/snitch_cluster run: | diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 656558761a..865c69fba6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -132,7 +132,7 @@ snitch-cluster-banshee: snitch-cluster-fdiv-vsim: script: - cd target/snitch_cluster - - make CFG_OVERRIDE=cfg/fdiv.hjson sw + - make CFG_OVERRIDE=cfg/fdiv.json sw - make bin/snitch_cluster.vsim - ./util/run.py sw/fdiv.yaml --simulator vsim -j --run-dir runs/vsim # Run additional, more extensive tests @@ -142,7 +142,7 @@ snitch-cluster-fdiv-vsim: snitch-cluster-omega-vsim: script: - cd target/snitch_cluster - - make CFG_OVERRIDE=cfg/omega.hjson sw + - make CFG_OVERRIDE=cfg/omega.json sw - make bin/snitch_cluster.vsim - ./util/run.py sw/run.yaml --simulator vsim -j --run-dir runs/vsim @@ -150,7 +150,7 @@ snitch-cluster-omega-vsim: snitch-cluster-mchan-vsim: script: - cd target/snitch_cluster - - make CFG_OVERRIDE=cfg/dma_mchan.hjson sw + - make CFG_OVERRIDE=cfg/dma_mchan.json sw - make bin/snitch_cluster.vsim - ./util/run.py sw/dma_mchan.yaml --simulator vsim -j --run-dir runs/vsim From bb591d6c5f775c41cee1444690ccacae391adcf0 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 18 Feb 2025 07:02:15 +0100 Subject: [PATCH 15/19] cfg: Fix string value for JSON5 --- target/snitch_cluster/cfg/omega.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/snitch_cluster/cfg/omega.json b/target/snitch_cluster/cfg/omega.json index f6e0150370..9ee3c84334 100644 --- a/target/snitch_cluster/cfg/omega.json +++ b/target/snitch_cluster/cfg/omega.json @@ -14,7 +14,7 @@ tcdm: { size: 128, banks: 32, - topology: OmegaNet + topology: 'OmegaNet' }, cluster_periph_size: 60, // kB zero_mem_size: 64, // kB From cd7d21f4844181f3155cd3c2fd9355e04b940112 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 18 Feb 2025 07:44:05 +0100 Subject: [PATCH 16/19] bootrom: Remove generated bootrom sources --- target/snitch_cluster/test/bootrom.bin | Bin 60 -> 0 bytes target/snitch_cluster/test/bootrom.dump | 24 ---------- target/snitch_cluster/test/bootrom.elf | Bin 4640 -> 0 bytes target/snitch_cluster/test/snitch_bootrom.sv | 45 ------------------- 4 files changed, 69 deletions(-) delete mode 100755 target/snitch_cluster/test/bootrom.bin delete mode 100644 target/snitch_cluster/test/bootrom.dump delete mode 100755 target/snitch_cluster/test/bootrom.elf delete mode 100644 target/snitch_cluster/test/snitch_bootrom.sv diff --git a/target/snitch_cluster/test/bootrom.bin b/target/snitch_cluster/test/bootrom.bin deleted file mode 100755 index ba15659a2638bf0091301407bf2cb382633908cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60 zcmbQv#K17QiHWIrLXbgm0*k?RCJrFKiJ^FclR+^w81g^N{{sN!4-t|8 diff --git a/target/snitch_cluster/test/bootrom.dump b/target/snitch_cluster/test/bootrom.dump deleted file mode 100644 index 864ef1f411..0000000000 --- a/target/snitch_cluster/test/bootrom.dump +++ /dev/null @@ -1,24 +0,0 @@ - -test/bootrom.elf: file format elf32-littleriscv - - -Disassembly of section .text: - -00000000 <_snitch_park>: - 0: 97 02 00 00 auipc t0, 0 - 4: 93 82 02 02 addi t0, t0, 32 - 8: 73 90 52 30 csrw mtvec, t0 - c: 73 60 04 30 csrsi mstatus, 8 - 10: b7 02 08 00 lui t0, 128 - 14: 93 82 82 00 addi t0, t0, 8 - 18: 73 90 42 30 csrw mie, t0 - 1c: 73 00 50 10 wfi - -00000020 <_snitch_resume>: - 20: 97 02 00 00 auipc t0, 0 - 24: 37 13 00 00 lui t1, 1 - 28: 13 03 83 16 addi t1, t1, 360 - 2c: b3 82 62 00 add t0, t0, t1 - 30: 83 a2 02 00 lw t0, 0(t0) - 34: e7 80 02 00 jalr t0 - 38: 6f f0 9f fc j 0x0 <_snitch_park> diff --git a/target/snitch_cluster/test/bootrom.elf b/target/snitch_cluster/test/bootrom.elf deleted file mode 100755 index 69fdbad3cea7aceaf9053321d00ab420417a4976..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4640 zcmeHLu}Z^G6uo(^)kUZj#K9prRl)SNw35p~L-?oylNmBcn}Nm9{CX@8*L;35eA zf`dQfDz1X7gZH++Sc>50^bXwKbMCu&NzZt$53EB?(?Ej32S`=MAzuPWV=sda4Dygc zH9pVECje?lspe>e^W)dpB|3}D>_BPdfO0@Npd3&RCGzT&bM;_xzup^X<)%aYZnM+L0G+0EUCyN@aCY)jj+%{ry8H3?;gFtkUL{~xFu(5kl z98TDzgJJcYP_*lw&!HZ5{Mhm8p@{l{NMx@Owx(Y22c>VNN-_`3MJOYYpiG4@k41Z& z1fqs}rxQB Date: Tue, 18 Feb 2025 07:44:21 +0100 Subject: [PATCH 17/19] bootrom: Regenerate bootrom sources --- target/snitch_cluster/test/bootrom.bin | Bin 0 -> 60 bytes target/snitch_cluster/test/bootrom.dump | 24 ++++++++++ target/snitch_cluster/test/bootrom.elf | Bin 0 -> 4640 bytes target/snitch_cluster/test/snitch_bootrom.sv | 45 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100755 target/snitch_cluster/test/bootrom.bin create mode 100644 target/snitch_cluster/test/bootrom.dump create mode 100755 target/snitch_cluster/test/bootrom.elf create mode 100644 target/snitch_cluster/test/snitch_bootrom.sv diff --git a/target/snitch_cluster/test/bootrom.bin b/target/snitch_cluster/test/bootrom.bin new file mode 100755 index 0000000000000000000000000000000000000000..ba15659a2638bf0091301407bf2cb382633908cb GIT binary patch literal 60 zcmbQv#K17QiHWIrLXbgm0*k?RCJrFKiJ^FclR+^w81g^N{{sN!4-t|8 literal 0 HcmV?d00001 diff --git a/target/snitch_cluster/test/bootrom.dump b/target/snitch_cluster/test/bootrom.dump new file mode 100644 index 0000000000..864ef1f411 --- /dev/null +++ b/target/snitch_cluster/test/bootrom.dump @@ -0,0 +1,24 @@ + +test/bootrom.elf: file format elf32-littleriscv + + +Disassembly of section .text: + +00000000 <_snitch_park>: + 0: 97 02 00 00 auipc t0, 0 + 4: 93 82 02 02 addi t0, t0, 32 + 8: 73 90 52 30 csrw mtvec, t0 + c: 73 60 04 30 csrsi mstatus, 8 + 10: b7 02 08 00 lui t0, 128 + 14: 93 82 82 00 addi t0, t0, 8 + 18: 73 90 42 30 csrw mie, t0 + 1c: 73 00 50 10 wfi + +00000020 <_snitch_resume>: + 20: 97 02 00 00 auipc t0, 0 + 24: 37 13 00 00 lui t1, 1 + 28: 13 03 83 16 addi t1, t1, 360 + 2c: b3 82 62 00 add t0, t0, t1 + 30: 83 a2 02 00 lw t0, 0(t0) + 34: e7 80 02 00 jalr t0 + 38: 6f f0 9f fc j 0x0 <_snitch_park> diff --git a/target/snitch_cluster/test/bootrom.elf b/target/snitch_cluster/test/bootrom.elf new file mode 100755 index 0000000000000000000000000000000000000000..69fdbad3cea7aceaf9053321d00ab420417a4976 GIT binary patch literal 4640 zcmeHLu}Z^G6uo(^)kUZj#K9prRl)SNw35p~L-?oylNmBcn}Nm9{CX@8*L;35eA zf`dQfDz1X7gZH++Sc>50^bXwKbMCu&NzZt$53EB?(?Ej32S`=MAzuPWV=sda4Dygc zH9pVECje?lspe>e^W)dpB|3}D>_BPdfO0@Npd3&RCGzT&bM;_xzup^X<)%aYZnM+L0G+0EUCyN@aCY)jj+%{ry8H3?;gFtkUL{~xFu(5kl z98TDzgJJcYP_*lw&!HZ5{Mhm8p@{l{NMx@Owx(Y22c>VNN-_`3MJOYYpiG4@k41Z& z1fqs}rxQB Date: Tue, 18 Feb 2025 19:05:44 +0100 Subject: [PATCH 18/19] clustergen: Remove `--memories` as untested --- target/common/common.mk | 2 +- target/snitch_cluster/Makefile | 3 +-- util/clustergen.py | 11 ----------- util/clustergen/cluster.py | 6 +++--- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/target/common/common.mk b/target/common/common.mk index f2fd26baf9..5455dc5bbe 100644 --- a/target/common/common.mk +++ b/target/common/common.mk @@ -195,7 +195,7 @@ endef define cluster_gen_rule $(1): $(CFG) $(CLUSTER_GEN_PREREQ) $(2) | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $$< -o $(GENERATED_DIR) $(if $(3),$(3),--template $(2)) + $(CLUSTER_GEN) -c $$< -o $(GENERATED_DIR) --template $(2) endef ########## diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 74135474da..5d01c0b708 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -165,11 +165,10 @@ CLUSTER_GEN_TPL = $(ROOT)/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl LINK_LD_TPL = $(ROOT)/hw/snitch_cluster/test/link.ld.tpl BOOTDATA_TPL = $(ROOT)/hw/snitch_cluster/test/bootdata.cc.tpl +# OCCAMYGEN artifacts $(eval $(call cluster_gen_rule,$(GENERATED_DIR)/snitch_cluster_wrapper.sv,$(CLUSTER_GEN_TPL))) $(eval $(call cluster_gen_rule,$(GENERATED_DIR)/link.ld,$(LINK_LD_TPL))) $(eval $(call cluster_gen_rule,$(GENERATED_DIR)/bootdata.cc,$(BOOTDATA_TPL))) -$(eval $(call cluster_gen_rule,$(GENERATED_DIR)/memories.json,,--memories)) - # REGGEN regfile $(PERIPH_DIR)/snitch_cluster_peripheral_reg_pkg.sv: $(PERIPH_DIR)/snitch_cluster_peripheral_reg_top.sv diff --git a/util/clustergen.py b/util/clustergen.py index b35f9e21cb..09bbcd12bd 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -46,9 +46,6 @@ def main(): type=pathlib.Path, required=True, help="Target directory.") - parser.add_argument("--memories", - action="store_true", - help="Generate memories") parser.add_argument("--template", metavar="template", help="Name of the template file") @@ -72,14 +69,6 @@ def main(): outdir = args.outdir outdir.mkdir(parents=True, exist_ok=True) - ############## - # Misc files # - ############## - - if args.memories: - with open(outdir / "memories.json", "w") as f: - f.write(cluster.memory_cfg()) - #################### # Generic template # #################### diff --git a/util/clustergen/cluster.py b/util/clustergen/cluster.py index 40d39b1bd3..67e969c98b 100644 --- a/util/clustergen/cluster.py +++ b/util/clustergen/cluster.py @@ -194,11 +194,11 @@ def add_mem(self, def memory_cfg(self): # Add TCDMs - self.add_mem(self.cfg['tcdm']['depth'], - self.cfg['data_width'], + self.add_mem(self.cfg['cluster']['tcdm']['depth'], + self.cfg['cluster']['data_width'], desc='tcdm') # Add instruction caches - for i, h in enumerate(self.cfg['hives']): + for i, h in enumerate(self.cfg['cluster']['hives']): self.add_mem(h['icache']['depth'], h['icache']['cacheline'], desc='icache data (hive {})'.format(i), From 2f23bea262ae63bf26b7e2d17868135cf28f2529 Mon Sep 17 00:00:00 2001 From: Luca Colagrande Date: Tue, 18 Feb 2025 19:12:44 +0100 Subject: [PATCH 19/19] clustergen: Allow overriding output file path --- target/common/common.mk | 6 +++++- target/snitch_cluster/sw.mk | 19 +++++++++---------- util/clustergen.py | 17 +++++------------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/target/common/common.mk b/target/common/common.mk index 5455dc5bbe..fa619ea9da 100644 --- a/target/common/common.mk +++ b/target/common/common.mk @@ -193,9 +193,13 @@ define BINARY_SIZE_CHECK @[ "$$(stat -c %s $(1))" -lt "$(2)" ] || (echo "Binary exceeds specified size of $(2)B"; exit 1) endef +# Common rule to fill a template file with clustergen +# Arg 1: path for the generated file +# Arg 2: path of the template file define cluster_gen_rule $(1): $(CFG) $(CLUSTER_GEN_PREREQ) $(2) | $(GENERATED_DIR) - $(CLUSTER_GEN) -c $$< -o $(GENERATED_DIR) --template $(2) + @echo "[CLUSTERGEN] Generate $$@" + $(CLUSTER_GEN) -c $$< -o $$@ --template $(2) endef ########## diff --git a/target/snitch_cluster/sw.mk b/target/snitch_cluster/sw.mk index 6083a8ee1c..e292602fe8 100644 --- a/target/snitch_cluster/sw.mk +++ b/target/snitch_cluster/sw.mk @@ -17,21 +17,20 @@ clean: clean-sw # Platform headers # #################### -CLUSTER_GEN_HEADERS = snitch_cluster_cfg.h \ - snitch_cluster_addrmap.h +TARGET_C_HDRS_DIR = $(ROOT)/target/snitch_cluster/sw/runtime/common -REGGEN_HEADERS = snitch_cluster_peripheral.h +SNITCH_CLUSTER_CFG_H = $(TARGET_C_HDRS_DIR)/snitch_cluster_cfg.h +SNITCH_CLUSTER_ADDRMAP_H = $(TARGET_C_HDRS_DIR)/snitch_cluster_addrmap.h +SNITCH_CLUSTER_PERIPHERAL_H = $(TARGET_C_HDRS_DIR)/snitch_cluster_peripheral.h -TARGET_C_HDRS_DIR = $(ROOT)/target/snitch_cluster/sw/runtime/common -TARGET_C_HDRS = $(addprefix $(TARGET_C_HDRS_DIR)/,$(CLUSTER_GEN_HEADERS) $(REGGEN_HEADERS)) +TARGET_C_HDRS = $(SNITCH_CLUSTER_CFG_H) $(SNITCH_CLUSTER_ADDRMAP_H) $(SNITCH_CLUSTER_PERIPHERAL_H) -# CLUSTERGEN headers, -$(addprefix $(TARGET_C_HDRS_DIR)/,$(CLUSTER_GEN_HEADERS)): %.h: $(CFG) $(CLUSTER_GEN_PREREQ) %.h.tpl - @echo "[CLUSTERGEN] Generate $@" - $(CLUSTER_GEN) -c $< --outdir $(TARGET_C_HDRS_DIR) --template $@.tpl +# CLUSTERGEN headers +$(eval $(call cluster_gen_rule,$(SNITCH_CLUSTER_CFG_H),$(SNITCH_CLUSTER_CFG_H).tpl)) +$(eval $(call cluster_gen_rule,$(SNITCH_CLUSTER_ADDRMAP_H),$(SNITCH_CLUSTER_ADDRMAP_H).tpl)) # REGGEN headers -$(TARGET_C_HDRS_DIR)/snitch_cluster_peripheral.h: $(ROOT)/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson $(REGGEN) +$(SNITCH_CLUSTER_PERIPHERAL_H): $(ROOT)/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson $(REGGEN) $(call reggen_generate_header,$@,$<) .PHONY: clean-headers diff --git a/util/clustergen.py b/util/clustergen.py index 09bbcd12bd..9b8fcf284a 100755 --- a/util/clustergen.py +++ b/util/clustergen.py @@ -14,7 +14,7 @@ from mako.template import Template -def write_template(tpl_path, outdir, fname=None, **kwargs): +def write_template(tpl_path, output_path, **kwargs): # Compile a regex to trim trailing whitespaces on lines. re_trailws = re.compile(r'[ \t\r]+$', re.MULTILINE) @@ -23,8 +23,7 @@ def write_template(tpl_path, outdir, fname=None, **kwargs): tpl_path = pathlib.Path(tpl_path).absolute() if tpl_path.exists(): tpl = Template(filename=str(tpl_path)) - fname = tpl_path.with_suffix("").name if not fname else fname - with open(outdir / fname, "w") as file: + with open(output_path, "w") as file: code = tpl.render_unicode(**kwargs) code = re_trailws.sub("", code) file.write(code) @@ -41,11 +40,11 @@ def main(): type=argparse.FileType('r'), required=True, help="A cluster configuration file") - parser.add_argument("--outdir", + parser.add_argument("--output", "-o", type=pathlib.Path, required=True, - help="Target directory.") + help="Output file path") parser.add_argument("--template", metavar="template", help="Name of the template file") @@ -63,12 +62,6 @@ def main(): cluster = SnitchCluster(obj) - if not args.outdir.is_dir(): - exit("Out directory is not a valid path.") - - outdir = args.outdir - outdir.mkdir(parents=True, exist_ok=True) - #################### # Generic template # #################### @@ -79,7 +72,7 @@ def main(): } if args.template: - write_template(args.template, outdir, **kwargs) + write_template(args.template, args.output, **kwargs) if __name__ == "__main__":