rockbox/utils/regtools/include/soc_desc_v1.hpp
Amaury Pouly 0f701a64be regtools: update v2 specification, library and tools
A v2 register description file can now include register variants and instances
addresses can now be a list (previously it could only be a stride or a formula).
Update the library to deal with that. The convert option of swiss_knife was
updated and one incompatible change was introduce: if a v1 device has several
addresses, those are converted to a single v2 instance with list (instead of
several single instances). This should have been the behaviour from the start.
Swiss_knife can now also convert regdumps, in which case it needs to be given
both the dump and register description file. Also introduce two register
descriptions files (vsoc1000 and vsoc2000) which give more complicated examples
of v2 register description files.

Change-Id: Id9415b8363269ffaf9216abfc6dd1bd1adbfcf8d
2016-02-06 15:12:55 +00:00

230 lines
No EOL
6.9 KiB
C++

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __SOC_DESC_V1__
#define __SOC_DESC_V1__
#include <stdint.h>
#include <vector>
#include <list>
#include <string>
#include <map>
/**
* These data structures represent the SoC register in a convenient way.
* The basic structure is the following:
* - each SoC has several devices
* - each device has a generic name, a list of {name,address} and several registers
* - each register has a generic name, a list of {name,address}, flags,
* several fields
* - each field has a name, a first and last bit position, can apply either
* to all addresses of a register or be specific to one only and has several values
* - each field value has a name and a value
*
* All addresses, values and names are relative to the parents. For example a field
* value BV_LCDIF_CTRL_WORD_LENGTH_18_BIT is represented has:
* - device LCDIF, register CTRL, field WORD_LENGTH, value 16_BIT
* The address of CTRL is related to the address of LCDIF, the value of 16_BIT
* ignores the position of the WORD_LENGTH field in the register.
*/
namespace soc_desc_v1
{
const size_t MAJOR_VERSION = 1;
const size_t MINOR_VERSION = 4;
const size_t REVISION_VERSION = 1;
/**
* Typedef for SoC types: word, address and flags */
typedef uint32_t soc_addr_t;
typedef uint32_t soc_word_t;
typedef uint32_t soc_reg_flags_t;
/** SoC error gravity level */
enum soc_error_level_t
{
SOC_ERROR_WARNING,
SOC_ERROR_FATAL,
};
/** SoC description error */
struct soc_error_t
{
soc_error_level_t level; /// level (warning, fatal, ...)
std::string location; /// human description of the location
std::string message; /// message
};
/** SoC register generic formula */
enum soc_reg_formula_type_t
{
REG_FORMULA_NONE, /// register has no generic formula
REG_FORMULA_STRING, /// register has a generic formula represented by a string
};
/** <soc_reg_t>.<flags> values */
const soc_reg_flags_t REG_HAS_SCT = 1 << 0; /// register SCT variants
/** SoC register field named value */
struct soc_reg_field_value_t
{
std::string name; /// name of the value
soc_word_t value; /// numeric value
std::string desc; /// human description
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC register field */
struct soc_reg_field_t
{
std::string name; /// name of the field
std::string desc; /// human description
unsigned first_bit, last_bit; /// bit range of the field
soc_reg_field_t():first_bit(0), last_bit(31) {}
/** Return field bitmask in register */
soc_word_t bitmask() const
{
// WARNING beware of the case where first_bit=0 and last_bit=31
if(first_bit == 0 && last_bit == 31)
return 0xffffffff;
else
return ((1 << (last_bit - first_bit + 1)) - 1) << first_bit;
}
/** Extract field value from register value */
soc_word_t extract(soc_word_t reg_val) const
{
return (reg_val & bitmask()) >> first_bit;
}
/** Replace the field value in a register value */
soc_word_t replace(soc_word_t reg_val, soc_word_t field_val) const
{
return (reg_val & ~bitmask()) | ((field_val << first_bit) & bitmask());
}
bool is_reserved() const
{
return name.substr(0, 4) == "RSVD" || name.substr(0, 5) == "RSRVD";
}
/** Return field value index, or -1 if none */
int find_value(soc_word_t v) const
{
for(size_t i = 0; i < value.size(); i++)
if(value[i].value == v)
return i;
return -1;
}
std::vector< soc_reg_field_value_t > value;
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC register address */
struct soc_reg_addr_t
{
std::string name; /// actual register name
soc_addr_t addr; /// actual register address (relative to device)
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC register formula */
struct soc_reg_formula_t
{
enum soc_reg_formula_type_t type;
std::string string; /// for STRING
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC register */
struct soc_reg_t
{
std::string name; /// generic name (for multi registers) or actual name
std::string desc; /// human description
std::vector< soc_reg_addr_t > addr; /// instances of the registers
soc_reg_formula_t formula; /// formula for the instance addresses
soc_reg_flags_t flags; /// ORed value
std::vector< soc_reg_field_t > field;
std::vector< soc_error_t > errors(bool recursive);
};
/** Soc device address */
struct soc_dev_addr_t
{
std::string name; /// actual device name
soc_addr_t addr;
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC device */
struct soc_dev_t
{
std::string name; /// generic name (of multi devices) or actual name
std::string long_name; /// human friendly name
std::string desc; /// human description
std::string version; /// description version
std::vector< soc_dev_addr_t > addr;
std::vector< soc_reg_t > reg;
std::vector< soc_error_t > errors(bool recursive);
};
/** SoC */
struct soc_t
{
std::string name; /// codename (rockbox)
std::string desc; /// SoC name
std::vector< soc_dev_t > dev;
std::vector< soc_error_t > errors(bool recursive);
};
/** Parse a SoC description from a XML file, append it to <soc>. */
bool parse_xml(const std::string& filename, soc_t& soc);
/** Write a SoC description to a XML file, overwriting it. A file can contain
* multiple Soc descriptions */
bool produce_xml(const std::string& filename, const soc_t& soc);
/** Normalise a soc description by reordering elements so that:
* - devices are sorted by first name
* - registers are sorted by first address
* - fields are sorted by last bit
* - values are sorted by value */
void normalize(soc_t& soc);
/** Formula parser: try to parse and evaluate a formula with some variables */
bool evaluate_formula(const std::string& formula,
const std::map< std::string, soc_word_t>& var, soc_word_t& result,
std::string& error);
} // soc_desc_v1
#endif /* __SOC_DESC_V1__ */