From 0c36da0b59bd3d5aeb6f7bd7f75913695a1dd366 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 8 Mar 2014 15:24:39 +0000 Subject: [PATCH] Implement ROMable modules. Add math module. mp_module_obj_t can now be put in ROM. Configuration of float type is now similar to longint: can now choose none, float or double as the implementation. math module has basic math functions. For STM port, these are not yet implemented (they are just stub functions). --- py/builtin.c | 12 ++++--- py/builtin.h | 3 +- py/builtinmath.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ py/builtinmp.c | 47 +++++++++++++++----------- py/mpconfig.h | 20 +++++++++-- py/obj.c | 8 ++--- py/obj.h | 21 +++++++----- py/objcomplex.c | 12 +++---- py/objfloat.c | 15 +++------ py/objfun.c | 2 +- py/objmodule.c | 42 +++++++++++++++-------- py/py.mk | 1 + py/qstrdefs.h | 29 +++++++++++++++- py/runtime.c | 12 ++++--- stm/Makefile | 1 + stm/main.c | 25 -------------- stm/math.c | 48 +++++++++++++++++++++++++++ stm/mpconfigport.h | 5 +-- unix/main.c | 6 ---- unix/mpconfigport.h | 5 +-- unix/time.c | 2 +- 21 files changed, 280 insertions(+), 117 deletions(-) create mode 100644 py/builtinmath.c create mode 100644 stm/math.c diff --git a/py/builtin.c b/py/builtin.c index ef9e70c94..df488e054 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -15,6 +15,10 @@ #include "map.h" #include "builtin.h" +#if MICROPY_ENABLE_FLOAT +#include +#endif + // args[0] is function from class body // args[1] is class name // args[2:] are base objects @@ -79,7 +83,7 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) { } return MP_OBJ_NEW_SMALL_INT(val); #if MICROPY_ENABLE_FLOAT - } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) { + } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) { mp_float_t value = mp_obj_float_get(o_in); // TODO check for NaN etc if (value < 0) { @@ -87,10 +91,10 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) { } else { return o_in; } - } else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) { + } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) { mp_float_t real, imag; mp_obj_complex_get(o_in, &real, &imag); - return mp_obj_new_float(machine_sqrt(real*real + imag*imag)); + return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)); #endif } else { assert(0); @@ -158,7 +162,7 @@ STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) { } else { // n_args == 1 // make a list of names in the given object mp_obj_type_t *type = mp_obj_get_type(args[0]); - if (type == &module_type) { + if (type == &mp_type_module) { map = mp_obj_module_get_globals(args[0]); } else if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)) { map = mp_obj_dict_get_map(type->locals_dict); diff --git a/py/builtin.h b/py/builtin.h index 85ceeafdf..d9414045d 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -34,4 +34,5 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_str_obj); MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj); -void mp_module_micropython_init(void); +extern const mp_obj_module_t mp_module_math; +extern const mp_obj_module_t mp_module_micropython; diff --git a/py/builtinmath.c b/py/builtinmath.c new file mode 100644 index 000000000..cccda9d48 --- /dev/null +++ b/py/builtinmath.c @@ -0,0 +1,81 @@ +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "map.h" +#include "builtin.h" + +#if MICROPY_ENABLE_FLOAT + +#define MATH_FUN_1(py_name, c_name) \ + mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ + STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); + +#define MATH_FUN_2(py_name, c_name) \ + mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \ + STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); + +STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI}; + +MATH_FUN_1(sqrt, sqrt) +MATH_FUN_2(pow, pow) +MATH_FUN_1(exp, exp) +MATH_FUN_1(log, log) +MATH_FUN_1(log2, log2) +MATH_FUN_1(log10, log10) +MATH_FUN_1(cosh, cosh) +MATH_FUN_1(sinh, sinh) +MATH_FUN_1(tanh, tanh) +MATH_FUN_1(acosh, acosh) +MATH_FUN_1(asinh, asinh) +MATH_FUN_1(atanh, atanh) +MATH_FUN_1(cos, cos) +MATH_FUN_1(sin, sin) +MATH_FUN_1(tan, tan) +MATH_FUN_1(acos, acos) +MATH_FUN_1(asin, asin) +MATH_FUN_1(atan, atan) +MATH_FUN_2(atan2, atan2) + +STATIC const mp_map_elem_t mp_module_math_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_math) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pi), (mp_obj_t)&mp_math_pi_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&mp_math_sqrt_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_math_pow_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_exp), (mp_obj_t)&mp_math_exp_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_log), (mp_obj_t)&mp_math_log_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_log2), (mp_obj_t)&mp_math_log2_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_log10), (mp_obj_t)&mp_math_log10_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_cosh), (mp_obj_t)&mp_math_cosh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&mp_math_sinh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&mp_math_tanh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_acosh), (mp_obj_t)&mp_math_acosh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_asinh), (mp_obj_t)&mp_math_asinh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_atanh), (mp_obj_t)&mp_math_atanh_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_cos), (mp_obj_t)&mp_math_cos_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sin), (mp_obj_t)&mp_math_sin_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&mp_math_tan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_acos), (mp_obj_t)&mp_math_acos_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&mp_math_asin_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&mp_math_atan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_atan2), (mp_obj_t)&mp_math_atan2_obj }, +}; + +STATIC const mp_map_t mp_module_math_globals = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_math_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_math_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_math_globals_table, +}; + +const mp_obj_module_t mp_module_math = { + .base = { &mp_type_module }, + .name = MP_QSTR_math, + .globals = (mp_map_t*)&mp_module_math_globals, +}; + +#endif // MICROPY_ENABLE_FLOAT diff --git a/py/builtinmp.c b/py/builtinmp.c index 28bea3b84..22091f4ea 100644 --- a/py/builtinmp.c +++ b/py/builtinmp.c @@ -1,45 +1,52 @@ #include -#include -#include -#include -#include -#include #include "misc.h" #include "mpconfig.h" #include "qstr.h" #include "obj.h" -#include "runtime.h" +#include "map.h" #include "builtin.h" // Various builtins specific to MicroPython runtime, // living in micropython module #if MICROPY_MEM_STATS -STATIC mp_obj_t mem_total() { +STATIC mp_obj_t mp_micropython_mem_total() { return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_total_bytes_allocated()); } -STATIC mp_obj_t mem_current() { +STATIC mp_obj_t mp_micropython_mem_current() { return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_current_bytes_allocated()); } -STATIC mp_obj_t mem_peak() { +STATIC mp_obj_t mp_micropython_mem_peak() { return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_peak_bytes_allocated()); } -MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_total_obj, mem_total); -MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_current_obj, mem_current); -MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_peak_obj, mem_peak); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak); #endif -void mp_module_micropython_init(void) { - mp_obj_t m_mp = mp_obj_new_module(MP_QSTR_micropython); - rt_store_name(MP_QSTR_micropython, m_mp); - +STATIC const mp_map_elem_t mp_module_micropython_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_micropython) }, #if MICROPY_MEM_STATS - rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_total"), (mp_obj_t)&mp_builtin_mem_total_obj); - rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_current"), (mp_obj_t)&mp_builtin_mem_current_obj); - rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_peak"), (mp_obj_t)&mp_builtin_mem_peak_obj); + { MP_OBJ_NEW_QSTR(MP_QSTR_mem_total), (mp_obj_t)&mp_micropython_mem_total_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mem_current), (mp_obj_t)&mp_micropython_mem_current_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mem_peak), (mp_obj_t)&mp_micropython_mem_peak_obj }, #endif -} +}; + +STATIC const mp_map_t mp_module_micropython_globals = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_micropython_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_micropython_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_micropython_globals_table, +}; + +const mp_obj_module_t mp_module_micropython = { + .base = { &mp_type_module }, + .name = MP_QSTR_micropython, + .globals = (mp_map_t*)&mp_module_micropython_globals, +}; diff --git a/py/mpconfig.h b/py/mpconfig.h index 34c83d324..5b13c4648 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -84,8 +84,24 @@ typedef long long mp_longint_impl_t; #define MICROPY_ENABLE_SOURCE_LINE (0) #endif -// Whether to support float and complex types -#ifndef MICROPY_ENABLE_FLOAT +// Float and complex implementation +#define MICROPY_FLOAT_IMPL_NONE (0) +#define MICROPY_FLOAT_IMPL_FLOAT (1) +#define MICROPY_FLOAT_IMPL_DOUBLE (2) + +#ifndef MICROPY_FLOAT_IMPL +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#endif + +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_FLOAT_C_FUN(fun) fun##f +typedef float mp_float_t; +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_FLOAT_C_FUN(fun) fun +typedef double mp_float_t; +#else #define MICROPY_ENABLE_FLOAT (0) #endif diff --git a/py/obj.c b/py/obj.c index 0068af4c4..0c97ee5aa 100644 --- a/py/obj.c +++ b/py/obj.c @@ -165,14 +165,14 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) { } #if MICROPY_ENABLE_FLOAT -machine_float_t mp_obj_get_float(mp_obj_t arg) { +mp_float_t mp_obj_get_float(mp_obj_t arg) { if (arg == mp_const_false) { return 0; } else if (arg == mp_const_true) { return 1; } else if (MP_OBJ_IS_SMALL_INT(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); - } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { + } else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) { return mp_obj_float_get(arg); } else { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); @@ -189,10 +189,10 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { } else if (MP_OBJ_IS_SMALL_INT(arg)) { *real = MP_OBJ_SMALL_INT_VALUE(arg); *imag = 0; - } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { + } else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) { *real = mp_obj_float_get(arg); *imag = 0; - } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) { + } else if (MP_OBJ_IS_TYPE(arg, &mp_type_complex)) { mp_obj_complex_get(arg, real, imag); } else { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); diff --git a/py/obj.h b/py/obj.h index 2ccda66ee..4d93c7afa 100644 --- a/py/obj.h +++ b/py/obj.h @@ -9,12 +9,6 @@ typedef machine_const_ptr_t mp_const_obj_t; typedef machine_int_t mp_small_int_t; -// The machine floating-point type used for float and complex numbers - -#if MICROPY_ENABLE_FLOAT -typedef machine_float_t mp_float_t; -#endif - // Anything that wants to be a Micro Python object must have // mp_obj_base_t as its first member (except NULL and small ints) @@ -318,12 +312,16 @@ extern const mp_obj_type_t bytes_type; #if MICROPY_ENABLE_FLOAT // float -extern const mp_obj_type_t float_type; +typedef struct _mp_obj_float_t { + mp_obj_base_t base; + mp_float_t value; +} mp_obj_float_t; +extern const mp_obj_type_t mp_type_float; mp_float_t mp_obj_float_get(mp_obj_t self_in); mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs); // complex -extern const mp_obj_type_t complex_type; +extern const mp_obj_type_t mp_type_complex; void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); #endif @@ -398,7 +396,12 @@ extern const mp_obj_type_t super_type; extern const mp_obj_type_t gen_instance_type; // module -extern const mp_obj_type_t module_type; +typedef struct _mp_obj_module_t { + mp_obj_base_t base; + qstr name; + struct _mp_map_t *globals; +} mp_obj_module_t; +extern const mp_obj_type_t mp_type_module; mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_module_get(qstr module_name); struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in); diff --git a/py/objcomplex.c b/py/objcomplex.c index 188c33413..bba89daf0 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -39,7 +39,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const case 1: // TODO allow string as first arg and parse it - if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { + if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { return args[0]; } else { return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); @@ -48,13 +48,13 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const case 2: { mp_float_t real, imag; - if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { + if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); } else { real = mp_obj_get_float(args[0]); imag = 0; } - if (MP_OBJ_IS_TYPE(args[1], &complex_type)) { + if (MP_OBJ_IS_TYPE(args[1], &mp_type_complex)) { mp_float_t real2, imag2; mp_obj_complex_get(args[1], &real2, &imag2); real -= imag2; @@ -85,7 +85,7 @@ STATIC mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in); } -const mp_obj_type_t complex_type = { +const mp_obj_type_t mp_type_complex = { { &mp_type_type }, .name = MP_QSTR_complex, .print = complex_print, @@ -96,14 +96,14 @@ const mp_obj_type_t complex_type = { mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) { mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t); - o->base.type = &complex_type; + o->base.type = &mp_type_complex; o->real = real; o->imag = imag; return o; } void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) { - assert(MP_OBJ_IS_TYPE(self_in, &complex_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_complex)); mp_obj_complex_t *self = self_in; *real = self->real; *imag = self->imag; diff --git a/py/objfloat.c b/py/objfloat.c index 268bc2bde..8ba9946b7 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -13,11 +13,6 @@ #if MICROPY_ENABLE_FLOAT -typedef struct _mp_obj_float_t { - mp_obj_base_t base; - mp_float_t value; -} mp_obj_float_t; - mp_obj_t mp_obj_new_float(mp_float_t value); STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { @@ -38,7 +33,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_decimal(s, l); - } else if (MP_OBJ_IS_TYPE(args[0], &float_type)) { + } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) { return args[0]; } else { return mp_obj_new_float(mp_obj_get_float(args[0])); @@ -61,14 +56,14 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) { STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_float_t *lhs = lhs_in; - if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) { + if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) { return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in); } else { return mp_obj_float_binary_op(op, lhs->value, rhs_in); } } -const mp_obj_type_t float_type = { +const mp_obj_type_t mp_type_float = { { &mp_type_type }, .name = MP_QSTR_float, .print = float_print, @@ -79,13 +74,13 @@ const mp_obj_type_t float_type = { mp_obj_t mp_obj_new_float(mp_float_t value) { mp_obj_float_t *o = m_new(mp_obj_float_t, 1); - o->base.type = &float_type; + o->base.type = &mp_type_float; o->value = value; return (mp_obj_t)o; } mp_float_t mp_obj_float_get(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &float_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_float)); mp_obj_float_t *self = self_in; return self->value; } diff --git a/py/objfun.c b/py/objfun.c index 80cee1643..361df1914 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -372,7 +372,7 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { uint l; return (machine_uint_t)mp_obj_str_get_data(obj, &l); #if MICROPY_ENABLE_FLOAT - } else if (MP_OBJ_IS_TYPE(obj, &float_type)) { + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_float)) { // convert float to int (could also pass in float registers) return (machine_int_t)mp_obj_float_get(obj); #endif diff --git a/py/objmodule.c b/py/objmodule.c index ab460fbd3..791932dc7 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -10,12 +10,7 @@ #include "obj.h" #include "runtime.h" #include "map.h" - -typedef struct _mp_obj_module_t { - mp_obj_base_t base; - qstr name; - mp_map_t *globals; -} mp_obj_module_t; +#include "builtin.h" STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_module_t *self = self_in; @@ -37,7 +32,7 @@ STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { return true; } -const mp_obj_type_t module_type = { +const mp_obj_type_t mp_type_module = { { &mp_type_type }, .name = MP_QSTR_module, .print = module_print, @@ -46,32 +41,51 @@ const mp_obj_type_t module_type = { }; mp_obj_t mp_obj_new_module(qstr module_name) { - mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); // We could error out if module already exists, but let C extensions // add new members to existing modules. if (el->value != MP_OBJ_NULL) { return el->value; } + // create new module object mp_obj_module_t *o = m_new_obj(mp_obj_module_t); - o->base.type = &module_type; + o->base.type = &mp_type_module; o->name = module_name; o->globals = mp_map_new(1); - el->value = o; + + // store __name__ entry in the module mp_map_lookup(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = MP_OBJ_NEW_QSTR(module_name); + + // store the new module into the slot in the global dict holding all modules + el->value = o; + + // return the new module return o; } mp_obj_t mp_obj_module_get(qstr module_name) { + // lookup module mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); - if (el == NULL) { - return MP_OBJ_NULL; + + // module found, return it + if (el != NULL) { + return el->value; } - return el->value; + + // module not found, look for builtin module names +#if MICROPY_ENABLE_FLOAT + if (module_name == MP_QSTR_math) { + return (mp_obj_t)&mp_module_math; + } +#endif + + // no module found, return NULL object + return MP_OBJ_NULL; } mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &module_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module)); mp_obj_module_t *self = self_in; return self->globals; } diff --git a/py/py.mk b/py/py.mk index 72ac785b5..579375e7d 100644 --- a/py/py.mk +++ b/py/py.mk @@ -73,6 +73,7 @@ PY_O_BASENAME = \ builtinimport.o \ builtinevex.o \ builtinmp.o \ + builtinmath.o \ vm.o \ showbc.o \ repl.o \ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index f1ba14ae6..8025b9bcc 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -1,5 +1,6 @@ // All the qstr definitions in this file are available as constants. -// That is, they are in ROM and you can reference them simple as MP_QSTR_xxxx. +// That is, they are in ROM and you can reference them simply as MP_QSTR_xxxx. +// TODO make it so we can use #defines here to select only those words that will be used Q(__build_class__) Q(__class__) @@ -115,6 +116,32 @@ Q(iterator) Q(module) Q(slice) +Q(math) +Q(pi) +Q(sqrt) +Q(pow) +Q(exp) +Q(log) +Q(log2) +Q(log10) +Q(cosh) +Q(sinh) +Q(tanh) +Q(acosh) +Q(asinh) +Q(atanh) +Q(cos) +Q(sin) +Q(tan) +Q(acos) +Q(asin) +Q(atan) +Q(atan2) + +Q(mem_total) +Q(mem_current) +Q(mem_peak) + Q() Q() Q() diff --git a/py/runtime.c b/py/runtime.c index 9d41f059f..7034ce13c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -92,13 +92,13 @@ STATIC const mp_builtin_elem_t builtin_table[] = { // built-in types { MP_QSTR_bool, (mp_obj_t)&bool_type }, #if MICROPY_ENABLE_FLOAT - { MP_QSTR_complex, (mp_obj_t)&complex_type }, + { MP_QSTR_complex, (mp_obj_t)&mp_type_complex }, #endif { MP_QSTR_dict, (mp_obj_t)&dict_type }, { MP_QSTR_enumerate, (mp_obj_t)&enumerate_type }, { MP_QSTR_filter, (mp_obj_t)&filter_type }, #if MICROPY_ENABLE_FLOAT - { MP_QSTR_float, (mp_obj_t)&float_type }, + { MP_QSTR_float, (mp_obj_t)&mp_type_float }, #endif { MP_QSTR_int, (mp_obj_t)&int_type }, { MP_QSTR_list, (mp_obj_t)&list_type }, @@ -203,7 +203,9 @@ void rt_init(void) { //sys_path = mp_obj_new_list(0, NULL); //rt_store_attr(m_sys, MP_QSTR_path, sys_path); - mp_module_micropython_init(); + // we pre-import the micropython module + // probably shouldn't do this, so we are compatible with CPython + rt_store_name(MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython); // TODO: wastes one mp_code_t structure in mem next_unique_code_id = 1; // 0 indicates "no code" @@ -586,9 +588,9 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } return mp_obj_new_int(lhs_val); #if MICROPY_ENABLE_FLOAT - } else if (MP_OBJ_IS_TYPE(rhs, &float_type)) { + } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_float)) { return mp_obj_float_binary_op(op, lhs_val, rhs); - } else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) { + } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) { return mp_obj_complex_binary_op(op, lhs_val, 0, rhs); #endif } diff --git a/stm/Makefile b/stm/Makefile index cc16eda43..1675c22ab 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -47,6 +47,7 @@ LIBS = SRC_C = \ main.c \ printf.c \ + math.c \ system_stm32f4xx.c \ stm32fxxx_it.c \ string0.c \ diff --git a/stm/main.c b/stm/main.c index e5f5d4e76..bab8933b1 100644 --- a/stm/main.c +++ b/stm/main.c @@ -666,28 +666,3 @@ soft_reset: first_soft_reset = false; goto soft_reset; } - -// these 2 functions seem to actually work... no idea why -// replacing with libgcc does not work (probably due to wrong calling conventions) -double __aeabi_f2d(float x) { - // TODO - return 0.0; -} - -float __aeabi_d2f(double x) { - // TODO - return 0.0; -} - -double sqrt(double x) { - // TODO - return 0.0; -} - -machine_float_t machine_sqrt(machine_float_t x) { - asm volatile ( - "vsqrt.f32 %[r], %[x]\n" - : [r] "=t" (x) - : [x] "t" (x)); - return x; -} diff --git a/stm/math.c b/stm/math.c new file mode 100644 index 000000000..ac680f6b7 --- /dev/null +++ b/stm/math.c @@ -0,0 +1,48 @@ +#include + +// these 2 functions seem to actually work... no idea why +// replacing with libgcc does not work (probably due to wrong calling conventions) +double __aeabi_f2d(float x) { + // TODO + return 0.0; +} + +float __aeabi_d2f(double x) { + // TODO + return 0.0; +} + +/* +double sqrt(double x) { + // TODO + return 0.0; +} +*/ + +float sqrtf(float x) { + asm volatile ( + "vsqrt.f32 %[r], %[x]\n" + : [r] "=t" (x) + : [x] "t" (x)); + return x; +} + +// TODO we need import these functions from some library (eg musl or newlib) +float powf(float x, float y) { return 0.0; } +float expf(float x) { return 0.0; } +float logf(float x) { return 0.0; } +float log2f(float x) { return 0.0; } +float log10f(float x) { return 0.0; } +float coshf(float x) { return 0.0; } +float sinhf(float x) { return 0.0; } +float tanhf(float x) { return 0.0; } +float acoshf(float x) { return 0.0; } +float asinhf(float x) { return 0.0; } +float atanhf(float x) { return 0.0; } +float cosf(float x) { return 0.0; } +float sinf(float x) { return 0.0; } +float tanf(float x) { return 0.0; } +float acosf(float x) { return 0.0; } +float asinf(float x) { return 0.0; } +float atanf(float x) { return 0.0; } +float atan2f(float x, float y) { return 0.0; } diff --git a/stm/mpconfigport.h b/stm/mpconfigport.h index 9cbda9c6c..3f48c43f0 100644 --- a/stm/mpconfigport.h +++ b/stm/mpconfigport.h @@ -6,8 +6,8 @@ #define MICROPY_EMIT_INLINE_THUMB (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_REPL_HELPERS (1) -#define MICROPY_ENABLE_FLOAT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_PATH_MAX (128) /* Enable FatFS LFNs 0: Disable LFN feature. @@ -29,9 +29,6 @@ typedef int32_t machine_int_t; // must be pointer size typedef uint32_t machine_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size -typedef float machine_float_t; - -machine_float_t machine_sqrt(machine_float_t x); // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via diff --git a/unix/main.c b/unix/main.c index fb0a6ecf0..481b81581 100644 --- a/unix/main.c +++ b/unix/main.c @@ -383,12 +383,6 @@ int main(int argc, char **argv) { return 0; } -// for sqrt -#include -machine_float_t machine_sqrt(machine_float_t x) { - return sqrt(x); -} - #include uint mp_import_stat(const char *path) { diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 99c13a7dc..8950337d4 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -8,7 +8,7 @@ #define MICROPY_ENABLE_REPL_HELPERS (1) #define MICROPY_ENABLE_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PATH_MAX (PATH_MAX) @@ -28,9 +28,6 @@ typedef unsigned int machine_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size -typedef double machine_float_t; - -machine_float_t machine_sqrt(machine_float_t x); struct _mp_obj_fun_native_t; extern const struct _mp_obj_fun_native_t mp_builtin_open_obj; diff --git a/unix/time.c b/unix/time.c index 6dba9f0d0..1abd7cff3 100644 --- a/unix/time.c +++ b/unix/time.c @@ -28,7 +28,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); static mp_obj_t mod_time_sleep(mp_obj_t arg) { #if MICROPY_ENABLE_FLOAT struct timeval tv; - machine_float_t val = mp_obj_get_float(arg); + mp_float_t val = mp_obj_get_float(arg); double ipart; tv.tv_usec = round(modf(val, &ipart) * 1000000); tv.tv_sec = ipart;