Multiplier unit in AVR's.

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was wondering if ATtiny has hardware multiplier. Referring the datasheet it is not mentioned but a particular line reads "Some implementations of the architecture also provide a powerful multiplier supporting both signed/unsigned multiplication and fractional format."  I would like to know if there is after all any hardware multiplier. If not which micro-controller with least pins ( and cost ) comes with a basic hardware multiplier? Thanks! 

This topic has a solution.

V!6h0¥€

Last Edited: Mon. Nov 20, 2017 - 01:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Near the end of each datasheet, there is a list of supported operations (instruction set summary). If mul is there, then it is supported.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just putting "ATtiny hardware multiplier" into google gives, among others, this:

 

http://www.avrfreaks.net/forum/attiny-features

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I never think the layout of this is great but take a look at this list:

 

http://www.nongnu.org/avr-libc/u...

 

In particular look for "AVR_HAS_MUL". As far as I can see every "fmaily architecture" beneath avr4 does not have that defined. So then look at the list below which maps devices to architecture.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Onde upon a time the simple rule was: ATtiny has no mutliplier, ATmega has multiplier. The definitive thing to check is to look in the supported instructions in the respective datasheets. If you find a MUL instruction in there, then it has the multiplier.

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW you can always test it:

#include <avr/io.h>

volatile int a,b,c;

int main(void)
{
	c = a * b;
}
C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -Os avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump.exe -S avr.elf

avr.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 2a 00     jmp     0x54    ; 0x54 <__ctors_end>
   4:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
   8:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
   c:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  10:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  14:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  18:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  1c:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  20:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  24:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  28:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  2c:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  30:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  34:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  38:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  3c:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  40:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  44:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  48:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  4c:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>
  50:   0c 94 3c 00     jmp     0x78    ; 0x78 <__bad_interrupt>

00000054 <__ctors_end>:
  54:   11 24           eor     r1, r1
  56:   1f be           out     0x3f, r1        ; 63
  58:   cf e5           ldi     r28, 0x5F       ; 95
  5a:   d4 e0           ldi     r29, 0x04       ; 4
  5c:   de bf           out     0x3e, r29       ; 62
  5e:   cd bf           out     0x3d, r28       ; 61

00000060 <__do_clear_bss>:
  60:   20 e0           ldi     r18, 0x00       ; 0
  62:   a0 e6           ldi     r26, 0x60       ; 96
  64:   b0 e0           ldi     r27, 0x00       ; 0
  66:   01 c0           rjmp    .+2             ; 0x6a <.do_clear_bss_start>

00000068 <.do_clear_bss_loop>:
  68:   1d 92           st      X+, r1

0000006a <.do_clear_bss_start>:
  6a:   a6 36           cpi     r26, 0x66       ; 102
  6c:   b2 07           cpc     r27, r18
  6e:   e1 f7           brne    .-8             ; 0x68 <.do_clear_bss_loop>
  70:   0e 94 3e 00     call    0x7c    ; 0x7c <main>
  74:   0c 94 54 00     jmp     0xa8    ; 0xa8 <_exit>

00000078 <__bad_interrupt>:
  78:   0c 94 00 00     jmp     0       ; 0x0 <__vectors>

0000007c <main>:
  7c:   40 91 64 00     lds     r20, 0x0064
  80:   50 91 65 00     lds     r21, 0x0065
  84:   20 91 60 00     lds     r18, 0x0060
  88:   30 91 61 00     lds     r19, 0x0061
  8c:   42 9f           mul     r20, r18
  8e:   c0 01           movw    r24, r0
  90:   43 9f           mul     r20, r19
  92:   90 0d           add     r25, r0
  94:   52 9f           mul     r21, r18
  96:   90 0d           add     r25, r0
  98:   11 24           eor     r1, r1
  9a:   90 93 63 00     sts     0x0063, r25
  9e:   80 93 62 00     sts     0x0062, r24
  a2:   80 e0           ldi     r24, 0x00       ; 0
  a4:   90 e0           ldi     r25, 0x00       ; 0
  a6:   08 95           ret

000000a8 <_exit>:
  a8:   f8 94           cli

000000aa <__stop_program>:
  aa:   ff cf           rjmp    .-2             ; 0xaa <__stop_program>

So clearly a mega16 does have MUL. Build the same for tiny2313:

C:\SysGCC\avr\bin>avr-gcc -mmcu=attiny2313 -Os avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump.exe -S avr.elf

avr.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:   12 c0           rjmp    .+36            ; 0x26 <__ctors_end>
   2:   1f c0           rjmp    .+62            ; 0x42 <__bad_interrupt>
   4:   1e c0           rjmp    .+60            ; 0x42 <__bad_interrupt>
   6:   1d c0           rjmp    .+58            ; 0x42 <__bad_interrupt>
   8:   1c c0           rjmp    .+56            ; 0x42 <__bad_interrupt>
   a:   1b c0           rjmp    .+54            ; 0x42 <__bad_interrupt>
   c:   1a c0           rjmp    .+52            ; 0x42 <__bad_interrupt>
   e:   19 c0           rjmp    .+50            ; 0x42 <__bad_interrupt>
  10:   18 c0           rjmp    .+48            ; 0x42 <__bad_interrupt>
  12:   17 c0           rjmp    .+46            ; 0x42 <__bad_interrupt>
  14:   16 c0           rjmp    .+44            ; 0x42 <__bad_interrupt>
  16:   15 c0           rjmp    .+42            ; 0x42 <__bad_interrupt>
  18:   14 c0           rjmp    .+40            ; 0x42 <__bad_interrupt>
  1a:   13 c0           rjmp    .+38            ; 0x42 <__bad_interrupt>
  1c:   12 c0           rjmp    .+36            ; 0x42 <__bad_interrupt>
  1e:   11 c0           rjmp    .+34            ; 0x42 <__bad_interrupt>
  20:   10 c0           rjmp    .+32            ; 0x42 <__bad_interrupt>
  22:   0f c0           rjmp    .+30            ; 0x42 <__bad_interrupt>
  24:   0e c0           rjmp    .+28            ; 0x42 <__bad_interrupt>

00000026 <__ctors_end>:
  26:   11 24           eor     r1, r1
  28:   1f be           out     0x3f, r1        ; 63
  2a:   cf ed           ldi     r28, 0xDF       ; 223
  2c:   cd bf           out     0x3d, r28       ; 61

0000002e <__do_clear_bss>:
  2e:   20 e0           ldi     r18, 0x00       ; 0
  30:   a0 e6           ldi     r26, 0x60       ; 96
  32:   b0 e0           ldi     r27, 0x00       ; 0
  34:   01 c0           rjmp    .+2             ; 0x38 <.do_clear_bss_start>

00000036 <.do_clear_bss_loop>:
  36:   1d 92           st      X+, r1

00000038 <.do_clear_bss_start>:
  38:   a6 36           cpi     r26, 0x66       ; 102
  3a:   b2 07           cpc     r27, r18
  3c:   e1 f7           brne    .-8             ; 0x36 <.do_clear_bss_loop>
  3e:   02 d0           rcall   .+4             ; 0x44 <main>
  40:   22 c0           rjmp    .+68            ; 0x86 <_exit>

00000042 <__bad_interrupt>:
  42:   de cf           rjmp    .-68            ; 0x0 <__vectors>

00000044 <main>:
  44:   80 91 64 00     lds     r24, 0x0064
  48:   90 91 65 00     lds     r25, 0x0065
  4c:   60 91 60 00     lds     r22, 0x0060
  50:   70 91 61 00     lds     r23, 0x0061
  54:   07 d0           rcall   .+14            ; 0x64 <__mulhi3>
  56:   90 93 63 00     sts     0x0063, r25
  5a:   80 93 62 00     sts     0x0062, r24
  5e:   80 e0           ldi     r24, 0x00       ; 0
  60:   90 e0           ldi     r25, 0x00       ; 0
  62:   08 95           ret

00000064 <__mulhi3>:
  64:   00 24           eor     r0, r0
  66:   55 27           eor     r21, r21
  68:   04 c0           rjmp    .+8             ; 0x72 <__mulhi3+0xe>
  6a:   08 0e           add     r0, r24
  6c:   59 1f           adc     r21, r25
  6e:   88 0f           add     r24, r24
  70:   99 1f           adc     r25, r25
  72:   00 97           sbiw    r24, 0x00       ; 0
  74:   29 f0           breq    .+10            ; 0x80 <__mulhi3+0x1c>
  76:   76 95           lsr     r23
  78:   67 95           ror     r22
  7a:   b8 f3           brcs    .-18            ; 0x6a <__mulhi3+0x6>
  7c:   71 05           cpc     r23, r1
  7e:   b9 f7           brne    .-18            ; 0x6e <__mulhi3+0xa>
  80:   80 2d           mov     r24, r0
  82:   95 2f           mov     r25, r21
  84:   08 95           ret

