Settings can be defined globally or per-ISA. They are available to code through a generated Settings struct with accessor methods per setting.
105 lines
3.0 KiB
Python
105 lines
3.0 KiB
Python
"""
|
|
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)
|