Skip to content

Instantly share code, notes, and snippets.

@kuldeepdhaka
Last active January 6, 2016 09:19
Show Gist options
  • Save kuldeepdhaka/6e8bcaf9ab86c7f3db1d to your computer and use it in GitHub Desktop.
Save kuldeepdhaka/6e8bcaf9ab86c7f3db1d to your computer and use it in GitHub Desktop.
uC-def-dsl
python uc-def.py test-input test-output
comment* @defgroup adc_reg_base ADC register base addresses
@ingroup adc_defines
@{
family
name ADC
instance ADC_BASE
code
#define ADC1 ADC_BASE /* for API compatibility */
comment* @}
cmnt ADC interrupt and status register
reg ISR
bit AWD 7
bit OVR 4
bit EOSEQ 3
bit EOC 2
bit EOSMP 1
bit ADRDY 0
cmnt Interrupt Enable Register
reg IER
bit AWDIE 7
bit OVRIE 4
bit EOSEQIE 3
bit EOCIE 2
bit EOSMPIE 1
bit ADRDYIE 0
cmnt Control Register
reg CR
bit ADCAL 31
bit ADSTP 4
bit ADSTART 2
bit ADDIS 1
bit ADEN 0
cmnt Configuration Register 1
reg CFGR1
bits AWDCH 5 26
bit AWDEN 23
bit AWDSGL 22
bit DISCEN 16
bit AUTOFF 15
bit WAIT 14
bit CONT 13
bit OVRMOD 12
bits
name EXTEN
offset 10
size 2
value DISABLE 0
value RISING 1
value FALLING 2
value BOTH 3
bits EXTSEL 3 6
bit ALIGN 5
bits
name RES
offset 3
size 2
value 12_BIT 0
value 10_BIT 1
value 8_BIT 2
value 6_BIT 3
bit SCANDIR 2
bit DMACFG 1
bit DMAEN 0
cmnt Configuration Register 2
reg CFGR2
bits
name CKMODE
offset 30
size 2
value CK_ADC 0
value PCLK_DIV2 1
value PCLK_DIV4 2
cmnt Sample Time Register 1
reg SMPR
bits
name SMP
offset 0
size 3
value 001DOT5 0
value 007DOT5 1
value 013DOT5 2
value 028DOT5 3
value 041DOT5 4
value 055DOT5 5
value 071DOT5 6
value 239DOT5 7
cmnt Watchdog Threshold Register
reg TR
bits LT 12 0
bits HT 12 16
cmnt Channel Select Register
reg CHSELR 0x28
code #define ADC_CHSELR_CHSEL(x) (1 << (x))
cmnt Regular Data Register
reg DR 0x40
code #define ADC_DR_DATA 0xFFFF
cmnt Regular Data Register
reg CCR 0x308
bit VBATEN 24
bit TSEN 23
bit VREFEN 22
/** @defgroup adc_reg_base ADC register base addresses
* @ingroup adc_defines
* @{
*/
#define ADC (ADC_BASE)
#define ADC1 ADC_BASE /* for API compatibility */
/** @}
*/
/* ADC interrupt and status register */
#define ADC_ISR MMIO32((ADC_BASE) + (0x0))
#define ADC_ISR_AWD_SHIFT (7)
#define ADC_ISR_AWD (1 << ADC_ISR_AWD_SHIFT)
#define ADC_ISR_OVR_SHIFT (4)
#define ADC_ISR_OVR (1 << ADC_ISR_OVR_SHIFT)
#define ADC_ISR_EOSEQ_SHIFT (3)
#define ADC_ISR_EOSEQ (1 << ADC_ISR_EOSEQ_SHIFT)
#define ADC_ISR_EOC_SHIFT (2)
#define ADC_ISR_EOC (1 << ADC_ISR_EOC_SHIFT)
#define ADC_ISR_EOSMP_SHIFT (1)
#define ADC_ISR_EOSMP (1 << ADC_ISR_EOSMP_SHIFT)
#define ADC_ISR_ADRDY_SHIFT (0)
#define ADC_ISR_ADRDY (1 << ADC_ISR_ADRDY_SHIFT)
/* Interrupt Enable Register */
#define ADC_IER MMIO32((ADC_BASE) + (0x4))
#define ADC_IER_AWDIE_SHIFT (7)
#define ADC_IER_AWDIE (1 << ADC_IER_AWDIE_SHIFT)
#define ADC_IER_OVRIE_SHIFT (4)
#define ADC_IER_OVRIE (1 << ADC_IER_OVRIE_SHIFT)
#define ADC_IER_EOSEQIE_SHIFT (3)
#define ADC_IER_EOSEQIE (1 << ADC_IER_EOSEQIE_SHIFT)
#define ADC_IER_EOCIE_SHIFT (2)
#define ADC_IER_EOCIE (1 << ADC_IER_EOCIE_SHIFT)
#define ADC_IER_EOSMPIE_SHIFT (1)
#define ADC_IER_EOSMPIE (1 << ADC_IER_EOSMPIE_SHIFT)
#define ADC_IER_ADRDYIE_SHIFT (0)
#define ADC_IER_ADRDYIE (1 << ADC_IER_ADRDYIE_SHIFT)
/* Control Register */
#define ADC_CR MMIO32((ADC_BASE) + (0x8))
#define ADC_CR_ADCAL_SHIFT (31)
#define ADC_CR_ADCAL (1 << ADC_CR_ADCAL_SHIFT)
#define ADC_CR_ADSTP_SHIFT (4)
#define ADC_CR_ADSTP (1 << ADC_CR_ADSTP_SHIFT)
#define ADC_CR_ADSTART_SHIFT (2)
#define ADC_CR_ADSTART (1 << ADC_CR_ADSTART_SHIFT)
#define ADC_CR_ADDIS_SHIFT (1)
#define ADC_CR_ADDIS (1 << ADC_CR_ADDIS_SHIFT)
#define ADC_CR_ADEN_SHIFT (0)
#define ADC_CR_ADEN (1 << ADC_CR_ADEN_SHIFT)
/* Configuration Register 1 */
#define ADC_CFGR1 MMIO32((ADC_BASE) + (0xc))
#define ADC_CFGR1_AWDCH_SHIFT (26)
#define ADC_CFGR1_AWDCH_MASK (0x1f << (ADC_CFGR1_AWDCH_SHIFT))
#define ADC_CFGR1_AWDCH(v) (((v) << (ADC_CFGR1_AWDCH_SHIFT)) & (ADC_CFGR1_AWDCH_MASK))
#define ADC_CFGR1_AWDEN_SHIFT (23)
#define ADC_CFGR1_AWDEN (1 << ADC_CFGR1_AWDEN_SHIFT)
#define ADC_CFGR1_AWDSGL_SHIFT (22)
#define ADC_CFGR1_AWDSGL (1 << ADC_CFGR1_AWDSGL_SHIFT)
#define ADC_CFGR1_DISCEN_SHIFT (16)
#define ADC_CFGR1_DISCEN (1 << ADC_CFGR1_DISCEN_SHIFT)
#define ADC_CFGR1_AUTOFF_SHIFT (15)
#define ADC_CFGR1_AUTOFF (1 << ADC_CFGR1_AUTOFF_SHIFT)
#define ADC_CFGR1_WAIT_SHIFT (14)
#define ADC_CFGR1_WAIT (1 << ADC_CFGR1_WAIT_SHIFT)
#define ADC_CFGR1_CONT_SHIFT (13)
#define ADC_CFGR1_CONT (1 << ADC_CFGR1_CONT_SHIFT)
#define ADC_CFGR1_OVRMOD_SHIFT (12)
#define ADC_CFGR1_OVRMOD (1 << ADC_CFGR1_OVRMOD_SHIFT)
#define ADC_CFGR1_EXTEN_SHIFT (10)
#define ADC_CFGR1_EXTEN_MASK (0x3 << (ADC_CFGR1_EXTEN_SHIFT))
#define ADC_CFGR1_EXTEN(v) (((v) << (ADC_CFGR1_EXTEN_SHIFT)) & (ADC_CFGR1_EXTEN_MASK))
#define ADC_CFGR1_EXTEN_DISABLE ADC_CFGR1_EXTEN(0x0)
#define ADC_CFGR1_EXTEN_RISING ADC_CFGR1_EXTEN(0x1)
#define ADC_CFGR1_EXTEN_FALLING ADC_CFGR1_EXTEN(0x2)
#define ADC_CFGR1_EXTEN_BOTH ADC_CFGR1_EXTEN(0x3)
#define ADC_CFGR1_EXTSEL_SHIFT (6)
#define ADC_CFGR1_EXTSEL_MASK (0x7 << (ADC_CFGR1_EXTSEL_SHIFT))
#define ADC_CFGR1_EXTSEL(v) (((v) << (ADC_CFGR1_EXTSEL_SHIFT)) & (ADC_CFGR1_EXTSEL_MASK))
#define ADC_CFGR1_ALIGN_SHIFT (5)
#define ADC_CFGR1_ALIGN (1 << ADC_CFGR1_ALIGN_SHIFT)
#define ADC_CFGR1_RES_SHIFT (3)
#define ADC_CFGR1_RES_MASK (0x3 << (ADC_CFGR1_RES_SHIFT))
#define ADC_CFGR1_RES(v) (((v) << (ADC_CFGR1_RES_SHIFT)) & (ADC_CFGR1_RES_MASK))
#define ADC_CFGR1_RES_12_BIT ADC_CFGR1_RES(0x0)
#define ADC_CFGR1_RES_10_BIT ADC_CFGR1_RES(0x1)
#define ADC_CFGR1_RES_8_BIT ADC_CFGR1_RES(0x2)
#define ADC_CFGR1_RES_6_BIT ADC_CFGR1_RES(0x3)
#define ADC_CFGR1_SCANDIR_SHIFT (2)
#define ADC_CFGR1_SCANDIR (1 << ADC_CFGR1_SCANDIR_SHIFT)
#define ADC_CFGR1_DMACFG_SHIFT (1)
#define ADC_CFGR1_DMACFG (1 << ADC_CFGR1_DMACFG_SHIFT)
#define ADC_CFGR1_DMAEN_SHIFT (0)
#define ADC_CFGR1_DMAEN (1 << ADC_CFGR1_DMAEN_SHIFT)
/* Configuration Register 2 */
#define ADC_CFGR2 MMIO32((ADC_BASE) + (0x10))
#define ADC_CFGR2_CKMODE_SHIFT (30)
#define ADC_CFGR2_CKMODE_MASK (0x3 << (ADC_CFGR2_CKMODE_SHIFT))
#define ADC_CFGR2_CKMODE(v) (((v) << (ADC_CFGR2_CKMODE_SHIFT)) & (ADC_CFGR2_CKMODE_MASK))
#define ADC_CFGR2_CKMODE_CK_ADC ADC_CFGR2_CKMODE(0x0)
#define ADC_CFGR2_CKMODE_PCLK_DIV2 ADC_CFGR2_CKMODE(0x1)
#define ADC_CFGR2_CKMODE_PCLK_DIV4 ADC_CFGR2_CKMODE(0x2)
/* Sample Time Register 1 */
#define ADC_SMPR MMIO32((ADC_BASE) + (0x14))
#define ADC_SMPR_SMP_SHIFT (0)
#define ADC_SMPR_SMP_MASK (0x7 << (ADC_SMPR_SMP_SHIFT))
#define ADC_SMPR_SMP(v) (((v) << (ADC_SMPR_SMP_SHIFT)) & (ADC_SMPR_SMP_MASK))
#define ADC_SMPR_SMP_001DOT5 ADC_SMPR_SMP(0x0)
#define ADC_SMPR_SMP_007DOT5 ADC_SMPR_SMP(0x1)
#define ADC_SMPR_SMP_013DOT5 ADC_SMPR_SMP(0x2)
#define ADC_SMPR_SMP_028DOT5 ADC_SMPR_SMP(0x3)
#define ADC_SMPR_SMP_041DOT5 ADC_SMPR_SMP(0x4)
#define ADC_SMPR_SMP_055DOT5 ADC_SMPR_SMP(0x5)
#define ADC_SMPR_SMP_071DOT5 ADC_SMPR_SMP(0x6)
#define ADC_SMPR_SMP_239DOT5 ADC_SMPR_SMP(0x7)
/* Watchdog Threshold Register */
#define ADC_TR MMIO32((ADC_BASE) + (0x18))
#define ADC_TR_LT_SHIFT (0)
#define ADC_TR_LT_MASK (0xfff << (ADC_TR_LT_SHIFT))
#define ADC_TR_LT(v) (((v) << (ADC_TR_LT_SHIFT)) & (ADC_TR_LT_MASK))
#define ADC_TR_HT_SHIFT (16)
#define ADC_TR_HT_MASK (0xfff << (ADC_TR_HT_SHIFT))
#define ADC_TR_HT(v) (((v) << (ADC_TR_HT_SHIFT)) & (ADC_TR_HT_MASK))
/* Channel Select Register */
#define ADC_CHSELR MMIO32((ADC_BASE) + (0x28))
#define ADC_CHSELR_CHSEL(x) (1 << (x))
/* Regular Data Register */
#define ADC_DR MMIO32((ADC_BASE) + (0x40))
#define ADC_DR_DATA 0xFFFF
/* Regular Data Register */
#define ADC_CCR MMIO32((ADC_BASE) + (0x308))
#define ADC_CCR_VBATEN_SHIFT (24)
#define ADC_CCR_VBATEN (1 << ADC_CCR_VBATEN_SHIFT)
#define ADC_CCR_TSEN_SHIFT (23)
#define ADC_CCR_TSEN (1 << ADC_CCR_TSEN_SHIFT)
#define ADC_CCR_VREFEN_SHIFT (22)
#define ADC_CCR_VREFEN (1 << ADC_CCR_VREFEN_SHIFT)
name of the language: uc-def
________________________________________________________________________________
anything that start with # (first character is a comment) in the uc-def language
note: in printing two register block, newline will automatically be placed
________________________________________________________________________________
newline for \n
short hand:
~~~~~~~~~
nl
~~~~~~~~~
________________________________________________________________________________
access flags
r = reading permitted
w = writing permitted
h = modified by hardware
c = write 1 to clear, writing 0 has no affect
s = write 1 to set, writing 0 has no affect
t = write 1 to toggle, writing 0 has no affect
________________________________________________________________________________
~~~~~~~~~~~~~~~~
family
name <name>
instance <address>
instance <id> <address>
register <size> <stride>
~~~~~~~~~~~~~~~~
short hand:
~~~~~~~~~~~~~~~~
fam <name> <address>
~~~~~~~~~~~~~~~~
example: <name> = SPI
note: for [instance <address>], it will output.
#define <name>_<register> (....)
note: for [instance <id> <address>], it will output.
#define <name><id>_<register>(...) <name>_<register>(<address>, ...)
note: there can only be one "instance <address>"
note: there can be multiple "instance <id> <address>" is used
note: instance is optional (so, that means for short hand, <address> is optional too)
note: "register <size> <stride>" tell the default
register size (in byte) and
register stride <stride> (in bytes)
note: "register <size> <stride>" is optional.
default: <size> = 4
default: <stride> = <size> [<stide> is again optional inside the register]
________________________________________________________________________________
~~~~~~~~~~~~~~~~
register
name <name>
offset <offset>
offset <id> <offset>
size <size>
access <access>
~~~~~~~~~~~~~~~~
short hand:
~~~~~~~~~~~~~~~~
reg <name> <offset> <size>
~~~~~~~~~~~~~~~~
example: <name> = CFG
note: <name> can be multiple times, and the non-first will be considered alias of first
note: <size> is in bytes and tell the number of bytes in the register
note: <offset> (optional) and is calculated from last register (size + offset).
offset tell the number of bytes away from the family
if the register is first in the family, this value is assumed 0
note: " offset <id> <offset>" can be used multiple times to specify several type of same register
note: " offset <id> <offset>" or " offset <offset>" . only one type can be used at a time
note: <size> not given, then 4 is assumed.
note: <access> is like global access
note: <access> if not provided, "r", "w" is assumed
note: <access-macro> = MMIO8 for <size> = 1
note: <access-macro> = MMIO16 for <size> = 2
note: <access-macro> = MMIO32 for <size> = 4
output: if multiple not given.
#define <family>_<name>(...) <access-macro>(... + <offset>)
output: if multiple given
FOR ALL i IN [0...<num>)
#define <family>_<name><i>(..., i) <access-macro>(... + <offset> + (<stride> * i))
________________________________________________________________________________
~~~~~~~~~~~~~~~~
bit
name <name>
offset <offset>
access <access>
~~~~~~~~~~~~~~~~
short hand
~~~~~~~~~~~~~~~~
bit <name> <offset>
~~~~~~~~~~~~~~~~
example: <name> = EN
note: <name> can be multiple times, and the non-first will be considered alias of first
note: <offset> is the offset of the bit in number-of-bits
note: <offset> (optional) is not provided, it calculated from using.
- just after "register": <offset> = 0
- after another "bit": <offset> = <last-bit-offset> + 1
- after another "bits": <offset> = <last-bits-offset> + <last-bits-size>
output:
#define <family>_<register>_<name>_SHIFT (<offset>)
#define <family>_<register>_<name>(...) (1 << <family>_<register>_<name>_SHIFT)
note: <access> is like global access
note: <access> if not provided, "r", "w" is assumed
________________________________________________________________________________
~~~~~~~~~~~~~~~~
bits
name <name>
offset <offset>
offset <id> <offset>
access <access>
size <size>
value <value-name> <value-value>
~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~
bits <name> <size> <offset>
~~~~~~~~~~~~~~~~
note: <name>, <offset> and <access> are same in docs like "bit"
note: <size> is the value of the span of the bits. (in number-of-bits)
note: "value <value-name> <value-value>" is used to define some kind of special value (multiple)
example:
for spi, MODE = 0, MODE1 = 1, MODE2 = 2, MODE3 = MODE3
using "value MODE0 0", "value MODE1 1" ... we can get the special values
note: <mask> = MASK_BIT0 << 0 | MASK_BIT1 |... MASK_BITn
where MASK_BITx = (1 << x) IF x IN [0, <size>)
or MASK_BITx = (0 << x) IF x NOT IN [0, <size>)
output:
#define <family>_<register>_<name>_SHIFT (<offset>)
#define <family>_<register>_<name>_MASK ((<mask>) << <family>_<register>_<name>_SHIFT)
#define <family>_<register>_<name>(..., v) \
(((v) << <family>_<register>_<name>_SHIFT) & <family>_<register>_<name>_MASK)
note:
<value-value> if missing, is infered from last value.
and for the first one in the data-structure, 0 is asssumed (because it do not have any previous to refer)
if "value" exists (for each "value")
#define <family>_<register>_<name>_<value-name>(...) \
<family>_<register>_<name>(..., <value-value>)
________________________________________________________________________________
code <code-start>
<code1>
<code2>
<code3>
<codeN>
output:
<code-start>
<code1>
<code2>
<code3>
<codeN>
note: if <code-start> is provided, <code...> is optional and vice versa
________________________________________________________________________________
comment<ch> <comment-start>
<comment1>
<comment2>
<comment3>
<commentN>
short-hand
~~~~~~~~~~~~~
cmnt<ch> <comment-start>
~~~~~~~~~~~~~
output:
/*<ch> <comment-start>
* <comment1>
* <comment2>
* <comment3>
* <commentN>
*/
note: <ch> is optional.
example: <ch> = * for /**
example: <ch> = ! for /*!
example: <ch> is not provided, /*
note: <comment...> is optional, if <comment-start> is given (and vice versa)
#!/bin/python
"""
uC Def.
Microcontroller register defination
Author: Kuldeep Singh Dhaka <[email protected]>
Licence: GPLv3 or later
"""
import sys
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def verify_access_flags(data):
for i in data:
if i not in ('r', 'w', 'c', 's', 'h'):
raise Exception("'%c' flag of flags '%s' not valid" % (i, data))
def next_useful_line(input_file):
if not hasattr(input_file, 'line_number'):
input_file.line_number = 0
while input_file.readable():
input_file.last_useful_pos = input_file.tell()
inp = input_file.readline()
if not len(inp):
break
inp = inp.rstrip()
if not len(inp):
logger.debug("** SKIPPING NEWLINE at %i ***" % input_file.line_number)
input_file.line_number += 1
continue
if not inp[0] == '#':
logger.debug("** LINE %i '%s' ***" % (input_file.line_number, inp))
input_file.line_number += 1
return inp;
else:
logger.debug("** SKIPPING %i '%s' ***" % (input_file.line_number, inp))
input_file.line_number += 1
logger.debug("** END OF FILE ***")
return ''
def restore_last_useful_line(input_file):
input_file.seek(input_file.last_useful_pos)
def get_line_number(input_file):
return input_file.line_number
def we_have_problem(msg, input_file):
raise Exception("%s [line: %i]" % (msg, get_line_number(input_file)))
def parse_code(inp, input_file):
result = []
# code <code-start>
assert(inp[0:4] == "code")
data = inp[5:]
has_head_code = False
if len(data):
has_head_code = True
result.append("%s\n" % data)
# more code
has_body = False
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
restore_last_useful_line(input_file)
break
has_body = True
result.append("%s\n" % inp[1:])
if not has_body and not has_head_code:
we_have_problem("code head had no code and also no member code", input_file)
return result
def parse_comment(inp, input_file):
result = []
if inp[0:4] == 'cmnt':
# cmnt<ch> <comment-start>
if inp[4] == ' ': result.append("/* %s */\n" % inp[5:])
else: result.append("/*%s %s */\n" % (inp[4], inp[6:]))
return result
# comment<ch> <comment-start>
assert(inp[0:7] == "comment")
if inp[7] == ' ': result.append("/* %s\n" % inp[8:])
else: result.append("/*%s %s\n" % (inp[7], inp[9:]))
# more comments
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
restore_last_useful_line(input_file)
break
result.append(' * %s\n' % inp[1:])
result.append(" */\n")
return result
def parse_extra(input_file):
result = None
while True:
inp = next_useful_line(input_file)
if inp == '': break
if inp[0] == 'n':
assert(inp in ("newline", "nl"))
r = ["\n"]
elif inp[0:3] == 'cod':
r = parse_code(inp, input_file)
elif inp[0:3] in ('com', 'cmn'):
r = parse_comment(inp, input_file)
else:
restore_last_useful_line(input_file)
break;
if result is None:
result = []
result += r
return result
# this will return the last readed line. (if it could not parse it)
def parse_family_member(input_file):
family = {'name': None, 'instance': None, 'register': None}
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
# revese back and return
restore_last_useful_line(input_file)
break
data = inp.split()
assert(len(data) >= 1)
# name <name>
if data[0] == "name":
family['name'] = data[1]
elif data[0] == "instance":
# instance <address>
if len(data) == 2:
assert(family['instance'] is None)
family['instance'] = data[1]
# instance <id> <address>
elif len(data) == 3:
if family['instance'] is None: family['instance'] = []
assert(type(family['instance']) == list)
instance = {'id': data[1], 'address': data[2]}
family['instance'].append(instance)
else: we_have_problem("unknown design of instance", input_file)
elif data[0] == "register":
assert(2 <= len(data) <= 3)
family['register'] = {
'size': data[1],
'stride': data[2] if len(data) > 2 else None
}
assert(family['name'] is not None)
return family
def parse_family(input_file):
inp = next_useful_line(input_file)
if inp == '':
return None
if not inp[0] == 'f':
restore_last_useful_line(input_file)
return None
if not inp == "family":
# fam <name> <address>
data = inp.slit()
assert(len(data) < 2 and data[0] == "fam")
return {
'name': data[1],
'instance': data[2] if len(data) > 2 else None,
'register': None
}
else:
return parse_family_member(input_file)
def parse_register_member(input_file):
register = {'name': [], 'offset': None, 'size': None, 'access': None}
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
# revese back and return
restore_last_useful_line(input_file)
break
data = inp.split()
assert(len(data) >= 1)
# name <name>
if data[0] == "name":
register['name'].append(data[1])
elif data[0] == "offset":
if len(data) == 2:
# offset <offset>
assert(register['offset'] is None)
register['offset'] = data[1]
elif len(data) == 3:
# offset <id> <offset>
if register['offset'] is None:
register['offset'] = []
assert(type(register['offset']) == list)
register['offset'].append({'id': data[1], 'offset': data[2]})
else:
we_have_problem("unknown design of offset", input_file)
elif data[1] == "size":
# size <size>
register['size'] = data[1]
elif data[1] == "access":
# access <access>
for c in data[1]:
assert(c in ('r', 'w', 'h'))
register['access'] = data[1]
assert(len(register['name']))
return register
def parse_register(input_file):
inp = next_useful_line(input_file)
if inp == '':
return None
if not inp[0] == 'r':
restore_last_useful_line(input_file)
return None
if inp[3] == ' ':
# reg <name> <offset> <size>
data = inp.split()
assert(2 <= len(data) <= 4)
assert(data[0] == "reg")
return {
'name': [ data[1] ],
'offset': data[2] if len(data) > 2 else None,
'size': data[3] if len(data) > 3 else None,
'access': None
}
else:
assert(inp == "register")
return parse_register_member(input_file)
def parse_bit_member(input_file):
bit = {'name': [], 'offset': None, 'access': None}
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
# revese back and return
restore_last_useful_line(input_file)
break
data = inp.split()
assert(len(data) >= 1)
# name <name>
if data[0] == "name":
bit['name'].append(data[1])
elif data[0] == "offset":
if len(data) == 2:
# offset <offset>
assert(bit['offset'] is None)
bit['offset'] = data[1]
elif len(data) == 3:
# offset <id> <offset>
if bit['offset'] is None:
bit['offset'] = []
assert(type(bit['offset']) == list)
bit['offset'].append({'id': data[1], 'offset': data[2]})
else:
we_have_problem("unknown design of offset", input_file)
elif data[0] == "access":
# access <access>
verify_access_flags(data[1])
bit['access'] = data[1]
assert(len(bit['name']))
return bit
def parse_bit(input_file):
inp = next_useful_line(input_file)
if inp == '':
return None
data = inp.split()
if data[0] != "bit":
restore_last_useful_line(input_file)
return None
if len(data) > 1:
# bit <name> <offset>
return {
'name' : [ data[1] ],
'offset': data[2] if len(data) > 2 else None,
'access': None
}
else:
return parse_bit_member(input_file)
def parse_bits_member(input_file):
bits = {'name': [], 'offset': None, 'size': None, 'access': None, 'values': []}
while True:
inp = next_useful_line(input_file)
if inp == '': break
if not inp[0] == ' ':
# revese back and return
restore_last_useful_line(input_file)
break
data = inp.split()
assert(len(data) >= 1)
# name <name>
if data[0] == "name":
bits['name'].append(data[1])
elif data[0] == "offset":
if len(data) == 2:
# offset <offset>
assert(bits['offset'] is None)
bits['offset'] = data[1]
elif len(data) == 3:
# offset <id> <offset>
if bits['offset'] is None:
bits['offset'] = []
assert(type(bits['offset']) == list)
bits['offset'].append({'id': data[1], 'offset': data[2]})
else:
we_have_problem("unknown design of offset", input_file)
elif data[0] == "size":
# size <size>
bits['size'] = data[1]
elif data[0] == "value":
assert(len(data) >= 1)
# value <value-name> <value-value>
bits['values'].append({
'name': data[1],
'value': data[2] if len(data) > 2 else None
})
elif data[0] == "access":
# access <access>
verify_access_flags(data[1])
bits['access'] = data[1]
assert(bits['name'] is not None)
assert(bits['size'] is not None)
return bits
def parse_bits(input_file):
inp = next_useful_line(input_file)
if inp == '':
return None
data = inp.split()
if data[0] != "bits":
restore_last_useful_line(input_file)
return None
if len(data) > 1:
assert(len(data) > 2)
# bits <name> <size> <offset>
return {
'name' : [ data[1] ] ,
'size': data[2],
'offset': data[3] if len(data) > 3 else None,
'access': None,
'values': []
}
else:
return parse_bits_member(input_file)
def parse_input(input_file):
data = []
while input_file.readable():
extra = parse_extra(input_file)
if extra is not None:
data.append({'type': 'extra', 'payload': extra})
family = parse_family(input_file)
if family is None:
break
data.append({'type': 'family', 'payload': family})
while True:
extra = parse_extra(input_file)
if extra is not None:
data.append({'type': 'extra', 'payload': extra})
register = parse_register(input_file)
if register is None:
break
data.append({'type': 'register', 'payload': register})
while True:
extra = parse_extra(input_file)
if extra is not None:
data.append({'type': 'extra', 'payload': extra})
bit = parse_bit(input_file)
if bit is not None:
data.append({'type': 'bit', 'payload': bit})
else:
bits = parse_bits(input_file)
if bits is None:
break
data.append({'type': 'bits', 'payload': bits})
return data
def generate_family(family, output_file):
# if instance are not provided
if family['instance'] is None:
return
if type(family['instance']) == list:
for i in family['instance']:
fam_id = '%s%s' % (family['name'], i['id'])
output_file.write("#define %s (%s)\n" % (fam_id, i['address']))
else:
addr = str(family['instance'])
name = family['name']
output_file.write("#define %s (%s)\n" % (name, addr))
# a final newline to seperate things
output_file.write("\n")
def generate_register(register, family, offset, output_file):
# calculate register size
size = 4
if register['size'] is not None:
size = int(register['size'], 0)
elif family['register'] is not None and family['register']['size'] is not None:
size = int(family['register']['size'], 0)
mmio = {
1: "MMIO8",
2: "MMIO16",
4: "MMIO32"
}.get(size)
assert(mmio is not None)
# calculate register offset
if register['offset'] is not None:
offset = int(register['offset'], 0)
#base macros of style PERPH_REG(base)
# if not instance is provided or multiple instance are there
if family['instance'] is None or type(family['instance']) is list:
register_name = register['name'][0]
actual_name = "%s_%s" % (family['name'], register_name)
output_file.write("#define %s(base) %s((base) + (%s))\n" % (actual_name, mmio, hex(offset)))
output_file.write("\n")
# alias of regiser (that accept base)
if len(register['name'][1:]):
output_file.write("/* Alias of %s */\n" % actual_name)
for register_name in register['name'][1:]:
alias_name = "%s_%s" % (family['name'], register_name)
output_file.write("#define %s(base) %s(base)\n" % \
(alias_name, actual_name))
if len(register['name'][1:]):
output_file.write("\n")
# instace that send base to above macros
if family['instance'] is not None: # ie family['instance'] type is of list
for instance in family['instance']:
for register_name in register['name']:
frm = "%s%s_%s" % (family['name'], instance['id'], register_name)
to = "%s_%s" % (family['name'], register_name)
addr = "%s%s" % (family['name'], instance['id'])
output_file.write("#define %s %s(%s)\n" % (frm, to, addr))
output_file.write("\n")
else:
#single instance
register_name = register['name'][0]
actual_name = "%s_%s" % (family['name'], register_name)
output_file.write("#define %s %s((%s) + (%s))\n" % \
(actual_name, mmio, family['instance'], hex(offset)))
output_file.write("\n")
if len(register['name'][1:]):
output_file.write("/* Alias of %s */\n" % actual_name)
for register_name in register['name'][1:]:
alias_name = "%s_%s" % (family['name'], register_name)
output_file.write("#define %s %s" % (alias_name, actual_name))
output_file.write("\n")
if len(register['name'][1:]):
output_file.write("\n")
stride = size
if family['register'] is not None and family['register']['stride'] is not None:
stride = int(family['register']['stride'], 0)
return (offset + stride), size
def generate_bit(bit, register, family, offset, register_size, output_file):
if bit['offset'] is not None:
offset = int(bit['offset'], 0)
assert((offset + 1) <= (register_size * 8))
actual_name = None
for register_name in register['name']:
for bit_name in bit['name']:
if register['name'].index(register_name) == bit['name'].index(bit_name) == 0:
actual_name = "%s_%s_%s" % (family['name'], register_name, bit_name)
output_file.write("#define %s_SHIFT (%i)\n" % (actual_name, offset))
output_file.write("#define %s (1 << %s_SHIFT)\n" % (actual_name, actual_name))
else:
alias_name = "%s_%s_%s" % (family['name'], register_name, bit_name)
output_file.write("/* Alias of %s */\n" % actual_name)
output_file.write("#define %s_SHIFT %s_SHIFT\n" % (alias_name, actual_name))
output_file.write("#define %s %s\n" % (alias_name, actual_name))
output_file.write("\n")
output_file.write("\n")
return (offset + 1)
def generate_bits(bits, register, family, offset, register_size, output_file):
if bits['offset'] is not None:
offset = int(bits['offset'], 0)
size = int(bits['size'], 0)
assert((offset + size) <= (register_size * 8))
mask = hex(pow(2, size) - 1)
actual_name = None
for register_name in register['name']:
for bits_name in bits['name']:
if (bits['name'].index(bits_name) == 0) and \
(register['name'].index(register_name) == 0):
#print original macro
actual_name = "%s_%s_%s" % (family['name'], register_name, bits_name)
output_file.write("#define %s_SHIFT (%i)\n" % (actual_name, offset))
output_file.write("#define %s_MASK (%s << (%s_SHIFT))\n" % \
(actual_name, mask, actual_name))
output_file.write("#define %s(v) (((v) << (%s_SHIFT)) & (%s_MASK))\n" % \
((actual_name, ) * 3))
# values
value_value = 0
for v in bits['values']:
if v['value'] is not None:
value_value = int(v['value'], 0)
output_file.write("#define %s_%s %s(%s)\n" % \
(actual_name, v['name'], actual_name, hex(value_value)))
value_value += 1
else:
#print alias macro
alias_name = "%s_%s_%s" % (family['name'], register_name, bits_name)
output_file.write("/* Alias of %s */\n" % actual_name)
output_file.write("#define %s_SHIFT %s_SHIFT\n" % (alias_name, actual_name))
output_file.write("#define %s_MASK %s_MASK\n" % (alias_name, actual_name))
output_file.write("#define %s(v) %s(v)\n" % (alias_name, actual_name))
# alias values
for v in bits['values']:
output_file.write("#define %s_%s %s_%s\n" % \
(alias_name, v['name'], actual_name, v['name']))
output_file.write("\n")
output_file.write("\n")
return (offset + size)
def generate_output(data, output_file):
family = None
register = None
register_size = None
register_offset = None
register_next_bit = None
for d in data:
if d['type'] == 'extra':
for i in d['payload']:
output_file.write(i)
output_file.write("\n")
elif d['type'] == 'family':
family = d['payload']
register_offset = 0 # reset register offset
generate_family(family, output_file)
elif d['type'] == 'register':
register = d['payload']
register_next_bit = 0
register_offset, register_size = generate_register( \
register, family, register_offset, output_file)
elif d['type'] == 'bit':
register_next_bit = generate_bit(d['payload'], register, family, \
register_next_bit, register_size, output_file)
elif d['type'] == 'bits':
register_next_bit = generate_bits(d['payload'], register, family, \
register_next_bit, register_size, output_file)
if __name__ == "__main__":
assert (len(sys.argv) > 1)
input_file = open(sys.argv[1])
output_file = open(sys.argv[2], 'w+') if len(sys.argv) > 2 else sys.stdout
data = parse_input(input_file)
#~ print(data)
generate_output(data, output_file)
@kuldeepdhaka
Copy link
Author

TODO: add a access flags for

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment