Message ID | 20240605063154.31298-3-frank.chang@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Introduce extension implied rules | expand |
On Wed, Jun 5, 2024 at 2:32 PM <frank.chang@sifive.com> wrote: > From: Frank Chang <frank.chang@sifive.com> > > Introduce helpers to enable the extensions based on the implied rules. > The implied extensions are enabled recursively, so we don't have to > expand all of them manually. This also eliminates the old-fashioned > ordering requirement. For example, Zvksg implies Zvks, Zvks implies > Zvksed, etc., removing the need to check the implied rules of Zvksg > before Zvks. > > Signed-off-by: Frank Chang <frank.chang@sifive.com> > --- > target/riscv/tcg/tcg-cpu.c | 89 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 89 insertions(+) > > diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c > index 683f604d9f..899d605d36 100644 > --- a/target/riscv/tcg/tcg-cpu.c > +++ b/target/riscv/tcg/tcg-cpu.c > @@ -36,6 +36,9 @@ > static GHashTable *multi_ext_user_opts; > static GHashTable *misa_ext_user_opts; > > +static GHashTable *misa_implied_rules; > +static GHashTable *ext_implied_rules; > + > static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) > { > return g_hash_table_contains(multi_ext_user_opts, > @@ -833,11 +836,95 @@ static void riscv_cpu_validate_profiles(RISCVCPU > *cpu) > } > } > > +static void riscv_cpu_init_implied_exts_rules(void) > +{ > + RISCVCPUImpliedExtsRule *rule; > + int i; > + > + for (i = 0; (rule = riscv_misa_implied_rules[i]); i++) { > + g_hash_table_insert(misa_implied_rules, > GUINT_TO_POINTER(rule->ext), > + (gpointer)rule); > + } > + > + for (i = 0; (rule = riscv_ext_implied_rules[i]); i++) { > + g_hash_table_insert(ext_implied_rules, > GUINT_TO_POINTER(rule->ext), > + (gpointer)rule); > + } > +} > + > +static void cpu_enable_implied_rule(RISCVCPU *cpu, > + RISCVCPUImpliedExtsRule *rule) > +{ > + CPURISCVState *env = &cpu->env; > + RISCVCPUImpliedExtsRule *ir; > + target_ulong hartid = 0; > + int i; > + > +#if !defined(CONFIG_USER_ONLY) > + hartid = env->mhartid; > +#endif > + > + if (!(rule->enabled & BIT_ULL(hartid))) { > + /* Enable the implied MISAs. */ > + if (rule->implied_misas) { > + riscv_cpu_set_misa_ext(env, env->misa_ext | > rule->implied_misas); > + > + for (i = 0; misa_bits[i] != 0; i++) { > + if (rule->implied_misas & misa_bits[i]) { > + ir = g_hash_table_lookup(misa_implied_rules, > + > GUINT_TO_POINTER(misa_bits[i])); > + > + if (ir) { > + cpu_enable_implied_rule(cpu, ir); > + } > + } > + } > + } > + > + /* Enable the implied extensions. */ > + for (i = 0; rule->implied_exts[i] != RISCV_IMPLIED_EXTS_RULE_END; > i++) { > + cpu_cfg_ext_auto_update(cpu, rule->implied_exts[i], true); > + > + ir = g_hash_table_lookup(ext_implied_rules, > + > GUINT_TO_POINTER(rule->implied_exts[i])); > + > + if (ir) { > + cpu_enable_implied_rule(cpu, ir); > + } > + } > + > + rule->enabled |= BIT_ULL(hartid); > Should I use the qatomic API here to set the enabled bitmask? This wouldn't impact the results but it may cause the implied rules to be traversed and re-enabled (which has no harm) if the enabled bit of a hart is accidentally cleared by another harts. > + } > +} > + > +static void riscv_cpu_enable_implied_rules(RISCVCPU *cpu) > +{ > + RISCVCPUImpliedExtsRule *rule; > + int i; > + > + /* Enable the implied MISAs. */ > + for (i = 0; (rule = riscv_misa_implied_rules[i]); i++) { > + if (riscv_has_ext(&cpu->env, rule->ext)) { > + cpu_enable_implied_rule(cpu, rule); > + } > + } > + > + /* Enable the implied extensions. */ > + for (i = 0; (rule = riscv_ext_implied_rules[i]); i++) { > + if (isa_ext_is_enabled(cpu, rule->ext)) { > + cpu_enable_implied_rule(cpu, rule); > + } > + } > +} > + > void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) > { > CPURISCVState *env = &cpu->env; > Error *local_err = NULL; > > + riscv_cpu_init_implied_exts_rules(); > + riscv_cpu_enable_implied_rules(cpu); > + > riscv_cpu_validate_misa_priv(env, &local_err); > if (local_err != NULL) { > error_propagate(errp, local_err); > @@ -1343,6 +1430,8 @@ static void riscv_tcg_cpu_instance_init(CPUState *cs) > > misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); > multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); > + misa_implied_rules = g_hash_table_new(NULL, g_direct_equal); > + ext_implied_rules = g_hash_table_new(NULL, g_direct_equal); > riscv_cpu_add_user_properties(obj); > > if (riscv_cpu_has_max_extensions(obj)) { > -- > 2.43.2 > >
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 683f604d9f..899d605d36 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -36,6 +36,9 @@ static GHashTable *multi_ext_user_opts; static GHashTable *misa_ext_user_opts; +static GHashTable *misa_implied_rules; +static GHashTable *ext_implied_rules; + static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) { return g_hash_table_contains(multi_ext_user_opts, @@ -833,11 +836,95 @@ static void riscv_cpu_validate_profiles(RISCVCPU *cpu) } } +static void riscv_cpu_init_implied_exts_rules(void) +{ + RISCVCPUImpliedExtsRule *rule; + int i; + + for (i = 0; (rule = riscv_misa_implied_rules[i]); i++) { + g_hash_table_insert(misa_implied_rules, GUINT_TO_POINTER(rule->ext), + (gpointer)rule); + } + + for (i = 0; (rule = riscv_ext_implied_rules[i]); i++) { + g_hash_table_insert(ext_implied_rules, GUINT_TO_POINTER(rule->ext), + (gpointer)rule); + } +} + +static void cpu_enable_implied_rule(RISCVCPU *cpu, + RISCVCPUImpliedExtsRule *rule) +{ + CPURISCVState *env = &cpu->env; + RISCVCPUImpliedExtsRule *ir; + target_ulong hartid = 0; + int i; + +#if !defined(CONFIG_USER_ONLY) + hartid = env->mhartid; +#endif + + if (!(rule->enabled & BIT_ULL(hartid))) { + /* Enable the implied MISAs. */ + if (rule->implied_misas) { + riscv_cpu_set_misa_ext(env, env->misa_ext | rule->implied_misas); + + for (i = 0; misa_bits[i] != 0; i++) { + if (rule->implied_misas & misa_bits[i]) { + ir = g_hash_table_lookup(misa_implied_rules, + GUINT_TO_POINTER(misa_bits[i])); + + if (ir) { + cpu_enable_implied_rule(cpu, ir); + } + } + } + } + + /* Enable the implied extensions. */ + for (i = 0; rule->implied_exts[i] != RISCV_IMPLIED_EXTS_RULE_END; i++) { + cpu_cfg_ext_auto_update(cpu, rule->implied_exts[i], true); + + ir = g_hash_table_lookup(ext_implied_rules, + GUINT_TO_POINTER(rule->implied_exts[i])); + + if (ir) { + cpu_enable_implied_rule(cpu, ir); + } + } + + rule->enabled |= BIT_ULL(hartid); + } +} + +static void riscv_cpu_enable_implied_rules(RISCVCPU *cpu) +{ + RISCVCPUImpliedExtsRule *rule; + int i; + + /* Enable the implied MISAs. */ + for (i = 0; (rule = riscv_misa_implied_rules[i]); i++) { + if (riscv_has_ext(&cpu->env, rule->ext)) { + cpu_enable_implied_rule(cpu, rule); + } + } + + /* Enable the implied extensions. */ + for (i = 0; (rule = riscv_ext_implied_rules[i]); i++) { + if (isa_ext_is_enabled(cpu, rule->ext)) { + cpu_enable_implied_rule(cpu, rule); + } + } +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = &cpu->env; Error *local_err = NULL; + riscv_cpu_init_implied_exts_rules(); + riscv_cpu_enable_implied_rules(cpu); + riscv_cpu_validate_misa_priv(env, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); @@ -1343,6 +1430,8 @@ static void riscv_tcg_cpu_instance_init(CPUState *cs) misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); + misa_implied_rules = g_hash_table_new(NULL, g_direct_equal); + ext_implied_rules = g_hash_table_new(NULL, g_direct_equal); riscv_cpu_add_user_properties(obj); if (riscv_cpu_has_max_extensions(obj)) {