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:
parent
81e050871b
commit
0f5c2877fe
1 changed files with 109 additions and 29 deletions
|
@ -535,6 +535,8 @@ private:
|
|||
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);
|
||||
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);
|
||||
protected:
|
||||
/// return true to generate support macros
|
||||
|
@ -543,6 +545,8 @@ protected:
|
|||
virtual bool has_support_macros() const = 0;
|
||||
/// return true to generate selector files
|
||||
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
|
||||
virtual std::string selector_soc_dir(const soc_ref_t& ref) const = 0;
|
||||
/// [selector only] return the header to include to select betweens socs
|
||||
|
@ -593,7 +597,9 @@ protected:
|
|||
/// prefix/suffix type
|
||||
enum macro_type_t
|
||||
{
|
||||
MT_NODE_ADDR, /// node address
|
||||
MT_REG_ADDR, /// register address
|
||||
MT_REG_OFFSET, /// register address relative to parent node
|
||||
MT_REG_TYPE, /// register type
|
||||
MT_REG_NAME, /// register prefix for fields
|
||||
MT_REG_INDEX, /// register index/indices
|
||||
|
@ -645,7 +651,7 @@ protected:
|
|||
/// generate address string for a register instance, and fill the parametric
|
||||
/// argument list, default does it the obvious way and parameters are _n1, _n2, ...
|
||||
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
|
||||
/// 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;
|
||||
|
@ -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,
|
||||
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);
|
||||
|
||||
// if asked, generate one for each instance
|
||||
std::vector< node_inst_t > list = inst.inst.children();
|
||||
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::vector< std::string >& params) const
|
||||
std::vector< std::string >& params, bool offset_only) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
unsigned counter = 1;
|
||||
size_t start_index = offset_only ? reg.parametric.size() - 1 : 0;
|
||||
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 << " + ";
|
||||
|
||||
node_inst_t ninst = reg.inst.parent(reg.parametric.size() - i - 1);
|
||||
instance_t& inst = *ninst.get();
|
||||
if(reg.parametric[i])
|
||||
|
@ -889,19 +898,13 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
|
|||
{
|
||||
os << "\n";
|
||||
define_align_context_t ctx;
|
||||
std::vector< std::string > params;
|
||||
std::string addr = register_address(reg, params);
|
||||
std::vector< std::string > addr_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 param_str;
|
||||
std::string param_str_no_paren;
|
||||
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 addr_param_str = generate_param_str(addr_params);
|
||||
std::string offset_param_str = generate_param_str(offset_params);
|
||||
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 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_suffix;
|
||||
std::vector< std::string > var_addr;
|
||||
std::vector< std::string > var_offset;
|
||||
std::vector< access_type_t > var_access;
|
||||
|
||||
var_prefix.push_back("");
|
||||
var_suffix.push_back("");
|
||||
var_access.push_back(register_access("", regr.get()->access));
|
||||
var_addr.push_back(addr);
|
||||
var_offset.push_back(offset);
|
||||
|
||||
std::vector< variant_ref_t > variants = regr.variants();
|
||||
for(size_t i = 0; i < variants.size(); i++)
|
||||
{
|
||||
var_prefix.push_back(variant_xfix(variants[i].type(), true));
|
||||
var_suffix.push_back(variant_xfix(variants[i].type(), false));
|
||||
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()) + ")");
|
||||
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;
|
||||
if(acc == UNSPECIFIED)
|
||||
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);
|
||||
std::string macro_addr = type_xfix(MT_REG_ADDR, true) + var_basename +
|
||||
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 +
|
||||
type_xfix(MT_REG_TYPE, false);
|
||||
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())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "(*(volatile uint" << regr.get()->width << "_t *)" << macro_addr + param_str << ")";
|
||||
ctx.add(macro_var + param_str, oss.str());
|
||||
oss << "(*(volatile uint" << regr.get()->width << "_t *)" << macro_addr + addr_param_str << ")";
|
||||
ctx.add(macro_var + addr_param_str, oss.str());
|
||||
}
|
||||
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 */
|
||||
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 */
|
||||
if(has_support_macros())
|
||||
{
|
||||
/* 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 */
|
||||
ctx.add(macro_prefix + param_str, basename);
|
||||
ctx.add(macro_prefix + addr_param_str, basename);
|
||||
/* print INDEX macro */
|
||||
ctx.add(macro_index + param_str, param_str);
|
||||
ctx.add(macro_index + addr_param_str, addr_param_str);
|
||||
}
|
||||
}
|
||||
/* print fields */
|
||||
|
@ -1009,6 +1028,40 @@ bool common_generator::generate_register(std::ostream& os, const pseudo_node_ins
|
|||
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)
|
||||
{
|
||||
/* 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++)
|
||||
{
|
||||
if(it->second[i].inst.node().reg().valid())
|
||||
{
|
||||
if(!generate_register(fout, it->second[i]))
|
||||
{
|
||||
printf("Cannot generate register");
|
||||
printf("Cannot generate register ");
|
||||
print_inst(it->second[i]);
|
||||
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);
|
||||
fout.close();
|
||||
|
@ -1646,6 +1711,11 @@ class jz_generator : public common_generator
|
|||
return m_soc.size() >= 2;
|
||||
}
|
||||
|
||||
bool has_offsets() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string selector_soc_dir(const soc_ref_t& ref) const
|
||||
{
|
||||
return ref.get()->name;
|
||||
|
@ -1811,6 +1881,11 @@ class imx_generator : public common_generator
|
|||
return m_soc.size() >= 2;
|
||||
}
|
||||
|
||||
bool has_offsets() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string selector_soc_dir(const soc_ref_t& ref) const
|
||||
{
|
||||
return ref.get()->name;
|
||||
|
@ -1978,6 +2053,11 @@ class atj_generator : public common_generator
|
|||
return false;
|
||||
}
|
||||
|
||||
bool has_offsets() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string selector_soc_dir(const soc_ref_t& ref) const
|
||||
{
|
||||
return ref.get()->name;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue