URL
https://opencores.org/ocsvn/neo430/neo430/trunk
Subversion Repositories neo430
Compare Revisions
- This comparison shows the changes necessary to convert path
/neo430/trunk/neo430
- from Rev 195 to Rev 196
- ↔ Reverse comparison
Rev 195 → Rev 196
/.gitignore
0,0 → 1,13
# no generated project files |
*.bin |
*.o |
*.elf |
*.dat |
*.s |
|
# no executables |
sw/tools/image_gen/image_gen |
*.exe |
|
# no temp/legacy files/folders |
~* |
/README.md
1,12 → 1,14
# The NEO430 Processor |
|
[](https://travis-ci.com/stnolting/neo430) |
[](https://github.com/stnolting/neo430/commits/master) |
[](https://github.com/stnolting/neo430/issues) |
[](https://github.com/stnolting/neo430/blob/master/LICENSE) |
[](https://github.com/stnolting/neo430/releases) |
[](https://github.com/stnolting/neo430/blob/master/LICENSE) |
[](https://raw.githubusercontent.com/stnolting/neo430/master/doc/NEO430.pdf) |
|
[](https://github.com/stnolting/neo430/issues) |
[](https://github.com/stnolting/neo430/pulls) |
[](https://github.com/stnolting/neo430/commits/master) |
|
## Table of Content |
|
* [Introduction](#Introduction) |
63,7 → 65,7
- 16-bit open source soft-core microcontroller-like processor system |
- Full support of the original [MSP430 instruction set architecture](https://raw.githubusercontent.com/stnolting/neo430/master/doc/instruction_set.pdf) |
- Code-efficient CISC-like instruction capabilities |
- Tool chain based on free [TI msp430-gcc compiler](http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html "TI `msp430-gcc` compiler") (also available here [on github](https://github.com/stnolting/msp430-gcc)) |
- Tool chain based on free [TI msp430-gcc compiler](http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html "TI `msp430-gcc` compiler") (also available [here on github](https://github.com/stnolting/msp430-gcc)) |
- Application compilation scripts ([makefiles](https://github.com/stnolting/neo430/blob/master/sw/example/blink_led/Makefile)) for Windows Powershell / Windows Subsystem for Linux / native Linux |
- Software requirements (regardless of platform): |
- TI `msp430-gcc` compiler |
77,18 → 79,18
- Optional multiplier/divider unit ([MULDIV](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_muldiv.vhd)) |
- Optional high-precision timer ([TIMER](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_timer.vhd)) |
- Optional universal asynchronous receiver and transmitter ([UART](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_uart.vhd)) |
- Optional serial peripheral interface ([SPI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_spi.vhd)), 8 or 16 bit tansfer data size, 6 dedicated CS lines |
- Optional I2C-compatible two wire serial interface ([TWI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_twi.vhd)) supporting clock stretching |
- Optional serial peripheral interface master ([SPI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_spi.vhd)), 8 or 16 bit transfer data size, 6 dedicated chip-select lines |
- Optional I2C-compatible two wire serial interface master ([TWI](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_twi.vhd)) supporting clock stretching |
- Optional general purpose parallel IO port ([GPIO](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_gpio.vhd)), 16 inputs & 16 outputs, with pin-change interrupt and PWM option |
- Optional 32-bit Wishbone bus interface adapter ([WB32](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_wb_interface.vhd)) - including bridges to [Avalon (TM](https://github.com/stnolting/neo430/blob/master/rtl/top_templates/neo430_top_avm.vhd)) bus and [AXI4-Lite (TM](https://github.com/stnolting/neo430/blob/master/rtl/top_templates/neo430_top_axi4lite.vhd)) |
- Optional 32-bit Wishbone bus master interface adapter ([WB32](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_wb_interface.vhd)) - including bridges to [Avalon (TM](https://github.com/stnolting/neo430/blob/master/rtl/top_templates/neo430_top_avm.vhd)) bus and [AXI4-Lite (TM](https://github.com/stnolting/neo430/blob/master/rtl/top_templates/neo430_top_axi4lite.vhd)) |
- Optional watchdog timer ([WDT](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_wdt.vhd)) |
- Optional cyclic redundancy check unit ([CRC16/32](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_crc.vhd)) |
- Optional custom functions unit ([CFU](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_cfu.vhd)) for user-defined processor extensions |
- Optional custom functions unit ([CFU](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_cfu.vhd)) for processor-internal user-defined processor extensions |
- Optional 4 channel PWM controller with 4 or 8 bit resolution ([PWM](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_pwm.vhd)) |
- Optional Galois Ring Oscillator (GARO) based true random number generator ([TRNG](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_trng.vhd)) with de-biasing and internal post-processing |
- Optional external interrupts controller with 8 independent channels ([EXIRQ](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_exirq.vhd)), can also be used for software-triggered interrupts (traps, breakpoints, etc.) |
- Optional NCO-based programmable frequency generator with 3 independent channels ([FREQ_GEN](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_freq_gen.vhd)) |
- Optional internal [bootloader](https://github.com/stnolting/neo430/blob/master/sw/bootloader/bootloader.c) (2kB ROM) with serial user console and automatic boot from external SPI flash (like the FPGA configuration storage) |
- Optional NCO-based programmable frequency generator ([FREQ_GEN](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_freq_gen.vhd)) with 3 independent output channels |
- Optional internal [bootloader](https://github.com/stnolting/neo430/blob/master/sw/bootloader/bootloader.c) (2kB ROM) with serial user console and automatic application boot from external SPI flash (like the FPGA configuration storage) |
|
|
|
102,26 → 104,29
- No analog components |
- No support of TI's Code Composer Studio |
- No support of CPU's DADD operation |
- Just 4 CPU interrupt channels |
- No *implicit* software support of the NEO430 multiplier - but: there is a work-around* for that! ;) |
- Just 4 CPU interrupt channels (can be extended via the external IRQ controller) |
- Single clock domain for complete processor |
- Different numbers of instruction execution cycles |
- Only one power-down (sleep) mode |
- Wishbone-compatible interface to attach custom IP |
- Internal bootloader with text interface (via UART serial port) |
- Extended ALU functions (if enabled) |
|
*) A quite promising experimental mode to allow implicit multiplier usage (just write A*B in your code and the compiler |
will automatically utilize the multiplier unit for this) |
|
|
|
## Top Entity |
|
The top entity of the processor is [neo430_top.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_top.vhd) (in the rtl\core folder). |
Just instantiate this file in you project and you are ready to go! All signals of this top entity are of type *std_ulogic* or *std_ulogic_vector*, respectively. |
If you need a top entity with resolved signals, take a look at the [top_templates](https://github.com/stnolting/neo430/blob/master/rtl/top_templates) folder. |
The top entity of the processor is [**neo430_top.vhd**](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_top.vhd) (from the rtl\core folder). |
Just instantiate this file in your project and you are ready to go! All signals of this top entity are of type *std_ulogic* or *std_ulogic_vector*, respectively. |
If you need a top entity with resolved signals (*std_logic*), take a look at the [top_templates](https://github.com/stnolting/neo430/blob/master/rtl/top_templates) folder. |
These alternative top entities also support AXI or Avalon connectivity. |
|
|
### Generics |
|
The main features and the actually implemented peripheral modules are configured via the top unit's generics. |
|
| Generic Name | Type | Default Value | Function | |
|:-------------|:-----------------------:|:-------------:|:---------------------------------------------------------| |
| CLOCK_SPEED | natural | 100000000 | Clock speed of CPU clock input "clk_i" in Hz | |
148,7 → 153,7
|
### Signals |
|
Note regarding unused unit's IO: Connect all unused inputs to low and leave all unused outputs 'open'. |
Regarding unused unit's signals: Connect all unused inputs to low and leave all unused outputs 'open'. |
Signal driections are seen from the processor. |
|
| Signal Name | Width | Direction | HW Unit | Function | |
197,7 → 202,7
| Full (default) configuration: | 1869 (8%) | 1137 (5%) | 65800 (11%) | 0 (0%) | 121 MHz | |
| Minimal configuration (CPU + GPIO): | 590 (3%) | 230 (1%) | 49408 (8%) | 0 (0%) | 122 MHz | |
|
| __Lattice iCE40 UltraPlus** (iCE40UP5K-SG48I)__ | LUTs | FFs | EBRs | DSPs | SRAMs | f_max* | |
| __Lattice iCE40 UltraPlus** (iCE40UP5K-SG48I)__ | LUTs | FFs | EBRs | DSPs | SPRAMs | f_max* | |
|:-------------------------------------------------|:----------:|:----------:|:-------:|:------:|:-------:|:---------:| |
| Full (default) configuration: | 3928 (74%) | 1923 (36%) | 9 (30%) | 0 (0%) | 2 (50%) | 20.25 MHz | |
| Minimal configuration (CPU + GPIO + Bootloader): | 1812 (34%) | 755 (14%) | 4 (13%) | 0 (0%) | 2 (50%) | 20.25 MHz | |
204,7 → 209,7
|
*) Constrained |
|
**) Using optimized memory modules for IMEM (32kB) & DMEM(12kB) from the `rtl\fpga_specific\lattice_ice40up` folder |
**) Using optimized memory modules for IMEM (32kB) & DMEM (12kB) from the `rtl\fpga_specific\lattice_ice40up` folder |
|
|
### Device Utilization by Entity |
244,15 → 249,15
|
## HW-SW Ecosystem |
|
The NEO430 Processor porjects provides driver libraries for the CPU itself and all included peripheral modules. These libraries |
provide a certain level of hardware abstraction and allow an easier usage of the different hardware module. Hw modules that cannot |
be "explicitly" used (like CPU modules or the different memories) are not listed below. Also, there is no CFU driver library or |
example project - this has to be provided by the CFU designer. |
The NEO430 Processor project provides driver libraries for the CPU itself and all included peripheral modules. These libraries |
provide a certain level of hardware abstraction and allow an easy usage of the different hardware modules. Modules that cannot |
be used "explicitly" (like CPU modules or the different memories) are not listed below. |
|
| Hardware unit | VHDL source | C library source | C library header | SW example project | |
|:---------------------------------------|:-----------:|:----------------:|:----------------:|:------------------:| |
| Main CPU defines file | - | - | [neo430.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430.h) | - | |
| Central Processing Unit (CPU) | [neo430_cpu.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_cpu.vhd) | [neo430_cpu.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_cpu.c) | [neo430_cpu.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_cpu.h) |- | |
| Custom Functions Unit (CFU) | [neo430_cpu.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_cfu.vhd) | provided by CFU designer | provided by CFU designer | [example](https://github.com/stnolting/neo430/tree/master/sw/example/cfu_test) | |
| Checksum Unit (CRC16/32) | [neo430_crc.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_crc.vhd) | [neo430_crc.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_crc.c) | [neo430_crc.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_crc.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/crc_test) | |
| External Interrupts Controller (EXIRQ) | [neo430_exirq.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_exirq.vhd) | [neo430_exirq.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_exirq.c) | [neo430_exirq.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_exirq.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/exirq_test) | |
| Frequency Generator (FREQ_GEN) | [neo430_freq_gen.vhd](https://github.com/stnolting/neo430/blob/master/rtl/core/neo430_freq_gen.vhd) | [neo430_freq_gen.c](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/source/neo430_freq_gen.c) | [neo430_freq_gen.h](https://github.com/stnolting/neo430/blob/master/sw/lib/neo430/include/neo430_freq_gen.h) | [example](https://github.com/stnolting/neo430/tree/master/sw/example/freq_gen_demo) | |
271,52 → 276,52
|
## Performance |
|
In contrast to most mainstream processors the NEO430 processor does not implement a pipelined instruction execution. Instead, |
In contrast to most mainstream processors the NEO430 processor does not implement a "classic" pipelined instruction execution. Instead, |
a **multi-cycle instruction execution scheme** is used: Each single instruction is executed in a series of micro instructions |
requiring several clock cycles to complete. The main benefit of this execution style is the highly reduced logic overhead as no |
complex pipeline hazard detection and resolving logic is required making the NEO430 even sammler - at the cost of a reduced IPC |
(instructions per cycle). Also, the MSP430 ISA is not really compatible to the classic (e.g., DLX/MIPS) pipeline scheme due to |
complex pipeline hazard detection and resolving logic is required. This makes the NEO430 even smaller - at the cost of a reduced IPC |
(*instructions per cycle*). Also, the MSP430 ISA is not really compatible to the classic (DLX/MIPS-like) pipeline scheme due to |
its complex operand and adressing modes (e.g., ALU operations executing directly on memory data). However, this concept allows |
the processor to use very **dense and powerfull CISC-like operations**. |
|
Furthermore, the multi-cycle architecture features a **very short crtitical path** when compared to other (even 32-bit) |
processors. Thus, the NEO430 can operate at very high frequencies even on low-cost (e.g., +110MHz on an Intel Cyclone 4) |
and low-power FPGAs (e.g., +20MHz on a Lattice iCE40 UltraPlus) and without area constraints. |
processors. Thus, the NEO430 can operate at very high frequencies even on low-cost (e.g., +120MHz on an Intel Cyclone IV) |
and low-power FPGAs (e.g., +20MHz on a Lattice iCE40 UltraPlus) even without any area constraints. |
|
Depending on the format of the instruction, the actual execution can take 3 to 10 clock cycles. If all possible instruction |
types and formates are executed in an eually distributed manner (i.e. worst case), the average CPI (clock cycles per instruction) |
evaluates to **7.33 cycles/instruction resulting in 0.136 MIPS per MHz (worst case)**. |
Depending on the format / operand addressing mode of an instruction, the actual execution can take 3 to 10 clock cycles. If all possible instruction |
types and formats are executed in an equally distributed manner (this is the worst case), the average CPI (clock cycles per instruction) |
evaluates to **7.33 cycles/instruction resulting in 0.136 MIPS per MHz (again: worst case)**. |
|
|
### CoreMark Benchmark |
|
The [CoreMark CPU benchmark](https://www.eembc.org/coremark/) was executed on the NEO430 and is available in the |
project's [sw/example/coremark](https://github.com/stnolting/neo430/blob/master/sw/example/coremark) folder This benchmark |
tests the capabilities of the CPU itself rather than the functions provided by the whole system / SoC. |
[sw/example/coremark](https://github.com/stnolting/neo430/blob/master/sw/example/coremark) project folder This benchmark |
tests the capabilities of a CPU itself rather than the functions provided by the whole system / SoC. |
|
~~~ |
Hardware: 100 MHz, 32kB IMEM, 12kB DMEM, HW verison 0x0404, no peripherals used (except for the TIMER and the UART) |
Software: msp430-gcc 8.3.0 for Linux, MEM_METHOD is MEM_STACK, 2000 coremark iterations |
Configuration |
Hardware: 100 MHz, 32kB IMEM, 12kB DMEM, HW verison 0x0406, peripherals used: TIMER, UART, MULDIV |
Software: msp430-gcc 8.3.0 for Linux, MEM_METHOD is MEM_STACK, 2000 CoreMark iterations |
~~~ |
|
|__Optimization__ | __Coremark Score__ | __Relative Score__ | |
|:--------------------:|:------------------:|:---------------------:| |
| -Os | 6.57 | 0.065 Coremarks/MHz | |
| -O2 | 7.16 | 0.072 Coremarks/MHz | |
| -Os + NEO430_MULDIV* | 12.98 | 0.129 Coremarks/MHz | |
| -O2 + NEO430_MULDIV* | 15.26 | 0.152 Coremarks/MHz | |
| __Optimization__ | __Executable Size__ | __CoreMark Score__ | __Relative Score__ | |
|:---------------------|:-------------------:|:------------------:|:-------------------:| |
| -Os | 12150 bytes | 6.57 | 0.065 CoreMarks/MHz | |
| -O2 | 14600 bytes | 7.16 | 0.072 CoreMarks/MHz | |
| -Os + NEO430_MULDIV* | 12118 bytes | 14.43 | 0.144 CoreMarks/MHz | |
| -O2 + NEO430_MULDIV* | 14562 bytes | 17.68 | 0.176 CoreMarks/MHz | |
|
*) Using the NEO430 MULDIV unit for the core of the matrix multiplications. |
*) These results were generated using the "NEO430_HWMUL_ABI_OVERRIDE" feature, which allows to map implicit multiplications |
in the source code via compiler primitives directly to the multiplier core of the MULDIV unit. For more information see |
chapter "Multiplier and Divider Unit (MULDIV)" of [NEO430.pdf](https://raw.githubusercontent.com/stnolting/neo430/master/doc/NEO430.pdf). |
|
Even though a score of 6.57 can outnumber certain architectures and configurations (see the score table on the coremark |
homepage), the relative score of 0.065 coremarks per second might pretty low. But you have to keep in mind that benchmark |
was executed using only the resources of the CPU itself. The CPU consists of only ~500 Intel Cyclone IV LUTs and does not |
contain any sophisticated ALU operations like multiplication or barrel shifting. Also, all instructions are executed in a |
multi-cycle scheme requiring several clock cycles to complete. When explicitly using the NEO430 MULDIV unit for performing |
the matrix-operations benchmark scenario (among other operations, it is based on matrix-scalar, matrix-vector and |
matrix-matrix multiplications) the **coremark score is increased to 15.26**. By using additional HW accelerators from the |
NEO430 ecosystem (like the CRC unit) or by using the MULDIV unit also for address and index computations the performance |
and thus, the coremark score can be further increased |
Even though a score of 6.57 can outnumber certain architectures and configurations (see the score table on the CoreMark |
homepage), the relative score of 0.065 coremarks per second might sound pretty low. True. But you have to keep in mind that benchmark |
was executed using only the resources of the CPU itself. The CPU consists of only ~520 Intel Cyclone IV LUTs and does not |
contain any sophisticated ALU operations like multiplication or barrel shifting. When including NEO430 MULDIV unit (using the |
"NEO430_HWMUL_ABI_OVERRIDE" feature) the CoreMark score is increased to 17.6. By explicitly using additional HW accelerators |
from the NEO430 ecosystem (e.g. the CRC unit) the performance can be further increased. |
|
|
|
362,9 → 367,8
|
## Contact |
|
If you have any questions, bug reports, ideas or if you are facing problems with the NEO430, open a |
[new issue](https://github.com/stnolting/neo430/issues) or directly drop me a line. Also, I'm always happy to |
hear what cool projects people are realizing with this core :smiley: |
If you have any questions, bug reports, ideas or if you are facing problems with the NEO430 or want to give some kinf of feedback, open a |
[new issue](https://github.com/stnolting/neo430/issues) or directly drop me a line: |
|
stnolting@gmail.com |
|
372,7 → 376,7
|
## Citation |
|
If you are using the NEO430 in some kind of publication, please cite it as follows: |
If you are using the NEO430 Processor in some kind of publication, please cite it as follows: |
|
> S. Nolting, "The NEO430 Processor", github.com/stnolting/neo430 |
|
/doc/NEO430.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/sw/example/blink_led/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/cfu_test/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/coremark/core_main.c
94,10 → 94,10
#endif |
|
// ----------------------------------------------- |
#ifndef USE_NEO430_MULTIPLIER |
#pragma warning ("Using SW multiplication. Use >>make clean compile CC_USER_FLAGS+=-DUSE_NEO430_MULTIPLIER<< to use the NEO430 MULDIV unit instead.") |
#ifndef NEO430_HWMUL_ABI_OVERRIDE |
#pragma warning ("Using SW multiplication. Use >>make clean compile CC_USER_FLAGS+=-DNEO430_HWMUL_ABI_OVERRIDE<< to use the NEO430 MULDIV unit instead (experimental!)") |
#else |
#pragma warning ("Using NEO430 MULDIV unit for multiplications.") |
#pragma warning ("Using NEO430 MULDIV unit for multiplications (highly experimental!)") |
#endif |
|
#ifndef RUN_COREMARK |
/sw/example/coremark/core_matrix.c
241,11 → 241,7
ee_u32 i,j; |
for (i=0; i<N; i++) { |
for (j=0; j<N; j++) { |
#if USE_NEO430_MUL |
C[i*N+j]=(MATRES)neo430_mul32((int16_t)A[i*N+j], (int16_t)val); |
#else |
C[i*N+j]=(MATRES)A[i*N+j] * (MATRES)val; |
#endif |
} |
} |
} |
271,11 → 267,7
for (i=0; i<N; i++) { |
C[i]=0; |
for (j=0; j<N; j++) { |
#if USE_NEO430_MUL |
C[i]+=(MATRES)neo430_mul32((int16_t)A[i*N+j], (int16_t)B[j]); |
#else |
C[i]+=(MATRES)A[i*N+j] * (MATRES)B[j]; |
#endif |
} |
} |
} |
291,11 → 283,7
C[i*N+j]=0; |
for(k=0;k<N;k++) |
{ |
#if USE_NEO430_MUL |
C[i*N+j]+=(MATRES)neo430_mul32((int16_t)A[i*N+k], (int16_t)B[k*N+j]); |
#else |
C[i*N+j]+=(MATRES)A[i*N+k] * (MATRES)B[k*N+j]; |
#endif |
} |
} |
} |
312,11 → 300,7
C[i*N+j]=0; |
for(k=0;k<N;k++) |
{ |
#if USE_NEO430_MUL |
MATRES tmp=(MATRES)neo430_mul32((int16_t)A[i*N+k], (int16_t)B[k*N+j]); |
#else |
MATRES tmp=(MATRES)A[i*N+k] * (MATRES)B[k*N+j]; |
#endif |
C[i*N+j]+=bit_extract(tmp,2,4)*bit_extract(tmp,5,7); |
} |
} |
/sw/example/coremark/core_portme.h
35,12 → 35,6
#define NEO430_TIMER_F (10) // Hz |
#define FLAGS_STR "-> see makefile" // compiler optimization |
|
#ifndef USE_NEO430_MULTIPLIER |
#define USE_NEO430_MUL 0 // set 1 to use MULDIV unit for matrix core operations |
#else |
#define USE_NEO430_MUL 1 // set 1 to use MULDIV unit for matrix core operations |
#endif |
|
// For debugging |
#define xstr(a) str(a) |
#define str(a) #a |
/sw/example/coremark/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/crc_test/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/exirq_test/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/freq_gen_demo/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/game_of_life/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/gpio_interrupt/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/gpio_pwm_demo/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/hw_analysis/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/morse_translator/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/muldiv_test/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/nested_irqs/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/prime_numbers/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/pwm_demo/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/timer_simple/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/trng_test/makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/twi_test/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/uart_irq/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/wb_terminal/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/example/wdt_test/Makefile
108,8 → 108,14
IMAGE_GEN = $(NEO430_EXE_PATH)/image_gen |
|
# Compiler flags |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -mhwmult=none -fno-delete-null-pointer-checks |
CC_OPTS = -mcpu=msp430 -pipe -Wall -Xassembler --mY -fno-delete-null-pointer-checks |
CC_OPTS += -Wl,-static -mrelax -minrt -nostartfiles -fdata-sections -ffunction-sections -Xlinker --gc-sections |
# Use NEO430 multiplier? (still experimental!) |
ifeq (,$(findstring NEO430_HWMUL_ABI_OVERRIDE,$(CC_USER_FLAGS))) |
CC_OPTS += -mhwmult=none |
else |
CC_OPTS += -mhwmult=16bit |
endif |
# Add user flags if available |
CC_OPTS += ${CC_USER_FLAGS} |
|
/sw/lib/neo430/include/neo430.h
40,6 → 40,18
#include <stdlib.h> |
|
// ---------------------------------------------------------------------------- |
// Aux data types |
// ---------------------------------------------------------------------------- |
union uint16_u { uint16_t uint16; uint8_t uint8[ sizeof(uint16_t)/1]; }; |
union uint32_u { uint32_t uint32; uint16_t uint16[sizeof(uint32_t)/2]; uint8_t uint8[ sizeof(uint32_t)/1]; }; |
union uint64_u { uint64_t uint64; uint32_t uint32[sizeof(uint64_t)/4]; uint16_t uint16[sizeof(uint64_t)/2]; uint8_t uint8[sizeof(uint32_t)/1]; }; |
|
union int16_u { int16_t int16; int8_t int8[ sizeof(int16_t)/1]; }; |
union int32_u { int32_t int32; int16_t int16[sizeof(int32_t)/2]; int8_t int8[ sizeof(int32_t)/1]; }; |
union int64_u { int64_t int64; int32_t int32[sizeof(int64_t)/4]; int16_t int16[sizeof(int64_t)/2]; int8_t int8[sizeof(int32_t)/1]; }; |
|
|
// ---------------------------------------------------------------------------- |
// CPU Status Register (r2) Flags |
// ---------------------------------------------------------------------------- |
#define C_FLAG 0 // r/w: carry |
/sw/lib/neo430/include/neo430_cpu.h
36,6 → 36,8
#define neo430_cpu_h |
|
// prototypes |
void neo430_critical_start(void); // start critical section |
void neo430_critical_end(void); // end critical section |
void neo430_eint(void); // enable global interrupts |
void neo430_dint(void); // disable global interrupts |
uint16_t neo430_get_sp(void); // get stack pointer |
/sw/lib/neo430/include/neo430_exirq.h
41,9 → 41,6
uint8_t enable; |
}; |
|
// private variables |
static uint16_t neo430_exirq_vectors[8] __attribute__((unused)); // do not ouput a warning when this variable is unused |
|
// prototypes |
void neo430_exirq_enable(void); // activate EXIRQ controller |
void neo430_exirq_disable(void); // deactivate EXIRQ controller |
/sw/lib/neo430/include/neo430_muldiv.h
37,15 → 37,19
|
// prototypes |
uint32_t neo430_umul32(uint16_t a, uint16_t b); |
int32_t neo430_mul32(int16_t a, int16_t b); |
uint32_t neo430_umul32_32(uint32_t a, uint32_t b); |
uint64_t neo430_umul64(uint32_t a, uint32_t b); |
|
int32_t neo430_mul32(int16_t a, int16_t b); |
int64_t neo430_mul64(int32_t a, int32_t b); |
|
uint16_t neo430_udiv16(uint16_t dividend, uint16_t divisor); |
int16_t neo430_div16(int16_t dividend, int16_t divisor); |
int16_t neo430_div16(int16_t dividend, int16_t divisor); |
|
uint16_t neo430_umod16(uint16_t dividend, uint16_t divisor); |
int16_t neo430_mod16(int16_t dividend, int16_t divisor); |
int16_t neo430_mod16(int16_t dividend, int16_t divisor); |
|
uint16_t neo430_umoddiv16(uint16_t *remainder, uint16_t dividend, uint16_t divisor); |
int16_t neo430_moddiv16(int16_t *remainder, int16_t dividend, int16_t divisor); |
int16_t neo430_moddiv16(int16_t *remainder, int16_t dividend, int16_t divisor); |
|
#endif // neo430_muldiv_h |
/sw/lib/neo430/source/neo430_cpu.c
35,8 → 35,35
#include "neo430.h" |
#include "neo430_cpu.h" |
|
// Private variables |
static uint16_t __neo430_sreg __attribute__((unused)); // do not ouput a warning when this variable is unused |
|
|
/* ------------------------------------------------------------ |
* INFO Beginning of critical section (store SREG and disable interrupts) |
* ------------------------------------------------------------ */ |
void neo430_critical_start(void) { |
|
register uint16_t d; |
asm volatile ("mov r2, %0" : "=r" (d)); |
__neo430_sreg = d; // store current SREG |
|
asm volatile ("dint"); |
asm volatile ("nop"); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO End of critical section (restore original SREG) |
* ------------------------------------------------------------ */ |
void neo430_critical_end(void) { |
|
register uint16_t r = __neo430_sreg; |
asm volatile ("mov %0, r2" : : "r" (r)); |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Enable global interrupt flag |
* ------------------------------------------------------------ */ |
void neo430_eint(void){ |
/sw/lib/neo430/source/neo430_exirq.c
35,6 → 35,9
#include "neo430.h" |
#include "neo430_exirq.h" |
|
// Private variables |
static uint16_t neo430_exirq_vectors[8] __attribute__((unused)); // do not ouput a warning when this variable is unused |
|
// Private function prototypes |
static void __attribute__((__interrupt__)) _exirq_irq_handler_(void); |
|
/sw/lib/neo430/source/neo430_muldiv.c
35,7 → 35,10
#include "neo430.h" |
#include "neo430_muldiv.h" |
|
// Macros |
#define muldiv_processing_delay {asm volatile("nop"); asm volatile("nop"); asm volatile("nop");} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16x16-bit multiplication |
* PARAM 16-bit factor a |
47,10 → 50,7
MULDIV_OPA_RESX = a; |
MULDIV_OPB_UMUL_RESY = b; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
return MULDIV_R32bit; |
} |
57,6 → 57,112
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 32x32-bit multiplication (large!) |
* PARAM 32-bit factor a |
* PARAM 32-bit factor b |
* RETURN 32-bit product |
* ------------------------------------------------------------ */ |
uint32_t neo430_umul32_32(uint32_t a, uint32_t b) { |
|
union uint32_u tmp32; |
|
// get input words (16-bit) |
tmp32.uint32 = a; |
register uint16_t a_lo = tmp32.uint16[0]; |
register uint16_t a_hi = tmp32.uint16[1]; |
|
tmp32.uint32 = b; |
register uint16_t b_lo = tmp32.uint16[0]; |
register uint16_t b_hi = tmp32.uint16[1]; |
|
// compute partial results and arrange in 64-bit word |
MULDIV_OPA_RESX = a_lo; |
MULDIV_OPB_UMUL_RESY = b_lo; |
muldiv_processing_delay // HW processing delay |
tmp32.uint16[0] = MULDIV_OPA_RESX; |
tmp32.uint16[1] = MULDIV_OPB_UMUL_RESY; |
uint32_t res32 = tmp32.uint32; |
|
//MULDIV_OPA_RESX = a_lo; |
MULDIV_OPB_UMUL_RESY = b_hi; |
muldiv_processing_delay // HW processing delay |
tmp32.uint16[0] = 0; |
tmp32.uint16[1] = MULDIV_OPA_RESX; |
res32 += tmp32.uint32; |
|
MULDIV_OPA_RESX = a_hi; |
MULDIV_OPB_UMUL_RESY = b_lo; |
muldiv_processing_delay // HW processing delay |
tmp32.uint16[0] = 0; |
tmp32.uint16[1] = MULDIV_OPA_RESX; |
res32 += tmp32.uint32; |
|
return res32; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 32x32-bit multiplication (large!) |
* PARAM 32-bit factor a |
* PARAM 32-bit factor b |
* RETURN 64-bit product |
* ------------------------------------------------------------ */ |
uint64_t neo430_umul64(uint32_t a, uint32_t b) { |
|
union uint32_u tmp32; |
union uint64_u tmp64; |
|
// get input words (16-bit) |
tmp32.uint32 = a; |
register uint16_t a_lo = tmp32.uint16[0]; |
register uint16_t a_hi = tmp32.uint16[1]; |
|
tmp32.uint32 = b; |
register uint16_t b_lo = tmp32.uint16[0]; |
register uint16_t b_hi = tmp32.uint16[1]; |
|
// compute partial results and arrange in 64-bit word |
MULDIV_OPA_RESX = a_lo; |
MULDIV_OPB_UMUL_RESY = b_lo; |
muldiv_processing_delay // HW processing delay |
tmp64.uint16[0] = MULDIV_OPA_RESX; |
tmp64.uint16[1] = MULDIV_OPB_UMUL_RESY; |
tmp64.uint16[2] = 0; |
tmp64.uint16[3] = 0; |
uint64_t res64 = tmp64.uint64; |
|
//MULDIV_OPA_RESX = a_lo; |
MULDIV_OPB_UMUL_RESY = b_hi; |
muldiv_processing_delay // HW processing delay |
tmp64.uint16[0] = 0; |
tmp64.uint16[1] = MULDIV_OPA_RESX; |
tmp64.uint16[2] = MULDIV_OPB_UMUL_RESY; |
tmp64.uint16[3] = 0; |
res64 += tmp64.uint64; |
|
MULDIV_OPA_RESX = a_hi; |
MULDIV_OPB_UMUL_RESY = b_lo; |
muldiv_processing_delay // HW processing delay |
tmp64.uint16[0] = 0; |
tmp64.uint16[1] = MULDIV_OPA_RESX; |
tmp64.uint16[2] = MULDIV_OPB_UMUL_RESY; |
tmp64.uint16[3] = 0; |
res64 += tmp64.uint64; |
|
//MULDIV_OPA_RESX = a_hi; |
MULDIV_OPB_UMUL_RESY = b_hi; |
muldiv_processing_delay // HW processing delay |
tmp64.uint16[0] = 0; |
tmp64.uint16[1] = 0; |
tmp64.uint16[2] = MULDIV_OPA_RESX; |
tmp64.uint16[3] = MULDIV_OPB_UMUL_RESY; |
res64 += tmp64.uint64; |
|
return res64; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Signed 16x16-bit multiplication |
* PARAM 16-bit factor a |
* PARAM 16-bit factor b |
67,10 → 173,7
MULDIV_OPA_RESX = (uint16_t)a; |
MULDIV_OPB_SMUL = (uint16_t)b; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
int32_t r = (int32_t)MULDIV_R32bit; |
|
79,6 → 182,73
|
|
/* ------------------------------------------------------------ |
* INFO Signed 32x32-bit multiplication (large!) |
* PARAM 32-bit factor a |
* PARAM 32-bit factor b |
* RETURN 64-bit product |
* ------------------------------------------------------------ */ |
int64_t neo430_mul64(int32_t a, int32_t b) { |
|
union int32_u tmp32; |
union int64_u tmp64; |
|
// get input words (16-bit) |
tmp32.int32 = a; |
register int16_t a_lo = tmp32.int16[0]; |
register int16_t a_hi = tmp32.int16[1]; |
|
tmp32.int32 = b; |
register int16_t b_lo = tmp32.int16[0]; |
register int16_t b_hi = tmp32.int16[1]; |
|
// compute partial results and arrange in 64-bit word |
MULDIV_OPA_RESX = (uint16_t)a_lo; |
MULDIV_OPB_SMUL = (uint16_t)b_lo; |
muldiv_processing_delay // HW processing delay |
tmp64.int16[0] = MULDIV_OPA_RESX; |
tmp64.int16[1] = MULDIV_OPB_UMUL_RESY; |
tmp64.int16[2] = 0; |
tmp64.int16[3] = 0; |
int64_t res64 = tmp64.int64; |
|
//MULDIV_OPA_RESX = (uint16_t)a_lo; |
MULDIV_OPB_SMUL = (uint16_t)b_hi; |
muldiv_processing_delay // HW processing delay |
tmp64.int16[0] = 0; |
tmp64.int16[1] = MULDIV_OPA_RESX; |
tmp64.int16[2] = MULDIV_OPB_UMUL_RESY; |
if (tmp64.int16[2] < 0) // sign extension |
tmp64.int16[3] = 0xffff; |
else |
tmp64.int16[3] = 0; |
res64 += tmp64.int64; |
|
MULDIV_OPA_RESX = (uint16_t)a_hi; |
MULDIV_OPB_SMUL = (uint16_t)b_lo; |
muldiv_processing_delay // HW processing delay |
tmp64.int16[0] = 0; |
tmp64.int16[1] = MULDIV_OPA_RESX; |
tmp64.int16[2] = MULDIV_OPB_UMUL_RESY; |
if (tmp64.int16[2] < 0) // sign extension |
tmp64.int16[3] = 0xffff; |
else |
tmp64.int16[3] = 0; |
res64 += tmp64.int64; |
|
//MULDIV_OPA_RESX = (uint16_t)a_hi; |
MULDIV_OPB_SMUL = (uint16_t)b_lo; |
muldiv_processing_delay // HW processing delay |
tmp64.int16[0] = 0; |
tmp64.int16[1] = 0; |
tmp64.int16[2] = MULDIV_OPA_RESX; |
tmp64.int16[3] = MULDIV_OPB_UMUL_RESY; |
res64 += tmp64.int64; |
|
return res64; |
} |
|
|
/* ------------------------------------------------------------ |
* INFO Unsigned 16 by 16-bit division |
* PARAM 16-bit dividend |
* PARAM 16-bit divisor |
89,10 → 259,7
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
return MULDIV_OPA_RESX; |
} |
115,10 → 282,7
MULDIV_OPA_RESX = (uint16_t)dividend; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
int16_t r = (int16_t)MULDIV_OPA_RESX; |
|
140,10 → 304,7
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
return MULDIV_OPB_UMUL_RESY; |
} |
168,10 → 329,7
MULDIV_OPA_RESX = (uint16_t)dividend_int; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
int16_t r = (int16_t)MULDIV_OPB_UMUL_RESY; |
|
194,10 → 352,7
MULDIV_OPA_RESX = dividend; |
MULDIV_OPB_UDIV = divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
*remainder = MULDIV_OPB_UMUL_RESY; |
return MULDIV_OPA_RESX; |
225,10 → 380,7
MULDIV_OPA_RESX = (uint16_t)dividend_int; |
MULDIV_OPB_UDIV = (uint16_t)divisor; |
|
// HW processing delay |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
muldiv_processing_delay // HW processing delay |
|
int16_t q = (int16_t)MULDIV_OPA_RESX; |
int16_t r = (int16_t)MULDIV_OPB_UMUL_RESY; |
243,3 → 395,37
else |
return q; |
} |
|
|
// ***************************************************************************** |
// * DANGER ZONE!!! * |
// * Override primitives for multiplication to use the MULDIV hardware unit * |
// ***************************************************************************** |
#if NEO430_HWMUL_ABI_OVERRIDE |
|
int16_t __mulhi2(int16_t x, int16_t y) { |
return (int16_t)neo430_umul32((uint16_t)x,(uint16_t)y); |
} |
|
int32_t __mulhisi2(int16_t x, int16_t y) { |
return neo430_mul32(x,y); |
} |
|
uint32_t __umulhisi2(uint16_t x, uint16_t y) { |
return neo430_umul32(x,y); |
} |
|
int32_t __mulsi2(int32_t x, int32_t y) { |
return (int32_t)neo430_umul32_32((uint32_t)x,(uint32_t)y); |
} |
|
int32_t __mulsidi2(int32_t x, int32_t y) { |
return neo430_mul64(x,y); |
} |
|
uint64_t __umulsidi2(uint32_t x, uint32_t y) { |
return neo430_umul64(x,y); |
} |
|
#endif |
// ***************************************************************************** |
/sw/lib/neo430/source/neo430_uart.c
266,8 → 266,11
* ------------------------------------------------------------ */ |
void neo430_uart_print_hex_word(uint16_t w) { |
|
neo430_uart_print_hex_byte((uint8_t)(w >> 8)); |
neo430_uart_print_hex_byte((uint8_t)(w >> 0)); |
union uint16_u tmp; |
tmp.uint16 = w; |
|
neo430_uart_print_hex_byte(tmp.uint8[1]); |
neo430_uart_print_hex_byte(tmp.uint8[0]); |
} |
|
|
277,8 → 280,13
* ------------------------------------------------------------ */ |
void neo430_uart_print_hex_dword(uint32_t dw) { |
|
neo430_uart_print_hex_word((uint16_t)(dw >> 16)); |
neo430_uart_print_hex_word((uint16_t)(dw >> 0)); |
union uint32_u tmp; |
tmp.uint32 = dw; |
|
neo430_uart_print_hex_byte(tmp.uint8[3]); |
neo430_uart_print_hex_byte(tmp.uint8[2]); |
neo430_uart_print_hex_byte(tmp.uint8[1]); |
neo430_uart_print_hex_byte(tmp.uint8[0]); |
} |
|
|
288,8 → 296,17
* ------------------------------------------------------------ */ |
void neo430_uart_print_hex_qword(uint64_t qw) { |
|
neo430_uart_print_hex_dword((uint32_t)(qw >> 32)); |
neo430_uart_print_hex_dword((uint32_t)(qw >> 0)); |
union uint64_u tmp; |
tmp.uint64 = qw; |
|
neo430_uart_print_hex_byte(tmp.uint8[7]); |
neo430_uart_print_hex_byte(tmp.uint8[6]); |
neo430_uart_print_hex_byte(tmp.uint8[5]); |
neo430_uart_print_hex_byte(tmp.uint8[4]); |
neo430_uart_print_hex_byte(tmp.uint8[3]); |
neo430_uart_print_hex_byte(tmp.uint8[2]); |
neo430_uart_print_hex_byte(tmp.uint8[1]); |
neo430_uart_print_hex_byte(tmp.uint8[0]); |
} |
|
|
315,8 → 332,11
* ------------------------------------------------------------ */ |
void neo430_uart_print_bin_word(uint16_t w) { |
|
neo430_uart_print_bin_byte((uint8_t)(w >> 8)); |
neo430_uart_print_bin_byte((uint8_t)(w >> 0)); |
union uint16_u tmp; |
tmp.uint16 = w; |
|
neo430_uart_print_bin_byte(tmp.uint8[1]); |
neo430_uart_print_bin_byte(tmp.uint8[0]); |
} |
|
|
326,8 → 346,13
* ------------------------------------------------------------ */ |
void neo430_uart_print_bin_dword(uint32_t dw) { |
|
neo430_uart_print_bin_word((uint16_t)(dw >> 16)); |
neo430_uart_print_bin_word((uint16_t)(dw >> 0)); |
union uint32_u tmp; |
tmp.uint32 = dw; |
|
neo430_uart_print_bin_byte(tmp.uint8[3]); |
neo430_uart_print_bin_byte(tmp.uint8[2]); |
neo430_uart_print_bin_byte(tmp.uint8[1]); |
neo430_uart_print_bin_byte(tmp.uint8[0]); |
} |
|
|
/travis_ci/sw_check.sh
12,5 → 12,5
ls -al $srcdir_bootloader |
|
# Try to compile all example projects |
make -C $srcdir_examples compile |
make -C $srcdir_bootloader all |
make -C $srcdir_examples clean_all compile |
make -C $srcdir_bootloader clean_all all |