Skip to content

Commit 873f005

Browse files
authored
Merge pull request #5903 from hmeiland/u74-gemm-4x4-kernel
Add SiFive U74 target with a scalar 4×4 register-tiled GEMM kernel
2 parents 65382d2 + 5d7868f commit 873f005

13 files changed

Lines changed: 1316 additions & 2 deletions

Makefile.prebuild

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ ifeq ($(TARGET), RISCV64_GENERIC)
7575
TARGET_FLAGS = -march=rv64imafdc -mabi=lp64d
7676
endif
7777

78+
ifeq ($(TARGET), U74)
79+
TARGET_FLAGS = -march=rv64imafdc_zba_zbb -mabi=lp64d
80+
endif
81+
7882
all: getarch_2nd
7983
./getarch_2nd 0 >> $(TARGET_MAKE)
8084
./getarch_2nd 1 >> $(TARGET_CONF)

Makefile.riscv64

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ ifeq ($(CORE), RISCV64_GENERIC)
2525
CCOMMON_OPT += -march=rv64imafdc -mabi=lp64d
2626
FCOMMON_OPT += -march=rv64imafdc -mabi=lp64d
2727
endif
28+
ifeq ($(CORE), U74)
29+
CCOMMON_OPT += -march=rv64imafdc_zba_zbb -mabi=lp64d -mtune=sifive-u74
30+
FCOMMON_OPT += -march=rv64imafdc_zba_zbb -mabi=lp64d -mtune=sifive-u74
31+
endif

TargetList.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ RISCV64_ZVL128B
128128
C910V
129129
x280
130130
RISCV64_ZVL256B
131+
U74 (e.g. SiFive U74 / StarFive JH7110 / VisionFive 2)
131132

132133
11.LOONGARCH64:
133134
// LOONGSONGENERIC/LOONGSON2K1000/LOONGSON3R5 are legacy names,

cmake/cc.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,9 @@ endif()
428428
if (${CORE} STREQUAL RISCV64_GENERIC)
429429
set (CCOMMON_OPT "${CCOMMON_OPT} -march=rv64imafdc -mabi=lp64d")
430430
endif()
431+
if (${CORE} STREQUAL U74)
432+
set (CCOMMON_OPT "${CCOMMON_OPT} -march=rv64imafdc_zba_zbb -mabi=lp64d -mtune=sifive-u74")
433+
endif()
431434
if (${CORE} STREQUAL x280)
432435
set (CCOMMON_OPT "${CCOMMON_OPT} -march=rv64imafdcv_zba_zbb_zfh_zvl512b -mabi=lp64d")
433436
endif()

