From b525b1d9b78bea3a7e7bea4e31945af28b5c6c5d Mon Sep 17 00:00:00 2001 From: TonyCrane Date: Thu, 6 Jul 2023 18:15:47 +0800 Subject: [PATCH] feat: Final RV64 CPU with MMU and kernel --- .gitignore | 4 +- README.md | 10 +- src/CPU.v | 396 +- src/Core.v | 51 +- src/CoreSim.v | 15 +- src/MMUSim.v | 35 + src/Makefile | 16 +- src/Top.sv | 56 +- src/{ => auxillary}/IO_Manager.sv | 0 src/auxillary/UART_TX_CTRL.vhd | 157 + src/auxillary/uart_buffer.v | 43 + src/components/ALU.v | 47 +- src/components/AddressTranslator.v | 179 + ...MretForwarding.v => CSRReturnForwarding.v} | 20 +- src/components/CSRs.v | 60 +- src/components/Control.v | 195 +- src/components/Datapath.v | 107 - src/components/ForwardingUnit.v | 28 +- src/components/ImmGen.v | 37 +- src/components/MMU.v | 66 + src/components/Memory.v | 73 + src/components/RegEXMEM.v | 85 + src/components/RegIDEX.v | 131 + src/components/RegIFID.v | 34 + src/components/RegMEMWB.v | 61 + src/components/Regs.v | 31 +- src/dump_changes.py | 63 + src/headers/Funct.vh | 19 + src/headers/Opcodes.vh | 41 +- src/memory/RAM.v | 26 - src/memory/ROM.v | 14 - src/tests/PageTableSim/ram.hex | 20488 ++++++++++++++++ src/tests/PipelineBranchPrediction/ram.hex | 180 + src/tests/PipelineBranchPrediction/rom.hex | 236 + src/tests/RV64/Makefile | 23 + src/tests/RV64/RV64I.hex | 41 + src/tests/RV64/RV64I.s | 32 + src/tests/kernel/.gitignore | 13 + src/tests/kernel/Makefile | 83 + src/tests/kernel/arch/riscv/Makefile | 12 + src/tests/kernel/arch/riscv/include/clock.h | 7 + src/tests/kernel/arch/riscv/include/defs.h | 58 + src/tests/kernel/arch/riscv/include/mm.h | 15 + src/tests/kernel/arch/riscv/include/proc.h | 58 + src/tests/kernel/arch/riscv/include/sbi.h | 18 + src/tests/kernel/arch/riscv/kernel/Makefile | 19 + src/tests/kernel/arch/riscv/kernel/clock.c | 19 + src/tests/kernel/arch/riscv/kernel/entry.S | 166 + src/tests/kernel/arch/riscv/kernel/head.S | 48 + src/tests/kernel/arch/riscv/kernel/mm.c | 51 + src/tests/kernel/arch/riscv/kernel/proc.c | 162 + src/tests/kernel/arch/riscv/kernel/sbi.c | 21 + src/tests/kernel/arch/riscv/kernel/trap.c | 48 + src/tests/kernel/arch/riscv/kernel/vm.c | 92 + .../kernel/arch/riscv/kernel/vmlinux.lds | 73 + src/tests/kernel/debug.gdb | 37 + src/tests/kernel/include/printk.h | 9 + src/tests/kernel/include/rand.h | 9 + src/tests/kernel/include/stddef.h | 15 + src/tests/kernel/include/string.h | 11 + src/tests/kernel/include/types.h | 6 + src/tests/kernel/init/Makefile | 10 + src/tests/kernel/init/main.c | 17 + src/tests/kernel/init/test.c | 11 + src/tests/kernel/lib/Makefile | 10 + src/tests/kernel/lib/printk.c | 114 + src/tests/kernel/lib/rand.c | 35 + src/tests/kernel/lib/string.c | 35 + src/tests/kernel/user/Makefile | 24 + src/tests/kernel/user/getpid.c | 34 + src/tests/kernel/user/link.lds | 31 + src/tests/kernel/user/printf.c | 130 + src/tests/kernel/user/start.S | 4 + src/tests/kernel/user/stddef.h | 15 + src/tests/kernel/user/stdio.h | 13 + src/tests/kernel/user/syscall.h | 3 + src/tests/kernel/write_sim_hex.py | 30 + src/tests/kernel/write_sim_hex_von.py | 44 + src/tests/kernel/write_sim_hex_von_split.py | 45 + src/utils/Mux2x64.v | 10 + src/utils/Mux4x64.v | 21 + src/utils/Mux8x64.v | 29 + src/utils/MuxPC.v | 14 +- src/wave.gtkw | 570 +- src/wave_mmu.gtkw | 69 + 85 files changed, 24762 insertions(+), 706 deletions(-) create mode 100644 src/MMUSim.v rename src/{ => auxillary}/IO_Manager.sv (100%) create mode 100644 src/auxillary/UART_TX_CTRL.vhd create mode 100644 src/auxillary/uart_buffer.v create mode 100644 src/components/AddressTranslator.v rename src/components/{MretForwarding.v => CSRReturnForwarding.v} (52%) delete mode 100644 src/components/Datapath.v create mode 100644 src/components/MMU.v create mode 100644 src/components/Memory.v create mode 100644 src/components/RegEXMEM.v create mode 100644 src/components/RegIDEX.v create mode 100644 src/components/RegIFID.v create mode 100644 src/components/RegMEMWB.v create mode 100644 src/dump_changes.py create mode 100644 src/headers/Funct.vh delete mode 100644 src/memory/RAM.v delete mode 100644 src/memory/ROM.v create mode 100644 src/tests/PageTableSim/ram.hex create mode 100644 src/tests/PipelineBranchPrediction/ram.hex create mode 100644 src/tests/PipelineBranchPrediction/rom.hex create mode 100644 src/tests/RV64/Makefile create mode 100644 src/tests/RV64/RV64I.hex create mode 100644 src/tests/RV64/RV64I.s create mode 100644 src/tests/kernel/.gitignore create mode 100644 src/tests/kernel/Makefile create mode 100644 src/tests/kernel/arch/riscv/Makefile create mode 100644 src/tests/kernel/arch/riscv/include/clock.h create mode 100644 src/tests/kernel/arch/riscv/include/defs.h create mode 100644 src/tests/kernel/arch/riscv/include/mm.h create mode 100644 src/tests/kernel/arch/riscv/include/proc.h create mode 100644 src/tests/kernel/arch/riscv/include/sbi.h create mode 100644 src/tests/kernel/arch/riscv/kernel/Makefile create mode 100644 src/tests/kernel/arch/riscv/kernel/clock.c create mode 100644 src/tests/kernel/arch/riscv/kernel/entry.S create mode 100644 src/tests/kernel/arch/riscv/kernel/head.S create mode 100644 src/tests/kernel/arch/riscv/kernel/mm.c create mode 100644 src/tests/kernel/arch/riscv/kernel/proc.c create mode 100644 src/tests/kernel/arch/riscv/kernel/sbi.c create mode 100644 src/tests/kernel/arch/riscv/kernel/trap.c create mode 100644 src/tests/kernel/arch/riscv/kernel/vm.c create mode 100644 src/tests/kernel/arch/riscv/kernel/vmlinux.lds create mode 100644 src/tests/kernel/debug.gdb create mode 100644 src/tests/kernel/include/printk.h create mode 100644 src/tests/kernel/include/rand.h create mode 100644 src/tests/kernel/include/stddef.h create mode 100644 src/tests/kernel/include/string.h create mode 100644 src/tests/kernel/include/types.h create mode 100644 src/tests/kernel/init/Makefile create mode 100644 src/tests/kernel/init/main.c create mode 100644 src/tests/kernel/init/test.c create mode 100644 src/tests/kernel/lib/Makefile create mode 100644 src/tests/kernel/lib/printk.c create mode 100644 src/tests/kernel/lib/rand.c create mode 100644 src/tests/kernel/lib/string.c create mode 100644 src/tests/kernel/user/Makefile create mode 100644 src/tests/kernel/user/getpid.c create mode 100644 src/tests/kernel/user/link.lds create mode 100644 src/tests/kernel/user/printf.c create mode 100644 src/tests/kernel/user/start.S create mode 100644 src/tests/kernel/user/stddef.h create mode 100644 src/tests/kernel/user/stdio.h create mode 100644 src/tests/kernel/user/syscall.h create mode 100644 src/tests/kernel/write_sim_hex.py create mode 100644 src/tests/kernel/write_sim_hex_von.py create mode 100644 src/tests/kernel/write_sim_hex_von_split.py create mode 100644 src/utils/Mux2x64.v create mode 100644 src/utils/Mux4x64.v create mode 100644 src/utils/Mux8x64.v create mode 100644 src/wave_mmu.gtkw diff --git a/.gitignore b/.gitignore index 4257897..898ed1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .DS_Store src/core.vvp -src/dump.vcd \ No newline at end of file +src/dump.vcd + +src/dut_changes.txt diff --git a/README.md b/README.md index 092e935..ad58fc4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ ## 实验进度 -系统贯通课程会逐步实现一个 RISC-V 五级流水线 CPU,并实现异常处理、分支预测、Cache 等功能。本 repo 通过分支、tag 等来记录实验进度,保存各阶段成果。 +系统贯通课程会逐步实现一个 RISC-V 五级流水线 CPU,并实现异常处理、分支预测、Cache、MMU 等功能,并在其上运行自己编写的简易 kernel。 + +本 repo 通过分支、tag 等来记录实验进度,保存各阶段成果。 - [x] 系统 Ⅰ lab5-1/lab5-2:单周期 CPU - [x] extra:单周期 CPU with 特权指令/异常处理 @@ -18,6 +20,12 @@ - 使用了提供的实验框架而非自己的,就不放在 repo 里了 - [x] 系统 Ⅲ lab2:流水线 CPU with Cache - 使用了提供的实验框架而非自己的,就不放在 repo 里了 +- [x] 系统 Ⅲ lab Xpart:软硬件贯通实验,主要部分是实现 MMU 以及调试 kernel + - RV64IZicsr 全部指令(除去 fence ebreak wfi) + - 包含 Supervisor 和 User 两个特权级 + - 实现了 Bare 和 Sv39 两种分页模式 + - 支持串口输出 + - 展示 slides 在:[slides.tonycrane.cc/sys3-xpart-pre](https://slides.tonycrane.cc/sys3-xpart-pre/) ## 实验环境 diff --git a/src/CPU.v b/src/CPU.v index d2e2707..1bd3bf7 100644 --- a/src/CPU.v +++ b/src/CPU.v @@ -3,236 +3,145 @@ module CPU( input clk, input rst, + input stall, input [31:0] inst, - input [31:0] data_in, // data from data memory + input [63:0] data_in, // data from data memory input [4:0] debug_reg_addr, - output [31:0] addr_out, // data memory address - output [31:0] data_out, // data to data memory - output [31:0] pc_out, // connect to instruction memory + output [63:0] addr_out, // data memory address + output [63:0] data_out, // data to data memory + output [63:0] pc_out, // connect to instruction memory output mem_write, - output [31:0] debug_reg + output mem_read, + output [63:0] debug_reg, + output [63:0] satp, + output [2:0] data_width ); - reg [31:0] pc; - wire [31:0] pc_next; + reg [63:0] pc; + wire [63:0] pc_next; - reg [31:0] IF_ID_pc; - reg [31:0] IF_ID_inst; + wire [63:0] IF_ID_pc; + wire [31:0] IF_ID_inst; - wire [31:0] read_data1, read_data2, imm; - wire [31:0] csr_read_data, csr_ret_pc; + wire [63:0] read_data1, read_data2, imm; + wire [63:0] csr_read_data, csr_ret_pc; + wire [63:0] csr_write_scause, sstatus, csr_write_sstatus; wire [11:0] csr_read_addr, csr_write_addr; wire [3:0] alu_op; wire [2:0] mem_to_reg; wire [1:0] pc_src, trap; wire alu_src; wire reg_write, branch, b_type, auipc, mem_write_; - wire mem_read, bubble_stop, jump; + wire mem_read_, bubble_stop, jump; wire csr_write, csr_write_src, rev_imm; - reg [31:0] ID_EX_data1, ID_EX_data2; - reg [31:0] ID_EX_pc, ID_EX_imm; - reg [4:0] ID_EX_rs1, ID_EX_rs2; - reg [4:0] ID_EX_write_addr; - reg [3:0] ID_EX_alu_op; - reg [2:0] ID_EX_mem_to_reg; - reg [1:0] ID_EX_pc_src; - reg ID_EX_alu_src; - reg ID_EX_reg_write, ID_EX_branch, ID_EX_b_type, ID_EX_auipc, ID_EX_mem_write; - reg ID_EX_mem_read; - reg [11:0] ID_EX_csr_write_addr; - reg ID_EX_csr_write, ID_EX_csr_write_src, ID_EX_rev_imm; - reg [31:0] ID_EX_csr_write_data, ID_EX_csr_read_data; - - wire [31:0] alu_data1, alu_data2, alu_result; + wire alu_work_on_word; + wire [2:0] data_width_; + wire [63:0] ID_EX_data1, ID_EX_data2; + wire [63:0] ID_EX_pc, ID_EX_imm; + wire [4:0] ID_EX_rs1, ID_EX_rs2; + wire [4:0] ID_EX_write_addr; + wire [3:0] ID_EX_alu_op; + wire [2:0] ID_EX_mem_to_reg; + wire [1:0] ID_EX_pc_src; + wire ID_EX_alu_src; + wire ID_EX_reg_write, ID_EX_branch, ID_EX_b_type, ID_EX_auipc, ID_EX_mem_write; + wire ID_EX_mem_read; + wire [11:0] ID_EX_csr_write_addr; + wire ID_EX_csr_write, ID_EX_csr_write_src, ID_EX_rev_imm; + wire [63:0] ID_EX_csr_write_data, ID_EX_csr_read_data; + wire ID_EX_alu_work_on_word; + wire [2:0] ID_EX_data_width; + + wire [63:0] alu_data1, alu_data2, alu_result; wire alu_zero; wire [2:0] forwardA, forwardB; wire [1:0] forwardC; - wire [31:0] ex_mem_data2; - reg [31:0] EX_MEM_alu_result, EX_MEM_pc, EX_MEM_imm; - reg [31:0] EX_MEM_data2; - reg [4:0] EX_MEM_write_addr; - reg [2:0] EX_MEM_mem_to_reg; - reg [1:0] EX_MEM_pc_src; - reg EX_MEM_reg_write, EX_MEM_branch, EX_MEM_b_type, EX_MEM_mem_write; - reg [11:0] EX_MEM_csr_write_addr; - reg EX_MEM_csr_write, EX_MEM_csr_write_src, EX_MEM_rev_imm; - reg [31:0] EX_MEM_csr_write_data, EX_MEM_csr_read_data; - - wire [31:0] write_data; - wire [31:0] jal_addr, jalr_addr; - reg [31:0] MEM_WB_data_in, MEM_WB_alu_result, MEM_WB_pc, MEM_WB_imm; - reg [4:0] MEM_WB_write_addr; - reg [2:0] MEM_WB_mem_to_reg; - reg MEM_WB_reg_write; - reg [11:0] MEM_WB_csr_write_addr; - reg MEM_WB_csr_write, MEM_WB_csr_write_src, MEM_WB_rev_imm; - reg [31:0] MEM_WB_csr_write_data, MEM_WB_csr_read_data; + wire [63:0] ex_mem_data2; + wire [63:0] EX_MEM_alu_result, EX_MEM_pc, EX_MEM_imm; + wire [63:0] EX_MEM_data2; + wire [4:0] EX_MEM_write_addr; + wire [2:0] EX_MEM_mem_to_reg; + wire [1:0] EX_MEM_pc_src; + wire EX_MEM_reg_write, EX_MEM_branch, EX_MEM_b_type, EX_MEM_mem_write, EX_MEM_mem_read; + wire [11:0] EX_MEM_csr_write_addr; + wire EX_MEM_csr_write, EX_MEM_csr_write_src, EX_MEM_rev_imm; + wire [63:0] EX_MEM_csr_write_data, EX_MEM_csr_read_data; + wire [2:0] EX_MEM_data_width; + + wire [63:0] write_data; + wire [63:0] jal_addr, jalr_addr; + wire [63:0] MEM_WB_data_in, MEM_WB_alu_result, MEM_WB_pc, MEM_WB_imm; + wire [4:0] MEM_WB_write_addr; + wire [2:0] MEM_WB_mem_to_reg; + wire MEM_WB_reg_write; + wire [11:0] MEM_WB_csr_write_addr; + wire MEM_WB_csr_write, MEM_WB_csr_write_src, MEM_WB_rev_imm; + wire [63:0] MEM_WB_csr_write_data, MEM_WB_csr_read_data; assign pc_out = pc; - always @(posedge clk or posedge rst) begin - if (rst) begin - pc <= 32'b0; - IF_ID_pc <= 32'b0; - IF_ID_inst <= 32'b0; - ID_EX_pc <= 32'b0; - ID_EX_data1 <= 32'b0; - ID_EX_data2 <= 32'b0; - ID_EX_imm <= 32'b0; - ID_EX_write_addr <= 5'b0; - ID_EX_alu_op <= 4'b0; - ID_EX_pc_src <= 2'b0; - ID_EX_mem_to_reg <= 3'b0; - ID_EX_reg_write <= 1'b0; - ID_EX_alu_src <= 1'b0; - ID_EX_branch <= 1'b0; - ID_EX_b_type <= 1'b0; - ID_EX_auipc <= 1'b0; - ID_EX_mem_write <= 1'b0; - ID_EX_mem_read <= 1'b0; - ID_EX_rs1 <= 5'b0; - ID_EX_rs2 <= 5'b0; - ID_EX_csr_write_addr <= 12'b0; - ID_EX_csr_write <= 1'b0; - ID_EX_csr_write_src <= 1'b0; - ID_EX_rev_imm <= 1'b0; - ID_EX_csr_write_data <= 32'b0; - ID_EX_csr_read_data <= 32'b0; - ID_EX_rev_imm <= 1'b0; - EX_MEM_alu_result <= 32'b0; - EX_MEM_pc <= 32'b0; - EX_MEM_imm <= 32'b0; - EX_MEM_data2 <= 32'b0; - EX_MEM_write_addr <= 5'b0; - EX_MEM_pc_src <= 2'b0; - EX_MEM_mem_to_reg <= 3'b0; - EX_MEM_reg_write <= 1'b0; - EX_MEM_branch <= 1'b0; - EX_MEM_b_type <= 1'b0; - EX_MEM_mem_write <= 1'b0; - EX_MEM_csr_write_addr <= 12'b0; - EX_MEM_csr_write <= 1'b0; - EX_MEM_csr_write_src <= 1'b0; - EX_MEM_rev_imm <= 1'b0; - EX_MEM_csr_write_data <= 32'b0; - EX_MEM_csr_read_data <= 32'b0; - MEM_WB_data_in <= 32'b0; - MEM_WB_alu_result <= 32'b0; - MEM_WB_pc <= 32'b0; - MEM_WB_imm <= 32'b0; - MEM_WB_write_addr <= 5'b0; - MEM_WB_mem_to_reg <= 3'b0; - MEM_WB_reg_write <= 1'b0; - MEM_WB_csr_write_addr <= 12'b0; - MEM_WB_csr_write <= 1'b0; - MEM_WB_csr_write_src <= 1'b0; - MEM_WB_rev_imm <= 1'b0; - MEM_WB_csr_write_data <= 32'b0; - MEM_WB_csr_read_data <= 32'b0; - end - else begin - if (bubble_stop) begin - ID_EX_alu_op <= 4'b0; - ID_EX_pc_src <= 2'b0; - ID_EX_mem_to_reg <= 3'b0; - ID_EX_reg_write <= 1'b0; - ID_EX_alu_src <= 1'b0; - ID_EX_branch <= 1'b0; - ID_EX_b_type <= 1'b0; - ID_EX_auipc <= 1'b0; - ID_EX_mem_write <= 1'b0; - ID_EX_mem_read <= 1'b0; - ID_EX_csr_write_addr <= 12'b0; - ID_EX_csr_write <= 1'b0; - ID_EX_csr_write_src <= 1'b0; - ID_EX_rev_imm <= 1'b0; - end else if (jump || trap != 2'b0) begin - pc <= pc_next; - - IF_ID_pc <= pc; - IF_ID_inst <= 32'h00000013; - - ID_EX_pc_src <= pc_src; - ID_EX_mem_to_reg <= mem_to_reg; - ID_EX_reg_write <= reg_write; - ID_EX_alu_src <= alu_src; - ID_EX_branch <= branch; - ID_EX_b_type <= b_type; - ID_EX_auipc <= auipc; - ID_EX_alu_op <= alu_op; - ID_EX_mem_write <= mem_write_; - ID_EX_mem_read <= mem_read; - ID_EX_csr_write_addr <= csr_write_addr; - ID_EX_csr_write <= csr_write; - ID_EX_csr_write_src <= csr_write_src; - ID_EX_rev_imm <= rev_imm; - end else begin - pc <= pc_next; - - IF_ID_pc <= pc; - IF_ID_inst <= inst; - - ID_EX_pc_src <= pc_src; - ID_EX_mem_to_reg <= mem_to_reg; - ID_EX_reg_write <= reg_write; - ID_EX_alu_src <= alu_src; - ID_EX_branch <= branch; - ID_EX_b_type <= b_type; - ID_EX_auipc <= auipc; - ID_EX_alu_op <= alu_op; - ID_EX_mem_write <= mem_write_; - ID_EX_mem_read <= mem_read; - ID_EX_csr_write_addr <= csr_write_addr; - ID_EX_csr_write <= csr_write; - ID_EX_csr_write_src <= csr_write_src; - ID_EX_rev_imm <= rev_imm; - end - - ID_EX_pc <= IF_ID_pc; - ID_EX_data1 <= read_data1; - ID_EX_data2 <= read_data2; - ID_EX_imm <= imm; - ID_EX_write_addr <= IF_ID_inst[11:7]; - ID_EX_rs1 <= IF_ID_inst[19:15]; - ID_EX_rs2 <= IF_ID_inst[24:20]; - ID_EX_csr_write_data <= read_data1; - ID_EX_csr_read_data <= csr_read_data; - - EX_MEM_pc <= ID_EX_pc; - EX_MEM_imm <= ID_EX_imm; - EX_MEM_data2 <= ex_mem_data2; - EX_MEM_alu_result <= alu_result; - EX_MEM_write_addr <= ID_EX_write_addr; - EX_MEM_pc_src <= ID_EX_pc_src; - EX_MEM_mem_to_reg <= ID_EX_mem_to_reg; - EX_MEM_reg_write <= ID_EX_reg_write; - EX_MEM_branch <= ID_EX_branch; - EX_MEM_b_type <= ID_EX_b_type; - EX_MEM_mem_write <= ID_EX_mem_write; - EX_MEM_csr_write_addr <= ID_EX_csr_write_addr; - EX_MEM_csr_write <= ID_EX_csr_write; - EX_MEM_csr_write_src <= ID_EX_csr_write_src; - EX_MEM_rev_imm <= ID_EX_rev_imm; - EX_MEM_csr_write_data <= alu_data1; - EX_MEM_csr_read_data <= ID_EX_csr_read_data; - - MEM_WB_data_in <= data_in; - MEM_WB_alu_result <= EX_MEM_alu_result; - MEM_WB_pc <= EX_MEM_pc; - MEM_WB_imm <= EX_MEM_imm; - MEM_WB_write_addr <= EX_MEM_write_addr; - MEM_WB_mem_to_reg <= EX_MEM_mem_to_reg; - MEM_WB_reg_write <= EX_MEM_reg_write; - MEM_WB_csr_write_addr <= EX_MEM_csr_write_addr; - MEM_WB_csr_write <= EX_MEM_csr_write; - MEM_WB_csr_write_src <= EX_MEM_csr_write_src; - MEM_WB_rev_imm <= EX_MEM_rev_imm; - MEM_WB_csr_write_data <= EX_MEM_csr_write_data; - MEM_WB_csr_read_data <= EX_MEM_csr_read_data; + reg ID_EX_flush, IF_ID_en; + + always @(posedge clk or posedge rst) begin + if (rst) begin + pc <= 64'h80200000; + end else if (~bubble_stop && ~stall) begin + pc <= pc_next; end end + RegIFID reg_IFID ( + .clk(clk), .rst(rst), .en(~stall), + .stall(bubble_stop), .flush(jump || trap != 2'b0), + .pc_IF(pc), .inst_IF(inst), + .pc_ID(IF_ID_pc), .inst_ID(IF_ID_inst) + ); + + RegIDEX reg_IDEX ( + .clk(clk), .rst(rst), .en(~stall), + .flush(bubble_stop), + .pc_ID(IF_ID_pc), .pc_src_ID(pc_src), .rs1_ID(IF_ID_inst[19:15]), .rs2_ID(IF_ID_inst[24:20]), .rd_ID(IF_ID_inst[11:7]), + .data1_ID(read_data1), .data2_ID(read_data2), .imm_ID(imm), + .alu_op_ID(alu_op), .alu_src_ID(alu_src), .alu_work_on_word_ID(alu_work_on_word), + .reg_write_ID(reg_write), .mem_to_reg_ID(mem_to_reg), .mem_read_ID(mem_read_), .mem_write_ID(mem_write_), .data_width_ID(data_width_), + .branch_ID(branch), .b_type_ID(b_type), .auipc_ID(auipc), + .csr_write_ID(csr_write), .csr_write_src_ID(csr_write_src), .csr_rd_ID(csr_write_addr), .csr_write_data_ID(read_data1), .csr_read_data_ID(csr_read_data), + + .pc_EX(ID_EX_pc), .pc_src_EX(ID_EX_pc_src), .rs1_EX(ID_EX_rs1), .rs2_EX(ID_EX_rs2), .rd_EX(ID_EX_write_addr), + .data1_EX(ID_EX_data1), .data2_EX(ID_EX_data2), .imm_EX(ID_EX_imm), + .alu_op_EX(ID_EX_alu_op), .alu_src_EX(ID_EX_alu_src), .alu_work_on_word_EX(ID_EX_alu_work_on_word), + .reg_write_EX(ID_EX_reg_write), .mem_to_reg_EX(ID_EX_mem_to_reg), .mem_read_EX(ID_EX_mem_read), .mem_write_EX(ID_EX_mem_write), .data_width_EX(ID_EX_data_width), + .branch_EX(ID_EX_branch), .b_type_EX(ID_EX_b_type), .auipc_EX(ID_EX_auipc), + .csr_write_EX(ID_EX_csr_write), .csr_write_src_EX(ID_EX_csr_write_src), .csr_rd_EX(ID_EX_csr_write_addr), .csr_write_data_EX(ID_EX_csr_write_data), .csr_read_data_EX(ID_EX_csr_read_data) + ); + + RegEXMEM reg_EXMEM ( + .clk(clk), .rst(rst), .en(~stall), + .pc_EX(ID_EX_pc), .pc_src_EX(ID_EX_pc_src), + .rd_EX(ID_EX_write_addr), .data2_EX(ex_mem_data2), .imm_EX(ID_EX_imm), .alu_result_EX(alu_result), + .mem_to_reg_EX(ID_EX_mem_to_reg), .reg_write_EX(ID_EX_reg_write), .mem_write_EX(ID_EX_mem_write), .mem_read_EX(ID_EX_mem_read), .data_width_EX(ID_EX_data_width), + .branch_EX(ID_EX_branch), .b_type_EX(ID_EX_b_type), + .csr_rd_EX(ID_EX_csr_write_addr), .csr_write_EX(ID_EX_csr_write), .csr_write_src_EX(ID_EX_csr_write_src), .csr_write_data_EX(csr_write_src ? csr_write_sstatus : alu_data1), .csr_read_data_EX(ID_EX_csr_read_data), + + .pc_MEM(EX_MEM_pc), .pc_src_MEM(EX_MEM_pc_src), + .rd_MEM(EX_MEM_write_addr), .data2_MEM(EX_MEM_data2), .imm_MEM(EX_MEM_imm), .alu_result_MEM(EX_MEM_alu_result), + .mem_to_reg_MEM(EX_MEM_mem_to_reg), .reg_write_MEM(EX_MEM_reg_write), .mem_write_MEM(EX_MEM_mem_write), .mem_read_MEM(EX_MEM_mem_read), .data_width_MEM(EX_MEM_data_width), + .branch_MEM(EX_MEM_branch), .b_type_MEM(EX_MEM_b_type), + .csr_rd_MEM(EX_MEM_csr_write_addr), .csr_write_MEM(EX_MEM_csr_write), .csr_write_src_MEM(EX_MEM_csr_write_src), .csr_write_data_MEM(EX_MEM_csr_write_data), .csr_read_data_MEM(EX_MEM_csr_read_data) + ); + + RegMEMWB reg_MEM_WB ( + .clk(clk), .rst(rst), .en(~stall), + .pc_MEM(EX_MEM_pc), .imm_MEM(EX_MEM_imm), .alu_result_MEM(EX_MEM_alu_result), .data_in_MEM(data_in), + .rd_MEM(EX_MEM_write_addr), .mem_to_reg_MEM(EX_MEM_mem_to_reg), .reg_write_MEM(EX_MEM_reg_write), + .csr_rd_MEM(EX_MEM_csr_write_addr), .csr_write_MEM(EX_MEM_csr_write), .csr_write_src_MEM(EX_MEM_csr_write_src), .csr_write_data_MEM(EX_MEM_csr_write_data), .csr_read_data_MEM(EX_MEM_csr_read_data), + + .pc_WB(MEM_WB_pc), .imm_WB(MEM_WB_imm), .alu_result_WB(MEM_WB_alu_result), .data_in_WB(MEM_WB_data_in), + .rd_WB(MEM_WB_write_addr), .mem_to_reg_WB(MEM_WB_mem_to_reg), .reg_write_WB(MEM_WB_reg_write), + .csr_rd_WB(MEM_WB_csr_write_addr), .csr_write_WB(MEM_WB_csr_write), .csr_write_src_WB(MEM_WB_csr_write_src), .csr_write_data_WB(MEM_WB_csr_write_data), .csr_read_data_WB(MEM_WB_csr_read_data) + ); + //--------------------ID--------------------// StallUnit stallunit ( @@ -246,10 +155,15 @@ module CPU( ); assign jal_addr = IF_ID_pc + imm; - wire [31:0] reg1, reg2; - assign reg1 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[19:15])) ? (EX_MEM_mem_to_reg == 2'b11 ? data_in : EX_MEM_alu_result) : read_data1; - assign reg2 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[24:20])) ? (EX_MEM_mem_to_reg == 2'b11 ? data_in : EX_MEM_alu_result) : read_data2; + wire [63:0] reg1, reg2; + assign reg1 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[19:15])) ? (EX_MEM_mem_to_reg == 3'b011 ? data_in : EX_MEM_alu_result) : read_data1; + assign reg2 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[24:20])) ? (EX_MEM_mem_to_reg == 3'b011 ? data_in : EX_MEM_alu_result) : read_data2; assign jalr_addr = reg1 + reg2; + wire [63:0] alu_res_tmp; + assign alu_res_tmp = + (alu_op == 4'b0100) ? (reg1 ^ reg2) : + (alu_op == 4'b0011) ? (reg1 < reg2) : + ($signed(reg1) < $signed(reg2)); MuxPC mux_pc ( .I0(jump ? pc : pc + 4), @@ -259,7 +173,7 @@ module CPU( .s(pc_src), .branch(branch), .b_type(b_type), - .alu_res(reg1 ^ reg2), + .alu_res(alu_res_tmp), .o(pc_next) ); @@ -277,28 +191,33 @@ module CPU( .debug_reg(debug_reg) ); + wire set_satp; + assign set_satp = EX_MEM_csr_write && (EX_MEM_csr_write_addr == 12'h180); + CSRs csrs ( .clk(clk), .rst(rst), - .we(MEM_WB_csr_write), + .we(set_satp ? EX_MEM_csr_write : MEM_WB_csr_write), .trap(trap), .pc(IF_ID_pc), .csr_read_addr(csr_read_addr), - .csr_write_addr(MEM_WB_csr_write_addr), - .csr_write_data(MEM_WB_csr_write_data), - .csr_read_data(csr_read_data) + .csr_write_addr(set_satp ? EX_MEM_csr_write_addr : MEM_WB_csr_write_addr), + .csr_write_data(set_satp ? EX_MEM_csr_write_data : MEM_WB_csr_write_data), + .csr_write_scause(csr_write_scause), + .csr_read_data(csr_read_data), + .csr_satp(satp), + .csr_sstatus(sstatus) ); - MretForwarding mretforwarding ( + CSRReturnForwarding csrretforwarding ( .ID_EX_csr_write(ID_EX_csr_write), .ID_EX_csr_write_addr(ID_EX_csr_write_addr), - // .ID_EX_csr_write_data(ID_EX_csr_write_data), - // .EX_MEM_csr_write(EX_MEM_csr_write), - // .EX_MEM_csr_write_addr(EX_MEM_csr_write_addr), - // .EX_MEM_csr_write_data(EX_MEM_csr_write_data), + .ID_EX_csr_write_data(ID_EX_csr_write_data), .EX_MEM_alu_result(EX_MEM_alu_result), .csr_read_data(csr_read_data), .trap(trap), + .EX_MEM_rd(EX_MEM_write_addr), + .ID_EX_rs1(ID_EX_rs1), .csr_ret_pc(csr_ret_pc) ); @@ -307,6 +226,8 @@ module CPU( .funct3(IF_ID_inst[14:12]), .funct7_5(IF_ID_inst[30]), .csr(IF_ID_inst[31:20]), + .pc(IF_ID_pc), + .sstatus(sstatus), .pc_src(pc_src), .reg_write(reg_write), .alu_src_b(alu_src), @@ -316,14 +237,18 @@ module CPU( .branch(branch), .b_type(b_type), .auipc(auipc), - .mem_read(mem_read), + .mem_read(mem_read_), .jump(jump), .trap(trap), .csr_read_addr(csr_read_addr), .csr_write_addr(csr_write_addr), .csr_write(csr_write), .csr_write_src(csr_write_src), - .rev_imm(rev_imm) + .csr_write_sstatus(csr_write_sstatus), + .csr_write_scause(csr_write_scause), + .rev_imm(rev_imm), + .alu_work_on_word(alu_work_on_word), + .data_width(data_width_) ); ImmGen immgen ( @@ -349,7 +274,7 @@ module CPU( .ForwardC(forwardC) ); - Mux8x32 mux_alu_a ( + Mux8x64 mux_alu_a ( .I0(ID_EX_data1), .I1(EX_MEM_alu_result), .I2(write_data), @@ -362,10 +287,10 @@ module CPU( .o(alu_data1) ); - wire [31:0] alu_b_imm; + wire [63:0] alu_b_imm; assign alu_b_imm = (ID_EX_mem_to_reg == 3'b100 ? ID_EX_csr_read_data : ID_EX_imm); - Mux8x32 mux_alu_b ( + Mux8x64 mux_alu_b ( .I0(ID_EX_data2), .I1(EX_MEM_alu_result), .I2(write_data), @@ -382,15 +307,16 @@ module CPU( .a(alu_data1), .b(alu_data2), .alu_op(ID_EX_alu_op), + .alu_work_on_word(ID_EX_alu_work_on_word), .res(alu_result), .zero(alu_zero) ); - Mux4x32 mux_data2 ( + Mux4x64 mux_data2 ( .I0(ID_EX_data2), .I1(EX_MEM_alu_result), .I2(write_data), - .I3(32'h00000000), + .I3(64'h00000000), .s(forwardC), .o(ex_mem_data2) ); @@ -399,26 +325,20 @@ module CPU( assign addr_out = EX_MEM_alu_result; assign data_out = EX_MEM_data2; assign mem_write = EX_MEM_mem_write; + assign mem_read = EX_MEM_mem_read; + assign data_width = EX_MEM_data_width; //--------------------WB--------------------// - // Mux4x32 mux4x32 ( - // .I0(MEM_WB_alu_result), - // .I1(MEM_WB_imm), - // .I2(MEM_WB_pc + 4), - // .I3(MEM_WB_data_in), - // .s(MEM_WB_mem_to_reg), - // .o(write_data) - // ); - Mux8x32 mux8x32 ( + Mux8x64 mux8x64 ( .I0(MEM_WB_alu_result), .I1(MEM_WB_imm), .I2(MEM_WB_pc + 4), .I3(MEM_WB_data_in), .I4(MEM_WB_csr_read_data), - .I5(0), - .I6(0), - .I7(0), + .I5(64'b0), + .I6(64'b0), + .I7(64'b0), .s(MEM_WB_mem_to_reg), .o(write_data) ); diff --git a/src/Core.v b/src/Core.v index 943f18c..50c168d 100644 --- a/src/Core.v +++ b/src/Core.v @@ -6,19 +6,25 @@ module Core ( input wire step, input wire debug_mode, input wire [4:0] debug_reg_addr, // register address - output wire [31:0] chip_debug_out0, - output wire [31:0] chip_debug_out1, - output wire [31:0] chip_debug_out2, - output wire [31:0] chip_debug_out3 + output wire [63:0] chip_debug_out0, + output wire [63:0] chip_debug_out1, + output wire [63:0] chip_debug_out2, + output wire [63:0] chip_debug_out3, + output wire [7:0] sim_uart_char_out, + output wire sim_uart_char_valid ); wire rst, mem_write, mem_clk, cpu_clk; - wire [31:0] inst, core_data_in, addr_out, core_data_out, pc_out; + wire [31:0] inst; + wire [63:0] core_data_in, addr_out, core_data_out, pc_out; reg [31:0] clk_div; - wire [31:0] debug_reg; + wire [63:0] debug_reg; + wire [63:0] satp; + wire stall, mem_read; + wire [2:0] width; assign rst = ~aresetn; - CPU cpu( + CPU cpu ( .clk(cpu_clk), .rst(rst), .inst(inst), @@ -27,8 +33,12 @@ module Core ( .data_out(core_data_out), // data to data memory .pc_out(pc_out), // connect to instruction memory .mem_write(mem_write), + .mem_read(mem_read), .debug_reg_addr(debug_reg_addr), - .debug_reg(debug_reg) + .debug_reg(debug_reg), + .satp(satp), + .data_width(width), + .stall(stall) ); always @(posedge clk) begin @@ -38,21 +48,24 @@ module Core ( assign mem_clk = ~clk_div[0]; assign cpu_clk = debug_mode ? clk_div[0] : step; - ROM rom_unit ( - .address(pc_out / 4), - .out(inst) - ); - - RAM ram_unit ( - .clk(mem_clk), - .we(mem_write), - .address(addr_out / 4), + MMU mmu ( + .clk(mem_clk), .rst(rst), + .inst_addr(pc_out), + .data_addr(addr_out), .write_data(core_data_out), - .read_data(core_data_in) + .mem_write(mem_write), + .mem_read(mem_read), + .width(width), + .satp(satp), + .inst_out(inst), + .read_data(core_data_in), + .stall_pipeline(stall), + .sim_uart_char_out(sim_uart_char_out), + .sim_uart_char_valid(sim_uart_char_valid) ); assign chip_debug_out0 = pc_out; assign chip_debug_out1 = addr_out; - assign chip_debug_out2 = inst; + assign chip_debug_out2 = {32'b0, inst}; assign chip_debug_out3 = debug_reg; endmodule diff --git a/src/CoreSim.v b/src/CoreSim.v index 06ed58c..f452065 100644 --- a/src/CoreSim.v +++ b/src/CoreSim.v @@ -2,7 +2,7 @@ module CoreSim; reg clk, rst; - Core core( + Core core ( .clk(clk), .aresetn(~rst), .step(1'b0), @@ -10,10 +10,12 @@ module CoreSim; .debug_reg_addr(5'b0) ); - initial begin - $dumpvars(0, CoreSim); - #700000 $finish; - end + // initial begin + // $dumpvars(0, CoreSim); + // // #700000 $finish; + // // #2000 $finish; + // // #1000000000 $finish; + // end initial begin clk = 0; @@ -21,4 +23,7 @@ module CoreSim; #2 rst = 0; end always #1 clk = ~clk; + // always #5000000 begin + // $display("pc: %h", core.cpu.MEM_WB_pc); + // end endmodule \ No newline at end of file diff --git a/src/MMUSim.v b/src/MMUSim.v new file mode 100644 index 0000000..92f4824 --- /dev/null +++ b/src/MMUSim.v @@ -0,0 +1,35 @@ +`timescale 1ns / 1ps + +module MMUSim; + reg clk, rst; + wire [31:0] inst_out; + wire [63:0] read_data; + wire stall_pipeline; + + MMU mmu ( + .clk(clk), .rst(rst), + .inst_addr(64'hffffffe000200000), + .data_addr(64'hffffffe00020b000), + // .data_addr(64'h800), + .write_data(64'h0000000000000000), + .mem_write(1'b0), + .mem_read(1'b1), + .width(3'b011), + .satp(64'h8000000000080202), + .inst_out(inst_out), + .read_data(read_data), + .stall_pipeline(stall_pipeline) + ); + + initial begin + $dumpvars(0, MMUSim); + #200 $finish; + end + + initial begin + clk = 0; + rst = 1; + #2 rst = 0; + end + always #1 clk = ~clk; +endmodule \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index a5f22d9..d562ea7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,13 +6,27 @@ all: compile simulate compile: iverilog -o core.vvp -y . \ - -y components -y memory -y utils \ + -y components -y utils \ -I headers \ CoreSim.v simulate: vvp -n core.vvp + +open: $(GTKWAVE) dump.vcd wave.gtkw +mmu: compile-mmu simulate-mmu + +compile-mmu: + iverilog -o core.vvp -y . \ + -y components -y utils \ + -I headers \ + MMUSim.v + +simulate-mmu: + vvp -n core.vvp + $(GTKWAVE) dump.vcd wave_mmu.gtkw + clean: rm -f core.vvp dump.vcd \ No newline at end of file diff --git a/src/Top.sv b/src/Top.sv index ba1db0c..634e218 100644 --- a/src/Top.sv +++ b/src/Top.sv @@ -10,18 +10,30 @@ module Top( output [ 2:0] rgb1, output [ 2:0] rgb2, output [ 7:0] num_csn, - output [ 7:0] num_an + output [ 7:0] num_an, + output UART_TXD ); logic aresetn; logic step; - logic [31:0] chip_debug_out0; - logic [31:0] chip_debug_out1; - logic [31:0] chip_debug_out2; - logic [31:0] chip_debug_out3; + logic [63:0] chip_debug_out0; + logic [63:0] chip_debug_out1; + logic [63:0] chip_debug_out2; + logic [63:0] chip_debug_out3; + + logic [7:0] uart_data, sim_uart_char; + logic uart_send, uart_ready, sim_uart_char_valid; + logic [31:0] clk_div; + logic clk_cpu; + + always @(posedge clk) begin + if (!resetn) clk_div <= 0; + else clk_div <= clk_div + 1; + end + assign clk_cpu = clk_div[3]; Core chip_inst( - .clk(clk), + .clk(clk_cpu), .aresetn(aresetn), .step(step), .debug_mode(switch[15]), @@ -29,11 +41,13 @@ module Top( .chip_debug_out0(chip_debug_out0), .chip_debug_out1(chip_debug_out1), .chip_debug_out2(chip_debug_out2), - .chip_debug_out3(chip_debug_out3) + .chip_debug_out3(chip_debug_out3), + .sim_uart_char_out(sim_uart_char), + .sim_uart_char_valid(sim_uart_char_valid), ); IO_Manager io_manager_inst( - .clk(clk), + .clk(clk_cpu), .resetn(resetn), // to chip @@ -54,9 +68,27 @@ module Top( .debug1({16'b0, switch[15:0]}), .debug2({12'b0, 3'b0, button[4], 3'b0, button[3], 3'b0, button[2], 3'b0, button[1], 3'b0, button[0]}), .debug3(32'h12345678), - .debug4(chip_debug_out0), - .debug5(chip_debug_out1), - .debug6(chip_debug_out2), - .debug7(chip_debug_out3) + .debug4(chip_debug_out0[31:0]), + .debug5(chip_debug_out1[31:0]), + .debug6(chip_debug_out2[31:0]), + .debug7(chip_debug_out3[31:0]) + ); + + UART_TX_CTRL uart_tx_ctrl ( + .SEND(uart_send), + .DATA(uart_data), + .CLK(clk), + .READY(uart_ready), + .UART_TX(UART_TXD) + ); + + uart_buffer UART_BUFF ( + .clk(clk_cpu), + .rst(~aresetn), + .ready(uart_ready), + .sim_uart_char_valid(sim_uart_char_valid), + .sim_uart_char(sim_uart_char), + .send(uart_send), + .datao(uart_data) ); endmodule diff --git a/src/IO_Manager.sv b/src/auxillary/IO_Manager.sv similarity index 100% rename from src/IO_Manager.sv rename to src/auxillary/IO_Manager.sv diff --git a/src/auxillary/UART_TX_CTRL.vhd b/src/auxillary/UART_TX_CTRL.vhd new file mode 100644 index 0000000..9eb78d8 --- /dev/null +++ b/src/auxillary/UART_TX_CTRL.vhd @@ -0,0 +1,157 @@ +---------------------------------------------------------------------------- +-- UART_TX_CTRL.vhd -- UART Data Transfer Component +---------------------------------------------------------------------------- +-- Author: Sam Bobrowicz +-- Copyright 2011 Digilent, Inc. +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- This component may be used to transfer data over a UART device. It will +-- serialize a byte of data and transmit it over a TXD line. The serialized +-- data has the following characteristics: +-- *9600 Baud Rate +-- *8 data bits, LSB first +-- *1 stop bit +-- *no parity +-- +-- Port Descriptions: +-- +-- SEND - Used to trigger a send operation. The upper layer logic should +-- set this signal high for a single clock cycle to trigger a +-- send. When this signal is set high DATA must be valid . Should +-- not be asserted unless READY is high. +-- DATA - The parallel data to be sent. Must be valid the clock cycle +-- that SEND has gone high. +-- CLK - A 100 MHz clock is expected +-- READY - This signal goes low once a send operation has begun and +-- remains low until it has completed and the module is ready to +-- send another byte. +-- UART_TX - This signal should be routed to the appropriate TX pin of the +-- external UART device. +-- +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- Revision History: +-- 08/08/2011(SamB): Created using Xilinx Tools 13.2 +---------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.std_logic_unsigned.all; + +entity UART_TX_CTRL is + Port ( SEND : in STD_LOGIC; + DATA : in STD_LOGIC_VECTOR (7 downto 0); + CLK : in STD_LOGIC; + READY : out STD_LOGIC; + UART_TX : out STD_LOGIC); +end UART_TX_CTRL; + +architecture Behavioral of UART_TX_CTRL is + +type TX_STATE_TYPE is (RDY, LOAD_BIT, SEND_BIT); + +constant BIT_TMR_MAX : std_logic_vector(13 downto 0) := "10100010110000"; --10416 = (round(100MHz / 9600)) - 1 +constant BIT_INDEX_MAX : natural := 10; + +--Counter that keeps track of the number of clock cycles the current bit has been held stable over the +--UART TX line. It is used to signal when the ne +signal bitTmr : std_logic_vector(13 downto 0) := (others => '0'); + +--combinatorial logic that goes high when bitTmr has counted to the proper value to ensure +--a 9600 baud rate +signal bitDone : std_logic; + +--Contains the index of the next bit in txData that needs to be transferred +signal bitIndex : natural; + +--a register that holds the current data being sent over the UART TX line +signal txBit : std_logic := '1'; + +--A register that contains the whole data packet to be sent, including start and stop bits. +signal txData : std_logic_vector(9 downto 0); + +signal txState : TX_STATE_TYPE := RDY; + +begin + +--Next state logic +next_txState_process : process (CLK) +begin + if (rising_edge(CLK)) then + case txState is + when RDY => + if (SEND = '1') then + txState <= LOAD_BIT; + end if; + when LOAD_BIT => + txState <= SEND_BIT; + when SEND_BIT => + if (bitDone = '1') then + if (bitIndex = BIT_INDEX_MAX) then + txState <= RDY; + else + txState <= LOAD_BIT; + end if; + end if; + when others=> --should never be reached + txState <= RDY; + end case; + end if; +end process; + +bit_timing_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + bitTmr <= (others => '0'); + else + if (bitDone = '1') then + bitTmr <= (others => '0'); + else + bitTmr <= bitTmr + 1; + end if; + end if; + end if; +end process; + +bitDone <= '1' when (bitTmr = BIT_TMR_MAX) else + '0'; + +bit_counting_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + bitIndex <= 0; + elsif (txState = LOAD_BIT) then + bitIndex <= bitIndex + 1; + end if; + end if; +end process; + +tx_data_latch_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (SEND = '1') then + txData <= '1' & DATA & '0'; + end if; + end if; +end process; + +tx_bit_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + txBit <= '1'; + elsif (txState = LOAD_BIT) then + txBit <= txData(bitIndex); + end if; + end if; +end process; + +UART_TX <= txBit; +READY <= '1' when (txState = RDY) else + '0'; + +end Behavioral; + diff --git a/src/auxillary/uart_buffer.v b/src/auxillary/uart_buffer.v new file mode 100644 index 0000000..758ca15 --- /dev/null +++ b/src/auxillary/uart_buffer.v @@ -0,0 +1,43 @@ +`timescale 1ns / 1ps + +module uart_buffer ( + input clk, rst, + input wire ready, + input wire [7:0] sim_uart_char, + input wire sim_uart_char_valid, + output reg send, + output reg [7:0] datao +); + localparam SIZE = 256; + reg[7:0] buffer[0:SIZE-1]; + + reg [7:0] head; + reg [7:0] tail; + + always@(posedge clk) begin + if(rst) begin + head <= 0; + tail <= 0; + end else begin + if (ready && (head != tail)) begin + datao <= buffer[head]; + send <= 1'b1; + head <= (head == SIZE-1)? 0 : head+1; + end + if (sim_uart_char_valid) begin + buffer[tail] <= sim_uart_char; + if (sim_uart_char == 8'h0a) begin + buffer[tail+1] <= 8'h0d; + tail <= (tail == SIZE-2)? 0 : + (tail == SIZE-1)? 1 : tail+2; + end else begin + tail <= (tail == SIZE-1)? 0 : tail+1; + end + end + if (send == 1'b1) begin + send <= 1'b0; + end + end + end + +endmodule \ No newline at end of file diff --git a/src/components/ALU.v b/src/components/ALU.v index 07bb0a6..fc4aaa7 100644 --- a/src/components/ALU.v +++ b/src/components/ALU.v @@ -1,36 +1,41 @@ `timescale 1ns / 1ps module ALU ( - input [31:0] a, - input [31:0] b, - input [3:0] alu_op, - output reg [31:0] res, - output zero + input [63:0] a, + input [63:0] b, + input [3:0] alu_op, + input alu_work_on_word, + output [63:0] res, + output zero ); `include "AluOp.vh" + + reg [63:0] res_tmp; + assign res = alu_work_on_word ? {{32{res_tmp[31]}}, res_tmp[31:0]} : res_tmp; + always @(*) begin case (alu_op) - ADD: res <= a + b; - SUB: res <= a - b; - SLL: res <= a << b[4:0]; + ADD: res_tmp <= a + b; + SUB: res_tmp <= a - b; + SLL: res_tmp <= a << b[5:0]; SLT: begin - if (a[31] == 0 && b[31] == 1) res <= 0; - else if (a[31] == 1 && b[31] == 0) res <= 1; - else if (a[31] == b[31]) begin - if (a[30:0] < b[30:0]) res <= 1; - else res <= 0; + if (a[63] == 0 && b[63] == 1) res_tmp <= 0; + else if (a[63] == 1 && b[63] == 0) res_tmp <= 1; + else if (a[63] == b[63]) begin + if (a[62:0] < b[62:0]) res_tmp <= 1; + else res_tmp <= 0; end end SLTU: begin - if (a < b) res <= 1; - else res <= 0; + if (a < b) res_tmp <= 1; + else res_tmp <= 0; end - XOR: res <= a ^ b; - SRL: res <= a >> b[4:0]; - SRA: res <= a >>> b[4:0]; - OR: res <= a | b; - AND: res <= a & b; - default: res = 0; + XOR: res_tmp <= a ^ b; + SRL: res_tmp <= a >> b[5:0]; + SRA: res_tmp <= $signed(a) >>> b[5:0]; + OR: res_tmp <= a | b; + AND: res_tmp <= a & b; + default: res_tmp = 0; endcase end assign zero = (a-b) ? 1'b0 : 1'b1; diff --git a/src/components/AddressTranslator.v b/src/components/AddressTranslator.v new file mode 100644 index 0000000..2482d95 --- /dev/null +++ b/src/components/AddressTranslator.v @@ -0,0 +1,179 @@ +`timescale 1ns / 1ps + +module AddressTranslator ( + input clk, + input rst, + input ram_en, + input [63:0] satp, + input [63:0] inst_addr, + input [63:0] data_addr, + input [63:0] memory_data1, + input [63:0] memory_data2, + output finish, + output reg [63:0] memory_addr1, + output reg [63:0] memory_addr2 +); + wire [3:0] satp_mode; + wire [43:0] satp_ppn; + reg [1:0] trans_state1, next_state1; + reg [1:0] trans_state2, next_state2; + + reg finish1, finish2; + + reg pte_D_1, pte_A_1, pte_G_1, pte_U_1, pte_X_1, pte_W_1, pte_R_1, pte_V_1; + reg [1:0] pte_RSW_1; + reg [25:0] pte_PPN2_1; + reg [8:0] pte_PPN1_1, pte_PPN0_1; + reg [9:0] pte_reserved_1; + + wire [8:0] vpn2_1, vpn1_1, vpn0_1; + wire [11:0] pgoff_1; + + reg pte_D_2, pte_A_2, pte_G_2, pte_U_2, pte_X_2, pte_W_2, pte_R_2, pte_V_2; + reg [1:0] pte_RSW_2; + reg [25:0] pte_PPN2_2; + reg [8:0] pte_PPN1_2, pte_PPN0_2; + reg [9:0] pte_reserved_2; + + wire [8:0] vpn2_2, vpn1_2, vpn0_2; + wire [11:0] pgoff_2; + + assign vpn2_1 = inst_addr[38:30]; + assign vpn1_1 = inst_addr[29:21]; + assign vpn0_1 = inst_addr[20:12]; + assign pgoff_1 = inst_addr[11:0]; + + assign vpn2_2 = data_addr[38:30]; + assign vpn1_2 = data_addr[29:21]; + assign vpn0_2 = data_addr[20:12]; + assign pgoff_2 = data_addr[11:0]; + + assign satp_mode = satp[63:60]; + assign satp_ppn = satp[43:0]; + + assign finish = ram_en ? finish1 && finish2 : finish1; + + localparam + S_IDLE = 0, + S_LEVEL1 = 1, + S_LEVEL2 = 2, + S_LEVEL3 = 3; + + always @(posedge clk or posedge rst) begin + if (rst) begin + trans_state1 = S_IDLE; + next_state1 = S_IDLE; + finish1 = 1'b0; + end else if (satp_mode == 0) begin + finish1 = 1'b0; + memory_addr1 = inst_addr; + end else begin + trans_state1 = next_state1; + if (trans_state1 == S_IDLE) begin + finish1 = 1'b0; + end + if (1'b1) begin + if (finish1) begin + finish1 = 1'b0; + end + case (trans_state1) + S_IDLE: begin + memory_addr1 = {8'b0, satp_ppn, vpn2_1, 3'b0}; + next_state1 = S_LEVEL1; + finish1 = 1'b0; + end + S_LEVEL1: begin + {pte_reserved_1, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, pte_RSW_1, pte_D_1, pte_A_1, pte_G_1, pte_U_1, pte_X_1, pte_W_1, pte_R_1, pte_V_1} = memory_data1[63:0]; + if (pte_R_1 == 1 || pte_X_1 == 1) begin + memory_addr1 = {8'b0, pte_PPN2_1, vpn1_1, vpn0_1, pgoff_1}; + next_state1 = S_IDLE; + finish1 = 1'b1; + end else begin + memory_addr1 = {8'b0, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, vpn1_1, 3'b0}; + next_state1 = S_LEVEL2; + finish1 = 1'b0; + end + end + S_LEVEL2: begin + {pte_reserved_1, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, pte_RSW_1, pte_D_1, pte_A_1, pte_G_1, pte_U_1, pte_X_1, pte_W_1, pte_R_1, pte_V_1} = memory_data1[63:0]; + if (pte_R_1 == 1 || pte_X_1 == 1) begin + memory_addr1 = {8'b0, pte_PPN2_1, pte_PPN1_1, vpn0_1, pgoff_1}; + next_state1 = S_IDLE; + finish1 = 1'b1; + end else begin + memory_addr1 = {8'b0, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, vpn0_1, 3'b0}; + next_state1 = S_LEVEL3; + finish1 = 1'b0; + end + end + S_LEVEL3: begin + {pte_reserved_1, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, pte_RSW_1, pte_D_1, pte_A_1, pte_G_1, pte_U_1, pte_X_1, pte_W_1, pte_R_1, pte_V_1} = memory_data1[63:0]; + memory_addr1 = {8'b0, pte_PPN2_1, pte_PPN1_1, pte_PPN0_1, pgoff_1}; + next_state1 = S_IDLE; + finish1 = 1'b1; + end + endcase + end + end + end + + always @(posedge clk or posedge rst) begin + if (rst) begin + trans_state2 = S_IDLE; + next_state2 = S_IDLE; + finish2 = 1'b0; + end else if (satp_mode == 0) begin + finish2 = 1'b0; + memory_addr2 = data_addr; + end else begin + trans_state2 = next_state2; + if (trans_state2 == S_IDLE) begin + finish2 = 1'b0; + memory_addr2 = data_addr; + end + if (ram_en) begin + if (finish2) begin + finish2 = 1'b0; + end + case (trans_state2) + S_IDLE: begin + memory_addr2 = {8'b0, satp_ppn, vpn2_2, 3'b0}; + next_state2 = S_LEVEL1; + finish2 = 1'b0; + end + S_LEVEL1: begin + {pte_reserved_2, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, pte_RSW_2, pte_D_2, pte_A_2, pte_G_2, pte_U_2, pte_X_2, pte_W_2, pte_R_2, pte_V_2} = memory_data2[63:0]; + if (pte_R_2 == 1 || pte_X_2 == 1) begin + memory_addr2 = {8'b0, pte_PPN2_2, vpn1_2, vpn0_2, pgoff_2}; + next_state2 = S_IDLE; + finish2 = 1'b1; + end else begin + memory_addr2 = {8'b0, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, vpn1_2, 3'b0}; + next_state2 = S_LEVEL2; + finish2 = 1'b0; + end + end + S_LEVEL2: begin + {pte_reserved_2, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, pte_RSW_2, pte_D_2, pte_A_2, pte_G_2, pte_U_2, pte_X_2, pte_W_2, pte_R_2, pte_V_2} = memory_data2[63:0]; + if (pte_R_2 == 1 || pte_X_2 == 1) begin + memory_addr2 = {8'b0, pte_PPN2_2, pte_PPN1_2, vpn0_2, pgoff_2}; + next_state2 = S_IDLE; + finish2 = 1'b1; + end else begin + memory_addr2 = {8'b0, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, vpn0_2, 3'b0}; + next_state2 = S_LEVEL3; + finish2 = 1'b0; + end + end + S_LEVEL3: begin + {pte_reserved_2, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, pte_RSW_2, pte_D_2, pte_A_2, pte_G_2, pte_U_2, pte_X_2, pte_W_2, pte_R_2, pte_V_2} = memory_data2[63:0]; + memory_addr2 = {8'b0, pte_PPN2_2, pte_PPN1_2, pte_PPN0_2, pgoff_2}; + next_state2 = S_IDLE; + finish2 = 1'b1; + end + endcase + end + end + end + +endmodule \ No newline at end of file diff --git a/src/components/MretForwarding.v b/src/components/CSRReturnForwarding.v similarity index 52% rename from src/components/MretForwarding.v rename to src/components/CSRReturnForwarding.v index 15eb973..4ee138a 100644 --- a/src/components/MretForwarding.v +++ b/src/components/CSRReturnForwarding.v @@ -1,19 +1,25 @@ `timescale 1ns / 1ps -module MretForwarding ( +module CSRReturnForwarding ( input ID_EX_csr_write, input [11:0] ID_EX_csr_write_addr, - input [31:0] EX_MEM_alu_result, - input [31:0] csr_read_data, + input [63:0] EX_MEM_alu_result, + input [63:0] ID_EX_csr_write_data, + input [63:0] csr_read_data, input [1:0] trap, // 00 no trap, 01 ecall, 10 unimp - output [31:0] csr_ret_pc + input [4:0] EX_MEM_rd, + input [4:0] ID_EX_rs1, + output [63:0] csr_ret_pc ); - reg [31:0] _csr_ret_pc; + reg [63:0] _csr_ret_pc; assign csr_ret_pc = _csr_ret_pc; always @(*) begin if (trap == 2'b11) begin - if (ID_EX_csr_write == 1 && ID_EX_csr_write_addr == 12'h341) begin - _csr_ret_pc <= EX_MEM_alu_result; + if (ID_EX_csr_write == 1 && ID_EX_csr_write_addr == 12'h141) begin + if (EX_MEM_rd == ID_EX_rs1) + _csr_ret_pc <= EX_MEM_alu_result; + else + _csr_ret_pc <= ID_EX_csr_write_data; end else begin _csr_ret_pc <= csr_read_data; diff --git a/src/components/CSRs.v b/src/components/CSRs.v index 62895ae..0eee2d0 100644 --- a/src/components/CSRs.v +++ b/src/components/CSRs.v @@ -5,41 +5,49 @@ module CSRs ( input rst, input we, input [1:0] trap, // 00 no trap, 01 ecall, 10 unimp, 11 mret - input [31:0] pc, + input [63:0] pc, input [11:0] csr_read_addr, input [11:0] csr_write_addr, - input [31:0] csr_write_data, - output [31:0] csr_read_data + input [63:0] csr_write_data, + input [63:0] csr_write_scause, + output [63:0] csr_read_data, + output [63:0] csr_satp, + output [63:0] csr_sstatus ); - reg [31:0] mstatus, mepc, mtvec, mcause; + reg [63:0] sstatus, sepc, stvec, scause, satp, sscratch; - assign csr_read_data = (csr_read_addr == 12'h300) ? mstatus : - (csr_read_addr == 12'h341) ? mepc : - (csr_read_addr == 12'h305) ? mtvec : - (csr_read_addr == 12'h342) ? mcause : 0; + assign csr_read_data = (csr_read_addr == 12'h100) ? sstatus : + (csr_read_addr == 12'h141) ? sepc : + (csr_read_addr == 12'h105) ? stvec : + (csr_read_addr == 12'h142) ? scause : + (csr_read_addr == 12'h180) ? satp : + (csr_read_addr == 12'h140) ? sscratch : 0; + assign csr_satp = satp; + assign csr_sstatus = sstatus; always @(negedge clk or posedge rst) begin if (rst == 1) begin - mstatus <= 0; - mepc <= 0; - mtvec <= 0; - mcause <= 0; - end - else if (trap != 0) begin - if (trap == 2'b01) begin - mepc <= pc; - mcause <= 11; + sstatus <= 0; + sepc <= 0; + stvec <= 64'h80200000; + scause <= 0; + satp <= 0; + sscratch <= 0; + end else begin + if (we == 1) begin + if (csr_write_addr == 12'h100) sstatus <= csr_write_data; + else if (csr_write_addr == 12'h141) sepc <= csr_write_data; + else if (csr_write_addr == 12'h105) stvec <= csr_write_data; + else if (csr_write_addr == 12'h142) scause <= csr_write_data; + else if (csr_write_addr == 12'h180) satp <= csr_write_data; + else if (csr_write_addr == 12'h140) sscratch <= csr_write_data; end - else if (trap == 2'b10) begin - mepc <= pc; - mcause <= 2; + if (trap != 0) begin + if (trap == 2'b01 || trap == 2'b10) begin + sepc <= pc; + scause <= csr_write_scause; + end end end - else if (we == 1) begin - if (csr_write_addr == 12'h300) mstatus <= csr_write_data; - else if (csr_write_addr == 12'h341) mepc <= csr_write_data; - else if (csr_write_addr == 12'h305) mtvec <= csr_write_data; - else if (csr_write_addr == 12'h342) mcause <= csr_write_data; - end end endmodule \ No newline at end of file diff --git a/src/components/Control.v b/src/components/Control.v index 9bd03df..02d2bf8 100644 --- a/src/components/Control.v +++ b/src/components/Control.v @@ -5,6 +5,8 @@ module Control ( input [2:0] funct3, input funct7_5, input [11:0] csr, + input [63:0] pc, + input [63:0] sstatus, output reg [1:0] pc_src, // 00 pc+4 01 JALR 10 JAL output reg reg_write, // write register or not output reg alu_src_b, // 0 -> from register, 1 -> from imm @@ -15,15 +17,34 @@ module Control ( output reg b_type, // 1 -> beq, 0 -> bne output reg auipc, // is auipc or not output reg mem_read, + output reg [2:0] data_width, output reg jump, output reg [1:0] trap, // 00 no trap, 01 ecall, 10 unimp, 11 mret(标识跳转) output reg [11:0] csr_read_addr, output reg [11:0] csr_write_addr, output reg csr_write, - output reg csr_write_src, // 0 来自 data1 1 来自 ALU - output reg rev_imm // ALU 运算时是否对立即数取反 + output reg csr_write_src, // 0 来自 data1 1 来自 Control + output reg [63:0] csr_write_sstatus, + output reg [63:0] csr_write_scause, + output reg rev_imm, // ALU 运算时是否对立即数取反 + output reg alu_work_on_word ); `include "AluOp.vh" + `include "Opcodes.vh" + `include "Funct.vh" + + `define UNKNOWN_INST_TRAP trap = 2'b10; csr_read_addr = 12'h105; pc_src = 2'b11; csr_write_scause = 64'h2; + `define UNSUPPORTED_CSR csr != 12'h100 && csr != 12'h141 && csr != 12'h105 && csr != 12'h142 && csr != 12'h180 && csr != 12'h140 + + reg [1:0] priv; + wire spp; + + initial begin + priv = 2'b01; + end + + assign spp = sstatus[8]; + always @(*) begin pc_src = 0; reg_write = 0; @@ -42,91 +63,148 @@ module Control ( csr_read_addr = 0; csr_write_addr = 0; csr_write_src = 0; + alu_work_on_word = 0; case (op_code) - 7'b0000011: begin // lw + LUI: begin + reg_write = 1; mem_to_reg = 3'b001; + end + AUIPC: begin + reg_write = 1; alu_src_b = 1; alu_op = ADD; + auipc = 1; + end + JAL: begin + pc_src = 2'b10; reg_write = 1; mem_to_reg = 3'b010; + jump = 1; + end + JALR: begin + pc_src = 2'b01; reg_write = 1; mem_to_reg = 3'b010; + alu_src_b = 1; jump = 1; + end + BRANCH: begin + branch = 1; jump = 1; + case (funct3) + BEQ: begin alu_op = XOR; b_type = 1; end + BNE: begin alu_op = XOR; b_type = 0; end + BLT: begin alu_op = SLT; b_type = 0; end + BGE: begin alu_op = SLT; b_type = 1; end + BLTU: begin alu_op = SLTU; b_type = 0; end + BGEU: begin alu_op = SLTU; b_type = 1; end + default: begin + $display("\033[33mWarning: Unknown branch funct3! [pc: %h]\033[0m", pc); + `UNKNOWN_INST_TRAP + end + endcase + end + LOAD: begin reg_write = 1; alu_src_b = 1; alu_op = ADD; - mem_to_reg = 3'b011; mem_read = 1; + mem_to_reg = 3'b011; mem_read = 1; + data_width = funct3; end - 7'b0100011: begin // sw + STORE: begin alu_src_b = 1; alu_op = ADD; mem_write = 1; + data_width = funct3; end - 7'b0010011: begin // addi slti xori ori andi slli srli + OP_IMM: begin reg_write = 1; alu_src_b = 1; case (funct3) 3'b000: alu_op = ADD; + 3'b001: alu_op = SLL; 3'b010: alu_op = SLT; + 3'b011: alu_op = SLTU; 3'b100: alu_op = XOR; + 3'b101: begin + if (funct7_5) alu_op = SRA; + else alu_op = SRL; + end 3'b110: alu_op = OR; 3'b111: alu_op = AND; + endcase + end + OP: begin + reg_write = 1; + end + OP_IMM_32: begin // addiw sltiw ... + reg_write = 1; alu_src_b = 1; alu_work_on_word = 1; + case (funct3) + 3'b000: alu_op = ADD; 3'b001: alu_op = SLL; 3'b101: begin if (funct7_5) alu_op = SRA; else alu_op = SRL; end + default: begin + $display("\033[33mWarning: Unknown OP_IMM_32 funct3! [pc: %h]\033[0m", pc); + `UNKNOWN_INST_TRAP + end endcase end - 7'b1100011: begin // bne beq - branch = 1; jump = 1; + OP_32: begin // addw + reg_write = 1; alu_work_on_word = 1; case (funct3) - 3'b000: begin alu_op = XOR; b_type = 1; end // beq - 3'b001: begin alu_op = XOR; b_type = 0; end // bne - 3'b100: begin alu_op = SLT; b_type = 0; end // blt - 3'b101: begin alu_op = SLT; b_type = 1; end // bge - 3'b110: begin alu_op = SLTU; b_type = 0; end // bltu - 3'b111: begin alu_op = SLTU; b_type = 1; end // bgeu + 3'b000: begin + if (funct7_5) alu_op = SUB; + else alu_op = ADD; + end + 3'b001: alu_op = SLL; + 3'b101: begin + if (funct7_5) alu_op = SRA; + else alu_op = SRL; + end + default: begin + $display("\033[33mWarning: Unknown OP_32 funct3! [pc: %h]\033[0m", pc); + `UNKNOWN_INST_TRAP + end endcase end - 7'b1101111: begin // jal - pc_src = 2'b10; reg_write = 1; mem_to_reg = 3'b010; - jump = 1; - end - 7'b0110111: begin // lui - reg_write = 1; mem_to_reg = 3'b001; - end - 7'b0110011: begin // add slt and or sll srl sltu - reg_write = 1; - end - 7'b0010111: begin // auipc - reg_write = 1; alu_src_b = 1; alu_op = ADD; - auipc = 1; - end - 7'b1100111: begin // jalr - pc_src = 2'b01; reg_write = 1; mem_to_reg = 3'b010; - alu_src_b = 1; jump = 1; - end - 7'b1110011: begin // system + SYSTEM: begin // system case (funct3) - 3'b000: begin + COMMAND: begin case (csr) - 12'b000000000000: begin // ecall - trap = 2'b01; csr_read_addr = 12'h305; - pc_src = 2'b11; + ECALL: begin + trap = 2'b01; csr_read_addr = 12'h105; + pc_src = 2'b11; csr_write = 1; + if (priv == 2'b00) begin + csr_write_scause = 64'h8; priv = 2'b01; + csr_write_addr = 12'h100; csr_write_src = 1; + csr_write_sstatus = sstatus & 64'hfffffffffffeff; + end else if (priv == 2'b01) begin + csr_write_scause = 64'h9; priv = 2'b01; + end end - 12'b001100000010: begin // mret + SRET: begin trap = 2'b11; - csr_read_addr = 12'h341; pc_src = 2'b11; + csr_read_addr = 12'h141; pc_src = 2'b11; + if (!spp) begin + csr_write = 1; csr_write_addr = 12'h100; + csr_write_src = 1; priv = 2'b00; + csr_write_sstatus = sstatus & 64'hfffffffffffeff; + end else begin + priv = 2'b01; + end + end + SFENCE: begin end default: begin - trap = 2'b10; csr_read_addr = 12'h305; - pc_src = 2'b11; + $display("\033[33mWarning: Unknown SYSTEM instruction! [pc: %h]\033[0m", pc); + `UNKNOWN_INST_TRAP end endcase end - 3'b001: begin // csrrw - if (csr != 12'h300 && csr != 12'h341 && csr != 12'h305 && csr != 12'h342) begin - trap = 2'b10; csr_read_addr = 12'h305; - pc_src = 2'b11; + CSRRW: begin + if (`UNSUPPORTED_CSR) begin + $display("\033[33mWarning: Unsupported CSR number (%h)! [pc: %h]\033[0m", csr, pc); + `UNKNOWN_INST_TRAP end else begin csr_write = 1; csr_read_addr = csr; csr_write_addr = csr; csr_write_src = 0; reg_write = 1; mem_to_reg = 3'b100; end end - 3'b010: begin // csrrs - if (csr != 12'h300 && csr != 12'h341 && csr != 12'h305 && csr != 12'h342) begin - trap = 2'b10; csr_read_addr = 12'h305; - pc_src = 2'b11; + CSRRS: begin + if (`UNSUPPORTED_CSR) begin + $display("\033[33mWarning: Unsupported CSR number (%h)! [pc: %h]\033[0m", csr, pc); + `UNKNOWN_INST_TRAP end else begin // csr_write = 1; csr_read_addr = csr; // csr_write_addr = csr; csr_write_src = 1; @@ -137,30 +215,27 @@ module Control ( reg_write = 1; mem_to_reg = 3'b100; end end - // 3'b011: begin // csrrc + // CSRRC: begin // // csr_write = 1; csr_read_addr = csr; // // csr_write_addr = csr; csr_write_src = 1; // // alu_op = AND; alu_src_b = 2'b10; rev_imm = 1; // // reg_write = 1; mem_to_reg = 3'b100; // end - // 3'b101: begin // csrrwi - + // CSRRWI: begin // end - // 3'b110: begin // csrrsi - + // CSRRSI: begin // end - // 3'b111: begin // csrrci - + // CSRRCI: begin // end default: begin - trap = 2'b10; csr_read_addr = 12'h305; - pc_src = 2'b11; + $display("\033[33mWarning: Unsupported SYSTEM funct3! [pc: %h]\033[0m", pc); + `UNKNOWN_INST_TRAP end endcase end default: begin - trap = 2'b10; csr_read_addr = 12'h305; - pc_src = 2'b11; + $display("\033[33mWarning: Unknown opcode (%b)! [pc: %h]\033[0m", op_code, pc); + `UNKNOWN_INST_TRAP end endcase end diff --git a/src/components/Datapath.v b/src/components/Datapath.v deleted file mode 100644 index 117811b..0000000 --- a/src/components/Datapath.v +++ /dev/null @@ -1,107 +0,0 @@ -`timescale 1ns / 1ps - -module Datapath( - input clk, - input rst, - input [1:0] pc_src, // 00 -> from pc+4, 01 -> from JALR, 10 -> from JAL - input reg_write, // write register or not - input alu_src_b, // ALUsrc - input branch, // whether branch or not - input b_type, // 0 -> bne, 1 -> beq - input auipc, // whether auipc or not - input [3:0] alu_op, // ALU operation - input [1:0] mem_to_reg, // 00 -> from ALU, 01 -> from imm, 10 -> from pc+4, 11 -> from RAM - input [31:0] inst_in, // now instruction - input [31:0] data_in, // data from data memory - output [31:0] addr_out, // data memory address - output [31:0] data_out, // data to data memory - output [31:0] pc_out, // connect to instruction memory - input [4:0] debug_reg_addr, - output [31:0] debug_reg -); - reg [31:0] pc; - wire [31:0] pc_next; - wire [31:0] write_data, read_data_1, read_data_2; - wire [31:0] alu_data_1, alu_data_2, alu_result; - wire alu_zero; - wire [31:0] imm; - wire [31:0] jal_addr, jalr_addr; - - assign pc_out = pc; - assign addr_out = alu_result; - assign data_out = read_data_2; - - always @(posedge clk or posedge rst) begin - if (rst) begin - pc <= 32'b0; - end - else begin - pc <= pc_next; - end - end - - Regs regs ( - .clk(clk), - .rst(rst), - .we(reg_write), - .read_addr_1(inst_in[19:15]), - .read_addr_2(inst_in[24:20]), - .write_addr(inst_in[11:7]), - .write_data(write_data), - .read_data_1(read_data_1), - .read_data_2(read_data_2), - .debug_reg_addr(debug_reg_addr), - .debug_reg(debug_reg) - ); - - ImmGen immgen ( - .inst(inst_in), - .imm(imm) - ); - - Mux2x32 mux2x32_1 ( - .I0(read_data_1), - .I1(pc), - .s(auipc), - .o(alu_data_1) - ); - - Mux2x32 mux2x32_2 ( - .I0(read_data_2), - .I1(imm), - .s(alu_src_b), - .o(alu_data_2) - ); - - ALU alu ( - .a(alu_data_1), - .b(alu_data_2), - .alu_op(alu_op), - .res(alu_result), - .zero(alu_zero) - ); - - Mux4x32 mux4x32 ( - .I0(alu_result), - .I1(imm), - .I2(pc + 4), - .I3(data_in), - .s(mem_to_reg), - .o(write_data) - ); - - assign jal_addr = pc + imm; - assign jalr_addr = alu_result; - - MuxPC mux_pc ( - .I0(pc + 4), - .I1(jalr_addr), - .I2(jal_addr), - .I3(jal_addr), - .s(pc_src), - .branch(branch), - .b_type(b_type), - .alu_res(alu_result), - .o(pc_next) - ); -endmodule \ No newline at end of file diff --git a/src/components/ForwardingUnit.v b/src/components/ForwardingUnit.v index ca4b94f..1b6d24f 100644 --- a/src/components/ForwardingUnit.v +++ b/src/components/ForwardingUnit.v @@ -8,8 +8,8 @@ module ForwardingUnit( input [4:0] ID_EX_rs2, input EX_MEM_reg_write, input MEM_WB_reg_write, - input [1:0] EX_MEM_mem_to_reg, - input [1:0] MEM_WB_mem_to_reg, + input [2:0] EX_MEM_mem_to_reg, + input [2:0] MEM_WB_mem_to_reg, input auipc, input alu_src_b, output [2:0] ForwardA, // 00 来自寄存器,01 来自 EX/MEM,10 来自 MEM/WB,11 来自 PC @@ -28,13 +28,13 @@ module ForwardingUnit( forwardA <= 3'b011; end else begin if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs1) begin - if (EX_MEM_mem_to_reg == 2'b01) forwardA <= 3'b110; - else if (EX_MEM_mem_to_reg == 2'b10) forwardA <= 3'b100; - else forwardA <= 3'b001; + if (EX_MEM_mem_to_reg == 3'b001) forwardA <= 3'b110; + else if (EX_MEM_mem_to_reg == 3'b010) forwardA <= 3'b100; + else forwardA <= 3'b001; end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs1) begin - if (MEM_WB_mem_to_reg == 2'b01) forwardA <= 3'b111; - else if (MEM_WB_mem_to_reg == 2'b10) forwardA <= 3'b101; - else forwardA <= 3'b010; + if (MEM_WB_mem_to_reg == 3'b001) forwardA <= 3'b111; + else if (MEM_WB_mem_to_reg == 3'b010) forwardA <= 3'b101; + else forwardA <= 3'b010; end else begin forwardA <= 3'b000; end @@ -43,13 +43,13 @@ module ForwardingUnit( forwardB <= 3'b011; end else begin if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs2) begin - if (EX_MEM_mem_to_reg == 2'b01) forwardB <= 3'b110; - else if (EX_MEM_mem_to_reg == 2'b10) forwardB <= 3'b100; - else forwardB <= 3'b001; + if (EX_MEM_mem_to_reg == 3'b001) forwardB <= 3'b110; + else if (EX_MEM_mem_to_reg == 3'b010) forwardB <= 3'b100; + else forwardB <= 3'b001; end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs2) begin - if (MEM_WB_mem_to_reg == 2'b01) forwardB <= 3'b111; - else if (MEM_WB_mem_to_reg == 2'b10) forwardB <= 3'b101; - else forwardB <= 3'b010; + if (MEM_WB_mem_to_reg == 3'b001) forwardB <= 3'b111; + else if (MEM_WB_mem_to_reg == 3'b010) forwardB <= 3'b101; + else forwardB <= 3'b010; end else begin forwardB <= 3'b000; end diff --git a/src/components/ImmGen.v b/src/components/ImmGen.v index 1d4c833..55e19c4 100644 --- a/src/components/ImmGen.v +++ b/src/components/ImmGen.v @@ -2,37 +2,26 @@ module ImmGen( input [31:0] inst, - output [31:0] imm + output [63:0] imm ); `include "Opcodes.vh" reg [3:0] type; reg [31:0] out; - assign imm = out; + assign imm = {{32{out[31]}}, out[31:0]}; always @(*) begin case (inst[6:0]) - LW: type <= I; - SW: type <= S; - ADDI: type <= I; - BNE: type <= B; - BEQ: type <= B; - JAL: type <= J; - LUI: type <= U; - ADD: type <= R; - SLT: type <= R; - SLTI: type <= I; - ANDI: type <= I; - ORI: type <= I; - AND: type <= R; - OR: type <= R; - SLL: type <= R; - XORI: type <= I; - SLLI: type <= R; - SRLI: type <= R; - SRL: type <= R; - AUIPC: type <= U; - SLTU: type <= R; - JALR: type <= I; + LUI: type <= U; + AUIPC: type <= U; + JAL: type <= J; + BRANCH: type <= B; + LOAD: type <= I; + STORE: type <= S; + OP_IMM: type <= I; + OP: type <= R; + SYSTEM: type <= I; + OP_IMM_32: type <= I; + OP_32: type <= R; endcase case (type) R: out <= {{20{inst[31]}}, inst[31:20]}; diff --git a/src/components/MMU.v b/src/components/MMU.v new file mode 100644 index 0000000..cfaa583 --- /dev/null +++ b/src/components/MMU.v @@ -0,0 +1,66 @@ +`timescale 1ns / 1ps + +module MMU ( + input clk, + input rst, + input [63:0] inst_addr, + input [63:0] data_addr, + input [63:0] write_data, + input mem_write, + input mem_read, + input [2:0] width, + input [63:0] satp, + output [31:0] inst_out, + output [63:0] read_data, + output stall_pipeline, + output [7:0] sim_uart_char_out, + output sim_uart_char_valid +); + localparam SIM_UART_ADDR = 64'h10000000; + + wire finish_translation; + wire [63:0] addr1; + wire [63:0] addr2; + wire [63:0] data1; + wire [63:0] data2; + wire ram_we, need_trans1, need_trans2, need_trans; + + assign need_trans1 = (satp[63:60] != 0); + assign need_trans2 = (mem_read || mem_write) && (satp[63:60] != 0) && (data_addr != SIM_UART_ADDR); + assign need_trans = need_trans1 || need_trans2; + + assign ram_we = mem_write && (!need_trans || finish_translation); + + AddressTranslator addr_trans ( + .clk(clk), + .rst(rst), + .ram_en((mem_read || mem_write) && need_trans2), + .satp(satp), + .inst_addr(inst_addr), + .data_addr(data_addr), + .memory_data1(data1), + .memory_data2(data2), + .finish(finish_translation), + .memory_addr1(addr1), + .memory_addr2(addr2) + ); + + Memory memory ( + .clk(~clk), + .address1(addr1), + .width1(stall_pipeline ? 3'b011 : 3'b010), + .read_data1(data1), + .we2(ram_we), + .address2(need_trans ? addr2 : data_addr), + .width2(stall_pipeline ? 3'b011 : width), + .write_data2(write_data), + .read_data2(data2), + .sim_uart_char_out(sim_uart_char_out), + .sim_uart_char_valid(sim_uart_char_valid) + ); + + assign inst_out = data1[31:0]; + assign read_data = data2; + assign stall_pipeline = need_trans && !finish_translation; + +endmodule \ No newline at end of file diff --git a/src/components/Memory.v b/src/components/Memory.v new file mode 100644 index 0000000..c58aa88 --- /dev/null +++ b/src/components/Memory.v @@ -0,0 +1,73 @@ +`timescale 1ns / 1ps + +module Memory ( + input clk, + input [63:0] address1, + input [2:0] width1, + output [63:0] read_data1, + input we2, + input [63:0] write_data2, + input [63:0] address2, + input [2:0] width2, + output [63:0] read_data2, + output [7:0] sim_uart_char_out, + output sim_uart_char_valid +); + localparam SIM_UART_ADDR = 64'h10000000; + parameter START_ADDR = 2149580800; // 80200000 + parameter END_ADDR = 2151677952; // 80400000 + reg [7:0] memory [START_ADDR:END_ADDR]; + + initial begin + // $readmemh("tests/kernel/memory.hex", memory); + $readmemh("tests/PageTableSim/ram.hex", memory); + end + + always @(posedge clk) begin + if (we2 == 1 && (address2 != SIM_UART_ADDR)) begin + memory[address2] <= write_data2[7:0]; + if (width2[0] | width2[1]) memory[address2 + 1] <= write_data2[15:8]; + if (width2[1]) begin + memory[address2 + 2] <= write_data2[23:16]; + memory[address2 + 3] <= write_data2[31:24]; + end + if (width2[0] & width2[1]) begin + memory[address2 + 4] <= write_data2[39:32]; + memory[address2 + 5] <= write_data2[47:40]; + memory[address2 + 6] <= write_data2[55:48]; + memory[address2 + 7] <= write_data2[63:56]; + end + + // if (width2[0] & width2[1]) $display("%h: RAM[%h] <= %h", CoreSim.core.cpu.EX_MEM_pc, address2, write_data2); + // else if (width2[1]) $display("%h: RAM[%h] <= %h", CoreSim.core.cpu.EX_MEM_pc, address2, write_data2[31:0]); + // else if (width2[0]) $display("%h: RAM[%h] <= %h", CoreSim.core.cpu.EX_MEM_pc, address2, write_data2[15:0]); + // else $display("%h: RAM[%h] <= %h", CoreSim.core.cpu.EX_MEM_pc, address2, write_data2[7:0]); + end + end + + assign read_data2 = address2 == SIM_UART_ADDR ? 64'b0 : + (width2[0] & width2[1]) ? {memory[address2 + 7], memory[address2 + 6], memory[address2 + 5], memory[address2 + 4], memory[address2 + 3], memory[address2 + 2], memory[address2 + 1], memory[address2]} : + (width2[1]) ? {width2[2] ? 32'b0 : {32{memory[address2 + 3][7]}}, memory[address2 + 3], memory[address2 + 2], memory[address2 + 1], memory[address2]} : + (width2[0]) ? {width2[2] ? 48'b0 : {48{memory[address2 + 1][7]}}, memory[address2 + 1], memory[address2]} : + {width2[2] ? 56'b0 : {56{memory[address2][7]}}, memory[address2]}; + + assign read_data1 = address1 == SIM_UART_ADDR ? 64'b0 : + (width1[0] & width1[1]) ? {memory[address1 + 7], memory[address1 + 6], memory[address1 + 5], memory[address1 + 4], memory[address1 + 3], memory[address1 + 2], memory[address1 + 1], memory[address1]} : + (width1[1]) ? {width1[2] ? 32'b0 : {32{memory[address1 + 3][7]}}, memory[address1 + 3], memory[address1 + 2], memory[address1 + 1], memory[address1]} : + (width1[0]) ? {width1[2] ? 48'b0 : {48{memory[address1 + 1][7]}}, memory[address1 + 1], memory[address1]} : + {width1[2] ? 56'b0 : {56{memory[address1][7]}}, memory[address1]}; + + reg [7:0] uart_char; + reg uart_addr_valid; + + initial begin + uart_addr_valid <= 0; + end + assign sim_uart_char_valid = uart_addr_valid; + assign sim_uart_char_out = uart_char; + always @(posedge clk) begin + uart_addr_valid <= we2 && (address2 == SIM_UART_ADDR); + uart_char <= write_data2[7:0]; + if (sim_uart_char_valid) $write("%c", sim_uart_char_out); + end +endmodule \ No newline at end of file diff --git a/src/components/RegEXMEM.v b/src/components/RegEXMEM.v new file mode 100644 index 0000000..8ac0193 --- /dev/null +++ b/src/components/RegEXMEM.v @@ -0,0 +1,85 @@ +`timescale 1ns / 1ps + +module RegEXMEM ( + input clk, + input rst, + input en, + input [63:0] pc_EX, + input [1:0] pc_src_EX, + input [4:0] rd_EX, + input [63:0] imm_EX, + input [63:0] data2_EX, + input [63:0] alu_result_EX, + input [2:0] mem_to_reg_EX, + input reg_write_EX, + input branch_EX, + input b_type_EX, + input mem_write_EX, + input mem_read_EX, + input [2:0] data_width_EX, + input [11:0] csr_rd_EX, + input csr_write_EX, + input csr_write_src_EX, + input [63:0] csr_write_data_EX, + input [63:0] csr_read_data_EX, + output reg [63:0] pc_MEM, + output reg [1:0] pc_src_MEM, + output reg [4:0] rd_MEM, + output reg [63:0] imm_MEM, + output reg [63:0] data2_MEM, + output reg [63:0] alu_result_MEM, + output reg [2:0] mem_to_reg_MEM, + output reg reg_write_MEM, + output reg branch_MEM, + output reg b_type_MEM, + output reg mem_write_MEM, + output reg mem_read_MEM, + output reg [2:0] data_width_MEM, + output reg [11:0] csr_rd_MEM, + output reg csr_write_MEM, + output reg csr_write_src_MEM, + output reg [63:0] csr_write_data_MEM, + output reg [63:0] csr_read_data_MEM +); + always @(posedge clk or posedge rst) begin + if (rst) begin + pc_MEM <= 63'h0; + pc_src_MEM <= 2'h0; + rd_MEM <= 5'h0; + imm_MEM <= 63'h0; + data2_MEM <= 63'h0; + alu_result_MEM <= 63'h0; + mem_to_reg_MEM <= 3'h0; + reg_write_MEM <= 1'h0; + branch_MEM <= 1'h0; + b_type_MEM <= 1'h0; + mem_write_MEM <= 1'h0; + mem_read_MEM <= 1'h0; + data_width_MEM <= 3'h0; + csr_rd_MEM <= 12'h0; + csr_write_MEM <= 1'h0; + csr_write_src_MEM <= 1'h0; + csr_write_data_MEM <= 63'h0; + csr_read_data_MEM <= 63'h0; + end else if (en) begin + pc_MEM <= pc_EX; + pc_src_MEM <= pc_src_EX; + rd_MEM <= rd_EX; + imm_MEM <= imm_EX; + data2_MEM <= data2_EX; + alu_result_MEM <= alu_result_EX; + mem_to_reg_MEM <= mem_to_reg_EX; + reg_write_MEM <= reg_write_EX; + branch_MEM <= branch_EX; + b_type_MEM <= b_type_EX; + mem_write_MEM <= mem_write_EX; + mem_read_MEM <= mem_read_EX; + data_width_MEM <= data_width_EX; + csr_rd_MEM <= csr_rd_EX; + csr_write_MEM <= csr_write_EX; + csr_write_src_MEM <= csr_write_src_EX; + csr_write_data_MEM <= csr_write_data_EX; + csr_read_data_MEM <= csr_read_data_EX; + end + end +endmodule \ No newline at end of file diff --git a/src/components/RegIDEX.v b/src/components/RegIDEX.v new file mode 100644 index 0000000..5d518b9 --- /dev/null +++ b/src/components/RegIDEX.v @@ -0,0 +1,131 @@ +`timescale 1ns / 1ps + +module RegIDEX ( + input clk, + input rst, + input en, + input flush, + input [63:0] pc_ID, + input [1:0] pc_src_ID, + input [4:0] rs1_ID, + input [4:0] rs2_ID, + input [4:0] rd_ID, + input [63:0] data1_ID, + input [63:0] data2_ID, + input [63:0] imm_ID, + input [3:0] alu_op_ID, + input alu_src_ID, + input alu_work_on_word_ID, + input reg_write_ID, + input branch_ID, + input b_type_ID, + input auipc_ID, + input mem_write_ID, + input mem_read_ID, + input [2:0] mem_to_reg_ID, + input [2:0] data_width_ID, + input csr_write_ID, + input csr_write_src_ID, + input [11:0] csr_rd_ID, + input [63:0] csr_write_data_ID, + input [63:0] csr_read_data_ID, + output reg [63:0] pc_EX, + output reg [1:0] pc_src_EX, + output reg [4:0] rs1_EX, + output reg [4:0] rs2_EX, + output reg [4:0] rd_EX, + output reg [63:0] data1_EX, + output reg [63:0] data2_EX, + output reg [63:0] imm_EX, + output reg [3:0] alu_op_EX, + output reg alu_src_EX, + output reg alu_work_on_word_EX, + output reg reg_write_EX, + output reg branch_EX, + output reg b_type_EX, + output reg auipc_EX, + output reg mem_write_EX, + output reg mem_read_EX, + output reg [2:0] mem_to_reg_EX, + output reg [2:0] data_width_EX, + output reg csr_write_EX, + output reg csr_write_src_EX, + output reg [11:0] csr_rd_EX, + output reg [63:0] csr_write_data_EX, + output reg [63:0] csr_read_data_EX +); + always @(posedge clk or posedge rst) begin + if (rst) begin + pc_EX <= 63'h0; + pc_src_EX <= 2'h0; + rs1_EX <= 5'h0; + rs2_EX <= 5'h0; + rd_EX <= 5'h0; + data1_EX <= 64'h0; + data2_EX <= 64'h0; + imm_EX <= 64'h0; + alu_op_EX <= 2'h0; + alu_src_EX <= 2'h0; + alu_work_on_word_EX <= 1'h0; + reg_write_EX <= 1'h0; + branch_EX <= 1'h0; + b_type_EX <= 1'h0; + auipc_EX <= 1'h0; + mem_write_EX <= 1'h0; + mem_read_EX <= 1'h0; + mem_to_reg_EX <= 3'h0; + data_width_EX <= 3'h0; + csr_write_EX <= 1'h0; + csr_write_src_EX <= 1'h0; + csr_rd_EX <= 12'h0; + csr_write_data_EX <= 64'h0; + csr_read_data_EX <= 64'h0; + end else if (en) begin + if (flush) begin + pc_src_EX <= 2'h0; + rd_EX <= 5'h0; + reg_write_EX <= 1'h0; + mem_write_EX <= 1'h0; + mem_read_EX <= 1'h0; + data_width_EX <= 3'h0; + csr_write_EX <= 1'h0; + csr_write_src_EX <= 1'h0; + csr_rd_EX <= 12'h0; + pc_EX <= pc_ID; + data1_EX <= data1_ID; + data2_EX <= data2_ID; + imm_EX <= imm_ID; + rd_EX <= rd_ID; + rs1_EX <= rs1_ID; + rs2_EX <= rs2_ID; + csr_write_data_EX <= csr_write_data_ID; + csr_read_data_EX <= csr_read_data_ID; + end else begin + pc_EX <= pc_ID; + pc_src_EX <= pc_src_ID; + rs1_EX <= rs1_ID; + rs2_EX <= rs2_ID; + rd_EX <= rd_ID; + data1_EX <= data1_ID; + data2_EX <= data2_ID; + imm_EX <= imm_ID; + alu_op_EX <= alu_op_ID; + alu_src_EX <= alu_src_ID; + alu_work_on_word_EX <= alu_work_on_word_ID; + reg_write_EX <= reg_write_ID; + branch_EX <= branch_ID; + b_type_EX <= b_type_ID; + auipc_EX <= auipc_ID; + mem_write_EX <= mem_write_ID; + mem_read_EX <= mem_read_ID; + mem_to_reg_EX <= mem_to_reg_ID; + data_width_EX <= data_width_ID; + csr_write_EX <= csr_write_ID; + csr_write_src_EX <= csr_write_src_ID; + csr_rd_EX <= csr_rd_ID; + csr_write_data_EX <= csr_write_data_ID; + csr_read_data_EX <= csr_read_data_ID; + end + end + end +endmodule \ No newline at end of file diff --git a/src/components/RegIFID.v b/src/components/RegIFID.v new file mode 100644 index 0000000..6f20d86 --- /dev/null +++ b/src/components/RegIFID.v @@ -0,0 +1,34 @@ +`timescale 1ns / 1ps + +module RegIFID ( + input clk, + input rst, + input en, + input stall, + input flush, + input [63:0] pc_IF, + input [31:0] inst_IF, + output reg [63:0] pc_ID, + output reg [31:0] inst_ID +); + always @(posedge clk or posedge rst) begin + if (rst) begin + pc_ID <= 63'h80200000; + inst_ID <= 32'h0; + end else if (en) begin + if (stall) begin + pc_ID <= pc_ID; + inst_ID <= inst_ID; + end else if (flush) begin + pc_ID <= pc_ID; + inst_ID <= 32'h00000013; + end else begin + pc_ID <= pc_IF; + inst_ID <= inst_IF; + end + end else begin + pc_ID <= pc_ID; + inst_ID <= inst_ID; + end + end +endmodule \ No newline at end of file diff --git a/src/components/RegMEMWB.v b/src/components/RegMEMWB.v new file mode 100644 index 0000000..1c7508a --- /dev/null +++ b/src/components/RegMEMWB.v @@ -0,0 +1,61 @@ +`timescale 1ns / 1ps + +module RegMEMWB ( + input clk, + input rst, + input en, + input [63:0] pc_MEM, + input [63:0] imm_MEM, + input [63:0] data_in_MEM, + input [63:0] alu_result_MEM, + input [4:0] rd_MEM, + input reg_write_MEM, + input [2:0] mem_to_reg_MEM, + input csr_write_MEM, + input csr_write_src_MEM, + input [11:0] csr_rd_MEM, + input [63:0] csr_write_data_MEM, + input [63:0] csr_read_data_MEM, + output reg [63:0] pc_WB, + output reg [63:0] imm_WB, + output reg [63:0] data_in_WB, + output reg [63:0] alu_result_WB, + output reg [4:0] rd_WB, + output reg reg_write_WB, + output reg [2:0] mem_to_reg_WB, + output reg csr_write_WB, + output reg csr_write_src_WB, + output reg [11:0] csr_rd_WB, + output reg [63:0] csr_write_data_WB, + output reg [63:0] csr_read_data_WB +); + always @(posedge clk or posedge rst) begin + if (rst) begin + pc_WB <= 63'h0; + imm_WB <= 63'h0; + data_in_WB <= 63'h0; + alu_result_WB <= 63'h0; + rd_WB <= 5'h0; + reg_write_WB <= 1'h0; + mem_to_reg_WB <= 3'h0; + csr_write_WB <= 1'h0; + csr_write_src_WB <= 1'h0; + csr_rd_WB <= 12'h0; + csr_write_data_WB <= 63'h0; + csr_read_data_WB <= 63'h0; + end else if (en) begin + pc_WB <= pc_MEM; + imm_WB <= imm_MEM; + data_in_WB <= data_in_MEM; + alu_result_WB <= alu_result_MEM; + rd_WB <= rd_MEM; + reg_write_WB <= reg_write_MEM; + mem_to_reg_WB <= mem_to_reg_MEM; + csr_write_WB <= csr_write_MEM; + csr_write_src_WB <= csr_write_src_MEM; + csr_rd_WB <= csr_rd_MEM; + csr_write_data_WB <= csr_write_data_MEM; + csr_read_data_WB <= csr_read_data_MEM; + end + end +endmodule \ No newline at end of file diff --git a/src/components/Regs.v b/src/components/Regs.v index c39cf01..79dab3d 100644 --- a/src/components/Regs.v +++ b/src/components/Regs.v @@ -7,19 +7,25 @@ module Regs ( input [4:0] read_addr_1, input [4:0] read_addr_2, input [4:0] write_addr, - input [31:0] write_data, + input [63:0] write_data, input [4:0] debug_reg_addr, - output [31:0] read_data_1, - output [31:0] read_data_2, - output [31:0] debug_reg + output [63:0] read_data_1, + output [63:0] read_data_2, + output [63:0] debug_reg ); integer i; - reg [31:0] register [1:31]; // x1 - x31, x0 keeps zero + reg [63:0] register [1:31]; // x1 - x31, x0 keeps zero - genvar idx; - for (idx = 1; idx < 32; idx = idx + 1) begin - initial $dumpvars(0, register[idx]); - end + // genvar idx; + // for (idx = 1; idx < 32; idx = idx + 1) begin + // initial $dumpvars(0, register[idx]); + // end + + integer dump_file_descriptor; + + // initial begin + // dump_file_descriptor = $fopen("dut_changes.txt", "w"); + // end assign read_data_1 = (read_addr_1 == 0) ? 0 : register[read_addr_1]; // read assign read_data_2 = (read_addr_2 == 0) ? 0 : register[read_addr_2]; // read @@ -27,6 +33,11 @@ module Regs ( always @(negedge clk or posedge rst) begin if (rst == 1) for (i = 1; i < 32; i = i + 1) register[i] <= 0; // reset - else if (we == 1 && write_addr != 0) register[write_addr] <= write_data; + else if (we == 1 && write_addr != 0) begin + // if (register[write_addr] != write_data) begin + // $fwrite(dump_file_descriptor, "[%h] x%d 0x%h\n", CoreSim.core.cpu.MEM_WB_pc, write_addr, write_data); + // end + register[write_addr] <= write_data; + end end endmodule \ No newline at end of file diff --git a/src/dump_changes.py b/src/dump_changes.py new file mode 100644 index 0000000..e22cadb --- /dev/null +++ b/src/dump_changes.py @@ -0,0 +1,63 @@ +import gdb +import re + +class DumpChanges(gdb.Command): + def __init__(self): + super(DumpChanges, self).__init__("dump-changes", gdb.COMMAND_USER) + self.registers = [ + "ra", "sp", "gp", "tp", + "t0", "t1", "t2", + "fp", "s1", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", + "t3", "t4", "t5", "t6" + ] + self.reg_to_idx = {} + for i, reg in enumerate(self.registers): + self.reg_to_idx[reg] = i + 1 + self.regs = {} + self.watched = False + self.output = open("gdb_changes.txt", "w") + self.cnt = 0 + + def invoke(self, arg, from_tty): + length = 0 + if arg: + length = int(arg) + + if self.regs == {}: + res = gdb.execute("info registers", to_string=True) + self.regs = self.parse_registers(res) + + while True: + gdb.execute("si") + + res = gdb.execute("info registers", to_string=True) + regs = self.parse_registers(res) + + for reg in self.registers: + if regs[reg] != self.regs[reg]: + pc = self.regs["pc"][2:].zfill(16) + idx = str(self.reg_to_idx[reg]).rjust(2) + old = self.regs[reg][2:].zfill(16) + new = regs[reg][2:].zfill(16) + self.output.write(f"[{pc}] x{idx} 0x{new}\n") + self.cnt += 1 + self.regs = regs + + if self.cnt == length: + self.output.close() + break + + def parse_registers(self, res): + regs = {} + for line in res.split("\n"): + if line == "": + continue + match = re.findall(r"(.*?) +(.*?)\t", line) + if match == []: + continue + regs[match[0][0]] = match[0][1] + return regs + +DumpChanges() \ No newline at end of file diff --git a/src/headers/Funct.vh b/src/headers/Funct.vh new file mode 100644 index 0000000..09d3dd1 --- /dev/null +++ b/src/headers/Funct.vh @@ -0,0 +1,19 @@ +parameter BEQ = 3'b000, + BNE = 3'b001, + BLT = 3'b100, + BGE = 3'b101, + BLTU = 3'b110, + BGEU = 3'b111; + +parameter COMMAND = 3'b000, + CSRRW = 3'b001, + CSRRS = 3'b010, + CSRRC = 3'b011, + CSRRWI = 3'b101, + CSRRSI = 3'b110, + CSRRCI = 3'b111; + +parameter ECALL = 12'b000000000000, + MRET = 12'b001100000010, + SRET = 12'b000100000010, + SFENCE = 12'b000100100000; \ No newline at end of file diff --git a/src/headers/Opcodes.vh b/src/headers/Opcodes.vh index f454bb0..81e6b2a 100644 --- a/src/headers/Opcodes.vh +++ b/src/headers/Opcodes.vh @@ -1,27 +1,19 @@ -//`ifndef OPCODES_H -//`define OPCODES_H -parameter LW = 7'b0000011, - SW = 7'b0100011, - ADDI = 7'b0010011, - BNE = 7'b1100011, - BEQ = 7'b1100011, - JAL = 7'b1101111, - LUI = 7'b0110111, - ADD = 7'b0110011, - SLT = 7'b0110011, - SLTI = 7'b0010011, - ANDI = 7'b0010011, - ORI = 7'b0010011, - AND = 7'b0110011, - OR = 7'b0110011, - SLL = 7'b0110011, - XORI = 7'b0010011, - SLLI = 7'b0010011, - SRLI = 7'b0010011, - SRL = 7'b0110011, - AUIPC = 7'b0010111, - SLTU = 7'b0110011, - JALR = 7'b1100111; +// `ifndef OPCODES_H +// `define OPCODES_H + +parameter LOAD = 7'b0000011, + MISC_MEM = 7'b0001111, + OP_IMM = 7'b0010011, + AUIPC = 7'b0010111, + OP_IMM_32 = 7'b0011011, + STORE = 7'b0100011, + OP = 7'b0110011, + OP_32 = 7'b0111011, + LUI = 7'b0110111, + BRANCH = 7'b1100011, + JALR = 7'b1100111, + JAL = 7'b1101111, + SYSTEM = 7'b1110011; parameter R = 3'b000, I = 3'b001, @@ -29,4 +21,5 @@ parameter R = 3'b000, B = 3'b011, U = 3'b100, J = 3'b101; + //`endif \ No newline at end of file diff --git a/src/memory/RAM.v b/src/memory/RAM.v deleted file mode 100644 index 555b9d6..0000000 --- a/src/memory/RAM.v +++ /dev/null @@ -1,26 +0,0 @@ -`timescale 1ns / 1ps - -module RAM ( - input clk, - input we, - input [31:0] write_data, - input [10:0] address, - output [31:0] read_data -); - reg [31:0] ram [0:2047]; - - genvar idx; - for (idx = 0; idx < 512; idx = idx + 1) begin - initial $dumpvars(0, ram[idx]); - end - - initial begin - for (integer i = 0; i < 2048; i = i + 1) ram[i] <= 0; - end - - always @(posedge clk) begin - if (we == 1) ram[address] <= write_data; - end - - assign read_data = ram[address]; -endmodule \ No newline at end of file diff --git a/src/memory/ROM.v b/src/memory/ROM.v deleted file mode 100644 index 7ad9cda..0000000 --- a/src/memory/ROM.v +++ /dev/null @@ -1,14 +0,0 @@ -`timescale 1ns / 1ps - -module ROM ( - input [10:0] address, - output [31:0] out -); - reg [31:0] rom [0:2047]; - - initial begin - $readmemh("tests/PipelinePriviledged/advance.hex", rom); - end - - assign out = rom[address]; -endmodule diff --git a/src/tests/PageTableSim/ram.hex b/src/tests/PageTableSim/ram.hex new file mode 100644 index 0000000..2e3c26d --- /dev/null +++ b/src/tests/PageTableSim/ram.hex @@ -0,0 +1,20488 @@ +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +0c +08 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +10 +08 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0f +14 +08 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +de +c0 +fe +ca +af +be +ad +de diff --git a/src/tests/PipelineBranchPrediction/ram.hex b/src/tests/PipelineBranchPrediction/ram.hex new file mode 100644 index 0000000..a1ce4d5 --- /dev/null +++ b/src/tests/PipelineBranchPrediction/ram.hex @@ -0,0 +1,180 @@ + 65 + 72 + 72 + 6f + 72 + 0a + 00 + 00 + 20 + 00 + 00 + 00 + 0a + 00 + 00 + 00 + 00 + 00 + 00 + 00 + 02 + 00 + 00 + 00 + 0c + 00 + 00 + 00 + 0e + 00 + 00 + 00 + 06 + 00 + 00 + 00 + 0d + 00 + 00 + 00 + 0f + 00 + 00 + 00 + 10 + 00 + 00 + 00 + 0a + 00 + 00 + 00 + 00 + 00 + 00 + 00 + 12 + 00 + 00 + 00 + 0b + 00 + 00 + 00 + 13 + 00 + 00 + 00 + 09 + 00 + 00 + 00 + 01 + 00 + 00 + 00 + 07 + 00 + 00 + 00 + 05 + 00 + 00 + 00 + 04 + 00 + 00 + 00 + 03 + 00 + 00 + 00 + 08 + 00 + 00 + 00 + 11 + 00 + 00 + 00 + 07 + 00 + 00 + 00 + 03 + 00 + 00 + 00 + 00 + 00 + 00 + 00 + 0d + 00 + 00 + 00 + 02 + 00 + 00 + 00 + 06 + 00 + 00 + 00 + 05 + 00 + 00 + 00 + 09 + 00 + 00 + 00 + 0a + 00 + 00 + 00 + 04 + 00 + 00 + 00 + 12 + 00 + 00 + 00 + 0b + 00 + 00 + 00 + 0e + 00 + 00 + 00 + 10 + 00 + 00 + 00 + 01 + 00 + 00 + 00 + 11 + 00 + 00 + 00 + 13 + 00 + 00 + 00 + 0f + 00 + 00 + 00 + 08 + 00 + 00 + 00 + 0c + 00 + 00 + 00 diff --git a/src/tests/PipelineBranchPrediction/rom.hex b/src/tests/PipelineBranchPrediction/rom.hex new file mode 100644 index 0000000..bf7169d --- /dev/null +++ b/src/tests/PipelineBranchPrediction/rom.hex @@ -0,0 +1,236 @@ + 00000413 + 00009117 + ffc10113 + 1fc000ef + 00050463 + 00008067 + 80000537 + ff010113 + 40050513 + 00112623 + 1f8000ef + 00100513 + 1d4000ef + 01300593 + 04c50613 + 02058863 + 00050793 + 0007a703 + 0047a683 + 00e6d663 + 00d7a023 + 00e7a223 + 00478793 + fec794e3 + fff58593 + ffc60613 + fc059ce3 + 00008067 + 00450e93 + 00000e13 + 01400313 + 01300f93 + ffceaf03 + 000e0813 + 001e0e13 + 000e8793 + 000f0613 + 000e0713 + 0140006f + 00170713 + 011505b3 + 00478793 + 02670463 + 0007a683 + 00281893 + 00078593 + fed652e3 + 00070813 + 00170713 + 00068613 + 00478793 + fe6710e3 + feceae23 + 01e5a023 + 004e8e93 + fbfe12e3 + 00008067 + ff010113 + 00812423 + 00912223 + 01212023 + 00112623 + 00050413 + 05050913 + 800004b7 + 00042503 + 00440413 + 134000ef + 40848513 + 10c000ef + ff2416e3 + 00812403 + 00c12083 + 00412483 + 00012903 + 80000537 + 40c50513 + 01010113 + 0e80006f + ff010113 + 00912223 + 800004b7 + 41448513 + 00112623 + 00812423 + 01212023 + f8dff0ef + 41448513 + ed5ff0ef + 41448513 + f7dff0ef + 41448493 + 00000413 + 01400913 + 0004a503 + 00448493 + 40850533 + 00153513 + 00140413 + e85ff0ef + ff2414e3 + 00100513 + 80000437 + e75ff0ef + 46440513 + f41ff0ef + 46440513 + ec5ff0ef + 46440513 + 46440413 + f2dff0ef + 05040913 + 01300493 + 00042503 + 00440413 + 40950533 + 00153513 + e3dff0ef + fff48493 + ff2414e3 + 00100513 + e2dff0ef + 00c12083 + 00812403 + 00412483 + 00012903 + 00000513 + 01010113 + 00008067 + 0000006f + 80000537 + ff010113 + 41050513 + 00112623 + f25ff0ef + 0000006f + 00054783 + 00078c63 + 10000737 + 00f70023 + 00154783 + 00150513 + fe079ae3 + 00008067 + fe010113 + 00912a23 + 00112e23 + 00812c23 + 01212823 + 01312623 + 00900793 + 00050493 + 08a7da63 + 00100413 + 06300993 + 00241793 + 00878433 + 00050913 + 00a00593 + 00141413 + 07c000ef + ff29c4e3 + 00900993 + 10000937 + 00040593 + 00048513 + 064000ef + 00050793 + 00040593 + 00048513 + 00000713 + 00f9e663 + 03078793 + 0ff7f713 + 00e90023 + 0c4000ef + 00050493 + 00a00593 + 00040513 + 030000ef + 00050413 + fa051ee3 + 01c12083 + 01812403 + 01412483 + 01012903 + 00c12983 + 02010113 + 00008067 + 00100413 + f91ff06f + 06054063 + 0605c663 + 00058613 + 00050593 + fff00513 + 02060c63 + 00100693 + 00b67a63 + 00c05863 + 00161613 + 00169693 + feb66ae3 + 00000513 + 00c5e663 + 40c585b3 + 00d56533 + 0016d693 + 00165613 + fe0696e3 + 00008067 + 00008293 + fb5ff0ef + 00058513 + 00028067 + 40a00533 + 00b04863 + 40b005b3 + f9dff06f + 40b005b3 + 00008293 + f91ff0ef + 40a00533 + 00028067 + 00008293 + 0005ca63 + 00054c63 + f79ff0ef + 00058513 + 00028067 + 40b005b3 + fe0558e3 + 40a00533 + f61ff0ef + 40b00533 + 00028067 diff --git a/src/tests/RV64/Makefile b/src/tests/RV64/Makefile new file mode 100644 index 0000000..28359d4 --- /dev/null +++ b/src/tests/RV64/Makefile @@ -0,0 +1,23 @@ +CROSS := riscv64-unknown-elf- +FLAGS := -nostdlib -nostdinc -static -g -Ttext 0x0 -march=rv64i -mabi=lp64 +CC := $(CROSS)gcc +OBJDUMP := $(CROSS)objdump +OBJCOPY := $(CROSS)objcopy + +all: RV64I.elf RV64I.bin RV64I.dump RV64I.hex + +RV64I.elf: RV64I.s + $(CC) $(FLAGS) RV64I.s -o RV64I.elf + +RV64I.bin: RV64I.elf + $(OBJCOPY) -O binary RV64I.elf RV64I.bin + +RV64I.dump: RV64I.elf + $(OBJDUMP) -d RV64I.elf > RV64I.dump + +RV64I.hex: RV64I.bin + # xxd -p -c 4 RV64I.bin > RV64I.hex + od -t x4 -An -v RV64I.bin | python -c 'import sys, re; print(re.sub("[ \n]+", "\n", "".join(sys.stdin))[1:])' > RV64I.hex + +clean: + rm -f *.elf *.bin *.dump \ No newline at end of file diff --git a/src/tests/RV64/RV64I.hex b/src/tests/RV64/RV64I.hex new file mode 100644 index 0000000..6b962a4 --- /dev/null +++ b/src/tests/RV64/RV64I.hex @@ -0,0 +1,41 @@ +ffdeb0b7 +dbf0809b +00e09093 +bf308093 +00c09093 +bfb08093 +00e09093 +0de08093 +00247137 +8ad1011b +00e11113 +c4d10113 +00c11113 +5e710113 +00d11113 +ef010113 +002081b3 +40208233 +12308293 +0020a333 +0020b3b3 +1230a413 +1230b493 +0020f533 +0020e5b3 +0020c633 +1230f693 +1230e713 +1230c793 +00800193 +00309833 +0030d8b3 +4030d933 +00409993 +0040da13 +4040da93 +01234b17 +01602423 +00802b83 +0000006f + diff --git a/src/tests/RV64/RV64I.s b/src/tests/RV64/RV64I.s new file mode 100644 index 0000000..a1896f0 --- /dev/null +++ b/src/tests/RV64/RV64I.s @@ -0,0 +1,32 @@ +.section .text +.globl _start +_start: + li x1, 0xDEADBEEFCAFEC0DE + li x2, 0x123456789ABCDEF0 + add x3, x1, x2 + sub x4, x1, x2 + addi x5, x1, 0x123 + slt x6, x1, x2 + sltu x7, x1, x2 + slti x8, x1, 0x123 + sltiu x9, x1, 0x123 + and x10, x1, x2 + or x11, x1, x2 + xor x12, x1, x2 + andi x13, x1, 0x123 + ori x14, x1, 0x123 + xori x15, x1, 0x123 + li x3, 8 + sll x16, x1, x3 + srl x17, x1, x3 + sra x18, x1, x3 + slli x19, x1, 4 + srli x20, x1, 4 + srai x21, x1, 4 + auipc x22, 0x1234 + sw x22, 8(x0) + lw x23, 8(x0) +loop: + j loop + +# riscv64-unknown-elf-gcc -nostdlib -nostdinc -static -g -Ttext 0x0 -o RV64I.elf RV64I.asm -march=rv64i -mabi=lp64 \ No newline at end of file diff --git a/src/tests/kernel/.gitignore b/src/tests/kernel/.gitignore new file mode 100644 index 0000000..3999cd6 --- /dev/null +++ b/src/tests/kernel/.gitignore @@ -0,0 +1,13 @@ +.DS_Store +.gdb_history +*.o +gdb_changes.txt + +arch/riscv/boot/Image +build/ +vmlinux +vmlinux.asm +System.map +*.hex + +user/uapp.* \ No newline at end of file diff --git a/src/tests/kernel/Makefile b/src/tests/kernel/Makefile new file mode 100644 index 0000000..d465414 --- /dev/null +++ b/src/tests/kernel/Makefile @@ -0,0 +1,83 @@ +export +CROSS := riscv64-linux-gnu- +GCC := ${CROSS}gcc +LD := ${CROSS}ld +OBJCOPY := ${CROSS}objcopy +OBJDUMP := ${CROSS}objdump +DEBUG := 0 + +NAME=kernel +TARGET_DIR=build +ELF=${TARGET_DIR}/${NAME}.elf +BIN=${TARGET_DIR}/${NAME}.bin +DUMP=${TARGET_DIR}/${NAME}.dump +SIM=${TARGET_DIR}/sim.elf +COE=${TARGET_DIR}/${NAME}.coe +HEX=${TARGET_DIR}/${NAME}.hex + +ISA := rv64ifd +ABI := lp64d + +INCLUDE := -I "$(shell pwd)/include" -I "$(shell pwd)/arch/riscv/include" +CF := -g3 -march=$(ISA) -mabi=$(ABI) -mcmodel=medany \ + -fno-builtin -ffunction-sections -fdata-sections \ + -nostartfiles -nostdlib -nostdinc -static -lgcc -Wl,--nmagic -Wl,--gc-sections $(shell test ${DEBUG} -eq 1 && echo -DDEBUG) +LDFLAGS := -L $(shell dirname $(shell ${GCC} "-march=$(ISA)" -print-libgcc-file-name)) -lgcc +CFLAG := ${CF} ${INCLUDE} + +.PHONY:all run debug clean + +all: + ${MAKE} -C lib all + ${MAKE} -C init all + ${MAKE} -C user all + ${MAKE} -C arch/riscv all + @echo -e '\n'Build Finished OK + mkdir -p build + make $(ELF) + make $(BIN) + make $(DUMP) + make $(COE) + make $(HEX) + make sim + +run: all + @echo Launch the qemu ...... + @qemu-system-riscv64 -nographic -machine virt -kernel vmlinux -bios default + +debug: all + @echo Launch the qemu for debug ...... + @qemu-system-riscv64 -nographic -machine virt -kernel vmlinux -bios default -S -s + + +$(ELF): vmlinux + cp vmlinux $(ELF) + +$(BIN): $(ELF) + ${OBJCOPY} -O binary $(ELF) $(BIN) + +$(DUMP): $(ELF) + $(OBJDUMP) -d $^ > $@ + +$(COE): $(BIN) + od -t x4 -An -v $^ | python -c 'import sys, re; print("memory_initialization_radix=16;\nmemory_initialization_vector=" + re.sub("[ \n]+", ",", "".join(sys.stdin))[1:])' > $@ + +$(HEX): $(BIN) + od -t x4 -An -v $^ | python -c 'import sys, re; print(re.sub("[ \n]+", "\n", "".join(sys.stdin))[1:])' > $@ + +sim: $(HEX) + python write_sim_hex.py + python write_sim_hex_von.py + python write_sim_hex_von_split.py + +clean: + ${MAKE} -C lib clean + ${MAKE} -C init clean + ${MAKE} -C user clean + ${MAKE} -C arch/riscv clean + $(shell test -f vmlinux && rm vmlinux) + $(shell test -f vmlinux.asm && rm vmlinux.asm) + $(shell test -f System.map && rm System.map) + $(shell rm -rf boot) + $(shell rm -rf build) + @echo -e '\n'Clean Finished \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/Makefile b/src/tests/kernel/arch/riscv/Makefile new file mode 100644 index 0000000..cde0864 --- /dev/null +++ b/src/tests/kernel/arch/riscv/Makefile @@ -0,0 +1,12 @@ +all: + ${MAKE} -C kernel all + ${LD} -T kernel/vmlinux.lds kernel/*.o ../../init/*.o ../../lib/*.o ../../user/uapp.o $(LDFLAGS) -o ../../vmlinux + $(shell test -d boot || mkdir -p boot) + ${OBJCOPY} -O binary ../../vmlinux boot/Image + ${OBJDUMP} -S ../../vmlinux > ../../vmlinux.asm + nm ../../vmlinux > ../../System.map + +clean: + ${MAKE} -C kernel clean + $(shell test -d boot && rm -rf boot) + \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/include/clock.h b/src/tests/kernel/arch/riscv/include/clock.h new file mode 100644 index 0000000..af5c1cc --- /dev/null +++ b/src/tests/kernel/arch/riscv/include/clock.h @@ -0,0 +1,7 @@ +#ifndef _CLOCK_H +#define _CLOCK_H + +unsigned long get_cycles(); +void clock_set_next_event(); + +#endif \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/include/defs.h b/src/tests/kernel/arch/riscv/include/defs.h new file mode 100644 index 0000000..fd2a59b --- /dev/null +++ b/src/tests/kernel/arch/riscv/include/defs.h @@ -0,0 +1,58 @@ +#ifndef _DEFS_H +#define _DEFS_H + +#include "types.h" + +#define PHY_START 0x0000000080000000 +#define PHY_SIZE 4 * 1024 * 1024 +#define PHY_END (PHY_START + PHY_SIZE) + +#define PGSIZE 0x1000 // 4KB +#define PGROUNDUP(addr) ((addr + PGSIZE - 1) & (~(PGSIZE - 1))) // 向上取整 +#define PGROUNDDOWN(addr) (addr & (~(PGSIZE - 1))) // 向下取整 + +// #define DEBUG 1 + +#define csr_read(csr) \ +({ \ + register uint64 __v; \ + \ + asm volatile ("csrr %0, " #csr \ + : "=r"(__v)); \ + __v; \ +}) + +#define csr_write(csr, val) \ +({ \ + uint64 __v = (uint64)(val); \ + asm volatile ("csrw " #csr ", %0" \ + : \ + : "r" (__v) \ + : "memory"); \ +}) + +#define OPENSBI_SIZE (0x200000) + +#define VM_START (0xffffffe000000000) +#define VM_END (0xffffffff00000000) +#define VM_SIZE (VM_END - VM_START) + +#define PA2VA_OFFSET (VM_START - PHY_START) + +#define USER_START (0x0000000000000000) +#define USER_END (0x0000004000000000) + +#define PTE_V 0x001 +#define PTE_R 0x002 +#define PTE_W 0x004 +#define PTE_X 0x008 +#define PTE_U 0x010 +#define PTE_G 0x020 +#define PTE_A 0x040 +#define PTE_D 0x080 + +#define SYS_write 64 +#define SYS_getpid 172 +#define SYS_yield 124 + +#endif \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/include/mm.h b/src/tests/kernel/arch/riscv/include/mm.h new file mode 100644 index 0000000..88889bd --- /dev/null +++ b/src/tests/kernel/arch/riscv/include/mm.h @@ -0,0 +1,15 @@ +#ifndef __MM_H__ +#define __MM_H__ + +#include "types.h" + +struct run { + struct run *next; +}; + +void mm_init(); + +uint64 kalloc(); +void kfree(uint64); + +#endif \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/include/proc.h b/src/tests/kernel/arch/riscv/include/proc.h new file mode 100644 index 0000000..a40d990 --- /dev/null +++ b/src/tests/kernel/arch/riscv/include/proc.h @@ -0,0 +1,58 @@ +// arch/riscv/include/proc.h +#ifndef __PROC_H__ +#define __PROC_H__ + +#include "types.h" + +#define NR_TASKS (1 + 3) // 用于控制 最大线程数量 (idle 线程 + 3 内核线程) + +#define TASK_RUNNING 0 + +#define PRIORITY_MIN 1 +#define PRIORITY_MAX 5 + +/* 用于记录 `线程` 的 `内核栈与用户栈指针` */ +struct thread_info { + uint64 kernel_sp; + uint64 user_sp; +}; + +/* 线程状态段数据结构 */ +struct thread_struct { + uint64 ra; + uint64 sp; + uint64 s[12]; + uint64 sepc, sstatus, sscratch; +}; + +/* 线程数据结构 */ +struct task_struct { + struct thread_info* thread_info; + uint64 state; // 线程状态 + uint64 counter; // 运行剩余时间 + uint64 priority; // 运行优先级 + uint64 pid; // 线程id + + // + 40 bytes + struct thread_struct thread; + uint64 satp; + uint64 kernel_sp; + uint64 user_sp; +}; + +/* 线程初始化 创建 NR_TASKS 个线程 */ +void task_init(); + +/* 在时钟中断处理中被调用 用于判断是否需要进行调度 */ +void do_timer(); + +/* 调度程序 选择出下一个运行的线程 */ +void schedule(); + +/* 线程切换入口函数*/ +void switch_to(struct task_struct* next); + +/* dummy funciton: 一个循环程序,循环输出自己的 pid 以及一个自增的局部变量*/ +void dummy(); + +#endif \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/include/sbi.h b/src/tests/kernel/arch/riscv/include/sbi.h new file mode 100644 index 0000000..1b57bd5 --- /dev/null +++ b/src/tests/kernel/arch/riscv/include/sbi.h @@ -0,0 +1,18 @@ +#ifndef _SBI_H +#define _SBI_H + +#define SBI_PUTCHAR 0x1 +#define SBI_SET_TIMER 0x0 + +#include "types.h" + +struct sbiret { + long error; + long value; +}; + +struct sbiret sbi_ecall(int ext, int fid, uint64 arg0, + uint64 arg1, uint64 arg2, + uint64 arg3, uint64 arg4, + uint64 arg5); +#endif diff --git a/src/tests/kernel/arch/riscv/kernel/Makefile b/src/tests/kernel/arch/riscv/kernel/Makefile new file mode 100644 index 0000000..782a260 --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/Makefile @@ -0,0 +1,19 @@ +ASM_SRC = $(sort $(wildcard *.S)) +# wildcard 意思是找出所有的 .S 文件,sort 意思是对文件名进行排序,这样可以保证编译的顺序 +C_SRC = $(sort $(wildcard *.c)) +OBJ = $(patsubst %.S,%.o,$(ASM_SRC)) $(patsubst %.c,%.o,$(C_SRC)) +# patsubst 意思是将 .S 文件替换成 .o 文件,将 .c 文件替换成 .o 文件 + +all:$(OBJ) + + +%.o:%.S + ${GCC} ${CFLAG} -c $< +# $< 意思是依赖文件的名字,$@ 意思是目标文件的名字 +# -c 意思是只编译,不链接 + +%.o:%.c + ${GCC} ${CFLAG} -c $< + +clean: + $(shell rm *.o 2>/dev/null) \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/kernel/clock.c b/src/tests/kernel/arch/riscv/kernel/clock.c new file mode 100644 index 0000000..139b1c4 --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/clock.c @@ -0,0 +1,19 @@ +// #include "printk.h" +// #include "sbi.h" + +// unsigned long TIMECLOCK = 10000000; + +// unsigned long get_cycles() { +// unsigned long time; +// asm volatile("rdtime %0" : "=r"(time)); +// // printk("get_cycles() get time: %lx \n", time); +// return time; +// } + +// void clock_set_next_event() { +// uint64 current_time = get_cycles(); +// uint64 next = current_time + TIMECLOCK; +// // printk("clock_set_next_event() current_time: %lx, next: %lx \n", current_time, next); +// sbi_ecall(SBI_SET_TIMER, 0, next, 0, 0, 0, 0, 0); +// return; +// } \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/kernel/entry.S b/src/tests/kernel/arch/riscv/kernel/entry.S new file mode 100644 index 0000000..63101e3 --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/entry.S @@ -0,0 +1,166 @@ + .section .text.entry + .align 2 + .globl _traps +_traps: + csrr t0, sscratch + beq t0, x0, _ignore_switch + csrw sscratch, sp + mv sp, t0 +_ignore_switch: + # 1. save 32 registers and sepc to stack + addi sp, sp, -32*8 + sd x2, 8(sp) + sd x1, 0(sp) + sd x3, 16(sp) + sd x4, 24(sp) + sd x5, 32(sp) + sd x6, 40(sp) + sd x7, 48(sp) + sd x8, 56(sp) + sd x9, 64(sp) + sd x10, 72(sp) + sd x11, 80(sp) + sd x12, 88(sp) + sd x13, 96(sp) + sd x14, 104(sp) + sd x15, 112(sp) + sd x16, 120(sp) + sd x17, 128(sp) + sd x18, 136(sp) + sd x19, 144(sp) + sd x20, 152(sp) + sd x21, 160(sp) + sd x22, 168(sp) + sd x23, 176(sp) + sd x24, 184(sp) + sd x25, 192(sp) + sd x26, 200(sp) + sd x27, 208(sp) + sd x28, 216(sp) + sd x29, 224(sp) + sd x30, 232(sp) + sd x31, 240(sp) + csrr t0, sepc + sd t0, 248(sp) + + # 2. call trap_handler + csrr a0, scause + csrr a1, sepc + addi a2, sp, -8 + jal trap_handler + + # 3. restore sepc and 32 registers (x2(sp) should be restore last) from stack + ld t0, 248(sp) + csrw sepc, t0 + ld x31, 240(sp) + ld x30, 232(sp) + ld x29, 224(sp) + ld x28, 216(sp) + ld x27, 208(sp) + ld x26, 200(sp) + ld x25, 192(sp) + ld x24, 184(sp) + ld x23, 176(sp) + ld x22, 168(sp) + ld x21, 160(sp) + ld x20, 152(sp) + ld x19, 144(sp) + ld x18, 136(sp) + ld x17, 128(sp) + ld x16, 120(sp) + ld x15, 112(sp) + ld x14, 104(sp) + ld x13, 96(sp) + ld x12, 88(sp) + ld x11, 80(sp) + ld x10, 72(sp) + ld x9, 64(sp) + ld x8, 56(sp) + ld x7, 48(sp) + ld x6, 40(sp) + ld x5, 32(sp) + ld x4, 24(sp) + ld x3, 16(sp) + ld x1, 0(sp) + ld x2, 8(sp) + addi sp, sp, 32*8 + + csrr t0, sscratch + beq t0, x0, _traps_sret + csrw sscratch, sp + mv sp, t0 +_traps_sret: + # 4. return from trap + sret + + .global __dummy +__dummy: + # 将 sepc 设置为 dummy() 的地址, 并使用 sret 从中断中返回。 + # la t0, dummy + # # csrw sepc, t0 + # # sret + # mv ra, t0 + # ret + csrr t0, sscratch + csrw sscratch, sp + mv sp, t0 + csrw sepc, x0 + sret + + .globl __switch_to +__switch_to: + # __switch_to接受两个 task_struct 指针作为参数 + # 保存当前线程的ra, sp, s0~s11到当前线程的 thread_struct 中 + # 将下一个线程的 thread_struct 中的相关数据载入到ra, sp, s0~s11中。 + + # save state to prev process,注意 a0 是 task_struct, 而要存储的地方是 thread_struct + sd ra, 40(a0) + sd sp, 48(a0) + sd s0, 56(a0) + sd s1, 64(a0) + sd s2, 72(a0) + sd s3, 80(a0) + sd s4, 88(a0) + sd s5, 96(a0) + sd s6, 104(a0) + sd s7, 112(a0) + sd s8, 120(a0) + sd s9, 128(a0) + sd s10, 136(a0) + sd s11, 144(a0) + csrr t1, sepc + sd t1, 152(a0) + csrr t1, sstatus + sd t1, 160(a0) + csrr t1, sscratch + sd t1, 168(a0) + csrr t1, satp + sd t1, 176(a0) + + # restore state from next process + ld ra, 40(a1) + ld sp, 48(a1) + ld s0, 56(a1) + ld s1, 64(a1) + ld s2, 72(a1) + ld s3, 80(a1) + ld s4, 88(a1) + ld s5, 96(a1) + ld s6, 104(a1) + ld s7, 112(a1) + ld s8, 120(a1) + ld s9, 128(a1) + ld s10, 136(a1) + ld s11, 144(a1) + ld t1, 152(a1) + csrw sepc, t1 + ld t1, 160(a1) + csrw sstatus, t1 + ld t1, 168(a1) + csrw sscratch, t1 + ld t1, 176(a1) + csrw satp, t1 + sfence.vma zero, zero + + # return from trap + ret \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/kernel/head.S b/src/tests/kernel/arch/riscv/kernel/head.S new file mode 100644 index 0000000..0208332 --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/head.S @@ -0,0 +1,48 @@ +.extern start_kernel +.extern _traps +.extern mm_init +.extern task_init + + .section .text.init + .globl _start +_start: + lla sp, _stack + call setup_vm + call relocate + call mm_init + call setup_vm_final + call task_init + + la x1, _traps + csrrw x0, stvec, x1 + + addi x1, x0, 0x2 + csrrs x0, sstatus, x1 + + lla sp, _stack + j start_kernel + +relocate: + + li t1, 0xffffffe000000000; # VM_START + li t2, 0x0000000080000000 ; # PHY_START + sub t1, t1, t2 ; # t1 = PA2VA_OFFSET = VM_START - PHY_START + + add ra, ra, t1 ; # set ra = ra + PA2VA_OFFSET + add sp, sp, t1 ; # set sp = sp + PA2VA_OFFSET + + # set satp with _early_pgtbl + lla t3, early_pgtbl + li t4, 0x0FFFFFFF + and t3, t3, t4 + li t4, 0x80000000 + or t3, t3, t4 + srli t3, t3, 12; # PPN = PA >> 12 + li t1, 0x8000000000000000; + or t3, t1, t3; + csrw satp, t3; + # flush tlb + sfence.vma zero, zero + + ret + diff --git a/src/tests/kernel/arch/riscv/kernel/mm.c b/src/tests/kernel/arch/riscv/kernel/mm.c new file mode 100644 index 0000000..46e605b --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/mm.c @@ -0,0 +1,51 @@ +#include "defs.h" +#include "string.h" +#include "mm.h" +#include "printk.h" + +#include "printk.h" + +extern char _end[]; + +struct { + struct run *freelist; +} kmem; + +uint64 kalloc() { + struct run *r; + + r = kmem.freelist; + kmem.freelist = r->next; + + memset((void *)r, 0x0, PGSIZE); + return (uint64) r; +} + +void kfree(uint64 addr) { + struct run *r; + + // PGSIZE align + addr = addr & ~(PGSIZE - 1); + + // memset((void *)addr, 0x0, (uint64)PGSIZE); + + r = (struct run *)addr; + r->next = kmem.freelist; + kmem.freelist = r; + + return ; +} + +void kfreerange(char *start, char *end) { + char *addr = (char *)PGROUNDUP((uint64)start); + for (; (uint64)(addr) + PGSIZE <= (uint64)end; addr += PGSIZE) { + kfree((uint64)addr); + } +} + +void mm_init(void) +{ + Log("mm_init start"); + kfreerange(_end, (char *)(PHY_END + PA2VA_OFFSET)); + Log("mm_init done"); +} diff --git a/src/tests/kernel/arch/riscv/kernel/proc.c b/src/tests/kernel/arch/riscv/kernel/proc.c new file mode 100644 index 0000000..752946d --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/proc.c @@ -0,0 +1,162 @@ +//arch/riscv/kernel/proc.c + +#include "printk.h" +#include "mm.h" +#include "proc.h" +#include "rand.h" +#include "defs.h" + +extern void do_timer(void); +extern void schedule(void); +extern void __dummy(); +extern void __switch_to(struct task_struct* prev, struct task_struct* next); +extern void set_priority(); + +struct task_struct* idle; // idle process +struct task_struct* current; // 指向当前运行线程的 `task_struct` +struct task_struct* task[NR_TASKS]; // 线程数组,所有的线程都保存在此 + +extern unsigned long swapper_pg_dir[512] __attribute__((__aligned__(0x1000))); +extern void create_mapping(uint64 *root_pgtbl, uint64 va, uint64 pa, uint64 sz, int perm); +extern char uapp_start[], uapp_end[]; + +void task_init() { + Log("proc_init start"); + + idle = (struct task_struct*)kalloc(); + idle->state = TASK_RUNNING; + idle->counter = 0; + idle->priority = 0; + idle->pid = 0; + idle->thread.sp = (uint64)idle + PGSIZE; + current = idle; + task[0] = idle; + + for (int i = 1; i < NR_TASKS; i++) { + task[i] = (struct task_struct*)kalloc(); + task[i]->state = TASK_RUNNING; + task[i]->counter = 0; + task[i]->priority = rand(); + task[i]->pid = i; + } + + for (int i = 1; i < NR_TASKS; i++) { + task[i]->thread.ra = (uint64)__dummy; + task[i]->thread.sp = (uint64)task[i] + PGSIZE; + task[i]->kernel_sp = (uint64)task[i] + PGSIZE; + task[i]->user_sp = kalloc(); + uint64 *pgtbl = (uint64*)kalloc(); + memcpy(pgtbl, swapper_pg_dir, PGSIZE); + uint64 va = USER_START; + uint64 pa = (uint64)(uapp_start) - PA2VA_OFFSET; + create_mapping(pgtbl, va, pa, uapp_end - uapp_start, PTE_R | PTE_W | PTE_X | PTE_U | PTE_V); + va = USER_END - PGSIZE; + pa = (uint64)(task[i]->user_sp) - PA2VA_OFFSET; + create_mapping(pgtbl, va, pa, PGSIZE, PTE_R | PTE_W | PTE_U | PTE_V); + uint64 satp = csr_read(satp); + satp = (satp >> 44) << 44; + satp |= ((uint64)(pgtbl) - PA2VA_OFFSET) >> 12; + task[i]->satp = satp; + + task[i]->thread.sepc = USER_START; + uint64 sstatus = csr_read(sstatus); + sstatus &= ~(1 << 8); + sstatus |= (1 << 5); + sstatus |= (1 << 18); + task[i]->thread.sstatus = sstatus; + task[i]->thread.sscratch = USER_END; + } + Log("proc_init done"); + + set_priority(); + + return; +} + +void dummy() { + uint64 MOD = 1000000007; + uint64 auto_inc_local_var = 0; + int last_counter = -1; // 记录上一个counter + int last_last_counter = -1; // 记录上上个counter + while(1) { + if (last_counter == -1 || current->counter != last_counter) { + last_last_counter = last_counter; + last_counter = current->counter; + auto_inc_local_var = (auto_inc_local_var + 1) % MOD; + printk("[PID = %d] is running. auto_inc_local_var = %d\n", current->pid, auto_inc_local_var); + printk("Thread space begin at %lx\n", current); + } else if((last_last_counter == 0 || last_last_counter == -1) && last_counter == 1) { // counter恒为1的情况 + // 这里比较 tricky,不要求理解。 + last_counter = 0; + current->counter = 0; + } + #ifdef DEBUG + for (int i = 0; i < 100000000; i++); + #else + for (int i = 0; i < 1000; ++i); + #endif + do_timer(); + } +} + +// 更新当前线程的 counter,查看是否需要进行 schedule +void do_timer(void) { + if (current->counter > 0) { + current->counter--; + }else{ + schedule(); + for (int i = 0; i < NR_TASKS; i++) { + if (current == task[i]) { + asm("addi gp, %0, 0x100" :: "r"(i)); + } + } + } +} + +// 选择优先级最高的线程进行调度 +void schedule(void) { + uint64 min_priority = -1; + int min_priority_index = -1; + int all_zero = 1; + for (int i = 1; i < NR_TASKS; i++) { // 遍历 task 数组 + if (task[i]->counter > 0 && task[i]->priority < min_priority) { + all_zero = 0; + min_priority = task[i]->priority; + min_priority_index = i; + } + } + if (all_zero) { + for (int i = 1; i < NR_TASKS; i++) { + task[i]->counter = task[i]->priority; + } + for (int i = 1; i < NR_TASKS; i++) { + if (i == 1) printk("\n"); + Log("SET [PID = %lu, PRIORITY = %lu]", task[i]->pid, task[i]->priority, task[i]->counter); + if (task[i]->priority < min_priority) { + min_priority = task[i]->priority; + min_priority_index = i; + } + } + }else{ + } + switch_to(task[min_priority_index]); +} + +// 切换到 next 线程 +void switch_to(struct task_struct* next) { + Log("switch to [PID = %lu, PRIORITY = %lu]", next->pid, next->priority, next->counter); + if (current->pid != next->pid) { + //copy + struct task_struct* temp = current; + current = next; + __switch_to(temp, next); + } + return; +} + +void set_priority() { + task[1]->priority = 1; + task[2]->priority = 2; + task[3]->priority = 3; + Log("set_priority done"); +} \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/kernel/sbi.c b/src/tests/kernel/arch/riscv/kernel/sbi.c new file mode 100644 index 0000000..279790e --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/sbi.c @@ -0,0 +1,21 @@ +#include "types.h" +#include "sbi.h" + +struct sbiret sbi_ecall(int ext, int fid, uint64 arg0, uint64 arg1, uint64 arg2, + uint64 arg3, uint64 arg4, uint64 arg5) +{ + struct sbiret ret; + register uint64 a0 asm("a0") = (uint64)arg0; + register uint64 a1 asm("a1") = (uint64)arg1; + register uint64 a2 asm("a2") = (uint64)arg2; + register uint64 a3 asm("a3") = (uint64)arg3; + register uint64 a4 asm("a4") = (uint64)arg4; + register uint64 a5 asm("a5") = (uint64)arg5; + register uint64 a6 asm("a6") = (uint64)fid; + register uint64 a7 asm("a7") = (uint64)ext; + + asm volatile("ecall"); + ret.error = a0; + ret.value = a1; + return ret; +} diff --git a/src/tests/kernel/arch/riscv/kernel/trap.c b/src/tests/kernel/arch/riscv/kernel/trap.c new file mode 100644 index 0000000..bb91fdb --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/trap.c @@ -0,0 +1,48 @@ +#include "printk.h" +#include "clock.h" +#include "proc.h" +#include "defs.h" + +extern struct task_struct* current; +extern struct task_struct* task[NR_TASKS]; +extern void schedule(); + +struct pt_regs { + uint64 x[32]; + uint64 sepc; +}; + +void syscall(struct pt_regs* regs) { + if (regs->x[17] == SYS_write) { + if (regs->x[10] == 1) { + char* buf = (char*)regs->x[11]; + for (int i = 0; i < regs->x[12]; i++) { + printk("%c", buf[i]); + } + regs->x[10] = regs->x[12]; + } else { + printk("not support fd = %d\n", regs->x[10]); + regs->x[10] = -1; + } + } else if (regs->x[17] == SYS_getpid) { + regs->x[10] = current->pid; + } else if (regs->x[17] == SYS_yield) { + current->counter = 0; + schedule(); + } else { + printk("not support syscall id = %d\n", regs->x[17]); + } + regs->sepc += 4; +} + +void trap_handler(unsigned long scause, unsigned long sepc, struct pt_regs* regs) { + if ((scause >> 63) && (scause & 0x7FFFFFFFFFFFFFFF) == 5) { + Log("Supervisor Mode Timer Interrupt\n"); + } else { + if (scause == 8) { + syscall(regs); + return; + } + } + Log("Unhandled trap: scause: %lx, sepc: %lx \n", scause, sepc); +} \ No newline at end of file diff --git a/src/tests/kernel/arch/riscv/kernel/vm.c b/src/tests/kernel/arch/riscv/kernel/vm.c new file mode 100644 index 0000000..ee873ff --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/vm.c @@ -0,0 +1,92 @@ +// arch/riscv/kernel/vm.c + +extern unsigned long _stext; +extern unsigned long _srodata; +extern unsigned long _sdata; +extern unsigned long _sbsss; + +#include "defs.h" +#include +#include +#include "mm.h" +#include "printk.h" +#include "types.h" + +/* early_pgtbl: 用于 setup_vm 进行 1GB 的 映射。 */ +unsigned long early_pgtbl[512] __attribute__((__aligned__(0x1000))); + +void setup_vm(void) { + unsigned long* phy_early_pgtbl = ((unsigned long)early_pgtbl & 0x3FFFFFFF) + PHY_START; + phy_early_pgtbl[384] = ((unsigned long)(0x1 << 29)) | 0x000000000000000f; + phy_early_pgtbl[2] = ((unsigned long)(0x1 << 29)) | 0x000000000000000f; +} + +unsigned long *get_the_PTE_addr(unsigned long *root, unsigned long va) { + unsigned long *cur_ptes_page_addr = root; + unsigned long *cur_pte_addr; + for (int level = 2; level > 0; level--) { + if (level == 2) + cur_pte_addr = &cur_ptes_page_addr[(va >> 30) & 0x1ff]; + else if (level == 1) + cur_pte_addr = &cur_ptes_page_addr[(va >> 21) & 0x1ff]; + if ((*cur_pte_addr) & 0x1) + cur_ptes_page_addr = (unsigned long *)((((*cur_pte_addr) >> 10) << 12) + PA2VA_OFFSET); + else { + if ((cur_ptes_page_addr = (uint64 *)kalloc()) == NULL) { + Log("No space!"); + return NULL; + } + *cur_pte_addr = ((unsigned long)(*(cur_pte_addr)) & 0xffc0000000000000) | ((unsigned long)(((unsigned long)cur_ptes_page_addr - PA2VA_OFFSET) >> 12) << 10) | ((unsigned long)(0) | (unsigned long)(1)); + } + } + return &cur_ptes_page_addr[(va >> 12) & 0x1ff]; +} + +/* 创建多级页表映射关系 */ +void create_mapping(uint64 *pgtbl, uint64 va, uint64 pa, uint64 sz, int perm) { + Log("root: %lx, [%lx, %lx) -> [%lx, %lx), perm: %x", pgtbl, pa, pa+sz, va, va+sz, perm); + unsigned long va_now = va; + unsigned long pa_now = pa; + for (va_now = va; va_now < va + sz; pa_now += PGSIZE, va_now += PGSIZE) { + unsigned long *PTE_addr = get_the_PTE_addr(pgtbl, va_now); + *PTE_addr = ((unsigned long)(*(PTE_addr)) & 0xffc0000000000000) | ((unsigned long)(((unsigned long)pa_now) >> 12) << 10) | ((unsigned long)(perm) | (unsigned long)(1)); + } +} + +unsigned long swapper_pg_dir[512] __attribute__((__aligned__(0x1000))); + +void setup_vm_final(void) { + memset(swapper_pg_dir, 0x0, PGSIZE); + unsigned long *pgtbl = swapper_pg_dir; + + // No OpenSBI mapping required + unsigned long va = VM_START + OPENSBI_SIZE, pa = PHY_START + OPENSBI_SIZE; + // mapping kernel text X|-|R|V + unsigned long text_length = (unsigned long)(&(_srodata)) - (unsigned long)(&(_stext)); + create_mapping(pgtbl, va, pa, text_length, 0b1011); + va += text_length; + pa += text_length; + + // mapping kernel rodata -|-|R|V + unsigned long rodata_length = (unsigned long)(&(_sdata)) - (unsigned long)(&(_srodata)); + create_mapping(pgtbl, va, pa, rodata_length, 0b0011); + + va += rodata_length; + pa += rodata_length; + + // mapping other memory -|W|R|V + unsigned long left_length = PHY_SIZE - rodata_length - text_length - OPENSBI_SIZE; // 128 MB - rodata - text + create_mapping(pgtbl, va, pa, left_length, 0b0111); + + // set satp with swapper_pg_dir + unsigned long temp = ((unsigned long)pgtbl) - PA2VA_OFFSET; + temp = ((unsigned long)temp) >> 12; + temp = (0x000fffffffffff & temp) | 0x8000000000000000; + + csr_write(satp, temp); + Log("set satp to %lx", temp); + // flush TLB + asm volatile("sfence.vma zero, zero"); + + return; +} diff --git a/src/tests/kernel/arch/riscv/kernel/vmlinux.lds b/src/tests/kernel/arch/riscv/kernel/vmlinux.lds new file mode 100644 index 0000000..fe5baee --- /dev/null +++ b/src/tests/kernel/arch/riscv/kernel/vmlinux.lds @@ -0,0 +1,73 @@ +/* 目标架构 */ +OUTPUT_ARCH( "riscv" ) + +/* 程序入口 */ +ENTRY( _start ) + +MEMORY { + ram (wxa!ri): ORIGIN = 0x0000000080000000 + (0x200000), LENGTH = 128 * 1024 * 1024 - (0x200000) + ramv (wxa!ri): ORIGIN = (0xffffffe000000000) + (0x200000), LENGTH = ((0xffffffff00000000) - (0xffffffe000000000)) - (0x200000) +} + +/* kernel代码起始位置 */ +BASE_ADDR = (0xffffffe000000000) + (0x200000); + +SECTIONS +{ + /* . 代表当前地址 */ + . = BASE_ADDR; + + /* 记录kernel代码的起始地址 */ + _start = .; + + /* ALIGN(0x1000) 表示4KB对齐 */ + /* _stext, _etext 分别记录了text段的起始与结束地址 */ + .text : ALIGN(0x1000){ + _stext = .; + + *(.text.init) + *(.text.entry) + *(.text .text.*) + + _etext = .; + } >ramv AT>ram + + .rodata : ALIGN(0x1000){ + _srodata = .; + + *(.srodata .srodata.*) + *(.rodata .rodata.*) + + _erodata = .; + } >ramv AT>ram + + .data : ALIGN(0x1000){ + _sdata = .; + + *(.sdata .sdata*) + *(.data .data.*) + + _edata = .; + + . = ALIGN(0x1000); + uapp_start = .; + *(.uapp .uapp*) + uapp_end = .; + . = ALIGN(0x1000); + } >ramv AT>ram + + .bss : ALIGN(0x1000){ + _sbss = .; + + *(.bss.stack) + *(.sbss .sbss.*) + *(.bss .bss.*) + + _ebss = .; + } >ramv AT>ram + /* 记录kernel代码的结束地址 */ + . = ALIGN(0x1000); + _end = .; + . = ALIGN(0x4000); + _stack = .; +} \ No newline at end of file diff --git a/src/tests/kernel/debug.gdb b/src/tests/kernel/debug.gdb new file mode 100644 index 0000000..2b70051 --- /dev/null +++ b/src/tests/kernel/debug.gdb @@ -0,0 +1,37 @@ +dashboard -enable off +target remote localhost:1234 +b *0x80200000 +c +set var $ra=0 +set var $sp=0 +set var $gp=0 +set var $tp=0 +set var $t0=0 +set var $t1=0 +set var $t2=0 +set var $fp=0 +set var $s1=0 +set var $a0=0 +set var $a1=0 +set var $a2=0 +set var $a3=0 +set var $a4=0 +set var $a5=0 +set var $a6=0 +set var $a7=0 +set var $s2=0 +set var $s3=0 +set var $s4=0 +set var $s5=0 +set var $s6=0 +set var $s7=0 +set var $s8=0 +set var $s9=0 +set var $s10=0 +set var $s11=0 +set var $t3=0 +set var $t4=0 +set var $t5=0 +set var $t6=0 +source ../../dump_changes.py +dump-changes 411 \ No newline at end of file diff --git a/src/tests/kernel/include/printk.h b/src/tests/kernel/include/printk.h new file mode 100644 index 0000000..63c04cf --- /dev/null +++ b/src/tests/kernel/include/printk.h @@ -0,0 +1,9 @@ +#pragma once + +#include "stddef.h" + +int printk(const char *, ...); + +#define Log(format, ...) \ + printk("\33[1;35m[%s,%d,%s] " format "\33[0m\n", \ + __FILE__, __LINE__, __func__, ## __VA_ARGS__) diff --git a/src/tests/kernel/include/rand.h b/src/tests/kernel/include/rand.h new file mode 100644 index 0000000..925eb7e --- /dev/null +++ b/src/tests/kernel/include/rand.h @@ -0,0 +1,9 @@ +#ifndef __RAND_H__ +#define __RAND_H__ + +#include "types.h" + +#define SEED 13 +uint64 rand(); + +#endif \ No newline at end of file diff --git a/src/tests/kernel/include/stddef.h b/src/tests/kernel/include/stddef.h new file mode 100644 index 0000000..0443422 --- /dev/null +++ b/src/tests/kernel/include/stddef.h @@ -0,0 +1,15 @@ +#pragma once + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +typedef __WCHAR_TYPE__ wchar_t; + +#define NULL 0L +#define offsetof(type, member) __builtin_offsetof(type, member) + +typedef __builtin_va_list va_list; + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) diff --git a/src/tests/kernel/include/string.h b/src/tests/kernel/include/string.h new file mode 100644 index 0000000..8729ad5 --- /dev/null +++ b/src/tests/kernel/include/string.h @@ -0,0 +1,11 @@ +#ifndef _STRING_H +#define _STRING_H + +#pragma once + +#include "types.h" + +void* memset(void *, int, uint64); +void* memcpy(void *, const void *, uint64); + +#endif \ No newline at end of file diff --git a/src/tests/kernel/include/types.h b/src/tests/kernel/include/types.h new file mode 100644 index 0000000..46a6bca --- /dev/null +++ b/src/tests/kernel/include/types.h @@ -0,0 +1,6 @@ +#ifndef _TYPE_H +#define _TYPE_H + +typedef unsigned long uint64; + +#endif diff --git a/src/tests/kernel/init/Makefile b/src/tests/kernel/init/Makefile new file mode 100644 index 0000000..c35315c --- /dev/null +++ b/src/tests/kernel/init/Makefile @@ -0,0 +1,10 @@ +C_SRC = $(sort $(wildcard *.c)) +OBJ = $(patsubst %.c,%.o,$(C_SRC)) + +file = main.o +all:$(OBJ) + +%.o:%.c + ${GCC} ${CFLAG} -c $< +clean: + $(shell rm *.o 2>/dev/null) diff --git a/src/tests/kernel/init/main.c b/src/tests/kernel/init/main.c new file mode 100644 index 0000000..80b669f --- /dev/null +++ b/src/tests/kernel/init/main.c @@ -0,0 +1,17 @@ +#include "printk.h" +#include "types.h" +#include "sbi.h" + +extern void test(); +extern void schedule(); + +int start_kernel(uint64 input) { + + printk("2023 ZJU Computer System III\n"); + + schedule(); + + test(); // DO NOT DELETE !!! + + return 0; +} diff --git a/src/tests/kernel/init/test.c b/src/tests/kernel/init/test.c new file mode 100644 index 0000000..4092e0f --- /dev/null +++ b/src/tests/kernel/init/test.c @@ -0,0 +1,11 @@ +#include "printk.h" +#include "defs.h" + +// Please do not modify + +void test() { + unsigned long record_time = 0; + while (1) { + do_timer(); + } +} diff --git a/src/tests/kernel/lib/Makefile b/src/tests/kernel/lib/Makefile new file mode 100644 index 0000000..d06dca0 --- /dev/null +++ b/src/tests/kernel/lib/Makefile @@ -0,0 +1,10 @@ +C_SRC = $(sort $(wildcard *.c)) +OBJ = $(patsubst %.c,%.o,$(C_SRC)) + +all:$(OBJ) + +%.o:%.c + ${GCC} ${CFLAG} -c $< + +clean: + $(shell rm *.o 2>/dev/null) \ No newline at end of file diff --git a/src/tests/kernel/lib/printk.c b/src/tests/kernel/lib/printk.c new file mode 100644 index 0000000..bfcb327 --- /dev/null +++ b/src/tests/kernel/lib/printk.c @@ -0,0 +1,114 @@ +#include "printk.h" +#include "sbi.h" + +void putc(char c) { +#ifdef DEBUG + sbi_ecall(SBI_PUTCHAR, 0, c, 0, 0, 0, 0, 0); +#else + asm volatile("sb %0, 0(%1)" : : "r"(c), "r"(0x10000000)); +#endif +} + +static int vprintfmt(void(*putch)(char), const char *fmt, va_list vl) { + int in_format = 0, longarg = 0; + size_t pos = 0; + for( ; *fmt; fmt++) { + if (in_format) { + switch(*fmt) { + case 'l': { + longarg = 1; + break; + } + + case 'x': { + long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + + int hexdigits = 2 * (longarg ? sizeof(long) : sizeof(int)) - 1; + for(int halfbyte = hexdigits; halfbyte >= 0; halfbyte--) { + int hex = (num >> (4*halfbyte)) & 0xF; + char hexchar = (hex < 10 ? '0' + hex : 'a' + hex - 10); + putch(hexchar); + pos++; + } + longarg = 0; in_format = 0; + break; + } + + case 'd': { + long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + if (num < 0) { + num = -num; putch('-'); + pos++; + } + int bits = 0; + char decchar[25] = {'0', 0}; + for (long tmp = num; tmp; bits++) { + decchar[bits] = (tmp % 10) + '0'; + tmp /= 10; + } + + for (int i = bits; i >= 0; i--) { + putch(decchar[i]); + } + pos += bits + 1; + longarg = 0; in_format = 0; + break; + } + + case 'u': { + unsigned long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + int bits = 0; + char decchar[25] = {'0', 0}; + for (long tmp = num; tmp; bits++) { + decchar[bits] = (tmp % 10) + '0'; + tmp /= 10; + } + + for (int i = bits; i >= 0; i--) { + putch(decchar[i]); + } + pos += bits + 1; + longarg = 0; in_format = 0; + break; + } + + case 's': { + const char* str = va_arg(vl, const char*); + while (*str) { + putch(*str); + pos++; + str++; + } + longarg = 0; in_format = 0; + break; + } + + case 'c': { + char ch = (char)va_arg(vl,int); + putch(ch); + pos++; + longarg = 0; in_format = 0; + break; + } + default: + break; + } + } + else if(*fmt == '%') { + in_format = 1; + } else { + putch(*fmt); + pos++; + } + } + return pos; +} + +int printk(const char* s, ...) { + int res = 0; + va_list vl; + va_start(vl, s); + res = vprintfmt(putc, s, vl); + va_end(vl); + return res; +} diff --git a/src/tests/kernel/lib/rand.c b/src/tests/kernel/lib/rand.c new file mode 100644 index 0000000..860f96d --- /dev/null +++ b/src/tests/kernel/lib/rand.c @@ -0,0 +1,35 @@ +#include "rand.h" + +int initialize = 0; +int r[1000]; +int t = 0; + +uint64 rand() { + int i; + + if (initialize == 0) { + r[0] = SEED; + for (i = 1; i < 31; i++) { + r[i] = (16807LL * r[i - 1]) % 2147483647; + if (r[i] < 0) { + r[i] += 2147483647; + } + } + for (i = 31; i < 34; i++) { + r[i] = r[i - 31]; + } + for (i = 34; i < 344; i++) { + r[i] = r[i - 31] + r[i - 3]; + } + + initialize = 1; + } + + t = t % 656; + + r[t + 344] = r[t + 344 - 31] + r[t + 344 - 3]; + + t++; + + return (uint64)r[t - 1 + 344]; +} diff --git a/src/tests/kernel/lib/string.c b/src/tests/kernel/lib/string.c new file mode 100644 index 0000000..553b985 --- /dev/null +++ b/src/tests/kernel/lib/string.c @@ -0,0 +1,35 @@ +#include "string.h" + +void *memset(void *dst, int c, uint64 n) { + char *cdst = (char *)dst; + if (((uint64)cdst % 8 == 0) && (n % 8 == 0) && (c == 0)) { + for (uint64 i = 0; i < n / 8; ++i) + *((uint64 *)cdst + i) = 0LL; + } else { + for (uint64 i = 0; i < n; ++i) + cdst[i] = c; + } + + return dst; +} + +void *memcpy(void *dst, const void *src, uint64 n) { + char *cdst = (char *)dst; + const char *csrc = (const char *)src; + if (((uint64)cdst % 8 == 0) && ((uint64)csrc % 8 == 0) && (n % 8 == 0)) { + for (uint64 i = 0; i < n / 8; ++i) + *((uint64 *)cdst + i) = *((uint64 *)csrc + i); + } else { + for (uint64 i = 0; i < n; ++i) + cdst[i] = csrc[i]; + } + return dst; +} + +// void *memset(void *dst, int c, uint64 n) { +// char *cdst = (char *)dst; +// for (uint64 i = 0; i < n; ++i) +// cdst[i] = c; + +// return dst; +// } diff --git a/src/tests/kernel/user/Makefile b/src/tests/kernel/user/Makefile new file mode 100644 index 0000000..53509f0 --- /dev/null +++ b/src/tests/kernel/user/Makefile @@ -0,0 +1,24 @@ +ASM_SRC = $(filter-out uapp.S, $(sort $(wildcard *.S))) +C_SRC = $(sort $(wildcard *.c)) +OBJ = $(patsubst %.S,%.o,$(ASM_SRC)) $(patsubst %.c,%.o,$(C_SRC)) + +CFLAG = -march=$(ISA) -mabi=$(ABI) -mcmodel=medany -fno-builtin -ffunction-sections -fdata-sections -nostartfiles -nostdlib -nostdinc -static -lgcc -Wl,--nmagic $(shell test ${DEBUG} -eq 1 && echo -DDEBUG) + +all: uapp.o + +uapp.o: uapp.S uapp.bin + ${GCC} ${CFLAG} -c uapp.S + +%.o:%.c + ${GCC} ${CFLAG} -c $< + +%.o:%.S + ${GCC} ${CFLAG} -c $< + +uapp.bin: $(OBJ) + ${GCC} ${CFLAG} -fpie -T link.lds -o uapp.elf ${OBJ} /Users/crane/riscv64-toolchain/lib/gcc/riscv64-unknown-elf/8.3.0/rv64ifd/lp64d/libgcc.a + ${OBJCOPY} uapp.elf -O binary uapp.bin + ${OBJDUMP} -d uapp.elf > uapp.dump + +clean: + $(shell rm *.o uapp.o uapp.elf uapp.bin 2>/dev/null) diff --git a/src/tests/kernel/user/getpid.c b/src/tests/kernel/user/getpid.c new file mode 100644 index 0000000..ba52f41 --- /dev/null +++ b/src/tests/kernel/user/getpid.c @@ -0,0 +1,34 @@ +#include "syscall.h" +#include "stdio.h" + + +static inline long getpid() { + long ret; + asm volatile ("li a7, %1\n" + "ecall\n" + "mv %0, a0\n" + : "+r" (ret) + : "i" (SYS_GETPID)); + return ret; +} + +static inline long yield() { + asm volatile ("li a7, %0\n" + "ecall\n" + : : "i" (SYS_YIELD)); +} + +int main() { + register unsigned long current_sp __asm__("sp"); + while (1) { + printf("[U-MODE] pid: %ld, sp is %lx\n", getpid(), current_sp); + #ifdef DEBUG + for (unsigned int i = 0; i < 100000000; i++); + #else + for (unsigned int i = 0; i < 1000; i++); + #endif + yield(); + } + + return 0; +} diff --git a/src/tests/kernel/user/link.lds b/src/tests/kernel/user/link.lds new file mode 100644 index 0000000..7d766e3 --- /dev/null +++ b/src/tests/kernel/user/link.lds @@ -0,0 +1,31 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0x0; + _start = .; + + .text.init : { + *(.text.init) + } + + .text : { + *(.text, .text.*) + } + + .data : { + *(.data, .data.*) + } + + .rodata : { + *(.rodata, .rodata*) + } + + .bss : { + *(.bss, .bss.*) + } + + .debug : { + *(*) + } +} diff --git a/src/tests/kernel/user/printf.c b/src/tests/kernel/user/printf.c new file mode 100644 index 0000000..16d9567 --- /dev/null +++ b/src/tests/kernel/user/printf.c @@ -0,0 +1,130 @@ +#include "stdio.h" +#include "syscall.h" + +int tail = 0; +char buffer[1000] = {[0 ... 999] = 0}; + +void putc(char c) { + buffer[tail++] = (char)c; +} + +static int vprintfmt(void(*putch)(char), const char *fmt, va_list vl) { + int in_format = 0, longarg = 0; + size_t pos = 0; + for( ; *fmt; fmt++) { + if (in_format) { + switch(*fmt) { + case 'l': { + longarg = 1; + break; + } + + case 'x': { + long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + + int hexdigits = 2 * (longarg ? sizeof(long) : sizeof(int)) - 1; + for(int halfbyte = hexdigits; halfbyte >= 0; halfbyte--) { + int hex = (num >> (4*halfbyte)) & 0xF; + char hexchar = (hex < 10 ? '0' + hex : 'a' + hex - 10); + putch(hexchar); + pos++; + } + longarg = 0; in_format = 0; + break; + } + + case 'd': { + long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + if (num < 0) { + num = -num; putch('-'); + pos++; + } + int bits = 0; + char decchar[25] = {'0', 0}; + for (long tmp = num; tmp; bits++) { + decchar[bits] = (tmp % 10) + '0'; + tmp /= 10; + } + + if (bits == 0) bits ++; + + for (int i = bits - 1; i >= 0; i--) { + putch(decchar[i]); + } + pos += bits + 1; + longarg = 0; in_format = 0; + break; + } + + case 'u': { + unsigned long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + int bits = 0; + char decchar[25] = {'0', 0}; + for (long tmp = num; tmp; bits++) { + decchar[bits] = (tmp % 10) + '0'; + tmp /= 10; + } + + if (bits == 0) bits ++; + + for (int i = bits - 1; i >= 0; i--) { + putch(decchar[i]); + } + pos += bits - 1; + longarg = 0; in_format = 0; + break; + } + + case 's': { + const char* str = va_arg(vl, const char*); + while (*str) { + putch(*str); + pos++; + str++; + } + longarg = 0; in_format = 0; + break; + } + + case 'c': { + char ch = (char)va_arg(vl,int); + putch(ch); + pos++; + longarg = 0; in_format = 0; + break; + } + default: + break; + } + } + else if(*fmt == '%') { + in_format = 1; + } + else { + putch(*fmt); + pos++; + } + } + + long syscall_ret, fd = 1; + buffer[tail++] = '\0'; + asm volatile ("li a7, %1\n" + "mv a0, %2\n" + "mv a1, %3\n" + "mv a2, %4\n" + "ecall\n" + "mv %0, a0\n" + : "+r" (syscall_ret) + : "i" (SYS_WRITE), "r" (fd), "r" (&buffer), "r" (tail)); + return syscall_ret; +} + +int printf(const char* s, ...) { + int res = 0; + va_list vl; + va_start(vl, s); + tail = 0; + res = vprintfmt(putc, s, vl); + va_end(vl); + return res; +} diff --git a/src/tests/kernel/user/start.S b/src/tests/kernel/user/start.S new file mode 100644 index 0000000..868def5 --- /dev/null +++ b/src/tests/kernel/user/start.S @@ -0,0 +1,4 @@ + .section .text.init + .global _start +_start: + j main diff --git a/src/tests/kernel/user/stddef.h b/src/tests/kernel/user/stddef.h new file mode 100644 index 0000000..0443422 --- /dev/null +++ b/src/tests/kernel/user/stddef.h @@ -0,0 +1,15 @@ +#pragma once + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +typedef __WCHAR_TYPE__ wchar_t; + +#define NULL 0L +#define offsetof(type, member) __builtin_offsetof(type, member) + +typedef __builtin_va_list va_list; + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) diff --git a/src/tests/kernel/user/stdio.h b/src/tests/kernel/user/stdio.h new file mode 100644 index 0000000..fe9edb2 --- /dev/null +++ b/src/tests/kernel/user/stdio.h @@ -0,0 +1,13 @@ +#pragma once + +#include "stddef.h" + +#ifdef DEBUG_LOG +#define Log(format, ...) \ + printf("[%s:%d %s] " format "\n", __FILE__, __LINE__, __func__, ## __VA_ARGS__); +#else +#define Log(format, ...); +#endif + + +int printf(const char *, ...); diff --git a/src/tests/kernel/user/syscall.h b/src/tests/kernel/user/syscall.h new file mode 100644 index 0000000..1875560 --- /dev/null +++ b/src/tests/kernel/user/syscall.h @@ -0,0 +1,3 @@ +#define SYS_WRITE 64 +#define SYS_GETPID 172 +#define SYS_YIELD 124 \ No newline at end of file diff --git a/src/tests/kernel/write_sim_hex.py b/src/tests/kernel/write_sim_hex.py new file mode 100644 index 0000000..4cdac09 --- /dev/null +++ b/src/tests/kernel/write_sim_hex.py @@ -0,0 +1,30 @@ +import os +from pwn import * + +elf = ELF("build/kernel.elf", checksec=False) + +def write_rom(): + with open("build/kernel.hex", "r") as f: + lines = f.readlines() + text_lines = elf.get_section_by_name(".text").data_size // 4 + rom_lines = lines[:text_lines] + with open("rom.hex", "w") as f: + f.writelines(rom_lines) + +def write_ram(): + rodata = elf.get_section_by_name(".rodata").data() + rodata_size = elf.get_section_by_name(".rodata").data_size + assert(rodata_size == len(rodata)) + bss_size = elf.get_section_by_name(".bss").data_size + with open("ram.hex", "w") as f: + for byte in rodata: + f.write(hex(byte)[2:].zfill(2) + "\n") + for i in range(0x1000 - rodata_size): + f.write("00\n") + for i in range(bss_size): + f.write("00\n") + + +if __name__ == "__main__": + write_rom() + write_ram() \ No newline at end of file diff --git a/src/tests/kernel/write_sim_hex_von.py b/src/tests/kernel/write_sim_hex_von.py new file mode 100644 index 0000000..b32d3fe --- /dev/null +++ b/src/tests/kernel/write_sim_hex_von.py @@ -0,0 +1,44 @@ +import os +from pwn import * + +elf = ELF("build/kernel.elf", checksec=False) + +def align_to_page(size): + return (size + 0xfff) & ~0xfff + +def write_rom(): + with open("build/kernel.hex", "r") as f: + lines = f.readlines() + text_lines = elf.get_section_by_name(".text").data_size // 4 + rom_lines = lines[:text_lines] + with open("rom.hex", "w") as f: + f.writelines(rom_lines) + +def write_ram(): + text = elf.get_section_by_name(".text").data() + text_size = elf.get_section_by_name(".text").data_size + assert(text_size == len(text)) + text = text + b"\x00" * (align_to_page(text_size) - text_size) + + rodata = elf.get_section_by_name(".rodata").data() + rodata_size = elf.get_section_by_name(".rodata").data_size + assert(rodata_size == len(rodata)) + rodata = rodata + b"\x00" * (align_to_page(rodata_size) - rodata_size) + + data = elf.get_section_by_name(".data").data() + data_size = elf.get_section_by_name(".data").data_size + assert(data_size == len(data)) + data = data + b"\x00" * (align_to_page(data_size) - data_size) + + bss_size = elf.get_section_by_name(".bss").data_size + + with open("memory.hex", "w") as f: + for byte in text + rodata + data: + f.write(hex(byte)[2:].zfill(2) + "\n") + for i in range(bss_size): + f.write("00\n") + + +if __name__ == "__main__": + # write_rom() + write_ram() \ No newline at end of file diff --git a/src/tests/kernel/write_sim_hex_von_split.py b/src/tests/kernel/write_sim_hex_von_split.py new file mode 100644 index 0000000..6f18c9d --- /dev/null +++ b/src/tests/kernel/write_sim_hex_von_split.py @@ -0,0 +1,45 @@ +import os +from pwn import * + +elf = ELF("build/kernel.elf", checksec=False) + +def align_to_page(size): + return (size + 0xfff) & ~0xfff + +def write_rom(): + with open("build/kernel.hex", "r") as f: + lines = f.readlines() + text_lines = elf.get_section_by_name(".text").data_size // 4 + rom_lines = lines[:text_lines] + with open("rom.hex", "w") as f: + f.writelines(rom_lines) + +def write_ram(): + text = elf.get_section_by_name(".text").data() + text_size = elf.get_section_by_name(".text").data_size + assert(text_size == len(text)) + text = text + b"\x00" * (align_to_page(text_size) - text_size) + + rodata = elf.get_section_by_name(".rodata").data() + rodata_size = elf.get_section_by_name(".rodata").data_size + assert(rodata_size == len(rodata)) + rodata = rodata + b"\x00" * (align_to_page(rodata_size) - rodata_size) + + data = elf.get_section_by_name(".data").data() + data_size = elf.get_section_by_name(".data").data_size + assert(data_size == len(data)) + data = data + b"\x00" * (align_to_page(data_size) - data_size) + + bss_size = elf.get_section_by_name(".bss").data_size + + total = text + rodata + data + b"\x00" * bss_size + + for i in range(8): + with open(f"memory_{i}.hex", "w") as f: + for byte in total[i::8]: + f.write(hex(byte)[2:].zfill(2) + "\n") + + +if __name__ == "__main__": + # write_rom() + write_ram() \ No newline at end of file diff --git a/src/utils/Mux2x64.v b/src/utils/Mux2x64.v new file mode 100644 index 0000000..63ac80a --- /dev/null +++ b/src/utils/Mux2x64.v @@ -0,0 +1,10 @@ +`timescale 1ns / 1ps + +module Mux2x64( + input [63:0] I0, + input [63:0] I1, + input s, + output [63:0] o +); + assign o = s ? I1 : I0; +endmodule \ No newline at end of file diff --git a/src/utils/Mux4x64.v b/src/utils/Mux4x64.v new file mode 100644 index 0000000..dc6c146 --- /dev/null +++ b/src/utils/Mux4x64.v @@ -0,0 +1,21 @@ +`timescale 1ns / 1ps + +module Mux4x64( + input [63:0] I0, + input [63:0] I1, + input [63:0] I2, + input [63:0] I3, + input [1:0] s, + output [63:0] o +); + reg [63:0] out; + always @(*) begin + case (s) + 2'b00: out <= I0; + 2'b01: out <= I1; + 2'b10: out <= I2; + 2'b11: out <= I3; + endcase + end + assign o = out; +endmodule \ No newline at end of file diff --git a/src/utils/Mux8x64.v b/src/utils/Mux8x64.v new file mode 100644 index 0000000..60f6e22 --- /dev/null +++ b/src/utils/Mux8x64.v @@ -0,0 +1,29 @@ +`timescale 1ns / 1ps + +module Mux8x64( + input [63:0] I0, + input [63:0] I1, + input [63:0] I2, + input [63:0] I3, + input [63:0] I4, + input [63:0] I5, + input [63:0] I6, + input [63:0] I7, + input [2:0] s, + output [63:0] o +); + reg [63:0] out; + always @(*) begin + case (s) + 3'b000: out <= I0; + 3'b001: out <= I1; + 3'b010: out <= I2; + 3'b011: out <= I3; + 3'b100: out <= I4; + 3'b101: out <= I5; + 3'b110: out <= I6; + 3'b111: out <= I7; + endcase + end + assign o = out; +endmodule \ No newline at end of file diff --git a/src/utils/MuxPC.v b/src/utils/MuxPC.v index 7dae106..cb84c16 100644 --- a/src/utils/MuxPC.v +++ b/src/utils/MuxPC.v @@ -1,17 +1,17 @@ `timescale 1ns / 1ps module MuxPC( - input [31:0] I0, - input [31:0] I1, - input [31:0] I2, - input [31:0] I3, + input [63:0] I0, + input [63:0] I1, + input [63:0] I2, + input [63:0] I3, input [1:0] s, input branch, input b_type, // 0 bne, 1 beq - input [31:0] alu_res, - output [31:0] o + input [63:0] alu_res, + output [63:0] o ); - reg [31:0] out; + reg [63:0] out; always @(*) begin if (branch) begin if (b_type) begin diff --git a/src/wave.gtkw b/src/wave.gtkw index 9b3048d..2bd69aa 100644 --- a/src/wave.gtkw +++ b/src/wave.gtkw @@ -3,30 +3,121 @@ [*] [timestart] 0 [size] 1792 998 -[pos] 0 320 -*-26.755173 87929000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[pos] 0 373 +*-29.420895 7076584000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] CoreSim. [treeopen] CoreSim.core. [treeopen] CoreSim.core.cpu. -[treeopen] CoreSim.core.ram_unit. +[treeopen] CoreSim.core.mmu. +[treeopen] CoreSim.core.mmu.memory. [sst_width] 244 -[signals_width] 260 +[signals_width] 382 [sst_expanded] 1 [sst_vpaned_height] 308 @28 CoreSim.core.cpu.clk CoreSim.core.cpu.rst @22 -CoreSim.core.cpu.pc_out[31:0] +CoreSim.core.cpu.pc_out[63:0] +CoreSim.core.cpu.pc_next[63:0] CoreSim.core.cpu.inst[31:0] +CoreSim.core.cpu.IF_ID_pc[63:0] +CoreSim.core.cpu.IF_ID_inst[31:0] +CoreSim.core.cpu.ID_EX_pc[63:0] +CoreSim.core.cpu.EX_MEM_pc[63:0] +@c00022 +CoreSim.core.cpu.MEM_WB_pc[63:0] +@28 +(0)CoreSim.core.cpu.MEM_WB_pc[63:0] +(1)CoreSim.core.cpu.MEM_WB_pc[63:0] +(2)CoreSim.core.cpu.MEM_WB_pc[63:0] +(3)CoreSim.core.cpu.MEM_WB_pc[63:0] +(4)CoreSim.core.cpu.MEM_WB_pc[63:0] +(5)CoreSim.core.cpu.MEM_WB_pc[63:0] +(6)CoreSim.core.cpu.MEM_WB_pc[63:0] +(7)CoreSim.core.cpu.MEM_WB_pc[63:0] +(8)CoreSim.core.cpu.MEM_WB_pc[63:0] +(9)CoreSim.core.cpu.MEM_WB_pc[63:0] +(10)CoreSim.core.cpu.MEM_WB_pc[63:0] +(11)CoreSim.core.cpu.MEM_WB_pc[63:0] +(12)CoreSim.core.cpu.MEM_WB_pc[63:0] +(13)CoreSim.core.cpu.MEM_WB_pc[63:0] +(14)CoreSim.core.cpu.MEM_WB_pc[63:0] +(15)CoreSim.core.cpu.MEM_WB_pc[63:0] +(16)CoreSim.core.cpu.MEM_WB_pc[63:0] +(17)CoreSim.core.cpu.MEM_WB_pc[63:0] +(18)CoreSim.core.cpu.MEM_WB_pc[63:0] +(19)CoreSim.core.cpu.MEM_WB_pc[63:0] +(20)CoreSim.core.cpu.MEM_WB_pc[63:0] +(21)CoreSim.core.cpu.MEM_WB_pc[63:0] +(22)CoreSim.core.cpu.MEM_WB_pc[63:0] +(23)CoreSim.core.cpu.MEM_WB_pc[63:0] +(24)CoreSim.core.cpu.MEM_WB_pc[63:0] +(25)CoreSim.core.cpu.MEM_WB_pc[63:0] +(26)CoreSim.core.cpu.MEM_WB_pc[63:0] +(27)CoreSim.core.cpu.MEM_WB_pc[63:0] +(28)CoreSim.core.cpu.MEM_WB_pc[63:0] +(29)CoreSim.core.cpu.MEM_WB_pc[63:0] +(30)CoreSim.core.cpu.MEM_WB_pc[63:0] +(31)CoreSim.core.cpu.MEM_WB_pc[63:0] +(32)CoreSim.core.cpu.MEM_WB_pc[63:0] +(33)CoreSim.core.cpu.MEM_WB_pc[63:0] +(34)CoreSim.core.cpu.MEM_WB_pc[63:0] +(35)CoreSim.core.cpu.MEM_WB_pc[63:0] +(36)CoreSim.core.cpu.MEM_WB_pc[63:0] +(37)CoreSim.core.cpu.MEM_WB_pc[63:0] +(38)CoreSim.core.cpu.MEM_WB_pc[63:0] +(39)CoreSim.core.cpu.MEM_WB_pc[63:0] +(40)CoreSim.core.cpu.MEM_WB_pc[63:0] +(41)CoreSim.core.cpu.MEM_WB_pc[63:0] +(42)CoreSim.core.cpu.MEM_WB_pc[63:0] +(43)CoreSim.core.cpu.MEM_WB_pc[63:0] +(44)CoreSim.core.cpu.MEM_WB_pc[63:0] +(45)CoreSim.core.cpu.MEM_WB_pc[63:0] +(46)CoreSim.core.cpu.MEM_WB_pc[63:0] +(47)CoreSim.core.cpu.MEM_WB_pc[63:0] +(48)CoreSim.core.cpu.MEM_WB_pc[63:0] +(49)CoreSim.core.cpu.MEM_WB_pc[63:0] +(50)CoreSim.core.cpu.MEM_WB_pc[63:0] +(51)CoreSim.core.cpu.MEM_WB_pc[63:0] +(52)CoreSim.core.cpu.MEM_WB_pc[63:0] +(53)CoreSim.core.cpu.MEM_WB_pc[63:0] +(54)CoreSim.core.cpu.MEM_WB_pc[63:0] +(55)CoreSim.core.cpu.MEM_WB_pc[63:0] +(56)CoreSim.core.cpu.MEM_WB_pc[63:0] +(57)CoreSim.core.cpu.MEM_WB_pc[63:0] +(58)CoreSim.core.cpu.MEM_WB_pc[63:0] +(59)CoreSim.core.cpu.MEM_WB_pc[63:0] +(60)CoreSim.core.cpu.MEM_WB_pc[63:0] +(61)CoreSim.core.cpu.MEM_WB_pc[63:0] +(62)CoreSim.core.cpu.MEM_WB_pc[63:0] +(63)CoreSim.core.cpu.MEM_WB_pc[63:0] +@1401200 +-group_end +@800029 +CoreSim.core.cpu.control.priv[1:0] +@29 +(0)CoreSim.core.cpu.control.priv[1:0] +(1)CoreSim.core.cpu.control.priv[1:0] +@1001201 +-group_end @800200 -CSR @22 -CoreSim.core.cpu.csrs.mstatus[31:0] -CoreSim.core.cpu.csrs.mepc[31:0] -CoreSim.core.cpu.csrs.mtvec[31:0] -@25 -CoreSim.core.cpu.csrs.mcause[31:0] +CoreSim.core.cpu.csrs.sstatus[63:0] +CoreSim.core.cpu.csrs.sepc[63:0] +CoreSim.core.cpu.csrs.stvec[63:0] +@24 +CoreSim.core.cpu.csrs.scause[63:0] +@22 +CoreSim.core.cpu.csrs.satp[63:0] +CoreSim.core.cpu.csrs.sscratch[63:0] +@28 +CoreSim.core.cpu.csrs.trap[1:0] +CoreSim.core.cpu.csrs.we +@22 +CoreSim.core.cpu.csrs.csr_write_addr[11:0] +CoreSim.core.cpu.csrs.csr_write_data[63:0] @1000200 -CSR @c00200 @@ -38,93 +129,394 @@ CoreSim.core.cpu.forwarding.ForwardB[2:0] CoreSim.core.cpu.forwarding.ForwardC[1:0] @1401200 -DataHazard -@800200 +@c00200 -registers -@c00024 -CoreSim.core.cpu.regs.\register[1][31:0] -@28 -(0)CoreSim.core.cpu.regs.\register[1][31:0] -(1)CoreSim.core.cpu.regs.\register[1][31:0] -(2)CoreSim.core.cpu.regs.\register[1][31:0] -(3)CoreSim.core.cpu.regs.\register[1][31:0] -(4)CoreSim.core.cpu.regs.\register[1][31:0] -(5)CoreSim.core.cpu.regs.\register[1][31:0] -(6)CoreSim.core.cpu.regs.\register[1][31:0] -(7)CoreSim.core.cpu.regs.\register[1][31:0] -(8)CoreSim.core.cpu.regs.\register[1][31:0] -(9)CoreSim.core.cpu.regs.\register[1][31:0] -(10)CoreSim.core.cpu.regs.\register[1][31:0] -(11)CoreSim.core.cpu.regs.\register[1][31:0] -(12)CoreSim.core.cpu.regs.\register[1][31:0] -(13)CoreSim.core.cpu.regs.\register[1][31:0] -(14)CoreSim.core.cpu.regs.\register[1][31:0] -(15)CoreSim.core.cpu.regs.\register[1][31:0] -(16)CoreSim.core.cpu.regs.\register[1][31:0] -(17)CoreSim.core.cpu.regs.\register[1][31:0] -(18)CoreSim.core.cpu.regs.\register[1][31:0] -(19)CoreSim.core.cpu.regs.\register[1][31:0] -(20)CoreSim.core.cpu.regs.\register[1][31:0] -(21)CoreSim.core.cpu.regs.\register[1][31:0] -(22)CoreSim.core.cpu.regs.\register[1][31:0] -(23)CoreSim.core.cpu.regs.\register[1][31:0] -(24)CoreSim.core.cpu.regs.\register[1][31:0] -(25)CoreSim.core.cpu.regs.\register[1][31:0] -(26)CoreSim.core.cpu.regs.\register[1][31:0] -(27)CoreSim.core.cpu.regs.\register[1][31:0] -(28)CoreSim.core.cpu.regs.\register[1][31:0] -(29)CoreSim.core.cpu.regs.\register[1][31:0] -(30)CoreSim.core.cpu.regs.\register[1][31:0] -(31)CoreSim.core.cpu.regs.\register[1][31:0] +@c00022 ++{x1 / ra} CoreSim.core.cpu.regs.\register[1][63:0] +@28 +(0)CoreSim.core.cpu.regs.\register[1][63:0] +(1)CoreSim.core.cpu.regs.\register[1][63:0] +(2)CoreSim.core.cpu.regs.\register[1][63:0] +(3)CoreSim.core.cpu.regs.\register[1][63:0] +(4)CoreSim.core.cpu.regs.\register[1][63:0] +(5)CoreSim.core.cpu.regs.\register[1][63:0] +(6)CoreSim.core.cpu.regs.\register[1][63:0] +(7)CoreSim.core.cpu.regs.\register[1][63:0] +(8)CoreSim.core.cpu.regs.\register[1][63:0] +(9)CoreSim.core.cpu.regs.\register[1][63:0] +(10)CoreSim.core.cpu.regs.\register[1][63:0] +(11)CoreSim.core.cpu.regs.\register[1][63:0] +(12)CoreSim.core.cpu.regs.\register[1][63:0] +(13)CoreSim.core.cpu.regs.\register[1][63:0] +(14)CoreSim.core.cpu.regs.\register[1][63:0] +(15)CoreSim.core.cpu.regs.\register[1][63:0] +(16)CoreSim.core.cpu.regs.\register[1][63:0] +(17)CoreSim.core.cpu.regs.\register[1][63:0] +(18)CoreSim.core.cpu.regs.\register[1][63:0] +(19)CoreSim.core.cpu.regs.\register[1][63:0] +(20)CoreSim.core.cpu.regs.\register[1][63:0] +(21)CoreSim.core.cpu.regs.\register[1][63:0] +(22)CoreSim.core.cpu.regs.\register[1][63:0] +(23)CoreSim.core.cpu.regs.\register[1][63:0] +(24)CoreSim.core.cpu.regs.\register[1][63:0] +(25)CoreSim.core.cpu.regs.\register[1][63:0] +(26)CoreSim.core.cpu.regs.\register[1][63:0] +(27)CoreSim.core.cpu.regs.\register[1][63:0] +(28)CoreSim.core.cpu.regs.\register[1][63:0] +(29)CoreSim.core.cpu.regs.\register[1][63:0] +(30)CoreSim.core.cpu.regs.\register[1][63:0] +(31)CoreSim.core.cpu.regs.\register[1][63:0] @1401200 -group_end -@24 -CoreSim.core.cpu.regs.\register[2][31:0] -CoreSim.core.cpu.regs.\register[3][31:0] -CoreSim.core.cpu.regs.\register[4][31:0] -CoreSim.core.cpu.regs.\register[5][31:0] -CoreSim.core.cpu.regs.\register[6][31:0] -CoreSim.core.cpu.regs.\register[7][31:0] -CoreSim.core.cpu.regs.\register[8][31:0] -CoreSim.core.cpu.regs.\register[9][31:0] -CoreSim.core.cpu.regs.\register[10][31:0] -CoreSim.core.cpu.regs.\register[11][31:0] -CoreSim.core.cpu.regs.\register[12][31:0] -CoreSim.core.cpu.regs.\register[13][31:0] -CoreSim.core.cpu.regs.\register[14][31:0] -CoreSim.core.cpu.regs.\register[15][31:0] -CoreSim.core.cpu.regs.\register[16][31:0] -CoreSim.core.cpu.regs.\register[17][31:0] -CoreSim.core.cpu.regs.\register[18][31:0] -CoreSim.core.cpu.regs.\register[19][31:0] -CoreSim.core.cpu.regs.\register[20][31:0] -CoreSim.core.cpu.regs.\register[21][31:0] -CoreSim.core.cpu.regs.\register[22][31:0] -CoreSim.core.cpu.regs.\register[23][31:0] -CoreSim.core.cpu.regs.\register[24][31:0] -CoreSim.core.cpu.regs.\register[25][31:0] -CoreSim.core.cpu.regs.\register[26][31:0] -CoreSim.core.cpu.regs.\register[27][31:0] -CoreSim.core.cpu.regs.\register[28][31:0] -CoreSim.core.cpu.regs.\register[29][31:0] -CoreSim.core.cpu.regs.\register[30][31:0] -CoreSim.core.cpu.regs.\register[31][31:0] -@1000200 +@22 ++{x2 / sp} CoreSim.core.cpu.regs.\register[2][63:0] ++{x3 / gp} CoreSim.core.cpu.regs.\register[3][63:0] ++{x4 / tp} CoreSim.core.cpu.regs.\register[4][63:0] ++{x5 / t0} CoreSim.core.cpu.regs.\register[5][63:0] ++{x6 / t1} CoreSim.core.cpu.regs.\register[6][63:0] ++{x7 / t2} CoreSim.core.cpu.regs.\register[7][63:0] ++{x8 / s0 / fp} CoreSim.core.cpu.regs.\register[8][63:0] ++{x9 / s1} CoreSim.core.cpu.regs.\register[9][63:0] ++{x10 / a0} CoreSim.core.cpu.regs.\register[10][63:0] +@c00022 ++{x11 / a1} CoreSim.core.cpu.regs.\register[11][63:0] +@28 +(0)CoreSim.core.cpu.regs.\register[11][63:0] +(1)CoreSim.core.cpu.regs.\register[11][63:0] +(2)CoreSim.core.cpu.regs.\register[11][63:0] +(3)CoreSim.core.cpu.regs.\register[11][63:0] +(4)CoreSim.core.cpu.regs.\register[11][63:0] +(5)CoreSim.core.cpu.regs.\register[11][63:0] +(6)CoreSim.core.cpu.regs.\register[11][63:0] +(7)CoreSim.core.cpu.regs.\register[11][63:0] +(8)CoreSim.core.cpu.regs.\register[11][63:0] +(9)CoreSim.core.cpu.regs.\register[11][63:0] +(10)CoreSim.core.cpu.regs.\register[11][63:0] +(11)CoreSim.core.cpu.regs.\register[11][63:0] +(12)CoreSim.core.cpu.regs.\register[11][63:0] +(13)CoreSim.core.cpu.regs.\register[11][63:0] +(14)CoreSim.core.cpu.regs.\register[11][63:0] +(15)CoreSim.core.cpu.regs.\register[11][63:0] +(16)CoreSim.core.cpu.regs.\register[11][63:0] +(17)CoreSim.core.cpu.regs.\register[11][63:0] +(18)CoreSim.core.cpu.regs.\register[11][63:0] +(19)CoreSim.core.cpu.regs.\register[11][63:0] +(20)CoreSim.core.cpu.regs.\register[11][63:0] +(21)CoreSim.core.cpu.regs.\register[11][63:0] +(22)CoreSim.core.cpu.regs.\register[11][63:0] +(23)CoreSim.core.cpu.regs.\register[11][63:0] +(24)CoreSim.core.cpu.regs.\register[11][63:0] +(25)CoreSim.core.cpu.regs.\register[11][63:0] +(26)CoreSim.core.cpu.regs.\register[11][63:0] +(27)CoreSim.core.cpu.regs.\register[11][63:0] +(28)CoreSim.core.cpu.regs.\register[11][63:0] +(29)CoreSim.core.cpu.regs.\register[11][63:0] +(30)CoreSim.core.cpu.regs.\register[11][63:0] +(31)CoreSim.core.cpu.regs.\register[11][63:0] +(32)CoreSim.core.cpu.regs.\register[11][63:0] +(33)CoreSim.core.cpu.regs.\register[11][63:0] +(34)CoreSim.core.cpu.regs.\register[11][63:0] +(35)CoreSim.core.cpu.regs.\register[11][63:0] +(36)CoreSim.core.cpu.regs.\register[11][63:0] +(37)CoreSim.core.cpu.regs.\register[11][63:0] +(38)CoreSim.core.cpu.regs.\register[11][63:0] +(39)CoreSim.core.cpu.regs.\register[11][63:0] +(40)CoreSim.core.cpu.regs.\register[11][63:0] +(41)CoreSim.core.cpu.regs.\register[11][63:0] +(42)CoreSim.core.cpu.regs.\register[11][63:0] +(43)CoreSim.core.cpu.regs.\register[11][63:0] +(44)CoreSim.core.cpu.regs.\register[11][63:0] +(45)CoreSim.core.cpu.regs.\register[11][63:0] +(46)CoreSim.core.cpu.regs.\register[11][63:0] +(47)CoreSim.core.cpu.regs.\register[11][63:0] +(48)CoreSim.core.cpu.regs.\register[11][63:0] +(49)CoreSim.core.cpu.regs.\register[11][63:0] +(50)CoreSim.core.cpu.regs.\register[11][63:0] +(51)CoreSim.core.cpu.regs.\register[11][63:0] +(52)CoreSim.core.cpu.regs.\register[11][63:0] +(53)CoreSim.core.cpu.regs.\register[11][63:0] +(54)CoreSim.core.cpu.regs.\register[11][63:0] +(55)CoreSim.core.cpu.regs.\register[11][63:0] +(56)CoreSim.core.cpu.regs.\register[11][63:0] +(57)CoreSim.core.cpu.regs.\register[11][63:0] +(58)CoreSim.core.cpu.regs.\register[11][63:0] +(59)CoreSim.core.cpu.regs.\register[11][63:0] +(60)CoreSim.core.cpu.regs.\register[11][63:0] +(61)CoreSim.core.cpu.regs.\register[11][63:0] +(62)CoreSim.core.cpu.regs.\register[11][63:0] +(63)CoreSim.core.cpu.regs.\register[11][63:0] +@1401200 +-group_end +@22 ++{x12 / a2} CoreSim.core.cpu.regs.\register[12][63:0] ++{x13 / a3} CoreSim.core.cpu.regs.\register[13][63:0] ++{x14 / a4} CoreSim.core.cpu.regs.\register[14][63:0] ++{x15 / a5} CoreSim.core.cpu.regs.\register[15][63:0] +@c00022 ++{x16 / a6} CoreSim.core.cpu.regs.\register[16][63:0] +@28 +(0)CoreSim.core.cpu.regs.\register[16][63:0] +(1)CoreSim.core.cpu.regs.\register[16][63:0] +(2)CoreSim.core.cpu.regs.\register[16][63:0] +(3)CoreSim.core.cpu.regs.\register[16][63:0] +(4)CoreSim.core.cpu.regs.\register[16][63:0] +(5)CoreSim.core.cpu.regs.\register[16][63:0] +(6)CoreSim.core.cpu.regs.\register[16][63:0] +(7)CoreSim.core.cpu.regs.\register[16][63:0] +(8)CoreSim.core.cpu.regs.\register[16][63:0] +(9)CoreSim.core.cpu.regs.\register[16][63:0] +(10)CoreSim.core.cpu.regs.\register[16][63:0] +(11)CoreSim.core.cpu.regs.\register[16][63:0] +(12)CoreSim.core.cpu.regs.\register[16][63:0] +(13)CoreSim.core.cpu.regs.\register[16][63:0] +(14)CoreSim.core.cpu.regs.\register[16][63:0] +(15)CoreSim.core.cpu.regs.\register[16][63:0] +(16)CoreSim.core.cpu.regs.\register[16][63:0] +(17)CoreSim.core.cpu.regs.\register[16][63:0] +(18)CoreSim.core.cpu.regs.\register[16][63:0] +(19)CoreSim.core.cpu.regs.\register[16][63:0] +(20)CoreSim.core.cpu.regs.\register[16][63:0] +(21)CoreSim.core.cpu.regs.\register[16][63:0] +(22)CoreSim.core.cpu.regs.\register[16][63:0] +(23)CoreSim.core.cpu.regs.\register[16][63:0] +(24)CoreSim.core.cpu.regs.\register[16][63:0] +(25)CoreSim.core.cpu.regs.\register[16][63:0] +(26)CoreSim.core.cpu.regs.\register[16][63:0] +(27)CoreSim.core.cpu.regs.\register[16][63:0] +(28)CoreSim.core.cpu.regs.\register[16][63:0] +(29)CoreSim.core.cpu.regs.\register[16][63:0] +(30)CoreSim.core.cpu.regs.\register[16][63:0] +(31)CoreSim.core.cpu.regs.\register[16][63:0] +(32)CoreSim.core.cpu.regs.\register[16][63:0] +(33)CoreSim.core.cpu.regs.\register[16][63:0] +(34)CoreSim.core.cpu.regs.\register[16][63:0] +(35)CoreSim.core.cpu.regs.\register[16][63:0] +(36)CoreSim.core.cpu.regs.\register[16][63:0] +(37)CoreSim.core.cpu.regs.\register[16][63:0] +(38)CoreSim.core.cpu.regs.\register[16][63:0] +(39)CoreSim.core.cpu.regs.\register[16][63:0] +(40)CoreSim.core.cpu.regs.\register[16][63:0] +(41)CoreSim.core.cpu.regs.\register[16][63:0] +(42)CoreSim.core.cpu.regs.\register[16][63:0] +(43)CoreSim.core.cpu.regs.\register[16][63:0] +(44)CoreSim.core.cpu.regs.\register[16][63:0] +(45)CoreSim.core.cpu.regs.\register[16][63:0] +(46)CoreSim.core.cpu.regs.\register[16][63:0] +(47)CoreSim.core.cpu.regs.\register[16][63:0] +(48)CoreSim.core.cpu.regs.\register[16][63:0] +(49)CoreSim.core.cpu.regs.\register[16][63:0] +(50)CoreSim.core.cpu.regs.\register[16][63:0] +(51)CoreSim.core.cpu.regs.\register[16][63:0] +(52)CoreSim.core.cpu.regs.\register[16][63:0] +(53)CoreSim.core.cpu.regs.\register[16][63:0] +(54)CoreSim.core.cpu.regs.\register[16][63:0] +(55)CoreSim.core.cpu.regs.\register[16][63:0] +(56)CoreSim.core.cpu.regs.\register[16][63:0] +(57)CoreSim.core.cpu.regs.\register[16][63:0] +(58)CoreSim.core.cpu.regs.\register[16][63:0] +(59)CoreSim.core.cpu.regs.\register[16][63:0] +(60)CoreSim.core.cpu.regs.\register[16][63:0] +(61)CoreSim.core.cpu.regs.\register[16][63:0] +(62)CoreSim.core.cpu.regs.\register[16][63:0] +(63)CoreSim.core.cpu.regs.\register[16][63:0] +@1401200 +-group_end +@22 ++{x17 / a7} CoreSim.core.cpu.regs.\register[17][63:0] ++{x18 / s2} CoreSim.core.cpu.regs.\register[18][63:0] ++{x19 / s3} CoreSim.core.cpu.regs.\register[19][63:0] ++{x20 / s4} CoreSim.core.cpu.regs.\register[20][63:0] ++{x21 / s5} CoreSim.core.cpu.regs.\register[21][63:0] ++{x22 / s6} CoreSim.core.cpu.regs.\register[22][63:0] ++{x23 / s7} CoreSim.core.cpu.regs.\register[23][63:0] ++{x24 / s8} CoreSim.core.cpu.regs.\register[24][63:0] ++{x25 / s9} CoreSim.core.cpu.regs.\register[25][63:0] ++{x26 / s10} CoreSim.core.cpu.regs.\register[26][63:0] ++{x27 / s11} CoreSim.core.cpu.regs.\register[27][63:0] ++{x28 / t3} CoreSim.core.cpu.regs.\register[28][63:0] ++{x29 / t4} CoreSim.core.cpu.regs.\register[29][63:0] ++{x30 / t5} CoreSim.core.cpu.regs.\register[30][63:0] ++{x32 / t6} CoreSim.core.cpu.regs.\register[31][63:0] +@1401200 -registers +@800200 +-MMU +@28 +CoreSim.core.mmu.clk +@c00022 +CoreSim.core.mmu.inst_addr[63:0] +@28 +(0)CoreSim.core.mmu.inst_addr[63:0] +(1)CoreSim.core.mmu.inst_addr[63:0] +(2)CoreSim.core.mmu.inst_addr[63:0] +(3)CoreSim.core.mmu.inst_addr[63:0] +(4)CoreSim.core.mmu.inst_addr[63:0] +(5)CoreSim.core.mmu.inst_addr[63:0] +(6)CoreSim.core.mmu.inst_addr[63:0] +(7)CoreSim.core.mmu.inst_addr[63:0] +(8)CoreSim.core.mmu.inst_addr[63:0] +(9)CoreSim.core.mmu.inst_addr[63:0] +(10)CoreSim.core.mmu.inst_addr[63:0] +(11)CoreSim.core.mmu.inst_addr[63:0] +(12)CoreSim.core.mmu.inst_addr[63:0] +(13)CoreSim.core.mmu.inst_addr[63:0] +(14)CoreSim.core.mmu.inst_addr[63:0] +(15)CoreSim.core.mmu.inst_addr[63:0] +(16)CoreSim.core.mmu.inst_addr[63:0] +(17)CoreSim.core.mmu.inst_addr[63:0] +(18)CoreSim.core.mmu.inst_addr[63:0] +(19)CoreSim.core.mmu.inst_addr[63:0] +(20)CoreSim.core.mmu.inst_addr[63:0] +(21)CoreSim.core.mmu.inst_addr[63:0] +(22)CoreSim.core.mmu.inst_addr[63:0] +(23)CoreSim.core.mmu.inst_addr[63:0] +(24)CoreSim.core.mmu.inst_addr[63:0] +(25)CoreSim.core.mmu.inst_addr[63:0] +(26)CoreSim.core.mmu.inst_addr[63:0] +(27)CoreSim.core.mmu.inst_addr[63:0] +(28)CoreSim.core.mmu.inst_addr[63:0] +(29)CoreSim.core.mmu.inst_addr[63:0] +(30)CoreSim.core.mmu.inst_addr[63:0] +(31)CoreSim.core.mmu.inst_addr[63:0] +(32)CoreSim.core.mmu.inst_addr[63:0] +(33)CoreSim.core.mmu.inst_addr[63:0] +(34)CoreSim.core.mmu.inst_addr[63:0] +(35)CoreSim.core.mmu.inst_addr[63:0] +(36)CoreSim.core.mmu.inst_addr[63:0] +(37)CoreSim.core.mmu.inst_addr[63:0] +(38)CoreSim.core.mmu.inst_addr[63:0] +(39)CoreSim.core.mmu.inst_addr[63:0] +(40)CoreSim.core.mmu.inst_addr[63:0] +(41)CoreSim.core.mmu.inst_addr[63:0] +(42)CoreSim.core.mmu.inst_addr[63:0] +(43)CoreSim.core.mmu.inst_addr[63:0] +(44)CoreSim.core.mmu.inst_addr[63:0] +(45)CoreSim.core.mmu.inst_addr[63:0] +(46)CoreSim.core.mmu.inst_addr[63:0] +(47)CoreSim.core.mmu.inst_addr[63:0] +(48)CoreSim.core.mmu.inst_addr[63:0] +(49)CoreSim.core.mmu.inst_addr[63:0] +(50)CoreSim.core.mmu.inst_addr[63:0] +(51)CoreSim.core.mmu.inst_addr[63:0] +(52)CoreSim.core.mmu.inst_addr[63:0] +(53)CoreSim.core.mmu.inst_addr[63:0] +(54)CoreSim.core.mmu.inst_addr[63:0] +(55)CoreSim.core.mmu.inst_addr[63:0] +(56)CoreSim.core.mmu.inst_addr[63:0] +(57)CoreSim.core.mmu.inst_addr[63:0] +(58)CoreSim.core.mmu.inst_addr[63:0] +(59)CoreSim.core.mmu.inst_addr[63:0] +(60)CoreSim.core.mmu.inst_addr[63:0] +(61)CoreSim.core.mmu.inst_addr[63:0] +(62)CoreSim.core.mmu.inst_addr[63:0] +(63)CoreSim.core.mmu.inst_addr[63:0] +@1401200 +-group_end +@22 +CoreSim.core.mmu.inst_out[31:0] +CoreSim.core.mmu.data_addr[63:0] +CoreSim.core.mmu.read_data[63:0] +CoreSim.core.mmu.satp[63:0] +@28 +CoreSim.core.mmu.finish_translation +CoreSim.core.mmu.need_trans +CoreSim.core.mmu.stall_pipeline +@22 +CoreSim.core.mmu.addr1[63:0] +CoreSim.core.mmu.addr2[63:0] +CoreSim.core.mmu.data1[63:0] +CoreSim.core.mmu.data2[63:0] +@28 +CoreSim.core.mmu.mem_read +CoreSim.core.mmu.mem_write +CoreSim.core.mmu.need_trans1 +CoreSim.core.mmu.need_trans2 +@1000200 +-MMU +@c00200 +-AddrTrans +@22 +CoreSim.core.mmu.addr_trans.satp_mode[3:0] +@28 +CoreSim.core.mmu.addr_trans.clk +@22 +CoreSim.core.mmu.addr_trans.satp_ppn[43:0] +@28 +CoreSim.core.mmu.addr_trans.finish +@1401200 +-AddrTrans @c00200 -RAM +@28 +CoreSim.core.mmu.memory.clk @22 -CoreSim.core.ram_unit.\ram[0][31:0] -CoreSim.core.ram_unit.\ram[1][31:0] -CoreSim.core.ram_unit.\ram[2][31:0] -CoreSim.core.ram_unit.\ram[3][31:0] -CoreSim.core.ram_unit.\ram[4][31:0] -CoreSim.core.ram_unit.\ram[5][31:0] -CoreSim.core.ram_unit.\ram[6][31:0] -CoreSim.core.ram_unit.\ram[7][31:0] -CoreSim.core.ram_unit.\ram[8][31:0] -CoreSim.core.ram_unit.\ram[9][31:0] -CoreSim.core.ram_unit.\ram[10][31:0] +CoreSim.core.mmu.memory.address1[63:0] +CoreSim.core.mmu.memory.address2[63:0] +CoreSim.core.mmu.memory.read_data1[63:0] +CoreSim.core.mmu.memory.read_data2[63:0] +@28 +CoreSim.core.mmu.memory.width1[2:0] +CoreSim.core.mmu.memory.width2[2:0] +CoreSim.core.mmu.memory.we2 +@22 +CoreSim.core.mmu.memory.write_data2[63:0] +CoreSim.core.mmu.memory.sim_uart_char_out[7:0] +@28 +CoreSim.core.mmu.memory.sim_uart_char_valid @1401200 -RAM +@c00200 +-Trans1 +@28 +CoreSim.core.mmu.addr_trans.trans_state1[1:0] +@800028 +CoreSim.core.mmu.addr_trans.next_state1[1:0] +@28 +(0)CoreSim.core.mmu.addr_trans.next_state1[1:0] +(1)CoreSim.core.mmu.addr_trans.next_state1[1:0] +@1001200 +-group_end +@28 +CoreSim.core.mmu.addr_trans.finish1 +@22 +CoreSim.core.mmu.addr_trans.memory_addr1[63:0] +CoreSim.core.mmu.addr_trans.memory_data1[63:0] +CoreSim.core.mmu.addr_trans.pgoff_1[11:0] +CoreSim.core.mmu.addr_trans.pte_PPN0_1[8:0] +CoreSim.core.mmu.addr_trans.pte_PPN1_1[8:0] +CoreSim.core.mmu.addr_trans.pte_PPN2_1[25:0] +CoreSim.core.mmu.addr_trans.vpn0_1[8:0] +CoreSim.core.mmu.addr_trans.vpn1_1[8:0] +CoreSim.core.mmu.addr_trans.vpn2_1[8:0] +@1401200 +-Trans1 +@c00200 +-Trans2 +@28 +CoreSim.core.mmu.addr_trans.trans_state2[1:0] +CoreSim.core.mmu.addr_trans.next_state2[1:0] +CoreSim.core.mmu.addr_trans.finish2 +@22 +CoreSim.core.mmu.addr_trans.memory_addr2[63:0] +CoreSim.core.mmu.addr_trans.memory_data2[63:0] +CoreSim.core.mmu.addr_trans.pgoff_2[11:0] +CoreSim.core.mmu.addr_trans.pte_PPN0_2[8:0] +CoreSim.core.mmu.addr_trans.pte_PPN1_2[8:0] +CoreSim.core.mmu.addr_trans.pte_PPN2_2[25:0] +CoreSim.core.mmu.addr_trans.vpn0_2[8:0] +CoreSim.core.mmu.addr_trans.vpn1_2[8:0] +CoreSim.core.mmu.addr_trans.vpn2_2[8:0] +@1401200 +-Trans2 +@22 +CoreSim.core.cpu.EX_MEM_csr_write_data[63:0] +@28 +CoreSim.core.cpu.EX_MEM_csr_write +CoreSim.core.cpu.csrs.we +@22 +CoreSim.core.cpu.csrs.csr_write_addr[11:0] +CoreSim.core.cpu.csrs.csr_write_data[63:0] +@28 +CoreSim.core.cpu.csrs.clk [pattern_trace] 1 [pattern_trace] 0 diff --git a/src/wave_mmu.gtkw b/src/wave_mmu.gtkw new file mode 100644 index 0000000..4f839eb --- /dev/null +++ b/src/wave_mmu.gtkw @@ -0,0 +1,69 @@ +[*] +[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI +[*] +[timestart] 0 +[size] 1792 998 +[pos] 0 0 +*-13.057517 9880 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] MMUSim. +[treeopen] MMUSim.mmu. +[treeopen] MMUSim.mmu.addr_trans. +[sst_width] 250 +[signals_width] 317 +[sst_expanded] 1 +[sst_vpaned_height] 308 +@28 +MMUSim.clk +MMUSim.rst +@800200 +-MMU +@22 +MMUSim.mmu.data_addr[63:0] +MMUSim.mmu.satp[63:0] +@28 +MMUSim.mmu.finish_translation +MMUSim.mmu.stall_pipeline +@1000200 +-MMU +@800200 +-AddrTrans +@22 +MMUSim.mmu.addr_trans.satp_mode[3:0] +MMUSim.mmu.addr_trans.satp_ppn[43:0] +@28 +MMUSim.mmu.addr_trans.trans_state2[1:0] +MMUSim.mmu.addr_trans.next_state2[1:0] +@22 +MMUSim.mmu.addr_trans.memory_addr2[63:0] +MMUSim.mmu.addr_trans.memory_data2[63:0] +MMUSim.mmu.addr_trans.vpn0_2[8:0] +MMUSim.mmu.addr_trans.vpn1_2[8:0] +MMUSim.mmu.addr_trans.vpn2_2[8:0] +MMUSim.mmu.addr_trans.pte_PPN0_2[8:0] +MMUSim.mmu.addr_trans.pte_PPN1_2[8:0] +MMUSim.mmu.addr_trans.pte_PPN2_2[25:0] +@28 +MMUSim.mmu.addr_trans.pte_X_2 +MMUSim.mmu.addr_trans.pte_W_2 +MMUSim.mmu.addr_trans.pte_V_2 +@22 +MMUSim.mmu.addr_trans.pgoff_2[11:0] +@28 +MMUSim.mmu.addr_trans.finish +@1000200 +-AddrTrans +@800200 +-RAM +@1000200 +-RAM +@22 +MMUSim.mmu.memory.address2[63:0] +MMUSim.mmu.memory.read_data2[63:0] +@29 +MMUSim.mmu.memory.width2[2:0] +@800200 +-ROM +@1000200 +-ROM +[pattern_trace] 1 +[pattern_trace] 0