aica: use SCIPD to detect TIMA overflow

Real hardware does not support TIMA reads--SCIPD is the correct way to
achieve this.
This commit is contained in:
Zack Buhman 2024-03-01 15:25:49 +08:00
parent 57721c485f
commit 73a685face
19 changed files with 707 additions and 257 deletions

View File

@ -8,7 +8,7 @@ g2_if = 0xa05f7800;
pvr_if = 0xa05f7c00;
holly = 0xa05f8000;
modem = 0xa0600000;
aica = 0xa0700000;
aica_sound = 0xa0700000;
aica_rtc = 0xa0710000;
system_boot_rom = 0xa0000000;

View File

@ -1,3 +1,5 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
@ -8,7 +10,7 @@
#include "aica_common.hpp"
#include "aica_rtc.hpp"
struct aica_reg {
struct aica_sound {
// 0x00700000 [64] channel data start
// 0x00702000 [64] channel data end
// 0x00702000 [18] dsp out start
@ -22,10 +24,10 @@ struct aica_reg {
struct aica_common common;
};
static_assert((sizeof (struct aica_reg)) == 0x2d08);
static_assert((offsetof (struct aica_reg, channel)) == 0);
static_assert((offsetof (struct aica_reg, dsp_out)) == 0x2000);
static_assert((offsetof (struct aica_reg, common)) == 0x2800);
static_assert((sizeof (struct aica_sound)) == 0x2d08);
static_assert((offsetof (struct aica_sound, channel)) == 0);
static_assert((offsetof (struct aica_sound, dsp_out)) == 0x2000);
static_assert((offsetof (struct aica_sound, common)) == 0x2800);
extern struct aica_reg aica __asm("aica");
extern struct aica_sound aica_sound __asm("aica_sound");
extern struct aica_rtc aica_rtc __asm("aica_rtc");

View File

@ -4,24 +4,78 @@
#include "type.hpp"
struct aica_channel {
reg32 reg_0000;
reg32 reg_0004;
reg32 reg_0008;
reg32 reg_000c;
reg32 reg_0010;
reg32 reg_0014;
reg32 reg_0018;
reg32 reg_001c;
reg32 reg_0020;
reg32 reg_0024;
reg32 reg_0028;
reg32 reg_002c;
reg32 reg_0030;
reg32 reg_0034;
reg32 reg_0038;
reg32 reg_003c;
reg32 reg_0040;
reg32 reg_0044;
union {
reg32 reg_0000;
reg32 kyonex_kyonb_ssctl_lpctl_pcms_sa0;
};
union {
reg32 reg_0004;
reg32 sa1;
};
union {
reg32 reg_0008;
reg32 lsa;
};
union {
reg32 reg_000c;
reg32 lea;
};
union {
reg32 reg_0010;
reg32 d2r_d1r_ar;
};
union {
reg32 reg_0014;
reg32 lpslnk_krs_dl_rr;
};
union {
reg32 reg_0018;
reg32 oct_fns;
};
union {
reg32 reg_001c;
reg32 lfore_lfof_plfows_plfos_alfows_alfos;
};
union {
reg32 reg_0020;
reg32 imxl_isel;
};
union {
reg32 reg_0024;
reg32 disdl_dipan;
};
union {
reg32 reg_0028;
reg32 tl_voff_lpoff_q;
};
union {
reg32 reg_002c;
reg32 flv0;
};
union {
reg32 reg_0030;
reg32 flv1;
};
union {
reg32 reg_0034;
reg32 flv2;
};
union {
reg32 reg_0038;
reg32 flv3;
};
union {
reg32 reg_003c;
reg32 flv4;
};
union {
reg32 reg_0040;
reg32 far_fd1r;
};
union {
reg32 reg_0044;
reg32 fd2r_frr;
};
const reg32 _pad0[14];
uint32_t KYONEX() const
@ -406,3 +460,83 @@ static_assert((offsetof (aica_channel, reg_0038)) == 0x38 - 0x0);
static_assert((offsetof (aica_channel, reg_003c)) == 0x3c - 0x0);
static_assert((offsetof (aica_channel, reg_0040)) == 0x40 - 0x0);
static_assert((offsetof (aica_channel, reg_0044)) == 0x44 - 0x0);
namespace aica {
namespace kyonex_kyonb_ssctl_lpctl_pcms_sa0 {
constexpr uint32_t KYONEX(const uint32_t v) { return (((v >> 0) & 0x1) << 15); }
constexpr uint32_t KYONB(const uint32_t v) { return (((v >> 0) & 0x1) << 14); }
constexpr uint32_t SSCTL(const uint32_t v) { return (((v >> 0) & 0x1) << 10); }
constexpr uint32_t LPCTL(const uint32_t v) { return (((v >> 0) & 0x1) << 9); }
constexpr uint32_t PCMS(const uint32_t v) { return (((v >> 0) & 0x3) << 7); }
constexpr uint32_t SA(const uint32_t v) { return (((v >> 16) & 0x7f) << 0); }
}
namespace sa1 {
constexpr uint32_t SA(const uint32_t v) { return (((v >> 0) & 0xffff) << 0); }
}
namespace lsa {
constexpr uint32_t LSA(const uint32_t v) { return (((v >> 0) & 0xffff) << 0); }
}
namespace lea {
constexpr uint32_t LEA(const uint32_t v) { return (((v >> 0) & 0xffff) << 0); }
}
namespace d2r_d1r_ar {
constexpr uint32_t D2R(const uint32_t v) { return (((v >> 0) & 0x1f) << 11); }
constexpr uint32_t D1R(const uint32_t v) { return (((v >> 0) & 0x1f) << 6); }
constexpr uint32_t AR(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
namespace lpslnk_krs_dl_rr {
constexpr uint32_t LPSLNK(const uint32_t v) { return (((v >> 0) & 0x1) << 14); }
constexpr uint32_t KRS(const uint32_t v) { return (((v >> 0) & 0xf) << 10); }
constexpr uint32_t DL(const uint32_t v) { return (((v >> 0) & 0x1f) << 5); }
constexpr uint32_t RR(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
namespace oct_fns {
constexpr uint32_t OCT(const uint32_t v) { return (((v >> 0) & 0xf) << 11); }
constexpr uint32_t FNS(const uint32_t v) { return (((v >> 0) & 0x3ff) << 0); }
}
namespace lfore_lfof_plfows_plfos_alfows_alfos {
constexpr uint32_t LFORE(const uint32_t v) { return (((v >> 0) & 0x1) << 15); }
constexpr uint32_t LFOF(const uint32_t v) { return (((v >> 0) & 0x1f) << 10); }
constexpr uint32_t PLFOWS(const uint32_t v) { return (((v >> 0) & 0x3) << 8); }
constexpr uint32_t PLFOS(const uint32_t v) { return (((v >> 0) & 0x7) << 5); }
constexpr uint32_t ALFOWS(const uint32_t v) { return (((v >> 0) & 0x3) << 3); }
constexpr uint32_t ALFOS(const uint32_t v) { return (((v >> 0) & 0x7) << 0); }
}
namespace imxl_isel {
constexpr uint32_t IMXL(const uint32_t v) { return (((v >> 0) & 0xf) << 4); }
constexpr uint32_t ISEL(const uint32_t v) { return (((v >> 0) & 0xf) << 0); }
}
namespace disdl_dipan {
constexpr uint32_t DISDL(const uint32_t v) { return (((v >> 0) & 0xf) << 8); }
constexpr uint32_t DIPAN(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
namespace tl_voff_lpoff_q {
constexpr uint32_t TL(const uint32_t v) { return (((v >> 0) & 0xff) << 8); }
constexpr uint32_t VOFF(const uint32_t v) { return (((v >> 0) & 0x1) << 6); }
constexpr uint32_t LPOFF(const uint32_t v) { return (((v >> 0) & 0x1) << 5); }
constexpr uint32_t Q(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
namespace flv0 {
constexpr uint32_t FLV0(const uint32_t v) { return (((v >> 0) & 0x1fff) << 0); }
}
namespace flv1 {
constexpr uint32_t FLV1(const uint32_t v) { return (((v >> 0) & 0x1fff) << 0); }
}
namespace flv2 {
constexpr uint32_t FLV2(const uint32_t v) { return (((v >> 0) & 0x1fff) << 0); }
}
namespace flv3 {
constexpr uint32_t FLV3(const uint32_t v) { return (((v >> 0) & 0x1fff) << 0); }
}
namespace flv4 {
constexpr uint32_t FLV4(const uint32_t v) { return (((v >> 0) & 0x1fff) << 0); }
}
namespace far_fd1r {
constexpr uint32_t FAR(const uint32_t v) { return (((v >> 0) & 0x1f) << 8); }
constexpr uint32_t FD1R(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
namespace fd2r_frr {
constexpr uint32_t FD2R(const uint32_t v) { return (((v >> 0) & 0x1f) << 8); }
constexpr uint32_t FRR(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
}

View File

@ -4,34 +4,109 @@
#include "type.hpp"
struct aica_common {
reg32 reg_2800;
reg32 reg_2804;
reg32 reg_2808;
reg32 reg_280c;
reg32 reg_2810;
reg32 reg_2814;
union {
reg32 reg_2800;
reg32 mono_mem8mb_dac18b_ver_mvol;
};
union {
reg32 reg_2804;
reg32 rbl_rbp;
};
union {
reg32 reg_2808;
reg32 moful_moemp_miovf_miful_miemp_mibuf;
};
union {
reg32 reg_280c;
reg32 afsel_mslc_mobuf;
};
union {
reg32 reg_2810;
reg32 lp_sgc_eg;
};
union {
reg32 reg_2814;
reg32 ca;
};
const reg32 _pad0[26];
reg32 reg_2880;
reg32 reg_2884;
reg32 reg_2888;
reg32 reg_288c;
reg32 reg_2890;
reg32 reg_2894;
reg32 reg_2898;
reg32 reg_289c;
reg32 reg_28a0;
reg32 reg_28a4;
reg32 reg_28a8;
reg32 reg_28ac;
reg32 reg_28b0;
reg32 reg_28b4;
reg32 reg_28b8;
reg32 reg_28bc;
union {
reg32 reg_2880;
reg32 dmea0_mrwinh;
};
union {
reg32 reg_2884;
reg32 dmea1;
};
union {
reg32 reg_2888;
reg32 dgate_drga;
};
union {
reg32 reg_288c;
reg32 ddir_dlg_dexe;
};
union {
reg32 reg_2890;
reg32 tactl_tima;
};
union {
reg32 reg_2894;
reg32 tbctl_timb;
};
union {
reg32 reg_2898;
reg32 tcctl_timc;
};
union {
reg32 reg_289c;
reg32 scieb;
};
union {
reg32 reg_28a0;
reg32 scipd;
};
union {
reg32 reg_28a4;
reg32 scire;
};
union {
reg32 reg_28a8;
reg32 scilv0;
};
union {
reg32 reg_28ac;
reg32 scilv1;
};
union {
reg32 reg_28b0;
reg32 scilv2;
};
union {
reg32 reg_28b4;
reg32 mcieb;
};
union {
reg32 reg_28b8;
reg32 mcipd;
};
union {
reg32 reg_28bc;
reg32 mcire;
};
const reg32 _pad1[208];
reg32 reg_2c00;
union {
reg32 reg_2c00;
reg32 vreg_armrst;
};
const reg32 _pad2[63];
reg32 reg_2d00;
reg32 reg_2d04;
union {
reg32 reg_2d00;
reg32 l7_l6_l5_l4_l3_l2_l1_l0;
};
union {
reg32 reg_2d04;
reg32 rp_m7_m6_m5_m4_m3_m2_m1_m0;
};
uint32_t MONO() const
{
@ -78,15 +153,6 @@ struct aica_common {
reg_2800 = (((v >> 0) & 0xf) << 0) | (reg_2800 & 0xfff0);
}
uint32_t TESTB0() const
{
return (static_cast<uint32_t>((reg_2804 >> 15) & 0x1) << 0);
}
void TESTB0(const uint32_t v)
{
reg_2804 = (((v >> 0) & 0x1) << 15) | (reg_2804 & 0x7fff);
}
uint32_t RBL() const
{
return (static_cast<uint32_t>((reg_2804 >> 13) & 0x3) << 0);
@ -159,11 +225,11 @@ struct aica_common {
reg_2808 = (((v >> 0) & 0xff) << 0) | (reg_2808 & 0xff00);
}
uint32_t AFSET() const
uint32_t AFSEL() const
{
return (static_cast<uint32_t>((reg_280c >> 14) & 0x1) << 0);
}
void AFSET(const uint32_t v)
void AFSEL(const uint32_t v)
{
reg_280c = (((v >> 0) & 0x1) << 14) | (reg_280c & 0xbfff);
}
@ -232,24 +298,6 @@ struct aica_common {
reg_2884 = (((v >> 2) & 0x3fff) << 2);
}
uint32_t TSCD() const
{
return (static_cast<uint32_t>((reg_2880 >> 5) & 0x7) << 0);
}
void TSCD(const uint32_t v)
{
reg_2880 = (((v >> 0) & 0x7) << 5) | (reg_2880 & 0xff1f);
}
uint32_t T() const
{
return (static_cast<uint32_t>((reg_2880 >> 4) & 0x1) << 0);
}
void T(const uint32_t v)
{
reg_2880 = (((v >> 0) & 0x1) << 4) | (reg_2880 & 0xffef);
}
uint32_t MRWINH() const
{
return (static_cast<uint32_t>((reg_2880 >> 0) & 0xf) << 0);
@ -421,11 +469,11 @@ struct aica_common {
reg_28b4 = (((v >> 0) & 0x7ff) << 0);
}
uint32_t MCIPB() const
uint32_t MCIPD() const
{
return (static_cast<uint32_t>((reg_28b8 >> 0) & 0x7ff) << 0);
}
void MCIPB(const uint32_t v)
void MCIPD(const uint32_t v)
{
reg_28b8 = (((v >> 0) & 0x7ff) << 0);
}
@ -638,3 +686,118 @@ static_assert((offsetof (aica_common, reg_28bc)) == 0x28bc - 0x2800);
static_assert((offsetof (aica_common, reg_2c00)) == 0x2c00 - 0x2800);
static_assert((offsetof (aica_common, reg_2d00)) == 0x2d00 - 0x2800);
static_assert((offsetof (aica_common, reg_2d04)) == 0x2d04 - 0x2800);
namespace aica {
namespace mono_mem8mb_dac18b_ver_mvol {
constexpr uint32_t MONO(const uint32_t v) { return (((v >> 0) & 0x1) << 15); }
constexpr uint32_t MEM8MB(const uint32_t v) { return (((v >> 0) & 0x1) << 9); }
constexpr uint32_t DAC18B(const uint32_t v) { return (((v >> 0) & 0x1) << 8); }
constexpr uint32_t VER(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 4) & 0xf) << 0); }
constexpr uint32_t MVOL(const uint32_t v) { return (((v >> 0) & 0xf) << 0); }
}
namespace rbl_rbp {
constexpr uint32_t RBL(const uint32_t v) { return (((v >> 0) & 0x3) << 13); }
constexpr uint32_t RBP(const uint32_t v) { return (((v >> 11) & 0xfff) << 0); }
}
namespace moful_moemp_miovf_miful_miemp_mibuf {
constexpr uint32_t MOFUL(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 12) & 0x1) << 0); }
constexpr uint32_t MOEMP(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 11) & 0x1) << 0); }
constexpr uint32_t MIOVF(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 10) & 0x1) << 0); }
constexpr uint32_t MIFUL(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 9) & 0x1) << 0); }
constexpr uint32_t MIEMP(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 8) & 0x1) << 0); }
constexpr uint32_t MIBUF(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 0) & 0xff) << 0); }
}
namespace afsel_mslc_mobuf {
constexpr uint32_t AFSEL(const uint32_t v) { return (((v >> 0) & 0x1) << 14); }
constexpr uint32_t MSLC(const uint32_t v) { return (((v >> 0) & 0x3f) << 8); }
constexpr uint32_t MOBUF(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace lp_sgc_eg {
constexpr uint32_t LP(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 15) & 0x1) << 0); }
constexpr uint32_t SGC(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 14) & 0x1) << 0); }
constexpr uint32_t EG(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 0) & 0x1fff) << 0); }
}
namespace ca {
constexpr uint32_t CA(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 0) & 0xffff) << 0); }
}
namespace dmea0_mrwinh {
constexpr uint32_t DMEA(const uint32_t v) { return (((v >> 16) & 0x7f) << 9); }
constexpr uint32_t MRWINH(const uint32_t v) { return (((v >> 0) & 0xf) << 0); }
}
namespace dmea1 {
constexpr uint32_t DMEA(const uint32_t v) { return (((v >> 2) & 0x3fff) << 2); }
}
namespace dgate_drga {
constexpr uint32_t DGATE(const uint32_t v) { return (((v >> 0) & 0x1) << 15); }
constexpr uint32_t DRGA(const uint32_t v) { return (((v >> 2) & 0x1fff) << 2); }
}
namespace ddir_dlg_dexe {
constexpr uint32_t DDIR(const uint32_t v) { return (((v >> 0) & 0x1) << 15); }
constexpr uint32_t DLG(const uint32_t v) { return (((v >> 2) & 0x1fff) << 2); }
constexpr uint32_t DEXE(const uint32_t v) { return (((v >> 0) & 0x1) << 0); }
}
namespace tactl_tima {
constexpr uint32_t TACTL(const uint32_t v) { return (((v >> 0) & 0x7) << 8); }
constexpr uint32_t TIMA(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace tbctl_timb {
constexpr uint32_t TBCTL(const uint32_t v) { return (((v >> 0) & 0x7) << 8); }
constexpr uint32_t TIMB(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace tcctl_timc {
constexpr uint32_t TCCTL(const uint32_t v) { return (((v >> 0) & 0x7) << 8); }
constexpr uint32_t TIMC(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace scieb {
constexpr uint32_t SCIEB(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace scipd {
constexpr uint32_t SCIPD(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace scire {
constexpr uint32_t SCIRE(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace scilv0 {
constexpr uint32_t SCILV0(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace scilv1 {
constexpr uint32_t SCILV1(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace scilv2 {
constexpr uint32_t SCILV2(const uint32_t v) { return (((v >> 0) & 0xff) << 0); }
}
namespace mcieb {
constexpr uint32_t MCIEB(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace mcipd {
constexpr uint32_t MCIPD(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace mcire {
constexpr uint32_t MCIRE(const uint32_t v) { return (((v >> 0) & 0x7ff) << 0); }
}
namespace vreg_armrst {
constexpr uint32_t VREG(const uint32_t v) { return (((v >> 0) & 0x3) << 8); }
constexpr uint32_t ARMRST(const uint32_t v) { return (((v >> 0) & 0x1) << 0); }
}
namespace l7_l6_l5_l4_l3_l2_l1_l0 {
constexpr uint32_t L7(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 7) & 0x1) << 0); }
constexpr uint32_t L6(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 6) & 0x1) << 0); }
constexpr uint32_t L5(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 5) & 0x1) << 0); }
constexpr uint32_t L4(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 4) & 0x1) << 0); }
constexpr uint32_t L3(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 3) & 0x1) << 0); }
constexpr uint32_t L2(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 2) & 0x1) << 0); }
constexpr uint32_t L1(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 1) & 0x1) << 0); }
constexpr uint32_t L0(const uint32_t reg) { return (static_cast<uint32_t>((reg >> 0) & 0x1) << 0); }
}
namespace rp_m7_m6_m5_m4_m3_m2_m1_m0 {
constexpr uint32_t RP(const uint32_t v) { return (((v >> 0) & 0x1) << 8); }
constexpr uint32_t M7(const uint32_t v) { return (((v >> 0) & 0x1) << 7); }
constexpr uint32_t M6(const uint32_t v) { return (((v >> 0) & 0x1) << 6); }
constexpr uint32_t M5(const uint32_t v) { return (((v >> 0) & 0x1) << 5); }
constexpr uint32_t M4(const uint32_t v) { return (((v >> 0) & 0x1) << 4); }
constexpr uint32_t M3(const uint32_t v) { return (((v >> 0) & 0x1) << 3); }
constexpr uint32_t M2(const uint32_t v) { return (((v >> 0) & 0x1) << 2); }
constexpr uint32_t M1(const uint32_t v) { return (((v >> 0) & 0x1) << 1); }
constexpr uint32_t M0(const uint32_t v) { return (((v >> 0) & 0x1) << 0); }
}
}

