├── .gitignore ├── program ├── .gitignore ├── 3rd_party │ └── emballoc │ │ ├── .circleci │ │ ├── .dockerignore │ │ ├── coverage.Dockerfile │ │ ├── miri.Dockerfile │ │ ├── README.md │ │ └── config.yml │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── LICENSE-MIT │ │ └── README.md ├── src │ ├── allocator.rs │ ├── bin │ │ ├── tetris │ │ │ ├── game │ │ │ │ ├── mod.rs │ │ │ │ ├── phase │ │ │ │ │ ├── finished.rs │ │ │ │ │ ├── menu.rs │ │ │ │ │ └── running.rs │ │ │ │ ├── phase.rs │ │ │ │ ├── math.rs │ │ │ │ ├── logic.rs │ │ │ │ ├── cycle.rs │ │ │ │ ├── level.rs │ │ │ │ └── state.rs │ │ │ ├── main.rs │ │ │ ├── LICENSE │ │ │ ├── input.rs │ │ │ └── tetrs.rs │ │ ├── main.rs │ │ ├── keyboard.rs │ │ ├── loader.rs │ │ ├── task1.rs │ │ ├── tubeshow.rs │ │ └── task2.rs │ ├── prelude.rs │ ├── lang_items.rs │ ├── tube.rs │ ├── uart.rs │ ├── entry.asm │ ├── linker-loader.ld │ ├── linker-program.ld │ ├── time.rs │ ├── rng.rs │ ├── lib.rs │ ├── board.rs │ ├── console.rs │ └── monitor.rs ├── .cargo │ └── config ├── fill.py ├── Cargo.toml ├── Cargo.lock └── Makefile ├── chisel ├── project │ ├── plugins.sbt │ └── build.properties ├── src │ ├── main │ │ └── scala │ │ │ ├── util │ │ │ ├── Helper.scala │ │ │ ├── Split.scala │ │ │ ├── GenerateOptions.scala │ │ │ ├── Counter.scala │ │ │ ├── Emit.scala │ │ │ ├── NumberExtend.scala │ │ │ ├── Encoder.scala │ │ │ └── Switch.scala │ │ │ ├── misc │ │ │ ├── RNG.scala │ │ │ ├── CrossClockQueue.scala │ │ │ └── Debounce.scala │ │ │ ├── Top.scala │ │ │ ├── core │ │ │ ├── ALU.scala │ │ │ ├── RegisterFile.scala │ │ │ ├── Comparator.scala │ │ │ └── Core.scala │ │ │ ├── ip │ │ │ ├── BlockMemoryRom.scala │ │ │ ├── ClockWizard.scala │ │ │ └── BlockMemory.scala │ │ │ └── board │ │ │ ├── Keyboard.scala │ │ │ ├── display │ │ │ ├── Color.scala │ │ │ ├── VGA.scala │ │ │ └── Console.scala │ │ │ ├── UART.scala │ │ │ ├── Board.scala │ │ │ └── Tubes.scala │ └── test │ │ └── scala │ │ └── core │ │ ├── TubesSpec.scala │ │ ├── ALUSpec.scala │ │ ├── CoreSpec.scala │ │ ├── UARTSpec.scala │ │ └── MemorySpec.scala ├── build.sbt ├── build.sc └── README.md ├── generated ├── Top.bit ├── tetris.bin └── README.md ├── .gitattributes ├── font ├── 0000-007F Basic Latin │ ├── 0020.png │ ├── 0021.png │ ├── 0022.png │ ├── 0023.png │ ├── 0024.png │ ├── 0025.png │ ├── 0026.png │ ├── 0027.png │ ├── 0028.png │ ├── 0029.png │ ├── 002A.png │ ├── 002B.png │ ├── 002C.png │ ├── 002D.png │ ├── 002E.png │ ├── 002F.png │ ├── 0030.png │ ├── 0031.png │ ├── 0032.png │ ├── 0033.png │ ├── 0034.png │ ├── 0035.png │ ├── 0036.png │ ├── 0037.png │ ├── 0038.png │ ├── 0039.png │ ├── 003A.png │ ├── 003B.png │ ├── 003C.png │ ├── 003D.png │ ├── 003E.png │ ├── 003F.png │ ├── 0040.png │ ├── 0041.png │ ├── 0042.png │ ├── 0043.png │ ├── 0044.png │ ├── 0045.png │ ├── 0046.png │ ├── 0047.png │ ├── 0048.png │ ├── 0049.png │ ├── 004A.png │ ├── 004B.png │ ├── 004C.png │ ├── 004D.png │ ├── 004E.png │ ├── 004F.png │ ├── 0050.png │ ├── 0051.png │ ├── 0052.png │ ├── 0053.png │ ├── 0054.png │ ├── 0055.png │ ├── 0056.png │ ├── 0057.png │ ├── 0058.png │ ├── 0059.png │ ├── 005A.png │ ├── 005B.png │ ├── 005C.png │ ├── 005D.png │ ├── 005E.png │ ├── 005F.png │ ├── 0060.png │ ├── 0061.png │ ├── 0062.png │ ├── 0063.png │ ├── 0064.png │ ├── 0065.png │ ├── 0066.png │ ├── 0067.png │ ├── 0068.png │ ├── 0069.png │ ├── 006A.png │ ├── 006B.png │ ├── 006C.png │ ├── 006D.png │ ├── 006E.png │ ├── 006F.png │ ├── 0070.png │ ├── 0071.png │ ├── 0072.png │ ├── 0073.png │ ├── 0074.png │ ├── 0075.png │ ├── 0076.png │ ├── 0077.png │ ├── 0078.png │ ├── 0079.png │ ├── 007A.png │ ├── 007B.png │ ├── 007C.png │ ├── 007D.png │ └── 007E.png ├── font_data │ ├── 20.txt │ ├── 21.txt │ ├── 22.txt │ ├── 23.txt │ ├── 24.txt │ ├── 25.txt │ ├── 26.txt │ ├── 27.txt │ ├── 28.txt │ ├── 29.txt │ ├── 2A.txt │ ├── 2B.txt │ ├── 2C.txt │ ├── 2D.txt │ ├── 2E.txt │ ├── 2F.txt │ ├── 30.txt │ ├── 31.txt │ ├── 32.txt │ ├── 33.txt │ ├── 34.txt │ ├── 35.txt │ ├── 36.txt │ ├── 37.txt │ ├── 38.txt │ ├── 39.txt │ ├── 3A.txt │ ├── 3B.txt │ ├── 3C.txt │ ├── 3D.txt │ ├── 3E.txt │ ├── 3F.txt │ ├── 40.txt │ ├── 41.txt │ ├── 42.txt │ ├── 43.txt │ ├── 44.txt │ ├── 45.txt │ ├── 46.txt │ ├── 47.txt │ ├── 48.txt │ ├── 49.txt │ ├── 4A.txt │ ├── 4B.txt │ ├── 4C.txt │ ├── 4D.txt │ ├── 4E.txt │ ├── 4F.txt │ ├── 50.txt │ ├── 51.txt │ ├── 52.txt │ ├── 53.txt │ ├── 54.txt │ ├── 55.txt │ ├── 56.txt │ ├── 57.txt │ ├── 58.txt │ ├── 59.txt │ ├── 5A.txt │ ├── 5B.txt │ ├── 5C.txt │ ├── 5D.txt │ ├── 5E.txt │ ├── 5F.txt │ ├── 60.txt │ ├── 61.txt │ ├── 62.txt │ ├── 63.txt │ ├── 64.txt │ ├── 65.txt │ ├── 66.txt │ ├── 67.txt │ ├── 68.txt │ ├── 69.txt │ ├── 6A.txt │ ├── 6B.txt │ ├── 6C.txt │ ├── 6D.txt │ ├── 6E.txt │ ├── 6F.txt │ ├── 70.txt │ ├── 71.txt │ ├── 72.txt │ ├── 73.txt │ ├── 74.txt │ ├── 75.txt │ ├── 76.txt │ ├── 77.txt │ ├── 78.txt │ ├── 79.txt │ ├── 7A.txt │ ├── 7B.txt │ ├── 7C.txt │ ├── 7D.txt │ ├── 7E.txt │ ├── A0.txt │ ├── A1.txt │ ├── A2.txt │ ├── A3.txt │ ├── A4.txt │ └── A5.txt ├── README.md ├── LICENSE-MIT ├── convert.py └── LICENSE-OFL └── simulation └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /program/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /bin 3 | -------------------------------------------------------------------------------- /chisel/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn 2 | -------------------------------------------------------------------------------- /chisel/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 1.8.0 2 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.circleci/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /generated/Top.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/generated/Top.bit -------------------------------------------------------------------------------- /generated/tetris.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/generated/tetris.bin -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # generated files 2 | generated/** linguist-generated 3 | generated/README.md linguist-documentation 4 | -------------------------------------------------------------------------------- /program/src/allocator.rs: -------------------------------------------------------------------------------- 1 | #[global_allocator] 2 | static ALLOCATOR: emballoc::Allocator<16384> = emballoc::Allocator::new(); 3 | -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0020.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0021.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0022.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0023.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0024.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0025.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0026.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0027.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0027.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0028.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0029.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002E.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/002F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/002F.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0030.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0030.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0031.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0032.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0032.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0033.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0034.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0035.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0035.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0036.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0037.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0037.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0038.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0038.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0039.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0039.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003E.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/003F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/003F.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0040.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0040.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0041.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0042.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0043.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0044.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0044.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0045.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0046.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0046.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0047.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0048.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0049.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0049.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004E.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/004F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/004F.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0050.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0050.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0051.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0052.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0053.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0054.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0054.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0055.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0055.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0056.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0056.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0057.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0057.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0058.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0058.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0059.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0059.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005E.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/005F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/005F.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0060.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0060.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0061.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0061.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0062.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0062.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0063.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0063.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0064.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0064.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0065.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0065.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0066.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0066.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0067.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0068.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0068.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0069.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0069.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006E.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/006F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/006F.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0070.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0071.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0071.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0072.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0072.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0073.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0073.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0074.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0075.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0075.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0076.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0076.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0077.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0077.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0078.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0078.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/0079.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/0079.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/007A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/007A.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/007B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/007B.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/007C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/007C.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/007D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/007D.png -------------------------------------------------------------------------------- /font/0000-007F Basic Latin/007E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YanWQ-monad/SUSTech_CS202_Project-CPU/HEAD/font/0000-007F Basic Latin/007E.png -------------------------------------------------------------------------------- /program/src/bin/tetris/game/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cycle; 2 | pub mod level; 3 | pub mod logic; 4 | pub mod math; 5 | pub mod state; 6 | pub mod tetromino; 7 | 8 | pub mod phase; 9 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Helper.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | object Helper { 4 | def log2(n: Int): Int = { 5 | LazyList.from(1).filter(x => n <= (1 << x)).head 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /program/src/prelude.rs: -------------------------------------------------------------------------------- 1 | pub use crate::board::*; 2 | pub use crate::console::*; 3 | pub use crate::monitor::monitor; 4 | pub use crate::time::*; 5 | pub use crate::tube::*; 6 | pub use crate::uart; 7 | -------------------------------------------------------------------------------- /program/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32i-unknown-none-elf" 3 | 4 | [target.riscv32i-unknown-none-elf] 5 | rustflags = [ 6 | "-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" 7 | ] 8 | -------------------------------------------------------------------------------- /font/font_data/20.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/21.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ___*____ 5 | __***___ 6 | __***___ 7 | __***___ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ________ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/22.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __*_*___ 5 | __*_*___ 6 | __*_*___ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/23.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __*__*__ 5 | __*__*__ 6 | _******_ 7 | __*__*__ 8 | __*__*__ 9 | __*__*__ 10 | __*__*__ 11 | _******_ 12 | __*__*__ 13 | __*__*__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/24.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ___*____ 4 | _*****__ 5 | *__*__*_ 6 | *__*____ 7 | *__*____ 8 | _***____ 9 | ___***__ 10 | ___*__*_ 11 | ___*__*_ 12 | *__*__*_ 13 | _*****__ 14 | ___*____ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/25.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _*___*__ 5 | *_*__*__ 6 | _*__*___ 7 | ____*___ 8 | ___*____ 9 | ___*____ 10 | __*_____ 11 | __*__*__ 12 | _*__*_*_ 13 | _*___*__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/26.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __**____ 5 | _*__*___ 6 | _*__*___ 7 | _*__*___ 8 | __**____ 9 | _*_*__*_ 10 | *___*_*_ 11 | *____*__ 12 | *____*__ 13 | _****_*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/27.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/28.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _____*__ 4 | ____*___ 5 | ____*___ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ____*___ 14 | ____*___ 15 | _____*__ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/29.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _*______ 4 | __*_____ 5 | __*_____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | __*_____ 14 | __*_____ 15 | _*______ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ___*____ 8 | _*_*_*__ 9 | __***___ 10 | _*_*_*__ 11 | ___*____ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ___*____ 8 | ___*____ 9 | _*****__ 10 | ___*____ 11 | ___*____ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ___**___ 13 | ___**___ 14 | ____*___ 15 | ___*____ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ________ 9 | _*****__ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ___**___ 13 | ___**___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/2F.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _____*__ 4 | _____*__ 5 | ____*___ 6 | ____*___ 7 | ____*___ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | __*_____ 12 | __*_____ 13 | __*_____ 14 | _*______ 15 | _*______ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/30.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | _*____*_ 7 | _*___**_ 8 | _*__*_*_ 9 | _*_*__*_ 10 | _**___*_ 11 | _*____*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/31.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ____*___ 5 | ___**___ 6 | __*_*___ 7 | ____*___ 8 | ____*___ 9 | ____*___ 10 | ____*___ 11 | ____*___ 12 | ____*___ 13 | ____*___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/32.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | ______*_ 7 | ______*_ 8 | _____*__ 9 | ____*___ 10 | ___*____ 11 | __*_____ 12 | _*______ 13 | _******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/33.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | ______*_ 7 | ______*_ 8 | ___***__ 9 | ______*_ 10 | ______*_ 11 | ______*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/34.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ____**__ 5 | ___*_*__ 6 | ___*_*__ 7 | __*__*__ 8 | __*__*__ 9 | _*___*__ 10 | _*___*__ 11 | _******_ 12 | _____*__ 13 | _____*__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/35.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _******_ 5 | _*______ 6 | _*______ 7 | _*______ 8 | _*****__ 9 | ______*_ 10 | ______*_ 11 | ______*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/36.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | _*______ 7 | _*______ 8 | _*****__ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/37.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _******_ 5 | ______*_ 6 | ______*_ 7 | _____*__ 8 | _____*__ 9 | _____*__ 10 | ____*___ 11 | ____*___ 12 | ____*___ 13 | ____*___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/38.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | _*____*_ 7 | _*____*_ 8 | __****__ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/39.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | _*____*_ 7 | _*____*_ 8 | _*____*_ 9 | __*****_ 10 | ______*_ 11 | ______*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ___**___ 8 | ___**___ 9 | ________ 10 | ________ 11 | ________ 12 | ___**___ 13 | ___**___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ___**___ 8 | ___**___ 9 | ________ 10 | ________ 11 | ________ 12 | ___**___ 13 | ___**___ 14 | ____*___ 15 | ___*____ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | _____*__ 7 | ____*___ 8 | ___*____ 9 | __*_____ 10 | ___*____ 11 | ____*___ 12 | _____*__ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | _*****__ 9 | ________ 10 | _*****__ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | __*_____ 7 | ___*____ 8 | ____*___ 9 | _____*__ 10 | ____*___ 11 | ___*____ 12 | __*_____ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/3F.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | _*____*_ 7 | ______*_ 8 | _____*__ 9 | ____*___ 10 | ____*___ 11 | ____*___ 12 | ________ 13 | ____*___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/40.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __***___ 5 | _*___*__ 6 | *_____*_ 7 | *__**_*_ 8 | *_*_*_*_ 9 | *_*_*_*_ 10 | *_*_*_*_ 11 | *_**_**_ 12 | *_______ 13 | _*______ 14 | __****__ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/41.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ___*____ 5 | ___*____ 6 | __*_*___ 7 | __*_*___ 8 | _*___*__ 9 | _*___*__ 10 | _*****__ 11 | *_____*_ 12 | *_____*_ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/42.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ******__ 5 | *_____*_ 6 | *_____*_ 7 | *_____*_ 8 | ******__ 9 | *_____*_ 10 | *_____*_ 11 | *_____*_ 12 | *_____*_ 13 | ******__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/43.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | *_______ 7 | *_______ 8 | *_______ 9 | *_______ 10 | *_______ 11 | *_______ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/44.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *****___ 5 | *____*__ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | *_____*_ 10 | *_____*_ 11 | *_____*_ 12 | *____*__ 13 | *****___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/45.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *******_ 5 | *_______ 6 | *_______ 7 | *_______ 8 | ******__ 9 | *_______ 10 | *_______ 11 | *_______ 12 | *_______ 13 | *******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/46.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *******_ 5 | *_______ 6 | *_______ 7 | *_______ 8 | ******__ 9 | *_______ 10 | *_______ 11 | *_______ 12 | *_______ 13 | *_______ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/47.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __****__ 5 | _*____*_ 6 | *_______ 7 | *_______ 8 | *_______ 9 | *___***_ 10 | *_____*_ 11 | *_____*_ 12 | _*____*_ 13 | __*****_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/48.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | *_____*_ 6 | *_____*_ 7 | *_____*_ 8 | *******_ 9 | *_____*_ 10 | *_____*_ 11 | *_____*_ 12 | *_____*_ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/49.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *******_ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | *******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ______*_ 5 | ______*_ 6 | ______*_ 7 | ______*_ 8 | ______*_ 9 | ______*_ 10 | *_____*_ 11 | *_____*_ 12 | _*___*__ 13 | __***___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | *____*__ 6 | *__**___ 7 | *_*_____ 8 | **______ 9 | *_*_____ 10 | *__*____ 11 | *___*___ 12 | *____*__ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_______ 5 | *_______ 6 | *_______ 7 | *_______ 8 | *_______ 9 | *_______ 10 | *_______ 11 | *_______ 12 | *_______ 13 | *******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | **___**_ 6 | **___**_ 7 | *_*_*_*_ 8 | *_*_*_*_ 9 | *__*__*_ 10 | *__*__*_ 11 | *_____*_ 12 | *_____*_ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | **____*_ 6 | **____*_ 7 | *_*___*_ 8 | *__*__*_ 9 | *__*__*_ 10 | *___*_*_ 11 | *____**_ 12 | *____**_ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/4F.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __***___ 5 | _*___*__ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | *_____*_ 10 | *_____*_ 11 | *_____*_ 12 | _*___*__ 13 | __***___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/50.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ******__ 5 | *_____*_ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | ******__ 10 | *_______ 11 | *_______ 12 | *_______ 13 | *_______ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/51.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __***___ 5 | _*___*__ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | *_____*_ 10 | *_____*_ 11 | *___*_*_ 12 | _*___*__ 13 | __***_*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/52.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ******__ 5 | *_____*_ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | ******__ 10 | *__*____ 11 | *___*___ 12 | *____*__ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/53.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _*****__ 5 | *_____*_ 6 | *_______ 7 | *_______ 8 | _***____ 9 | ____**__ 10 | ______*_ 11 | ______*_ 12 | *_____*_ 13 | _*****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/54.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *******_ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/55.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | *_____*_ 6 | *_____*_ 7 | *_____*_ 8 | *_____*_ 9 | *_____*_ 10 | *_____*_ 11 | *_____*_ 12 | _*___*__ 13 | __***___ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/56.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | *_____*_ 6 | _*___*__ 7 | _*___*__ 8 | _*___*__ 9 | __*_*___ 10 | __*_*___ 11 | __*_*___ 12 | ___*____ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/57.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *__*__*_ 5 | *__*__*_ 6 | *__*__*_ 7 | *__*__*_ 8 | *_*_*_*_ 9 | *_*_*_*_ 10 | *_*_*_*_ 11 | _*___*__ 12 | _*___*__ 13 | _*___*__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/58.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | _*___*__ 6 | _*___*__ 7 | __*_*___ 8 | ___*____ 9 | __*_*___ 10 | _*___*__ 11 | _*___*__ 12 | *_____*_ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/59.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *_____*_ 5 | *_____*_ 6 | _*___*__ 7 | _*___*__ 8 | __*_*___ 9 | __*_*___ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | *******_ 5 | ______*_ 6 | _____*__ 7 | ____*___ 8 | ___*____ 9 | ___*____ 10 | __*_____ 11 | _*______ 12 | *_______ 13 | *******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ___***__ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ___*____ 15 | ___***__ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _*______ 4 | _*______ 5 | __*_____ 6 | __*_____ 7 | __*_____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ____*___ 12 | ____*___ 13 | ____*___ 14 | _____*__ 15 | _____*__ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _***____ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ___*____ 15 | _***____ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ___*____ 5 | __*_*___ 6 | _*___*__ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/5F.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | *******_ 17 | -------------------------------------------------------------------------------- /font/font_data/60.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | __*_____ 5 | ___*____ 6 | ____*___ 7 | ________ 8 | ________ 9 | ________ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/61.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __****__ 8 | ______*_ 9 | ______*_ 10 | __*****_ 11 | _*____*_ 12 | _*____*_ 13 | __*****_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/62.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _*______ 5 | _*______ 6 | _*______ 7 | _*****__ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | _*****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/63.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __****__ 8 | _*____*_ 9 | _*______ 10 | _*______ 11 | _*______ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/64.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ______*_ 5 | ______*_ 6 | ______*_ 7 | __*****_ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __*****_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/65.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __****__ 8 | _*____*_ 9 | _*____*_ 10 | _******_ 11 | _*______ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/66.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ____***_ 5 | ___*____ 6 | ___*____ 7 | _******_ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/67.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __*****_ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __*****_ 14 | ______*_ 15 | ______*_ 16 | __****__ 17 | -------------------------------------------------------------------------------- /font/font_data/68.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _*______ 5 | _*______ 6 | _*______ 7 | _*_***__ 8 | _**___*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | _*____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/69.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ____*___ 5 | ________ 6 | ________ 7 | _****___ 8 | ____*___ 9 | ____*___ 10 | ____*___ 11 | ____*___ 12 | ____*___ 13 | _******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/6A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _____*__ 5 | ________ 6 | ________ 7 | _*****__ 8 | _____*__ 9 | _____*__ 10 | _____*__ 11 | _____*__ 12 | _____*__ 13 | _____*__ 14 | _____*__ 15 | _____*__ 16 | _****___ 17 | -------------------------------------------------------------------------------- /font/font_data/6B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _*______ 5 | _*______ 6 | _*______ 7 | _*____*_ 8 | _*__**__ 9 | _*_*____ 10 | _**_____ 11 | _*_*____ 12 | _*__*___ 13 | _*___**_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/6C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | _***____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ____***_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/6D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ***_**__ 8 | *__*__*_ 9 | *__*__*_ 10 | *__*__*_ 11 | *__*__*_ 12 | *__*__*_ 13 | *__*__*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/6E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | _*_***__ 8 | _**___*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | _*____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/6F.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __****__ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/70.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | _*****__ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | _*****__ 14 | _*______ 15 | _*______ 16 | _*______ 17 | -------------------------------------------------------------------------------- /font/font_data/71.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __*****_ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*____*_ 13 | __*****_ 14 | ______*_ 15 | ______*_ 16 | ______*_ 17 | -------------------------------------------------------------------------------- /font/font_data/72.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | _*_***__ 8 | _**___*_ 9 | _*______ 10 | _*______ 11 | _*______ 12 | _*______ 13 | _*______ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/73.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | __****__ 8 | _*____*_ 9 | _*______ 10 | __****__ 11 | ______*_ 12 | _*____*_ 13 | __****__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/74.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | _******_ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ____***_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/75.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | _*____*_ 8 | _*____*_ 9 | _*____*_ 10 | _*____*_ 11 | _*____*_ 12 | _*___**_ 13 | __***_*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/76.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | *_____*_ 8 | *_____*_ 9 | _*___*__ 10 | _*___*__ 11 | __*_*___ 12 | __*_*___ 13 | ___*____ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/77.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | *__*__*_ 8 | *__*__*_ 9 | *__*__*_ 10 | *_*_*_*_ 11 | *_*_*_*_ 12 | _*___*__ 13 | _*___*__ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/78.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | *_____*_ 8 | _*___*__ 9 | __*_*___ 10 | ___*____ 11 | __*_*___ 12 | _*___*__ 13 | *_____*_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/79.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | *_____*_ 8 | *_____*_ 9 | _*___*__ 10 | _*___*__ 11 | __*_*___ 12 | __*_*___ 13 | ___*____ 14 | ___*____ 15 | __*_____ 16 | **______ 17 | -------------------------------------------------------------------------------- /font/font_data/7A.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | _******_ 8 | ______*_ 9 | _____*__ 10 | ___**___ 11 | __*_____ 12 | _*______ 13 | _******_ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/7B.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ____**__ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | __*_____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ___*____ 15 | ____**__ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/7C.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ___*____ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ___*____ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ___*____ 15 | ___*____ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/7D.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | _**_____ 4 | ___*____ 5 | ___*____ 6 | ___*____ 7 | ___*____ 8 | ___*____ 9 | ____*___ 10 | ___*____ 11 | ___*____ 12 | ___*____ 13 | ___*____ 14 | ___*____ 15 | _**_____ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/7E.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | _**_____ 9 | *__*__*_ 10 | ____**__ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/A0.txt: -------------------------------------------------------------------------------- 1 | ___**___ 2 | ___**___ 3 | ___**___ 4 | ___**___ 5 | ___**___ 6 | ___**___ 7 | ___**___ 8 | ___**___ 9 | ___**___ 10 | ___**___ 11 | ___**___ 12 | ___**___ 13 | ___**___ 14 | ___**___ 15 | ___**___ 16 | ___**___ 17 | -------------------------------------------------------------------------------- /font/font_data/A1.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ******** 9 | ******** 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/A2.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | ___***** 9 | ___***** 10 | ___**___ 11 | ___**___ 12 | ___**___ 13 | ___**___ 14 | ___**___ 15 | ___**___ 16 | ___**___ 17 | -------------------------------------------------------------------------------- /font/font_data/A3.txt: -------------------------------------------------------------------------------- 1 | ________ 2 | ________ 3 | ________ 4 | ________ 5 | ________ 6 | ________ 7 | ________ 8 | *****___ 9 | *****___ 10 | ___**___ 11 | ___**___ 12 | ___**___ 13 | ___**___ 14 | ___**___ 15 | ___**___ 16 | ___**___ 17 | -------------------------------------------------------------------------------- /font/font_data/A4.txt: -------------------------------------------------------------------------------- 1 | ___**___ 2 | ___**___ 3 | ___**___ 4 | ___**___ 5 | ___**___ 6 | ___**___ 7 | ___**___ 8 | ___***** 9 | ___***** 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /font/font_data/A5.txt: -------------------------------------------------------------------------------- 1 | ___**___ 2 | ___**___ 3 | ___**___ 4 | ___**___ 5 | ___**___ 6 | ___**___ 7 | ___**___ 8 | *****___ 9 | *****___ 10 | ________ 11 | ________ 12 | ________ 13 | ________ 14 | ________ 15 | ________ 16 | ________ 17 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/phase/finished.rs: -------------------------------------------------------------------------------- 1 | use crate::game::state::GameState; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub struct Finished { 5 | pub state: GameState, 6 | } 7 | 8 | impl Finished { 9 | pub fn handle(&self) {} 10 | } 11 | -------------------------------------------------------------------------------- /program/fill.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | name = sys.argv[1] 4 | with open(name) as f: 5 | lines = [ line.strip() for line in f ] 6 | 7 | lines.extend(['00000000'] * (8192 - len(lines))) 8 | with open(sys.argv[2], 'w') as f: 9 | f.write('\n'.join(lines) + '\n') 10 | 11 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Split.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | 5 | object Split { 6 | def apply(x: UInt, n: Int, len: Int): Vec[UInt] = { 7 | val vec = Wire(Vec(n, UInt(len.W))) 8 | for (i <- 0 until n) 9 | vec(i) := x.asUInt((i + 1) * len - 1, i * len) 10 | vec 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/phase.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | 3 | use self::{finished::Finished, running::Running}; 4 | 5 | pub mod finished; 6 | // pub mod menu; 7 | pub mod running; 8 | 9 | #[derive(Debug, Clone, PartialEq)] 10 | pub enum Phase { 11 | Running(Box), 12 | Finished(Box), 13 | } 14 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.circleci/coverage.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.62.1 2 | 3 | RUN rustup component add llvm-tools-preview 4 | ENV PATH=/usr/local/rustup/toolchains/1.62.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/:$PATH 5 | RUN apt-get update && \ 6 | apt-get install -y jq && \ 7 | rm -rf /var/lib/apt/lists/* 8 | -------------------------------------------------------------------------------- /font/README.md: -------------------------------------------------------------------------------- 1 | ## Pixel Font (Ark Pixel) 2 | 3 | Adapted from [Ark Pixel Font](https://github.com/TakWolf/ark-pixel-font), "0000-007F Basic Latin" part. 4 | 5 | > ### 授权信息 6 | > 7 | > 分为「字体」和「构建程序」两个部分。 8 | > 9 | > #### 字体 10 | > 11 | > 使用 [SIL 开放字体许可证第 1.1 版](LICENSE-OFL) 授权,保留字体名称「方舟像素 / Ark Pixel」。 12 | > 13 | > #### 构建程序 14 | > 15 | > 使用 [MIT 许可证](LICENSE-MIT) 授权。 16 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.circleci/miri.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.62 2 | 3 | # the specific nightly version to use 4 | ARG nightly_version 5 | 6 | RUN rustup toolchain install nightly-$nightly_version --component miri && \ 7 | rustup override set nightly-$nightly_version 8 | RUN cargo miri setup --target x86_64-unknown-linux-gnu 9 | RUN cargo miri setup --target mips64-unknown-linux-gnuabi64 10 | -------------------------------------------------------------------------------- /program/src/bin/tetris/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate alloc; 5 | 6 | #[macro_use] 7 | extern crate cpu_lib; 8 | 9 | use game::logic::End; 10 | use tetrs::Tetrs; 11 | 12 | mod game; 13 | mod input; 14 | mod tetrs; 15 | mod ui; 16 | 17 | #[no_mangle] 18 | fn main() -> i32 { 19 | let game = Tetrs::new(); 20 | while game.run() != End::Quit {} 21 | 22 | 0 23 | } 24 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/GenerateOptions.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | case class GenerateOptions( 4 | enableDebugPorts: Boolean, 5 | useIP: Boolean, 6 | 7 | systemClock: Int, 8 | standardClock: Int, 9 | uartClock: Int, 10 | vgaClock: Int, 11 | ) 12 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Counter.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | 5 | object Counter { 6 | def maxBits(bits: Int): UInt = { 7 | val x = RegInit(0.U(bits.W)) 8 | x := x + 1.U 9 | x 10 | } 11 | 12 | def maxBits(bits: Int, en: Bool): UInt = { 13 | val x = RegInit(0.U(bits.W)) 14 | x := Mux(en, x + 1.U, x) 15 | x 16 | } 17 | } 18 | 19 | object Pulse { 20 | def apply(n: UInt): Bool = n.andR 21 | } 22 | -------------------------------------------------------------------------------- /simulation/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS := -lunicorn -lSDL2 2 | export LDFLAGS 3 | 4 | TARGET ?= main 5 | 6 | .PHONY: all 7 | all: obj_dir_$(TARGET)/VTop 8 | 9 | obj_dir_$(TARGET)/VTop: obj_dir_$(TARGET)/VTop.mk $(TARGET).cpp 10 | make OPT_FAST="-Os" -C obj_dir_$(TARGET) -f VTop.mk -j 11 | 12 | obj_dir_$(TARGET)/VTop.mk: ../verilog/Top.sv 13 | verilator --cc --vpi --trace --Mdir obj_dir_$(TARGET) Top.sv --exe $(TARGET).cpp 14 | 15 | .PHONY: run 16 | run: all 17 | ./obj_dir_$(TARGET)/VTop 18 | -------------------------------------------------------------------------------- /program/src/lang_items.rs: -------------------------------------------------------------------------------- 1 | use core::panic::PanicInfo; 2 | 3 | use crate::println; 4 | 5 | #[panic_handler] 6 | fn panic(info: &PanicInfo) -> ! { 7 | let err = info.message().unwrap(); 8 | if let Some(location) = info.location() { 9 | println!( 10 | "Panicked at {}:{}, {}", 11 | location.file(), 12 | location.line(), 13 | err 14 | ); 15 | } else { 16 | println!("Panicked: {}", err); 17 | } 18 | 19 | loop {} 20 | } 21 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Emit.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | import circt.stage.ChiselStage 5 | 6 | object Emit { 7 | def apply(gen: => RawModule, args: Array[String]): Unit = { 8 | val emitArgs = if (args.isEmpty) { 9 | Array("--target-dir", "verilog") 10 | } else { 11 | args 12 | } 13 | 14 | ChiselStage.emitSystemVerilogFile( 15 | gen, 16 | emitArgs, 17 | firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info") 18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "emballoc" 3 | description = "Simple but reliable memory allocator for embedded Rust and #![no_std]" 4 | version = "0.1.2" 5 | edition = "2021" 6 | categories = ["memory-management", "no-std", "embedded", "algorithms"] 7 | keywords = ["allocator", "embedded", "no-std", "no_std"] 8 | license = "MIT OR Apache-2.0" 9 | repository = "https://github.com/jfrimmel/emballoc" 10 | documentation = "https://docs.rs/emballoc" 11 | rust-version = "1.57" 12 | 13 | [package.metadata.docs.rs] 14 | targets = ["x86_64-unknown-linux-gnu"] 15 | -------------------------------------------------------------------------------- /chisel/src/main/scala/misc/RNG.scala: -------------------------------------------------------------------------------- 1 | package misc 2 | 3 | import chisel3._ 4 | import chisel3.util.random._ 5 | 6 | object RNG { 7 | private val primes: LazyList[Int] = 2 #:: LazyList.from(3).filter { n => !primes.takeWhile(_ <= math.sqrt(n)).exists(n % _ == 0) } 8 | 9 | def apply(width: Int): UInt = { 10 | val groupLength = 8 11 | RegNext(VecInit( 12 | primes 13 | .slice(6, width / groupLength + 6) 14 | .zip(Seq(1017L, 393241L, 6291469L, 402653189L)) 15 | .map(p => GaloisLFSR.maxPeriod(p._1, true.B, Some(p._2))(groupLength - 1, 0))) 16 | .asUInt) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /program/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpu_lib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | rand = { version = "^0.8.5", default-features = false } 10 | emballoc = { version = "0.1.2", path = "3rd_party/emballoc", optional = true } 11 | 12 | [features] 13 | alloc = ["dep:emballoc"] 14 | 15 | [[bin]] 16 | name = "tetris" 17 | required-features = ["alloc"] 18 | 19 | [profile.release] 20 | # opt-level = "z" 21 | strip = "debuginfo" 22 | lto = true 23 | panic = "abort" 24 | codegen-units = 1 25 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/phase/menu.rs: -------------------------------------------------------------------------------- 1 | use crate::{game::state::GameState, input::Input}; 2 | 3 | use super::running::Running; 4 | 5 | #[derive(Debug, Clone, PartialEq)] 6 | pub struct Menu {} 7 | 8 | impl Menu { 9 | pub fn handle(&self, inputs: &[Input]) -> Option> { 10 | let input = inputs.iter().find_map(|&x| match x { 11 | Input::Number(number) => Some(number), 12 | _ => None, 13 | }); 14 | 15 | input.map(|level| { 16 | Box::new(Running { 17 | state: GameState::new(level), 18 | }) 19 | }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/NumberExtend.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | object SignExt { 7 | def apply(n: Int, x: UInt): UInt = { 8 | val m = n - x.getWidth 9 | val highest = x(x.getWidth - 1) 10 | val signs = Fill(m, highest) 11 | Cat(signs, x) 12 | } 13 | } 14 | 15 | object SignExt32 { 16 | def apply(x: UInt): UInt = SignExt(32, x) 17 | } 18 | 19 | object ZeroExt { 20 | def apply(n: Int, x: UInt): UInt = { 21 | val m = n - x.getWidth 22 | val signs = Fill(m, 0.B) 23 | Cat(signs, x) 24 | } 25 | } 26 | 27 | object ZeroExt32 { 28 | def apply(x: UInt): UInt = ZeroExt(32, x) 29 | } 30 | -------------------------------------------------------------------------------- /generated/README.md: -------------------------------------------------------------------------------- 1 | ## 文件内容 2 | 3 | | 文件 | 备注 | 4 | |----------------------------|----------| 5 | | [Top.sv](Top.sv) | Chisel 生成的 Verilog 代码 | 6 | | [font.coe](font.coe) | 字体 ROM 的 coe | 7 | | [loader.coe](loader.coe) | Bootloader 的 coe | 8 | | [Top.bit](Top.bit) | Vivado 生成出来的比特流文件 ~~(希望没有粘贴错)~~ | 9 | | [tetris.bin](tetris.bin) | 俄罗斯方块程序 | 10 | 11 | ## 使用 12 | 13 | 1. 直接烧录 `Top.bit`。 14 | 2. 将 UART 输入输出连接到 M5(rx), M6(tx) 上(可以参考根目录 README 的图)。 15 | 3. UART 上应该输出了 Bootloader 的欢迎信息。 16 | 先输入 `72468`(`tetris.bin` 的长度),然后将 `tetris.bin`(binary)通过 UART 传输出去。 17 | 4. 连接 VGA 显示,显示器上应该能显示俄罗斯方块界面,并且能通过 UART 进行控制(`hjkl` 移动、旋转,空格落下,`r` 重开)。 18 | -------------------------------------------------------------------------------- /program/src/tube.rs: -------------------------------------------------------------------------------- 1 | use crate::board::*; 2 | 3 | #[repr(u8)] 4 | pub enum TubeMode { 5 | Dec = 0, 6 | Hex = 1, 7 | } 8 | 9 | pub fn set_tube_value(v: u32) { 10 | unsafe { 11 | write_u32(0xFFFFF038, v); 12 | } 13 | } 14 | 15 | pub fn set_tube_enable(mask: u8) { 16 | unsafe { 17 | write_u32(0xFFFFF03C, mask as u32); 18 | } 19 | } 20 | 21 | pub fn set_tube_mode(mode: TubeMode) { 22 | unsafe { 23 | write_u32(0xFFFFF030, mode as u8 as u32); 24 | } 25 | } 26 | 27 | pub fn set_tube_value_option(v: Option) { 28 | set_tube_enable(if v.is_some() { 0xFF } else { 0 }); 29 | if let Some(v) = v { 30 | set_tube_value(v); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Encoder.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | object Encoder { 7 | def apply(width: Int)(in: UInt): UInt = { 8 | val inWidth = Helper.log2(width) 9 | require(inWidth == in.getWidth) 10 | 11 | val table = LazyList.range(0, width) 12 | .map(b => b.U(inWidth.W) -> (BigInt(1) << b).U(width.W)) 13 | 14 | MuxLookup(in, 0.U)(table) 15 | } 16 | } 17 | 18 | object Decoder { 19 | def apply(width: Int)(in: UInt): UInt = { 20 | val outWidth = Helper.log2(width) 21 | 22 | val table = LazyList.range(0, width) 23 | .map(b => (BigInt(1) << b).U(width.W) -> b.U(outWidth.W)) 24 | 25 | MuxLookup(in, 0.U)(table) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /program/src/uart.rs: -------------------------------------------------------------------------------- 1 | use crate::board::*; 2 | 3 | #[inline] 4 | pub fn output_ready() -> bool { 5 | unsafe { read_u32(0xFFFFF00C) > 0 } 6 | } 7 | 8 | #[inline] 9 | pub fn input_ready() -> bool { 10 | unsafe { read_u32(0xFFFFF008) > 0 } 11 | } 12 | 13 | #[inline] 14 | pub unsafe fn write_unchecked(data: u8) { 15 | unsafe { write_u32(0xFFFFF004, data as u32) } 16 | } 17 | 18 | #[inline] 19 | pub unsafe fn read_unchecked() -> u8 { 20 | unsafe { read_u32(0xFFFFF000) as u8 } 21 | } 22 | 23 | #[inline] 24 | pub fn write(data: u8) { 25 | while !output_ready() {} 26 | unsafe { write_unchecked(data) } 27 | } 28 | 29 | #[inline] 30 | pub fn read() -> u8 { 31 | while !input_ready() {} 32 | unsafe { read_unchecked() } 33 | } 34 | -------------------------------------------------------------------------------- /chisel/src/test/scala/core/TubesSpec.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import misc._ 4 | import chisel3._ 5 | import chiseltest._ 6 | import org.scalatest.flatspec.AnyFlatSpec 7 | 8 | class TubesSpec extends AnyFlatSpec with ChiselScalatestTester { 9 | behavior of "misc.Tubes" 10 | 11 | def asUnsigned(x: Int) = (BigInt(x >>> 1) << 1) + (x & 1) 12 | 13 | it should "read and write word" in { 14 | test(new DivTen()) { implicit dut => 15 | val rand = new scala.util.Random 16 | for (_ <- 0 until 1024) { 17 | val v = asUnsigned(rand.nextInt()) 18 | // println(v) 19 | dut.io.in.poke(v) 20 | 21 | dut.io.quotient.expect(v / 10) 22 | dut.io.remainder.expect(v % 10) 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /chisel/build.sbt: -------------------------------------------------------------------------------- 1 | // See README.md for license details. 2 | 3 | ThisBuild / scalaVersion := "2.13.8" 4 | ThisBuild / version := "0.1.0" 5 | ThisBuild / organization := "com.monadx.cpu" 6 | 7 | val chiselVersion = "3.6.0" 8 | 9 | lazy val root = (project in file(".")) 10 | .settings( 11 | name := "cpu", 12 | libraryDependencies ++= Seq( 13 | "edu.berkeley.cs" %% "chisel3" % chiselVersion, 14 | "edu.berkeley.cs" %% "chiseltest" % "0.6.0" 15 | ), 16 | scalacOptions ++= Seq( 17 | "-language:reflectiveCalls", 18 | "-deprecation", 19 | "-feature", 20 | "-Xcheckinit", 21 | ), 22 | addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full), 23 | ) 24 | 25 | -------------------------------------------------------------------------------- /program/src/entry.asm: -------------------------------------------------------------------------------- 1 | .section .text.entry 2 | .globl _start 3 | _start: 4 | li t0, 0 5 | li t1, 0 6 | li t2, 0 7 | li a0, 0 8 | li a1, 0 9 | li a2, 0 10 | li a3, 0 11 | li a4, 0 12 | li a5, 0 13 | li a6, 0 14 | li a7, 0 15 | li t4, 0 16 | li t5, 0 17 | li t6, 0 18 | 19 | move t3, sp 20 | la sp, boot_stack_top 21 | addi sp, sp, -16 22 | sw ra, 12(sp) 23 | sw t3, 8(sp) 24 | jal rust_main 25 | lw ra, 12(sp) 26 | lw sp, 8(sp) 27 | ret 28 | 29 | .section .bss.stack 30 | .globl boot_stack_lower_bound 31 | boot_stack_lower_bound: 32 | .space 4096 * 4 33 | .globl boot_stack_top 34 | boot_stack_top: 35 | 36 | -------------------------------------------------------------------------------- /program/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "cpu_lib" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "emballoc", 10 | "rand", 11 | ] 12 | 13 | [[package]] 14 | name = "emballoc" 15 | version = "0.1.2" 16 | 17 | [[package]] 18 | name = "rand" 19 | version = "0.8.5" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 22 | dependencies = [ 23 | "rand_core", 24 | ] 25 | 26 | [[package]] 27 | name = "rand_core" 28 | version = "0.6.4" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 31 | -------------------------------------------------------------------------------- /program/src/bin/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | #[macro_use] 5 | extern crate cpu_lib; 6 | 7 | use cpu_lib::prelude::*; 8 | 9 | #[no_mangle] 10 | fn main() -> i32 { 11 | println!("Hello, world!"); 12 | let mut buf = [0; 16]; 13 | 14 | monitor::set_color(1); 15 | print!("n1: "); 16 | let line = read_line(&mut buf); 17 | let n1: i32 = line.parse().unwrap(); 18 | 19 | monitor::set_color(2); 20 | print!("n2: "); 21 | let line = read_line(&mut buf); 22 | let n2: i32 = line.parse().unwrap(); 23 | 24 | monitor::set_color(3); 25 | println!("n1 = {}", n1); 26 | monitor::set_color(4); 27 | println!("n2 = {}", n2); 28 | monitor::set_color(5); 29 | println!("n1 + n2 = {}", n1 + n2); 30 | 31 | // loop {} 32 | 33 | 0 34 | } 35 | -------------------------------------------------------------------------------- /chisel/build.sc: -------------------------------------------------------------------------------- 1 | // import Mill dependency 2 | import mill._ 3 | import mill.define.Sources 4 | import mill.modules.Util 5 | import mill.scalalib.TestModule.ScalaTest 6 | import scalalib._ 7 | // support BSP 8 | import mill.bsp._ 9 | 10 | object cpu extends SbtModule { m => 11 | override def millSourcePath = os.pwd 12 | override def scalaVersion = "2.13.8" 13 | override def scalacOptions = Seq( 14 | "-language:reflectiveCalls", 15 | "-deprecation", 16 | "-feature", 17 | "-Xcheckinit", 18 | "-P:chiselplugin:genBundleElements" 19 | ) 20 | override def ivyDeps = Agg( 21 | ivy"edu.berkeley.cs::chisel3:3.5.4", 22 | ) 23 | override def scalacPluginIvyDeps = Agg( 24 | ivy"edu.berkeley.cs:::chisel3-plugin:3.5.4", 25 | ) 26 | object test extends Tests with ScalaTest { 27 | override def ivyDeps = m.ivyDeps() ++ Agg( 28 | ivy"edu.berkeley.cs::chiseltest:0.5.4" 29 | ) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /program/src/linker-loader.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(riscv) 2 | ENTRY(_start) 3 | BASE_ADDRESS = 0x00000000; 4 | 5 | SECTIONS 6 | { 7 | . = BASE_ADDRESS; 8 | skernel = .; 9 | 10 | stext = .; 11 | .text : { 12 | *(.text.entry) 13 | *(.text .text.*) 14 | } 15 | 16 | . = ALIGN(16); 17 | etext = .; 18 | srodata = .; 19 | .rodata : { 20 | *(.rodata .rodata.*) 21 | *(.srodata .srodata.*) 22 | } 23 | 24 | . = ALIGN(16); 25 | erodata = .; 26 | sdata = .; 27 | .data : { 28 | *(.data .data.*) 29 | *(.sdata .sdata.*) 30 | } 31 | 32 | . = ALIGN(16); 33 | edata = .; 34 | .bss : { 35 | *(.bss.stack) 36 | sbss = .; 37 | *(.bss .bss.*) 38 | *(.sbss .sbss.*) 39 | } 40 | 41 | . = ALIGN(16); 42 | ebss = .; 43 | ekernel = .; 44 | 45 | /DISCARD/ : { 46 | *(.eh_frame) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /program/src/linker-program.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(riscv) 2 | ENTRY(_start) 3 | BASE_ADDRESS = 0x00008000; 4 | 5 | SECTIONS 6 | { 7 | . = BASE_ADDRESS; 8 | skernel = .; 9 | 10 | stext = .; 11 | .text : { 12 | *(.text.entry) 13 | *(.text .text.*) 14 | } 15 | 16 | . = ALIGN(16); 17 | etext = .; 18 | srodata = .; 19 | .rodata : { 20 | *(.rodata .rodata.*) 21 | *(.srodata .srodata.*) 22 | } 23 | 24 | . = ALIGN(16); 25 | erodata = .; 26 | sdata = .; 27 | .data : { 28 | *(.data .data.*) 29 | *(.sdata .sdata.*) 30 | } 31 | 32 | . = ALIGN(16); 33 | edata = .; 34 | .bss : { 35 | *(.bss.stack) 36 | sbss = .; 37 | *(.bss .bss.*) 38 | *(.sbss .sbss.*) 39 | } 40 | 41 | . = ALIGN(16); 42 | ebss = .; 43 | ekernel = .; 44 | 45 | /DISCARD/ : { 46 | *(.eh_frame) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /program/src/time.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Sub; 2 | use core::time::Duration; 3 | 4 | use crate::board::read_u32; 5 | 6 | pub const CPU_FREQUENCY: usize = 20_000_000; 7 | 8 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 9 | pub struct Instant(Duration); 10 | 11 | impl Instant { 12 | pub fn now() -> Instant { 13 | Instant(Duration::from_micros((read_cycles() / 10) as u64)) 14 | } 15 | 16 | pub fn duration_since(&self, earlier: Instant) -> Duration { 17 | self.0 - earlier.0 18 | } 19 | } 20 | 21 | impl Sub for Instant { 22 | type Output = Duration; 23 | fn sub(self, other: Instant) -> Duration { 24 | self.duration_since(other) 25 | } 26 | } 27 | 28 | pub fn read_cycles() -> usize { 29 | unsafe { read_u32(0xFFFFF010) as usize } 30 | } 31 | 32 | pub fn sleep(duration: Duration) { 33 | let until = Instant::now().0 + duration; 34 | while Instant::now().0 < until {} 35 | } 36 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/math.rs: -------------------------------------------------------------------------------- 1 | pub struct Matrix2D { 2 | pub x0: i32, 3 | pub x1: i32, 4 | pub y0: i32, 5 | pub y1: i32, 6 | } 7 | 8 | pub const ROTATE_CCW: Matrix2D = Matrix2D { 9 | x0: 0, 10 | x1: 1, 11 | y0: -1, 12 | y1: 0, 13 | }; 14 | 15 | pub const ROTATE_CW: Matrix2D = Matrix2D { 16 | x0: 0, 17 | x1: -1, 18 | y0: 1, 19 | y1: 0, 20 | }; 21 | 22 | #[derive(Debug, Clone, PartialEq, Hash)] 23 | pub struct Vector2D { 24 | pub x: i32, 25 | pub y: i32, 26 | } 27 | 28 | impl Vector2D { 29 | // This is explicitly not implemented as the Default trait in order to make it const 30 | pub const fn default() -> Self { 31 | Self { x: 3, y: 0 } 32 | } 33 | 34 | pub fn rotate(&self, center: &Vector2D, rot: &Matrix2D) -> Vector2D { 35 | Vector2D { 36 | x: rot.x0 * self.x + rot.x1 * self.y + center.x - rot.x0 * center.x - rot.x1 * center.y, 37 | y: rot.y0 * self.x + rot.y1 * self.y + center.y - rot.y0 * center.x - rot.y1 * center.y, 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /chisel/src/main/scala/Top.scala: -------------------------------------------------------------------------------- 1 | import core._ 2 | import util._ 3 | import board._ 4 | import ip._ 5 | import chisel3._ 6 | 7 | class Top(implicit options: GenerateOptions) extends Module { 8 | val out = IO(new RealBoardDataBundle) 9 | 10 | val clocks = Module(new ClockWizard()) 11 | val board = withClockAndReset(clocks.io.clockCpu, clocks.io.reset) { Module(new BoardDataController()) } 12 | val core = withClockAndReset(clocks.io.clockCpu, clocks.io.reset) { Module(new Core()) } 13 | 14 | board.inside <> core.io.external 15 | board.outer <> out 16 | board.io.uartClock := clocks.io.clockUart 17 | board.io.vgaClock := clocks.io.clockVga 18 | board.io.cpuClock := clocks.io.clockCpu 19 | board.io.cycles := core.io.cycles 20 | board.io.originPC := core.io.originPC 21 | core.io.interrupt := board.io.interrupt 22 | } 23 | 24 | object VerilogMain extends App { 25 | implicit val options = new GenerateOptions( 26 | false, 27 | true, 28 | 100_000_000, 29 | 20_000_000, 30 | 12_500_000, 31 | 40_000_000) 32 | 33 | Emit(new Top(), args) 34 | } 35 | -------------------------------------------------------------------------------- /program/src/rng.rs: -------------------------------------------------------------------------------- 1 | use rand::{Error, RngCore}; 2 | 3 | use crate::board::random_value; 4 | 5 | pub struct FpgaRng; 6 | 7 | pub fn rng() -> FpgaRng { 8 | FpgaRng 9 | } 10 | 11 | impl RngCore for FpgaRng { 12 | #[inline] 13 | fn next_u32(&mut self) -> u32 { 14 | random_value() 15 | } 16 | 17 | fn next_u64(&mut self) -> u64 { 18 | let v1 = self.next_u32(); 19 | let v2 = self.next_u32() ^ self.next_u32(); 20 | (v1 as u64) << 32 | (v2 as u64) 21 | } 22 | 23 | fn fill_bytes(&mut self, dest: &mut [u8]) { 24 | dest.iter_mut().for_each(|ptr| { 25 | let v = self.next_u32(); 26 | let p1 = (v >> 24) & 0x3; 27 | let p2 = (v >> 16) & 0x3; 28 | let p3 = (v >> 8) & 0x3; 29 | let p4 = (v >> 0) & 0x3; 30 | let v = (p1 << 6) | (p2 << 4) | (p3 << 2) | p4; 31 | *ptr = v as u8; 32 | }); 33 | } 34 | 35 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 36 | self.fill_bytes(dest); 37 | Ok(()) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /chisel/src/main/scala/core/ALU.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import util._ 4 | import chisel3._ 5 | 6 | class ALU extends Module { 7 | val io = IO(new Bundle { 8 | val lhs = Input(SInt(32.W)) 9 | val rhs = Input(SInt(32.W)) 10 | val shamt = Input(UInt(5.W)) 11 | val aluType = Input(ALUType()) 12 | 13 | val output = Output(SInt(32.W)) 14 | }) 15 | 16 | switch (io.aluType) 17 | .is (ALUType.Add) { io.output := io.lhs + io.rhs } 18 | .is (ALUType.Sub) { io.output := io.lhs - io.rhs } 19 | .is (ALUType.Xor) { io.output := io.lhs ^ io.rhs } 20 | .is (ALUType.Or) { io.output := io.lhs | io.rhs } 21 | .is (ALUType.And) { io.output := io.lhs & io.rhs } 22 | .is (ALUType.Sll) { io.output := io.lhs << io.shamt } 23 | .is (ALUType.Srl) { io.output := (io.lhs.asUInt >> io.shamt).asSInt } 24 | .is (ALUType.Sra) { io.output := io.lhs >> io.shamt } 25 | .default { io.output := DontCare } 26 | } 27 | 28 | object ALUType extends ChiselEnum { 29 | val Add, Sub, Xor, Or, And, Sll, Srl, Sra = Value 30 | // 0 1 2 3 4 5 6 7 31 | } 32 | -------------------------------------------------------------------------------- /chisel/src/main/scala/core/RegisterFile.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import util.GenerateOptions 4 | import chisel3._ 5 | 6 | // just a register table 7 | class RegisterFile(implicit options: GenerateOptions) extends Module { 8 | val io = IO(new Bundle { 9 | val rs1Addr = Input(UInt(5.W)) 10 | val rs2Addr = Input(UInt(5.W)) 11 | val rdAddr = Input(UInt(5.W)) 12 | val rdDataIn = Input(SInt(32.W)) 13 | val write = Input(Bool()) 14 | 15 | val rs1Out = Output(SInt(32.W)) 16 | val rs2Out = Output(SInt(32.W)) 17 | }) 18 | 19 | val debug = if (options.enableDebugPorts) Some(IO(new Bundle { 20 | val debugAddr = Input(UInt(5.W)) 21 | val debugData = Output(SInt(32.W)) 22 | })) else None 23 | 24 | val mem = Mem(32, SInt(32.W)) 25 | 26 | io.rs1Out := Mux(io.rs1Addr === 0.U, 0.S, mem.read(io.rs1Addr)) 27 | io.rs2Out := Mux(io.rs2Addr === 0.U, 0.S, mem.read(io.rs2Addr)) 28 | when (io.write && (io.rdAddr =/= 0.U)) { 29 | mem.write(io.rdAddr, io.rdDataIn) 30 | } 31 | 32 | debug.foreach { debug => 33 | debug.debugData := mem.read(debug.debugAddr) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 J. Frimmel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /font/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 TakWolf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /program/src/bin/keyboard.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | #[macro_use] 5 | extern crate cpu_lib; 6 | 7 | use cpu_lib::prelude::*; 8 | 9 | fn read_number() -> u32 { 10 | let mut v = 0; 11 | let mut en = 0; 12 | 13 | while keyboard_ready() { 14 | read_keyboard(); 15 | } 16 | 17 | loop { 18 | while !keyboard_ready() { 19 | if read_button(Button::Left) { 20 | en >>= 1; 21 | v /= 10; 22 | set_tube_value_option(Some(v)); 23 | set_tube_enable(en); 24 | while read_button(Button::Left) {} 25 | } 26 | if read_button(Button::Center) { 27 | while read_button(Button::Center) {} 28 | return v; 29 | } 30 | } 31 | 32 | en = en << 1 | 1; 33 | let key = read_keyboard().as_number().unwrap(); 34 | v = v * 10 + key; 35 | set_tube_value_option(Some(v)); 36 | set_tube_enable(en); 37 | } 38 | } 39 | 40 | #[no_mangle] 41 | fn main() -> i32 { 42 | let v = read_number(); 43 | println!("read number => {}", v); 44 | 45 | 0 46 | } 47 | -------------------------------------------------------------------------------- /program/src/bin/tetris/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Moritz Freyburger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.circleci/README.md: -------------------------------------------------------------------------------- 1 | # CI definitions for CircleCI 2 | 3 | This directory contains all the necessary files for th Continuous Integration setup. 4 | Most importantly, there is the [config.yml](config.yml)-file, which contains the core definitions of the CI. 5 | It also contains docker files for custom containers used during the CI run. 6 | 7 | ## Container for Miri 8 | 9 | This container is a version of `rust`, which already contains a pre-setup `miri` environment. 10 | 11 | To build the docker container, select the desired nightly version (which, of course, has to contain the `miri` component) and run the following command from the repository root (replace `2022-08-22` with the required version): 12 | 13 | ```bash 14 | docker build -t jfrimmel/miri:nightly-2022-08-22 --build-arg nightly_version=2022-08-22 -f .circleci/miri.Dockerfile .circleci/ 15 | ``` 16 | 17 | ## Container for coverage testing 18 | 19 | This container is a version of `rust`, which already contains a pre-installed coverage-testing tools. 20 | 21 | To build the container use: 22 | 23 | ```bash 24 | docker build -t jfrimmel/coverage -f .circleci/coverage.Dockerfile .circleci/ 25 | ``` 26 | -------------------------------------------------------------------------------- /program/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(let_chains)] 3 | #![feature(linkage)] 4 | #![feature(panic_info_message)] 5 | 6 | #[cfg(feature = "alloc")] 7 | extern crate alloc; 8 | 9 | use core::arch::global_asm; 10 | 11 | pub mod board; 12 | pub mod console; 13 | mod lang_items; 14 | pub mod monitor; 15 | pub mod rng; 16 | pub mod time; 17 | pub mod tube; 18 | pub mod uart; 19 | 20 | #[cfg(feature = "alloc")] 21 | mod allocator; 22 | 23 | pub mod prelude; 24 | 25 | // #[cfg(feature = "loader")] 26 | // global_asm!(include_str!("entry-loader.asm")); 27 | // #[cfg(not(feature = "loader"))] 28 | global_asm!(include_str!("entry.asm")); 29 | 30 | #[linkage = "weak"] 31 | #[no_mangle] 32 | fn main() -> i32 { 33 | panic!("Cannot find main!"); 34 | } 35 | 36 | #[no_mangle] 37 | #[link_section = ".text.entry"] 38 | pub extern "C" fn rust_main() -> i32 { 39 | clear_bss(); 40 | monitor::init(); 41 | monitor::monitor::clear_screen(); 42 | main() 43 | } 44 | 45 | #[allow(dead_code)] 46 | fn clear_bss() { 47 | extern "C" { 48 | fn sbss(); 49 | fn ebss(); 50 | } 51 | 52 | (sbss as usize..ebss as usize).for_each(|a| unsafe { (a as *mut u8).write_volatile(0) }); 53 | } 54 | -------------------------------------------------------------------------------- /chisel/src/test/scala/core/ALUSpec.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import chisel3._ 4 | import chiseltest._ 5 | import org.scalatest.flatspec.AnyFlatSpec 6 | 7 | class ALUSpec extends AnyFlatSpec with ChiselScalatestTester { 8 | behavior of "core.ALU" 9 | 10 | it should "yield correct result in ADD" in { 11 | test(new ALU) { dut => 12 | dut.io.aluType.poke(ALUType.Add) 13 | dut.io.lhs.poke(15.S) 14 | dut.io.rhs.poke(16.S) 15 | dut.io.output.expect(31.S) 16 | 17 | dut.io.lhs.poke(-1.S) 18 | dut.io.rhs.poke(1.S) 19 | dut.io.output.expect(0.S) 20 | } 21 | } 22 | 23 | it should "yield correct result in shifts" in { 24 | test(new ALU) { dut => 25 | dut.io.aluType.poke(ALUType.Sll) 26 | dut.io.lhs.poke(15.S) 27 | dut.io.shamt.poke(3.U) 28 | dut.io.output.expect((15 << 3).S) 29 | 30 | dut.io.aluType.poke(ALUType.Srl) 31 | dut.io.lhs.poke(-1.S) // 0xFFFFFFFF 32 | dut.io.shamt.poke(16.U) 33 | dut.io.output.expect(0xFFFF.S) 34 | 35 | dut.io.aluType.poke(ALUType.Sra) 36 | dut.io.lhs.poke(-32.S) 37 | dut.io.shamt.poke(4.U) 38 | dut.io.output.expect((-(32 >> 4)).S) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /program/src/bin/loader.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::ptr::write_volatile; 5 | 6 | extern crate cpu_lib; 7 | 8 | use cpu_lib::prelude::*; 9 | 10 | const APP_BASE_ADDRESS: usize = 0x00008000; 11 | 12 | #[no_mangle] 13 | fn main() -> i32 { 14 | print_str("[loader] Welcome to the program loader!\r\n"); 15 | let mut buf = [0; 16]; 16 | 17 | loop { 18 | print_str("[loader] Program size (bytes): "); 19 | let line = read_line(&mut buf); 20 | 21 | let size: usize = if let Ok(size) = line.parse() { 22 | size 23 | } else { 24 | print_str("[loader] Invalid number!"); 25 | continue 26 | }; 27 | 28 | print_str("[loader] Transfer the data below\r\n"); 29 | unsafe { 30 | core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, size) 31 | .iter_mut() 32 | .for_each(|addr| write_volatile(addr, get_char(false))); 33 | } 34 | 35 | print_str("[loader] Program loaded! Calling...\r\n"); 36 | let code: extern "C" fn() = unsafe { core::mem::transmute(APP_BASE_ADDRESS as *const ()) }; 37 | (code)(); 38 | 39 | monitor::clear_screen(); 40 | print_str("[loader] Program exited\r\n\r\n"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /program/src/bin/tetris/input.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use cpu_lib::uart; 4 | 5 | #[derive(Debug, PartialEq, Clone, Copy)] 6 | pub enum Input { 7 | Left, 8 | Right, 9 | Down, 10 | Rotate, 11 | Drop, 12 | Quit, 13 | Restart, 14 | Number(u32), 15 | } 16 | 17 | impl TryFrom for Input { 18 | type Error = (); 19 | 20 | fn try_from(key: char) -> Result { 21 | match key { 22 | 'w' => Ok(Input::Rotate), 23 | 'd' => Ok(Input::Right), 24 | 'a' => Ok(Input::Left), 25 | 's' => Ok(Input::Down), 26 | 'k' => Ok(Input::Rotate), 27 | 'l' => Ok(Input::Right), 28 | 'h' => Ok(Input::Left), 29 | 'j' => Ok(Input::Down), 30 | ' ' => Ok(Input::Drop), 31 | 'q' => Ok(Input::Quit), 32 | 'r' => Ok(Input::Restart), 33 | c => match c { 34 | '0'..='9' => Ok(Input::Number(c.to_digit(10).expect("Should not fail"))), 35 | _ => Err(()), 36 | }, 37 | } 38 | } 39 | } 40 | 41 | pub fn collect_inputs() -> Vec { 42 | let mut v = Vec::new(); 43 | while uart::input_ready() { 44 | if let Ok(input) = Input::try_from(uart::read() as char) { 45 | println!("Input: {:?}", input); 46 | v.push(input); 47 | } 48 | } 49 | v 50 | } 51 | -------------------------------------------------------------------------------- /chisel/src/main/scala/misc/CrossClockQueue.scala: -------------------------------------------------------------------------------- 1 | package misc 2 | 3 | import util.Helper 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | // a queue for transfer data between clock, with buffer (avoid data loss between different clocks) 8 | class CrossClockQueue[T <: Data](gen: T, depth: Int) extends Module { 9 | val io = IO(new Bundle { 10 | val enq = Flipped(Decoupled(gen)) 11 | val deq = Decoupled(gen) 12 | 13 | val clkEnq = Input(Clock()) 14 | val clkDeq = Input(Clock()) 15 | }) 16 | 17 | // data: [ _ 1 2 3 4 _ _ _ ] 18 | // | | 19 | // deq enq ---> 20 | 21 | val mem = withClock(io.clkEnq) { 22 | Mem(depth, gen) 23 | } 24 | 25 | val depthBits = Helper.log2(depth) 26 | val enqIdx = withClock(io.clkEnq) { 27 | RegInit(0.U(depthBits.W)) 28 | } 29 | val deqIdx = withClock(io.clkDeq) { 30 | RegInit(0.U(depthBits.W)) 31 | } 32 | 33 | val enqNextIdx = enqIdx + 1.U 34 | val deqNextIdx = deqIdx + 1.U 35 | 36 | val full = enqNextIdx === deqIdx 37 | val empty = enqIdx === deqIdx 38 | 39 | io.enq.ready := !full 40 | withClock(io.clkEnq) { 41 | when(!full && io.enq.valid) { 42 | mem.write(enqIdx, io.enq.bits) 43 | enqIdx := enqNextIdx 44 | } 45 | } 46 | 47 | io.deq.valid := !empty 48 | io.deq.bits := mem.read(deqIdx, io.clkDeq) 49 | when(!empty && io.deq.ready) { 50 | deqIdx := deqNextIdx 51 | } 52 | } 53 | 54 | //object TempMain extends App { 55 | // Emit(new CrossClockQueue(UInt(8.W), 16), args) 56 | //} 57 | -------------------------------------------------------------------------------- /chisel/src/main/scala/misc/Debounce.scala: -------------------------------------------------------------------------------- 1 | package misc 2 | 3 | import util.{GenerateOptions, Helper} 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | class DebounceOutBundle extends Bundle { 8 | val out = Output(Bool()) 9 | val onDown = Output(Bool()) 10 | val onUp = Output(Bool()) 11 | } 12 | 13 | class Debounce(implicit options: GenerateOptions) extends Module { 14 | private val REQUIRED_INTERVAL = 5 // ms 15 | private val REQUIRED_CYCLES = options.systemClock * REQUIRED_INTERVAL / 1000 16 | private val REQUIRED_BITS = Helper.log2(REQUIRED_CYCLES) 17 | 18 | val io = IO(new Bundle { 19 | val in = Input(Bool()) 20 | val out = new DebounceOutBundle() 21 | }) 22 | 23 | val sync = ShiftRegister(io.in, 2) 24 | 25 | val out = RegInit(0.B) 26 | val idle = out === sync 27 | 28 | // idea: only take the input when it's stable (unchanged) in `REQUIRED_INTERVAL` time. 29 | // when the input is different from output, increasing the counter 30 | // when the counter is full, flipped the output 31 | val cnt = RegInit(0.U(REQUIRED_BITS.W)) 32 | val onMax = cnt.andR 33 | cnt := Mux(idle, 0.U, cnt + 1.U) 34 | out := Mux(onMax, !out, out) 35 | 36 | io.out.out := RegNext(out) 37 | io.out.onDown := RegNext(!idle && onMax && !out) 38 | io.out.onUp := RegNext(!idle && onMax && out) 39 | } 40 | 41 | object Debounce { 42 | def apply(in: Bool)(implicit options: GenerateOptions): DebounceOutBundle = { 43 | val debounce = Module(new Debounce()) 44 | debounce.io.in := in 45 | debounce.io.out 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /chisel/src/main/scala/util/Switch.scala: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import chisel3._ 4 | import chisel3.experimental.SourceInfo 5 | 6 | object switch { 7 | def apply[T <: Element](cond: => T): SwitchContext[T] = new SwitchContext(cond, None, Set.empty) 8 | } 9 | 10 | class SwitchContext[T <: Element](cond: T, whenContext: Option[WhenContext], lits: Set[BigInt]) { 11 | def is(v: Iterable[T])(block: => Any)( 12 | implicit sourceInfo: SourceInfo, 13 | compileOptions: CompileOptions 14 | ): SwitchContext[T] = { 15 | val newLits = v.map { w => 16 | require(w.litOption.isDefined, "is condition must be literal") 17 | val value = w.litValue 18 | require(!lits.contains(value), "all is conditions must be mutually exclusive!") 19 | value 20 | } 21 | 22 | def p = v.map(_.asUInt === cond.asUInt).reduce(_ || _) 23 | whenContext match { 24 | case Some(w) => new SwitchContext(cond, Some(w.elsewhen(p)(block)), lits ++ newLits) 25 | case None => new SwitchContext(cond, Some(when(p)(block)), lits ++ newLits) 26 | } 27 | } 28 | 29 | def is(vr: T*)(block: => Any)( 30 | implicit sourceInfo: SourceInfo, 31 | compileOptions: CompileOptions 32 | ): SwitchContext[T] = is(vr.toList)(block) 33 | 34 | def default(block: => Any)( 35 | implicit sourceInfo: SourceInfo, 36 | compileOptions: CompileOptions 37 | ): Unit = { 38 | whenContext match { 39 | case Some(w) => w.otherwise(block) 40 | case None => require(false, "Do not use single 'default'") 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /chisel/src/main/scala/ip/BlockMemoryRom.scala: -------------------------------------------------------------------------------- 1 | package ip 2 | 3 | import util.GenerateOptions 4 | import chisel3._ 5 | 6 | private class RawBlockMemoryRom(id: Int, addrWidth: Int, dataWidth: Int) extends BlackBox { 7 | val io = IO(new Bundle { 8 | val addra = Input(UInt(addrWidth.W)) 9 | val clka = Input(Clock()) 10 | val douta = Output(UInt(dataWidth.W)) 11 | }) 12 | 13 | override def desiredName = f"blk_mem_gen_${id}%d" 14 | } 15 | 16 | class MemoryRomPort(val addrWidth: Int, val dataWidth: Int) extends Bundle { 17 | val addr = Input(UInt(addrWidth.W)) 18 | val dataOut = Output(UInt(dataWidth.W)) 19 | 20 | def init(): Unit = { 21 | addr := DontCare 22 | } 23 | 24 | def setRead(addr: UInt): UInt = { 25 | this.addr := addr 26 | dataOut 27 | } 28 | } 29 | 30 | class BlockMemoryRom(id: Int, depth: BigInt, val dataWidth: Int, simInitializeFile: Option[String] = None)(implicit options: GenerateOptions) extends Module { 31 | val addrWidth = LazyList.from(1).filter(x => (1 << x) >= depth).head 32 | val io = IO(new MemoryRomPort(addrWidth, dataWidth)) 33 | 34 | if (options.useIP) { 35 | val raw = Module(new RawBlockMemoryRom(id, addrWidth, dataWidth)) 36 | raw.io.clka := clock 37 | raw.io.addra := io.addr 38 | io.dataOut := raw.io.douta 39 | } 40 | else { 41 | val mem = SyncReadMem(1 << addrWidth, UInt(dataWidth.W)) 42 | simInitializeFile.foreach { file => 43 | chisel3.util.experimental.loadMemoryFromFileInline(mem, file) 44 | } 45 | 46 | io.dataOut := mem.read(io.addr) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /font/convert.py: -------------------------------------------------------------------------------- 1 | import png 2 | import os 3 | import struct 4 | 5 | 6 | def load_glyph_data_from_png(file_path): 7 | width, height, bitmap, info = png.Reader(filename=file_path).read() 8 | glyph_data = [] 9 | for bitmap_row in bitmap: 10 | glyph_data_row = [] 11 | bitmap_row_len = len(bitmap_row) 12 | pixel_step = int(bitmap_row_len / width) 13 | for x in range(pixel_step - 1, bitmap_row_len, pixel_step): 14 | alpha = bitmap_row[x] 15 | if alpha > 127: 16 | glyph_data_row.append(1) 17 | else: 18 | glyph_data_row.append(0) 19 | glyph_data.append(glyph_data_row) 20 | return glyph_data, width, height 21 | 22 | 23 | if __name__ == '__main__': 24 | # for i in range(0x20, 0x7F): 25 | # (data, _, _) = load_glyph_data_from_png(f'0000-007F Basic Latin/00{i:02X}.png') 26 | # with open(f'font_data/{i:02X}.txt', 'w') as f: 27 | # data = '\n'.join([ ''.join([ '_' if c == 0 else '*' for c in row ]) for row in data ]) 28 | # f.write(data + '\n') 29 | 30 | with open('font.txt', 'w') as f: 31 | for i in range(0x00, 0xFF + 1): 32 | filename = f'font_data/{i:02X}.txt' 33 | if os.path.exists(filename): 34 | with open(f'font_data/{i:02X}.txt') as g: 35 | lines = [ line.strip() for line in g ] 36 | values = [ int(line.replace('_', '0').replace('*', '1')[::-1], 2) for line in lines ] 37 | else: 38 | values = [ 0 ] * 16 39 | for v in values: 40 | f.write(struct.pack('>B', v).hex() + '\n') 41 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/logic.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use alloc::vec::Vec; 3 | 4 | use crate::input::{collect_inputs, Input}; 5 | 6 | use super::{phase::running::Running, phase::Phase}; 7 | use crate::game::state::GameState; 8 | 9 | #[derive(PartialEq)] 10 | pub enum End { 11 | Quit, 12 | Restart, 13 | } 14 | 15 | pub enum TickResult { 16 | Phase(Phase), 17 | End(End), 18 | } 19 | 20 | impl From for Option { 21 | fn from(value: Input) -> Self { 22 | match value { 23 | Input::Restart => Some(End::Restart), 24 | Input::Quit => Some(End::Quit), 25 | _ => None, 26 | } 27 | } 28 | } 29 | 30 | pub struct Logic { 31 | phase: Phase, 32 | } 33 | 34 | impl Logic { 35 | pub fn new() -> Self { 36 | Self { 37 | phase: Phase::Running(Box::new(Running { 38 | state: GameState::new(1), 39 | })), 40 | } 41 | } 42 | 43 | pub fn update(&mut self) -> TickResult { 44 | let inputs: Vec = collect_inputs(); 45 | 46 | if let Some(end) = self.check_for_end(&inputs) { 47 | return TickResult::End(end); 48 | } 49 | 50 | match &mut self.phase { 51 | Phase::Running(running) => { 52 | if let Some(finished) = running.handle(&inputs) { 53 | self.phase = Phase::Finished(finished); 54 | } 55 | } 56 | Phase::Finished(finished) => finished.handle(), 57 | }; 58 | 59 | TickResult::Phase(self.phase.clone()) 60 | } 61 | 62 | fn check_for_end(&self, inputs: &[Input]) -> Option { 63 | inputs.iter().find_map(|&x| x.into()) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/phase/running.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use core::mem::swap; 3 | 4 | use crate::{ 5 | game::{state::GameState, tetromino::Tetromino}, 6 | input::Input, 7 | }; 8 | 9 | use super::finished::Finished; 10 | 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub struct Running { 13 | pub state: GameState, 14 | } 15 | 16 | impl Running { 17 | pub fn handle(&mut self, inputs: &[Input]) -> Option> { 18 | if self.state.is_finished() { 19 | return Some(Box::new(Finished { 20 | state: self.state.clone(), 21 | })); 22 | } 23 | 24 | let solidified = self.handle_inputs(inputs); 25 | let solidified = self.state.advance_game(solidified); 26 | 27 | if solidified { 28 | let cleared_lines = self.state.clear_lines(); 29 | self.state.level.up(&cleared_lines); 30 | 31 | swap(&mut self.state.current, &mut self.state.next); 32 | self.state.next = Tetromino::next(); 33 | } 34 | 35 | self.state.preview = self.state.determine_preview(); 36 | 37 | None 38 | } 39 | 40 | fn handle_inputs(&mut self, inputs: &[Input]) -> bool { 41 | let input = inputs.iter().next(); 42 | 43 | match input { 44 | Some(i) => self.handle_input(i), 45 | None => false, 46 | } 47 | } 48 | 49 | fn handle_input(&mut self, input: &Input) -> bool { 50 | match input { 51 | Input::Right => self.state.move_right(), 52 | Input::Left => self.state.move_left(), 53 | Input::Rotate => self.state.rotate(), 54 | _ => (), 55 | } 56 | 57 | match input { 58 | Input::Down => self.state.move_down(), 59 | Input::Drop => self.state.drop(), 60 | _ => false, 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /chisel/src/main/scala/ip/ClockWizard.scala: -------------------------------------------------------------------------------- 1 | package ip 2 | 3 | import util.GenerateOptions 4 | import chisel3._ 5 | 6 | private class RawClockWizard extends BlackBox { 7 | val io = IO(new Bundle { 8 | val reset = Input(Reset()) 9 | val clk_in1 = Input(Clock()) // 100 MHz 10 | val clk_std = Output(Clock()) // 40 MHz 11 | val clk_vga = Output(Clock()) // 40 MHz 12 | val clk_uart = Output(Clock()) // 12.5 MHz 13 | val locked = Output(Bool()) 14 | }) 15 | 16 | override def desiredName = "clk_wiz_0" 17 | } 18 | 19 | class ClockWizard(implicit options: GenerateOptions) extends Module { 20 | val io = IO(new Bundle { 21 | val clockCpu = Output(Clock()) 22 | val clockVga = Output(Clock()) 23 | val clockUart = Output(Clock()) 24 | val reset = Output(Reset()) 25 | }) 26 | 27 | if (options.useIP) { 28 | val raw = Module(new RawClockWizard()) 29 | 30 | // UART needs to slow down further 31 | // 12.5 MHz * (151 / 1024) = 1.8432617188 MHz ~ 115203.857425 Hz * 16(oversample) 32 | withReset (0.B.asAsyncReset) { // disable reset to clock 33 | withClock(raw.io.clk_uart) { 34 | val cnt = RegInit(0.U(10.W)) 35 | cnt := cnt + 151.U 36 | io.clockUart := cnt(cnt.getWidth - 1).asClock 37 | } 38 | } 39 | 40 | raw.io.reset := false.B.asAsyncReset 41 | raw.io.clk_in1 := clock 42 | io.clockCpu := raw.io.clk_std 43 | io.clockVga := raw.io.clk_vga 44 | 45 | val syncReset = Wire(Reset()) 46 | syncReset := (reset.asBool || !raw.io.locked) 47 | io.reset := syncReset 48 | } 49 | else { 50 | // at simulation, the clock doesn't need to be cared a lot 51 | io.clockCpu := clock 52 | 53 | withReset (0.B.asAsyncReset) { 54 | val stdCnt = RegInit(0.U(2.W)) 55 | stdCnt := stdCnt + 1.U 56 | io.clockUart := stdCnt(1).asClock 57 | } 58 | 59 | io.clockVga := clock // ignore now 60 | io.reset := reset 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /chisel/src/test/scala/core/CoreSpec.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import chisel3._ 4 | import chiseltest._ 5 | import org.scalatest.flatspec.AnyFlatSpec 6 | 7 | import scala.util.control._ 8 | 9 | class CoreSpec extends AnyFlatSpec with ChiselScalatestTester { 10 | behavior of "core.Core" 11 | 12 | implicit val debugMode = true 13 | 14 | val regNames = Array("x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6") 15 | 16 | def asUnsigned(x: Int) = (BigInt(x >>> 1) << 1) + (x & 1) 17 | 18 | // it should "work" in { 19 | // test(new Core()).withAnnotations(Seq(WriteVcdAnnotation)) { dut => 20 | // dut.clock.step(1) 21 | // 22 | // val loop = new Breaks 23 | // loop.breakable { 24 | // for (i <- 0 until 512) { 25 | // val pc = dut.debug.get.pc.peek().litValue 26 | // println(f"PC = 0x${pc}%x") 27 | //// println(f"${i}%d, PC: 0x${pc}%x invalid flag: ${dut.debug.get.invalid.peek().litValue}") 28 | // dut.clock.step(2) 29 | // 30 | // for (i <- 0 until 32) { 31 | // dut.debug.get.debugRegAddr.poke(i.U) 32 | // val value = asUnsigned(dut.debug.get.debugRegData.peek().litValue.toInt) 33 | // val name = regNames(i) 34 | // print(f"${name}%3s: ${value}%08x ") 35 | // if ((i + 1) % 8 == 0) 36 | // println() 37 | // } 38 | // 39 | // val value = dut.io.extOut.peek().litValue 40 | // println(f"val: ${value}%08x") 41 | // 42 | // if (pc == 0xd0 || (pc & 0x3) > 0) 43 | // loop.break 44 | // 45 | // // for (i <- 0 until 8) { 46 | // // val value = dut.io.externalOut(i).peek().litValue 47 | // // print(f"${i}%d: ${value}%08x ") 48 | // // } 49 | // // println() 50 | // println() 51 | // } 52 | // } 53 | // } 54 | // } 55 | } 56 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/cycle.rs: -------------------------------------------------------------------------------- 1 | use core::time::Duration; 2 | 3 | use cpu_lib::time::{sleep, Instant}; 4 | 5 | use crate::ui::Ui; 6 | 7 | use super::logic::{End, Logic, TickResult}; 8 | 9 | const TICKS_PER_SECOND: f64 = 60f64; 10 | 11 | pub struct GameLoop { 12 | tick_duration: Duration, 13 | previous: Instant, 14 | current: Instant, 15 | accumulated: Duration, 16 | logic: Logic, 17 | ui: Ui, 18 | } 19 | 20 | impl GameLoop { 21 | pub fn new(logic: Logic, ui: Ui) -> Self { 22 | let instant = Instant::now(); 23 | 24 | GameLoop { 25 | tick_duration: Duration::from_secs_f64(1.0 / TICKS_PER_SECOND), 26 | previous: instant, 27 | current: instant, 28 | accumulated: Duration::default(), 29 | logic, 30 | ui, 31 | } 32 | } 33 | 34 | pub fn run(&mut self) -> End { 35 | self.ui.draw_border(); 36 | loop { 37 | if let Some(end) = self.iterate() { 38 | return end; 39 | } 40 | } 41 | } 42 | 43 | fn iterate(&mut self) -> Option { 44 | self.current = Instant::now(); 45 | 46 | let mut elapsed = self.current - self.previous; 47 | self.previous = self.current; 48 | 49 | if elapsed > self.tick_duration { 50 | elapsed = self.tick_duration; 51 | } 52 | 53 | self.accumulated += elapsed; 54 | 55 | if self.accumulated >= self.tick_duration { 56 | self.accumulated -= self.tick_duration; 57 | 58 | match self.logic.update() { 59 | TickResult::End(end) => { 60 | return Some(end); 61 | } 62 | TickResult::Phase(phase) => self.ui.draw(&phase), 63 | }; 64 | } else { 65 | self.idle(self.tick_duration - self.accumulated); 66 | } 67 | 68 | None 69 | } 70 | 71 | fn idle(&self, difference: Duration) { 72 | sleep(difference); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /chisel/src/main/scala/core/Comparator.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import util._ 4 | import chisel3._ 5 | 6 | class Comparator extends Module { 7 | val io = IO(new Bundle { 8 | val cmpType = Input(CmpType()) 9 | 10 | val lhs = Input(SInt(32.W)) 11 | val rhs = Input(SInt(32.W)) 12 | 13 | val output = Output(Bool()) 14 | }) 15 | 16 | val impl = Module(new ComparatorImpl) 17 | impl.io.lhs := io.lhs 18 | impl.io.rhs := io.rhs 19 | io.output := impl.io.output 20 | 21 | // use three control signals to control the lower-level comparator 22 | def assignToImpl(equals: => Data, invert: => Data, unsigned: => Data): Unit = { 23 | impl.io.equals := equals 24 | impl.io.invert := invert 25 | impl.io.unsigned := unsigned 26 | } 27 | 28 | switch (io.cmpType) 29 | .is(CmpType.Eq ) { assignToImpl(1.B, 0.B, DontCare) } 30 | .is(CmpType.Ne ) { assignToImpl(1.B, 1.B, DontCare) } 31 | .is(CmpType.Lt ) { assignToImpl(0.B, 0.B, 0.B) } 32 | .is(CmpType.Ge ) { assignToImpl(0.B, 1.B, 0.B) } 33 | .is(CmpType.LtU) { assignToImpl(0.B, 0.B, 1.B) } 34 | .is(CmpType.GeU) { assignToImpl(0.B, 1.B, 1.B) } 35 | .default { assignToImpl(DontCare, DontCare, DontCare) } 36 | } 37 | 38 | object CmpType extends ChiselEnum { 39 | val Eq, Ne, Lt, Ge, LtU, GeU = Value 40 | } 41 | 42 | // lower-level comparator, only compare equals and less-than 43 | // with control of `unsigned` (the input) and `invert` (the result) 44 | class ComparatorImpl extends Module { 45 | val io = IO(new Bundle { 46 | val equals = Input(Bool()) 47 | val invert = Input(Bool()) 48 | val unsigned = Input(Bool()) 49 | 50 | val lhs = Input(SInt(32.W)) 51 | val rhs = Input(SInt(32.W)) 52 | 53 | val output = Output(Bool()) 54 | }) 55 | 56 | val equals = io.lhs === io.rhs 57 | val lessThanS = io.lhs < io.rhs 58 | val lessThanU = io.lhs.asUInt < io.rhs.asUInt 59 | 60 | val interim = Wire(Bool()) 61 | when (io.equals === true.B) { 62 | interim := equals 63 | } .elsewhen (io.unsigned === true.B) { 64 | interim := lessThanU 65 | } .otherwise { 66 | interim := lessThanS 67 | } 68 | 69 | io.output := interim ^ io.invert 70 | } 71 | -------------------------------------------------------------------------------- /program/src/board.rs: -------------------------------------------------------------------------------- 1 | use core::ptr::{read_volatile, write_volatile}; 2 | 3 | const SWITCH_BASEADDR: *mut u32 = 0xFFFFF100 as *mut u32; 4 | const LED_BASEADDR: *mut u32 = 0xFFFFF200 as *mut u32; 5 | 6 | #[derive(Debug)] 7 | #[repr(u8)] 8 | pub enum Keyboard { 9 | _0 = 2, 10 | _1 = 15, 11 | _2 = 14, 12 | _3 = 13, 13 | _4 = 11, 14 | _5 = 10, 15 | _6 = 9, 16 | _7 = 7, 17 | _8 = 6, 18 | _9 = 5, 19 | A = 12, 20 | B = 8, 21 | C = 4, 22 | D = 0, 23 | Star = 3, 24 | Number = 1, 25 | } 26 | 27 | #[repr(usize)] 28 | pub enum Button { 29 | Center = 0xFFFFF01C, 30 | Up = 0xFFFFF020, 31 | Down = 0xFFFFF024, 32 | Left = 0xFFFFF028, 33 | Right = 0xFFFFF02C, 34 | } 35 | 36 | impl Keyboard { 37 | pub fn as_number(&self) -> Option { 38 | match self { 39 | Keyboard::_0 => Some(0), 40 | Keyboard::_1 => Some(1), 41 | Keyboard::_2 => Some(2), 42 | Keyboard::_3 => Some(3), 43 | Keyboard::_4 => Some(4), 44 | Keyboard::_5 => Some(5), 45 | Keyboard::_6 => Some(6), 46 | Keyboard::_7 => Some(7), 47 | Keyboard::_8 => Some(8), 48 | Keyboard::_9 => Some(9), 49 | _ => None, 50 | } 51 | } 52 | } 53 | 54 | #[inline] 55 | pub unsafe fn read_u32(addr: usize) -> u32 { 56 | read_volatile(addr as *mut u32) 57 | } 58 | 59 | #[inline] 60 | pub unsafe fn write_u32(addr: usize, data: u32) { 61 | write_volatile(addr as *mut u32, data) 62 | } 63 | 64 | pub fn read_switch(index: usize) -> bool { 65 | assert!(index < 24); 66 | unsafe { SWITCH_BASEADDR.add(index).read_volatile() > 0 } 67 | } 68 | 69 | pub fn set_led(index: usize, enable: bool) { 70 | assert!(index < 24); 71 | unsafe { LED_BASEADDR.add(index).write_volatile(enable as u32) } 72 | } 73 | 74 | pub fn read_button(button: Button) -> bool { 75 | unsafe { read_u32(button as usize) > 0 } 76 | } 77 | 78 | pub fn random_value() -> u32 { 79 | unsafe { read_u32(0xFFFFF044) } 80 | } 81 | 82 | pub fn keyboard_ready() -> bool { 83 | unsafe { read_u32(0xFFFFF018) > 0 } 84 | } 85 | 86 | pub fn read_keyboard() -> Keyboard { 87 | while !keyboard_ready() {} 88 | unsafe { core::mem::transmute(read_u32(0xFFFFF014) as u8) } 89 | } 90 | -------------------------------------------------------------------------------- /program/src/console.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{self, Write}; 2 | 3 | use crate::monitor; 4 | use crate::uart; 5 | 6 | struct Stdout; 7 | 8 | const UART_NEWLINE: u8 = b'\r'; 9 | const UART_BACKSPACE: u8 = b'\x7f'; 10 | 11 | static mut PRINT_TO_SCREEN: bool = true; 12 | 13 | fn putchar(ch: u8) { 14 | uart::write(ch); 15 | if unsafe { PRINT_TO_SCREEN } { 16 | monitor::monitor::putchar(ch); 17 | } 18 | } 19 | 20 | pub fn set_screen_print(enable: bool) { 21 | unsafe { PRINT_TO_SCREEN = enable } 22 | } 23 | 24 | impl Write for Stdout { 25 | fn write_str(&mut self, s: &str) -> fmt::Result { 26 | for c in s.chars() { 27 | putchar(c as u8); 28 | } 29 | Ok(()) 30 | } 31 | } 32 | 33 | pub fn print_str(s: &str) { 34 | let result = Stdout.write_str(s); 35 | unsafe { result.unwrap_unchecked() } 36 | } 37 | 38 | pub fn print(args: fmt::Arguments) { 39 | Stdout.write_fmt(args).unwrap(); 40 | } 41 | 42 | #[macro_export] 43 | macro_rules! print { 44 | ($fmt: literal $(, $($arg: tt)+)?) => { 45 | $crate::prelude::print(format_args!($fmt $(, $($arg)+)?)) 46 | } 47 | } 48 | 49 | #[macro_export] 50 | macro_rules! println { 51 | ($fmt: literal $(, $($arg: tt)+)?) => { 52 | $crate::prelude::print(format_args!(concat!($fmt, "\r\n") $(, $($arg)+)?)) 53 | } 54 | } 55 | 56 | pub fn get_char(echo: bool) -> u8 { 57 | let c = uart::read(); 58 | if echo { 59 | putchar(c); 60 | match c { 61 | UART_NEWLINE => putchar(b'\n'), 62 | UART_BACKSPACE => { 63 | putchar(b'\x08'); 64 | putchar(b' '); 65 | putchar(b'\x08'); 66 | } 67 | _ => {} 68 | } 69 | } 70 | c 71 | } 72 | 73 | pub fn read_line(buf: &mut [u8]) -> &str { 74 | let mut idx: usize = 0; 75 | 76 | while idx < buf.len() { 77 | match get_char(true) { 78 | UART_NEWLINE => break, 79 | UART_BACKSPACE => { 80 | idx = idx.saturating_sub(1); 81 | } 82 | c => { 83 | buf[idx] = c; 84 | idx += 1; 85 | } 86 | } 87 | } 88 | 89 | if idx > buf.len() { 90 | unsafe { core::hint::unreachable_unchecked() } 91 | } 92 | 93 | unsafe { core::str::from_utf8_unchecked(&buf[..idx]) } 94 | } 95 | -------------------------------------------------------------------------------- /program/src/bin/task1.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | #[macro_use] 5 | extern crate cpu_lib; 6 | 7 | use cpu_lib::prelude::*; 8 | 9 | fn read_switch_number() -> u8 { 10 | let mut v = 0; 11 | for i in 0..8 { 12 | v = v << 1 | (read_switch(7 - i) as u8); 13 | } 14 | v 15 | } 16 | 17 | fn set_led_number(v: u8) { 18 | for i in 0..8 { 19 | set_led(i, (v & (1 << i)) > 0); 20 | } 21 | } 22 | 23 | #[no_mangle] 24 | fn main() -> i32 { 25 | loop { 26 | println!("new task!"); 27 | 28 | while !read_button(Button::Center) {} 29 | 30 | let b: u32 = read_switch(16) as u32 31 | | ((read_switch(17) as u32) << 1) 32 | | ((read_switch(18) as u32) << 2); 33 | println!("b = {}", b); 34 | 35 | (0..8).for_each(|x| set_led(x + 16, false)); 36 | set_led(16 + b as usize, true); 37 | 38 | while read_button(Button::Center) {} 39 | while !read_button(Button::Center) {} 40 | 41 | let v1 = read_switch_number(); 42 | set_led_number(v1); 43 | println!("v1 = {}", v1); 44 | 45 | while read_button(Button::Center) {} 46 | while !read_button(Button::Center) {} 47 | 48 | let v2 = if b > 1 { read_switch_number() } else { 0 }; 49 | set_led_number(v2); 50 | println!("v2 = {}", v2); 51 | 52 | while read_button(Button::Center) {} 53 | while !read_button(Button::Center) {} 54 | 55 | let r = match b { 56 | 0b000 => { 57 | let a = v1 as i32; 58 | ((a & (a - 1)) == 0) as u8 59 | } 60 | 0b001 => v1 % 2, 61 | 0b010 => v1 | v2, 62 | 0b011 => !(v1 | v2), 63 | 0b100 => v1 ^ v2, 64 | 0b101 => ((v1 as i8) < (v2 as i8)) as u8, 65 | 0b110 => (v1 < v2) as u8, 66 | 0b111 => { 67 | println!("show v1 = {}", v1); 68 | set_tube_value_option(Some(v1 as u32)); 69 | 70 | while read_button(Button::Center) {} 71 | while !read_button(Button::Center) {} 72 | 73 | v2 74 | } 75 | _ => 0, 76 | }; 77 | set_led_number(r); 78 | set_tube_value_option(Some(r as u32)); 79 | println!("r = {}", r); 80 | 81 | while read_button(Button::Center) {} 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /chisel/src/main/scala/core/Core.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import util._ 4 | import board._ 5 | import ip._ 6 | import chisel3._ 7 | 8 | class Core(implicit options: GenerateOptions) extends Module { 9 | val io = IO(new Bundle { 10 | val cycles = Output(UInt(32.W)) 11 | val external = Flipped(new BoardDataBundle()) 12 | 13 | val interrupt = Input(Bool()) 14 | val originPC = Output(UInt(32.W)) 15 | }) 16 | 17 | val id = Module(new Decoder()) 18 | val alu = Module(new ALU()) 19 | val cmp = Module(new Comparator()) 20 | val reg = Module(new RegisterFile()) 21 | val mem = Module(new Memory(32768)) 22 | 23 | // Core (Sequential) logic 24 | val cycles = RegInit(0.U(32.W)) 25 | val stage = RegInit(1.B) 26 | val pc = RegInit(0.U(32.W)) 27 | val pcOld = RegInit(0.U(32.W)) 28 | val originPC = RegInit(0.U(32.W)) 29 | val nextPc = Wire(UInt(32.W)) 30 | 31 | when(stage) { 32 | cycles := cycles + 1.U 33 | }.otherwise { 34 | pcOld := pc 35 | 36 | // interrupt handling 37 | pc := Mux(io.interrupt, 0.U, nextPc) 38 | when (io.interrupt) { originPC := pc } 39 | } 40 | stage := !stage 41 | 42 | // Core (combination) logic 43 | io.external <> mem.io.external 44 | io.cycles := cycles 45 | io.originPC := originPC 46 | 47 | val exeResult = Wire(SInt(32.W)) 48 | mem.io.addrPC := pc 49 | id.io.instruction := mem.io.dataPC 50 | 51 | val PcSrc = Mux(id.io.pcUseReg, reg.io.rs1Out.asUInt, pc) 52 | nextPc := Mux((cmp.io.output && id.io.branch) | id.io.jump, PcSrc + id.io.immPc.asUInt, pc + 4.U) 53 | 54 | reg.io.rs1Addr := id.io.rs1 55 | reg.io.rs2Addr := id.io.rs2 56 | reg.io.rdAddr := id.io.rd 57 | reg.io.write := id.io.regWrite && stage 58 | reg.io.rdDataIn := Mux(id.io.memLoad, mem.io.dataOut, exeResult) 59 | 60 | cmp.io.cmpType := id.io.cmpType 61 | cmp.io.lhs := reg.io.rs1Out 62 | cmp.io.rhs := Mux(id.io.useImm, id.io.imm, reg.io.rs2Out) 63 | alu.io.aluType := id.io.aluType 64 | alu.io.lhs := Mux(id.io.pcLink, pcOld.asSInt, reg.io.rs1Out) 65 | alu.io.rhs := reg.io.rs2Out 66 | alu.io.shamt := Mux(id.io.useImm, id.io.rs2, reg.io.rs2Out(4, 0).asUInt) 67 | exeResult := Mux(id.io.useALU, alu.io.output, ZeroExt32(cmp.io.output).asSInt) 68 | 69 | mem.io.addr := exeResult.asUInt 70 | mem.io.memWidth := id.io.memWidth 71 | mem.io.write := id.io.memWrite && stage // only perform write on stage=1 72 | mem.io.willWrite := id.io.memWrite 73 | mem.io.enable := id.io.memLoad | id.io.memWrite 74 | mem.io.dataIn := reg.io.rs2Out 75 | mem.io.unsigned := id.io.memUnsigned 76 | mem.io.stage := stage 77 | } 78 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/level.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::{max, min}; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub struct Level { 5 | pub current: u32, 6 | pub score: u32, 7 | pub cleared_lines: u32, 8 | } 9 | 10 | impl Level { 11 | pub fn new(level: u32) -> Self { 12 | Self { 13 | current: level, 14 | score: 0, 15 | cleared_lines: 0, 16 | } 17 | } 18 | 19 | pub const fn required_ticks(&self) -> u32 { 20 | match self.current { 21 | 0 => 48, 22 | 1 => 43, 23 | 2 => 38, 24 | 3 => 33, 25 | 4 => 28, 26 | 5 => 23, 27 | 6 => 18, 28 | 7 => 13, 29 | 8 => 8, 30 | 9 => 6, 31 | 10..=12 => 5, 32 | 13..=15 => 4, 33 | 16..=18 => 3, 34 | 19..=28 => 2, 35 | _ => 1, 36 | } 37 | } 38 | 39 | fn required_lines(&self) -> u32 { 40 | min( 41 | self.current * 10 + 10, 42 | max(100, (self.current * 10).saturating_sub(50)), 43 | ) 44 | } 45 | 46 | pub fn up(&mut self, cleared: &ClearedLines) { 47 | self.cleared_lines += cleared.value(); 48 | self.score += self.score(cleared); 49 | 50 | if self.cleared_lines >= self.required_lines() { 51 | self.current += 1; 52 | } 53 | } 54 | 55 | const fn score(&self, cleared: &ClearedLines) -> u32 { 56 | match cleared { 57 | ClearedLines::None => 0, 58 | ClearedLines::Single => 40 * (self.current + 1), 59 | ClearedLines::Double => 100 * (self.current + 1), 60 | ClearedLines::Triple => 300 * (self.current + 1), 61 | ClearedLines::Tetrs => 1200 * (self.current + 1), 62 | } 63 | } 64 | } 65 | 66 | impl From for ClearedLines { 67 | fn from(value: usize) -> Self { 68 | match value { 69 | 0 => ClearedLines::None, 70 | 1 => ClearedLines::Single, 71 | 2 => ClearedLines::Double, 72 | 3 => ClearedLines::Triple, 73 | 4 => ClearedLines::Tetrs, 74 | _ => panic!("This must never happen"), 75 | } 76 | } 77 | } 78 | 79 | impl ClearedLines { 80 | fn value(&self) -> u32 { 81 | match self { 82 | ClearedLines::None => 0, 83 | ClearedLines::Single => 1, 84 | ClearedLines::Double => 2, 85 | ClearedLines::Triple => 3, 86 | ClearedLines::Tetrs => 4, 87 | } 88 | } 89 | } 90 | 91 | pub enum ClearedLines { 92 | None, 93 | Single, 94 | Double, 95 | Triple, 96 | Tetrs, 97 | } 98 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/Keyboard.scala: -------------------------------------------------------------------------------- 1 | package board 2 | 3 | import util.{Counter, _} 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | class KeyboardInBundle extends Bundle { 8 | val rows = Output(Vec(4, Bool())) 9 | val cols = Input(Vec(4, Bool())) 10 | } 11 | 12 | class Keyboard(implicit options: GenerateOptions) extends Module { 13 | private val REQUIRED_INTERVAL = 1 // ms 14 | private val REQUIRED_CYCLES = options.systemClock * REQUIRED_INTERVAL / 1000 15 | private val REQUIRED_BITS = Helper.log2(REQUIRED_CYCLES) 16 | 17 | val io = IO(new Bundle { 18 | val in = new KeyboardInBundle() // require denounced 19 | val out = Decoupled(KeyboardButton()) 20 | }) 21 | 22 | // the columns data for each row 23 | val rows = RegInit(VecInit.fill(4)(0.U(4.W))) 24 | 25 | // because debounce in keyboard is hard, so we slow down the scan speed to achieve debounce 26 | // here, we scan every line in every 2^REQUIRED_CYCLES cycles. 27 | val tick = Pulse(Counter.maxBits(REQUIRED_BITS)) 28 | val cnt = Counter.maxBits(2, tick) 29 | io.in.rows := RegNext(~Encoder(4)(cnt)).asTypeOf(UInt(4.W)).asBools 30 | when (tick) { rows(cnt) := ~io.in.cols.asUInt } 31 | 32 | 33 | // record whether the key is pressed, avoiding multiple events 34 | val press = RegInit(false.B) 35 | // if no rows has key pressed, then reset `press` 36 | when (!rows.asUInt.orR) { 37 | press := false.B 38 | } 39 | 40 | // now, we scan each line, to decode which key is pressed 41 | val state = RegInit(KeyboardState.Row1) 42 | state := MuxLookup(state, KeyboardState.Row1)(KeyboardState.nextTable()) 43 | 44 | val currentRow = rows(state.asUInt) 45 | // `onDown`: tell whether `currentRow` has new key pressed (so rule out that `press` is true) 46 | // note: `onDown` will be high in only one cycle 47 | val onDown = !press && currentRow.orR 48 | val out = RegInit(KeyboardButton._1) 49 | 50 | io.out.bits := out 51 | io.out.valid := RegNext(onDown) // delay one cycle, to match `io.out.bits` 52 | 53 | when (onDown) { 54 | val row = state.asUInt 55 | val col = Decoder(4)(currentRow) 56 | out := KeyboardButton(Cat(row, col)) // decode the key by simple concat 57 | press := true.B 58 | } 59 | } 60 | 61 | object KeyboardState extends ChiselEnum { 62 | val Row1 = Value(0.U) 63 | val Row2 = Value(1.U) 64 | val Row3 = Value(2.U) 65 | val Row4 = Value(3.U) 66 | 67 | def nextTable(): Seq[(Type, Type)] = Seq( 68 | Row1 -> Row2, 69 | Row2 -> Row3, 70 | Row3 -> Row4, 71 | Row4 -> Row1, 72 | ) 73 | } 74 | 75 | object KeyboardButton extends ChiselEnum { 76 | val D, _Number, _0, Star, 77 | C, _9, _8, _7, 78 | B, _6, _5, _4, 79 | A, _3, _2, _1 = Value 80 | } 81 | -------------------------------------------------------------------------------- /chisel/README.md: -------------------------------------------------------------------------------- 1 | 源码在 [src/main/scala](src/main/scala) 文件夹下。 2 | 3 | ## 目录结构 4 | 5 | | 文件(夹) | 备注 | 6 | |---------------------------------------------------------------------------|----------| 7 | | [Top.scala](src/main/scala/Top.scala) | 顶层模块 | 8 | | [core/](src/main/scala/core) | CPU 核心部分 | 9 | |   [Core.scala](src/main/scala/core/Core.scala) | CPU 核心部分的顶层模块(主要是连线) | 10 | |   [Decoder.scala](src/main/scala/core/Decoder.scala) | ID 模块,从指令解码出各种控制线的值(有点像 control) | 11 | |   [Memory.scala](src/main/scala/core/Memory.scala) | 内存部分,包括翻译 MMIO 地址 | 12 | |   [ALU.scala](src/main/scala/core/ALU.scala) | ALU 模块 | 13 | |   [Comparator.scala](src/main/scala/core/Comparator.scala) | 比较(大于小于等)模块,RISC-V 需要 | 14 | |   [RegisterFile.scala](src/main/scala/core/RegisterFile.scala) | 寄存器表 | 15 | | [board/](src/main/scala/board) | 硬件 IO 部分(把 CPU 的内存操作翻译到板子需要的 IO 信号,反之亦然) | 16 | |   [Board.scala](src/main/scala/board/Board.scala) | IO 部分的顶层模块(主要也是连线) | 17 | |   [display/](src/main/scala/board/display) | VGA 显示 | 18 | |    [Console.scala](src/main/scala/board/display/Console.scala) | VGA 核心部分,从缓冲区读取字符并渲染出来 | 19 | |    [VGA.scala](src/main/scala/board/display/VGA.scala) | VGA 屏幕参数和 Timing 部分 | 20 | |    [Color.scala](src/main/scala/board/display/Color.scala) | 16 色调色板 | 21 | |   [UART.scala](src/main/scala/board/UART.scala) | UART | 22 | |   [Keyboard.scala](src/main/scala/board/Keyboard.scala) | 小键盘 | 23 | |   [Tubes.scala](src/main/scala/board/Tubes.scala) | 7 段数码管 | 24 | | [ip/](src/main/scala/ip) | 用 BlackBox 来对接 Vivado 的 IP 核 | 25 | |   [BlockMemory.scala](src/main/scala/ip/BlockMemory.scala) | Block Memory(双端口读写) | 26 | |   [BlockMemoryRom.scala](src/main/scala/ip/BlockMemoryRom.scala) | Block Memory (ROM) | 27 | |   [ClockWizard.scala](src/main/scala/ip/ClockWizard.scala) | Clock Wizard | 28 | | [misc/](src/main/scala/misc) | 一些杂七杂八的模块 | 29 | |   [CrossClockQueue.scala](src/main/scala/misc/CrossClockQueue.scala) | 用于跨时钟传输数据的循环队列 | 30 | |   [Debounce.scala](src/main/scala/misc/Debounce.scala) | 消抖模块 | 31 | |   [RNG.scala](src/main/scala/misc/RNG.scala) | 基于 LFSR 的随机数生成器 | 32 | | [util/](src/main/scala/util) | 一些杂七杂八的 util 函数(一般与模块无关) | 33 | -------------------------------------------------------------------------------- /chisel/src/main/scala/ip/BlockMemory.scala: -------------------------------------------------------------------------------- 1 | package ip 2 | 3 | import util.GenerateOptions 4 | import chisel3._ 5 | 6 | private class RawBlockMemory(id: Int, addrWidth: Int, dataWidth: Int) extends BlackBox { 7 | val io = IO(new Bundle { 8 | val addra = Input(UInt(addrWidth.W)) 9 | val clka = Input(Clock()) 10 | val dina = Input(UInt(dataWidth.W)) 11 | val douta = Output(UInt(dataWidth.W)) 12 | val wea = Input(Bool()) 13 | 14 | val addrb = Input(UInt(addrWidth.W)) 15 | val clkb = Input(Clock()) 16 | val dinb = Input(UInt(dataWidth.W)) 17 | val doutb = Output(UInt(dataWidth.W)) 18 | val web = Input(Bool()) 19 | }) 20 | 21 | override def desiredName = f"blk_mem_gen_${id}%d" 22 | } 23 | 24 | class MemoryPort(val addrWidth: Int, val dataWidth: Int) extends Bundle { 25 | val addr = Input(UInt(addrWidth.W)) 26 | val dataIn = Input(UInt(dataWidth.W)) 27 | val dataOut = Output(UInt(dataWidth.W)) 28 | val write = Input(Bool()) 29 | 30 | def init(): Unit = { 31 | addr := DontCare 32 | dataIn := DontCare 33 | write := false.B 34 | } 35 | 36 | def setRead(addr: UInt): UInt = { 37 | this.addr := addr 38 | dataOut 39 | } 40 | 41 | def setWrite(addr: UInt, data: UInt, write: Bool): Unit = { 42 | this.addr := addr 43 | this.dataIn := data 44 | this.write := write 45 | } 46 | } 47 | 48 | // BlockMemory that calls the Vivado IP (if IP is enabled in `options`), 49 | // or otherwise use array as memory at out-of-Vivado simulation 50 | class BlockMemory(id: Int, depth: BigInt, val dataWidth: Int, simInitializeFile: Option[String] = None)(implicit options: GenerateOptions) extends Module { 51 | val addrWidth = LazyList.from(1).filter(x => (1 << x) >= depth).head 52 | val io1 = IO(new MemoryPort(addrWidth, dataWidth)) 53 | val io2 = IO(new MemoryPort(addrWidth, dataWidth)) 54 | 55 | val io = IO(new Bundle { 56 | val clockB = Input(Clock()) 57 | }) 58 | 59 | if (options.useIP) { 60 | val raw = Module(new RawBlockMemory(id, addrWidth, dataWidth)) 61 | raw.io.clka := clock 62 | raw.io.addra := io1.addr 63 | raw.io.dina := io1.dataIn 64 | io1.dataOut := raw.io.douta 65 | raw.io.wea := io1.write 66 | 67 | raw.io.clkb := io.clockB 68 | raw.io.addrb := io2.addr 69 | raw.io.dinb := io2.dataIn 70 | io2.dataOut := raw.io.doutb 71 | raw.io.web := io2.write 72 | } 73 | else { 74 | val mem = SyncReadMem(1 << addrWidth, UInt(dataWidth.W)) 75 | simInitializeFile.foreach { file => 76 | chisel3.util.experimental.loadMemoryFromFileInline(mem, file) 77 | } 78 | 79 | def generate_for(io: MemoryPort, clock: Clock) = { 80 | io.dataOut := mem.read(io.addr, clock) 81 | when (io.write) { 82 | mem.write(io.addr, io.dataIn, clock) 83 | } 84 | } 85 | 86 | generate_for(io1, clock) 87 | generate_for(io2, io.clockB) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/display/Color.scala: -------------------------------------------------------------------------------- 1 | package board.display 2 | 3 | import chisel3._ 4 | import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor 5 | 6 | class RGB4BitBundle extends Bundle { 7 | val r = UInt(4.W) 8 | val g = UInt(4.W) 9 | val b = UInt(4.W) 10 | } 11 | 12 | object RGB4BitBundle { 13 | def fromRGBLiteral(r: Int, g: Int, b: Int): RGB4BitBundle = 14 | (new RGB4BitBundle).Lit(_.r -> r.U(4.W), _.g -> g.U(4.W), _.b -> b.U(4.W)) 15 | def Black: RGB4BitBundle = fromRGBLiteral(0, 0, 0) 16 | } 17 | 18 | class ColorRGB4Bit(val r : Int, val g : Int, val b : Int) { 19 | def asChiselBundle: RGB4BitBundle = RGB4BitBundle.fromRGBLiteral(r, g, b) 20 | } 21 | 22 | object ColorRGB4Bit { 23 | private def makeBetween(value: Int, min: Int, max: Int): Int = 24 | Math.max(min, Math.min(max, value)) 25 | 26 | def fromFullRGB(r: Int, g: Int, b: Int): ColorRGB4Bit = new ColorRGB4Bit( 27 | makeBetween((r >> 4) + ((r >> 3) & 1), 0, 0xF), 28 | makeBetween((g >> 4) + ((r >> 3) & 1), 0, 0xF), 29 | makeBetween((b >> 4) + ((r >> 3) & 1), 0, 0xF), 30 | ) 31 | } 32 | 33 | object DraculaPalette { 34 | val Background = ColorRGB4Bit.fromFullRGB(40, 42, 54) 35 | val CurrentLine = ColorRGB4Bit.fromFullRGB(68, 71, 90) 36 | val Foreground = ColorRGB4Bit.fromFullRGB(248, 248, 242) 37 | val Comment = ColorRGB4Bit.fromFullRGB(98, 114, 164) 38 | val Cyan = ColorRGB4Bit.fromFullRGB(139, 233, 253) 39 | val Green = ColorRGB4Bit.fromFullRGB(80, 250, 123) 40 | val Orange = ColorRGB4Bit.fromFullRGB(255, 184, 108) 41 | val Pink = ColorRGB4Bit.fromFullRGB(255, 121, 198) 42 | val Purple = ColorRGB4Bit.fromFullRGB(189, 147, 249) 43 | val Red = ColorRGB4Bit.fromFullRGB(255, 85, 85) 44 | val Yellow = ColorRGB4Bit.fromFullRGB(241, 250, 140) 45 | } 46 | 47 | object DraculaPaletteModified { 48 | val Background = new ColorRGB4Bit(0x2, 0x2, 0x2) 49 | // val Background = ColorRGB4Bit.fromFullRGB(40, 42, 54) 50 | val CurrentLine = ColorRGB4Bit.fromFullRGB(68, 71, 90) 51 | val Foreground = ColorRGB4Bit.fromFullRGB(248, 248, 242) 52 | val Comment = ColorRGB4Bit.fromFullRGB(98, 114, 164) 53 | val Black = new ColorRGB4Bit(0x2, 0x2, 0x2) 54 | val BrightBlack = new ColorRGB4Bit(0x6, 0x7, 0xA) 55 | val Red = new ColorRGB4Bit(0xF, 0x5, 0x5) 56 | val BrightRed = new ColorRGB4Bit(0xF, 0x8, 0x8) 57 | val Green = new ColorRGB4Bit(0x3, 0xE, 0x6) 58 | val BrightGreen = new ColorRGB4Bit(0x7, 0xF, 0xA) 59 | val Yellow = new ColorRGB4Bit(0xE, 0xE, 0x6) 60 | val BrightYellow = new ColorRGB4Bit(0xF, 0xF, 0xB) 61 | val Blue = new ColorRGB4Bit(0xB, 0x9, 0xF) 62 | val BrightBlue = new ColorRGB4Bit(0xD, 0xA, 0xF) 63 | val Magenta = new ColorRGB4Bit(0xE, 0x6, 0xB) 64 | val BrightMagenta = new ColorRGB4Bit(0xF, 0x9, 0xD) 65 | val Cyan = new ColorRGB4Bit(0x7, 0xC, 0xD) 66 | val BrightCyan = new ColorRGB4Bit(0xA, 0xE, 0xE) 67 | val White = new ColorRGB4Bit(0xE, 0xE, 0xE) 68 | val BrightWhite = new ColorRGB4Bit(0xF, 0xF, 0xF) 69 | } 70 | -------------------------------------------------------------------------------- /program/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := riscv32i-unknown-none-elf 2 | MODE := release 3 | 4 | PROGRAM_SRC_DIR := src/bin 5 | CARGO_TARGET_DIR := target/$(TARGET)/$(MODE) 6 | TARGET_DIR := bin 7 | 8 | PROGRAM_SRC := $(wildcard $(PROGRAM_SRC_DIR)/*.rs) $(PROGRAM_SRC_DIR)/tetris.rs 9 | PROGRAM_NAMES := $(notdir $(PROGRAM_SRC)) 10 | PROGRAM_ELF := $(addprefix $(CARGO_TARGET_DIR)/,$(filter-out tetris,$(PROGRAM_NAMES:%.rs=%))) 11 | PROGRAM_BIN := $(addprefix $(TARGET_DIR)/,$(PROGRAM_NAMES:%.rs=%.bin)) 12 | PROGRAM_TXT := $(addprefix $(TARGET_DIR)/,$(PROGRAM_NAMES:%.rs=%.txt)) 13 | PROGRAM_COE := $(addprefix $(TARGET_DIR)/,$(PROGRAM_NAMES:%.rs=%.coe)) 14 | PROGRAM_WITH_LOADER := $(addprefix $(TARGET_DIR)/,$(PROGRAM_NAMES:%.rs=%-loader.txt)) 15 | PROGRAM_ASM := $(addprefix $(TARGET_DIR)/,$(PROGRAM_NAMES:%.rs=%.asm)) 16 | 17 | TETRIS_SRC := $(shell find $(PROGRAM_SRC_DIR)/tetris -type f) 18 | 19 | LOADER_LINKER := src/linker-loader.ld 20 | PROGRAM_LINKER := src/linker-program.ld 21 | 22 | RUST_DEPS := $(filter-out $(shell find $(PROGRAM_SRC_DIR) -type f) $(LOADER_LINKER) $(PROGRAM_LINKER),$(shell find src -type f)) Cargo.toml 23 | 24 | ifeq ($(MODE), release) 25 | MODE_ARG := --release 26 | endif 27 | 28 | OBJDUMP := rust-objdump --arch-name=riscv32 29 | OBJCOPY := rust-objcopy --binary-architecture=riscv32 30 | 31 | .PHONY: all 32 | all: $(PROGRAM_BIN) $(PROGRAM_TXT) $(PROGRAM_COE) $(PROGRAM_WITH_LOADER) $(PROGRAM_ASM) 33 | 34 | $(TARGET_DIR): 35 | mkdir -p $(TARGET_DIR) 36 | 37 | $(PROGRAM_ELF): $(CARGO_TARGET_DIR)/%: $(PROGRAM_SRC_DIR)/%.rs $(RUST_DEPS) $(PROGRAM_LINKER) 38 | cp $(PROGRAM_LINKER) src/linker.ld 39 | cargo build $(MODE_ARG) --bin $* 40 | rm src/linker.ld 41 | 42 | $(CARGO_TARGET_DIR)/tetris: $(TETRIS_SRC) $(RUST_DEPS) $(PROGRAM_LINKER) 43 | cp $(PROGRAM_LINKER) src/linker.ld 44 | cargo build $(MODE_ARG) --bin tetris --features="alloc" 45 | rm src/linker.ld 46 | 47 | $(CARGO_TARGET_DIR)/loader: $(PROGRAM_SRC_DIR)/loader.rs $(RUST_DEPS) $(LOADER_LINKER) 48 | cp $(LOADER_LINKER) src/linker.ld 49 | cargo build $(MODE_ARG) --bin $* 50 | rm src/linker.ld 51 | 52 | $(PROGRAM_ASM): $(TARGET_DIR)/%.asm: $(CARGO_TARGET_DIR)/% | $(TARGET_DIR) 53 | $(OBJDUMP) -S $< > $@ 54 | 55 | $(PROGRAM_BIN): $(TARGET_DIR)/%.bin: $(CARGO_TARGET_DIR)/% | $(TARGET_DIR) 56 | $(OBJCOPY) $< --strip-all -O binary $@ 57 | head -c $$((4 - $$(stat -f %z $@) % 4)) /dev/zero >> $@ 58 | 59 | $(PROGRAM_TXT): $(TARGET_DIR)/%.txt: $(TARGET_DIR)/%.bin | $(TARGET_DIR) 60 | xxd -ps -c 4 -e $< | awk '{ print $$2 }' > $@ 61 | 62 | $(PROGRAM_COE): $(TARGET_DIR)/%.coe: $(TARGET_DIR)/%.txt | $(TARGET_DIR) 63 | echo 'memory_initialization_radix = 16;\nmemory_initialization_vector =' > $@ 64 | cat $< | awk '{ print $$0"," }' >> $@ 65 | echo '00000000;' >> $@ 66 | 67 | $(PROGRAM_WITH_LOADER): $(TARGET_DIR)/%-loader.txt: $(TARGET_DIR)/%.txt $(TARGET_DIR)/loader.txt fill.py | $(TARGET_DIR) 68 | python3 fill.py $(TARGET_DIR)/loader.txt $@ 69 | cat $< >> $@ 70 | 71 | .PHONY: send 72 | send: bin/$(PROGRAM).bin 73 | stat -f %z $< | tr '\n' '\r' > /dev/tty.usbserial-120 74 | cat $< > /dev/tty.usbserial-120 75 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/display/VGA.scala: -------------------------------------------------------------------------------- 1 | package board.display 2 | 3 | import chisel3._ 4 | 5 | case class OneTiming( 6 | visibleArea: Int, 7 | frontPorch: Int, 8 | syncPulse: Int, 9 | backPorch: Int, 10 | ) { 11 | def wholeLine: Int = visibleArea + frontPorch + syncPulse + backPorch 12 | 13 | def lineStart: Int = 0 - frontPorch - syncPulse - backPorch 14 | def syncStart: Int = lineStart + frontPorch 15 | def syncEnd: Int = syncStart + syncPulse 16 | def activeStart: Int = 0 17 | def lineEnd: Int = visibleArea 18 | } 19 | 20 | case class VGAParams( 21 | horizontal: OneTiming, 22 | vertical: OneTiming, 23 | coordinateWidth: Int, 24 | ) 25 | 26 | class VGAOutBundle extends Bundle { 27 | val hsync = Output(Bool()) 28 | val vsync = Output(Bool()) 29 | val data = Output(new RGB4BitBundle()) 30 | } 31 | 32 | class VGAInfoBundle(coordinateWidth: Int) extends Bundle { 33 | val frameSignal = Output(Bool()) 34 | val lineSignal = Output(Bool()) 35 | val x = Output(SInt(coordinateWidth.W)) 36 | val y = Output(SInt(coordinateWidth.W)) 37 | } 38 | 39 | class VGATop(params: VGAParams) extends Module { 40 | val io = IO(new Bundle { 41 | val out = new VGAOutBundle() 42 | val info = new VGAInfoBundle(params.coordinateWidth) 43 | val in = Input(new RGB4BitBundle()) 44 | }) 45 | 46 | val timing = Module(new VGATiming(params)) 47 | io.out.hsync := timing.io.hsync 48 | io.out.vsync := timing.io.vsync 49 | io.out.data := Mux(timing.io.dataEnable, io.in, RGB4BitBundle.Black) 50 | 51 | io.info <> timing.io.info 52 | } 53 | 54 | class VGATiming(params: VGAParams) extends Module { 55 | val CoordinateType = SInt(params.coordinateWidth.W) 56 | 57 | val io = IO(new Bundle { 58 | val hsync = Output(Bool()) 59 | val vsync = Output(Bool()) 60 | val dataEnable = Output(Bool()) 61 | val info = new VGAInfoBundle(params.coordinateWidth) 62 | }) 63 | 64 | val x = RegInit(CoordinateType, params.horizontal.lineStart.S) 65 | val y = RegInit(CoordinateType, params.vertical.lineStart.S) 66 | val trueY = RegInit(CoordinateType, params.vertical.lineStart.S) // use trueY, so vsync will appear correctly 67 | 68 | when(x === -1.S) { // only when x is going to be 0, update trueY 69 | trueY := y 70 | } 71 | 72 | when(x === (params.horizontal.lineEnd - 1).S) { 73 | val frameEnd = y === (params.vertical.lineEnd - 1).S 74 | y := Mux(frameEnd, params.vertical.lineStart.S, y + 1.S) 75 | x := params.horizontal.lineStart.S 76 | }.otherwise { 77 | x := x + 1.S 78 | } 79 | 80 | io.hsync := RegNext(!(x >= params.horizontal.syncStart.S && x < params.horizontal.syncEnd.S)) 81 | io.vsync := RegNext(!(trueY >= params.vertical.syncStart.S && trueY < params.vertical.syncEnd.S)) 82 | io.dataEnable := RegNext(x >= params.horizontal.activeStart.S && y >= params.vertical.activeStart.S) 83 | io.info.frameSignal := RegNext(x === params.horizontal.lineStart.S && y === params.vertical.lineStart.S) 84 | io.info.lineSignal := RegNext(x === params.horizontal.lineStart.S) 85 | 86 | io.info.x := RegNext(x) 87 | io.info.y := RegNext(y) 88 | } 89 | -------------------------------------------------------------------------------- /chisel/src/test/scala/core/UARTSpec.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import chisel3._ 4 | import chiseltest._ 5 | import org.scalatest.flatspec.AnyFlatSpec 6 | 7 | class TestModule extends Module { 8 | val io = IO(new Bundle { 9 | val extIn = Input(UInt(8.W)) 10 | val extOut = Output(UInt(32.W)) 11 | 12 | val uartTx = Output(Bool()) 13 | val uartRx = Input(Bool()) 14 | }) 15 | 16 | val debug = IO(new Bundle { 17 | val pc = Output(UInt(32.W)) 18 | val invalid = Output(Bool()) 19 | val debugRegAddr = Input(UInt(5.W)) 20 | val debugRegData = Output(SInt(32.W)) 21 | }) 22 | 23 | // implicit val debugMode = true 24 | // val dut = Module(new Core()) 25 | // 26 | // dut.clocks.uart := clock 27 | // 28 | // io <> dut.io 29 | // debug <> dut.debug.get 30 | } 31 | 32 | class UARTSpec extends AnyFlatSpec with ChiselScalatestTester { 33 | behavior of "UART" 34 | 35 | val regNames = Array("x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6") 36 | 37 | def asUnsigned(x: Int) = (BigInt(x >>> 1) << 1) + (x & 1) 38 | 39 | it should "send and receive data via UART" in { 40 | test(new TestModule()).withAnnotations(Seq(WriteVcdAnnotation)) { implicit dut => 41 | fork { 42 | dut.clock.step(1) 43 | 44 | for (i <- 0 until 256) { 45 | val pc = dut.debug.pc.peek().litValue 46 | println(f"PC = 0x${pc}%x") 47 | // println(f"${i}%d, PC: 0x${pc}%x invalid flag: ${dut.debug.invalid.peek().litValue}") 48 | dut.clock.step(2) 49 | 50 | for (i <- 0 until 32) { 51 | dut.debug.debugRegAddr.poke(i.U) 52 | val value = asUnsigned(dut.debug.debugRegData.peek().litValue.toInt) 53 | val name = regNames(i) 54 | print(f"${name}%3s: ${value}%08x ") 55 | if ((i + 1) % 8 == 0) 56 | println() 57 | } 58 | 59 | val value = dut.io.extOut.peek().litValue 60 | println(f"val: ${value}%08x") 61 | 62 | // if (pc == 0xd0 || (pc & 0x3) > 0) 63 | // loop.break 64 | 65 | // for (i <- 0 until 8) { 66 | // val value = dut.io.externalOut(i).peek().litValue 67 | // print(f"${i}%d: ${value}%08x ") 68 | // } 69 | // println() 70 | println() 71 | } 72 | } .fork { 73 | def sendSignal(s: Boolean) = for (_ <- 0 until 8) { 74 | dut.io.uartRx.poke(s.B) 75 | dut.clock.step() 76 | } 77 | dut.io.uartRx.poke(true.B) 78 | dut.clock.step(12) 79 | 80 | val bits = Array(0, 1, 1, 0, 1, 0, 1, 1) 81 | 82 | sendSignal(false) // start 83 | for (bit <- bits) { 84 | sendSignal(bit > 0) 85 | } // bit 86 | sendSignal(true) // stop1 87 | sendSignal(true) // stop2 88 | 89 | val bits2 = Array(1, 0, 0, 1, 1, 1, 0, 1) 90 | sendSignal(false) // start 91 | for (bit <- bits2) { 92 | sendSignal(bit > 0) 93 | } // bit 94 | sendSignal(true) // stop1 95 | sendSignal(true) // stop2 96 | for (_ <- 0 until 512 / 8) 97 | sendSignal(true) 98 | } .fork { 99 | for (_ <- 0 until 732) { 100 | dut.clock.step() 101 | val value = dut.io.uartTx.peek().litValue 102 | println(f"==> UART val: ${value}%d") 103 | } 104 | } .join() 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/display/Console.scala: -------------------------------------------------------------------------------- 1 | package board.display 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.experimental.requireIsChiselType 6 | 7 | private object Top { 8 | val ColorPaletteScheme = DraculaPaletteModified 9 | } 10 | 11 | class ConsoleCharBundle extends Bundle { 12 | val color = UInt(4.W) 13 | val colorBg = UInt(4.W) 14 | val char = UInt(8.W) 15 | 16 | def pack: UInt = asUInt 17 | } 18 | 19 | object ConsoleCharBundle { 20 | def packedWidth: Int = 4 + 4 + 8 21 | // def asBundle(color: UInt, char: UInt): ConsoleCharBundle = { 22 | // val bundle = Wire(new ConsoleCharBundle) 23 | // bundle.color := color 24 | // bundle.char := char 25 | // bundle 26 | // } 27 | def unpack(data: UInt): ConsoleCharBundle = data.asTypeOf(new ConsoleCharBundle()) 28 | def pack(bundle: ConsoleCharBundle): UInt = bundle.pack 29 | } 30 | 31 | class Console(params: VGAParams) extends Module { 32 | private def wireOf[T <: Data](gen: T, value: T): T = { 33 | requireIsChiselType(gen, "wireof") 34 | val wire = Wire(gen) 35 | wire := value 36 | wire 37 | } 38 | 39 | val CoordinateType = SInt(params.coordinateWidth.W) 40 | val DELAY = 2 41 | val CONSOLE_CHAR_WIDTH = 8 42 | val CONSOLE_CHAR_HEIGHT = 16 43 | val CHAR_COLS = params.horizontal.visibleArea / CONSOLE_CHAR_WIDTH 44 | val CHAR_ROWS = params.vertical.visibleArea / CONSOLE_CHAR_HEIGHT 45 | 46 | require(CHAR_COLS < 256) // 8 bits 47 | require(CHAR_ROWS < 64) // 6 bits 48 | 49 | val io = IO(new Bundle { 50 | val info = Flipped(new VGAInfoBundle(params.coordinateWidth)) 51 | 52 | val charRamAddr = Output(UInt(14.W)) 53 | val charRamData = Input(UInt(ConsoleCharBundle.packedWidth.W)) 54 | 55 | val fontRomAddr = Output(UInt(12.W)) 56 | val fontRomData = Input(UInt(8.W)) 57 | 58 | val out = Output(new RGB4BitBundle()) 59 | }) 60 | 61 | val paletteFg = Module(new ColorPalette()) 62 | val paletteBg = Module(new ColorPalette()) 63 | 64 | val x = io.info.x + DELAY.S 65 | 66 | // 1 cycle delay: read character from buffer (RAM) 67 | val charX = wireOf(UInt(8.W), (x >> 3).asUInt) 68 | val charY = wireOf(UInt(6.W), (io.info.y >> 4).asUInt) 69 | io.charRamAddr := Cat(charY, charX) // get the char should display in (x, y) 70 | val charData = ConsoleCharBundle.unpack(io.charRamData) 71 | paletteFg.io.idx := charData.color 72 | paletteBg.io.idx := charData.colorBg 73 | 74 | // 1 cycle delay: read font data from ROM 75 | val charLine = io.info.y(3, 0) 76 | io.fontRomAddr := Cat(charData.char, charLine) 77 | 78 | val pixelEnable = io.fontRomData(io.info.x(2, 0)) 79 | io.out :<= Mux(pixelEnable, paletteFg.io.out, paletteBg.io.out) 80 | } 81 | 82 | object ConsoleCharState extends ChiselEnum { 83 | val Idle = Value 84 | } 85 | 86 | class ColorPalette extends Module { 87 | val io = IO(new Bundle { 88 | val idx = Input(UInt(4.W)) 89 | val out = Output(new RGB4BitBundle()) 90 | }) 91 | 92 | val table = Seq( 93 | 0x0 -> Top.ColorPaletteScheme.Black, 94 | 0x1 -> Top.ColorPaletteScheme.Red, 95 | 0x2 -> Top.ColorPaletteScheme.Green, 96 | 0x3 -> Top.ColorPaletteScheme.Yellow, 97 | 0x4 -> Top.ColorPaletteScheme.Blue, 98 | 0x5 -> Top.ColorPaletteScheme.Magenta, 99 | 0x6 -> Top.ColorPaletteScheme.Cyan, 100 | 0x7 -> Top.ColorPaletteScheme.White, 101 | 0x8 -> Top.ColorPaletteScheme.BrightBlack, 102 | 0x9 -> Top.ColorPaletteScheme.BrightRed, 103 | 0xA -> Top.ColorPaletteScheme.BrightGreen, 104 | 0xB -> Top.ColorPaletteScheme.BrightYellow, 105 | 0xC -> Top.ColorPaletteScheme.BrightBlue, 106 | 0xD -> Top.ColorPaletteScheme.BrightMagenta, 107 | 0xE -> Top.ColorPaletteScheme.BrightCyan, 108 | 0xF -> Top.ColorPaletteScheme.BrightWhite, 109 | ).map(o => o._1.U(io.idx.getWidth.W) -> o._2.asChiselBundle) 110 | 111 | io.out := MuxLookup(io.idx, table.head._2)(table) 112 | } 113 | -------------------------------------------------------------------------------- /program/src/bin/tubeshow.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::time::Duration; 5 | 6 | #[macro_use] 7 | extern crate cpu_lib; 8 | 9 | use cpu_lib::prelude::*; 10 | 11 | fn set_tube(d: &[Option; 8]) { 12 | println!("{:?}", d); 13 | let value = d 14 | .iter() 15 | .rev() 16 | .fold(0u32, |v, o| (v << 4) | o.unwrap_or(0) as u32); 17 | let mask = d 18 | .iter() 19 | .rev() 20 | .fold(0u8, |v, o| (v << 1) | o.is_some() as u8); 21 | set_tube_value(value); 22 | set_tube_enable(mask); 23 | 24 | sleep(Duration::from_millis(200)); 25 | } 26 | 27 | #[no_mangle] 28 | fn main() -> i32 { 29 | set_tube_mode(TubeMode::Hex); 30 | 31 | let mut value = [None, None, None, None, None, None, None, None]; 32 | 33 | for i in 1..=8 { 34 | value[8 - i] = Some(i as u8); 35 | set_tube(&value); 36 | } 37 | for i in 0..8 { 38 | value[i] = None; 39 | set_tube(&value); 40 | } 41 | 42 | for i in 1..=8 { 43 | value[i - 1] = Some(i as u8); 44 | set_tube(&value); 45 | } 46 | for i in 0..8 { 47 | value[7 - i] = None; 48 | set_tube(&value); 49 | } 50 | 51 | for i in 1..=8 { 52 | value[8 - i] = Some(i as u8); 53 | set_tube(&value); 54 | value[8 - i] = None; 55 | } 56 | for i in 0..8 { 57 | value[i] = Some(8 - i as u8); 58 | set_tube(&value); 59 | value[i] = None; 60 | } 61 | 62 | for i in 1..=8 { 63 | value[i - 1] = Some(i as u8); 64 | set_tube(&value); 65 | value[i - 1] = None; 66 | } 67 | for i in 0..8 { 68 | value[7 - i] = Some(8 - i as u8); 69 | set_tube(&value); 70 | value[7 - i] = None; 71 | } 72 | 73 | let templ_1 = [ 74 | None, 75 | Some(1), 76 | Some(1), 77 | Some(4), 78 | Some(5), 79 | Some(1), 80 | Some(4), 81 | None, 82 | ]; 83 | let templ_2 = [ 84 | Some(1), 85 | Some(9), 86 | Some(1), 87 | Some(9), 88 | Some(8), 89 | Some(1), 90 | Some(0), 91 | None, 92 | ]; 93 | let templ_3 = [ 94 | Some(1), 95 | Some(9), 96 | Some(2), 97 | Some(6), 98 | Some(0), 99 | Some(8), 100 | Some(1), 101 | Some(7), 102 | ]; 103 | 104 | for _ in 0..8 { 105 | templ_1 106 | .iter() 107 | .rev() 108 | .enumerate() 109 | .map(|(i, v)| if i % 2 == 0 { v } else { &None }) 110 | .zip(value.iter_mut()) 111 | .for_each(|(t, v)| *v = *t); 112 | set_tube(&value); 113 | templ_1 114 | .iter() 115 | .rev() 116 | .enumerate() 117 | .map(|(i, v)| if i % 2 != 0 { v } else { &None }) 118 | .zip(value.iter_mut()) 119 | .for_each(|(t, v)| *v = *t); 120 | set_tube(&value); 121 | } 122 | 123 | for _ in 0..8 { 124 | templ_2 125 | .iter() 126 | .rev() 127 | .enumerate() 128 | .map(|(i, v)| if i < 4 { v } else { &None }) 129 | .zip(value.iter_mut()) 130 | .for_each(|(t, v)| *v = *t); 131 | set_tube(&value); 132 | templ_2 133 | .iter() 134 | .rev() 135 | .enumerate() 136 | .map(|(i, v)| if i >= 4 { v } else { &None }) 137 | .zip(value.iter_mut()) 138 | .for_each(|(t, v)| *v = *t); 139 | set_tube(&value); 140 | } 141 | 142 | for _ in 0..24 { 143 | let idx = (random_value() % 8) as usize; 144 | value[idx] = templ_3[7 - idx]; 145 | set_tube(&value); 146 | value.iter_mut().for_each(|v| *v = None); 147 | // set_tube(&value); 148 | } 149 | set_tube(&value); 150 | 151 | 0 152 | } 153 | -------------------------------------------------------------------------------- /program/src/bin/task2.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::time::Duration; 5 | 6 | #[macro_use] 7 | extern crate cpu_lib; 8 | 9 | use cpu_lib::prelude::*; 10 | 11 | /* 12 | fn read_number() -> u32 { 13 | let mut v = 0; 14 | let mut en = 0; 15 | 16 | while keyboard_ready() { 17 | read_keyboard(); 18 | } 19 | 20 | loop { 21 | while !keyboard_ready() { 22 | if read_button(Button::Center) { 23 | while read_button(Button::Center) {} 24 | return v; 25 | } 26 | } 27 | 28 | en = en << 1 | 1; 29 | let key = read_keyboard().as_number().unwrap(); 30 | v = v * 10 + key; 31 | set_tube_value_option(Some(v)); 32 | set_tube_enable(en); 33 | } 34 | } 35 | */ 36 | 37 | fn read_number() -> u8 { 38 | while !read_button(Button::Center) {} 39 | 40 | let mut v = 0; 41 | for i in 0..8 { 42 | v = v << 1 | (read_switch(7 - i) as u8); 43 | } 44 | set_led_number(v); 45 | 46 | while read_button(Button::Center) {} 47 | 48 | v 49 | } 50 | 51 | fn set_led_number(v: u8) { 52 | for i in 0..8 { 53 | set_led(i, (v & (1 << i)) > 0); 54 | } 55 | } 56 | 57 | fn accumulate(v: u8, t: u8) -> u8 { 58 | if t == 1 { 59 | set_tube_value_option(Some(v as u32)); 60 | sleep(Duration::from_secs(1)); 61 | } 62 | 63 | match v { 64 | 0 => 0, 65 | _ => { 66 | let w = accumulate(v - 1, t) + v; 67 | if t == 2 { 68 | set_tube_value_option(Some(v as u32)); 69 | sleep(Duration::from_secs(1)); 70 | } 71 | w 72 | } 73 | } 74 | } 75 | 76 | fn task_accumulative(b: u8) { 77 | let v1 = read_number(); 78 | if (v1 as i8) < 0 { 79 | loop { 80 | set_led_number(v1); 81 | sleep(Duration::from_millis(500)); 82 | set_led_number(0); 83 | sleep(Duration::from_millis(500)); 84 | } 85 | } 86 | let w = accumulate(v1, b - 1); 87 | if b == 0 { 88 | println!("{}", w); 89 | set_tube_value_option(Some(w as u32)); 90 | } else if b == 1 { 91 | set_tube_value_option(Some((v1 * 2) as u32)); 92 | } 93 | } 94 | 95 | fn task_arithmetic(b: u8) { 96 | let v1 = read_number() as i8; 97 | let v2 = read_number() as i8; 98 | 99 | match b { 100 | 0b100 => { 101 | let (r, o) = v1.overflowing_add(v2); 102 | set_led_number(r as u8); 103 | set_led(11, o); 104 | } 105 | 0b101 => { 106 | let (r, o) = v1.overflowing_sub(v2); 107 | set_led_number(r as u8); 108 | set_led(11, o); 109 | } 110 | 0b110 => { 111 | let r = ((v1 as i16) * (v2 as i16)) as u16; 112 | for i in 0..16 { 113 | set_led(i, (r & (1 << i)) > 0); 114 | } 115 | } 116 | 0b111 => { 117 | let q = v1 / v2; 118 | let r = v1 % v2; 119 | loop { 120 | set_led_number(q as u8); 121 | sleep(Duration::from_secs(5)); 122 | set_led_number(r as u8); 123 | sleep(Duration::from_secs(5)); 124 | } 125 | } 126 | _ => {} 127 | } 128 | } 129 | 130 | #[no_mangle] 131 | fn main() -> i32 { 132 | loop { 133 | println!("new task!"); 134 | 135 | while !read_button(Button::Center) {} 136 | 137 | let b: u8 = 138 | read_switch(16) as u8 | ((read_switch(17) as u8) << 1) | ((read_switch(18) as u8) << 2); 139 | (0..8).for_each(|x| set_led(x + 16, false)); 140 | set_led(16 + b as usize, true); 141 | println!("b = {}", b); 142 | 143 | while read_button(Button::Center) {} 144 | 145 | if b < 4 { 146 | task_accumulative(b); 147 | } else { 148 | task_arithmetic(b); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /program/src/bin/tetris/tetrs.rs: -------------------------------------------------------------------------------- 1 | use cpu_lib::console::set_screen_print; 2 | use cpu_lib::monitor::monitor::clear_screen; 3 | 4 | use crate::{ 5 | game::{ 6 | cycle::GameLoop, 7 | logic::{End, Logic}, 8 | }, 9 | ui::Ui, 10 | }; 11 | 12 | pub struct Tetrs; 13 | 14 | impl Tetrs { 15 | pub fn new() -> Tetrs { 16 | Tetrs 17 | } 18 | 19 | pub fn run(&self) -> End { 20 | clear_screen(); 21 | 22 | // println!("Note that the behavior of \\xXX on byte-string literals matches the expectations established by the C program in Behavior of xXX in C; that is good. The problem is the behavior of \\xXX for XX > 0x7F in string-literal contexts, namely in the fourth and fifth examples where the .as_bytes() invocations are showing that the underlying byte array has two elements instead of one."); 23 | // println!("Currently, we allow any traits to be used for trait objects, but restrict the methods which can be called on such objects. Here, we propose instead restricting which traits can be used to make objects. Despite being less flexible, this will make for better error messages, less surprising software evolution, and (hopefully) better design. The motivation for the proposed change is stronger due to part of the DST changes."); 24 | // println!("Software evolution is improved with this proposal: imagine adding a non-object-safe method to a previously object-safe trait. With this proposal, you would then get errors wherever a trait-object is created. The error would explain why the trait object could not be created and point out exactly which method was to blame and why. Without this proposal, the only errors you would get would be where a trait object is used with a generic call and would be something like \"type error: SomeTrait does not implement SomeTrait\" - no indication that the non-object-safe method were to blame, only a failure in trait matching."); 25 | // println!("Note that a trait can be object-safe even if some of its methods use features that are not supported with an object receiver. This is true when code that attempted to use those features would only work if the Self type is Sized. This is why all methods that require Self:Sized are exempt from the typical rules. This is also why by-value self methods are permitted, since currently one cannot invoke pass an unsized type by-value (though we consider that a useful future extension)."); 26 | // println!("The problem is that currently, there is no clear/consistent guideline about which of these APIs should live as methods/static functions associated with a type, and which should live in a raw submodule. Both forms appear throughout the standard library."); 27 | // println!("In addition, in the future box patterns are expected to be made more general by enabling them to destructure any type that implements one of the Deref family of traits. As such a generalisation may potentially lead to some currently valid programs being rejected due to the interaction with type inference or other language features, it is desirable that this particular feature stays feature gated until then."); 28 | // println!("This syntax simply removes the implicit Sized bound on every type parameter using the ? symbol. It resolves the problem about not mentioning Sized that the first two syntaxes didn’t. It also hints towards being related to sizedness, resolving the problem that plagued type. It also successfully states that unsizedness is only optional—that the parameter may be sized or unsized. This syntax has stuck, and is the syntax used today. Additionally, it could potentially be extended to other traits: for example, a new pointer type that cannot be dropped, &uninit, could be added, requiring that it be written to before being dropped. However, many generic functions assume that any parameter passed to them can be dropped. Drop could be made a default bound to resolve this, and Drop? would remove this bound from a type parameter."); 29 | 30 | // loop {} 31 | 32 | set_screen_print(false); 33 | 34 | let result = GameLoop::new(Logic::new(), Ui::default()).run(); 35 | 36 | set_screen_print(true); 37 | result 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | codecov: codecov/codecov@3.2.3 5 | 6 | jobs: 7 | build: 8 | docker: 9 | - image: rust:latest 10 | steps: 11 | - checkout 12 | - run: 13 | name: Build the source 14 | command: cargo build 15 | 16 | test: 17 | docker: 18 | - image: rust:latest 19 | steps: 20 | - checkout 21 | - run: 22 | name: Run the tests 23 | command: cargo test 24 | 25 | miri: 26 | parameters: 27 | target: 28 | type: string 29 | docker: 30 | - image: jfrimmel/miri:nightly-2022-08-22 31 | steps: 32 | - checkout 33 | - run: 34 | name: Run the tests 35 | command: MIRIFLAGS='-Zmiri-symbolic-alignment-check' cargo miri test --target << parameters.target >> --lib 36 | 37 | coverage: 38 | docker: 39 | - image: jfrimmel/coverage 40 | steps: 41 | - checkout 42 | - run: 43 | name: Record testing coverage 44 | command: | 45 | # build and run all tests. This produces a single .profraw-file per 46 | # test. 47 | RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="emballoc-%m.profraw" cargo test 48 | # merge the individual runs into a collective .profdata-file 49 | llvm-profdata merge -sparse emballoc-*.profraw -o emballoc.profdata 50 | 51 | # collect the names of the binaries and convert them to command line 52 | # parameters. This is adopted from https://doc.rust-lang.org/rustc/instrument-coverage.html#tips-for-listing-the-binaries-automatically 53 | binaries=($(RUSTFLAGS="-C instrument-coverage" cargo test --tests --quiet --no-run --message-format=json | jq -r "select(.profile.test == true) | .filenames[]" | grep -v dSYM -)) 54 | binaries=("${binaries[@]/#/-object=}") 55 | 56 | # Show the precise coverage, so that it shows up in the CI logs and 57 | # convert it into an `lcov` file, so that it can be uploaded (this 58 | # is one of the few supported format according to 59 | # https://stackoverflow.com/a/50884416). 60 | llvm-cov report --ignore-filename-regex='/usr/local/cargo/registry' --instr-profile=emballoc.profdata "${binaries[@]}" --use-color 61 | llvm-cov export --ignore-filename-regex='/usr/local/cargo/registry' --instr-profile=emballoc.profdata "${binaries[@]}" -format=lcov > coverage.lcov 62 | - codecov/upload 63 | 64 | msrv: 65 | docker: 66 | - image: rust:1.57 67 | steps: 68 | - checkout 69 | - run: 70 | name: Build the source 71 | command: cargo check 72 | 73 | style: 74 | docker: 75 | - image: rust:latest 76 | steps: 77 | - checkout 78 | - run: 79 | name: Install linter and formatter 80 | command: rustup component add rustfmt clippy 81 | - run: 82 | name: Check formatting 83 | command: cargo fmt --check 84 | - run: 85 | name: Run linter 86 | command: | 87 | cargo clippy -- \ 88 | -D clippy::cargo \ 89 | -D clippy::complexity \ 90 | -D clippy::nursery \ 91 | -D clippy::pedantic \ 92 | -D clippy::perf \ 93 | -D clippy::style \ 94 | -D clippy::suspicious \ 95 | -F clippy::dbg_macro \ 96 | -F clippy::print_stdout \ 97 | -F clippy::print_stderr \ 98 | -F clippy::todo \ 99 | -F clippy::unimplemented \ 100 | -D clippy::undocumented_unsafe_blocks 101 | 102 | doc: 103 | docker: 104 | - image: rust:latest 105 | steps: 106 | - checkout 107 | - run: 108 | name: Build the documentation 109 | command: cargo doc 110 | 111 | workflows: 112 | ci: 113 | jobs: 114 | - build 115 | - test: 116 | requires: [build] 117 | - miri: 118 | requires: [build] 119 | matrix: 120 | parameters: 121 | target: 122 | ["x86_64-unknown-linux-gnu", "mips64-unknown-linux-gnuabi64"] 123 | - coverage: 124 | requires: [build] 125 | - msrv 126 | - style 127 | - doc 128 | -------------------------------------------------------------------------------- /program/src/monitor.rs: -------------------------------------------------------------------------------- 1 | const DATA_BASEADDR: *mut u32 = 0xFFFD0000 as *mut u32; 2 | const COLOR_BASEADDR: *mut u32 = 0xFFFE0000 as *mut u32; 3 | 4 | pub const SCREEN_BUFFER_MULTIPLIER: usize = 256; 5 | pub const SCREEN_WIDTH: usize = 800 / 8; 6 | pub const SCREEN_HEIGHT: usize = 600 / 16; 7 | 8 | #[derive(Debug, Clone, Copy, PartialEq)] 9 | pub enum Color { 10 | Black = 0x0, 11 | Red = 0x1, 12 | Green = 0x2, 13 | Yellow = 0x3, 14 | Blue = 0x4, 15 | Magenta = 0x5, 16 | Cyan = 0x6, 17 | White = 0x7, 18 | BrightBlack = 0x8, 19 | BrightRed = 0x9, 20 | BrightGreen = 0xA, 21 | BrightYellow = 0xB, 22 | BrightBlue = 0xC, 23 | BrightMagenta = 0xD, 24 | BrightCyan = 0xE, 25 | BrightWhite = 0xF, 26 | } 27 | 28 | impl Color { 29 | pub fn default_fg() -> Color { 30 | Color::White 31 | } 32 | pub fn default_bg() -> Color { 33 | Color::Black 34 | } 35 | } 36 | 37 | pub fn init() { 38 | monitor::set_color(0x07); 39 | } 40 | 41 | #[inline] 42 | fn offset(x: usize, y: usize) -> usize { 43 | // assert!(x < SCREEN_BUFFER_MULTIPLIER && y < 64); 44 | y * SCREEN_BUFFER_MULTIPLIER + x 45 | } 46 | 47 | pub fn set_character(x: usize, y: usize, ch: u8) { 48 | unsafe { DATA_BASEADDR.add(offset(x, y)).write_volatile(ch as u32) } 49 | } 50 | 51 | pub fn get_character(x: usize, y: usize) -> u8 { 52 | unsafe { DATA_BASEADDR.add(offset(x, y)).read_volatile() as u8 } 53 | } 54 | 55 | pub fn set_color(x: usize, y: usize, ch: u8) { 56 | unsafe { COLOR_BASEADDR.add(offset(x, y)).write_volatile(ch as u32) } 57 | } 58 | 59 | pub fn get_color(x: usize, y: usize) -> u8 { 60 | unsafe { COLOR_BASEADDR.add(offset(x, y)).read_volatile() as u8 } 61 | } 62 | 63 | static mut SCREEN_X: usize = 0; 64 | static mut SCREEN_Y: usize = 0; 65 | static mut CURRENT_COLOR: u8 = 0; 66 | 67 | pub mod monitor { 68 | use super::*; 69 | 70 | #[inline] 71 | pub fn get_x() -> usize { 72 | unsafe { SCREEN_X } 73 | } 74 | 75 | #[inline] 76 | pub fn get_y() -> usize { 77 | unsafe { SCREEN_Y } 78 | } 79 | 80 | #[inline] 81 | pub fn set_x(x: usize) { 82 | unsafe { SCREEN_X = x } 83 | } 84 | 85 | #[inline] 86 | pub fn set_y(y: usize) { 87 | unsafe { SCREEN_Y = y } 88 | } 89 | 90 | #[inline] 91 | pub fn set_xy(x: usize, y: usize) { 92 | unsafe { 93 | SCREEN_X = x; 94 | SCREEN_Y = y; 95 | } 96 | } 97 | 98 | #[inline] 99 | pub fn get_color() -> u8 { 100 | unsafe { CURRENT_COLOR } 101 | } 102 | 103 | #[inline] 104 | pub fn set_color(color: u8) { 105 | unsafe { CURRENT_COLOR = color } 106 | } 107 | 108 | pub fn clear_screen() { 109 | let color = get_color(); 110 | for y in 0..SCREEN_HEIGHT { 111 | for x in 0..SCREEN_WIDTH { 112 | set_character(x, y, b' '); 113 | super::set_color(x, y, color); 114 | } 115 | } 116 | set_xy(0, 0); 117 | } 118 | 119 | pub fn scroll_down() { 120 | for y in 0..SCREEN_HEIGHT - 1 { 121 | for x in 0..SCREEN_WIDTH { 122 | set_character(x, y, get_character(x, y + 1)); 123 | super::set_color(x, y, super::get_color(x, y + 1)); 124 | } 125 | } 126 | for x in 0..SCREEN_WIDTH { 127 | set_character(x, SCREEN_HEIGHT - 1, b' '); 128 | } 129 | } 130 | 131 | pub fn newline() { 132 | let y = get_y(); 133 | if y + 1 == SCREEN_HEIGHT { 134 | scroll_down(); 135 | set_x(0); 136 | } else { 137 | set_xy(0, y + 1); 138 | } 139 | } 140 | 141 | pub fn move_cursor_next() { 142 | let x = get_x(); 143 | if x + 1 == SCREEN_WIDTH { 144 | newline(); 145 | } else { 146 | set_x(x + 1); 147 | } 148 | } 149 | 150 | #[allow(irrefutable_let_patterns)] 151 | pub fn putchar(ch: u8) { 152 | match ch { 153 | b'\r' => set_x(0), 154 | b'\n' => newline(), 155 | b'\x7f' => if let x = get_x() && x > 0 { set_x(x - 1) }, 156 | ch => { 157 | let x = get_x(); 158 | let y = get_y(); 159 | set_character(x, y, ch); 160 | super::set_color(x, y, get_color()); 161 | move_cursor_next(); 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/UART.scala: -------------------------------------------------------------------------------- 1 | package board 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class UARTPair extends Bundle { 7 | val tx = Output(Bool()) 8 | val rx = Input(Bool()) 9 | } 10 | 11 | class UART(dataBits: Int, oversampleLog: Int) extends Module { 12 | val io = IO(new Bundle { 13 | val pair = new UARTPair() 14 | 15 | val dataIn = Flipped(Decoupled(UInt(dataBits.W))) 16 | val dataOut = Decoupled(UInt(dataBits.W)) 17 | }) 18 | 19 | val tx = Module(new UARTTransmitter(dataBits)) 20 | val rx = Module(new UARTReceiver(dataBits, oversampleLog)) 21 | 22 | rx.rx := io.pair.rx 23 | rx.io <> io.dataOut 24 | rx.io.ready := DontCare 25 | tx.io <> io.dataIn 26 | io.pair.tx := tx.tx 27 | 28 | // transmitter doesn't not need oversample, so we need to slow down its clock (by ticking) 29 | val clkCnt = RegInit(0.U(oversampleLog.W)) 30 | clkCnt := clkCnt + 1.U 31 | tx.tick := clkCnt.andR 32 | } 33 | 34 | class UARTTransmitter(dataBits: Int) extends Module { 35 | val io = IO(Flipped(Decoupled(UInt(dataBits.W)))) 36 | val tx = IO(Output(Bool())) 37 | val tick = IO(Input(Bool())) 38 | 39 | val state = RegInit(UARTState.Idle) 40 | val data = Reg(UInt(dataBits.W)) 41 | val idle = state === UARTState.Idle 42 | 43 | when (tick) { 44 | val idleNext = Mux(io.valid, UARTState.Start, UARTState.Idle) 45 | val nextState = MuxLookup(state, idleNext)(UARTState.nextTable()) 46 | state := nextState 47 | 48 | data := Mux(state === UARTState.Start && io.valid, io.bits, data >> 1) 49 | } 50 | 51 | val onBit = state.asUInt >= 4.U // is sending a bit (compared to Start, Stop1, and Stop2) 52 | // if `onBit`, send bit (from LSB), otherwise send control signal 53 | tx := Mux(onBit, data(0), Mux(state === UARTState.Start, 0.B, 1.B)) 54 | 55 | // to tell whether the data is sent, used for popping the head data from the queue 56 | io.ready := tick && state === UARTState.Start 57 | } 58 | 59 | class UARTReceiver(dataBits: Int, oversampleLog: Int) extends Module { 60 | val io = IO(Decoupled(UInt(dataBits.W))) 61 | val rx = IO(Input(Bool())) 62 | 63 | val initialCnt = (1 << (oversampleLog - 1)) - 2 64 | val cnt = RegInit(initialCnt.U((oversampleLog - 1).W)) 65 | 66 | val sync = ShiftRegister(rx, 2) 67 | val bit = RegInit(true.B) 68 | 69 | when (sync && !cnt.andR) { 70 | cnt := cnt + 1.U 71 | } .elsewhen (!sync && cnt =/= 0.U) { 72 | cnt := cnt - 1.U 73 | } 74 | 75 | // take the majority bits as the final bit 76 | when (cnt.andR) { bit := 1.U } 77 | .elsewhen (cnt === 0.U) { bit := 0.U } 78 | 79 | // -------------| START |-------------- 80 | // IDLE |---------------| BIT0 81 | // spacing: 0000000123456789ABCDEF0123 82 | // cnt: 333321000..........012333..... 83 | // bit: 111111000......000..00111..... 84 | // ^ ^ 85 | // | we take the final bit here. If we take it in spacing=F, there will be more errors 86 | // cnt to 0, spacing starts 87 | 88 | val spacing = RegInit(0.U(oversampleLog.W)) 89 | val tick = spacing === ((1 << oversampleLog) - oversampleLog * 3 / 2).U // tell should we take the bit 90 | 91 | val state = RegInit(UARTState.Idle) 92 | val isIdle = state === UARTState.Idle 93 | 94 | when (isIdle) { 95 | state := Mux(!bit, UARTState.Start, UARTState.Idle) 96 | } .otherwise { 97 | state := Mux(spacing.andR, MuxLookup(state, UARTState.Idle)(UARTState.nextTable()), state) 98 | } 99 | 100 | spacing := Mux(isIdle, 0.U, spacing + 1.U) 101 | 102 | val data = ShiftRegisters(bit, 8, tick) // when `tick`, take the bit as LSB, and shift left 103 | io.bits := Cat(data).asUInt 104 | 105 | // only valid for 1 cycles when the data is ready, tell the queue to push 106 | io.valid := false.B 107 | when (state === UARTState.Stop1 && tick) { 108 | io.valid := true.B 109 | } 110 | } 111 | 112 | // Idle -> Start -> Bit0 -> Bit1 -> ... -> Bit7 -> Stop1 -> Idle(Stop2) -> Start -> Bit0 113 | // note that, when sending continuously, Idle is equivalent to Stop2 114 | object UARTState extends ChiselEnum { 115 | val Idle = Value(0.U) 116 | val Start = Value(1.U) 117 | val Stop1 = Value(2.U) 118 | val Stop2 = Value(3.U) // emit 119 | val Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7 = Value 120 | // 4 5 6 7 8 9 A B 121 | 122 | def nextTable(): Seq[(Type, Type)] = Array( 123 | Start -> Bit0, 124 | Bit0 -> Bit1, 125 | Bit1 -> Bit2, 126 | Bit2 -> Bit3, 127 | Bit3 -> Bit4, 128 | Bit4 -> Bit5, 129 | Bit5 -> Bit6, 130 | Bit6 -> Bit7, 131 | Bit7 -> Stop1, 132 | Stop1 -> Idle, 133 | ) 134 | } 135 | -------------------------------------------------------------------------------- /font/LICENSE-OFL: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, TakWolf (https://takwolf.com), 2 | with Reserved Font Name "Ark Pixel". 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /program/3rd_party/emballoc/README.md: -------------------------------------------------------------------------------- 1 | # `emballoc` — Embedded Memory Allocator 2 | 3 | [![crates.io](https://img.shields.io/crates/v/emballoc)](https://crates.io/crates/emballoc) 4 | [![circleci](https://img.shields.io/circleci/build/github/jfrimmel/emballoc)](https://app.circleci.com/pipelines/github/jfrimmel/emballoc) 5 | [![codecov](https://codecov.io/gh/jfrimmel/emballoc/branch/main/graph/badge.svg?token=XU4EG0HGRP)](https://codecov.io/gh/jfrimmel/emballoc) 6 | [![docs.rs](https://img.shields.io/docsrs/emballoc)](https://docs.rs/emballoc) 7 | 8 | This repository provides the [`emballoc`](https://crates.io/crates/emballoc) crate: a simple memory allocator developed for usage in small embedded systems. 9 | It is one possible way to support dynamic memory on targets without the standard library, i.e. ones with `#![no_std]`. 10 | This is achieved by providing a type [`Allocation`](https://docs.rs/emballoc/*/emballoc/struct.Allocator.html) which can be registered as the global allocator for the binary. 11 | See the usage description below. 12 | 13 | An allocator is a rather critical part of a software project: 14 | when using dynamic memory many operations implicitly can or will allocate, sometimes unexpectedly. 15 | Therefore a misbehaving allocator can "randomly" crash the program in very obscure ways. 16 | As such an allocator has to be well-tested and battle-proven (see more information [here][docu-testing] and a [real world example][gist_hosted-test]). 17 | Furthermore it has to be _simple_: the simpler the algorithm is, the more likely is a correct implementation. 18 | 19 | Refer to the [crate-documentation](https://docs.rs/emballoc/) for details on the algorithm and usage hints. 20 | 21 | # Usage 22 | 23 | Copy the following snippet to your `Cargo.toml` to pull the crate in as one of your dependencies. 24 | 25 | ```toml 26 | [dependencies.emballoc] 27 | version = "*" # replace with current version from crates.io 28 | ``` 29 | 30 | After that the usage is very simple: just copy the following code to the binary crate of the project. 31 | Substitute the `4096` with the desired heap size in bytes. 32 | 33 | ```rust 34 | #[global_allocator] 35 | static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new(); 36 | 37 | extern crate alloc; 38 | ``` 39 | 40 | Now the crate can use the `std` collections such as `Vec`, `BTreeMap`, etc. together with important types like `Box` and `Rc`. 41 | Note, that things in the `std`-prelude (e.g. `Vec`, `Box`, ...) have to be imported explicitly. 42 | 43 | # Why choosing this crate 44 | 45 | This crate started as part of an embedded project, but was extracted to make it usable in other projects and for other users. 46 | This sections answers the question: 47 | 48 | > Why should you consider using this crate in your project? 49 | 50 | - the core algorithm is _simple_ and thus implementation errors are less likely 51 | - rigorous testing is done (see [here][docu-testing]) 52 | - crate is free of undefined behavior according to `miri` 53 | - statically determined heap size preventing growing the heap into the stack 54 | - it is used in real-world applications 55 | - it even works on a PC (see [here][gist_hosted-test]), although that is not the primary use case 56 | - supports the stable compiler as there are only stable features used 57 | - has only a single dependency on the popular `spin`-crate (without any transitive dependencies) 58 | 59 | I'm glad, if that convinced you, but if you have any questions simply [open an issue](https://github.com/jfrimmel/emballoc/issues/new/choose). 60 | 61 | A note to users on systems with advanced memory features like MMUs and MPUs: 62 | 63 | - if you have an _memory protection unit_ (MPU) or similar available, you have to configure it yourself as this crate is platform-agnostic. 64 | An example usage might be to configure it, that reading from and writing to the heap is allowed, but execution is not. 65 | It is not possible to surround the heap with guard pages, as this allocator will never read/write outside of the internal byte array. 66 | However it might be advised to guard the stack, so that it doesn't grow into the heap (or any other variable). 67 | - if you have an (active) _memory management unit_ (MMU), this is likely not the crate for you: it doesn't use any of the important features, which makes it perform much worse than possible. 68 | Use a proper memory allocator for that use case (one that supports paging, etc.). 69 | However, if you need dynamic memory before enabling the MMU, this crate certainly is an option. 70 | 71 | # Minimum supported Rust version 72 | 73 | This crate has a stability guarantee about the compiler version supported. 74 | The so-called minimum supported Rust version is currently set to **1.57** and won't be raised without a proper increase in the semantic version number scheme. 75 | This MSRV is specified in `Cargo.toml` and is tested in CI. 76 | 77 | # License 78 | 79 | Licensed under either of 80 | 81 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) 82 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) 83 | 84 | at your option. 85 | 86 | [docu-testing]: https://docs.rs/emballoc/latest/emballoc/#testing 87 | [gist_hosted-test]: https://gist.github.com/jfrimmel/61943f9879adfbe760a78efa17a0ecaa 88 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/Board.scala: -------------------------------------------------------------------------------- 1 | package board 2 | 3 | import board.display._ 4 | import misc._ 5 | import util.GenerateOptions 6 | import chisel3._ 7 | import chisel3.util._ 8 | import ip._ 9 | 10 | class BoardDataRegableBundle extends Bundle { 11 | val tubes = new TubesInputBundle() 12 | val leds = Vec(24, Bool()) 13 | } 14 | 15 | class ButtonGroupBundle extends Bundle { 16 | val up = Input(Bool()) 17 | val down = Input(Bool()) 18 | val left = Input(Bool()) 19 | val right = Input(Bool()) 20 | val center = Input(Bool()) 21 | } 22 | 23 | class BoardDataBundle extends Bundle { 24 | val uartOut = Flipped(Decoupled(UInt(8.W))) 25 | val uartIn = Decoupled(UInt(8.W)) 26 | val cycles = Output(UInt(32.W)) 27 | val regable = Input(new BoardDataRegableBundle()) 28 | val switches = Output(Vec(24, Bool())) 29 | val buttons = Flipped(new ButtonGroupBundle()) 30 | val keyboard = Decoupled(KeyboardButton()) 31 | val vgaDataPort = new MemoryPort(14, 16) 32 | val originPC = Output(UInt(32.W)) 33 | } 34 | 35 | class RealBoardDataBundle extends Bundle { 36 | val uart = new UARTPair() 37 | val tubes = new TubesGroupBundle() 38 | val vga = new VGAOutBundle() 39 | val switches = Input(Vec(24, Bool())) 40 | val buttons = new ButtonGroupBundle() 41 | val keyboard = new KeyboardInBundle() 42 | val leds = Output(Vec(24, Bool())) 43 | val interrupt = Input(Bool()) 44 | } 45 | 46 | class BoardDataController(implicit options: GenerateOptions) extends Module { 47 | val outer = IO(new RealBoardDataBundle()) 48 | val inside = IO(new BoardDataBundle()) 49 | val io = IO(new Bundle { 50 | val uartClock = Input(Clock()) 51 | val vgaClock = Input(Clock()) 52 | val cpuClock = Input(Clock()) 53 | val cycles = Input(UInt(32.W)) 54 | 55 | val originPC = Input(UInt(32.W)) 56 | val interrupt = Output(Bool()) 57 | }) 58 | 59 | inside.cycles := io.cycles 60 | inside.originPC := io.originPC 61 | io.interrupt := withClock (io.cpuClock) { Debounce(outer.interrupt).onDown } 62 | 63 | inside.switches <> outer.switches.map(Debounce(_).out) 64 | inside.buttons.elements.foreach(pair => pair._2 := Debounce(outer.buttons.elements(pair._1).asUInt.asBool).out) 65 | inside.regable.leds <> outer.leds 66 | 67 | val uart = Module(new UARTWrap(8, 4)) 68 | uart.io.pair <> outer.uart 69 | uart.io.dataTx <> inside.uartOut 70 | uart.io.dataRx <> inside.uartIn 71 | uart.io.uartClock := io.uartClock 72 | 73 | val tube = Module(new TubesController()) 74 | tube.io.out <> outer.tubes 75 | tube.io.in <> inside.regable.tubes 76 | 77 | val keyboard = Module(new Keyboard()) 78 | val keyboardQueue = Module(new CrossClockQueue(KeyboardButton(), 32)) 79 | keyboard.io.in <> outer.keyboard 80 | keyboardQueue.io.clkEnq := clock 81 | keyboardQueue.io.clkDeq := clock 82 | keyboardQueue.io.enq <> keyboard.io.out 83 | keyboardQueue.io.deq <> inside.keyboard 84 | 85 | val display = Module(new DisplaySubsystem()) 86 | display.io.vgaClock := io.vgaClock 87 | display.io.vgaDataPort <> inside.vgaDataPort 88 | outer.vga := RegNext(display.io.out) 89 | } 90 | 91 | class DisplaySubsystem(implicit options: GenerateOptions) extends Module { 92 | val vgaParams = VGAParams( 93 | new OneTiming(800, 40, 128, 88), // horizontal 94 | new OneTiming(600, 1, 4, 23), // vertical 95 | 11) 96 | 97 | val io = IO(new Bundle { 98 | val vgaClock = Input(Clock()) 99 | val out = new VGAOutBundle() 100 | val vgaDataPort = new MemoryPort(14, 16) 101 | }) 102 | 103 | val vga = withClock(io.vgaClock) { Module(new VGATop(vgaParams)) } 104 | val console = withClock(io.vgaClock) { Module(new Console(vgaParams)) } 105 | val dataMem = Module(new BlockMemory(1, 256 * 64, ConsoleCharBundle.packedWidth)) 106 | val fontRom = withClock(io.vgaClock) { Module(new BlockMemoryRom(2, 0x100 * 16, 8, Some("font.txt"))) } 107 | dataMem.io.clockB := io.vgaClock 108 | dataMem.io2.init() 109 | fontRom.io.init() 110 | 111 | require(dataMem.addrWidth == io.vgaDataPort.addrWidth) 112 | require(dataMem.dataWidth == io.vgaDataPort.dataWidth) 113 | 114 | vga.io.out <> io.out 115 | 116 | console.io.charRamData := dataMem.io2.setRead(console.io.charRamAddr) 117 | console.io.fontRomData := fontRom.io.setRead(console.io.fontRomAddr) 118 | console.io.out <> vga.io.in 119 | console.io.info <> vga.io.info 120 | io.vgaDataPort <> dataMem.io1 121 | } 122 | 123 | class UARTWrap(dataBits: Int, oversampleLog: Int) extends Module { 124 | val io = IO(new Bundle { 125 | val pair = new UARTPair() 126 | 127 | val dataTx = Flipped(Decoupled(UInt(dataBits.W))) 128 | val dataRx = Decoupled(UInt(dataBits.W)) 129 | 130 | val uartClock = Input(Clock()) 131 | }) 132 | 133 | val txQueue = Module(new CrossClockQueue(UInt(dataBits.W), 128)) // CPU --> UART 134 | val rxQueue = Module(new CrossClockQueue(UInt(dataBits.W), 128)) // UART --> CPU 135 | 136 | val uart = withClock(io.uartClock) { 137 | Module(new UART(dataBits, oversampleLog)) 138 | } 139 | 140 | uart.io.pair <> io.pair 141 | 142 | txQueue.io.clkEnq := clock 143 | txQueue.io.clkDeq := io.uartClock 144 | txQueue.io.enq <> io.dataTx 145 | txQueue.io.deq <> uart.io.dataIn 146 | 147 | rxQueue.io.clkEnq := io.uartClock 148 | rxQueue.io.clkDeq := clock 149 | rxQueue.io.enq <> uart.io.dataOut 150 | rxQueue.io.deq <> io.dataRx 151 | } 152 | -------------------------------------------------------------------------------- /chisel/src/test/scala/core/MemorySpec.scala: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import util.GenerateOptions 4 | import chisel3._ 5 | import chiseltest._ 6 | import org.scalatest.flatspec.AnyFlatSpec 7 | 8 | class MemorySpec extends AnyFlatSpec with ChiselScalatestTester { 9 | behavior of "core.Memory" 10 | 11 | def write(addr: UInt, data: SInt, width: MemWidth.Type)(implicit dut: Memory): Unit = { 12 | dut.io.addr.poke(addr) 13 | dut.io.memWidth.poke(width) 14 | dut.io.write.poke(true.B) 15 | dut.io.dataIn.poke(data) 16 | 17 | dut.clock.step(1) 18 | dut.io.write.poke(false.B) 19 | } 20 | 21 | def read(addr: UInt, width: MemWidth.Type, unsigned: Bool)(implicit dut: Memory): SInt = { 22 | dut.io.addr.poke(addr) 23 | dut.io.memWidth.poke(width) 24 | dut.io.unsigned.poke(unsigned) 25 | 26 | dut.clock.step(1) 27 | dut.io.dataOut 28 | } 29 | 30 | def getMemory: Memory = { 31 | implicit val options = new GenerateOptions( 32 | true, 33 | false, 34 | 100_000_000, 35 | 10_000_000, 36 | 8_500_000, 37 | 40_000_000) 38 | new Memory(32) 39 | } 40 | 41 | it should "read and write word" in { 42 | test(getMemory) { implicit dut => 43 | dut.io.enable.poke(true.B) 44 | write(4.U, 0x01020304.S, MemWidth.Word) 45 | read(4.U, MemWidth.Word, true.B).expect(0x01020304.S) 46 | } 47 | } 48 | 49 | it should "read and write half-word" in { 50 | test(getMemory) { implicit dut => 51 | dut.io.enable.poke(true.B) 52 | write(4.U, 0x0102.S, MemWidth.Half) 53 | read(4.U, MemWidth.Half, true.B).expect(0x0102.S) 54 | 55 | write(6.U, 0x0102.S, MemWidth.Half) 56 | read(6.U, MemWidth.Half, true.B).expect(0x0102.S) 57 | } 58 | } 59 | 60 | it should "read and write byte" in { 61 | test(getMemory) { implicit dut => 62 | dut.io.enable.poke(true.B) 63 | 64 | for (i <- 0 until 8) { 65 | write(i.U, i.S, MemWidth.Half) 66 | read(i.U, MemWidth.Half, true.B).expect(i.S) 67 | } 68 | } 69 | } 70 | 71 | it should "read little endian in half-word" in { 72 | test(getMemory) { implicit dut => 73 | dut.io.enable.poke(true.B) 74 | 75 | write(4.U, 0x01020304.S, MemWidth.Word) 76 | read(4.U, MemWidth.Half, true.B).expect(0x0304.S) 77 | read(6.U, MemWidth.Half, true.B).expect(0x0102.S) 78 | } 79 | } 80 | 81 | it should "write little endian in half-word" in { 82 | test(getMemory) { implicit dut => 83 | dut.io.enable.poke(true.B) 84 | 85 | write(4.U, 0x0304.S, MemWidth.Half) 86 | write(6.U, 0x0102.S, MemWidth.Half) 87 | read(4.U, MemWidth.Word, true.B).expect(0x01020304.S) 88 | } 89 | } 90 | 91 | it should "read little endian in byte" in { 92 | test(getMemory) { implicit dut => 93 | dut.io.enable.poke(true.B) 94 | 95 | write(4.U, 0x01020304.S, MemWidth.Word) 96 | read(4.U, MemWidth.Byte, true.B).expect(0x04.S) 97 | read(5.U, MemWidth.Byte, true.B).expect(0x03.S) 98 | read(6.U, MemWidth.Byte, true.B).expect(0x02.S) 99 | read(7.U, MemWidth.Byte, true.B).expect(0x01.S) 100 | } 101 | } 102 | 103 | it should "write little endian in byte" in { 104 | test(getMemory) { implicit dut => 105 | dut.io.enable.poke(true.B) 106 | 107 | write(4.U, 0x04.S, MemWidth.Byte) 108 | write(5.U, 0x03.S, MemWidth.Byte) 109 | write(6.U, 0x02.S, MemWidth.Byte) 110 | write(7.U, 0x01.S, MemWidth.Byte) 111 | read(4.U, MemWidth.Word, true.B).expect(0x01020304.S) 112 | } 113 | } 114 | 115 | it should "partial write of half-word" in { 116 | test(getMemory) { implicit dut => 117 | dut.io.enable.poke(true.B) 118 | 119 | write(4.U, 0x01020304.S, MemWidth.Word) 120 | write(6.U, 0x0506.S, MemWidth.Half) 121 | read(4.U, MemWidth.Word, true.B).expect(0x05060304.S) 122 | write(4.U, 0x0708.S, MemWidth.Half) 123 | read(4.U, MemWidth.Word, true.B).expect(0x05060708.S) 124 | } 125 | } 126 | 127 | it should "partial write of byte" in { 128 | test(getMemory) { implicit dut => 129 | dut.io.enable.poke(true.B) 130 | 131 | write(4.U, 0x01020304.S, MemWidth.Word) 132 | write(6.U, 0x05.S, MemWidth.Byte) 133 | read(4.U, MemWidth.Word, true.B).expect(0x01050304.S) 134 | write(7.U, 0x06.S, MemWidth.Byte) 135 | read(4.U, MemWidth.Word, true.B).expect(0x06050304.S) 136 | write(4.U, 0x07.S, MemWidth.Byte) 137 | read(4.U, MemWidth.Word, true.B).expect(0x06050307.S) 138 | write(5.U, 0x08.S, MemWidth.Byte) 139 | read(4.U, MemWidth.Word, true.B).expect(0x06050807.S) 140 | } 141 | } 142 | 143 | it should "read signed half-word" in { 144 | test(getMemory) { implicit dut => 145 | dut.io.enable.poke(true.B) 146 | 147 | write(4.U, 0xF000F000.S, MemWidth.Word) 148 | read(6.U, MemWidth.Half, false.B).expect(0xFFFFF000.S) 149 | read(4.U, MemWidth.Half, false.B).expect(0xFFFFF000.S) 150 | } 151 | } 152 | 153 | it should "read signed byte" in { 154 | test(getMemory) { implicit dut => 155 | dut.io.enable.poke(true.B) 156 | 157 | write(4.U, 0xF0F0F0F0.S, MemWidth.Word) 158 | read(4.U, MemWidth.Byte, false.B).expect(0xFFFFFFF0.S) 159 | read(5.U, MemWidth.Byte, false.B).expect(0xFFFFFFF0.S) 160 | read(6.U, MemWidth.Byte, false.B).expect(0xFFFFFFF0.S) 161 | read(7.U, MemWidth.Byte, false.B).expect(0xFFFFFFF0.S) 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /chisel/src/main/scala/board/Tubes.scala: -------------------------------------------------------------------------------- 1 | package board 2 | 3 | import util.{Encoder, GenerateOptions, Helper, Split, switch} 4 | import chisel3._ 5 | import chisel3.util._ 6 | 7 | import scala.collection.mutable.ListBuffer 8 | 9 | class TubesGroupBundle extends Bundle { 10 | val enable = Output(Vec(8, Bool())) 11 | val tubes = Output(Vec(8, Bool())) // [7:0] PGFEDCBA 12 | } 13 | 14 | class TubesInputBundle extends Bundle { 15 | val value = UInt(32.W) 16 | val enables = Vec(8, Bool()) 17 | val mode = TubesMode() 18 | val effect = TubesEffect() // unused (unimplemented) 19 | } 20 | 21 | object TubesMode extends ChiselEnum { 22 | val Dec, Hex = Value 23 | } 24 | 25 | object TubesEffect extends ChiselEnum { 26 | val None, Blink = Value 27 | } 28 | 29 | class TubesController(implicit options: GenerateOptions) extends Module { 30 | val io = IO(new Bundle { 31 | val in = Input(new TubesInputBundle()) 32 | val out = new TubesGroupBundle() 33 | }) 34 | 35 | // val scale = { 36 | // val ratio = options.standardClock / 8000 37 | // Helper.log2(ratio) 38 | // } 39 | val scale = 12 40 | 41 | // since we need to scan each digit every several milliseconds 42 | // this frequency is much slower than the system clock, which MMCM does not support 43 | // so we need to manually slow the clock down 44 | // note: clock does not expected to be reset 45 | val tubeClock = withReset(0.B.asAsyncReset) { 46 | val clockCnt = RegInit(0.U(scale.W)) 47 | clockCnt := clockCnt + 1.U 48 | clockCnt(scale - 1).asClock 49 | } 50 | dontTouch(tubeClock) // tell Chisel don't touch, since we need it for timing constraints 51 | 52 | withClock(tubeClock) { 53 | // decode the decimal into 8 digits (more are ignored) 54 | val decDigits = { 55 | val buffer = ListBuffer.empty[UInt] 56 | var current = io.in.value 57 | for (_ <- 0 until 8) { 58 | val (q, r) = DivTen(current) 59 | current = q 60 | buffer += r 61 | } 62 | 63 | buffer.toSeq 64 | } 65 | 66 | // hexadecimal value is much simpler, just spilt them by 4 bits 67 | val hexDigits = Split(io.in.value, 8, 4) 68 | 69 | // mux which group of digits is to be display 70 | val digits = Wire(Vec(8, UInt(4.W))) 71 | switch (io.in.mode) 72 | .is (TubesMode.Dec) { digits := decDigits } 73 | .is (TubesMode.Hex) { digits := hexDigits } 74 | .default { digits := DontCare } 75 | 76 | val tube = Module(new Tubes) 77 | tube.io.digits := digits.reverse 78 | tube.io.enables := io.in.enables 79 | tube.io.dots := 0.U(8.W).asBools 80 | io.out <> tube.io.out 81 | } 82 | } 83 | 84 | // given 8 digits, 8 dots (unused), and 8 enables (tell whether this digit should be display) 85 | // this module will translate the data to the raw board signal 86 | // that is, it will "scan" the digits in a very fast way, making them display simultaneously 87 | class Tubes extends Module { 88 | val io = IO(new Bundle { 89 | val digits = Input(Vec(8, UInt(4.W))) 90 | val dots = Input(Vec(8, Bool())) 91 | val enables = Input(Vec(8, Bool())) 92 | 93 | val out = new TubesGroupBundle() 94 | }) 95 | 96 | // scan each row 97 | val now = RegInit(0.U(3.W)) 98 | now := now + 1.U 99 | 100 | // since both enable and tube data is low valid, so we need to invert them 101 | io.out.enable := (~(Encoder(8)(now) & io.enables.asUInt)).asBools 102 | io.out.tubes := (~Cat(io.dots(now), BcdToTube(io.digits(now)).asUInt)).asBools 103 | } 104 | 105 | // digits (0-F) --> tubes (tube enables) 106 | class BcdToTube extends Module { 107 | val io = IO(new Bundle { 108 | val digit = Input(UInt(4.W)) 109 | val tubes = Output(Vec(7, Bool())) // [6:0] GFEDCBA 110 | }) 111 | 112 | val table = Seq( 113 | 0x0 -> "b0111111", 114 | 0x1 -> "b0000110", 115 | 0x2 -> "b1011011", 116 | 0x3 -> "b1001111", 117 | 0x4 -> "b1100110", 118 | 0x5 -> "b1101101", 119 | 0x6 -> "b1111101", 120 | 0x7 -> "b0000111", 121 | 0x8 -> "b1111111", 122 | 0x9 -> "b1101111", 123 | 0xA -> "b1110111", 124 | 0xB -> "b1111100", 125 | 0xC -> "b1011000", 126 | 0xD -> "b1011110", 127 | 0xE -> "b1111001", 128 | 0xF -> "b1110001", 129 | ).map((o) => o._1.U(io.digit.getWidth.W) -> o._2.U(io.tubes.getWidth.W)) 130 | 131 | io.tubes := MuxLookup(io.digit, table.head._2)(table).asBools 132 | } 133 | 134 | object BcdToTube { 135 | def apply(digit: UInt): Vec[Bool] = { 136 | val toTube = Module(new BcdToTube) 137 | toTube.io.digit := digit 138 | toTube.io.tubes 139 | } 140 | } 141 | 142 | // a quick way to perform division by 10 143 | // given `in` as input, output quotient and remainder 144 | class DivTen extends Module { 145 | val io = IO(new Bundle { 146 | val in = Input(UInt(32.W)) 147 | val quotient = Output(UInt(29.W)) 148 | val remainder = Output(UInt(4.W)) 149 | }) 150 | 151 | val q1 = (io.in >> 1).asUInt +& (io.in >> 2).asUInt; 152 | val q2 = q1 + (q1 >> 4).asUInt 153 | val q3 = q2 + (q2 >> 8).asUInt 154 | val q4 = q3 + (q3 >> 16).asUInt 155 | val q5 = (q4 >> 3).asUInt 156 | val r = io.in - (((q5 << 2).asUInt + q5) << 1).asUInt 157 | 158 | io.quotient := q5 + (r > 9.U).asUInt 159 | io.remainder := io.in - (io.quotient << 1).asUInt - (io.quotient << 3).asUInt 160 | } 161 | 162 | object DivTen { 163 | def apply(in: UInt): (UInt, UInt) = { 164 | val divTen = Module(new DivTen()) 165 | divTen.io.in := in 166 | (divTen.io.quotient, divTen.io.remainder) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /program/src/bin/tetris/game/state.rs: -------------------------------------------------------------------------------- 1 | use alloc::collections::VecDeque; 2 | use alloc::vec; 3 | 4 | use cpu_lib::monitor::Color; 5 | 6 | use super::{ 7 | level::{ClearedLines, Level}, 8 | tetromino::Tetromino, 9 | }; 10 | 11 | #[derive(Debug, Clone, Copy, PartialEq)] 12 | pub enum Square { 13 | Empty, 14 | Occupied(Color), 15 | } 16 | 17 | pub const FIELD_HEIGHT: usize = 20; 18 | pub const FIELD_WIDTH: usize = 10; 19 | 20 | pub type Field = VecDeque<[Square; FIELD_WIDTH]>; 21 | 22 | #[derive(Debug, Clone, PartialEq)] 23 | pub struct GameState { 24 | pub level: Level, 25 | pub current: Tetromino, 26 | pub next: Tetromino, 27 | pub preview: Option, 28 | pub ticks: u32, 29 | pub field: Field, 30 | } 31 | 32 | impl GameState { 33 | pub fn new(level: u32) -> Self { 34 | let mut state = Self { 35 | level: Level::new(level), 36 | current: Tetromino::next(), 37 | next: Tetromino::next(), 38 | preview: None, 39 | ticks: 0, 40 | field: VecDeque::from(vec![[Square::Empty; 10]; 20]), 41 | }; 42 | 43 | state.preview = state.determine_preview(); 44 | 45 | state 46 | } 47 | } 48 | 49 | impl GameState { 50 | pub fn determine_preview(&self) -> Option { 51 | let mut preview = self.current.clone(); 52 | 53 | preview.move_down(); 54 | 55 | if self.check_collision(&preview).is_some() { 56 | return None; 57 | } 58 | 59 | while self.check_collision(&preview).is_none() { 60 | preview.move_down(); 61 | } 62 | 63 | preview.move_up(); 64 | 65 | Some(preview) 66 | } 67 | 68 | pub fn try_move_down(&mut self) -> bool { 69 | match self.try_solidify() { 70 | true => true, 71 | false => { 72 | self.current.move_down(); 73 | false 74 | } 75 | } 76 | } 77 | 78 | fn try_solidify(&mut self) -> bool { 79 | let mut copy = self.current.clone(); 80 | copy.move_down(); 81 | 82 | if self.check_collision(©).is_some() { 83 | for elem in self.current.offset_blocks().iter() { 84 | self.field[elem.vec.y as usize][elem.vec.x as usize] = 85 | Square::Occupied(self.current.color); 86 | } 87 | 88 | return true; 89 | } 90 | 91 | false 92 | } 93 | 94 | pub fn check_collision(&self, tetromino: &Tetromino) -> Option { 95 | if Self::is_out_of_bounds(tetromino) { 96 | return Some(Collision::OutOfBounds); 97 | } 98 | 99 | if Self::has_collision_with_block(tetromino, &self.field) { 100 | return Some(Collision::WithBlock); 101 | } 102 | 103 | None 104 | } 105 | 106 | fn has_collision_with_block(tetromino: &Tetromino, field: &Field) -> bool { 107 | tetromino.offset_blocks().iter().any(|block| { 108 | match &field[block.vec.y as usize][block.vec.x as usize] { 109 | Square::Empty => false, 110 | Square::Occupied(_) => true, 111 | } 112 | }) 113 | } 114 | 115 | fn is_out_of_bounds(tetromino: &Tetromino) -> bool { 116 | tetromino.offset_blocks().iter().any(|block| { 117 | block.vec.x as usize >= FIELD_WIDTH 118 | || block.vec.x < 0 119 | || block.vec.y as usize >= FIELD_HEIGHT 120 | || block.vec.y < 0 121 | }) 122 | } 123 | 124 | pub fn clear_lines(&mut self) -> ClearedLines { 125 | self.field 126 | .retain(|line| line.iter().any(|square| square == &Square::Empty)); 127 | 128 | let cleared_lines = FIELD_HEIGHT - self.field.len(); 129 | 130 | while self.field.len() < FIELD_HEIGHT { 131 | self.field.push_front([Square::Empty; 10]); 132 | } 133 | 134 | cleared_lines.into() 135 | } 136 | 137 | pub fn rotate(&mut self) { 138 | let original = self.current.clone(); 139 | self.current.rotate(); 140 | 141 | self.kickback(original); 142 | } 143 | 144 | pub fn move_right(&mut self) { 145 | let original = self.current.clone(); 146 | self.current.move_right(); 147 | 148 | self.kickback(original); 149 | } 150 | 151 | pub fn move_left(&mut self) { 152 | let original = self.current.clone(); 153 | self.current.move_left(); 154 | 155 | self.kickback(original); 156 | } 157 | 158 | pub fn move_down(&mut self) -> bool { 159 | self.try_move_down() 160 | } 161 | 162 | pub fn drop(&mut self) -> bool { 163 | while !self.try_move_down() {} 164 | 165 | true 166 | } 167 | 168 | fn kickback(&mut self, original: Tetromino) { 169 | if self.check_collision(&self.current).is_some() { 170 | self.current = original; 171 | } 172 | } 173 | 174 | pub fn advance_game(&mut self, already_solidified: bool) -> bool { 175 | self.ticks += 1; 176 | 177 | match self.ticks > self.level.required_ticks() { 178 | true => { 179 | self.ticks = 0; 180 | already_solidified || self.try_move_down() 181 | } 182 | false => already_solidified, 183 | } 184 | } 185 | 186 | pub fn is_finished(&self) -> bool { 187 | self.check_collision(&self.current).is_some() 188 | } 189 | } 190 | 191 | pub enum Collision { 192 | OutOfBounds, 193 | WithBlock, 194 | } 195 | --------------------------------------------------------------------------------