Add Chisel source for picorF0, no changes to main design
diff --git a/README.md b/README.md index 0d7a31d..1ea1296 100644 --- a/README.md +++ b/README.md
@@ -1,8 +1,9 @@ # caravel-picoRF0 - CAN bus controller for autonomous vehicles, connected to caravel and with it's I/O and debug interfaces exposed on I/O pins (developed by Natalia Machado) + - See [nxmq/Can_Core](https://github.com/nxmq/Can_Core) for CAN controller Chisel source code -- picoRF0 - a multicycle CPU core running a simplified RISC ISA (used for teaching, normally on FPGAs). Connected to caravel for memory interfacing and I/O usage - - can be tied to the CAN bus controller through caravel +- picoRF0 - a multicycle CPU core running a simplified RISC ISA (targeted for teaching purposes). Connected to caravel for memory interfacing and I/O usage + - See `picoRF0` directory for CPU Chisel source code - Tiny VGA pong game controller to test I/O interface speed
diff --git a/picorF0/.gitignore b/picorF0/.gitignore new file mode 100644 index 0000000..12033d3 --- /dev/null +++ b/picorF0/.gitignore
@@ -0,0 +1,341 @@ +### Project Specific stuff +test_run_dir/* +### XilinxISE template +# intermediate build files +*.bgn +*.bit +*.bld +*.cmd_log +*.drc +*.ll +*.lso +*.msd +*.msk +*.ncd +*.ngc +*.ngd +*.ngr +*.pad +*.par +*.pcf +*.prj +*.ptwx +*.rbb +*.rbd +*.stx +*.syr +*.twr +*.twx +*.unroutes +*.ut +*.xpi +*.xst +*_bitgen.xwbt +*_envsettings.html +*_map.map +*_map.mrp +*_map.ngm +*_map.xrpt +*_ngdbuild.xrpt +*_pad.csv +*_pad.txt +*_par.xrpt +*_summary.html +*_summary.xml +*_usage.xml +*_xst.xrpt + +# project-wide generated files +*.gise +par_usage_statistics.html +usage_statistics_webtalk.html +webtalk.log +webtalk_pn.xml + +# generated folders +iseconfig/ +xlnx_auto_0_xdb/ +xst/ +_ngo/ +_xmsgs/ +### Eclipse template +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse +### C template +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +### SBT template +# Simple Build Tool +# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control + +target/ +lib_managed/ +src_managed/ +project/boot/ +.history +.cache +### Emacs template +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +### Vim template +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +### C++ template +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### OSX template +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +### Scala template +*.class +*.log +/.bsp + +# sbt specific +.cache +.history +.lib/ +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet +### Java template +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +
diff --git a/picorF0/build.sbt b/picorF0/build.sbt new file mode 100644 index 0000000..b3c97b7 --- /dev/null +++ b/picorF0/build.sbt
@@ -0,0 +1,26 @@ +// See README.md for license details. + +ThisBuild / scalaVersion := "2.12.13" +ThisBuild / version := "0.1.0" +ThisBuild / organization := "com.anishsinghani" + +lazy val root = (project in file(".")) + .settings( + name := "picorF0", + libraryDependencies ++= Seq( + "edu.berkeley.cs" %% "chisel3" % "3.4.3", + "edu.berkeley.cs" %% "chiseltest" % "0.3.3" % "test" + ), + scalacOptions ++= Seq( + "-Xsource:2.11", + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + // Enables autoclonetype2 in 3.4.x (on by default in 3.5) + "-P:chiselplugin:useBundlePlugin" + ), + addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.4.3" cross CrossVersion.full), + addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) + ) +
diff --git a/picorF0/build.sc b/picorF0/build.sc new file mode 100644 index 0000000..d095a55 --- /dev/null +++ b/picorF0/build.sc
@@ -0,0 +1,34 @@ +// import Mill dependency +import mill._ +import mill.define.Sources +import mill.modules.Util +import mill.scalalib.TestModule.ScalaTest +import scalalib._ +// support BSP +import mill.bsp._ + +object noc-generator extends SbtModule { m => + override def millSourcePath = os.pwd + override def scalaVersion = "2.12.13" + override def scalacOptions = Seq( + "-Xsource:2.11", + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + // Enables autoclonetype2 in 3.4.x (on by default in 3.5) + "-P:chiselplugin:useBundlePlugin" + ) + override def ivyDeps = Agg( + ivy"edu.berkeley.cs::chisel3:3.4.3", + ) + override def scalacPluginIvyDeps = Agg( + ivy"edu.berkeley.cs:::chisel3-plugin:3.4.3", + ivy"org.scalamacros:::paradise:2.1.1" + ) + object test extends Tests with ScalaTest { + override def ivyDeps = m.ivyDeps() ++ Agg( + ivy"edu.berkeley.cs::chiseltest:0.3.3" + ) + } +}
diff --git a/picorF0/project/build.properties b/picorF0/project/build.properties new file mode 100644 index 0000000..ddffd37 --- /dev/null +++ b/picorF0/project/build.properties
@@ -0,0 +1 @@ +sbt.version = 1.4.9
diff --git a/picorF0/project/plugins.sbt b/picorF0/project/plugins.sbt new file mode 100644 index 0000000..5708f81 --- /dev/null +++ b/picorF0/project/plugins.sbt
@@ -0,0 +1 @@ +logLevel := Level.Warn
diff --git a/picorF0/src/main/scala/components/ALU.scala b/picorF0/src/main/scala/components/ALU.scala new file mode 100644 index 0000000..eef15b1 --- /dev/null +++ b/picorF0/src/main/scala/components/ALU.scala
@@ -0,0 +1,83 @@ +package components + +import chisel3._ +import chisel3.util._ +import chisel3.experimental.ChiselEnum + +object ALUOp extends ChiselEnum { + val ADD, AND, NOT, OR, SLL, SLT, SRA, SRL, SUB, XOR = Value +} + +class ZCNV extends Bundle { + val z = Bool() + val c = Bool() + val n = Bool() + val v = Bool() +} + +class ALU extends Module { + val io = IO(new Bundle { + val in1 = Input(UInt(16.W)) + val in2 = Input(UInt(16.W)) + val op = Input(ALUOp()) + + val out = Output(UInt(16.W)) + val cc = Output(new ZCNV) + }) + + val in1 = Wire(UInt(17.W)) + val in2 = Wire(UInt(17.W)) + in1 := io.in1 + in2 := io.in2 + + val result = Wire(UInt(17.W)) + io.out := result(15, 0) + + val in1_minus_in2 = Wire(UInt(17.W)) + in1_minus_in2 := in1 - in2 + + result := 0.U + + // Compute result + switch (io.op) { + is (ALUOp.ADD) { result := in1 + in2 } + is (ALUOp.AND) { result := in1 & in2 } + is (ALUOp.NOT) { result := ~in1 } + is (ALUOp.OR) { result := in1 | in2 } + is (ALUOp.SLL) { result := in1 << in2(3, 0) } + is (ALUOp.SLT) { result := Cat(0.U(15.W), (in1(15, 0).asSInt() < in2(15, 0).asSInt())(0)) } + is (ALUOp.SRA) { result := (in1(15, 0).asSInt() >> in2(3, 0)).asUInt()(15,0) } + is (ALUOp.SRL) { result := in1 >> in2(3, 0) } + is (ALUOp.SUB) { result := in1_minus_in2 } + is (ALUOp.XOR) { result := in1 ^ in2 } + } + + // Compute flags + when (io.op === ALUOp.ADD) { + io.cc.z := (io.out === 0.U) + io.cc.c := result(16) + io.cc.n := result(15) + io.cc.v := (in1(15) && in2(15) && !io.out(15)) || + (!in1(15) && !in2(15) && io.out(15)) + } + .elsewhen (io.op === ALUOp.SUB) { + io.cc.z := (io.out === 0.U) + io.cc.c := (in2 >= in1) // Weird but works + io.cc.n := result(15) + io.cc.v := (in1(15) && !in2(15) && !io.out(15)) || + (!in1(15) && in2(15) && io.out(15)) + } + .elsewhen (io.op === ALUOp.SLT) { + io.cc.z := (in1_minus_in2 === 0.U) + io.cc.c := (in2 >= in1) + io.cc.n := in1_minus_in2(15) + io.cc.v := (in1(15) && !in2(15) && !in1_minus_in2(15)) || + (!in1(15) && in2(15) && in1_minus_in2(15)) + } + .otherwise { + io.cc.z := (io.out === 0.U) + io.cc.c := false.B + io.cc.n := result(15) + io.cc.v := false.B + } +}
diff --git a/picorF0/src/main/scala/components/InstrDecoder.scala b/picorF0/src/main/scala/components/InstrDecoder.scala new file mode 100644 index 0000000..2f9cb89 --- /dev/null +++ b/picorF0/src/main/scala/components/InstrDecoder.scala
@@ -0,0 +1,145 @@ +package components + +import chisel3._ +import chisel3.experimental.ChiselEnum +import utils.MathUtils.BinStrToInt + +object CCMode extends ChiselEnum { + // ALU = use CC values from ALU + // WB = use ZN from write-back value, C = 0, V = 0 + // NONE = don't change CC flags + val ALU, WB, NONE = Value +} + +class Instruction extends Bundle { + val rs1 = UInt(3.W) + val rs2 = UInt(3.W) + val rd = UInt(3.W) + val imm = UInt(16.W) + + val cc_mode = CCMode() + val alu_op = ALUOp() + val bra_mask = new ZCNV // Which CC bits to branch on + + val has_jump = Bool() + val has_stop = Bool() + val has_branch = Bool() + val has_mem = Bool() + val has_wb = Bool() + val has_imm = Bool() + + val is_valid = Bool() +} + +object OpCode { + val ADD = b"0000 000" + val ADDI = b"0011 000" + val AND = b"1001 000" + val BRA = b"1111 100" + val BRC = b"1010 100" + val BRN = b"1001 100" + val BRNZ = b"1101 100" + val BRV = b"1011 100" + val BRZ = b"1100 100" + // LI = ADDI + val LW = b"0010 100" + val MV = b"0010 000" + val NOT = b"1000 000" + val OR = b"1010 000" + val SLL = b"1100 000" + val SLLI = b"1100 001" + val SLT = b"0101 000" + val SLTI = b"0101 001" + val SRA = b"1111 000" + val SRAI = b"1111 001" + val SRL = b"1110 000" + val SRLI = b"1110 001" + val STOP = b"1111 111" + val SUB = b"0001 000" + val SW = b"0011 100" + val XOR = b"1011 000" +} + +class InstrDecoder extends Module { + val io = IO(new Bundle { + val instr = Input(UInt(16.W)) + val imm = Input(UInt(16.W)) + + val decoded = Output(new Instruction) + }) + + val instructions = Map( + // Opcode ALU op CC mode BRA mask jmp stp bra mem wb imm + OpCode.ADD -> (Some(ALUOp.ADD), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // ADD + OpCode.ADDI -> (Some(ALUOp.ADD), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // ADDI + OpCode.AND -> (Some(ALUOp.AND), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // AND + OpCode.BRA -> (None, CCMode.NONE, b"0000", 1, 0, 0, 0, 0, 1 ), // BRA + OpCode.BRC -> (None, CCMode.NONE, b"0100", 0, 0, 1, 0, 0, 1 ), // BRC + OpCode.BRN -> (None, CCMode.NONE, b"0010", 0, 0, 1, 0, 0, 1 ), // BRN + OpCode.BRNZ -> (None, CCMode.NONE, b"1010", 0, 0, 1, 0, 0, 1 ), // BRNZ + OpCode.BRV -> (None, CCMode.NONE, b"0001", 0, 0, 1, 0, 0, 1 ), // BRV + OpCode.BRZ -> (None, CCMode.NONE, b"1000", 0, 0, 1, 0, 0, 1 ), // BRZ + // LI does not have its own encoding, it uses ADDI with rs1 = 0 + OpCode.LW -> (Some(ALUOp.ADD), CCMode.WB, b"0000", 0, 0, 0, 1, 1, 1 ), // LW + OpCode.MV -> (Some(ALUOp.ADD), CCMode.NONE, b"0000", 0, 0, 0, 0, 1, 0 ), // MV (ADD, rs2 = 0) + OpCode.NOT -> (Some(ALUOp.NOT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // NOT + OpCode.OR -> (Some(ALUOp.OR), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // OR + OpCode.SLL -> (Some(ALUOp.SLL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SLL + OpCode.SLLI -> (Some(ALUOp.SLL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SLLI + OpCode.SLT -> (Some(ALUOp.SLT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SLT + OpCode.SLTI -> (Some(ALUOp.SLT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SLTI + OpCode.SRA -> (Some(ALUOp.SRA), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SRA + OpCode.SRAI -> (Some(ALUOp.SRA), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SRAI + OpCode.SRL -> (Some(ALUOp.SRL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SRL + OpCode.SRLI -> (Some(ALUOp.SRL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SRLI + OpCode.STOP -> (None, CCMode.NONE, b"0000", 0, 1, 0, 0, 0, 0 ), // STOP + OpCode.SUB -> (Some(ALUOp.SUB), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SUB + OpCode.SW -> (Some(ALUOp.ADD), CCMode.NONE, b"0000", 0, 0, 0, 1, 0, 1 ), // SW + OpCode.XOR -> (Some(ALUOp.XOR), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // XOR + ) + + val opcode = io.instr(15, 9) + + // Operands + io.decoded.imm := io.imm + io.decoded.rd := io.instr(8, 6) // When instruction has no write-back it's always zero - useful feature of the ISA + io.decoded.rs1 := io.instr(5, 3) + io.decoded.rs2 := io.instr(2, 0) + + // Default values + io.decoded.cc_mode := CCMode.NONE + io.decoded.alu_op := ALUOp.ADD + io.decoded.bra_mask.z := false.B + io.decoded.bra_mask.c := false.B + io.decoded.bra_mask.n := false.B + io.decoded.bra_mask.v := false.B + io.decoded.has_jump := false.B + io.decoded.has_stop := false.B + io.decoded.has_branch := false.B + io.decoded.has_mem := false.B + io.decoded.has_wb := false.B + io.decoded.has_imm := false.B + io.decoded.is_valid := false.B + + for ((inst_opcode, (aluop, ccmode, bramask, jmp, stp, bra, mem, wb, imm)) <- instructions) { + when (inst_opcode.U === opcode) { + io.decoded.cc_mode := ccmode + io.decoded.alu_op := aluop getOrElse ALUOp.ADD + + io.decoded.bra_mask.z := ((bramask & b"1000") != 0).B + io.decoded.bra_mask.c := ((bramask & b"0100") != 0).B + io.decoded.bra_mask.n := ((bramask & b"0010") != 0).B + io.decoded.bra_mask.v := ((bramask & b"0001") != 0).B + + io.decoded.has_jump := jmp.B + io.decoded.has_stop := stp.B + io.decoded.has_branch := bra.B + io.decoded.has_mem := mem.B + io.decoded.has_wb := wb.B + io.decoded.has_imm := imm.B + + io.decoded.is_valid := true.B + } + } + +} \ No newline at end of file
diff --git a/picorF0/src/main/scala/components/RegFile.scala b/picorF0/src/main/scala/components/RegFile.scala new file mode 100644 index 0000000..d272465 --- /dev/null +++ b/picorF0/src/main/scala/components/RegFile.scala
@@ -0,0 +1,45 @@ +package components + +import chisel3._ +import chisel3.util._ +import chisel3.experimental.ChiselEnum + +class RegFile extends Module { + val io = IO(new Bundle { + val rs1 = Input(UInt(3.W)) + val rs2 = Input(UInt(3.W)) + + val rs1_dat = Output(UInt(16.W)) + val rs2_dat = Output(UInt(16.W)) + + val rd = Input(UInt(3.W)) + val rd_dat = Input(UInt(16.W)) + val rd_en = Input(Bool()) + + val cc_in = Input(new ZCNV) + val cc_mask = Input(new ZCNV) + val cc_en = Input(Bool()) + + val cc_out = Output(new ZCNV) + }) + + val rf = Reg(Vec(8, UInt(16.W))) + + // Handle reads + io.rs1_dat := Mux(io.rs1 === 0.U, 0.U, rf(io.rs1)) + io.rs2_dat := Mux(io.rs2 === 0.U, 0.U, rf(io.rs2)) + + // Handle writes + when (io.rd_en) { rf(io.rd) := io.rd_dat } + + // Handle ZCNV + val cc_reg = Reg(new ZCNV) + io.cc_out := cc_reg + + when (io.cc_en) { + when (io.cc_mask.z) { cc_reg.z := io.cc_in.z } + when (io.cc_mask.c) { cc_reg.c := io.cc_in.c } + when (io.cc_mask.n) { cc_reg.n := io.cc_in.n } + when (io.cc_mask.v) { cc_reg.v := io.cc_in.v } + } +}
diff --git a/picorF0/src/main/scala/core/ControlPath.scala b/picorF0/src/main/scala/core/ControlPath.scala new file mode 100644 index 0000000..305dce6 --- /dev/null +++ b/picorF0/src/main/scala/core/ControlPath.scala
@@ -0,0 +1,99 @@ +package core + +import chisel3._ +import chisel3.experimental.ChiselEnum +import chisel3.util.{switch, is} +import components.Instruction + +import ControlPath._ + +object ControlPath { + object S extends ChiselEnum { + val IF, IF_WAIT, DECODE, EXEC, MEM, MEM_WAIT, WB, HALT = Value + } +} + +class ControlPath extends Module { + + val io = IO(new Bundle { + val instr = Input(new Instruction) + + val issue_if = Output(Bool()) + val if_done = Input(Bool()) + + val issue_mem = Output(Bool()) + val mem_we = Output(Bool()) + val mem_done = Input(Bool()) + + val waiting = Output(Bool()) + val halted = Output(Bool()) + + val state = Output(S()) + + val restart_core = Input(Bool()) + val restart = Output(Bool()) // to datapath + }) + + val restart_reg = RegInit(false.B) + io.restart := io.restart_core || restart_reg + + val state = RegInit(S.IF) + io.state := state + + val is_store_instr = (io.instr.has_mem && !io.instr.has_wb) + + io.issue_if := (state === S.IF) + io.issue_mem := (state === S.MEM) + io.mem_we := is_store_instr + + io.waiting := (state === S.IF_WAIT || state === S.MEM_WAIT) + io.halted := (state === S.HALT) + + // State-transition logic + switch (state) { + is (S.IF) { + state := S.IF_WAIT + } + is (S.IF_WAIT) { + state := Mux(io.if_done, S.DECODE, S.IF_WAIT) + } + is (S.DECODE) { + state := S.EXEC + } + is (S.EXEC) { + when (io.instr.has_stop) { + state := S.HALT + }.elsewhen (io.instr.has_jump || io.instr.has_branch) { + state := S.IF + }.elsewhen (io.instr.has_mem) { + state := S.MEM + }.otherwise { + state := S.WB + } + } + is (S.MEM) { + state := S.MEM_WAIT + } + is (S.MEM_WAIT) { + state := Mux(io.mem_done, + Mux(is_store_instr, S.IF, S.WB), + S.MEM_WAIT) + } + is (S.WB) { + state := S.IF + } + is (S.HALT) { + state := S.HALT + } + } + + when (io.restart_core) { + restart_reg := true.B + } + + when (restart_reg && (state =/= S.IF) && (state =/= S.IF_WAIT) && (state =/= S.MEM) && (state =/= S.MEM_WAIT)) { + restart_reg := false.B + state := S.IF + } + +} \ No newline at end of file
diff --git a/picorF0/src/main/scala/core/Core.scala b/picorF0/src/main/scala/core/Core.scala new file mode 100644 index 0000000..5f93fb0 --- /dev/null +++ b/picorF0/src/main/scala/core/Core.scala
@@ -0,0 +1,61 @@ +package core + +import chisel3._ +import components._ +import _root_.core.ControlPath._ + +class Core(val INIT_PC: Int = 0) extends Module { + val io = IO(new Bundle { + val ibus_addr = Output(UInt(16.W)) + val ibus_data_rd = Input(UInt(32.W)) + val ibus_stb = Output(Bool()) + val ibus_ack = Input(Bool()) + + val dbus_addr = Output(UInt(16.W)) + val dbus_we = Output(Bool()) + val dbus_data_rd = Input(UInt(16.W)) + val dbus_data_wr = Output(UInt(16.W)) + val dbus_stb = Output(Bool()) + val dbus_ack = Input(Bool()) + + val restart_pc = Input(UInt(16.W)) + val restart_core = Input(Bool()) + + val waiting = Output(Bool()) + val halted = Output(Bool()) + }) + + val dpath = Module(new Datapath(INIT_PC)) + dpath.io.ibus_addr <> io.ibus_addr + dpath.io.ibus_data_rd <> io.ibus_data_rd + dpath.io.ibus_stb <> io.ibus_stb + dpath.io.ibus_ack <> io.ibus_ack + + dpath.io.dbus_addr <> io.dbus_addr + dpath.io.dbus_we <> io.dbus_we + dpath.io.dbus_data_rd <> io.dbus_data_rd + dpath.io.dbus_data_wr <> io.dbus_data_wr + dpath.io.dbus_stb <> io.dbus_stb + dpath.io.dbus_ack <> io.dbus_ack + + dpath.io.restart_pc <> io.restart_pc + + val cpath = Module(new ControlPath) + cpath.io.instr <> dpath.io.instr + + cpath.io.issue_if <> dpath.io.issue_if + cpath.io.if_done <> dpath.io.if_done + cpath.io.issue_mem <> dpath.io.issue_mem + cpath.io.mem_we <> dpath.io.mem_we + cpath.io.mem_done <> dpath.io.mem_done + + cpath.io.waiting <> io.waiting + cpath.io.halted <> io.halted + cpath.io.state <> dpath.io.state + + cpath.io.restart_core <> io.restart_core + cpath.io.restart <> dpath.io.restart + +} + +
diff --git a/picorF0/src/main/scala/core/Datapath.scala b/picorF0/src/main/scala/core/Datapath.scala new file mode 100644 index 0000000..88ef6bc --- /dev/null +++ b/picorF0/src/main/scala/core/Datapath.scala
@@ -0,0 +1,138 @@ +package core + +import chisel3._ +import chisel3.util.{is, switch} +import components.{ALU, CCMode, InstrDecoder, Instruction, RegFile, ZCNV} +import ControlPath._ + +class Datapath(val INIT_PC: Int = 0) extends Module { + val io = IO(new Bundle { + val instr = Output(new Instruction) + + val issue_if = Input(Bool()) + val if_done = Output(Bool()) + val issue_mem = Input(Bool()) + val mem_we = Input(Bool()) + val mem_done = Output(Bool()) + val state = Input(S()) + + val ibus_addr = Output(UInt(16.W)) + val ibus_data_rd = Input(UInt(32.W)) + val ibus_stb = Output(Bool()) + val ibus_ack = Input(Bool()) + + val dbus_addr = Output(UInt(16.W)) + val dbus_we = Output(Bool()) + val dbus_data_rd = Input(UInt(16.W)) + val dbus_data_wr = Output(UInt(16.W)) + val dbus_stb = Output(Bool()) + val dbus_ack = Input(Bool()) + + val restart_pc = Input(UInt(16.W)) + val restart = Input(Bool()) + }) + + val pc_reg = RegInit(INIT_PC.U(16.W)) + val ifetch_reg = RegInit(0.U(32.W)) + val instr_reg = RegInit(0.U.asTypeOf(new Instruction)) + val rs1_reg = RegInit(0.U(16.W)) + val rs2_reg = RegInit(0.U(16.W)) + val cc_reg = RegInit(0.U(4.W).asTypeOf(new ZCNV)) + + val result_reg = RegInit(0.U(16.W)) + val result_cc_reg = RegInit(0.U(4.W).asTypeOf(new ZCNV)) + + io.instr := instr_reg + + // Next PC + when (io.restart) { + // When rising edge of restart, set the PC to restart PC + // otherwise don't let the PC change + when (!RegNext(io.restart)) { + pc_reg := io.restart_pc + } + } .elsewhen (io.state === S.EXEC) { + pc_reg := pc_reg + Mux(io.instr.has_imm, 4.U, 2.U) + + val take_branch = (io.instr.bra_mask.asUInt() & cc_reg.asUInt()).orR() + when (io.instr.has_jump || (io.instr.has_branch && take_branch)) { + pc_reg := io.instr.imm + } + } + + // IFetch + io.ibus_addr := pc_reg + io.ibus_stb := io.issue_if + io.if_done := io.ibus_ack + when (io.ibus_ack) { ifetch_reg := io.ibus_data_rd } + + // Decoder + val decoder = Module(new InstrDecoder) + decoder.io.instr := ifetch_reg(31, 16) + decoder.io.imm := ifetch_reg(15, 0) + var instr_decoded = decoder.io.decoded + when (io.state === S.DECODE) { + instr_reg := instr_decoded + } + + // ALU + val alu = Module(new ALU) + alu.io.in1 := rs1_reg + alu.io.in2 := Mux(instr_reg.has_imm, instr_reg.imm, rs2_reg) + alu.io.op := instr_reg.alu_op + when (io.state === S.EXEC) { + result_reg := alu.io.out + result_cc_reg := alu.io.cc + } + + // Data memory + io.dbus_addr := result_reg + io.dbus_we := io.mem_we + io.dbus_data_wr := rs2_reg + io.dbus_stb := io.issue_mem + io.mem_done := io.dbus_ack + when (io.state === S.MEM_WAIT && !io.mem_we && io.dbus_ack) { + result_reg := io.dbus_data_rd + } + + // Register file (in decode / WB stages) + // RF read happens in decode stage so it should use instr_decoded instead of instr_reg + val regfile = Module(new RegFile) + regfile.io.rs1 := instr_decoded.rs1 + regfile.io.rs2 := instr_decoded.rs2 + regfile.io.rd := instr_reg.rd + + regfile.io.rd_en := false.B + regfile.io.cc_en := false.B + + regfile.io.cc_mask.z := true.B + regfile.io.cc_mask.c := true.B + regfile.io.cc_mask.n := true.B + regfile.io.cc_mask.v := true.B + + regfile.io.rd_dat := result_reg + + when (io.state === S.DECODE) { + rs1_reg := regfile.io.rs1_dat + rs2_reg := regfile.io.rs2_dat + cc_reg := regfile.io.cc_out + } + + when (io.state === S.WB) { + regfile.io.rd_en := true.B + regfile.io.cc_en := (instr_reg.cc_mode =/= CCMode.NONE) + } + + when (instr_reg.cc_mode === CCMode.ALU) { + regfile.io.cc_in.z := result_cc_reg.z + regfile.io.cc_in.c := result_cc_reg.c + regfile.io.cc_in.n := result_cc_reg.n + regfile.io.cc_in.v := result_cc_reg.v + } .otherwise { + regfile.io.cc_in.z := (result_reg === 0.U) + regfile.io.cc_in.c := false.B + regfile.io.cc_in.n := result_reg(15) + regfile.io.cc_in.v := false.B + } + +} \ No newline at end of file
diff --git a/picorF0/src/main/scala/top/CoreTop.scala b/picorF0/src/main/scala/top/CoreTop.scala new file mode 100644 index 0000000..f1e734b --- /dev/null +++ b/picorF0/src/main/scala/top/CoreTop.scala
@@ -0,0 +1,80 @@ +package top + +import chisel3._ +import chisel3.util._ +import _root_.core.Core + +// Connect the core to the caravel logic analyzer to use as it's memory interface +class CoreTop extends Module { + val INIT_PC: Int = 0 + + val io = IO(new Bundle { + val la_data_in = Input(UInt(128.W)) + val la_data_out = Output(UInt(128.W)) + val la_oenb = Input(UInt(128.W)) + }) + + val la_data_in = RegNext(Mux(io.la_oenb(127, 64).orR, 0.U(128.W), Cat(io.la_data_in(127, 64), 0.U(64.W)))) + + val ibus_stb_latch = RegInit(false.B) + val ibus_ack_in = Wire(Bool()) + val ibus_stb_clear = Wire(Bool()) + + val dbus_stb_latch = RegInit(false.B) + val dbus_ack_in = Wire(Bool()) + val dbus_stb_clear = Wire(Bool()) + + val core = Module(new Core(INIT_PC)) + + when (core.io.ibus_stb) { ibus_stb_latch := true.B } + when (ibus_stb_clear && !RegNext(ibus_stb_clear)) { ibus_stb_latch := false.B } + core.io.ibus_ack := ibus_ack_in && !RegNext(ibus_ack_in) // Rising edge + + when (core.io.dbus_stb) { dbus_stb_latch := true.B } + when (dbus_stb_clear && !RegNext(dbus_stb_clear)) { dbus_stb_latch := false.B } + core.io.dbus_ack := dbus_ack_in && !RegNext(dbus_ack_in) // Rising edge + + // LA[15:0] = ibus_addr + // LA[31:16] = dbus_addr + // LA[47:32] = dbus_data_wr + // LA[48] = ibus_stb + // LA[49] = dbus_stb + // LA[50] = dbus_we + // LA[51] = waiting + // LA[52] = halted + // LA[63:53] = reserved (core -> caravel) + io.la_data_out := RegNext(Cat( + core.io.halted, + core.io.waiting, + core.io.dbus_we, + dbus_stb_latch, + ibus_stb_latch, + core.io.dbus_data_wr, + core.io.dbus_addr, + core.io.ibus_addr + )) + + // LA[95:64] = data_rd / restart_pc + core.io.ibus_data_rd := la_data_in(95, 64) + core.io.dbus_data_rd := la_data_in(79, 64) + core.io.restart_pc := la_data_in(95, 80) + + // LA[96] = ibus_ack + ibus_ack_in := la_data_in(96) + + // LA[97] = ibus_stb_clear + ibus_stb_clear := la_data_in(97) + + // LA[98] = dbus_ack + dbus_ack_in := la_data_in(98) + + // LA[99] = dbus_stb_clear + dbus_stb_clear := la_data_in(99) + + // LA[100] = restart_core + core.io.restart_core := la_data_in(100) && !RegNext(la_data_in(100)) + + // LA[127:101] = reserved (caravel -> core) +} + +
diff --git a/picorF0/src/main/scala/top/GenerateVerilog.scala b/picorF0/src/main/scala/top/GenerateVerilog.scala new file mode 100644 index 0000000..b6a9035 --- /dev/null +++ b/picorF0/src/main/scala/top/GenerateVerilog.scala
@@ -0,0 +1,8 @@ +package top + +import chisel3.stage.ChiselStage +import top.CoreTop + +object GenerateVerilog extends App { + (new ChiselStage).emitVerilog(new CoreTop) +}
diff --git a/picorF0/src/main/scala/utils/MathUtils.scala b/picorF0/src/main/scala/utils/MathUtils.scala new file mode 100644 index 0000000..1ac7072 --- /dev/null +++ b/picorF0/src/main/scala/utils/MathUtils.scala
@@ -0,0 +1,25 @@ +package utils + +object MathUtils { + def intLog2(x: Int): Int = { + val log = (Math.log(x) / Math.log(2.0)).round.toInt + assert((1 << log) == x) + return log + } + + implicit class BinStrToInt(val sc: StringContext) extends AnyVal { + def b(args: Any*): Int = { + val strings = sc.parts.iterator + val expressions = args.iterator + val buf = new StringBuilder(strings.next()) + while(strings.hasNext) { + buf.append(expressions.next()) + buf.append(strings.next()) + } + + Integer.parseInt("0" + buf.toString + .replaceAll("_", "") + .replaceAll(" ", ""), 2) + } + } +} \ No newline at end of file
diff --git a/picorF0/src/test/scala/core/CoreTests.scala b/picorF0/src/test/scala/core/CoreTests.scala new file mode 100644 index 0000000..4a937ef --- /dev/null +++ b/picorF0/src/test/scala/core/CoreTests.scala
@@ -0,0 +1,255 @@ +package core + +import chisel3._ +import chisel3.tester._ +import components.OpCode._ +import org.scalatest.FreeSpec +import utils.MathUtils.BinStrToInt + +import scala.io.Source +import scala.util.Random +import scala.util.control.Breaks._ + +class CoreTests extends FreeSpec with ChiselScalatestTester { + + def asm(opcode: Int, rd: Int = 0, rs1: Int = 0, rs2: Int = 0): Int = + ((opcode & b"1111 111") << 9) | + ((rd & b"111") << 6) | + ((rs1 & b"111") << 3) | + ((rs2 & b"111") << 0) + + // `program` is an array of 16-bit memory words + def handleIFetch(dut: Core, program: Array[Int], verbose: Boolean = false): Unit = { + val prog = program :+ 0 // Allows fetching last instruction in program if it is a short-style instruction + + breakable { + while (true) { + while (!dut.io.ibus_stb.peek().litToBoolean) { + dut.clock.step() + if (dut.io.halted.peek().litToBoolean) break + } + + val addr = dut.io.ibus_addr.peek().litValue().toInt + val result = (BigInt(prog(addr >> 1)) << 16) | BigInt(prog((addr >> 1) + 1)) // 32-bit fetch + + for (_ <- 0 until (Random.nextInt(3) + 2)) { // 2-5 cycle latency + dut.clock.step() + dut.io.ibus_stb.expect(false.B) + } + + dut.io.ibus_data_rd.poke(result.U) + dut.io.ibus_ack.poke(true.B) + dut.clock.step() + dut.io.ibus_ack.poke(false.B) + + if (verbose) { + println(f"IF[0x$addr%04X] => 0x$result%08X") + } + } + } + } + + // `data` is 64K-element array of 16-bit memory words + // it will be modified upon stores + def handleDMem(dut: Core, data: collection.mutable.Map[Int, Int], verbose: Boolean = false): Unit = { + + breakable { + while (true) { + while (!dut.io.dbus_stb.peek().litToBoolean) { + dut.clock.step() + if (dut.io.halted.peek().litToBoolean) break + } + + val addr = (dut.io.dbus_addr.peek().litValue().toInt >> 1) << 1 + var result = 0 + if (dut.io.dbus_we.peek().litToBoolean) { + data.put(addr, dut.io.dbus_data_wr.peek().litValue().toInt) + if (verbose) { + println(f"M[0x$addr%04X] <= 0x${dut.io.dbus_data_wr.peek().litValue().toInt}%08X") + } + + } else { + result = data.getOrElse(addr, 0) + + if (verbose) { + println(f"M[0x$addr%04X] => 0x$result%08X") + } + } + + for (_ <- 0 until (Random.nextInt(3) + 2)) { // 2-5 cycle latency + dut.clock.step() + dut.io.dbus_stb.expect(false.B) + } + + dut.io.dbus_data_rd.poke(result.U) + dut.io.dbus_ack.poke(true.B) + dut.clock.step() + dut.io.dbus_ack.poke(false.B) + } + } + } + + def waitForHalt(dut: Core): Unit = { + while (!dut.io.halted.peek().litToBoolean) dut.clock.step() + } + + "should fetch instructions" in { + test(new Core(0x0000)) { dut => + val rand = new Random + + dut.io.ibus_ack.poke(false.B) + dut.io.dbus_ack.poke(false.B) + + dut.io.restart_core.poke(false.B) + + dut.io.waiting.expect(false.B) + dut.io.halted.expect(false.B) + + // Expect instruction fetch + dut.io.ibus_stb.expect(true.B) + dut.io.ibus_addr.expect(0.U) + + for (_ <- 0 until (Random.nextInt(10) + 2)) { + dut.clock.step() + dut.io.ibus_stb.expect(false.B) + } + + dut.io.ibus_ack.poke(true.B) + dut.io.ibus_data_rd.poke(0.U) // ADD r0, r0, r0 + + var i = 0 + while (!dut.io.ibus_stb.peek().litToBoolean) { + dut.clock.step() + i += 1 + } + + println(s"ADD r0, r0, r0 took $i cycles") + } + } + + "should issue loads" in { + test(new Core(0x0000)) { dut => + dut.io.ibus_ack.poke(false.B) + dut.io.dbus_ack.poke(false.B) + dut.io.restart_core.poke(false.B) + + dut.io.waiting.expect(false.B) + dut.io.halted.expect(false.B) + + val program = Array ( + b"0010 100 001 000 000", // LW r1, r0 + 0x1234, + b"1111 111 000 000 000", // STOP + ) + + fork { handleIFetch(dut, program, verbose = true) } .fork { + + while(!dut.io.dbus_stb.peek().litToBoolean) dut.clock.step(1) + println(f"LOAD, 0x${dut.io.dbus_addr.peek().litValue().toInt}%04X") + + dut.clock.step(2) + dut.io.dbus_data_rd.poke(0.U) + dut.io.dbus_ack.poke(true.B) + dut.clock.step(1) + dut.io.dbus_ack.poke(false.B) + + }.join() + } + } + + "should issue loads and stores" in { + test(new Core(0x0000)) { dut => + dut.io.ibus_ack.poke(false.B) + dut.io.dbus_ack.poke(false.B) + dut.io.restart_core.poke(false.B) + + dut.io.waiting.expect(false.B) + dut.io.halted.expect(false.B) + + val program = Array ( + asm(LW, rd = 1, rs1 = 0), + 0x1000, + asm(SW, rs1 = 0, rs2 = 1), + 0x1002, + asm(STOP) + ) + + val dmem = collection.mutable.Map ( + 0x1000 -> 0xABCD + ) + + fork { handleIFetch(dut, program, verbose = true) } + .fork { handleDMem(dut, dmem, verbose = true) } .fork { + + waitForHalt(dut) + assert(dmem(0x1002) == dmem(0x1000)) + + }.join() + } + } + + "should pass a test suite" in { + test(new Core(0x0000)) { dut => + dut.io.ibus_ack.poke(false.B) + dut.io.dbus_ack.poke(false.B) + dut.io.restart_core.poke(false.B) + + dut.io.waiting.expect(false.B) + dut.io.halted.expect(false.B) + + val memfile = Source.fromFile("testsuite.hex") + val program = memfile.getLines.map(x => Integer.parseInt(x, 16)).toArray + memfile.close() + + val dmem = collection.mutable.Map ( + 0x1000 -> 0xABCD, + 0x9000 -> 0x0000 + ) + + fork { handleIFetch(dut, program, verbose = true) } + .fork { handleDMem(dut, dmem, verbose = true) } .fork { + + waitForHalt(dut) + + if (dmem(0x9000) == 0xABCD) { + println("All tests passed") + } else if (dmem(0x9000) == 0x0001) { + println(s"Failed at test ${dmem(0x9002)}") + } else { + println("Failure: halted without reporting success or failure") + } + + }.join() + } + } + + /*"Gcd should calculate proper greatest common denominator" in { + test(new DecoupledGcd(16)) { dut => + dut.input.initSource() + dut.input.setSourceClock(dut.clock) + dut.output.initSink() + dut.output.setSinkClock(dut.clock) + + val testValues = for { x <- 0 to 10; y <- 0 to 10} yield (x, y) + val inputSeq = testValues.map { case (x, y) => (new GcdInputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U) } + val resultSeq = testValues.map { case (x, y) => + (new GcdOutputBundle(16)).Lit(_.value1 -> x.U, _.value2 -> y.U, _.gcd -> BigInt(x).gcd(BigInt(y)).U) + } + + fork { + // push inputs into the calculator, stall for 11 cycles one third of the way + val (seq1, seq2) = inputSeq.splitAt(resultSeq.length / 3) + dut.input.enqueueSeq(seq1) + dut.clock.step(11) + dut.input.enqueueSeq(seq2) + }.fork { + // retrieve computations from the calculator, stall for 10 cycles one half of the way + val (seq1, seq2) = resultSeq.splitAt(resultSeq.length / 2) + dut.output.expectDequeueSeq(seq1) + dut.clock.step(10) + dut.output.expectDequeueSeq(seq2) + }.join() + + } + }*/ +}
diff --git a/picorF0/testsuite.hex.txt b/picorF0/testsuite.hex.txt new file mode 100644 index 0000000..6f62e19 --- /dev/null +++ b/picorF0/testsuite.hex.txt
@@ -0,0 +1,3055 @@ +F800 +0200 +31C0 +ABCD +3807 +9000 +3800 +9002 +FE00 +31C0 +0001 +3807 +9000 +3801 +9002 +FE00 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +3040 +0001 +3100 +000B +3140 +0017 +00E5 +3080 +0022 +1013 +C800 +021E +F800 +0012 +2000 +3040 +0002 +3100 +000B +3140 +0017 +00E5 +C800 +0012 +F800 +0236 +2000 +3040 +0003 +3100 +000B +3140 +0017 +00E5 +A800 +0012 +F800 +024E +2000 +3040 +0004 +3100 +000B +3140 +0017 +00E5 +9800 +0012 +F800 +0266 +2000 +3040 +0005 +3100 +000B +3140 +0017 +00E5 +B800 +0012 +F800 +027E +2000 +3040 +0006 +3100 +8001 +3140 +8000 +00E5 +3080 +0001 +1013 +C800 +029C +F800 +0012 +2000 +3040 +0007 +3100 +8001 +3140 +8000 +00E5 +C800 +0012 +F800 +02B4 +2000 +3040 +0008 +3100 +8001 +3140 +8000 +00E5 +A800 +02CC +F800 +0012 +2000 +3040 +0009 +3100 +8001 +3140 +8000 +00E5 +9800 +0012 +F800 +02E4 +2000 +3040 +000A +3100 +8001 +3140 +8000 +00E5 +B800 +02FC +F800 +0012 +2000 +3040 +000B +3100 +8000 +3140 +7FFF +00E5 +3080 +FFFF +1013 +C800 +031A +F800 +0012 +2000 +3040 +000C +3100 +8000 +3140 +7FFF +00E5 +C800 +0012 +F800 +0332 +2000 +3040 +000D +3100 +8000 +3140 +7FFF +00E5 +A800 +0012 +F800 +034A +2000 +3040 +000E +3100 +8000 +3140 +7FFF +00E5 +9800 +0362 +F800 +0012 +2000 +3040 +000F +3100 +8000 +3140 +7FFF +00E5 +B800 +0012 +F800 +037A +2000 +3040 +0010 +3100 +8000 +3140 +8000 +00E5 +3080 +0000 +1013 +C800 +0398 +F800 +0012 +2000 +3040 +0011 +3100 +8000 +3140 +8000 +00E5 +C800 +03B0 +F800 +0012 +2000 +3040 +0012 +3100 +8000 +3140 +8000 +00E5 +A800 +03C8 +F800 +0012 +2000 +3040 +0013 +3100 +8000 +3140 +8000 +00E5 +9800 +0012 +F800 +03E0 +2000 +3040 +0014 +3100 +8000 +3140 +8000 +00E5 +B800 +03F8 +F800 +0012 +2000 +3040 +0015 +3100 +000B +30E0 +0017 +3080 +0022 +1013 +C800 +0414 +F800 +0012 +2000 +3040 +0016 +3100 +000B +30E0 +0017 +C800 +0012 +F800 +042A +2000 +3040 +0017 +3100 +000B +30E0 +0017 +A800 +0012 +F800 +0440 +2000 +3040 +0018 +3100 +000B +30E0 +0017 +9800 +0012 +F800 +0456 +2000 +3040 +0019 +3100 +000B +30E0 +0017 +B800 +0012 +F800 +046C +2000 +3040 +001A +3100 +8001 +30E0 +8000 +3080 +0001 +1013 +C800 +0488 +F800 +0012 +2000 +3040 +001B +3100 +8001 +30E0 +8000 +C800 +0012 +F800 +049E +2000 +3040 +001C +3100 +8001 +30E0 +8000 +A800 +04B4 +F800 +0012 +2000 +3040 +001D +3100 +8001 +30E0 +8000 +9800 +0012 +F800 +04CA +2000 +3040 +001E +3100 +8001 +30E0 +8000 +B800 +04E0 +F800 +0012 +2000 +3040 +001F +3100 +8000 +30E0 +7FFF +3080 +FFFF +1013 +C800 +04FC +F800 +0012 +2000 +3040 +0020 +3100 +8000 +30E0 +7FFF +C800 +0012 +F800 +0512 +2000 +3040 +0021 +3100 +8000 +30E0 +7FFF +A800 +0012 +F800 +0528 +2000 +3040 +0022 +3100 +8000 +30E0 +7FFF +9800 +053E +F800 +0012 +2000 +3040 +0023 +3100 +8000 +30E0 +7FFF +B800 +0012 +F800 +0554 +2000 +3040 +0024 +3100 +8000 +30E0 +8000 +3080 +0000 +1013 +C800 +0570 +F800 +0012 +2000 +3040 +0025 +3100 +8000 +30E0 +8000 +C800 +0586 +F800 +0012 +2000 +3040 +0026 +3100 +8000 +30E0 +8000 +A800 +059C +F800 +0012 +2000 +3040 +0027 +3100 +8000 +30E0 +8000 +9800 +0012 +F800 +05B2 +2000 +3040 +0028 +3100 +8000 +30E0 +8000 +B800 +05C8 +F800 +0012 +2000 +3040 +0029 +3100 +000B +3140 +0017 +90E5 +3080 +0003 +1013 +C800 +05E6 +F800 +0012 +2000 +3040 +002A +3100 +000B +3140 +0017 +90E5 +C800 +0012 +F800 +05FE +2000 +3040 +002B +3100 +000B +3140 +0017 +90E5 +A800 +0012 +F800 +0616 +2000 +3040 +002C +3100 +000B +3140 +0017 +90E5 +9800 +0012 +F800 +062E +2000 +3040 +002D +3100 +000B +3140 +0017 +90E5 +B800 +0012 +F800 +0646 +2000 +3040 +002E +3100 +AAAA +3140 +5555 +90E5 +3080 +0000 +1013 +C800 +0664 +F800 +0012 +2000 +3040 +002F +3100 +AAAA +3140 +5555 +90E5 +C800 +067C +F800 +0012 +2000 +3040 +0030 +3100 +AAAA +3140 +5555 +90E5 +A800 +0012 +F800 +0694 +2000 +3040 +0031 +3100 +AAAA +3140 +5555 +90E5 +9800 +0012 +F800 +06AC +2000 +3040 +0032 +3100 +AAAA +3140 +5555 +90E5 +B800 +0012 +F800 +06C4 +2000 +3040 +0033 +3100 +5381 +3140 +1AE4 +90E5 +3080 +1280 +1013 +C800 +06E2 +F800 +0012 +2000 +3040 +0034 +3100 +2342 +3140 +0123 +90E5 +3080 +0102 +1013 +C800 +0700 +F800 +0012 +2000 +3040 +0035 +3100 +0017 +3140 +000B +10E5 +3080 +000C +1013 +C800 +071E +F800 +0012 +2000 +3040 +0036 +3100 +0017 +3140 +000B +10E5 +C800 +0012 +F800 +0736 +2000 +3040 +0037 +3100 +0017 +3140 +000B +10E5 +A800 +0012 +F800 +074E +2000 +3040 +0038 +3100 +0017 +3140 +000B +10E5 +9800 +0012 +F800 +0766 +2000 +3040 +0039 +3100 +0017 +3140 +000B +10E5 +B800 +0012 +F800 +077E +2000 +3040 +003A +3100 +0017 +3140 +0017 +10E5 +3080 +0000 +1013 +C800 +079C +F800 +0012 +2000 +3040 +003B +3100 +0017 +3140 +0017 +10E5 +C800 +07B4 +F800 +0012 +2000 +3040 +003C +3100 +0017 +3140 +0017 +10E5 +A800 +07CC +F800 +0012 +2000 +3040 +003D +3100 +0017 +3140 +0017 +10E5 +9800 +0012 +F800 +07E4 +2000 +3040 +003E +3100 +0017 +3140 +0017 +10E5 +B800 +0012 +F800 +07FC +2000 +3040 +003F +3100 +0017 +3140 +0018 +10E5 +3080 +FFFF +1013 +C800 +081A +F800 +0012 +2000 +3040 +0040 +3100 +0017 +3140 +0018 +10E5 +C800 +0012 +F800 +0832 +2000 +3040 +0041 +3100 +0017 +3140 +0018 +10E5 +A800 +084A +F800 +0012 +2000 +3040 +0042 +3100 +0017 +3140 +0018 +10E5 +9800 +0862 +F800 +0012 +2000 +3040 +0043 +3100 +0017 +3140 +0018 +10E5 +B800 +0012 +F800 +087A +2000 +3040 +0044 +3100 +0017 +3140 +0019 +10E5 +3080 +FFFE +1013 +C800 +0898 +F800 +0012 +2000 +3040 +0045 +3100 +0017 +3140 +0019 +10E5 +C800 +0012 +F800 +08B0 +2000 +3040 +0046 +3100 +0017 +3140 +0019 +10E5 +A800 +08C8 +F800 +0012 +2000 +3040 +0047 +3100 +0017 +3140 +0019 +10E5 +9800 +08E0 +F800 +0012 +2000 +3040 +0048 +3100 +0017 +3140 +0019 +10E5 +B800 +0012 +F800 +08F8 +2000 +3040 +0049 +3100 +8000 +3140 +0001 +10E5 +3080 +7FFF +1013 +C800 +0916 +F800 +0012 +2000 +3040 +004A +3100 +8000 +3140 +0001 +10E5 +C800 +0012 +F800 +092E +2000 +3040 +004B +3100 +8000 +3140 +0001 +10E5 +A800 +0012 +F800 +0946 +2000 +3040 +004C +3100 +8000 +3140 +0001 +10E5 +9800 +0012 +F800 +095E +2000 +3040 +004D +3100 +8000 +3140 +0001 +10E5 +B800 +0976 +F800 +0012 +2000 +3040 +004E +3100 +0017 +3140 +000B +B0E5 +3080 +001C +1013 +C800 +0994 +F800 +0012 +2000 +3040 +004F +3100 +AAAA +3140 +5555 +B0E5 +3080 +FFFF +1013 +C800 +09B2 +F800 +0012 +2000 +3040 +0050 +3100 +0000 +3140 +0000 +B0E5 +3080 +0000 +1013 +C800 +09D0 +F800 +0012 +2000 +3040 +0051 +3100 +001F +3140 +0000 +C0E5 +3080 +001F +1013 +C800 +09EE +F800 +0012 +2000 +3040 +0052 +3100 +001F +C2E0 +0000 +3080 +001F +1013 +C800 +0A0A +F800 +0012 +2000 +3040 +0053 +3100 +001F +3140 +0001 +C0E5 +3080 +003E +1013 +C800 +0A28 +F800 +0012 +2000 +3040 +0054 +3100 +001F +C2E0 +0001 +3080 +003E +1013 +C800 +0A44 +F800 +0012 +2000 +3040 +0055 +3100 +001F +3140 +0002 +C0E5 +3080 +007C +1013 +C800 +0A62 +F800 +0012 +2000 +3040 +0056 +3100 +001F +C2E0 +0002 +3080 +007C +1013 +C800 +0A7E +F800 +0012 +2000 +3040 +0057 +3100 +001F +C2E0 +000F +3080 +8000 +1013 +C800 +0A9A +F800 +0012 +2000 +3040 +0058 +3100 +8000 +C2E0 +0001 +3080 +0000 +1013 +C800 +0AB6 +F800 +0012 +2000 +3040 +0059 +3100 +8000 +C2E0 +000F +3080 +0000 +1013 +C800 +0AD2 +F800 +0012 +2000 +3040 +005A +3100 +001F +3140 +0000 +E0E5 +3080 +001F +1013 +C800 +0AF0 +F800 +0012 +2000 +3040 +005B +3100 +001F +E2E0 +0000 +3080 +001F +1013 +C800 +0B0C +F800 +0012 +2000 +3040 +005C +3100 +001F +3140 +0001 +E0E5 +3080 +000F +1013 +C800 +0B2A +F800 +0012 +2000 +3040 +005D +3100 +001F +E2E0 +0001 +3080 +000F +1013 +C800 +0B46 +F800 +0012 +2000 +3040 +005E +3100 +001F +3140 +0002 +E0E5 +3080 +0007 +1013 +C800 +0B64 +F800 +0012 +2000 +3040 +005F +3100 +001F +E2E0 +0002 +3080 +0007 +1013 +C800 +0B80 +F800 +0012 +2000 +3040 +0060 +3100 +001F +E2E0 +000F +3080 +0000 +1013 +C800 +0B9C +F800 +0012 +2000 +3040 +0061 +3100 +8000 +E2E0 +0001 +3080 +4000 +1013 +C800 +0BB8 +F800 +0012 +2000 +3040 +0062 +3100 +8000 +E2E0 +000F +3080 +0001 +1013 +C800 +0BD4 +F800 +0012 +2000 +3040 +0063 +3100 +001F +3140 +0000 +F0E5 +3080 +001F +1013 +C800 +0BF2 +F800 +0012 +2000 +3040 +0064 +3100 +001F +F2E0 +0000 +3080 +001F +1013 +C800 +0C0E +F800 +0012 +2000 +3040 +0065 +3100 +001F +3140 +0001 +F0E5 +3080 +000F +1013 +C800 +0C2C +F800 +0012 +2000 +3040 +0066 +3100 +001F +F2E0 +0001 +3080 +000F +1013 +C800 +0C48 +F800 +0012 +2000 +3040 +0067 +3100 +001F +3140 +0002 +F0E5 +3080 +0007 +1013 +C800 +0C66 +F800 +0012 +2000 +3040 +0068 +3100 +001F +F2E0 +0002 +3080 +0007 +1013 +C800 +0C82 +F800 +0012 +2000 +3040 +0069 +3100 +001F +F2E0 +000F +3080 +0000 +1013 +C800 +0C9E +F800 +0012 +2000 +3040 +006A +3100 +8000 +F2E0 +0001 +3080 +C000 +1013 +C800 +0CBA +F800 +0012 +2000 +3040 +006B +3100 +8000 +F2E0 +000F +3080 +FFFF +1013 +C800 +0CD6 +F800 +0012 +2000 +3040 +006C +3100 +0017 +3140 +000B +50E5 +3080 +0000 +1013 +C800 +0CF4 +F800 +0012 +2000 +3040 +006D +3100 +0017 +3140 +000B +50E5 +C800 +0012 +F800 +0D0C +2000 +3040 +006E +3100 +0017 +3140 +000B +50E5 +A800 +0012 +F800 +0D24 +2000 +3040 +006F +3100 +0017 +3140 +000B +50E5 +9800 +0012 +F800 +0D3C +2000 +3040 +0070 +3100 +0017 +3140 +000B +50E5 +B800 +0012 +F800 +0D54 +2000 +3040 +0071 +3100 +0017 +52E0 +000B +3080 +0000 +1013 +C800 +0D70 +F800 +0012 +2000 +3040 +0072 +3100 +0017 +52E0 +000B +C800 +0012 +F800 +0D86 +2000 +3040 +0073 +3100 +0017 +52E0 +000B +A800 +0012 +F800 +0D9C +2000 +3040 +0074 +3100 +0017 +52E0 +000B +9800 +0012 +F800 +0DB2 +2000 +3040 +0075 +3100 +0017 +52E0 +000B +B800 +0012 +F800 +0DC8 +2000 +3040 +0076 +3100 +0017 +3140 +0017 +50E5 +3080 +0000 +1013 +C800 +0DE6 +F800 +0012 +2000 +3040 +0077 +3100 +0017 +3140 +0017 +50E5 +C800 +0DFE +F800 +0012 +2000 +3040 +0078 +3100 +0017 +3140 +0017 +50E5 +A800 +0E16 +F800 +0012 +2000 +3040 +0079 +3100 +0017 +3140 +0017 +50E5 +9800 +0012 +F800 +0E2E +2000 +3040 +007A +3100 +0017 +3140 +0017 +50E5 +B800 +0012 +F800 +0E46 +2000 +3040 +007B +3100 +0017 +52E0 +0017 +3080 +0000 +1013 +C800 +0E62 +F800 +0012 +2000 +3040 +007C +3100 +0017 +52E0 +0017 +C800 +0E78 +F800 +0012 +2000 +3040 +007D +3100 +0017 +52E0 +0017 +A800 +0E8E +F800 +0012 +2000 +3040 +007E +3100 +0017 +52E0 +0017 +9800 +0012 +F800 +0EA4 +2000 +3040 +007F +3100 +0017 +52E0 +0017 +B800 +0012 +F800 +0EBA +2000 +3040 +0080 +3100 +0017 +3140 +0018 +50E5 +3080 +0001 +1013 +C800 +0ED8 +F800 +0012 +2000 +3040 +0081 +3100 +0017 +3140 +0018 +50E5 +C800 +0012 +F800 +0EF0 +2000 +3040 +0082 +3100 +0017 +3140 +0018 +50E5 +A800 +0F08 +F800 +0012 +2000 +3040 +0083 +3100 +0017 +3140 +0018 +50E5 +9800 +0F20 +F800 +0012 +2000 +3040 +0084 +3100 +0017 +3140 +0018 +50E5 +B800 +0012 +F800 +0F38 +2000 +3040 +0085 +3100 +0017 +52E0 +0018 +3080 +0001 +1013 +C800 +0F54 +F800 +0012 +2000 +3040 +0086 +3100 +0017 +52E0 +0018 +C800 +0012 +F800 +0F6A +2000 +3040 +0087 +3100 +0017 +52E0 +0018 +A800 +0F80 +F800 +0012 +2000 +3040 +0088 +3100 +0017 +52E0 +0018 +9800 +0F96 +F800 +0012 +2000 +3040 +0089 +3100 +0017 +52E0 +0018 +B800 +0012 +F800 +0FAC +2000 +3040 +008A +3100 +0017 +3140 +0019 +50E5 +3080 +0001 +1013 +C800 +0FCA +F800 +0012 +2000 +3040 +008B +3100 +0017 +3140 +0019 +50E5 +C800 +0012 +F800 +0FE2 +2000 +3040 +008C +3100 +0017 +3140 +0019 +50E5 +A800 +0FFA +F800 +0012 +2000 +3040 +008D +3100 +0017 +3140 +0019 +50E5 +9800 +1012 +F800 +0012 +2000 +3040 +008E +3100 +0017 +3140 +0019 +50E5 +B800 +0012 +F800 +102A +2000 +3040 +008F +3100 +0017 +52E0 +0019 +3080 +0001 +1013 +C800 +1046 +F800 +0012 +2000 +3040 +0090 +3100 +0017 +52E0 +0019 +C800 +0012 +F800 +105C +2000 +3040 +0091 +3100 +0017 +52E0 +0019 +A800 +1072 +F800 +0012 +2000 +3040 +0092 +3100 +0017 +52E0 +0019 +9800 +1088 +F800 +0012 +2000 +3040 +0093 +3100 +0017 +52E0 +0019 +B800 +0012 +F800 +109E +2000 +3040 +0094 +3100 +8000 +3140 +0001 +50E5 +3080 +0001 +1013 +C800 +10BC +F800 +0012 +2000 +3040 +0095 +3100 +8000 +3140 +0001 +50E5 +C800 +0012 +F800 +10D4 +2000 +3040 +0096 +3100 +8000 +3140 +0001 +50E5 +A800 +0012 +F800 +10EC +2000 +3040 +0097 +3100 +8000 +3140 +0001 +50E5 +9800 +0012 +F800 +1104 +2000 +3040 +0098 +3100 +8000 +3140 +0001 +50E5 +B800 +111C +F800 +0012 +2000 +3040 +0099 +3100 +8000 +52E0 +0001 +3080 +0001 +1013 +C800 +1138 +F800 +0012 +2000 +3040 +009A +3100 +8000 +52E0 +0001 +C800 +0012 +F800 +114E +2000 +3040 +009B +3100 +8000 +52E0 +0001 +A800 +0012 +F800 +1164 +2000 +3040 +009C +3100 +8000 +52E0 +0001 +9800 +0012 +F800 +117A +2000 +3040 +009D +3100 +8000 +52E0 +0001 +B800 +1190 +F800 +0012 +2000 +3040 +009E +3100 +0017 +3140 +000B +50E5 +3080 +0000 +1013 +C800 +11AE +F800 +0012 +2000 +3040 +009F +3100 +0017 +3140 +000B +50E5 +C800 +0012 +F800 +11C6 +2000 +3040 +00A0 +3100 +0017 +3140 +000B +50E5 +A800 +0012 +F800 +11DE +2000 +3040 +00A1 +3100 +0017 +3140 +000B +50E5 +9800 +0012 +F800 +11F6 +2000 +3040 +00A2 +3100 +0017 +3140 +000B +50E5 +B800 +0012 +F800 +120E +2000 +3040 +00A3 +3100 +0017 +52E0 +000B +3080 +0000 +1013 +C800 +122A +F800 +0012 +2000 +3040 +00A4 +3100 +0017 +52E0 +000B +C800 +0012 +F800 +1240 +2000 +3040 +00A5 +3100 +0017 +52E0 +000B +A800 +0012 +F800 +1256 +2000 +3040 +00A6 +3100 +0017 +52E0 +000B +9800 +0012 +F800 +126C +2000 +3040 +00A7 +3100 +0017 +52E0 +000B +B800 +0012 +F800 +1282 +2000 +3040 +00A8 +3100 +0017 +3140 +0017 +50E5 +3080 +0000 +1013 +C800 +12A0 +F800 +0012 +2000 +3040 +00A9 +3100 +0017 +3140 +0017 +50E5 +C800 +12B8 +F800 +0012 +2000 +3040 +00AA +3100 +0017 +3140 +0017 +50E5 +A800 +12D0 +F800 +0012 +2000 +3040 +00AB +3100 +0017 +3140 +0017 +50E5 +9800 +0012 +F800 +12E8 +2000 +3040 +00AC +3100 +0017 +3140 +0017 +50E5 +B800 +0012 +F800 +1300 +2000 +3040 +00AD +3100 +0017 +52E0 +0017 +3080 +0000 +1013 +C800 +131C +F800 +0012 +2000 +3040 +00AE +3100 +0017 +52E0 +0017 +C800 +1332 +F800 +0012 +2000 +3040 +00AF +3100 +0017 +52E0 +0017 +A800 +1348 +F800 +0012 +2000 +3040 +00B0 +3100 +0017 +52E0 +0017 +9800 +0012 +F800 +135E +2000 +3040 +00B1 +3100 +0017 +52E0 +0017 +B800 +0012 +F800 +1374 +2000 +3040 +00B2 +3100 +0017 +3140 +0018 +50E5 +3080 +0001 +1013 +C800 +1392 +F800 +0012 +2000 +3040 +00B3 +3100 +0017 +3140 +0018 +50E5 +C800 +0012 +F800 +13AA +2000 +3040 +00B4 +3100 +0017 +3140 +0018 +50E5 +A800 +13C2 +F800 +0012 +2000 +3040 +00B5 +3100 +0017 +3140 +0018 +50E5 +9800 +13DA +F800 +0012 +2000 +3040 +00B6 +3100 +0017 +3140 +0018 +50E5 +B800 +0012 +F800 +13F2 +2000 +3040 +00B7 +3100 +0017 +52E0 +0018 +3080 +0001 +1013 +C800 +140E +F800 +0012 +2000 +3040 +00B8 +3100 +0017 +52E0 +0018 +C800 +0012 +F800 +1424 +2000 +3040 +00B9 +3100 +0017 +52E0 +0018 +A800 +143A +F800 +0012 +2000 +3040 +00BA +3100 +0017 +52E0 +0018 +9800 +1450 +F800 +0012 +2000 +3040 +00BB +3100 +0017 +52E0 +0018 +B800 +0012 +F800 +1466 +2000 +3040 +00BC +3100 +0017 +3140 +0019 +50E5 +3080 +0001 +1013 +C800 +1484 +F800 +0012 +2000 +3040 +00BD +3100 +0017 +3140 +0019 +50E5 +C800 +0012 +F800 +149C +2000 +3040 +00BE +3100 +0017 +3140 +0019 +50E5 +A800 +14B4 +F800 +0012 +2000 +3040 +00BF +3100 +0017 +3140 +0019 +50E5 +9800 +14CC +F800 +0012 +2000 +3040 +00C0 +3100 +0017 +3140 +0019 +50E5 +B800 +0012 +F800 +14E4 +2000 +3040 +00C1 +3100 +0017 +52E0 +0019 +3080 +0001 +1013 +C800 +1500 +F800 +0012 +2000 +3040 +00C2 +3100 +0017 +52E0 +0019 +C800 +0012 +F800 +1516 +2000 +3040 +00C3 +3100 +0017 +52E0 +0019 +A800 +152C +F800 +0012 +2000 +3040 +00C4 +3100 +0017 +52E0 +0019 +9800 +1542 +F800 +0012 +2000 +3040 +00C5 +3100 +0017 +52E0 +0019 +B800 +0012 +F800 +1558 +2000 +3040 +00C6 +3100 +8000 +3140 +0001 +50E5 +3080 +0001 +1013 +C800 +1576 +F800 +0012 +2000 +3040 +00C7 +3100 +8000 +3140 +0001 +50E5 +C800 +0012 +F800 +158E +2000 +3040 +00C8 +3100 +8000 +3140 +0001 +50E5 +A800 +0012 +F800 +15A6 +2000 +3040 +00C9 +3100 +8000 +3140 +0001 +50E5 +9800 +0012 +F800 +15BE +2000 +3040 +00CA +3100 +8000 +3140 +0001 +50E5 +B800 +15D6 +F800 +0012 +2000 +3040 +00CB +3100 +8000 +52E0 +0001 +3080 +0001 +1013 +C800 +15F2 +F800 +0012 +2000 +3040 +00CC +3100 +8000 +52E0 +0001 +C800 +0012 +F800 +1608 +2000 +3040 +00CD +3100 +8000 +52E0 +0001 +A800 +0012 +F800 +161E +2000 +3040 +00CE +3100 +8000 +52E0 +0001 +9800 +0012 +F800 +1634 +2000 +3040 +00CF +3100 +8000 +52E0 +0001 +B800 +164A +F800 +0012 +2000 +3040 +00D0 +3100 +0017 +3140 +0000 +20E0 +3080 +0017 +1013 +C800 +1668 +F800 +0012 +2000 +3040 +00D1 +3100 +0020 +3140 +0000 +20E0 +3080 +0020 +1013 +C800 +1686 +F800 +0012 +2000 +3040 +00D2 +3100 +8000 +3140 +0000 +20E0 +3080 +8000 +1013 +C800 +16A4 +F800 +0012 +2000 +3040 +00D3 +3100 +0000 +3140 +0000 +20E0 +3080 +0000 +1013 +C800 +16C2 +F800 +0012 +2000 +3040 +00D4 +3100 +0017 +3140 +0000 +80E0 +3080 +FFE8 +1013 +C800 +16E0 +F800 +0012 +2000 +3040 +00D5 +3100 +0020 +3140 +0000 +80E0 +3080 +FFDF +1013 +C800 +16FE +F800 +0012 +2000 +3040 +00D6 +3100 +8000 +3140 +0000 +80E0 +3080 +7FFF +1013 +C800 +171C +F800 +0012 +2000 +3040 +00D7 +3100 +0000 +3140 +0000 +80E0 +3080 +FFFF +1013 +C800 +173A +F800 +0012 +2000 +3040 +00D8 +3100 +0017 +3140 +0000 +80E0 +3080 +FFE8 +1013 +C800 +1758 +F800 +0012 +2000 +3040 +00D9 +3100 +0020 +3140 +0000 +80E0 +3080 +FFDF +1013 +C800 +1776 +F800 +0012 +2000 +3040 +00DA +3100 +8000 +3140 +0000 +80E0 +3080 +7FFF +1013 +C800 +1794 +F800 +0012 +2000 +3040 +00DB +3100 +0000 +3140 +0000 +80E0 +3080 +FFFF +1013 +C800 +17B2 +F800 +0012 +2000 +3040 +0220 +30C0 +ABCD +3080 +A000 +3813 +0323 +3100 +0323 +2920 +A000 +5220 +ABCD +C800 +17D8 +F800 +0012 +2000 +F800 +0004