View File

@ -4,7 +4,10 @@
#include "type.hpp"
struct aica_dsp_out {
reg32 reg_0000;
union {
reg32 reg_0000;
reg32 efdsl_efpan;
};
uint32_t EFDSL() const
{
@ -28,3 +31,10 @@ struct aica_dsp_out {
static_assert((sizeof (aica_dsp_out)) == 0x4 - 0x0);
static_assert((offsetof (aica_dsp_out, reg_0000)) == 0x0 - 0x0);
namespace aica {
namespace efdsl_efpan {
constexpr uint32_t EFDSL(const uint32_t v) { return (((v >> 0) & 0xf) << 8); }
constexpr uint32_t EFPAN(const uint32_t v) { return (((v >> 0) & 0x1f) << 0); }
}
}

View File

@ -4,9 +4,18 @@
#include "type.hpp"
struct aica_rtc {
reg32 reg_0000;
reg32 reg_0004;
reg32 reg_0008;
union {
reg32 reg_0000;
reg32 rtc0;
};
union {
reg32 reg_0004;
reg32 rtc1;
};
union {
reg32 reg_0008;
reg32 en;
};
uint32_t RTC() const
{
@ -33,3 +42,15 @@ static_assert((sizeof (aica_rtc)) == 0xc - 0x0);
static_assert((offsetof (aica_rtc, reg_0000)) == 0x0 - 0x0);
static_assert((offsetof (aica_rtc, reg_0004)) == 0x4 - 0x0);
static_assert((offsetof (aica_rtc, reg_0008)) == 0x8 - 0x0);
namespace aica {
namespace rtc0 {
constexpr uint32_t RTC(const uint32_t v) { return (((v >> 16) & 0xffff) << 0); }
}
namespace rtc1 {
constexpr uint32_t RTC(const uint32_t v) { return (((v >> 0) & 0xffff) << 0); }
}
namespace en {
constexpr uint32_t EN(const uint32_t v) { return (((v >> 0) & 0x1) << 0); }
}
}

View File

@ -1,8 +1,8 @@
#include "memorymap.hpp"
#include "aica/aica.hpp"
#include "sh7091/serial.hpp"
#include "systembus.hpp"
#include "systembus_bits.hpp"
#include "aica/aica.hpp"
extern void * _binary_start __asm("_binary_example_arm_channel_bin_start");
extern void * _binary_size __asm("_binary_example_arm_channel_bin_size");
@ -27,35 +27,37 @@ void main()
const uint32_t * binary = reinterpret_cast<uint32_t *>(&_binary_start);
const uint32_t binary_size = reinterpret_cast<uint32_t>(&_binary_size);
wait(); aica.common.reg_2c00 = 1;
wait(); aica.common.reg_2880 = 0;
wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1);
wait(); aica_sound.common.dmea0_mrwinh = aica::dmea0_mrwinh::MRWINH(0);
for (uint32_t i = 0; i < binary_size / 4; i++) {
// copy
aica_wave_memory[i] = binary[i];
if (i % 8 == 7) wait();
while (aica_wave_memory[i] != binary[i]) {
wait();
aica_wave_memory[i] = binary[i];
}
}
wait(); aica.common.reg_2c00 = 0;
wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(0);
serial::integer<uint32_t>(aica_wave_memory[0]);
wait(); aica.common.MSLC(0);
wait(); aica_sound.common.afsel_mslc_mobuf = aica::afsel_mslc_mobuf::MSLC(0);
serial::string("mrwinh: ");
wait_read();
serial::integer<uint8_t>(aica.common.MRWINH());
serial::integer<uint8_t>(aica_sound.common.MRWINH());
while (1) {
wait_read();
serial::string("sgc: ");
serial::integer<uint8_t>(aica.common.SGC(), ' ');
serial::integer<uint8_t>(aica_sound.common.SGC(), ' ');
serial::string("; ca: ");
serial::integer<uint8_t>(aica.common.CA(), ' ');
serial::integer<uint8_t>(aica_sound.common.CA(), ' ');
serial::string("; eg: ");
serial::integer<uint8_t>(aica.common.EG(), ' ');
serial::integer<uint8_t>(aica_sound.common.EG(), ' ');
serial::string("; lp: ");
serial::integer<uint8_t>(aica.common.LP(), ' ');
serial::integer<uint8_t>(aica_sound.common.LP(), ' ');
serial::character('\n');
for (int i = 0; i < 10000000; i++) {
asm volatile ("nop");
}
serial::integer<uint32_t>(aica_wave_memory[0], ' ');
serial::integer<uint32_t>(aica_wave_memory[1], '\n');
}
while (1);

62
example/aica_gdrom.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "memorymap.hpp"
#include "aica/aica.hpp"
#include "sh7091/serial.hpp"
#include "systembus.hpp"
#include "systembus_bits.hpp"
extern void * _binary_start __asm("_binary_example_arm_channel_bin_start");
extern void * _binary_size __asm("_binary_example_arm_channel_bin_size");
void wait()
{
while (ffst::aica_internal_write_buffer(system.FFST));
}
void wait_read()
{
uint32_t ffst = ~0;
while ( ffst::holly_cpu_if_block_internal_write_buffer(ffst)
| ffst::holly_g2_if_block_internal_write_buffer(ffst)
| ffst::aica_internal_write_buffer(ffst)) {
ffst = system.FFST;
};
}
void main()
{
const uint32_t * binary = reinterpret_cast<uint32_t *>(&_binary_start);
const uint32_t binary_size = reinterpret_cast<uint32_t>(&_binary_size);
wait(); aica.common.reg_2c00 = 1;
wait(); aica.common.reg_2880 = 0;
for (uint32_t i = 0; i < binary_size / 4; i++) {
// copy
aica_wave_memory[i] = binary[i];
if (i % 8 == 7) wait();
}
wait(); aica.common.reg_2c00 = 0;
serial::integer<uint32_t>(aica_wave_memory[0]);
wait(); aica.common.MSLC(0);
serial::string("mrwinh: ");
wait_read();
serial::integer<uint8_t>(aica.common.MRWINH());
while (1) {
wait_read();
serial::string("sgc: ");
serial::integer<uint8_t>(aica.common.SGC(), ' ');
serial::string("; ca: ");
serial::integer<uint8_t>(aica.common.CA(), ' ');
serial::string("; eg: ");
serial::integer<uint8_t>(aica.common.EG(), ' ');
serial::string("; lp: ");
serial::integer<uint8_t>(aica.common.LP(), ' ');
serial::character('\n');
for (int i = 0; i < 10000000; i++) {
asm volatile ("nop");
}
}
while (1);
}

View File

@ -1,2 +1,2 @@
dram = 0x00000000;
aica = 0x00800000;
aica_sound = 0x00800000;

View File

@ -19,41 +19,46 @@ void main()
dsp[i] = 0;
}
aica.channel[0].KYONB(1);
aica.channel[0].LPCTL(1);
aica.channel[0].PCMS(0);
aica.channel[0].SA(sine_addr);
aica.channel[0].LSA(0);
aica.channel[0].LEA(128);
aica.channel[0].D2R(0x0);
aica.channel[0].D1R(0x0);
aica.channel[0].RR(0x0);
aica.channel[0].AR(0x1f);
aica_sound.channel[0].KYONB(1);
aica_sound.channel[0].LPCTL(1);
aica_sound.channel[0].PCMS(0);
aica_sound.channel[0].SA(sine_addr);
aica_sound.channel[0].LSA(0);
aica_sound.channel[0].LEA(128);
aica_sound.channel[0].D2R(0x0);
aica_sound.channel[0].D1R(0x0);
aica_sound.channel[0].RR(0x0);
aica_sound.channel[0].AR(0x1f);
aica.channel[0].OCT(0);
aica.channel[0].FNS(0);
aica.channel[0].DISDL(0xf);
aica.channel[0].DIPAN(0x0);
aica_sound.channel[0].OCT(0);
aica_sound.channel[0].FNS(0);
aica_sound.channel[0].DISDL(0xf);
aica_sound.channel[0].DIPAN(0x0);
aica.channel[0].Q(0b00100);
aica.channel[0].TL(0);
aica.channel[0].LPOFF(1);
aica_sound.channel[0].Q(0b00100);
aica_sound.channel[0].TL(0);
aica_sound.channel[0].LPOFF(1);
aica.common.MVOL(0xf);
aica_sound.common.MVOL(0xf);
uint32_t segment = 0;
aica.common.TACTL(7); // increment once every 128 samples
aica.common.TIMA(0);
aica.channel[0].KYONEX(1);
aica_sound.common.TACTL(7); // increment once every 128 samples
aica_sound.common.TIMA(255);
aica_sound.channel[0].KYONEX(1);
dram[0] = 0x11223344;
dram[1] = sine_addr;
constexpr uint32_t timer_a_interrupt = (1 << 6);
aica_sound.common.scire = timer_a_interrupt;
while (1) {
if (aica.common.TIMA() >= 1) {
aica.common.TIMA(0);
if (aica_sound.common.SCIPD() & timer_a_interrupt) {
aica_sound.common.scire = timer_a_interrupt;
aica_sound.common.TIMA(255);
segment += 1;
if (segment >= 3440) segment = 0;
aica.channel[0].SA(sine_addr + (128 * 2) * segment);
uint32_t sa = sine_addr + (128 * 2) * segment;
dram[1] = sa;
aica_sound.channel[0].SA(sa);
}
}
}

View File

@ -1,42 +1,42 @@
"name","part","address","register_bits","argument_bits"
"KYONEX",,"0x0000","15",
"KYONB",,"0x0000","14",
"SSCTL",,"0x0000","10",
"LPCTL",,"0x0000","9",
"PCMS",,"0x0000","8-7",
"SA","0","0x0000","6-0","22-16"
"SA","1","0x0004","15-0",
"LSA",,"0x0008","15-0",
"LEA",,"0x000c","15-0",
"D2R",,"0x0010","15-11",
"D1R",,"0x0010","10-6",
"AR",,"0x0010","4-0",
"LPSLNK",,"0x0014","14",
"KRS",,"0x0014","13-10",
"DL",,"0x0014","9-5",
"RR",,"0x0014","4-0",
"OCT",,"0x0018","14-11",
"FNS",,"0x0018","9-0",
"LFORE",,"0x001c","15",
"LFOF",,"0x001c","14-10",
"PLFOWS",,"0x001c","9-8",
"PLFOS",,"0x001c","7-5",
"ALFOWS",,"0x001c","4-3",
"ALFOS",,"0x001c","2-0",
"IMXL",,"0x0020","7-4",
"ISEL",,"0x0020","3-0",
"DISDL",,"0x0024","11-8",
"DIPAN",,"0x0024","4-0",
"TL",,"0x0028","15-8",
"VOFF",,"0x0028","6",
"LPOFF",,"0x0028","5",
"Q",,"0x0028","4-0",
"FLV0",,"0x002c","12-0",
"FLV1",,"0x0030","12-0",
"FLV2",,"0x0034","12-0",
"FLV3",,"0x0038","12-0",
"FLV4",,"0x003c","12-0",
"FAR",,"0x0040","12-8",
"FD1R",,"0x0040","4-0",
"FD2R",,"0x0044","12-8",
"FRR",,"0x0044","4-0",
"name","part","address","register_bits","argument_bits","rw"
"KYONEX",,"0x0000","15",,"w"
"KYONB",,"0x0000","14",,"rw"
"SSCTL",,"0x0000","10",,"rw"
"LPCTL",,"0x0000","9",,"rw"
"PCMS",,"0x0000","8-7",,"rw"
"SA","0","0x0000","6-0","22-16","rw"
"SA","1","0x0004","15-0",,"rw"
"LSA",,"0x0008","15-0",,"rw"
"LEA",,"0x000c","15-0",,"rw"
"D2R",,"0x0010","15-11",,"rw"
"D1R",,"0x0010","10-6",,"rw"
"AR",,"0x0010","4-0",,"rw"
"LPSLNK",,"0x0014","14",,"rw"
"KRS",,"0x0014","13-10",,"rw"
"DL",,"0x0014","9-5",,"rw"
"RR",,"0x0014","4-0",,"rw"
"OCT",,"0x0018","14-11",,"rw"
"FNS",,"0x0018","9-0",,"rw"
"LFORE",,"0x001c","15",,"rw"
"LFOF",,"0x001c","14-10",,"rw"
"PLFOWS",,"0x001c","9-8",,"rw"
"PLFOS",,"0x001c","7-5",,"rw"
"ALFOWS",,"0x001c","4-3",,"rw"
"ALFOS",,"0x001c","2-0",,"rw"
"IMXL",,"0x0020","7-4",,"rw"
"ISEL",,"0x0020","3-0",,"rw"
"DISDL",,"0x0024","11-8",,"rw"
"DIPAN",,"0x0024","4-0",,"rw"
"TL",,"0x0028","15-8",,"rw"
"VOFF",,"0x0028","6",,"rw"
"LPOFF",,"0x0028","5",,"rw"
"Q",,"0x0028","4-0",,"rw"
"FLV0",,"0x002c","12-0",,"rw"
"FLV1",,"0x0030","12-0",,"rw"
"FLV2",,"0x0034","12-0",,"rw"
"FLV3",,"0x0038","12-0",,"rw"
"FLV4",,"0x003c","12-0",,"rw"
"FAR",,"0x0040","12-8",,"rw"
"FD1R",,"0x0040","4-0",,"rw"
"FD2R",,"0x0044","12-8",,"rw"
"FRR",,"0x0044","4-0",,"rw"

1 name part address register_bits argument_bits rw
2 KYONEX 0x0000 15 w
3 KYONB 0x0000 14 rw
4 SSCTL 0x0000 10 rw
5 LPCTL 0x0000 9 rw
6 PCMS 0x0000 8-7 rw
7 SA 0 0x0000 6-0 22-16 rw
8 SA 1 0x0004 15-0 rw
9 LSA 0x0008 15-0 rw
10 LEA 0x000c 15-0 rw
11 D2R 0x0010 15-11 rw
12 D1R 0x0010 10-6 rw
13 AR 0x0010 4-0 rw
14 LPSLNK 0x0014 14 rw
15 KRS 0x0014 13-10 rw
16 DL 0x0014 9-5 rw
17 RR 0x0014 4-0 rw
18 OCT 0x0018 14-11 rw
19 FNS 0x0018 9-0 rw
20 LFORE 0x001c 15 rw
21 LFOF 0x001c 14-10 rw
22 PLFOWS 0x001c 9-8 rw
23 PLFOS 0x001c 7-5 rw
24 ALFOWS 0x001c 4-3 rw
25 ALFOS 0x001c 2-0 rw
26 IMXL 0x0020 7-4 rw
27 ISEL 0x0020 3-0 rw
28 DISDL 0x0024 11-8 rw
29 DIPAN 0x0024 4-0 rw
30 TL 0x0028 15-8 rw
31 VOFF 0x0028 6 rw
32 LPOFF 0x0028 5 rw
33 Q 0x0028 4-0 rw
34 FLV0 0x002c 12-0 rw
35 FLV1 0x0030 12-0 rw
36 FLV2 0x0034 12-0 rw
37 FLV3 0x0038 12-0 rw
38 FLV4 0x003c 12-0 rw
39 FAR 0x0040 12-8 rw
40 FD1R 0x0040 4-0 rw
41 FD2R 0x0044 12-8 rw
42 FRR 0x0044 4-0 rw

Binary file not shown.

View File

@ -1,66 +1,66 @@
"name","part","address","register_bits","argument_bits"
"MONO",,"0x2800","15",
"MEM8MB",,"0x2800","9",
"DAC18B",,"0x2800","8",
"VER",,"0x2800","7-4",
"MVOL",,"0x2800","3-0",
"TESTB0",,"0x2804","15",
"RBL",,"0x2804","14-13",
"RBP",,"0x2804","11-0","22-11"
"MOFUL",,"0x2808","12",
"MOEMP",,"0x2808","11",
"MIOVF",,"0x2808","10",
"MIFUL",,"0x2808","9",
"MIEMP",,"0x2808","8",
"MIBUF",,"0x2808","7-0",
"AFSET",,"0x280c","14",
"MSLC",,"0x280c","13-8",
"MOBUF",,"0x280c","7-0",
"LP",,"0x2810","15",
"SGC",,"0x2810","14",
"EG",,"0x2810","12-0",
"CA",,"0x2814","15-0",
"DMEA","0","0x2880","15-9","22-16"
"TSCD",,"0x2880","7-5",
"T",,"0x2880","4",
"MRWINH",,"0x2880","3-0",
"DMEA","1","0x2884","15-2","15-2"
"DGATE",,"0x2888","15",
"DRGA",,"0x2888","14-2","14-2"
"DDIR",,"0x288c","15",
"DLG",,"0x288c","14-2","14-2"
"DEXE",,"0x288c","0",
"TACTL",,"0x2890","10-8",
"TIMA",,"0x2890","7-0",
"TBCTL",,"0x2894","10-8",
"TIMB",,"0x2894","7-0",
"TCCTL",,"0x2898","10-8",
"TIMC",,"0x2898","7-0",
"SCIEB",,"0x289c","10-0",
"SCIPD",,"0x28a0","10-0",
"SCIRE",,"0x28a4","10-0",
"SCILV0",,"0x28a8","7-0",
"SCILV1",,"0x28ac","7-0",
"SCILV2",,"0x28b0","7-0",
"MCIEB",,"0x28b4","10-0",
"MCIPB",,"0x28b8","10-0",
"MCIRE",,"0x28bc","10-0",
"VREG",,"0x2c00","9-8",
"ARMRST",,"0x2c00","0",
"L7",,"0x2d00","7",
"L6",,"0x2d00","6",
"L5",,"0x2d00","5",
"L4",,"0x2d00","4",
"L3",,"0x2d00","3",
"L2",,"0x2d00","2",
"L1",,"0x2d00","1",
"L0",,"0x2d00","0",
"RP",,"0x2d04","8",
"M7",,"0x2d04","7",
"M6",,"0x2d04","6",
"M5",,"0x2d04","5",
"M4",,"0x2d04","4",
"M3",,"0x2d04","3",
"M2",,"0x2d04","2",
"M1",,"0x2d04","1",
"M0",,"0x2d04","0",
"name","part","address","register_bits","argument_bits","rw"
"MONO",,"0x2800","15",,"w"
"MEM8MB",,"0x2800","9",,"w"
"DAC18B",,"0x2800","8",,"w"
"VER",,"0x2800","7-4",,"r"
"MVOL",,"0x2800","3-0",,"w"
"TESTB0",,"0x2804","15",,
"RBL",,"0x2804","14-13",,"w"
"RBP",,"0x2804","11-0","22-11","w"
"MOFUL",,"0x2808","12",,"r"
"MOEMP",,"0x2808","11",,"r"
"MIOVF",,"0x2808","10",,"r"
"MIFUL",,"0x2808","9",,"r"
"MIEMP",,"0x2808","8",,"r"
"MIBUF",,"0x2808","7-0",,"r"
"AFSEL",,"0x280c","14",,"w"
"MSLC",,"0x280c","13-8",,"w"
"MOBUF",,"0x280c","7-0",,"w"
"LP",,"0x2810","15",,"r"
"SGC",,"0x2810","14",,"r"
"EG",,"0x2810","12-0",,"r"
"CA",,"0x2814","15-0",,"r"
"DMEA","0","0x2880","15-9","22-16","w"
"TSCD",,"0x2880","7-5",,
"T",,"0x2880","4",,
"MRWINH",,"0x2880","3-0",,"w"
"DMEA","1","0x2884","15-2","15-2","w"
"DGATE",,"0x2888","15",,"rw"
"DRGA",,"0x2888","14-2","14-2","w"
"DDIR",,"0x288c","15",,"rw"
"DLG",,"0x288c","14-2","14-2","w"
"DEXE",,"0x288c","0",,"rw"
"TACTL",,"0x2890","10-8",,"w"
"TIMA",,"0x2890","7-0",,"w"
"TBCTL",,"0x2894","10-8",,"w"
"TIMB",,"0x2894","7-0",,"w"
"TCCTL",,"0x2898","10-8",,"w"
"TIMC",,"0x2898","7-0",,"w"
"SCIEB",,"0x289c","10-0",,"rw"
"SCIPD",,"0x28a0","10-0",,"rw"
"SCIRE",,"0x28a4","10-0",,"w"
"SCILV0",,"0x28a8","7-0",,"w"
"SCILV1",,"0x28ac","7-0",,"w"
"SCILV2",,"0x28b0","7-0",,"w"
"MCIEB",,"0x28b4","10-0",,"rw"
"MCIPD",,"0x28b8","10-0",,"rw"
"MCIRE",,"0x28bc","10-0",,"w"
"VREG",,"0x2c00","9-8",,"rw"
"ARMRST",,"0x2c00","0",,"rw"
"L7",,"0x2d00","7",,"r"
"L6",,"0x2d00","6",,"r"
"L5",,"0x2d00","5",,"r"
"L4",,"0x2d00","4",,"r"
"L3",,"0x2d00","3",,"r"
"L2",,"0x2d00","2",,"r"
"L1",,"0x2d00","1",,"r"
"L0",,"0x2d00","0",,"r"
"RP",,"0x2d04","8",,"w"
"M7",,"0x2d04","7",,"w"
"M6",,"0x2d04","6",,"w"
"M5",,"0x2d04","5",,"w"
"M4",,"0x2d04","4",,"w"
"M3",,"0x2d04","3",,"w"
"M2",,"0x2d04","2",,"w"
"M1",,"0x2d04","1",,"w"
"M0",,"0x2d04","0",,"w"

1 name part address register_bits argument_bits rw
2 MONO 0x2800 15 w
3 MEM8MB 0x2800 9 w
4 DAC18B 0x2800 8 w
5 VER 0x2800 7-4 r
6 MVOL 0x2800 3-0 w
7 TESTB0 0x2804 15
8 RBL 0x2804 14-13 w
9 RBP 0x2804 11-0 22-11 w
10 MOFUL 0x2808 12 r
11 MOEMP 0x2808 11 r
12 MIOVF 0x2808 10 r
13 MIFUL 0x2808 9 r
14 MIEMP 0x2808 8 r
15 MIBUF 0x2808 7-0 r
16 AFSET AFSEL 0x280c 14 w
17 MSLC 0x280c 13-8 w
18 MOBUF 0x280c 7-0 w
19 LP 0x2810 15 r
20 SGC 0x2810 14 r
21 EG 0x2810 12-0 r
22 CA 0x2814 15-0 r
23 DMEA 0 0x2880 15-9 22-16 w
24 TSCD 0x2880 7-5
25 T 0x2880 4
26 MRWINH 0x2880 3-0 w
27 DMEA 1 0x2884 15-2 15-2 w
28 DGATE 0x2888 15 rw
29 DRGA 0x2888 14-2 14-2 w
30 DDIR 0x288c 15 rw
31 DLG 0x288c 14-2 14-2 w
32 DEXE 0x288c 0 rw
33 TACTL 0x2890 10-8 w
34 TIMA 0x2890 7-0 w
35 TBCTL 0x2894 10-8 w
36 TIMB 0x2894 7-0 w
37 TCCTL 0x2898 10-8 w
38 TIMC 0x2898 7-0 w
39 SCIEB 0x289c 10-0 rw
40 SCIPD 0x28a0 10-0 rw
41 SCIRE 0x28a4 10-0 w
42 SCILV0 0x28a8 7-0 w
43 SCILV1 0x28ac 7-0 w
44 SCILV2 0x28b0 7-0 w
45 MCIEB 0x28b4 10-0 rw
46 MCIPB MCIPD 0x28b8 10-0 rw
47 MCIRE 0x28bc 10-0 w
48 VREG 0x2c00 9-8 rw
49 ARMRST 0x2c00 0 rw
50 L7 0x2d00 7 r
51 L6 0x2d00 6 r
52 L5 0x2d00 5 r
53 L4 0x2d00 4 r
54 L3 0x2d00 3 r
55 L2 0x2d00 2 r
56 L1 0x2d00 1 r
57 L0 0x2d00 0 r
58 RP 0x2d04 8 w
59 M7 0x2d04 7 w
60 M6 0x2d04 6 w
61 M5 0x2d04 5 w
62 M4 0x2d04 4 w
63 M3 0x2d04 3 w
64 M2 0x2d04 2 w
65 M1 0x2d04 1 w
66 M0 0x2d04 0 w

Binary file not shown.

View File

@ -1,3 +1,3 @@
"name","part","address","register_bits","argument_bits"
"EFDSL",,"0x0000","11-8",
"EFPAN",,"0x0000","4-0",
"name","part","address","register_bits","argument_bits","rw"
"EFDSL",,"0x0000","11-8",,"rw"
"EFPAN",,"0x0000","4-0",,"rw"

1 name part address register_bits argument_bits rw
2 EFDSL 0x0000 11-8 rw
3 EFPAN 0x0000 4-0 rw

Binary file not shown.

View File

@ -1,4 +1,4 @@
"name","part","address","register_bits","argument_bits"
"RTC","0","0x0000","15-0","31-16"
"RTC","1","0x0004","15-0","15-0"
"EN",,"0x0008","0",
"name","part","address","register_bits","argument_bits","rw"
"RTC","0","0x0000","15-0","31-16","rw"
"RTC","1","0x0004","15-0","15-0","rw"
"EN",,"0x0008","0",,"w"

1 name part address register_bits argument_bits rw
2 RTC 0 0x0000 15-0 31-16 rw
3 RTC 1 0x0004 15-0 15-0 rw
4 EN 0x0008 0 w

Binary file not shown.

View File

@ -15,6 +15,7 @@ class Part:
@dataclass
class Register:
name: str
rw: set[str]
parts: list[Part]
def parse_slice(s):
@ -51,7 +52,8 @@ def parse_row(row):
register_bits,
argument_bits,
)
return name, part
rw = set(row["rw"])
return name, rw, part
def group_parts(rows, address_increment):
by_name: dict[str, Register] = {}
@ -60,17 +62,20 @@ def group_parts(rows, address_increment):
register_order = []
addresses = []
last_address = 0
parts_by_register_name: dict[str, list] = defaultdict(list)
for row in rows:
name, part = parse_row(row)
name, rw, part = parse_row(row)
if rw == set():
continue
assert part.address >= last_address, row
assert part.address % address_increment == 0, row
last_address = part.address
if part.address not in set(a[0] for a in addresses):
addresses.append((part.address, [name]))
addresses.append((part.address, [(name, part.index)]))
else:
assert addresses[-1][0] == part.address
addresses[-1][1].append(name)
addresses[-1][1].append((name, part.index))
bits = slice_bits(part.register_bits)
assert bits.intersection(register_bit_alloc[part.address]) == set(), row
@ -82,24 +87,33 @@ def group_parts(rows, address_increment):
if name not in by_name:
assert part.index == 0, row
register = Register(name, [part])
register = Register(name, rw, [part])
by_name[name] = register
register_order.append(register)
else:
assert len(by_name[name].parts) == part.index
by_name[name].parts.append(part)
return addresses, register_order
parts_by_register_name[name].append(part.index)
return addresses, register_order, parts_by_register_name
def format_reg(address):
return f"reg_{address:04x}"
def render_struct_fields(struct_size, addresses, address_increment, c_type, c_type_size):
def format_reg_friendly_name(names, parts_by_register_name):
return "_".join(
name.lower() if len(parts_by_register_name[name]) == 1
else f"{name.lower()}{part_index}"
for name, part_index in names
)
def render_struct_fields(struct_size, addresses, address_increment, c_type, c_type_size, parts_by_register_name):
assert address_increment >= c_type_size
assert address_increment % c_type_size == 0
next_address = None
pad_index = 0
for address, _ in addresses:
for address, names in addresses:
if next_address is None:
next_address = address
if address != next_address:
@ -108,7 +122,12 @@ def render_struct_fields(struct_size, addresses, address_increment, c_type, c_ty
yield f"const {c_type} _pad{pad_index}[{padding}];"
pad_index += 1
# render the actual field
yield "union {"
yield f"{c_type} {format_reg(address)};"
yield f"{c_type} {format_reg_friendly_name(names, parts_by_register_name)};"
yield "};"
if c_type_size < address_increment:
padding = (address_increment - c_type_size) // c_type_size
yield f"const {c_type} _pad{pad_index}[{padding}];"
@ -136,17 +155,23 @@ def mask_from_bits(bit_slice):
mask = 2 ** ((h - l) + 1) - 1
return mask
def part_get_expression(part):
def part_get_expression(part, value=None):
_, reg_end = part.register_bits
_, arg_end = part.argument_bits
arg_mask = mask_from_bits(part.argument_bits)
return f"(static_cast<uint32_t>(({format_reg(part.address)} >> {reg_end}) & {hex(arg_mask)}) << {arg_end})"
value_expression = format_reg(part.address) if value is None else value
return f"(static_cast<uint32_t>(({value_expression} >> {reg_end}) & {hex(arg_mask)}) << {arg_end})"
def part_set_expression(part):
_, reg_end = part.register_bits
_, arg_end = part.argument_bits
arg_mask = mask_from_bits(part.argument_bits)
expression = f"(((v >> {arg_end}) & {hex(arg_mask)}) << {reg_end})"
return expression
def part_set_statement(addresses_dict, c_type_real_size, part):
_, reg_end = part.register_bits
_, arg_end = part.argument_bits
arg_mask = mask_from_bits(part.argument_bits)
assignment = f"{format_reg(part.address)} = (((v >> {arg_end}) & {hex(arg_mask)}) << {reg_end})"
assignment = f"{format_reg(part.address)} = {part_set_expression(part)}"
if len(addresses_dict[part.address]) > 1:
reg_mask = mask_from_bits(part.register_bits) << reg_end
inverse_mask = (~reg_mask) & ((2 ** (c_type_real_size * 8)) - 1)
@ -169,14 +194,40 @@ def render_struct_accessors(addresses_dict, c_type, c_type_real_size, registers)
yield "}"
yield ""
def render_struct(struct_name, struct_size, addresses, address_increment, c_type, c_type_size, c_type_real_size, registers):
def render_bits(addresses_dict, registers, parts_by_register_name):
parts_by_address = defaultdict(list)
for register in registers:
for part in register.parts:
parts_by_address[part.address].append((register, part))
for address, names in addresses_dict.items():
namespace = format_reg_friendly_name(names, parts_by_register_name)
yield f"namespace {namespace} {{"
for register, part in parts_by_address[address]:
if 'w' in register.rw:
arg = "v"
expression = part_set_expression(part)
elif 'r' in register.rw:
arg = "reg"
expression = part_get_expression(part, arg)
else:
continue
yield f"constexpr uint32_t {register.name}(const uint32_t {arg}) {{ return {expression}; }}";
yield "}"
def render_struct(struct_name, struct_size, addresses, address_increment, c_type, c_type_size, c_type_real_size, registers, parts_by_register_name):
yield f"struct {struct_name} {{"
yield from render_struct_fields(struct_size, addresses, address_increment, c_type, c_type_size)
yield from render_struct_fields(struct_size, addresses, address_increment, c_type, c_type_size, parts_by_register_name)
yield ""
addresses_dict = dict(addresses)
yield from render_struct_accessors(addresses_dict, c_type, c_type_real_size, registers)
yield "};"
yield from render_struct_static_assertions(struct_name, struct_size, addresses, address_increment)
yield ""
yield f"namespace aica {{"
yield from render_bits(addresses_dict, registers, parts_by_register_name)
yield "}"
def header():
yield '#include <stdint.h>'
@ -194,8 +245,8 @@ if __name__ == "__main__":
c_type = "reg32"
c_type_size = 4
c_type_real_size = 2
addresses, registers = group_parts(rows, address_increment)
addresses, registers, parts_by_register_name = group_parts(rows, address_increment)
render, out = renderer()
render(header())
render(render_struct(struct_name, struct_size, addresses, address_increment, c_type, c_type_size, c_type_real_size, registers))
render(render_struct(struct_name, struct_size, addresses, address_increment, c_type, c_type_size, c_type_real_size, registers, parts_by_register_name))
sys.stdout.write(out.getvalue())