00000086 <_exit>:
  86:   f8 94           cli

00000088 <__stop_program>:
  88:   ff cf           rjmp    .-2             ; 0x88 <__stop_program>

here you see the compiler had to use a software simulation of MUL because the CPU does not AVR_HAS_MUL. If I ask the compiler/linker to produce a .map file then within it (for the 2313 build) I see:

 

LOAD c:/sysgcc/avr/bin/../lib/gcc/avr/5.3.0/../../../../avr/lib/avr25/tiny-stack/crtattiny2313.o
LOAD C:\Users\uid23021\AppData\Local\Temp\cciO9rnf.o
START GROUP
LOAD c:/sysgcc/avr/bin/../lib/gcc/avr/5.3.0/avr25/tiny-stack\libgcc.a

That confirms that tiny2313 is "avr25" architecture and as in the previous post avr25 does not have AVR_HAS_MUL

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yet another way to determine this is to look at the source of the GCC compiler:

 

https://github.com/gcc-mirror/gc...

 

That table has a flag for "MUL" in the second column. then this file maps each device to an architecture:

 

https://github.com/gcc-mirror/gc...

 

Note in particular this group:

 

https://github.com/gcc-mirror/gc...

 

they are the "avrxmega3" devices (even though they have "tiny" names). Now look back to the first file I linked to:

 { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0x8000, 0, "103", "avrxmega3" },

avrxmega3 has a 1 in the "MUL" column !! So that means all these "tiny" devices have MUL:

 

AVR_MCU ("attiny212",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny212__",   0x3f80, 0x0, 0x800)
AVR_MCU ("attiny214",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny214__",   0x3f80, 0x0, 0x800)
AVR_MCU ("attiny412",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny412__",   0x3f00, 0x0, 0x1000)
AVR_MCU ("attiny414",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny414__",   0x3f00, 0x0, 0x1000)
AVR_MCU ("attiny416",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny416__",   0x3f00, 0x0, 0x1000)
AVR_MCU ("attiny417",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny417__",   0x3f00, 0x0, 0x1000)
AVR_MCU ("attiny814",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny814__",   0x3e00, 0x0, 0x2000)
AVR_MCU ("attiny816",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny816__",   0x3e00, 0x0, 0x2000)
AVR_MCU ("attiny817",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny817__",   0x3e00, 0x0, 0x2000)
AVR_MCU ("attiny1614",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1614__",  0x3800, 0x0, 0x4000)
AVR_MCU ("attiny1616",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1616__",  0x3800, 0x0, 0x4000)
AVR_MCU ("attiny1617",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1617__",  0x3800, 0x0, 0x4000)
AVR_MCU ("attiny3214",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny3214__",  0x3800, 0x0, 0x8000)
AVR_MCU ("attiny3216",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny3216__",  0x3800, 0x0, 0x8000)
AVR_MCU ("attiny3217", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny3217__", 0x3800, 0x0, 0x8000)

Those will be the "tiny's you have never heard of" because they are all recent releases and as I say they have more in common with Xmega than Tiny in fact. Some folks have coined the phrase "Xtiny" for them. (to complement "Xmega")

 

PS a quick google reveals that something like an attiny212 is an 8 pin device.

Last Edited: Mon. Nov 20, 2017 - 01:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
PS a quick google reveals that something like an attiny212 is an 8 pin device.
... but tiny212 is not yet available.

In lieu of, could compare tiny45 with tiny417; both are 4mm-sq (MLF, QFN)

tiny417 is slightly less in price than tiny45.

 

http://www.microchip.com/wwwproducts/en/attiny212

http://www.microchip.com/wwwproducts/en/attiny45

http://www.microchip.com/wwwproducts/en/ATTINY417

 

"Dare to be naïve." - Buckminster Fuller