cmake/prebuild.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,15 @@ endif ()
15041504
"#define DTB_DEFAULT_ENTRIES 128\n"
15051505
"#define DTB_SIZE 4096\n"
15061506
"#define L2_ASSOCIATIVE 4\n")
1507+
elseif ("${TCORE}" STREQUAL "U74")
1508+
file(APPEND ${TARGET_CONF_TEMP}
1509+
"#define L1_DATA_SIZE 32768\n"
1510+
"#define L1_DATA_LINESIZE 64\n"
1511+
"#define L2_SIZE 2097152\n"
1512+
"#define L2_LINESIZE 64 \n"
1513+
"#define DTB_DEFAULT_ENTRIES 128\n"
1514+
"#define DTB_SIZE 4096\n"
1515+
"#define L2_ASSOCIATIVE 16\n")
15071516
elseif ("${TCORE}" STREQUAL "WASM128_GENERIC")
15081517
file(APPEND ${TARGET_CONF_TEMP}
15091518
"#define L1_DATA_SIZE 32768\n"

cmake/system.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ if (${TARGET} STREQUAL NEOVERSEV1)
409409
if (${TARGET} STREQUAL RISCV64_GENERIC)
410410
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -march=rv64imafdc -mabi=lp64d")
411411
endif()
412+
if (${TARGET} STREQUAL U74)
413+
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -march=rv64imafdc_zba_zbb -mabi=lp64d -mtune=sifive-u74")
414+
endif()
412415
if (${TARGET} STREQUAL x280)
413416
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -march=rv64imafdcv_zba_zbb_zfh_zvl512b -mabi=lp64d")
414417
endif()

cpuid_riscv64.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,24 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7575
#define CPU_x280 2
7676
#define CPU_RISCV64_ZVL256B 3
7777
#define CPU_RISCV64_ZVL128B 4
78+
#define CPU_U74 5
7879

7980
static char *cpuname[] = {
8081
"RISCV64_GENERIC",
8182
"C910V",
8283
"x280",
8384
"CPU_RISCV64_ZVL256B",
84-
"CPU_RISCV64_ZVL128B"
85+
"CPU_RISCV64_ZVL128B",
86+
"U74"
8587
};
8688

8789
static char *cpuname_lower[] = {
8890
"riscv64_generic",
8991
"c910v",
9092
"x280",
9193
"riscv64_zvl256b",
92-
"riscv64_zvl128b"
94+
"riscv64_zvl128b",
95+
"u74"
9396
};
9497

9598
int detect(void){

getarch.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,20 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12321232
#else
12331233
#endif
12341234

1235+
#ifdef FORCE_U74
1236+
#define FORCE
1237+
#define ARCHITECTURE "RISCV64"
1238+
#define SUBARCHITECTURE "U74"
1239+
#define SUBDIRNAME "riscv64"
1240+
#define ARCHCONFIG "-DU74 " \
1241+
"-DL1_DATA_SIZE=32768 -DL1_DATA_LINESIZE=64 " \
1242+
"-DL2_SIZE=2097152 -DL2_LINESIZE=64 " \
1243+
"-DDTB_DEFAULT_ENTRIES=128 -DDTB_SIZE=4096 -DL2_ASSOCIATIVE=16 "
1244+
#define LIBNAME "u74"
1245+
#define CORENAME "U74"
1246+
#else
1247+
#endif
1248+
12351249
#ifdef FORCE_WASM128_GENERIC
12361250
#define FORCE
12371251
#define ARCHITECTURE "WASM"

kernel/generic/gemmkernel_4x4.c

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
/***************************************************************************
2+
* Copyright (c) 2026, The OpenBLAS Project
3+
* All rights reserved.
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in
11+
* the documentation and/or other materials provided with the
12+
* distribution.
13+
* 3. Neither the name of the OpenBLAS project nor the names of
14+
* its contributors may be used to endorse or promote products
15+
* derived from this software without specific prior written permission.
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* *****************************************************************************/
28+
29+
/*
30+
* Portable C GEMM micro-kernel with a 4x4 register tile (16 accumulators).
31+
*
32+
* This is a wider companion to gemmkernel_2x2.c intended for in-order scalar
33+
* cores whose FP FMA has a multi-cycle latency but 1/cycle throughput (e.g.
34+
* SiFive U74: fmadd.d latency 7, repeat rate 1). A 2x2 tile exposes only 4
35+
* independent accumulator chains, which is fewer than the FMA latency and
36+
* leaves the FP pipe stalled on the accumulator dependency. A 4x4 tile keeps
37+
* 16 independent chains -- comfortably above the latency -- and lowers the
38+
* load:FMA ratio from 1:1 to 1:2, so the single load/store pipe stops being
39+
* the bottleneck. RV64G has 32 FP registers, so 16 accumulators + 4 A + 4 B
40+
* fit without spilling.
41+
*
42+
* Packed-data contract (identical to the 2x2 kernel, verified against the
43+
* generic tcopy_4 / ncopy_4 copy routines): the A operand is packed by
44+
* tcopy_<UNROLL_M> into MR-row micro-panels [A(r0,k)..A(r3,k)] per k, and the
45+
* B operand by ncopy_<UNROLL_N> into NR-col micro-panels [B(k,c0)..B(k,c3)]
46+
* per k. Both dimensions are decomposed as 4 / 2 / 1 sub-blocks at the edges.
47+
*/
48+
49+
#include "common.h"
50+
51+
#include "conversion_macros.h"
52+
53+
#ifdef BGEMM
54+
#define C_TO_F32 TO_F32
55+
#else
56+
#define C_TO_F32
57+
#endif
58+
59+
int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,FLOAT* C,BLASLONG ldc
60+
#ifdef TRMMKERNEL
61+
,BLASLONG offset
62+
#endif
63+
)
64+
{
65+
BLASLONG i,j,k;
66+
FLOAT *C0,*C1,*C2,*C3;
67+
IFLOAT *ptrba,*ptrbb;
68+
FLOAT r0c0,r1c0,r2c0,r3c0;
69+
FLOAT r0c1,r1c1,r2c1,r3c1;
70+
FLOAT r0c2,r1c2,r2c2,r3c2;
71+
FLOAT r0c3,r1c3,r2c3,r3c3;
72+
IFLOAT a0,a1,a2,a3,b0,b1,b2,b3;
73+
74+
/* ==================== N panels of 4 ==================== */
75+
for (j=0; j<bn/4; j+=1)
76+
{
77+
C0 = C;
78+
C1 = C0+ldc;
79+
C2 = C1+ldc;
80+
C3 = C2+ldc;
81+
ptrba = ba;
82+
83+
/* ---- 4x4 : 4 rows x 4 cols, 16 accumulators ---- */
84+
for (i=0; i<bm/4; i+=1)
85+
{
86+
ptrbb = bb;
87+
r0c0=r1c0=r2c0=r3c0=0;
88+
r0c1=r1c1=r2c1=r3c1=0;
89+
r0c2=r1c2=r2c2=r3c2=0;
90+
r0c3=r1c3=r2c3=r3c3=0;
91+
for (k=0; k<bk; k+=1)
92+
{
93+
b0=ptrbb[0]; b1=ptrbb[1]; b2=ptrbb[2]; b3=ptrbb[3];
94+
a0=ptrba[0]; a1=ptrba[1]; a2=ptrba[2]; a3=ptrba[3];
95+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0); r2c0+=TO_F32(a2)*TO_F32(b0); r3c0+=TO_F32(a3)*TO_F32(b0);
96+
r0c1+=TO_F32(a0)*TO_F32(b1); r1c1+=TO_F32(a1)*TO_F32(b1); r2c1+=TO_F32(a2)*TO_F32(b1); r3c1+=TO_F32(a3)*TO_F32(b1);
97+
r0c2+=TO_F32(a0)*TO_F32(b2); r1c2+=TO_F32(a1)*TO_F32(b2); r2c2+=TO_F32(a2)*TO_F32(b2); r3c2+=TO_F32(a3)*TO_F32(b2);
98+
r0c3+=TO_F32(a0)*TO_F32(b3); r1c3+=TO_F32(a1)*TO_F32(b3); r2c3+=TO_F32(a2)*TO_F32(b3); r3c3+=TO_F32(a3)*TO_F32(b3);
99+
ptrba+=4; ptrbb+=4;
100+
}
101+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA); C0[2]=TO_OUTPUT(C_TO_F32(C0[2])+r2c0*ALPHA); C0[3]=TO_OUTPUT(C_TO_F32(C0[3])+r3c0*ALPHA);
102+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA); C1[1]=TO_OUTPUT(C_TO_F32(C1[1])+r1c1*ALPHA); C1[2]=TO_OUTPUT(C_TO_F32(C1[2])+r2c1*ALPHA); C1[3]=TO_OUTPUT(C_TO_F32(C1[3])+r3c1*ALPHA);
103+
C2[0]=TO_OUTPUT(C_TO_F32(C2[0])+r0c2*ALPHA); C2[1]=TO_OUTPUT(C_TO_F32(C2[1])+r1c2*ALPHA); C2[2]=TO_OUTPUT(C_TO_F32(C2[2])+r2c2*ALPHA); C2[3]=TO_OUTPUT(C_TO_F32(C2[3])+r3c2*ALPHA);
104+
C3[0]=TO_OUTPUT(C_TO_F32(C3[0])+r0c3*ALPHA); C3[1]=TO_OUTPUT(C_TO_F32(C3[1])+r1c3*ALPHA); C3[2]=TO_OUTPUT(C_TO_F32(C3[2])+r2c3*ALPHA); C3[3]=TO_OUTPUT(C_TO_F32(C3[3])+r3c3*ALPHA);
105+
C0+=4; C1+=4; C2+=4; C3+=4;
106+
}
107+
/* ---- 2x4 : 2 rows x 4 cols ---- */
108+
if (bm & 2)
109+
{
110+
ptrbb = bb;
111+
r0c0=r1c0=0; r0c1=r1c1=0; r0c2=r1c2=0; r0c3=r1c3=0;
112+
for (k=0; k<bk; k+=1)
113+
{
114+
b0=ptrbb[0]; b1=ptrbb[1]; b2=ptrbb[2]; b3=ptrbb[3];
115+
a0=ptrba[0]; a1=ptrba[1];
116+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0);
117+
r0c1+=TO_F32(a0)*TO_F32(b1); r1c1+=TO_F32(a1)*TO_F32(b1);
118+
r0c2+=TO_F32(a0)*TO_F32(b2); r1c2+=TO_F32(a1)*TO_F32(b2);
119+
r0c3+=TO_F32(a0)*TO_F32(b3); r1c3+=TO_F32(a1)*TO_F32(b3);
120+
ptrba+=2; ptrbb+=4;
121+
}
122+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA);
123+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA); C1[1]=TO_OUTPUT(C_TO_F32(C1[1])+r1c1*ALPHA);
124+
C2[0]=TO_OUTPUT(C_TO_F32(C2[0])+r0c2*ALPHA); C2[1]=TO_OUTPUT(C_TO_F32(C2[1])+r1c2*ALPHA);
125+
C3[0]=TO_OUTPUT(C_TO_F32(C3[0])+r0c3*ALPHA); C3[1]=TO_OUTPUT(C_TO_F32(C3[1])+r1c3*ALPHA);
126+
C0+=2; C1+=2; C2+=2; C3+=2;
127+
}
128+
/* ---- 1x4 : 1 row x 4 cols ---- */
129+
if (bm & 1)
130+
{
131+
ptrbb = bb;
132+
r0c0=0; r0c1=0; r0c2=0; r0c3=0;
133+
for (k=0; k<bk; k+=1)
134+
{
135+
b0=ptrbb[0]; b1=ptrbb[1]; b2=ptrbb[2]; b3=ptrbb[3];
136+
a0=ptrba[0];
137+
r0c0+=TO_F32(a0)*TO_F32(b0);
138+
r0c1+=TO_F32(a0)*TO_F32(b1);
139+
r0c2+=TO_F32(a0)*TO_F32(b2);
140+
r0c3+=TO_F32(a0)*TO_F32(b3);
141+
ptrba+=1; ptrbb+=4;
142+
}
143+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA);
144+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA);
145+
C2[0]=TO_OUTPUT(C_TO_F32(C2[0])+r0c2*ALPHA);
146+
C3[0]=TO_OUTPUT(C_TO_F32(C3[0])+r0c3*ALPHA);
147+
C0+=1; C1+=1; C2+=1; C3+=1;
148+
}
149+
bb = bb + bk*4;
150+
C = C + ldc*4;
151+
}
152+
153+
/* ==================== N panel of 2 ==================== */
154+
if (bn & 2)
155+
{
156+
C0 = C;
157+
C1 = C0+ldc;
158+
ptrba = ba;
159+
160+
for (i=0; i<bm/4; i+=1)
161+
{
162+
ptrbb = bb;
163+
r0c0=r1c0=r2c0=r3c0=0;
164+
r0c1=r1c1=r2c1=r3c1=0;
165+
for (k=0; k<bk; k+=1)
166+
{
167+
b0=ptrbb[0]; b1=ptrbb[1];
168+
a0=ptrba[0]; a1=ptrba[1]; a2=ptrba[2]; a3=ptrba[3];
169+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0); r2c0+=TO_F32(a2)*TO_F32(b0); r3c0+=TO_F32(a3)*TO_F32(b0);
170+
r0c1+=TO_F32(a0)*TO_F32(b1); r1c1+=TO_F32(a1)*TO_F32(b1); r2c1+=TO_F32(a2)*TO_F32(b1); r3c1+=TO_F32(a3)*TO_F32(b1);
171+
ptrba+=4; ptrbb+=2;
172+
}
173+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA); C0[2]=TO_OUTPUT(C_TO_F32(C0[2])+r2c0*ALPHA); C0[3]=TO_OUTPUT(C_TO_F32(C0[3])+r3c0*ALPHA);
174+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA); C1[1]=TO_OUTPUT(C_TO_F32(C1[1])+r1c1*ALPHA); C1[2]=TO_OUTPUT(C_TO_F32(C1[2])+r2c1*ALPHA); C1[3]=TO_OUTPUT(C_TO_F32(C1[3])+r3c1*ALPHA);
175+
C0+=4; C1+=4;
176+
}
177+
if (bm & 2)
178+
{
179+
ptrbb = bb;
180+
r0c0=r1c0=0; r0c1=r1c1=0;
181+
for (k=0; k<bk; k+=1)
182+
{
183+
b0=ptrbb[0]; b1=ptrbb[1];
184+
a0=ptrba[0]; a1=ptrba[1];
185+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0);
186+
r0c1+=TO_F32(a0)*TO_F32(b1); r1c1+=TO_F32(a1)*TO_F32(b1);
187+
ptrba+=2; ptrbb+=2;
188+
}
189+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA);
190+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA); C1[1]=TO_OUTPUT(C_TO_F32(C1[1])+r1c1*ALPHA);
191+
C0+=2; C1+=2;
192+
}
193+
if (bm & 1)
194+
{
195+
ptrbb = bb;
196+
r0c0=0; r0c1=0;
197+
for (k=0; k<bk; k+=1)
198+
{
199+
b0=ptrbb[0]; b1=ptrbb[1];
200+
a0=ptrba[0];
201+
r0c0+=TO_F32(a0)*TO_F32(b0);
202+
r0c1+=TO_F32(a0)*TO_F32(b1);
203+
ptrba+=1; ptrbb+=2;
204+
}
205+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA);
206+
C1[0]=TO_OUTPUT(C_TO_F32(C1[0])+r0c1*ALPHA);
207+
C0+=1; C1+=1;
208+
}
209+
bb = bb + bk*2;
210+
C = C + ldc*2;
211+
}
212+
213+
/* ==================== N panel of 1 ==================== */
214+
if (bn & 1)
215+
{
216+
C0 = C;
217+
ptrba = ba;
218+
219+
for (i=0; i<bm/4; i+=1)
220+
{
221+
ptrbb = bb;
222+
r0c0=r1c0=r2c0=r3c0=0;
223+
for (k=0; k<bk; k+=1)
224+
{
225+
b0=ptrbb[0];
226+
a0=ptrba[0]; a1=ptrba[1]; a2=ptrba[2]; a3=ptrba[3];
227+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0); r2c0+=TO_F32(a2)*TO_F32(b0); r3c0+=TO_F32(a3)*TO_F32(b0);
228+
ptrba+=4; ptrbb+=1;
229+
}
230+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA); C0[2]=TO_OUTPUT(C_TO_F32(C0[2])+r2c0*ALPHA); C0[3]=TO_OUTPUT(C_TO_F32(C0[3])+r3c0*ALPHA);
231+
C0+=4;
232+
}
233+
if (bm & 2)
234+
{
235+
ptrbb = bb;
236+
r0c0=r1c0=0;
237+
for (k=0; k<bk; k+=1)
238+
{
239+
b0=ptrbb[0];
240+
a0=ptrba[0]; a1=ptrba[1];
241+
r0c0+=TO_F32(a0)*TO_F32(b0); r1c0+=TO_F32(a1)*TO_F32(b0);
242+
ptrba+=2; ptrbb+=1;
243+
}
244+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA); C0[1]=TO_OUTPUT(C_TO_F32(C0[1])+r1c0*ALPHA);
245+
C0+=2;
246+
}
247+
if (bm & 1)
248+
{
249+
ptrbb = bb;
250+
r0c0=0;
251+
for (k=0; k<bk; k+=1)
252+
{
253+
r0c0+=TO_F32(ptrba[0])*TO_F32(ptrbb[0]);
254+
ptrba+=1; ptrbb+=1;
255+
}
256+
C0[0]=TO_OUTPUT(C_TO_F32(C0[0])+r0c0*ALPHA);
257+
C0+=1;
258+
}
259+
bb = bb + bk;
260+
C = C + ldc;
261+
}
262+
263+
return 0;
264+
}

0 commit comments

Comments
 (0)