1
0
Fork 0
forked from len0rd/rockbox

headergen_v2: generate register offsets and node addresses

Register offsets are defined as the address of the register minus
the address of the parent node. If enabled by the generator, these
will be emitted alongside defines for the node base addresses.

This allows the base address to be stored in a variable, and the
offset can be used to access registers relative to the base.

Change-Id: I15576aeb2945293a259007da7f00a26055f4d0f0
This commit is contained in:
Aidan MacDonald 2025-01-24 10:05:16 +00:00 committed by Solomon Peachy
parent 81e050871b
commit 0f5c2877fe

View file

@ -535,6 +535,8 @@ private:
void print_inst(const pseudo_node_inst_t& inst, bool end = true); // debug void print_inst(const pseudo_node_inst_t& inst, bool end = true); // debug
std::vector< soc_ref_t > list_socs(const std::vector< pseudo_node_inst_t >& list); std::vector< soc_ref_t > list_socs(const std::vector< pseudo_node_inst_t >& list);
bool generate_register(std::ostream& os, const pseudo_node_inst_t& reg); bool generate_register(std::ostream& os, const pseudo_node_inst_t& reg);
bool generate_node(std::ostream& os, const pseudo_node_inst_t& node);
std::string generate_param_str(const std::vector<std::string>& params);
bool generate_macro_header(error_context_t& ectx); bool generate_macro_header(error_context_t& ectx);
protected: protected:
/// return true to generate support macros /// return true to generate support macros
@ -543,6 +545,8 @@ protected:
virtual bool has_support_macros() const = 0; virtual bool has_support_macros() const = 0;
/// return true to generate selector files /// return true to generate selector files
virtual bool has_selectors() const = 0; virtual bool has_selectors() const = 0;
/// return true to generate node address and register offset macros
virtual bool has_offsets() const = 0;
/// [selector only] return the directory name for the soc /// [selector only] return the directory name for the soc
virtual std::string selector_soc_dir(const soc_ref_t& ref) const = 0; virtual std::string selector_soc_dir(const soc_ref_t& ref) const = 0;
/// [selector only] return the header to include to select betweens socs /// [selector only] return the header to include to select betweens socs
@ -593,7 +597,9 @@ protected:
/// prefix/suffix type /// prefix/suffix type
enum macro_type_t enum macro_type_t
{ {
MT_NODE_ADDR, /// node address
MT_REG_ADDR, /// register address MT_REG_ADDR, /// register address
MT_REG_OFFSET, /// register address relative to parent node
MT_REG_TYPE, /// register type MT_REG_TYPE, /// register type
MT_REG_NAME, /// register prefix for fields MT_REG_NAME, /// register prefix for fields
MT_REG_INDEX, /// register index/indices MT_REG_INDEX, /// register index/indices
@ -645,7 +651,7 @@ protected:
/// generate address string for a register instance, and fill the parametric /// generate address string for a register instance, and fill the parametric
/// argument list, default does it the obvious way and parameters are _n1, _n2, ... /// argument list, default does it the obvious way and parameters are _n1, _n2, ...
virtual std::string register_address(const pseudo_node_inst_t& reg, virtual std::string register_address(const pseudo_node_inst_t& reg,
std::vector< std::string >& params) const; std::vector< std::string >& params, bool offset_only = false) const;
/// return access type for a variant and a given register access /// return access type for a variant and a given register access
/// NOTE variant with the unspecified access type will be promoted to register access /// NOTE variant with the unspecified access type will be promoted to register access
virtual access_type_t register_access(const std::string& variant, access_t access) const = 0; virtual access_type_t register_access(const std::string& variant, access_t access) const = 0;
@ -766,8 +772,9 @@ std::string common_generator::safe_macro_paste(bool left, const std::string& mac
void common_generator::gather_files(const pseudo_node_inst_t& inst, const std::string& prefix, void common_generator::gather_files(const pseudo_node_inst_t& inst, const std::string& prefix,
std::map< std::string, std::vector< pseudo_node_inst_t > >& map) std::map< std::string, std::vector< pseudo_node_inst_t > >& map)
{ {
if(inst.inst.node().reg().valid()) if(!inst.inst.is_root())
map[prefix + register_header(inst.inst)].push_back(inst); map[prefix + register_header(inst.inst)].push_back(inst);
// if asked, generate one for each instance // if asked, generate one for each instance
std::vector< node_inst_t > list = inst.inst.children(); std::vector< node_inst_t > list = inst.inst.children();
for(size_t i = 0; i < list.size(); i++) for(size_t i = 0; i < list.size(); i++)
@ -814,15 +821,17 @@ std::string common_generator::header_include_guard(const std::string& filename)
} }
std::string common_generator::register_address(const pseudo_node_inst_t& reg, std::string common_generator::register_address(const pseudo_node_inst_t& reg,
std::vector< std::string >& params) const std::vector< std::string >& params, bool offset_only) const
{ {
std::ostringstream oss; std::ostringstream oss;
unsigned counter = 1; unsigned counter = 1;
size_t start_index = offset_only ? reg.parametric.size() - 1 : 0;
oss << "("; oss << "(";
for(size_t i = 0; i < reg.parametric.size(); i++) for(size_t i = start_index; i < reg.parametric.size(); i++)
{ {
if(i != 0) if(i != start_index)
oss << " + "; oss << " + ";
node_inst_t ninst = reg.inst.parent(reg.parametric.size() - i - 1); node_inst_t ninst = reg.inst.parent(reg.parametric.size() - i - 1);
instance_t& inst = *ninst.get(); instance_t& inst = *ninst.get();
if(reg.parametric[i]) if(reg.parametric[i])
@ -889,19 +898,13 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
{ {
os << "\n"; os << "\n";
define_align_context_t ctx; define_align_context_t ctx;
std::vector< std::string > params; std::vector< std::string > addr_params;
std::string addr = register_address(reg, params); std::vector< std::string > offset_params;
std::string addr = register_address(reg, addr_params);
std::string offset = register_address(reg, offset_params, true);
std::string basename = macro_basename(reg); std::string basename = macro_basename(reg);
std::string param_str; std::string addr_param_str = generate_param_str(addr_params);
std::string param_str_no_paren; std::string offset_param_str = generate_param_str(offset_params);
std::string param_str_no_paren_comma;
if(params.size() > 0)
{
for(size_t i = 0; i < params.size(); i++)
param_str_no_paren += (i == 0 ? "" : ",") + params[i];
param_str = "(" + param_str_no_paren + ")";
param_str_no_paren_comma = param_str_no_paren + ",";
}
std::string bp_prefix = macro_basename(reg, MT_FIELD_BP) + field_prefix(); std::string bp_prefix = macro_basename(reg, MT_FIELD_BP) + field_prefix();
std::string bm_prefix = macro_basename(reg, MT_FIELD_BM) + field_prefix(); std::string bm_prefix = macro_basename(reg, MT_FIELD_BM) + field_prefix();
std::string bf_prefix = macro_basename(reg, MT_FIELD_BF) + field_prefix(); std::string bf_prefix = macro_basename(reg, MT_FIELD_BF) + field_prefix();
@ -914,19 +917,26 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
std::vector< std::string > var_prefix; std::vector< std::string > var_prefix;
std::vector< std::string > var_suffix; std::vector< std::string > var_suffix;
std::vector< std::string > var_addr; std::vector< std::string > var_addr;
std::vector< std::string > var_offset;
std::vector< access_type_t > var_access; std::vector< access_type_t > var_access;
var_prefix.push_back(""); var_prefix.push_back("");
var_suffix.push_back(""); var_suffix.push_back("");
var_access.push_back(register_access("", regr.get()->access)); var_access.push_back(register_access("", regr.get()->access));
var_addr.push_back(addr); var_addr.push_back(addr);
var_offset.push_back(offset);
std::vector< variant_ref_t > variants = regr.variants(); std::vector< variant_ref_t > variants = regr.variants();
for(size_t i = 0; i < variants.size(); i++) for(size_t i = 0; i < variants.size(); i++)
{ {
var_prefix.push_back(variant_xfix(variants[i].type(), true)); var_prefix.push_back(variant_xfix(variants[i].type(), true));
var_suffix.push_back(variant_xfix(variants[i].type(), false)); var_suffix.push_back(variant_xfix(variants[i].type(), false));
var_addr.push_back("(" + type_xfix(MT_REG_ADDR, true) + basename + var_addr.push_back("(" + type_xfix(MT_REG_ADDR, true) + basename +
type_xfix(MT_REG_ADDR, false) + param_str + " + " + type_xfix(MT_REG_ADDR, false) + addr_param_str + " + " +
to_hex(variants[i].offset()) + ")"); to_hex(variants[i].offset()) + ")");
var_offset.push_back("(" + type_xfix(MT_REG_OFFSET, true) + basename +
type_xfix(MT_REG_OFFSET, false) + offset_param_str + " + " +
to_hex(variants[i].offset()));
access_t acc = variants[i].get()->access; access_t acc = variants[i].get()->access;
if(acc == UNSPECIFIED) if(acc == UNSPECIFIED)
acc = regr.get()->access; // fallback to register access acc = regr.get()->access; // fallback to register access
@ -940,6 +950,8 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
type_xfix(MT_REG_VAR, false); type_xfix(MT_REG_VAR, false);
std::string macro_addr = type_xfix(MT_REG_ADDR, true) + var_basename + std::string macro_addr = type_xfix(MT_REG_ADDR, true) + var_basename +
type_xfix(MT_REG_ADDR, false); type_xfix(MT_REG_ADDR, false);
std::string macro_offset = type_xfix(MT_REG_OFFSET, true) + var_basename +
type_xfix(MT_REG_OFFSET, false);
std::string macro_type = type_xfix(MT_REG_TYPE, true) + var_basename + std::string macro_type = type_xfix(MT_REG_TYPE, true) + var_basename +
type_xfix(MT_REG_TYPE, false); type_xfix(MT_REG_TYPE, false);
std::string macro_prefix = type_xfix(MT_REG_NAME, true) + var_basename + std::string macro_prefix = type_xfix(MT_REG_NAME, true) + var_basename +
@ -953,22 +965,29 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
if(!has_support_macros()) if(!has_support_macros())
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "(*(volatile uint" << regr.get()->width << "_t *)" << macro_addr + param_str << ")"; oss << "(*(volatile uint" << regr.get()->width << "_t *)" << macro_addr + addr_param_str << ")";
ctx.add(macro_var + param_str, oss.str()); ctx.add(macro_var + addr_param_str, oss.str());
} }
else else
ctx.add(macro_var + param_str, macro_name(MN_VARIABLE) + "(" + var_basename + param_str + ")"); ctx.add(macro_var + addr_param_str, macro_name(MN_VARIABLE) + "(" + var_basename + addr_param_str + ")");
/* print ADDR macro */ /* print ADDR macro */
ctx.add(macro_addr + param_str, var_addr[i]); ctx.add(macro_addr + addr_param_str, var_addr[i]);
if(has_offsets())
{
/* print OFFSET macro */
ctx.add(macro_offset + offset_param_str, var_offset[i]);
}
/* disable macros if needed */ /* disable macros if needed */
if(has_support_macros()) if(has_support_macros())
{ {
/* print TYPE macro */ /* print TYPE macro */
ctx.add(macro_type + param_str, register_type_name(var_access[i], regr.get()->width)); ctx.add(macro_type + addr_param_str, register_type_name(var_access[i], regr.get()->width));
/* print PREFIX macro */ /* print PREFIX macro */
ctx.add(macro_prefix + param_str, basename); ctx.add(macro_prefix + addr_param_str, basename);
/* print INDEX macro */ /* print INDEX macro */
ctx.add(macro_index + param_str, param_str); ctx.add(macro_index + addr_param_str, addr_param_str);
} }
} }
/* print fields */ /* print fields */
@ -1009,6 +1028,40 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
return true; return true;
} }
bool common_generator::generate_node(std::ostream& os, const pseudo_node_inst_t& node)
{
os << "\n";
define_align_context_t ctx;
std::vector< std::string > params;
std::string addr = register_address(node, params);
std::string basename = macro_basename(node);
std::string param_str = generate_param_str(params);
std::string macro_addr = type_xfix(MT_NODE_ADDR, true) + basename +
type_xfix(MT_NODE_ADDR, false);
ctx.add(macro_addr + param_str, addr);
ctx.print(os);
return true;
}
std::string common_generator::generate_param_str(const std::vector<std::string>& params)
{
std::string param_str;
if(params.size() > 0)
{
param_str = "(";
for(size_t i = 0; i < params.size(); i++)
param_str += (i == 0 ? "" : ",") + params[i];
param_str += ")";
}
return param_str;
}
bool common_generator::generate_macro_header(error_context_t& ectx) bool common_generator::generate_macro_header(error_context_t& ectx)
{ {
/* only generate if we need support macros */ /* only generate if we need support macros */
@ -1563,14 +1616,26 @@ bool common_generator::generate(error_context_t& ectx)
} }
for(size_t i = 0; i < it->second.size(); i++) for(size_t i = 0; i < it->second.size(); i++)
{
if(it->second[i].inst.node().reg().valid())
{ {
if(!generate_register(fout, it->second[i])) if(!generate_register(fout, it->second[i]))
{ {
printf("Cannot generate register"); printf("Cannot generate register ");
print_inst(it->second[i]); print_inst(it->second[i]);
return false; return false;
} }
} }
else if(has_offsets() && !it->second[i].inst.node().is_root())
{
if(!generate_node(fout, it->second[i]))
{
printf("Cannot generate node ");
print_inst(it->second[i]);
return false;
}
}
}
print_guard(fout, guard, false); print_guard(fout, guard, false);
fout.close(); fout.close();
@ -1646,6 +1711,11 @@ class jz_generator : public common_generator
return m_soc.size() >= 2; return m_soc.size() >= 2;
} }
bool has_offsets() const
{
return false;
}
std::string selector_soc_dir(const soc_ref_t& ref) const std::string selector_soc_dir(const soc_ref_t& ref) const
{ {
return ref.get()->name; return ref.get()->name;
@ -1811,6 +1881,11 @@ class imx_generator : public common_generator
return m_soc.size() >= 2; return m_soc.size() >= 2;
} }
bool has_offsets() const
{
return false;
}
std::string selector_soc_dir(const soc_ref_t& ref) const std::string selector_soc_dir(const soc_ref_t& ref) const
{ {
return ref.get()->name; return ref.get()->name;
@ -1978,6 +2053,11 @@ class atj_generator : public common_generator
return false; return false;
} }
bool has_offsets() const
{
return false;
}
std::string selector_soc_dir(const soc_ref_t& ref) const std::string selector_soc_dir(const soc_ref_t& ref) const
{ {
return ref.get()->name; return ref.get()->name;