From 13966f9b02ea53eff2e9eea7651204fe7395fae0 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 4 Oct 2020 22:31:00 +0800 Subject: [PATCH] initial commit Signed-off-by: Sean Cross --- .gitignore | 2 + Cargo.toml | 10 + examples/soc.svd | 4742 ++++++++++++++++++++++++++++++++++++++++++++++ src/generate.rs | 635 +++++++ src/lib.rs | 10 + src/main.rs | 10 + 6 files changed, 5409 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 examples/soc.svd create mode 100644 src/generate.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9d5b650 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "utra" +version = "0.1.0" +authors = ["Sean Cross "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +quick-xml = "0.19" diff --git a/examples/soc.svd b/examples/soc.svd new file mode 100644 index 0000000..84655cb --- /dev/null +++ b/examples/soc.svd @@ -0,0 +1,4742 @@ + + + + litex + JTAG + + 8 + 32 + 32 + read-write + 0x00000000 + 0xFFFFFFFF + + + + CTRL + 0xF0000000 + CTRL + + + RESET + + 0x0000 + 0x00 + 32 + read-write + + + reset + 0 + [0:0] + 0 + + + + + SCRATCH + + 0x0004 + 0x12345678 + 32 + read-write + + + scratch + 31 + [31:0] + 0 + + + + + BUS_ERRORS + + 0x0008 + 0x00 + 32 + read-only + + + bus_errors + 31 + [31:0] + 0 + + + + + + 0 + 0xc + registers + + + + IDENTIFIER_MEM + 0xF0002000 + IDENTIFIER_MEM + + + IDENTIFIER_MEM + + 0x0000 + 0x00 + 32 + read-write + + + identifier_mem + 7 + [7:0] + 0 + + + + + + 0 + 0x4 + registers + + + + UART_PHY + 0xF0003000 + UART_PHY + + + TUNING_WORD + 0x0000 + 0x4b7f5a + 32 + read-write + + + tuning_word + 31 + [31:0] + 0 + + + + + + 0 + 0x4 + registers + + + + UART + 0xF0004000 + UART + + + RXTX + 0x0000 + 0x00 + 32 + read-write + + + rxtx + 7 + [7:0] + 0 + + + + + TXFULL + 0x0004 + 0x00 + 32 + read-only + + + txfull + 0 + [0:0] + 0 + + + + + RXEMPTY + 0x0008 + 0x00 + 32 + read-only + + + rxempty + 0 + [0:0] + 0 + + + + + EV_STATUS + 0x000c + 0x00 + 32 + read-write + + + status + 1 + [1:0] + 0 + + + + + EV_PENDING + 0x0010 + 0x00 + 32 + read-write + + + pending + 1 + [1:0] + 0 + + + + + EV_ENABLE + 0x0014 + 0x00 + 32 + read-write + + + enable + 1 + [1:0] + 0 + + + + + TXEMPTY + 0x0018 + 0x00 + 32 + read-only + + + txempty + 0 + [0:0] + 0 + + + + + RXFULL + 0x001c + 0x00 + 32 + read-only + + + rxfull + 0 + [0:0] + 0 + + + + + + 0 + 0x20 + registers + + + uart + 0 + + + + TIMER0 + 0xF0005000 + TIMER0 + + + LOAD + + 0x0000 + 0x00 + 32 + read-write + + + load + 31 + [31:0] + 0 + + + + + RELOAD + + 0x0004 + 0x00 + 32 + read-write + + + reload + 31 + [31:0] + 0 + + + + + EN + + 0x0008 + 0x00 + 32 + read-write + + + en + 0 + [0:0] + 0 + + + + + UPDATE_VALUE + + 0x000c + 0x00 + 32 + read-write + + + update_value + 0 + [0:0] + 0 + + + + + VALUE + + 0x0010 + 0x00 + 32 + read-only + + + value + 31 + [31:0] + 0 + + + + + EV_STATUS + 0x0014 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x0018 + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x001c + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + + 0 + 0x20 + registers + + + timer0 + 1 + + + + REBOOT + 0xF0006000 + REBOOT + + + CTRL + 0x0000 + 0x00 + 32 + read-write + + + ctrl + 7 + [7:0] + 0 + + + + + ADDR + 0x0004 + 0x00 + 32 + read-write + + + addr + 31 + [31:0] + 0 + + + + + + 0 + 0x8 + registers + + + + CRG + 0xF0007000 + CRG + + + MMCM_DRP_RESET + 0x0000 + 0x00 + 32 + read-write + + + mmcm_drp_reset + 0 + [0:0] + 0 + + + + + MMCM_DRP_LOCKED + 0x0004 + 0x00 + 32 + read-only + + + mmcm_drp_locked + 0 + [0:0] + 0 + + + + + MMCM_DRP_READ + 0x0008 + 0x00 + 32 + read-write + + + mmcm_drp_read + 0 + [0:0] + 0 + + + + + MMCM_DRP_WRITE + 0x000c + 0x00 + 32 + read-write + + + mmcm_drp_write + 0 + [0:0] + 0 + + + + + MMCM_DRP_DRDY + 0x0010 + 0x00 + 32 + read-only + + + mmcm_drp_drdy + 0 + [0:0] + 0 + + + + + MMCM_DRP_ADR + 0x0014 + 0x00 + 32 + read-write + + + mmcm_drp_adr + 6 + [6:0] + 0 + + + + + MMCM_DRP_DAT_W + 0x0018 + 0x00 + 32 + read-write + + + mmcm_drp_dat_w + 15 + [15:0] + 0 + + + + + MMCM_DRP_DAT_R + 0x001c + 0x00 + 32 + read-only + + + mmcm_drp_dat_r + 15 + [15:0] + 0 + + + + + + 0 + 0x20 + registers + + + + INFO + 0xF0008000 + INFO + + + DNA_ID1 + + 0x0000 + 0x00 + 32 + read-only + + + dna_id + 31 + [31:0] + 0 + + + + + DNA_ID0 + + 0x0004 + 0x00 + 32 + read-only + + + dna_id + 31 + [31:0] + 0 + + + + + GIT_MAJOR + + 0x0008 + 0x00 + 32 + read-only + + + git_major + 7 + [7:0] + 0 + + + + + GIT_MINOR + + 0x000c + 0x00 + 32 + read-only + + + git_minor + 7 + [7:0] + 0 + + + + + GIT_REVISION + + 0x0010 + 0x00 + 32 + read-only + + + git_revision + 7 + [7:0] + 0 + + + + + GIT_GITREV + + 0x0014 + 0x00 + 32 + read-only + + + git_gitrev + 31 + [31:0] + 0 + + + + + GIT_GITEXTRA + + 0x0018 + 0x00 + 32 + read-only + + + git_gitextra + 9 + [9:0] + 0 + + + + + GIT_DIRTY + 0x001c + 0x00 + 32 + read-only + + + dirty + 0 + [0:0] + 0 + + + + + + PLATFORM_PLATFORM1 + + 0x0020 + 0x00 + 32 + read-only + + + platform_platform + 31 + [31:0] + 0 + + + + + PLATFORM_PLATFORM0 + + 0x0024 + 0x00 + 32 + read-only + + + platform_platform + 31 + [31:0] + 0 + + + + + PLATFORM_TARGET1 + + 0x0028 + 0x00 + 32 + read-only + + + platform_target + 31 + [31:0] + 0 + + + + + PLATFORM_TARGET0 + + 0x002c + 0x00 + 32 + read-only + + + platform_target + 31 + [31:0] + 0 + + + + + XADC_TEMPERATURE + + 0x0030 + 0x00 + 32 + read-only + + + xadc_temperature + 11 + [11:0] + 0 + + + + + XADC_VCCINT + + 0x0034 + 0x00 + 32 + read-only + + + xadc_vccint + 11 + [11:0] + 0 + + + + + XADC_VCCAUX + + 0x0038 + 0x00 + 32 + read-only + + + xadc_vccaux + 11 + [11:0] + 0 + + + + + XADC_VCCBRAM + + 0x003c + 0x00 + 32 + read-only + + + xadc_vccbram + 11 + [11:0] + 0 + + + + + XADC_EOC + + 0x0040 + 0x00 + 32 + read-only + + + xadc_eoc + 0 + [0:0] + 0 + + + + + XADC_EOS + + 0x0044 + 0x00 + 32 + read-only + + + xadc_eos + 0 + [0:0] + 0 + + + + + XADC_DRP_ENABLE + 0x0048 + 0x00 + 32 + read-write + + + xadc_drp_enable + 0 + [0:0] + 0 + + + + + XADC_DRP_READ + 0x004c + 0x00 + 32 + read-write + + + xadc_drp_read + 0 + [0:0] + 0 + + + + + XADC_DRP_WRITE + 0x0050 + 0x00 + 32 + read-write + + + xadc_drp_write + 0 + [0:0] + 0 + + + + + XADC_DRP_DRDY + 0x0054 + 0x00 + 32 + read-only + + + xadc_drp_drdy + 0 + [0:0] + 0 + + + + + XADC_DRP_ADR + 0x0058 + 0x00 + 32 + read-write + + + xadc_drp_adr + 6 + [6:0] + 0 + + + + + XADC_DRP_DAT_W + 0x005c + 0x00 + 32 + read-write + + + xadc_drp_dat_w + 15 + [15:0] + 0 + + + + + XADC_DRP_DAT_R + 0x0060 + 0x00 + 32 + read-only + + + xadc_drp_dat_r + 15 + [15:0] + 0 + + + + + + 0 + 0x64 + registers + + + + SRAM_EXT + 0xF0009000 + SRAM_EXT + + + CONFIG_STATUS + 0x0000 + 0x00 + 32 + read-only + + + mode + 31 + [31:0] + 0 + + + + + + READ_CONFIG + 0x0004 + 0x00 + 32 + read-write + + + trigger + 0 + [0:0] + 0 + + + + + + + 0 + 0x8 + registers + + + + MEMLCD + 0xF000A000 + MEMLCD + + + COMMAND + 0x0000 + 0x00 + 32 + read-write + + + UpdateDirty + 0 + [0:0] + 0 + + + + UpdateAll + 1 + [1:1] + 1 + + + + + + BUSY + + 0x0004 + 0x00 + 32 + read-only + + + busy + 0 + [0:0] + 0 + + + + + PRESCALER + + 0x0008 + 0x63 + 32 + read-write + + + prescaler + 7 + [7:0] + 0 + + + + + EV_STATUS + 0x000c + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x0010 + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x0014 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + + 0 + 0x18 + registers + + + + COM + 0xF000B000 + COM + + + TX + + 0x0000 + 0x00 + 32 + read-write + + + tx + 15 + [15:0] + 0 + + + + + RX + + 0x0004 + 0x00 + 32 + read-only + + + rx + 15 + [15:0] + 0 + + + + + CONTROL + 0x0008 + 0x00 + 32 + read-write + + + intena + 0 + [0:0] + 0 + + + + + + STATUS + 0x000c + 0x00 + 32 + read-only + + + tip + 0 + [0:0] + 0 + + + + + + EV_STATUS + 0x0010 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x0014 + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x0018 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + + 0 + 0x1c + registers + + + + I2C + 0xF000C000 + I2C + + + PRESCALE + + 0x0000 + 0xffff + 32 + read-write + + + prescale + 15 + [15:0] + 0 + + + + + CONTROL + 0x0004 + 0x00 + 32 + read-write + + + Resvd + 5 + [5:0] + 0 + + + + IEN + 6 + [6:6] + 6 + + + + EN + 7 + [7:7] + 7 + + + + + + TXR + + 0x0008 + 0x00 + 32 + read-write + + + txr + 7 + [7:0] + 0 + + + + + RXR + + 0x000c + 0x00 + 32 + read-only + + + rxr + 7 + [7:0] + 0 + + + + + COMMAND + 0x0010 + 0x00 + 32 + read-write + + + IACK + 0 + [0:0] + 0 + + + + Resvd + 2 + [2:1] + 1 + + + + ACK + 3 + [3:3] + 3 + + + + WR + 4 + [4:4] + 4 + + + + RD + 5 + [5:5] + 5 + + + + STO + 6 + [6:6] + 6 + + + + STA + 7 + [7:7] + 7 + + + + + + STATUS + 0x0014 + 0x00 + 32 + read-only + + + IF + 0 + [0:0] + 0 + + + + TIP + 1 + [1:1] + 1 + + + + Resvd + 4 + [4:2] + 2 + + + + ArbLost + 5 + [5:5] + 5 + + + + Busy + 6 + [6:6] + 6 + + + + RxACK + 7 + [7:7] + 7 + + + + + + EV_STATUS + 0x0018 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x001c + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x0020 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + + 0 + 0x24 + registers + + + i2c + 2 + + + + BTEVENTS + 0xF000D000 + BTEVENTS + + + EV_STATUS + 0x0000 + 0x00 + 32 + read-write + + + status + 1 + [1:0] + 0 + + + + + EV_PENDING + 0x0004 + 0x00 + 32 + read-write + + + pending + 1 + [1:0] + 0 + + + + + EV_ENABLE + 0x0008 + 0x00 + 32 + read-write + + + enable + 1 + [1:0] + 0 + + + + + + 0 + 0xc + registers + + + btevents + 3 + + + + MESSIBLE + 0xF000E000 + MESSIBLE + + + IN + + 0x0000 + 0x00 + 32 + read-write + + + in + 7 + [7:0] + 0 + + + + + OUT + + 0x0004 + 0x00 + 32 + read-only + + + out + 7 + [7:0] + 0 + + + + + STATUS + 0x0008 + 0x00 + 32 + read-only + + + full + 0 + [0:0] + 0 + + + + have + 1 + [1:1] + 1 + + + + + + + 0 + 0xc + registers + + + + TICKTIMER + 0xF000F000 + TICKTIMER + + + CONTROL + 0x0000 + 0x00 + 32 + read-write + + + reset + 0 + [0:0] + 0 + + + + pause + 1 + [1:1] + 1 + + + + + + TIME1 + + 0x0004 + 0x00 + 32 + read-only + + + time + 31 + [31:0] + 0 + + + + + TIME0 + + 0x0008 + 0x00 + 32 + read-only + + + time + 31 + [31:0] + 0 + + + + + + 0 + 0xc + registers + + + + POWER + 0xF0010000 + POWER + + + POWER + 0x0000 + 0x0a + 32 + read-write + + + audio + 0 + [0:0] + 0 + + + + self + 1 + [1:1] + 1 + + + + ec_snoop + 2 + [2:2] + 2 + + + + state + 4 + [4:3] + 3 + + + + noisebias + 5 + [5:5] + 5 + + + + noise + 7 + [7:6] + 6 + + + + reset_ec + 8 + [8:8] + 8 + + + + up5k_on + 9 + [9:9] + 9 + + + + boostmode + 10 + [10:10] + 10 + + + + selfdestruct + 11 + [11:11] + 11 + + + + + + VIBE + + 0x0004 + 0x00 + 32 + read-write + + + vibe + 0 + [0:0] + 0 + + + + + + EV_STATUS + 0x0008 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x000c + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x0010 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + + 0 + 0x14 + registers + + + + SPINOR + 0xF0011000 + SPINOR + + + CONFIG + 0x0000 + 0x0a + 32 + read-write + + + dummy + 4 + [4:0] + 0 + + + + + + DELAY_CONFIG + 0x0004 + 0x1f + 32 + read-write + + + d + 4 + [4:0] + 0 + + + + load + 5 + [5:5] + 5 + + + + + + DELAY_STATUS + 0x0008 + 0x00 + 32 + read-only + + + q + 4 + [4:0] + 0 + + + + + + COMMAND + + 0x000c + 0x00 + 32 + read-write + + + wakeup + 0 + [0:0] + 0 + + + + sector_erase + 1 + [1:1] + 1 + + + + + + SECTOR + + 0x0010 + 0x00 + 32 + read-write + + + sector + 31 + [31:0] + 0 + + + + + + STATUS + + 0x0014 + 0x00 + 32 + read-only + + + wip + 0 + [0:0] + 0 + + + + + + EV_STATUS + 0x0018 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x001c + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x0020 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + ECC_ADDRESS + 0x0024 + 0x00 + 32 + read-only + + + ecc_address + 31 + [31:0] + 0 + + + + + + ECC_STATUS + 0x0028 + 0x00 + 32 + read-only + + + ecc_error + 0 + [0:0] + 0 + + + + ecc_overflow + 1 + [1:1] + 1 + + + + + + + 0 + 0x2c + registers + + + + KEYBOARD + 0xF0012000 + KEYBOARD + + + ROW0DAT + + 0x0000 + 0x00 + 32 + read-only + + + row0dat + 9 + [9:0] + 0 + + + + + ROW1DAT + + 0x0004 + 0x00 + 32 + read-only + + + row1dat + 9 + [9:0] + 0 + + + + + ROW2DAT + + 0x0008 + 0x00 + 32 + read-only + + + row2dat + 9 + [9:0] + 0 + + + + + ROW3DAT + + 0x000c + 0x00 + 32 + read-only + + + row3dat + 9 + [9:0] + 0 + + + + + ROW4DAT + + 0x0010 + 0x00 + 32 + read-only + + + row4dat + 9 + [9:0] + 0 + + + + + ROW5DAT + + 0x0014 + 0x00 + 32 + read-only + + + row5dat + 9 + [9:0] + 0 + + + + + ROW6DAT + + 0x0018 + 0x00 + 32 + read-only + + + row6dat + 9 + [9:0] + 0 + + + + + ROW7DAT + + 0x001c + 0x00 + 32 + read-only + + + row7dat + 9 + [9:0] + 0 + + + + + ROW8DAT + + 0x0020 + 0x00 + 32 + read-only + + + row8dat + 9 + [9:0] + 0 + + + + + EV_STATUS + 0x0024 + 0x00 + 32 + read-write + + + status + 0 + [0:0] + 0 + + + + + EV_PENDING + 0x0028 + 0x00 + 32 + read-write + + + pending + 0 + [0:0] + 0 + + + + + EV_ENABLE + 0x002c + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + + ROWCHANGE + + 0x0030 + 0x00 + 32 + read-only + + + rowchange + 8 + [8:0] + 0 + + + + + + 0 + 0x34 + registers + + + keyboard + 4 + + + + GPIO + 0xF0013000 + GPIO + + + OUTPUT + + 0x0000 + 0x00 + 32 + read-write + + + output + 5 + [5:0] + 0 + + + + + INPUT + + 0x0004 + 0x00 + 32 + read-only + + + input + 5 + [5:0] + 0 + + + + + DRIVE + + 0x0008 + 0x00 + 32 + read-write + + + drive + 5 + [5:0] + 0 + + + + + INTENA + + 0x000c + 0x00 + 32 + read-only + + + intena + 5 + [5:0] + 0 + + + + + INTPOL + + 0x0010 + 0x00 + 32 + read-only + + + intpol + 5 + [5:0] + 0 + + + + + EV_STATUS + 0x0014 + 0x00 + 32 + read-write + + + status + 5 + [5:0] + 0 + + + + + EV_PENDING + 0x0018 + 0x00 + 32 + read-write + + + pending + 5 + [5:0] + 0 + + + + + EV_ENABLE + 0x001c + 0x00 + 32 + read-write + + + enable + 5 + [5:0] + 0 + + + + + + 0 + 0x20 + registers + + + gpio + 5 + + + + SEED + 0xF0014000 + SEED + + + SEED1 + + 0x0000 + 0x64f83336 + 32 + read-only + + + seed + 31 + [31:0] + 0 + + + + + SEED0 + + 0x0004 + 0x60e6ef3 + 32 + read-only + + + seed + 31 + [31:0] + 0 + + + + + + 0 + 0x8 + registers + + + + ROMTEST + 0xF0015000 + ROMTEST + + + ADDRESS + + 0x0000 + 0x00 + 32 + read-write + + + address + 7 + [7:0] + 0 + + + + + DATA + + 0x0004 + 0x00 + 32 + read-only + + + data + 31 + [31:0] + 0 + + + + + + 0 + 0x8 + registers + + + + AUDIO + 0xF0016000 + AUDIO + + + EV_STATUS + 0x0000 + 0x00 + 32 + read-write + + + status + 3 + [3:0] + 0 + + + + + EV_PENDING + 0x0004 + 0x00 + 32 + read-write + + + pending + 3 + [3:0] + 0 + + + + + EV_ENABLE + 0x0008 + 0x00 + 32 + read-write + + + enable + 3 + [3:0] + 0 + + + + + RX_CTL + + 0x000c + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + reset + 1 + [1:1] + 1 + + + + + + RX_STAT + + 0x0010 + 0x80000000 + 32 + read-only + + + overflow + 0 + [0:0] + 0 + + + + underflow + 1 + [1:1] + 1 + + + + dataready + 2 + [2:2] + 2 + + + + empty + 3 + [3:3] + 3 + + + + wrcount + 12 + [12:4] + 4 + + + + rdcount + 21 + [21:13] + 13 + + + + fifo_depth + 30 + [30:22] + 22 + + + + concatenate_channels + 31 + [31:31] + 31 + + + + + + RX_CONF + + 0x0014 + 0xac4442 + 32 + read-only + + + format + 1 + [1:0] + 0 + + + + sample_width + 7 + [7:2] + 2 + + + + lrck_freq + 31 + [31:8] + 8 + + + + + + TX_CTL + + 0x0018 + 0x00 + 32 + read-write + + + enable + 0 + [0:0] + 0 + + + + reset + 1 + [1:1] + 1 + + + + + + TX_STAT + + 0x001c + 0x1000000 + 32 + read-only + + + overflow + 0 + [0:0] + 0 + + + + underflow + 1 + [1:1] + 1 + + + + free + 2 + [2:2] + 2 + + + + almostfull + 3 + [3:3] + 3 + + + + full + 4 + [4:4] + 4 + + + + empty + 5 + [5:5] + 5 + + + + wrcount + 14 + [14:6] + 6 + + + + rdcount + 23 + [23:15] + 15 + + + + concatenate_channels + 24 + [24:24] + 24 + + + + + + TX_CONF + + 0x0020 + 0xac4442 + 32 + read-only + + + format + 1 + [1:0] + 0 + + + + sample_width + 7 + [7:2] + 2 + + + + lrck_freq + 31 + [31:8] + 8 + + + + + + + 0 + 0x24 + registers + + + audio + 6 + + + + TRNG_OSC + 0xF0017000 + TRNG_OSC + + + CTL + 0x0000 + 0x2000192 + 32 + read-write + + + ena + 0 + [0:0] + 0 + + + + gang + 1 + [1:1] + 1 + + + + dwell + 21 + [21:2] + 2 + + + + delay + 31 + [31:22] + 22 + + + + + + RAND + 0x0004 + 0xdeadbeef + 32 + read-only + + + rand + 31 + [31:0] + 0 + + + + + + STATUS + 0x0008 + 0x00 + 32 + read-only + + + fresh + 0 + [0:0] + 0 + + + + + + + 0 + 0xc + registers + + + + AES + 0xF0018000 + AES + + + KEY_0_Q + 0x0000 + 0x00 + 32 + read-write + + + key_0 + 31 + [31:0] + 0 + + + + + + KEY_1_Q + 0x0004 + 0x00 + 32 + read-write + + + key_1 + 31 + [31:0] + 0 + + + + + + KEY_2_Q + 0x0008 + 0x00 + 32 + read-write + + + key_2 + 31 + [31:0] + 0 + + + + + + KEY_3_Q + 0x000c + 0x00 + 32 + read-write + + + key_3 + 31 + [31:0] + 0 + + + + + + KEY_4_Q + 0x0010 + 0x00 + 32 + read-write + + + key_4 + 31 + [31:0] + 0 + + + + + + KEY_5_Q + 0x0014 + 0x00 + 32 + read-write + + + key_5 + 31 + [31:0] + 0 + + + + + + KEY_6_Q + 0x0018 + 0x00 + 32 + read-write + + + key_6 + 31 + [31:0] + 0 + + + + + + KEY_7_Q + 0x001c + 0x00 + 32 + read-write + + + key_7 + 31 + [31:0] + 0 + + + + + + DATAOUT_0 + 0x0020 + 0x00 + 32 + read-only + + + data_0 + 31 + [31:0] + 0 + + + + + + DATAOUT_1 + 0x0024 + 0x00 + 32 + read-only + + + data_1 + 31 + [31:0] + 0 + + + + + + DATAOUT_2 + 0x0028 + 0x00 + 32 + read-only + + + data_2 + 31 + [31:0] + 0 + + + + + + DATAOUT_3 + 0x002c + 0x00 + 32 + read-only + + + data_3 + 31 + [31:0] + 0 + + + + + + DATAIN_0 + 0x0030 + 0x00 + 32 + read-write + + + data_0 + 31 + [31:0] + 0 + + + + + + DATAIN_1 + 0x0034 + 0x00 + 32 + read-write + + + data_1 + 31 + [31:0] + 0 + + + + + + DATAIN_2 + 0x0038 + 0x00 + 32 + read-write + + + data_2 + 31 + [31:0] + 0 + + + + + + DATAIN_3 + 0x003c + 0x00 + 32 + read-write + + + data_3 + 31 + [31:0] + 0 + + + + + + IV_0 + 0x0040 + 0x00 + 32 + read-write + + + iv_0 + 31 + [31:0] + 0 + + + + + + IV_1 + 0x0044 + 0x00 + 32 + read-write + + + iv_1 + 31 + [31:0] + 0 + + + + + + IV_2 + 0x0048 + 0x00 + 32 + read-write + + + iv_2 + 31 + [31:0] + 0 + + + + + + IV_3 + 0x004c + 0x00 + 32 + read-write + + + iv_3 + 31 + [31:0] + 0 + + + + + + CTRL + 0x0050 + 0x00 + 32 + read-write + + + mode + 2 + [2:0] + 0 + + + + key_len + 5 + [5:3] + 3 + + + + manual_operation + 6 + [6:6] + 6 + + + + operation + 7 + [7:7] + 7 + + + + + + STATUS + 0x0054 + 0x09 + 32 + read-only + + + idle + 0 + [0:0] + 0 + + + + stall + 1 + [1:1] + 1 + + + + output_valid + 2 + [2:2] + 2 + + + + input_ready + 3 + [3:3] + 3 + + + + operation_rbk + 4 + [4:4] + 4 + + + + mode_rbk + 7 + [7:5] + 5 + + + + key_len_rbk + 10 + [10:8] + 8 + + + + manual_operation_rbk + 11 + [11:11] + 11 + + + + + + TRIGGER + 0x0058 + 0x00 + 32 + read-write + + + start + 0 + [0:0] + 0 + + + + key_clear + 1 + [1:1] + 1 + + + + iv_clear + 2 + [2:2] + 2 + + + + data_in_clear + 3 + [3:3] + 3 + + + + data_out_clear + 4 + [4:4] + 4 + + + + prng_reseed + 5 + [5:5] + 5 + + + + + + + 0 + 0x5c + registers + + + + SHA2 + 0xF0019000 + SHA2 + + + KEY0 + + 0x0000 + 0x00 + 32 + read-write + + + key0 + 31 + [31:0] + 0 + + + + + KEY1 + + 0x0004 + 0x00 + 32 + read-write + + + key1 + 31 + [31:0] + 0 + + + + + KEY2 + + 0x0008 + 0x00 + 32 + read-write + + + key2 + 31 + [31:0] + 0 + + + + + KEY3 + + 0x000c + 0x00 + 32 + read-write + + + key3 + 31 + [31:0] + 0 + + + + + KEY4 + + 0x0010 + 0x00 + 32 + read-write + + + key4 + 31 + [31:0] + 0 + + + + + KEY5 + + 0x0014 + 0x00 + 32 + read-write + + + key5 + 31 + [31:0] + 0 + + + + + KEY6 + + 0x0018 + 0x00 + 32 + read-write + + + key6 + 31 + [31:0] + 0 + + + + + KEY7 + + 0x001c + 0x00 + 32 + read-write + + + key7 + 31 + [31:0] + 0 + + + + + CONFIG + + 0x0020 + 0x00 + 32 + read-write + + + sha_en + 0 + [0:0] + 0 + + + + endian_swap + 1 + [1:1] + 1 + + + + digest_swap + 2 + [2:2] + 2 + + + + hmac_en + 3 + [3:3] + 3 + + + + + + COMMAND + + 0x0024 + 0x00 + 32 + read-write + + + hash_start + 0 + [0:0] + 0 + + + + hash_process + 1 + [1:1] + 1 + + + + + + WIPE + + 0x0028 + 0x00 + 32 + read-write + + + wipe + 31 + [31:0] + 0 + + + + + DIGEST0 + + 0x002c + 0x00 + 32 + read-only + + + digest0 + 31 + [31:0] + 0 + + + + + DIGEST1 + + 0x0030 + 0x00 + 32 + read-only + + + digest1 + 31 + [31:0] + 0 + + + + + DIGEST2 + + 0x0034 + 0x00 + 32 + read-only + + + digest2 + 31 + [31:0] + 0 + + + + + DIGEST3 + + 0x0038 + 0x00 + 32 + read-only + + + digest3 + 31 + [31:0] + 0 + + + + + DIGEST4 + + 0x003c + 0x00 + 32 + read-only + + + digest4 + 31 + [31:0] + 0 + + + + + DIGEST5 + + 0x0040 + 0x00 + 32 + read-only + + + digest5 + 31 + [31:0] + 0 + + + + + DIGEST6 + + 0x0044 + 0x00 + 32 + read-only + + + digest6 + 31 + [31:0] + 0 + + + + + DIGEST7 + + 0x0048 + 0x00 + 32 + read-only + + + digest7 + 31 + [31:0] + 0 + + + + + MSG_LENGTH1 + + 0x004c + 0x00 + 32 + read-only + + + msg_length + 31 + [31:0] + 0 + + + + + MSG_LENGTH0 + + 0x0050 + 0x00 + 32 + read-only + + + msg_length + 31 + [31:0] + 0 + + + + + ERROR_CODE + + 0x0054 + 0x00 + 32 + read-only + + + error_code + 31 + [31:0] + 0 + + + + + EV_STATUS + 0x0058 + 0x00 + 32 + read-write + + + status + 3 + [3:0] + 0 + + + + + EV_PENDING + 0x005c + 0x00 + 32 + read-write + + + pending + 3 + [3:0] + 0 + + + + + EV_ENABLE + 0x0060 + 0x00 + 32 + read-write + + + enable + 3 + [3:0] + 0 + + + + + FIFO + + 0x0064 + 0x00 + 32 + read-only + + + read_count + 9 + [9:0] + 0 + + + + write_count + 19 + [19:10] + 10 + + + + read_error + 20 + [20:20] + 20 + + + + write_error + 21 + [21:21] + 21 + + + + almost_full + 22 + [22:22] + 22 + + + + almost_empty + 23 + [23:23] + 23 + + + + + + + 0 + 0x68 + registers + + + sha2 + 7 + + + + SHA512 + 0xF001A000 + SHA512 + + + CONFIG + + 0x0000 + 0x00 + 32 + read-write + + + sha_en + 0 + [0:0] + 0 + + + + endian_swap + 1 + [1:1] + 1 + + + + digest_swap + 2 + [2:2] + 2 + + + + select_256 + 3 + [3:3] + 3 + + + + + + COMMAND + + 0x0004 + 0x00 + 32 + read-write + + + hash_start + 0 + [0:0] + 0 + + + + hash_process + 1 + [1:1] + 1 + + + + + + DIGEST01 + + 0x0008 + 0x00 + 32 + read-only + + + digest0 + 31 + [31:0] + 0 + + + + + DIGEST00 + + 0x000c + 0x00 + 32 + read-only + + + digest0 + 31 + [31:0] + 0 + + + + + DIGEST11 + + 0x0010 + 0x00 + 32 + read-only + + + digest1 + 31 + [31:0] + 0 + + + + + DIGEST10 + + 0x0014 + 0x00 + 32 + read-only + + + digest1 + 31 + [31:0] + 0 + + + + + DIGEST21 + + 0x0018 + 0x00 + 32 + read-only + + + digest2 + 31 + [31:0] + 0 + + + + + DIGEST20 + + 0x001c + 0x00 + 32 + read-only + + + digest2 + 31 + [31:0] + 0 + + + + + DIGEST31 + + 0x0020 + 0x00 + 32 + read-only + + + digest3 + 31 + [31:0] + 0 + + + + + DIGEST30 + + 0x0024 + 0x00 + 32 + read-only + + + digest3 + 31 + [31:0] + 0 + + + + + DIGEST41 + + 0x0028 + 0x00 + 32 + read-only + + + digest4 + 31 + [31:0] + 0 + + + + + DIGEST40 + + 0x002c + 0x00 + 32 + read-only + + + digest4 + 31 + [31:0] + 0 + + + + + DIGEST51 + + 0x0030 + 0x00 + 32 + read-only + + + digest5 + 31 + [31:0] + 0 + + + + + DIGEST50 + + 0x0034 + 0x00 + 32 + read-only + + + digest5 + 31 + [31:0] + 0 + + + + + DIGEST61 + + 0x0038 + 0x00 + 32 + read-only + + + digest6 + 31 + [31:0] + 0 + + + + + DIGEST60 + + 0x003c + 0x00 + 32 + read-only + + + digest6 + 31 + [31:0] + 0 + + + + + DIGEST71 + + 0x0040 + 0x00 + 32 + read-only + + + digest7 + 31 + [31:0] + 0 + + + + + DIGEST70 + + 0x0044 + 0x00 + 32 + read-only + + + digest7 + 31 + [31:0] + 0 + + + + + MSG_LENGTH1 + + 0x0048 + 0x00 + 32 + read-only + + + msg_length + 31 + [31:0] + 0 + + + + + MSG_LENGTH0 + + 0x004c + 0x00 + 32 + read-only + + + msg_length + 31 + [31:0] + 0 + + + + + EV_STATUS + 0x0050 + 0x00 + 32 + read-write + + + status + 2 + [2:0] + 0 + + + + + EV_PENDING + 0x0054 + 0x00 + 32 + read-write + + + pending + 2 + [2:0] + 0 + + + + + EV_ENABLE + 0x0058 + 0x00 + 32 + read-write + + + enable + 2 + [2:0] + 0 + + + + + FIFO + + 0x005c + 0x00 + 32 + read-only + + + read_count + 8 + [8:0] + 0 + + + + write_count + 17 + [17:9] + 9 + + + + read_error + 18 + [18:18] + 18 + + + + write_error + 19 + [19:19] + 19 + + + + almost_full + 20 + [20:20] + 20 + + + + almost_empty + 21 + [21:21] + 21 + + + + running + 22 + [22:22] + 22 + + + + + + + 0 + 0x60 + registers + + + sha512 + 8 + + + + ENGINE + 0xF001B000 + ENGINE + + + WINDOW + 0x0000 + 0x00 + 32 + read-write + + + window + 3 + [3:0] + 0 + + + + + + MPSTART + 0x0004 + 0x00 + 32 + read-write + + + mpstart + 9 + [9:0] + 0 + + + + + + MPLEN + 0x0008 + 0x00 + 32 + read-write + + + mplen + 9 + [9:0] + 0 + + + + + + CONTROL + 0x000c + 0x00 + 32 + read-write + + + go + 0 + [0:0] + 0 + + + + + + STATUS + 0x0010 + 0x00 + 32 + read-write + + + running + 0 + [0:0] + 0 + + + + mpc + 10 + [10:1] + 1 + + + + + + EV_STATUS + 0x0014 + 0x00 + 32 + read-write + + + status + 1 + [1:0] + 0 + + + + + EV_PENDING + 0x0018 + 0x00 + 32 + read-write + + + pending + 1 + [1:0] + 0 + + + + + EV_ENABLE + 0x001c + 0x00 + 32 + read-write + + + enable + 1 + [1:0] + 0 + + + + + INSTRUCTION + + 0x0020 + 0x00 + 32 + read-only + + + opcode + 5 + [5:0] + 0 + + + + ra + 10 + [10:6] + 6 + + + + ca + 11 + [11:11] + 11 + + + + rb + 16 + [16:12] + 12 + + + + cb + 17 + [17:17] + 17 + + + + wd + 22 + [22:18] + 18 + + + + immediate + 31 + [31:23] + 23 + + + + + + + 0 + 0x24 + registers + + + engine + 9 + + + + JTAG + 0xF001C000 + JTAG + + + NEXT + + 0x0000 + 0x00 + 32 + read-write + + + tdi + 0 + [0:0] + 0 + + + + tms + 1 + [1:1] + 1 + + + + + + TDO + + 0x0004 + 0x00 + 32 + read-only + + + tdo + 0 + [0:0] + 0 + + + + ready + 1 + [1:1] + 1 + + + + + + + 0 + 0x8 + registers + + + + + + + ROM + 0x00000000 + 0x00008000 + + + SRAM + 0x10000000 + 0x00020000 + + + VEXRISCV_DEBUG + 0xEFFF0000 + 0x00000100 + + + SRAM_EXT + 0x40000000 + 0x01000000 + + + MEMLCD + 0xB0000000 + 0x00005C20 + + + SPIFLASH + 0x20000000 + 0x08000000 + + + AUDIO + 0xE0000000 + 0x00000004 + + + SHA2 + 0xE0001000 + 0x00000004 + + + SHA512 + 0xE0002000 + 0x00000008 + + + ENGINE + 0xE0020000 + 0x00020000 + + + CSR + 0xF0000000 + 0x00040000 + + + + \ No newline at end of file diff --git a/src/generate.rs b/src/generate.rs new file mode 100644 index 0000000..6f00672 --- /dev/null +++ b/src/generate.rs @@ -0,0 +1,635 @@ +use quick_xml::events::Event; +use quick_xml::Reader; +use std::io::{BufRead, BufReader, Read, Write}; + +#[derive(Debug)] +pub enum ParseError { + UnexpectedTag, + MissingValue, + ParseIntError, + NonUTF8, +} + +#[derive(Default, Debug)] +struct Field { + name: String, + lsb: usize, + msb: usize, +} + +#[derive(Default, Debug)] +struct Register { + name: String, + offset: usize, + description: Option, + fields: Vec, +} + +#[derive(Default, Debug)] +struct Peripheral { + name: String, + base: usize, + size: usize, + interrupt: Option, + registers: Vec, +} + +#[derive(Default, Debug)] +struct MemoryRegion { + name: String, + base: usize, + size: usize, +} + +#[derive(Default, Debug)] +struct Description { + peripherals: Vec, + memory_regions: Vec, +} + +pub fn get_base(value: &str) -> (&str, u32) { + if value.starts_with("0x") { + (value.trim_start_matches("0x"), 16) + } else if value.starts_with("0X") { + (value.trim_start_matches("0X"), 16) + } else if value.starts_with("0b") { + (value.trim_start_matches("0b"), 2) + } else if value.starts_with("0B") { + (value.trim_start_matches("0B"), 2) + } else if value.starts_with('0') && value != "0" { + (value.trim_start_matches('0'), 8) + } else { + (value, 10) + } +} + +fn parse_usize(value: &[u8]) -> Result { + let value_as_str = String::from_utf8(value.to_vec()).or(Err(ParseError::NonUTF8))?; + let (value, base) = get_base(&value_as_str); + usize::from_str_radix(value, base).or(Err(ParseError::ParseIntError)) +} + +fn extract_contents(reader: &mut Reader) -> Result { + let mut buf = Vec::new(); + let contents = reader + .read_event(&mut buf) + .map_err(|_| ParseError::UnexpectedTag)?; + match contents { + Event::Text(t) => t + .unescape_and_decode(reader) + .map_err(|_| ParseError::NonUTF8), + _ => Err(ParseError::UnexpectedTag), + } +} + +fn generate_field(reader: &mut Reader) -> Result { + let mut buf = Vec::new(); + let mut name = None; + let mut lsb = None; + let mut msb = None; + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => { + let tag_name = e + .unescape_and_decode(reader) + .map_err(|_| ParseError::NonUTF8)?; + match tag_name.as_str() { + "name" => name = Some(extract_contents(reader)?), + "lsb" => lsb = Some(parse_usize(extract_contents(reader)?.as_bytes())?), + "msb" => msb = Some(parse_usize(extract_contents(reader)?.as_bytes())?), + _ => (), + } + } + Ok(Event::End(ref e)) => { + if let b"field" = e.name() { + break; + } + } + Ok(_) => (), + Err(e) => panic!("error parsing: {:?}", e), + } + } + + Ok(Field { + name: name.ok_or(ParseError::MissingValue)?, + lsb: lsb.ok_or(ParseError::MissingValue)?, + msb: msb.ok_or(ParseError::MissingValue)?, + }) +} + +fn generate_fields( + reader: &mut Reader, + fields: &mut Vec, +) -> Result<(), ParseError> { + let mut buf = Vec::new(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"field" => fields.push(generate_field(reader)?), + _ => panic!("unexpected tag in : {:?}", e), + }, + Ok(Event::End(ref e)) => match e.name() { + b"fields" => { + // println!("End fields"); + break; + } + e => panic!("unhandled value: {:?}", e), + }, + Ok(Event::Text(_)) => (), + e => panic!("unhandled value: {:?}", e), + } + } + Ok(()) +} + +fn generate_register(reader: &mut Reader) -> Result { + let mut buf = Vec::new(); + let mut name = None; + let mut offset = None; + let description = None; + let mut fields = vec![]; + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => { + let tag_name = e + .unescape_and_decode(reader) + .map_err(|_| ParseError::NonUTF8)?; + match tag_name.as_str() { + "name" => name = Some(extract_contents(reader)?), + "addressOffset" => { + offset = Some(parse_usize(extract_contents(reader)?.as_bytes())?) + } + "fields" => generate_fields(reader, &mut fields)?, + _ => (), + } + } + Ok(Event::End(ref e)) => { + if let b"register" = e.name() { + break; + } + } + Ok(_) => (), + Err(e) => panic!("error parsing: {:?}", e), + } + } + + Ok(Register { + name: name.ok_or(ParseError::MissingValue)?, + offset: offset.ok_or(ParseError::MissingValue)?, + description, + fields, + }) +} + +fn generate_registers( + reader: &mut Reader, + registers: &mut Vec, +) -> Result<(), ParseError> { + let mut buf = Vec::new(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"register" => registers.push(generate_register(reader)?), + _ => panic!("unexpected tag in : {:?}", e), + }, + Ok(Event::End(ref e)) => match e.name() { + b"registers" => { + break; + } + e => panic!("unhandled value: {:?}", e), + }, + Ok(Event::Text(_)) => (), + e => panic!("unhandled value: {:?}", e), + } + } + Ok(()) +} + +fn generate_peripheral(reader: &mut Reader) -> Result { + let mut buf = Vec::new(); + let mut name = None; + let mut base = None; + let mut size = None; + let mut registers = vec![]; + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => { + let tag_name = e + .unescape_and_decode(reader) + .map_err(|_| ParseError::NonUTF8)?; + match tag_name.as_str() { + "name" => name = Some(extract_contents(reader)?), + "baseAddress" => { + base = Some(parse_usize(extract_contents(reader)?.as_bytes())?) + } + "size" => size = Some(parse_usize(extract_contents(reader)?.as_bytes())?), + "registers" => generate_registers(reader, &mut registers)?, + _ => (), + } + } + Ok(Event::End(ref e)) => { + if let b"peripheral" = e.name() { + break; + } + } + Ok(_) => (), + Err(e) => panic!("error parsing: {:?}", e), + } + } + + Ok(Peripheral { + name: name.ok_or(ParseError::MissingValue)?, + base: base.ok_or(ParseError::MissingValue)?, + size: size.ok_or(ParseError::MissingValue)?, + interrupt: None, + registers, + }) +} + +fn generate_peripherals(reader: &mut Reader) -> Result, ParseError> { + let mut buf = Vec::new(); + let mut peripherals = vec![]; + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"peripheral" => peripherals.push(generate_peripheral(reader)?), + _ => panic!("unexpected tag in : {:?}", e), + }, + Ok(Event::End(ref e)) => match e.name() { + b"peripherals" => { + break; + } + e => panic!("unhandled value: {:?}", e), + }, + Ok(Event::Text(_)) => (), + e => panic!("unhandled value: {:?}", e), + } + } + Ok(peripherals) +} + +fn generate_memory_region(reader: &mut Reader) -> Result { + let mut buf = Vec::new(); + let mut name = None; + let mut base = None; + let mut size = None; + + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => { + let tag_name = e + .unescape_and_decode(reader) + .map_err(|_| ParseError::NonUTF8)?; + match tag_name.as_str() { + "name" => name = Some(extract_contents(reader)?), + "baseAddress" => { + base = Some(parse_usize(extract_contents(reader)?.as_bytes())?) + } + "size" => size = Some(parse_usize(extract_contents(reader)?.as_bytes())?), + _ => (), + } + } + Ok(Event::End(ref e)) => { + if let b"memoryRegion" = e.name() { + break; + } + } + Ok(_) => (), + Err(e) => panic!("error parsing: {:?}", e), + } + } + + Ok(MemoryRegion { + name: name.ok_or(ParseError::MissingValue)?, + base: base.ok_or(ParseError::MissingValue)?, + size: size.ok_or(ParseError::MissingValue)?, + }) +} + +fn parse_memory_regions( + reader: &mut Reader, + description: &mut Description, +) -> Result<(), ParseError> { + let mut buf = Vec::new(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"memoryRegion" => description + .memory_regions + .push(generate_memory_region(reader)?), + _ => panic!("unexpected tag in : {:?}", e), + }, + Ok(Event::End(ref e)) => match e.name() { + b"memoryRegions" => { + break; + } + e => panic!("unhandled value: {:?}", e), + }, + Ok(Event::Text(_)) => (), + e => panic!("unhandled value: {:?}", e), + } + } + Ok(()) +} + +fn parse_vendor_extensions( + reader: &mut Reader, + description: &mut Description, +) -> Result<(), ParseError> { + let mut buf = Vec::new(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"memoryRegions" => parse_memory_regions(reader, description)?, + _ => panic!("unexpected tag in : {:?}", e), + }, + Ok(Event::End(ref e)) => match e.name() { + b"vendorExtensions" => { + break; + } + e => panic!("unhandled value: {:?}", e), + }, + Ok(Event::Text(_)) => (), + e => panic!("unhandled value: {:?}", e), + } + } + Ok(()) +} + +fn print_header(out: &mut U) -> std::io::Result<()> { + let s = r####" +#![cfg_attr(target_os = "none", no_std)] +use core::convert::TryInto; +pub struct Register { + /// Offset of this register within this CSR + offset: usize, +} +impl Register { + pub const fn new(offset: usize) -> Register { + Register { offset } + } +} +pub struct Field { + /// A bitmask we use to AND to the value, unshifted. + /// E.g. for a width of `3` bits, this mask would be 0b111. + mask: usize, + /// Offset of the first bit in this field + offset: usize, + /// A copy of the register address that this field + /// is a member of. Ideally this is optimized out by the + /// compiler. + register: Register, +} +impl Field { + /// Define a new CSR field with the given width at a specified + /// offset from the start of the register. + pub const fn new(width: usize, offset: usize, register: Register) -> Field { + // Asserts don't work in const fn yet. + // assert!(width != 0, "field width cannot be 0"); + // assert!((width + offset) < 32, "field with and offset must fit within a 32-bit value"); + // It would be lovely if we could call `usize::pow()` in a const fn. + let mask = match width { + 0 => 0, + 1 => 1, + 2 => 3, + 3 => 7, + 4 => 15, + 5 => 31, + 6 => 63, + 7 => 127, + 8 => 255, + 9 => 511, + 10 => 1023, + 11 => 2047, + 12 => 4095, + 13 => 8191, + 14 => 16383, + 15 => 32767, + 16 => 65535, + 17 => 131071, + 18 => 262143, + 19 => 524287, + 20 => 1048575, + 21 => 2097151, + 22 => 4194303, + 23 => 8388607, + 24 => 16777215, + 25 => 33554431, + 26 => 67108863, + 27 => 134217727, + 28 => 268435455, + 29 => 536870911, + 30 => 1073741823, + 31 => 2147483647, + _ => 0, + }; + Field { + mask, + offset, + register, + } + } +} +pub struct CSR { + base: *mut T, +} +impl CSR +where + T: core::convert::TryFrom + core::convert::TryInto + core::default::Default, +{ + pub fn new(base: *mut T) -> Self { + CSR { base } + } + /// Read the contents of this register + pub fn r(&mut self, reg: Register) -> T { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + unsafe { usize_base.add(reg.offset).read_volatile() } + .try_into() + .unwrap_or_default() + } + /// Read a field from this CSR + pub fn rf(&mut self, field: Field) -> T { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + ((unsafe { usize_base.add(field.register.offset).read_volatile() } >> field.offset) + & field.mask) + .try_into() + .unwrap_or_default() + } + /// Read-modify-write a given field in this CSR + pub fn rmwf(&mut self, field: Field, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset; + let previous = + unsafe { usize_base.add(field.register.offset).read_volatile() } & !field.mask; + unsafe { + usize_base + .add(field.register.offset) + .write_volatile(previous | value_as_usize) + }; + } + /// Write a given field without reading it first + pub fn wfo(&mut self, field: Field, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = (value.try_into().unwrap_or_default() & field.mask) << field.offset; + unsafe { + usize_base + .add(field.register.offset) + .write_volatile(value_as_usize) + }; + } + /// Write the entire contents of a register without reading it first + pub fn wo(&mut self, reg: Register, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = value.try_into().unwrap_or_default(); + unsafe { usize_base.add(reg.offset).write_volatile(value_as_usize) }; + } + /// Zero a field from a provided value + pub fn zf(&mut self, field: Field, value: T) -> T { + let value_as_usize: usize = value.try_into().unwrap_or_default(); + (value_as_usize & !(field.mask << field.offset)) + .try_into() + .unwrap_or_default() + } + /// Shift & mask a value to its final field position + pub fn ms(&mut self, field: Field, value: T) -> T { + let value_as_usize: usize = value.try_into().unwrap_or_default(); + ((value_as_usize & field.mask) << field.offset) + .try_into() + .unwrap_or_default() + } +} +"####; + out.write_all(s.as_bytes()) +} + +fn print_memory_regions(regions: &[MemoryRegion], out: &mut U) -> std::io::Result<()> { + writeln!(out, "// Physical base addresses of memory regions")?; + for region in regions { + writeln!( + out, + "pub const HW_{}_MEM: u32 = 0x{:08x};", + region.name, region.base + )?; + writeln!( + out, + "pub const HW_{}_MEM_LEN: u32 = {};", + region.name, region.size + )?; + } + writeln!(out)?; + Ok(()) +} + +fn print_peripherals(peripherals: &[Peripheral], out: &mut U) -> std::io::Result<()> { + writeln!(out, "// Physical base addresses of registers")?; + for peripheral in peripherals { + writeln!( + out, + "pub const HW_{}_BASE : u32 = {};", + peripheral.name, peripheral.base + )?; + } + writeln!(out)?; + + writeln!(out, "pub mod utra {{")?; + for peripheral in peripherals { + writeln!(out)?; + writeln!(out, " pub mod {} {{", peripheral.name.to_lowercase())?; + for register in &peripheral.registers { + writeln!(out)?; + if let Some(description) = ®ister.description { + writeln!(out, " /// {}", description)?; + } + writeln!( + out, + " pub const {}: crate::Register = crate::Register::new({});", + register.name, register.offset + )?; + for field in ®ister.fields { + writeln!( + out, + " pub const {}_{}: crate::Field = crate::Field::new({}, {}, {});", + register.name, + field.name.to_uppercase(), + field.msb + 1 - field.lsb, + field.lsb, + register.name + )?; + } + } + writeln!(out, " }}")?; + } + writeln!(out, "}}")?; + Ok(()) +} + +fn print_tests(peripherals: &[Peripheral], out: &mut U) -> std::io::Result<()> { + let test_header = r####" +#[cfg(test)] +mod tests { + #[test] + #[ignore] + fn compile_check() { + use super::*; +"####.as_bytes(); + out.write_all(test_header)?; + for peripheral in peripherals { + // name = peripheral.find('name') + // peri_base = 'HW_' + name.text + '_BASE' + // registers = peripheral.find('registers') + let mod_name = peripheral.name.to_lowercase(); + let reg_name = peripheral.name.to_uppercase() + "_csr"; + writeln!(out, " let mut {}_csr = CSR::new(HW_{}_BASE as *mut u32);", peripheral.name.to_lowercase(), peripheral.name.to_uppercase())?; + for register in &peripheral.registers { + // name = register.find('name') + // offset = register.find('addressOffset') + // register_name = name.text + writeln!(out, " let foo = {}.r(utra::{}::{});", reg_name, mod_name, register.name.to_lowercase())?; + // lib.write(' {}.wo(utra::{}::{}, foo);\n'.format(reg_name, mod_name, register_name)) + // for fields in register.find('fields'): + // field = fields.find('name') + // field_name = register_name + '_' + field.text.upper() + // lib.write(' let bar = {}.rf(utra::{}::{});\n'.format(reg_name, mod_name, field_name)) + // lib.write(' {}.rmwf(utra::{}::{}, bar);\n'.format(reg_name, mod_name, field_name)) + // lib.write(' let mut baz = {}.zf(utra::{}::{}, bar);\n'.format(reg_name, mod_name, field_name)) + // lib.write(' baz |= {}.ms(utra::{}::{}, 1);\n'.format(reg_name, mod_name, field_name)) + // lib.write(' {}.wfo(utra::{}::{}, baz);\n'.format(reg_name, mod_name, field_name)) + } + // lib.write('\n') + } + writeln!(out, " }}")?; + writeln!(out, "}}")?; + Ok(()) +} + + +pub fn generate(src: T, dest: &mut U) -> Result<(), ParseError> { + let mut buf = Vec::new(); + let buf_reader = BufReader::new(src); + let mut reader = Reader::from_reader(buf_reader); + let mut description = Description::default(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) => match e.name() { + b"peripherals" => { + description.peripherals = generate_peripherals(&mut reader)?; + } + b"vendorExtensions" => { + parse_vendor_extensions(&mut reader, &mut description)?; + } + _ => (), + }, + Ok(Event::Eof) => break, + Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), + _ => (), + } + buf.clear(); + } + + print_header(dest).unwrap(); + print_memory_regions(&description.memory_regions, dest).unwrap(); + print_peripherals(&description.peripherals, dest).unwrap(); + print_tests(&description.peripherals, dest).unwrap(); + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0607b56 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,10 @@ +mod generate; +pub use generate::*; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5d1ed44 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,10 @@ +mod generate; +use generate::*; + +use std::fs::File; + +fn main() { + let src = File::open("examples/soc.svd").unwrap(); + let mut dest = File::create("example.rs").unwrap(); + generate(src, &mut dest).unwrap(); +}