Scaffolding for defining settings.
Settings can be defined globally or per-ISA. They are available to code through a generated Settings struct with accessor methods per setting.
This commit is contained in:
104
meta/gen_settings.py
Normal file
104
meta/gen_settings.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
Generate sources with settings.
|
||||
"""
|
||||
|
||||
import srcgen
|
||||
from cretonne import BoolSetting, NumSetting, settings
|
||||
|
||||
|
||||
def layout_group(sgrp):
|
||||
"""
|
||||
Layout the settings in sgrp, assigning byte and bit offsets.
|
||||
|
||||
Return the next unused byte offset.
|
||||
"""
|
||||
# Byte offset where booleans are allocated.
|
||||
bool_byte = -1
|
||||
# Next available bit number in bool_byte.
|
||||
bool_bit = 10
|
||||
# Next available whole byte.
|
||||
next_byte = 0
|
||||
|
||||
for setting in sgrp.settings:
|
||||
if isinstance(setting, BoolSetting):
|
||||
# Allocate a bit from bool_byte.
|
||||
if bool_bit > 7:
|
||||
bool_byte = next_byte
|
||||
next_byte += 1
|
||||
bool_bit = 0
|
||||
setting.byte_offset = bool_byte
|
||||
setting.bit_offset = bool_bit
|
||||
bool_bit += 1
|
||||
else:
|
||||
# This is a numerical or enumerated setting. Allocate a single
|
||||
# byte.
|
||||
setting.byte_offset = next_byte
|
||||
next_byte += 1
|
||||
|
||||
return next_byte
|
||||
|
||||
|
||||
def gen_getter(setting, fmt):
|
||||
"""
|
||||
Emit a getter function for `setting`.
|
||||
"""
|
||||
fmt.doc_comment(setting.__doc__ + '.')
|
||||
|
||||
if isinstance(setting, BoolSetting):
|
||||
proto = 'pub fn {}(&self) -> bool'.format(setting.name)
|
||||
with fmt.indented(proto + ' {', '}'):
|
||||
fmt.line('(self.bytes[{}] & (1 << {})) != 0'.format(
|
||||
setting.byte_offset,
|
||||
setting.bit_offset))
|
||||
elif isinstance(setting, NumSetting):
|
||||
proto = 'pub fn {}(&self) -> u8'.format(setting.name)
|
||||
with fmt.indented(proto + ' {', '}'):
|
||||
fmt.line('self.bytes[{}]'.format(setting.byte_offset))
|
||||
else:
|
||||
raise AssertionError("Unknown setting kind")
|
||||
|
||||
|
||||
def gen_getters(sgrp, fmt):
|
||||
"""
|
||||
Emit getter functions for all the settings in fmt.
|
||||
"""
|
||||
fmt.doc_comment("User-defined settings.")
|
||||
with fmt.indented('impl Settings {', '}'):
|
||||
for setting in sgrp.settings:
|
||||
gen_getter(setting, fmt)
|
||||
|
||||
|
||||
def gen_default(sgrp, byte_size, fmt):
|
||||
"""
|
||||
Emit a Default impl for Settings.
|
||||
"""
|
||||
v = [0] * byte_size
|
||||
for setting in sgrp.settings:
|
||||
v[setting.byte_offset] |= setting.default_byte()
|
||||
|
||||
with fmt.indented('impl Default for Settings {', '}'):
|
||||
fmt.doc_comment('Return a `Settings` object with default values.')
|
||||
with fmt.indented('fn default() -> Settings {', '}'):
|
||||
with fmt.indented('Settings {', '}'):
|
||||
vs = ', '.join('{:#04x}'.format(x) for x in v)
|
||||
fmt.line('bytes: [ {} ],'.format(vs))
|
||||
|
||||
|
||||
def gen_group(sgrp, fmt):
|
||||
"""
|
||||
Generate a Settings struct representing `sgrp`.
|
||||
"""
|
||||
byte_size = layout_group(sgrp)
|
||||
|
||||
fmt.doc_comment('Settings group `{}`.'.format(sgrp.name))
|
||||
with fmt.indented('pub struct Settings {', '}'):
|
||||
fmt.line('bytes: [u8; {}],'.format(byte_size))
|
||||
|
||||
gen_getters(sgrp, fmt)
|
||||
gen_default(sgrp, byte_size, fmt)
|
||||
|
||||
|
||||
def generate(isas, out_dir):
|
||||
fmt = srcgen.Formatter()
|
||||
gen_group(settings.group, fmt)
|
||||
fmt.update_file('settings.rs', out_dir)
|
||||
Reference in New Issue
Block a user