Last active
January 6, 2016 09:19
-
-
Save kuldeepdhaka/6e8bcaf9ab86c7f3db1d to your computer and use it in GitHub Desktop.
uC-def-dsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
python uc-def.py test-input test-output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TODO: add a access flags for