return len;
}
-static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
+static bool feat_matrix_chained(struct ethosu_device *edev, struct feat_matrix *fm)
+{
+ u32 storage = fm->precision >> 14;
+
+ return !ethosu_is_u65(edev) && storage == 2;
+}
+
+static u64 feat_matrix_length(struct ethosu_device *edev,
+ struct ethosu_validated_cmdstream_info *info,
struct feat_matrix *fm,
u32 x, u32 y, u32 c, bool ofm)
{
if (fm->region < 0)
return U64_MAX;
+ if (feat_matrix_chained(edev, fm))
+ return 0;
+
switch (storage) {
case 0:
if (x >= fm->width0 + 1) {
tile = 1;
}
break;
+ default:
+ return U64_MAX;
}
if (fm->base[tile] == U64_MAX)
return U64_MAX;
u16 op, struct cmd_state *st,
bool ifm, bool ifm2, bool weight, bool scale)
{
+ struct ethosu_device *edev = to_ethosu_device(ddev);
u64 len;
if (ifm) {
if (ifm_height < 0 || ifm_width < 0)
return -EINVAL;
- len = feat_matrix_length(info, &st->ifm, ifm_width,
+ len = feat_matrix_length(edev, info, &st->ifm, ifm_width,
ifm_height, st->ifm.depth, false);
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
op, st->ifm.region, st->ifm.base[0], len);
}
if (ifm2) {
- len = feat_matrix_length(info, &st->ifm2, st->ifm.depth,
+ len = feat_matrix_length(edev, info, &st->ifm2, st->ifm.depth,
0, st->ofm.depth, false);
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
op, st->ifm2.region, st->ifm2.base[0], len);
st->scale[0].base + st->scale[0].length);
}
- len = feat_matrix_length(info, &st->ofm, st->ofm.width,
+ len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
st->ofm.height[2], st->ofm.depth, true);
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
op, st->ofm.region, st->ofm.base[0], len);
if (len == U64_MAX)
return -EINVAL;
- info->output_region[st->ofm.region] = true;
+ if (!feat_matrix_chained(edev, &st->ofm))
+ info->output_region[st->ofm.region] = true;
return 0;
}
u16 op, struct cmd_state *st,
bool ifm, bool ifm2)
{
+ struct ethosu_device *edev = to_ethosu_device(ddev);
u32 height, width, depth;
u64 len;
width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width;
depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth;
- len = feat_matrix_length(info, &st->ifm, width,
+ len = feat_matrix_length(edev, info, &st->ifm, width,
height, depth, false);
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
op, st->ifm.region, st->ifm.base[0], len);
width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width;
depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth;
- len = feat_matrix_length(info, &st->ifm2, width,
+ len = feat_matrix_length(edev, info, &st->ifm2, width,
height, depth, false);
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
op, st->ifm2.region, st->ifm2.base[0], len);
return -EINVAL;
}
- len = feat_matrix_length(info, &st->ofm, st->ofm.width,
+ len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
st->ofm.height[2], st->ofm.depth, true);
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
op, st->ofm.region, st->ofm.base[0], len);
if (len == U64_MAX)
return -EINVAL;
- info->output_region[st->ofm.region] = true;
+ if (!feat_matrix_chained(edev, &st->ofm))
+ info->output_region[st->ofm.region] = true;
return 0;
}