├── .gitignore ├── test-prog.hex ├── .gitmodules ├── src ├── rvbs │ ├── RVBS_VMTranslateTypes.bsv │ ├── RVBS_Types.bsv │ ├── RVBS_Ext_Zifencei.bsv │ ├── RVBS.bsv │ ├── RVBS_PMPTypes.bsv │ ├── RVBS_PMP.bsv │ ├── RVBS_Ext_64_M.bsv │ ├── RVBS_MemTypes.bsv │ ├── RVBS_Ext_32_M.bsv │ ├── RVBS_TraceUtils.bsv │ ├── RVBS_Ext_Zicsr.bsv │ ├── RVBS_Ext_64_C.bsv │ ├── RVBS_State.bsv │ ├── RVBS_BasicTypes.bsv │ ├── RVBS_TraceInsts.bsv │ ├── RVBS_Base_RV64I.bsv │ ├── RVBS_VMTranslate.bsv │ ├── RVBS_StateTypes.bsv │ ├── RVBS_RVCommon.bsv │ ├── RVBS_MemAccess.bsv │ ├── RVBS_CSRs.bsv │ ├── RVBS_Ext_32_C.bsv │ └── RVBS_Trap.bsv ├── RVBS_Core.bsv ├── toplevels │ ├── Top_cheri.bsv │ ├── Top_isa_test.bsv │ ├── Top_sim.bsv │ └── Top_rvfi_dii.bsv └── CLINT.bsv ├── dtb.hex ├── readme.md └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *.sched 2 | *.so 3 | *.elf 4 | *.dump 5 | *.ihex 6 | *.hex 7 | *.mif 8 | *.log 9 | *.trace 10 | *-bdir 11 | *-simdir 12 | test-traces 13 | .doit.db 14 | __pycache__ 15 | -------------------------------------------------------------------------------- /test-prog.hex: -------------------------------------------------------------------------------- 1 | 10000493 2 | 80004137 3 | 03C0006F 4 | FF810113 5 | 00112023 6 | 00912223 7 | C00024F3 8 | 00301013 9 | 00305013 10 | C00024F3 11 | 009064B3 12 | 009074B3 13 | 009044B3 14 | 00412483 15 | 00012083 16 | 00810113 17 | 00008067 18 | FFF48493 19 | FC5FF0EF 20 | 009484B3 21 | 409484B3 22 | FA0486E3 23 | FEDFF06F 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "BID"] 2 | path = BID 3 | url = https://github.com/CTSRD-CHERI/BID.git 4 | [submodule "BSV-RVFI-DII"] 5 | path = BSV-RVFI-DII 6 | url = https://github.com/CTSRD-CHERI/BSV-RVFI-DII.git 7 | [submodule "CHERISOC"] 8 | path = src/toplevels/CHERISOC 9 | url = https://github.com/CTSRD-CHERI/CHERISOC.git 10 | [submodule "cheri-cap-lib"] 11 | path = src/rvbs/cheri-cap-lib 12 | url = https://github.com/CTSRD-CHERI/cheri-cap-lib.git 13 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_VMTranslateTypes.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import RVBS_MemTypes :: *; 30 | 31 | typedef AddrLookup#(VAddr, PAddr) VMLookup; 32 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Types.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | package RVBS_Types; 30 | 31 | import RVBS_BasicTypes :: *; 32 | export RVBS_BasicTypes :: *; 33 | 34 | import RVBS_MemTypes :: *; 35 | export RVBS_MemTypes :: *; 36 | 37 | import RVBS_CSRTypes :: *; 38 | export RVBS_CSRTypes :: *; 39 | 40 | `ifdef PMP 41 | import RVBS_PMPTypes :: *; 42 | export RVBS_PMPTypes :: *; 43 | `endif 44 | 45 | `ifdef SUPERVISOR_MODE 46 | export RVBS_VMTranslateTypes :: *; 47 | import RVBS_VMTranslateTypes :: *; 48 | `endif 49 | 50 | import RVBS_StateTypes :: *; 51 | export RVBS_StateTypes :: *; 52 | 53 | endpackage 54 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_Zifencei.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import BID :: *; 30 | import BitPat :: *; 31 | import BlueUtils :: *; 32 | import RVBS_Types :: *; 33 | 34 | // funct3 = FENCE.I = 001 35 | // opcode = 0001111 36 | function Action instrFENCE_I(RVState s) = action 37 | //TODO 38 | printTLogPlusArgs("itrace", $format("pc: 0x%0x -- fence.i", s.pc)); 39 | endaction; 40 | 41 | module [ISADefModule] mkExt_Zifencei#(RVState s) (); 42 | defineInstEntry("fence.i", pat(n(4'b0000), n(4'b0000), n(4'b0000), n(5'b00000), n(3'b001), n(5'b00000), n(7'b0001111)), instrFENCE_I(s)); 43 | endmodule 44 | -------------------------------------------------------------------------------- /src/rvbs/RVBS.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | package RVBS; 30 | 31 | import RVBS_Types :: *; 32 | import RVBS_State :: *; 33 | import RVBS_Trap :: *; 34 | import RVBS_RVCommon :: *; 35 | import RVBS_MemAccess :: *; 36 | 37 | export RVBS_Types :: *; 38 | export RVBS_State :: *; 39 | export RVBS_Trap :: *; 40 | export RVBS_RVCommon :: *; 41 | export RVBS_MemAccess :: *; 42 | 43 | import RVBS_Base_RV32I :: *; 44 | export RVBS_Base_RV32I :: *; 45 | `ifdef RVZICSR 46 | import RVBS_Ext_Zicsr :: *; 47 | export RVBS_Ext_Zicsr :: *; 48 | `endif 49 | `ifdef RVZIFENCEI 50 | import RVBS_Ext_Zifencei :: *; 51 | export RVBS_Ext_Zifencei :: *; 52 | `endif 53 | `ifdef RVM 54 | import RVBS_Ext_32_M :: *; 55 | export RVBS_Ext_32_M :: *; 56 | `endif 57 | `ifdef RVC 58 | import RVBS_Ext_32_C :: *; 59 | export RVBS_Ext_32_C :: *; 60 | `endif 61 | `ifdef RVXCHERI 62 | import RVBS_Ext_Xcheri :: *; 63 | export RVBS_Ext_Xcheri :: *; 64 | `endif 65 | 66 | `ifdef XLEN64 67 | import RVBS_Base_RV64I :: *; 68 | export RVBS_Base_RV64I :: *; 69 | `ifdef RVM 70 | import RVBS_Ext_64_M :: *; 71 | export RVBS_Ext_64_M :: *; 72 | `endif 73 | `ifdef RVC 74 | import RVBS_Ext_64_C :: *; 75 | export RVBS_Ext_64_C :: *; 76 | `endif 77 | `endif 78 | 79 | endpackage 80 | -------------------------------------------------------------------------------- /src/RVBS_Core.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import RVBS :: *; 30 | import BlueBasics :: *; 31 | import BID :: *; 32 | 33 | ////////////////////// 34 | // Core RVBS module // 35 | //////////////////////////////////////////////////////////////////////////////// 36 | 37 | module [Module] mkRVBSCore#(RVState s, 38 | function ISADefModule#(Empty) init (RVState st), 39 | function ISADefModule#(Empty) iFetch (RVState st)) 40 | (BIDProbes); 41 | 42 | // instanciating simulator 43 | let modList = list(init, iFetch, mkRVCommon, mkRVTrap, mkBase_RV32I); 44 | `ifdef RVM 45 | modList = append(modList, list(mkExt_32_M)); 46 | `endif 47 | `ifdef RVC 48 | modList = append(modList, list(mkExt_32_C)); 49 | `endif 50 | `ifdef XLEN64 51 | modList = append(modList, list(mkBase_RV64I)); 52 | `ifdef RVM 53 | modList = append(modList, list(mkExt_64_M)); 54 | `endif 55 | `ifdef RVC 56 | modList = append(modList, list(mkExt_64_C)); 57 | `endif 58 | `endif 59 | `ifdef RVZICSR 60 | modList = append(modList, list(mkExt_Zicsr)); 61 | `endif 62 | `ifdef RVZIFENCEI 63 | modList = append(modList, list(mkExt_Zifencei)); 64 | `endif 65 | `ifdef RVXCHERI 66 | modList = append(modList, list(mkExt_Xcheri)); 67 | `endif 68 | let bid_probes <- mkISASim(s, modList); 69 | 70 | return bid_probes; 71 | 72 | endmodule 73 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_PMPTypes.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import DefaultValue :: *; 30 | import ConfigReg :: *; 31 | import Vector :: *; 32 | 33 | import RVBS_MemTypes :: *; 34 | 35 | typedef enum { 36 | OFF = 2'b00, TOR = 2'b01, NA4 = 2'b10, NAPOT = 2'b11 37 | } AddrMatchMode deriving (Bits, Eq, FShow); 38 | 39 | typedef struct { 40 | Bool l; 41 | Bit#(2) wiri; 42 | AddrMatchMode a; 43 | Bool x; 44 | Bool w; 45 | Bool r; 46 | } PMPCfg deriving (Bits, FShow); 47 | instance DefaultValue#(PMPCfg); 48 | function defaultValue = PMPCfg { 49 | l: False, wiri: 2'b00, a: OFF, x: True, w: True, r: True 50 | }; 51 | endinstance 52 | typedef Vector#(n, PMPCfg) PMPCfgIfc#(numeric type n); 53 | module mkPMPCfgIfcReg (Reg#(PMPCfgIfc#(n))); 54 | Vector#(n, Reg#(PMPCfg)) cfgs <- replicateM(mkConfigReg(defaultValue)); 55 | method Action _write(PMPCfgIfc#(n) vals) = action 56 | function Action doWrite(Reg#(PMPCfg) r, PMPCfg v) = action 57 | if (!r.l) r <= v; 58 | endaction; 59 | joinActions(zipWith(doWrite, cfgs, vals)); 60 | endaction; 61 | method PMPCfgIfc#(n) _read() = readVReg(cfgs); 62 | endmodule 63 | 64 | typedef TSub#(PAddrWidth, 2) SmallPAWidth; 65 | typedef struct { 66 | `ifdef XLEN64 67 | Bit#(10) wiri; 68 | `endif 69 | Bit#(SmallPAWidth) address; 70 | } PMPAddr deriving (Bits, FShow); 71 | instance DefaultValue#(PMPAddr); 72 | function defaultValue = PMPAddr { 73 | `ifdef XLEN64 74 | wiri: 0, 75 | `endif 76 | address: 0 77 | }; 78 | endinstance 79 | 80 | typedef AddrLookup#(PAddr, PAddr) PMPLookup; 81 | -------------------------------------------------------------------------------- /dtb.hex: -------------------------------------------------------------------------------- 1 | edfe0dd0 2 | 23030000 3 | 38000000 4 | 88020000 5 | 28000000 6 | 11000000 7 | 10000000 8 | 00000000 9 | 9b000000 10 | 50020000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 01000000 16 | 00000000 17 | 03000000 18 | 05000000 19 | 00000000 20 | 73627672 21 | 00000000 22 | 03000000 23 | 04000000 24 | 0b000000 25 | 01000000 26 | 03000000 27 | 04000000 28 | 1a000000 29 | 01000000 30 | 01000000 31 | 73757063 32 | 00000000 33 | 03000000 34 | 04000000 35 | 0b000000 36 | 01000000 37 | 03000000 38 | 04000000 39 | 1a000000 40 | 00000000 41 | 03000000 42 | 04000000 43 | 26000000 44 | 80969800 45 | 01000000 46 | 40757063 47 | 00000030 48 | 03000000 49 | 06000000 50 | 00000000 51 | 63736972 52 | 00000076 53 | 03000000 54 | 04000000 55 | 39000000 56 | 00000000 57 | 03000000 58 | 04000000 59 | 3d000000 60 | 00ca9a3b 61 | 01000000 62 | 65746e69 63 | 70757272 64 | 6f632d74 65 | 6f72746e 66 | 72656c6c 67 | 00000000 68 | 03000000 69 | 04000000 70 | 4d000000 71 | 01000000 72 | 03000000 73 | 00000000 74 | 5e000000 75 | 03000000 76 | 0f000000 77 | 00000000 78 | 63736972 79 | 70632c76 80 | 6e692d75 81 | 00006374 82 | 03000000 83 | 04000000 84 | 73000000 85 | 01000000 86 | 02000000 87 | 02000000 88 | 02000000 89 | 01000000 90 | 2d697861 91 | 6574696c 92 | 7375622d 93 | 00000000 94 | 03000000 95 | 04000000 96 | 0b000000 97 | 01000000 98 | 03000000 99 | 04000000 100 | 1a000000 101 | 01000000 102 | 01000000 103 | 72616863 104 | 406f692d 105 | 30303031 106 | 30303030 107 | 00000000 108 | 03000000 109 | 08000000 110 | 00000000 111 | 72616863 112 | 006f692d 113 | 03000000 114 | 08000000 115 | 39000000 116 | 00000010 117 | 00100000 118 | 02000000 119 | 01000000 120 | 6e696c63 121 | 30324074 122 | 30303030 123 | 00000030 124 | 03000000 125 | 0d000000 126 | 00000000 127 | 63736972 128 | 6c632c76 129 | 30746e69 130 | 00000000 131 | 03000000 132 | 10000000 133 | 7b000000 134 | 01000000 135 | 03000000 136 | 01000000 137 | 07000000 138 | 03000000 139 | 08000000 140 | 39000000 141 | 00000002 142 | 00000100 143 | 02000000 144 | 02000000 145 | 01000000 146 | 6f6d656d 147 | 38407972 148 | 30303030 149 | 00303030 150 | 03000000 151 | 07000000 152 | 8f000000 153 | 6f6d656d 154 | 00007972 155 | 03000000 156 | 08000000 157 | 39000000 158 | 00000080 159 | 00000100 160 | 02000000 161 | 02000000 162 | 09000000 163 | 706d6f63 164 | 62697461 165 | 2300656c 166 | 72646461 167 | 2d737365 168 | 6c6c6563 169 | 73230073 170 | 2d657a69 171 | 6c6c6563 172 | 69740073 173 | 6162656d 174 | 662d6573 175 | 75716572 176 | 79636e65 177 | 67657200 178 | 6f6c6300 179 | 662d6b63 180 | 75716572 181 | 79636e65 182 | 6e692300 183 | 72726574 184 | 2d747075 185 | 6c6c6563 186 | 6e690073 187 | 72726574 188 | 2d747075 189 | 746e6f63 190 | 6c6c6f72 191 | 70007265 192 | 646e6168 193 | 6900656c 194 | 7265746e 195 | 74707572 196 | 78652d73 197 | 646e6574 198 | 64006465 199 | 63697665 200 | 79745f65 201 | 00006570 202 | -------------------------------------------------------------------------------- /src/toplevels/Top_cheri.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Vector :: *; 30 | 31 | import AXI :: *; 32 | import Routable :: *; 33 | import RVBS :: *; 34 | import RVBS_Wrappers :: *; 35 | import CHERISOC :: *; 36 | 37 | typedef 2 NMASTERS; 38 | typedef 5 SID_sz; 39 | typedef TSub#(SID_sz, TLog#(NMASTERS)) MID_sz; 40 | 41 | `ifdef CAP64 42 | `define AXI_USR 2 43 | `else // CAP128 44 | `define AXI_USR 1 45 | `endif 46 | 47 | typedef PAddrWidth ADDR_sz; 48 | typedef 128 DATA_sz; 49 | typedef 0 AWUSER_sz; 50 | typedef `AXI_USR WUSER_sz; 51 | typedef 0 BUSER_sz; 52 | typedef 0 ARUSER_sz; 53 | typedef `AXI_USR RUSER_sz; 54 | 55 | `define AXI_MASTER_PARAMS MID_sz, ADDR_sz, DATA_sz,\ 56 | AWUSER_sz, WUSER_sz, BUSER_sz, ARUSER_sz, RUSER_sz 57 | `define AXI_SLAVE_PARAMS SID_sz, ADDR_sz, DATA_sz,\ 58 | AWUSER_sz, WUSER_sz, BUSER_sz, ARUSER_sz, RUSER_sz 59 | 60 | // simulation top module 61 | //////////////////////////////////////////////////////////////////////////////// 62 | module mkRVBS_sim (Empty); 63 | // RESET PC 64 | let reset_pc = 'h80000000; 65 | // RVBS instance 66 | let rvbs <- mkRVBS_CLINT(reset_pc); 67 | // cheriSOC 68 | let cheriSOC <- mkCHERISOC; 69 | // plug things in 70 | connectIFCs(rvbs, cheriSOC); 71 | endmodule 72 | 73 | module connectIFCs#(RVBS_CLINT rvbs, CHERISOC#(ADDR_sz) cheriSOC) (Empty); 74 | // interconnect 75 | Vector#(NMASTERS, AXI4_Master#(`AXI_MASTER_PARAMS)) ms; 76 | ms[0] <- fromAXI4Lite_Master(rvbs.instAXI4Lite_Master); 77 | ms[1] <- fromAXI4Lite_Master(rvbs.dataAXI4Lite_Master); 78 | Vector#(1, AXI4_Slave#(`AXI_SLAVE_PARAMS)) ss; 79 | ss[0] = expandAXI4_Slave_Addr(cheriSOC.slave); 80 | MappingTable#(1, ADDR_sz) maptab = newVector; 81 | maptab[0] = Range{base: 'h00000000, size: 'h100000000}; 82 | mkAXI4Bus(routeFromMappingTable(maptab), ms, ss); 83 | rule connect_interrupts; 84 | rvbs.setMEIP(unpack(cheriSOC.peekIRQs[0])); 85 | endrule 86 | endmodule 87 | 88 | `undef AXI_MASTER_PARAMS 89 | `undef AXI_SLAVE_PARAMS 90 | -------------------------------------------------------------------------------- /src/toplevels/Top_isa_test.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Vector :: *; 30 | import Connectable :: *; 31 | 32 | import RVBS :: *; 33 | import RVBS_Wrappers :: *; 34 | import AXI :: *; 35 | import Routable :: *; 36 | import BlueBasics :: *; 37 | import BlueUtils :: *; 38 | 39 | `define MEM_AXI4_PARAMS PAddrWidth, 128, 0, 0, 0, 0, 0 40 | `ifdef RVXCHERI 41 | `define AXI4_PARAMS PAddrWidth, 128, 0, 1, 0, 0, 1 42 | `else 43 | `define AXI4_PARAMS PAddrWidth, 128, 0, 0, 0, 0, 0 44 | `endif 45 | `define MASTER_T AXI4Lite_Master#(`AXI4_PARAMS) 46 | `define SLAVE_T AXI4Lite_Slave#(`AXI4_PARAMS) 47 | 48 | // memory subsystem 49 | //////////////////////////////////////////////////////////////////////////////// 50 | 51 | module mkTestSOC (SOC_NO_CLINT); 52 | `define NMASTERS 1 53 | `define NSLAVES 2 54 | // input shim 55 | AXI4Lite_Shim#(`AXI4_PARAMS) shimData <- mkAXI4LiteShim; 56 | // memory module 57 | `ifdef MEM_IMG 58 | String memimg = `MEM_IMG; 59 | `else 60 | String memimg = "test-prog.hex"; 61 | `endif 62 | AXI4Lite_Slave#(`MEM_AXI4_PARAMS) tmp[2] <- mkAXI4LiteSharedMem2('h10000, Valid(memimg)); 63 | `SLAVE_T mem[2]; 64 | `ifdef RVXCHERI 65 | mem[0] = zeroUserFields(tmp[0]); 66 | mem[1] = zeroUserFields(tmp[1]); 67 | `else 68 | mem = tmp; 69 | `endif 70 | // tester 71 | module mkAXI4LiteTester (`SLAVE_T); 72 | let shim <- mkAXI4LiteShim; 73 | rule doWrite; 74 | let awflit <- get(shim.master.aw); 75 | let wflit <- get(shim.master.w); 76 | if (wflit.wstrb[0] == 1 && wflit.wdata[0] == 1) $display("TEST SUCCESS"); 77 | else $display("TEST FAILURE"); 78 | $finish(0); 79 | endrule 80 | rule doRead; 81 | let arflit <- get(shim.master.ar); 82 | $display("tester should not be read"); 83 | $finish(0); 84 | endrule 85 | return shim.slave; 86 | endmodule 87 | `SLAVE_T tester <- mkAXI4LiteTester; 88 | // interconnect 89 | Vector#(`NMASTERS, `MASTER_T) ms; 90 | ms[0] = shimData.master; 91 | Vector#(`NSLAVES, `SLAVE_T) ss; 92 | ss[0] = offsetSlave(mem[1], 'h80000000); 93 | ss[1] = tester; 94 | MappingTable#(`NSLAVES, PAddrWidth) maptab = newVector; 95 | maptab[0] = Range{base: 'h80000000, size: 'h01000}; 96 | maptab[1] = Range{base: 'h80001000, size: 'h01000}; 97 | mkAXI4LiteBus(routeFromMappingTable(maptab), ms, ss); 98 | // interfaces 99 | interface instAXI4Lite_Slave = offsetSlave(mem[0], 'h80000000); 100 | interface dataAXI4Lite_Slave = shimData.slave; 101 | method Bool peekMEIP = False; 102 | `undef NMASTERS 103 | `undef NSLAVES 104 | endmodule 105 | 106 | // simulation top module 107 | //////////////////////////////////////////////////////////////////////////////// 108 | module mkRVBS_isa_test (Empty); 109 | // RESET PC 110 | let reset_pc = 'h80000000; 111 | // RVBS instance 112 | let rvbs <- mkRVBS_CLINT(reset_pc); 113 | // mem map 114 | let memoryMap <- mkTestSOC; 115 | // plug things in 116 | mkConnection(rvbs, memoryMap); 117 | endmodule 118 | 119 | `undef AXI4_PARAMS 120 | `undef MASTER_T 121 | `undef SLAVE_T 122 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_PMP.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import FIFOF :: *; 30 | import SpecialFIFOs :: *; 31 | import Vector :: *; 32 | import DefaultValue :: *; 33 | import UniqueWrappers :: * ; 34 | 35 | import BlueUtils :: *; 36 | import SourceSink :: *; 37 | import MasterSlave :: *; 38 | 39 | import RVBS_Types :: *; 40 | 41 | module mkPMPLookup#(Vector#(16, PMPCfg) pmpcfgs, Vector#(16, PMPAddr) pmpaddrs, PrivLvl plvl) (PMPLookup); 42 | 43 | let rsp <- mkBypassFIFOF; 44 | // lookup method 45 | function lookup (req); 46 | // authorisation after match 47 | ExcCode excCode = case (req.reqType) 48 | READ: return LoadAccessFault; 49 | WRITE: return StrAMOAccessFault; 50 | IFETCH: return InstAccessFault; 51 | endcase; 52 | // inner helper for zipwith 53 | //function Maybe#(Either#(ExcToken, PAddr)) doLookup (PMPCfg cfg1, Bit#(SmallPAWidth) a1, Bit#(SmallPAWidth) a0); 54 | function doLookup (cfg1, a1, a0); 55 | // privilege level and R, W, X checks 56 | let isExc =(!(!cfg1.l && plvl == M) && 57 | ((req.reqType == READ && !cfg1.r) || 58 | (req.reqType == WRITE && !cfg1.w) || 59 | (req.reqType == IFETCH && !cfg1.x))); 60 | // matching 61 | PAddr mask = ((~0) << 3) << countZerosLSB(~a0); // 3 because bottom 2 bits + 1 terminating 0 62 | PAddr baseAddr = req.addr; 63 | PAddr topAddr = req.addr + zeroExtend(readBitPO(req.numBytes)); 64 | function checkCond(c) = c ? Valid(isExc ? Left(craftExcToken(excCode)) : Right(baseAddr)) : Invalid; 65 | case (cfg1.a) 66 | // Top Of Range mode 67 | TOR: return checkCond({a0,2'b00} <= baseAddr && topAddr <= {a1,2'b00}); 68 | // Naturally Aligned Power Of Two region (4-bytes region) 69 | NA4: return checkCond(a0 == truncateLSB(baseAddr) && a0 == truncateLSB(topAddr)); 70 | // Naturally Aligned Power Of Two region (>= 8-bytes region) 71 | NAPOT: return checkCond(({a0,2'b00} & mask) == (baseAddr & mask) && ({a0,2'b00} & mask) == (topAddr & mask)); 72 | default: return Invalid; // OFF 73 | endcase 74 | endfunction 75 | // return first match or default response 76 | function Bit#(SmallPAWidth) getAddr(PMPAddr x) = x.address; 77 | Vector#(16, Bit#(SmallPAWidth)) addrs = map(getAddr, pmpaddrs); 78 | let pmpMatches = zipWith3(doLookup, pmpcfgs, addrs, shiftInAt0(addrs,0)); 79 | return fromMaybe( 80 | (plvl != M ? Left(craftExcToken(excCode)) : Right(req.addr)), 81 | fromMaybe(Invalid, find(isValid, pmpMatches)) // flatten the Maybe#(Maybe#(AddrRsp)) 82 | ); 83 | endfunction 84 | // build the lookup interface 85 | let lookupWrapper <- mkUniqueWrapper(lookup); 86 | interface sink = interface Sink; 87 | method canPut = rsp.notFull; 88 | method put (e_req) = case (e_req) matches 89 | tagged Left .excTok: rsp.enq(Left(excTok)); // always pass down incomming exception without further side effects 90 | tagged Right .req: composeM(lookupWrapper.func, rsp.enq)(req); // XXX The bluespec reference guide seams to have the arguments the wrong way around for composeM 91 | endcase; 92 | endinterface; 93 | interface source = toSource(rsp); 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /src/toplevels/Top_sim.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Vector :: *; 30 | import Connectable :: *; 31 | 32 | import AXI :: *; 33 | import Routable :: *; 34 | import BlueUtils :: *; 35 | import CharIO :: *; 36 | import CLINT :: *; 37 | import RVBS :: *; 38 | import RVBS_Wrappers :: *; 39 | 40 | typedef PAddrWidth ADDR_sz; 41 | typedef 128 DATA_sz; 42 | typedef 0 AWUSER_sz; 43 | typedef 0 WUSER_sz; 44 | typedef 0 BUSER_sz; 45 | typedef 0 ARUSER_sz; 46 | typedef 0 RUSER_sz; 47 | 48 | `define AXI4_PARAMS ADDR_sz, DATA_sz,\ 49 | AWUSER_sz, WUSER_sz, BUSER_sz, ARUSER_sz, RUSER_sz 50 | `define MASTER_T AXI4Lite_Master#(`AXI4_PARAMS) 51 | `define SLAVE_T AXI4Lite_Slave#(`AXI4_PARAMS) 52 | 53 | // memory subsystem 54 | //////////////////////////////////////////////////////////////////////////////// 55 | 56 | module mkSimSOC (SOC); 57 | `define NMASTERS 1 58 | `define NSLAVES 4 59 | // input shim 60 | AXI4Lite_Shim#(`AXI4_PARAMS) shimData <- mkAXI4LiteShim; 61 | // DTB 62 | `ifdef DTB_IMG 63 | String dtbimg = `DTB_IMG; 64 | `else 65 | String dtbimg = "dtb.hex"; 66 | `endif 67 | AXI4Lite_Slave#(`AXI4_PARAMS) dtb <- mkAXI4LiteMem('h2000, Valid(dtbimg)); 68 | // CharIO 69 | AXI4Lite_Slave#(`AXI4_PARAMS) charIO <- mkAXI4LiteSocketCharIO("CHAR_IO", 6000); 70 | // clint 71 | AXI4LiteCLINT#(ADDR_sz, DATA_sz) clint <- mkAXI4LiteCLINT; 72 | // memory module 73 | `ifdef MEM_IMG 74 | String memimg = `MEM_IMG; 75 | `else 76 | String memimg = "test-prog.hex"; 77 | `endif 78 | `ifdef MEM_SIZE 79 | Integer memsize = `MEM_SIZE; 80 | `else 81 | Integer memsize = 'h10000000; 82 | `endif 83 | AXI4Lite_Slave#(`AXI4_PARAMS) mem[2] <- mkAXI4LiteSharedMem2(memsize, Valid(memimg)); 84 | // interconnect 85 | Vector#(`NMASTERS, `MASTER_T) ms; 86 | ms[0] = shimData.master; 87 | Vector#(`NSLAVES, `SLAVE_T) ss; 88 | ss[0] = offsetSlave(dtb, 'h00004000); 89 | ss[1] = offsetSlave(charIO, 'h10000000); 90 | ss[2] = offsetSlave(clint.axiLiteSlave, 'h02000000); 91 | ss[3] = offsetSlave(mem[1], 'h80000000); 92 | MappingTable#(`NSLAVES, ADDR_sz) maptab = newVector; 93 | maptab[0] = Range{base: 'h00004000, size: 'h02000}; 94 | maptab[1] = Range{base: 'h10000000, size: 'h01000}; 95 | maptab[2] = Range{base: 'h02000000, size: 'h10000}; 96 | maptab[3] = Range{base: 'h80000000, size: fromInteger(memsize)}; 97 | mkAXI4LiteBus(routeFromMappingTable(maptab), ms, ss); 98 | // interfaces 99 | interface instAXI4Lite_Slave = offsetSlave(mem[0], 'h80000000); 100 | interface dataAXI4Lite_Slave = shimData.slave; 101 | method Bool peekMEIP = False; 102 | method Bool peekMTIP = clint.peekMTIP; 103 | method Bool peekMSIP = clint.peekMSIP; 104 | `undef NMASTERS 105 | `undef NSLAVES 106 | endmodule 107 | 108 | // simulation top module 109 | //////////////////////////////////////////////////////////////////////////////// 110 | module mkRVBS_sim (Empty); 111 | // RESET PC 112 | let reset_pc = 'h80000000; 113 | // RVBS instance 114 | let rvbs <- mkRVBS(reset_pc); 115 | // mem map 116 | let memoryMap <- mkSimSOC; 117 | // plug things in 118 | mkConnection(rvbs, memoryMap); 119 | endmodule 120 | 121 | `undef AXI4_PARAMS 122 | `undef MASTER_T 123 | `undef SLAVE_T 124 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_64_M.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import BID :: *; 30 | import BitPat :: *; 31 | import BlueUtils :: *; 32 | 33 | import RVBS_Types :: *; 34 | import RVBS_TraceInsts :: *; 35 | 36 | // div helper 37 | function t safeDiv(t a, t b) provisos (Arith#(t), Eq#(t)) = a / ((b == 0) ? 1 : b); 38 | function t safeRem(t a, t b) provisos (Arith#(t), Eq#(t)) = a % ((b == 0) ? 1 : b); 39 | 40 | /* 41 | R-type 42 | 43 | 31 25 24 20 19 15 14 12 11 7 6 0 44 | +----------------------------+--------+--------+--------+--------+----------+ 45 | | funct7 | rs2 | rs1 | funct3 | rd | opcode | 46 | +----------------------------+--------+--------+--------+--------+----------+ 47 | 48 | */ 49 | 50 | // funct7 = MULDIV = 0000001 51 | // funct3 = MULW = 000 52 | // opcode = OP = 0111011 53 | function Action instrMULW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 54 | Bit#(32) tmp = truncate(s.rGPR(rs1)) * truncate(s.rGPR(rs2)); 55 | s.wGPR(rd, signExtend(tmp)); 56 | logInst(s, fmtInstR("mulw", rd, rs1, rs2)); 57 | endaction; 58 | 59 | // funct7 = MULDIV = 0000001 60 | // funct3 = DIVW = 100 61 | // opcode = OP = 0111011 62 | function Action instrDIVW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 63 | if (s.rGPR(rs2) == 0) s.wGPR(rd, ~0); 64 | else begin 65 | Int#(32) tmp = safeDiv(unpack(truncate(s.rGPR(rs1))), unpack(truncate(s.rGPR(rs2)))); 66 | s.wGPR(rd, signExtend(pack(tmp))); 67 | end 68 | logInst(s, fmtInstR("divw", rd, rs1, rs2)); 69 | endaction; 70 | 71 | // funct7 = MULDIV = 0000001 72 | // funct3 = DIVUW = 101 73 | // opcode = OP = 0111011 74 | function Action instrDIVUW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 75 | if (s.rGPR(rs2) == 0) s.wGPR(rd, ~0); 76 | else begin 77 | Bit#(32) tmp = safeDiv(truncate(s.rGPR(rs1)), truncate(s.rGPR(rs2))); 78 | s.wGPR(rd, signExtend(tmp)); 79 | end 80 | logInst(s, fmtInstR("divuw", rd, rs1, rs2)); 81 | endaction; 82 | 83 | // funct7 = MULDIV = 0000001 84 | // funct3 = REMW = 110 85 | // opcode = OP = 0111011 86 | function Action instrREMW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 87 | if (s.rGPR(rs2) == 0) s.wGPR(rd, s.rGPR(rs1)); 88 | else begin 89 | Int#(32) tmp = safeRem(unpack(truncate(s.rGPR(rs1))), unpack(truncate(s.rGPR(rs2)))); 90 | s.wGPR(rd, signExtend(pack(tmp))); 91 | end 92 | logInst(s, fmtInstR("remw", rd, rs1, rs2)); 93 | endaction; 94 | 95 | // funct7 = MULDIV = 0000001 96 | // funct3 = REMUW = 111 97 | // opcode = OP = 0111011 98 | function Action instrREMUW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 99 | if (s.rGPR(rs2) == 0) s.wGPR(rd, s.rGPR(rs1)); 100 | else begin 101 | Bit#(32) tmp = safeRem(truncate(s.rGPR(rs1)), truncate(s.rGPR(rs2))); 102 | s.wGPR(rd, signExtend(tmp)); 103 | end 104 | logInst(s, fmtInstR("remuw", rd, rs1, rs2)); 105 | endaction; 106 | 107 | //////////////////////////////////////////////////////////////////////////////// 108 | 109 | module [ISADefModule] mkExt_64_M#(RVState s) (); 110 | 111 | defineInstEntry("mulw", pat(n(7'b0000001), v, v, n(3'b000), v, n(7'b0111011)), instrMULW(s)); 112 | defineInstEntry("divw", pat(n(7'b0000001), v, v, n(3'b100), v, n(7'b0111011)), instrDIVW(s)); 113 | defineInstEntry("divuw", pat(n(7'b0000001), v, v, n(3'b101), v, n(7'b0111011)), instrDIVUW(s)); 114 | defineInstEntry("remw", pat(n(7'b0000001), v, v, n(3'b110), v, n(7'b0111011)), instrREMW(s)); 115 | defineInstEntry("remuw", pat(n(7'b0000001), v, v, n(3'b111), v, n(7'b0111011)), instrREMUW(s)); 116 | 117 | endmodule 118 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # RVBS - RISC-V Bluespec SystemVerilog Specification 2 | 3 | **RVBS** (pronounced *"rubs"*) is an ISA level description of the RISC-V instruction set in [Bluespec SystemVerilog](http://wiki.bluespec.com/bluespec-systemverilog-and-compiler). It uses the [BID library](https://github.com/CTSRD-CHERI/BID) to describe the instructions, providing a readable, executable and synthesizeable specification, with an AXI interface, that could be used as a golden model. 4 | 5 | **RVBS** is **not** a heavily pipelined, superscalar or optimised RISC-V core. It is however capable to boot small embedded operating systems. 6 | 7 | RVBS currently supports: 8 | 9 | - 32-bit and 64-bit RISC-V **I** base integer instructions 10 | - RISC-V **M** integer multiply/divide instructions 11 | - RISC-V **C** compressed instructions 12 | - RISC-V **Zicsr** control and status registers manipulation instructions 13 | - **Machine/Supervisor/User** privilege modes 14 | - **Sv32** virtual memory translation mechanism **without Sv32 memory protection features** 15 | - **PMP** physical memory protection mechanism 16 | - *RISC-V **Zifencei** the fence.i instruction, currently a nop* 17 | 18 | RVBS supports traps between privilege modes, but **Supervisor mode** is not fully implemented. 19 | 20 | ## Building RVBS 21 | 22 | In order to build a RVBS Bluesim simulator, you will need a valid installation of [Bluespec SystemVerilog](http://wiki.bluespec.com/bluespec-systemverilog-and-compiler) on your machine. RVBS relies on the following three Bluespec libraries: 23 | 24 | - [Recipe](https://github.com/CTSRD-CHERI/Recipe) 25 | - [BitPat](https://github.com/CTSRD-CHERI/BitPat) 26 | - [BlueStuff](https://github.com/CTSRD-CHERI/BlueStuff) 27 | - [BID](https://github.com/CTSRD-CHERI/BID) 28 | 29 | [BID](https://github.com/CTSRD-CHERI/BID) is a submodule of the [RVBS](https://github.com/CTSRD-CHERI/RVBS.git) repository. [Recipe](https://github.com/CTSRD-CHERI/Recipe), [BitPat](https://github.com/CTSRD-CHERI/BitPat) and [BlueStuff](https://github.com/CTSRD-CHERI/BlueStuff) are themselves submodules of the [BID](https://github.com/CTSRD-CHERI/BID) repository. In order to checkout all of them, you need to run: 30 | ```sh 31 | $ git submodule update --init --recursive 32 | ``` 33 | 34 | Once the libraries are available, you can build RVBS and specify a number of build options as environment variables. The `XLEN` environment variable must be set to one of `32` or `64` to specify the XLEN to build with. The following optional environment variables are available: 35 | 36 | - `USER_MODE` can be set to enable *User mode* support 37 | - `SUPERVISOR_MODE` can be set to enable *Supervisor mode* support (implies *User mode*) 38 | - `PMP` can be set to enable the Physical Memory Protection unit 39 | - `RVM` can be set to enable the *M* integer multiply/divide instructions extention 40 | - `RVC` can be set to enable the *C* compressed instructions extention 41 | - `RVZICSR` can be set to enable the *Zicsr* control and status registers manipulation instructions extention 42 | - `RVZIFENCEI` can be set to enable the *Zifencei* fence.i instruction extention 43 | - `NO_LOGS` can be set to skip print statements (accelerates simulation) 44 | - `PRINT_ABI_REG_NAME` can be set to use ABI names for registers instead of their index 45 | 46 | ### Bluesim 47 | 48 | Several Bluesim build targets are available: 49 | 50 | - `isa-test` to get a simulator that can be used for running the ISA tests from [riscv-tests](https://github.com/riscv/riscv-tests) 51 | - `rfvi-dii` to get a rvfi-dii server to be used with a [TestRIG](https://github.com/CTSRD-CHERI/TestRIG) configuration 52 | - `sim` to get the default simulator. It can be further configured using: 53 | * `MEM_SIZE` can be used to specify the size of the memory in bytes 54 | * `MEM_IMG` can be used to specify the memory image used to initialize the memory 55 | * `MEM_DELAY` can be set to enable artificial memory delay 56 | 57 | The generated simulator is found under the `output/` folder, and when run, will execute the program found in `test-prog.hex`. 58 | 59 | #### Examples 60 | 61 | - To build a 64-bit bluesim simulator with support for multiply/divide instructions and 32KB of memory, you can run: 62 | 63 | ```sh 64 | $ make RVM=1 XLEN=64 MEM_SIZE=32768 sim 65 | ``` 66 | 67 | - To build a 32-bit bluesim simulator with support for compressed instructions and as an rvfi-dii server, you can run: 68 | 69 | ```sh 70 | $ make RVC=1 rvfi-dii 71 | ``` 72 | 73 | - To build a 32-bit bluesim simulator capable of running the ISA tests, you can run: 74 | 75 | ```sh 76 | $ make isa-test 77 | ``` 78 | 79 | #### Run time flags 80 | 81 | The `+itrace` flag can be specified on the command line when running the simulator to get an instruction trace in `stdout` as follows: 82 | 83 | ```sh 84 | $ output/rvbs-rv64IM +itrace 85 | ``` 86 | 87 | ### Verilog 88 | 89 | To build a 32-bit verilog module with support for compressed instructions, you can run: 90 | ```sh 91 | $ make RVC=1 XLEN=32 verilog 92 | ``` 93 | The generated verilog can be found in the `output/rvbs-rv32IC-vdir/` folder. Specifically, the `rvbs` verilog module with an AXI4Lite interface can be found in `output/rvbs-rv32IC-vdir/rvbs.v`. 94 | 95 | ### TODOs, upcoming features and experimentations... 96 | 97 | - sv39/sv48 memory virtualisation 98 | - N extention for User mode interrupt and exception support 99 | - CHERI extension 100 | 101 | ## References 102 | 103 | - [l3riscv](https://github.com/SRI-CSL/l3riscv) 104 | - [sail-riscv](https://github.com/rems-project/sail-riscv) 105 | - [Nikhil's initial RISC-V spec in Bluespec](https://github.com/rsnikhil/RISCV_ISA_Formal_Spec_in_BSV) 106 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_MemTypes.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import RVBS_BasicTypes :: *; 30 | import BlueBasics :: *; 31 | import BlueUtils :: *; 32 | import AXI :: *; 33 | 34 | `ifdef XLEN64 35 | typedef 56 PAddrWidth; 36 | `else 37 | typedef 34 PAddrWidth; 38 | `endif 39 | typedef Bit#(XLEN) VAddr; 40 | typedef Bit#(PAddrWidth) PAddr; 41 | function PAddr toPAddr (VAddr addr); 42 | Bit#(TMax#(PAddrWidth, XLEN)) tmp = zeroExtend(addr); 43 | return truncate(tmp); 44 | endfunction 45 | 46 | typedef 32 InstWidth; 47 | typedef XLEN IMemWidth; 48 | typedef XLEN DMemWidth; 49 | typedef XLEN IVMMemWidth; 50 | typedef XLEN DVMMemWidth; 51 | 52 | // RV load/store/ifetch util types 53 | typedef enum {READ, WRITE, IFETCH} RVMemReqType deriving (Bits, Eq, FShow); 54 | typedef struct { String name; Integer numBytes; Bool sgnExt; } LoadArgs; 55 | typedef struct { String name; Integer numBytes; } StrArgs; 56 | 57 | typedef struct 58 | { 59 | addr_t addr; 60 | BitPO#(4) numBytes; 61 | RVMemReqType reqType; 62 | } AddrReq#(type addr_t) deriving (Bits, FShow); 63 | instance NeedRsp#(AddrReq#(addr_t)); function needRsp(req) = True; endinstance 64 | function AddrReq#(addr_t) aReq(RVMemReqType rt, addr_t a, BitPO#(4) n) = 65 | AddrReq {addr: a, numBytes: n, reqType: rt}; 66 | function AddrReq#(addr_t) aReqRead(addr_t a, BitPO#(4) n) = aReq(READ, a, n); 67 | function AddrReq#(addr_t) aReqWrite(addr_t a, BitPO#(4) n) = aReq(WRITE, a, n); 68 | function AddrReq#(addr_t) aReqIFetch(addr_t a, BitPO#(4) n) = aReq(IFETCH, a, n); 69 | function Either#(ExcToken, AddrReq#(addr_t)) craftAReq (RVMemReqType rt, 70 | Either#(ExcToken, addr_t) e_a, 71 | BitPO#(4) n) = 72 | case (e_a) matches 73 | tagged Left .excTok: Left(excTok); 74 | tagged Right .addr: Right(aReq(rt, addr, n)); 75 | endcase; 76 | 77 | typedef Slave#(Either#(ExcToken, AddrReq#(addr_req)), 78 | Either#(ExcToken, addr_t)) AddrLookup#(type addr_req, type addr_t); 79 | 80 | // Memory interface 81 | // supports data of 128 bits (16 bytes) 82 | typedef union tagged { 83 | struct { 84 | PAddr addr; 85 | BitPO#(4) numBytes; 86 | } RVReadReq; 87 | struct { 88 | PAddr addr; 89 | Bit#(16) byteEnable; 90 | Bit#(128) data; 91 | `ifdef RVXCHERI 92 | Bit#(1) captag; 93 | `endif 94 | } RVWriteReq; 95 | } RVMemReq deriving (Bits, FShow); 96 | 97 | instance NeedRsp#(RVMemReq); 98 | function needRsp(r) = True; 99 | endinstance 100 | 101 | instance ToAXI4Lite_AWFlit#(RVMemReq, PAddrWidth, user_sz); 102 | function toAXI4Lite_AWFlit(x); 103 | let w = x.RVWriteReq; 104 | return AXI4Lite_AWFlit {awaddr: pack(w.addr), awprot: 0, awuser: 0}; 105 | endfunction 106 | endinstance 107 | 108 | instance ToAXI4Lite_WFlit#(RVMemReq, 128, user_sz) 109 | `ifdef RVXCHERI 110 | provisos (Add#(1, a__, user_sz)) 111 | `endif 112 | ; 113 | function toAXI4Lite_WFlit(x); 114 | let w = x.RVWriteReq; 115 | return AXI4Lite_WFlit { 116 | wdata: pack(w.data), wstrb: w.byteEnable, 117 | `ifdef RVXCHERI 118 | wuser: zeroExtend(w.captag) 119 | `else 120 | wuser: 0 121 | `endif 122 | }; 123 | endfunction 124 | endinstance 125 | 126 | instance ToAXI4Lite_ARFlit#(RVMemReq, PAddrWidth, user_sz); 127 | function toAXI4Lite_ARFlit(x); 128 | let r = x.RVReadReq; 129 | return AXI4Lite_ARFlit {araddr: pack(r.addr), arprot: 0, aruser: 0}; 130 | endfunction 131 | endinstance 132 | 133 | typedef union tagged { 134 | `ifdef RVXCHERI 135 | Tuple2#(Bit#(1), Bit#(128)) RVReadRsp; 136 | `else 137 | Bit#(128) RVReadRsp; 138 | `endif 139 | void RVWriteRsp; 140 | void RVBusError; 141 | } RVMemRsp deriving (Bits, FShow); 142 | 143 | instance FromAXI4Lite_RFlit#(RVMemRsp, 128, user_sz) 144 | `ifdef RVXCHERI 145 | provisos (Add#(1, a__, user_sz)) 146 | `endif 147 | ; 148 | function fromAXI4Lite_RFlit(x) = case (x.rresp) 149 | OKAY: 150 | `ifdef RVXCHERI 151 | RVReadRsp(tuple2(truncate(x.ruser), unpack(x.rdata))); 152 | `else 153 | RVReadRsp(unpack(x.rdata)); 154 | `endif 155 | default: RVBusError; 156 | endcase; 157 | endinstance 158 | 159 | instance FromAXI4Lite_BFlit#(RVMemRsp, user_sz); 160 | function fromAXI4Lite_BFlit(x) = case (x.bresp) 161 | OKAY: RVWriteRsp; 162 | default: RVBusError; 163 | endcase; 164 | endinstance 165 | 166 | typedef Slave#(Either#(ExcToken, RVMemReq), 167 | Either#(ExcToken, RVMemRsp)) RVMem; 168 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_32_M.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import BID :: *; 30 | import BitPat :: *; 31 | import BlueUtils :: *; 32 | 33 | import RVBS_Types :: *; 34 | import RVBS_TraceInsts :: *; 35 | 36 | // div helper 37 | function t safeDiv(t a, t b) provisos (Arith#(t), Eq#(t)) = a / ((b == 0) ? 1 : b); 38 | function t safeRem(t a, t b) provisos (Arith#(t), Eq#(t)) = a % ((b == 0) ? 1 : b); 39 | 40 | /* 41 | R-type 42 | 43 | 31 25 24 20 19 15 14 12 11 7 6 0 44 | +----------------------------+--------+--------+--------+--------+----------+ 45 | | funct7 | rs2 | rs1 | funct3 | rd | opcode | 46 | +----------------------------+--------+--------+--------+--------+----------+ 47 | 48 | */ 49 | 50 | // funct7 = MULDIV = 0000001 51 | // funct3 = MUL = 000 52 | // opcode = OP = 0110011 53 | function Action instrMUL (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 54 | Bit#(TMul#(XLEN, 2)) tmp = zeroExtend(s.rGPR(rs1)) * zeroExtend(s.rGPR(rs2)); 55 | s.wGPR(rd, truncate(tmp)); 56 | logInst(s, fmtInstR("mul", rd, rs1, rs2)); 57 | endaction; 58 | 59 | // funct7 = MULDIV = 0000001 60 | // funct3 = MULH = 001 61 | // opcode = OP = 0110011 62 | function Action instrMULH (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 63 | Int#(TMul#(XLEN, 2)) tmp = unpack(signExtend(s.rGPR(rs1))) * unpack(signExtend(s.rGPR(rs2))); 64 | s.wGPR(rd, truncateLSB(pack(tmp))); 65 | logInst(s, fmtInstR("mulh", rd, rs1, rs2)); 66 | endaction; 67 | 68 | // funct7 = MULDIV = 0000001 69 | // funct3 = MULHSU = 010 70 | // opcode = OP = 0110011 71 | function Action instrMULHSU (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 72 | Int#(TMul#(XLEN, 2)) tmp = unpack(signExtend(s.rGPR(rs1))) * unpack(zeroExtend(s.rGPR(rs2))); 73 | s.wGPR(rd, truncateLSB(pack(tmp))); 74 | logInst(s, fmtInstR("mulhsu", rd, rs1, rs2)); 75 | endaction; 76 | 77 | // funct7 = MULDIV = 0000001 78 | // funct3 = MULHU = 011 79 | // opcode = OP = 0110011 80 | function Action instrMULHU (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 81 | Bit#(TMul#(XLEN, 2)) tmp = zeroExtend(s.rGPR(rs1)) * zeroExtend(s.rGPR(rs2)); 82 | s.wGPR(rd, truncateLSB(tmp)); 83 | logInst(s, fmtInstR("mulhu", rd, rs1, rs2)); 84 | endaction; 85 | 86 | // funct7 = MULDIV = 0000001 87 | // funct3 = DIV = 100 88 | // opcode = OP = 0110011 89 | function Action instrDIV (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 90 | if (s.rGPR(rs2) == 0) s.wGPR(rd, ~0); 91 | else begin 92 | Int#(XLEN) tmp = safeDiv(unpack(s.rGPR(rs1)), unpack(s.rGPR(rs2))); 93 | s.wGPR(rd, pack(tmp)); 94 | end 95 | logInst(s, fmtInstR("div", rd, rs1, rs2)); 96 | endaction; 97 | 98 | // funct7 = MULDIV = 0000001 99 | // funct3 = DIVU = 101 100 | // opcode = OP = 0110011 101 | function Action instrDIVU (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 102 | s.wGPR(rd, (s.rGPR(rs2) == 0) ? ~0 : safeDiv(s.rGPR(rs1), s.rGPR(rs2))); 103 | logInst(s, fmtInstR("divu", rd, rs1, rs2)); 104 | endaction; 105 | 106 | // funct7 = MULDIV = 0000001 107 | // funct3 = REM = 110 108 | // opcode = OP = 0110011 109 | function Action instrREM (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 110 | Int#(XLEN) tmp = unpack(s.rGPR(rs1)) % unpack(s.rGPR(rs2)); // XXX use safeRem ? 111 | s.wGPR(rd, (s.rGPR(rs2) == 0) ? s.rGPR(rs1) : pack(tmp)); 112 | logInst(s, fmtInstR("rem", rd, rs1, rs2)); 113 | endaction; 114 | 115 | // funct7 = MULDIV = 0000001 116 | // funct3 = REMU = 111 117 | // opcode = OP = 0110011 118 | function Action instrREMU (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 119 | s.wGPR(rd, (s.rGPR(rs2) == 0) ? s.rGPR(rs1) : s.rGPR(rs1) % s.rGPR(rs2)); // XXX 120 | logInst(s, fmtInstR("remu", rd, rs1, rs2)); 121 | endaction; 122 | 123 | //////////////////////////////////////////////////////////////////////////////// 124 | 125 | module [ISADefModule] mkExt_32_M#(RVState s) (); 126 | 127 | defineInstEntry("mul", pat(n(7'b0000001), v, v, n(3'b000), v, n(7'b0110011)), instrMUL(s)); 128 | defineInstEntry("mulh", pat(n(7'b0000001), v, v, n(3'b001), v, n(7'b0110011)), instrMULH(s)); 129 | defineInstEntry("mulhsu", pat(n(7'b0000001), v, v, n(3'b010), v, n(7'b0110011)), instrMULHSU(s)); 130 | defineInstEntry("mulhu", pat(n(7'b0000001), v, v, n(3'b011), v, n(7'b0110011)), instrMULHU(s)); 131 | defineInstEntry("div", pat(n(7'b0000001), v, v, n(3'b100), v, n(7'b0110011)), instrDIV(s)); 132 | defineInstEntry("divu", pat(n(7'b0000001), v, v, n(3'b101), v, n(7'b0110011)), instrDIVU(s)); 133 | defineInstEntry("rem", pat(n(7'b0000001), v, v, n(3'b110), v, n(7'b0110011)), instrREM(s)); 134 | defineInstEntry("remu", pat(n(7'b0000001), v, v, n(3'b111), v, n(7'b0110011)), instrREMU(s)); 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /src/toplevels/Top_rvfi_dii.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import FIFOF :: *; 30 | import SpecialFIFOs :: *; 31 | 32 | import RVBS :: *; 33 | import RVBS_Core :: *; 34 | `ifdef RVXCHERI 35 | import CHERICap :: *; 36 | `endif 37 | import RVFI_DII :: *; 38 | import Recipe :: *; 39 | import BlueBasics :: *; 40 | import BlueUtils :: *; 41 | import BID :: *; 42 | 43 | // helper 44 | function Bit#(TLog#(TAdd#(1, n))) idxMSB(Bit#(n) x) = 45 | pack(fromInteger(valueOf(n)) - countZerosMSB(x) - 1); 46 | 47 | (* synthesize *) 48 | module mkRVBS_rvfi_dii (Empty); 49 | 50 | // create the RVFI-DII bridge 51 | let bridge <- mkRVFI_DII_Bridge("RVFI_DII", 5000); 52 | // create a memory 53 | module memShim (Array#(RVMem)); 54 | `ifdef RVXCHERI 55 | Mem#(PAddr, Bit#(1)) mem_tag[2] <- mkMemSimWithOffset(2, 'h80000000, 'h10000, Invalid); 56 | `endif 57 | Mem#(PAddr, Bit#(128)) mem[2] <- mkMemSimWithOffset(2, 'h80000000, 'h10000, Invalid); 58 | // 2 memory interfaces 59 | RVMem m[2]; 60 | for (Integer i = 0; i < 2; i = i + 1) begin 61 | let rspFF <- mkBypassFIFOF; 62 | let errorFF <- mkFIFOF; 63 | let excFF <- mkFIFOF; 64 | // get responses 65 | rule drainMemRsp(!excFF.notEmpty && !errorFF.first); 66 | let rsp <- get(mem[i].source); 67 | `ifdef RVXCHERI 68 | let tag <- get(mem_tag[i].source); 69 | `endif 70 | case (rsp) matches 71 | tagged ReadRsp .data: rspFF.enq(Right(RVReadRsp( 72 | `ifdef RVXCHERI 73 | tuple2(tag.ReadRsp, data) 74 | `else 75 | data 76 | `endif 77 | ))); 78 | tagged WriteRsp: rspFF.enq(Right(RVWriteRsp)); 79 | endcase 80 | errorFF.deq; 81 | endrule 82 | rule errorRsp(!excFF.notEmpty && errorFF.first); 83 | rspFF.enq(Right(RVBusError)); 84 | errorFF.deq; 85 | endrule 86 | rule exceptionRsp(excFF.notEmpty); 87 | rspFF.enq(Left(excFF.first)); 88 | excFF.deq; 89 | endrule 90 | // convert requests/responses 91 | m[i] = interface RVMem; 92 | interface sink = interface Sink; 93 | method canPut = errorFF.notFull; 94 | method put (e_req) = action 95 | case (e_req) matches 96 | tagged Left .excTok: excFF.enq(excTok); 97 | tagged Right .req: case (req) matches 98 | tagged RVReadReq .r &&& 99 | (r.addr >= 'h80000000 && 100 | {1'b0, r.addr} + zeroExtend(readBitPO(r.numBytes) - 1) < 'h80010000): begin 101 | mem[i].sink.put(ReadReq{addr: r.addr, numBytes: r.numBytes}); 102 | `ifdef RVXCHERI 103 | mem_tag[i].sink.put(ReadReq{addr: r.addr, numBytes: 1}); 104 | `endif 105 | errorFF.enq(False); 106 | end 107 | tagged RVWriteReq .w &&& 108 | (w.addr >= 'h80000000 && 109 | {1'b0, w.addr} + zeroExtend(idxMSB(w.byteEnable)) + 1 < 'h80010000): begin 110 | mem[i].sink.put(WriteReq{ 111 | addr: w.addr, byteEnable: w.byteEnable, data: w.data 112 | }); 113 | `ifdef RVXCHERI 114 | mem_tag[i].sink.put(WriteReq{ 115 | addr: w.addr, byteEnable: 1, data: w.captag 116 | }); 117 | `endif 118 | errorFF.enq(False); 119 | end 120 | default: errorFF.enq(True); 121 | endcase 122 | endcase 123 | endaction; 124 | endinterface; 125 | interface source = toSource(rspFF); 126 | endinterface; 127 | end 128 | return m; 129 | endmodule 130 | RVMem mem[2] <- memShim(reset_by bridge.new_rst); 131 | // prepare state 132 | let reset_pc = 'h80000000; 133 | `ifdef SUPERVISOR_MODE 134 | RVMem imem[2] <- virtualize(mem[0], 2, reset_by bridge.new_rst); 135 | RVMem dmem[2] <- virtualize(mem[1], 2, reset_by bridge.new_rst); 136 | RVState s <- mkState(reset_pc, imem[1], dmem[1], imem[0], dmem[0], bridge, reset_by bridge.new_rst); 137 | `else 138 | RVState s <- mkState(reset_pc, mem[0], mem[1], bridge, reset_by bridge.new_rst); 139 | `endif 140 | // initialization 141 | module [ISADefModule] mkRVInit#(RVState st) (Empty); 142 | Reg#(Bit#(6)) cnt <- mkRegU; 143 | defineInitEntry(rSeq(rBlock( 144 | printTLogPlusArgs("itrace", "-------- Reseting --------"), 145 | action s.pc <= reset_pc; endaction, action s.pc.commit; endaction, 146 | `ifdef RVXCHERI 147 | action CapType c0 = nullCap; s.wCR(0, c0); endaction, 148 | s.regFile.commit, 149 | writeReg(cnt, 1), 150 | rWhile(cnt < 32, rFastSeq(rBlock( 151 | action CapType c = almightyCap; s.wCR(truncate(cnt), c); endaction, 152 | action 153 | s.regFile.commit; 154 | cnt <= cnt + 1; 155 | endaction 156 | ))) 157 | `else 158 | writeReg(cnt, 0), 159 | rWhile(cnt < 32, rFastSeq(rBlock( 160 | s.wGPR(truncate(cnt), 0), 161 | action 162 | s.regFile.commit; 163 | cnt <= cnt + 1; 164 | endaction 165 | ))) 166 | `endif 167 | ))); 168 | endmodule 169 | // instanciating simulator 170 | let _ <- mkRVBSCore(s, mkRVInit, mkRVIFetch_RVFI_DII, reset_by bridge.new_rst); 171 | 172 | endmodule 173 | -------------------------------------------------------------------------------- /src/CLINT.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import DefaultValue :: *; 30 | import Vector :: *; 31 | import FIFO :: *; 32 | 33 | import AXI4Lite :: *; 34 | import BlueUtils :: *; 35 | import SourceSink :: *; 36 | 37 | // CLINT interface 38 | //////////////////////////////////////////////////////////////////////////////// 39 | 40 | interface AXI4LiteCLINT#(numeric type addr_sz, numeric type data_sz); 41 | interface AXI4Lite_Slave#(addr_sz, data_sz, 0, 0, 0, 0, 0) axiLiteSlave; 42 | method Bool peekMSIP; 43 | method Bool peekMTIP; 44 | endinterface 45 | 46 | // helpers 47 | //////////////////////////////////////////////////////////////////////////////// 48 | 49 | function Bit#(n) merge(Bit#(n) old_val, Bit#(n) new_val, Bit#(TDiv#(n, 8)) be) 50 | provisos (Bits#(Vector::Vector#(TDiv#(n, 8), Bit#(8)), n)); 51 | Vector#(TDiv#(n, 8),Bit#(8)) old_vec = unpack(old_val); 52 | Vector#(TDiv#(n, 8),Bit#(8)) new_vec = unpack(new_val); 53 | Vector#(TDiv#(n, 8),Bool) be_vec = unpack(be); 54 | function mergeByte(b_old, b_new, b) = (b) ? b_new : b_old; 55 | return pack(zipWith3(mergeByte, old_vec, new_vec, be_vec)); 56 | endfunction 57 | 58 | // CLINT implementation 59 | //////////////////////////////////////////////////////////////////////////////// 60 | 61 | module mkAXI4LiteCLINT (AXI4LiteCLINT#(addr_sz, data_sz)) 62 | provisos ( 63 | // 64 | Add#(a__, 64, data_sz), 65 | Add#(b__, 8, TDiv#(data_sz, 8)), 66 | // 67 | Add#(c__, 32, data_sz), 68 | Add#(d__, 4, TDiv#(data_sz, 8)), 69 | // 70 | Add#(e__, 1, data_sz) 71 | ); 72 | // local state 73 | AXI4Lite_Shim#(addr_sz, data_sz, 0, 0, 0, 0, 0) shim <- mkAXI4LiteShim; 74 | Reg#(Bit#(64)) r_mtime <- mkReg(0); // XXX mkRegU 75 | Reg#(Bit#(64)) r_mtimecmp <- mkRegU; 76 | `ifndef XLEN64 // 32-bit only 77 | Reg#(Bit#(32)) cmp_top <- mkRegU; 78 | `endif 79 | Reg#(Bool) r_msip <- mkReg(False); // XXX mkRegU 80 | Reg#(Bool) r_mtip[2] <- mkCRegU(2); 81 | let wRsp <- mkFIFO1; 82 | let rRsp <- mkFIFO1; 83 | // bit idx helper 84 | Integer topBitIdx = valueOf(TLog#(TDiv#(data_sz, 8))) - 1; 85 | // timer rules 86 | rule count_time; r_mtime <= r_mtime + 1; endrule 87 | rule compare; 88 | r_mtip[0] <= r_mtime >= r_mtimecmp; 89 | // debug 90 | if (!r_mtip[0] && r_mtime >= r_mtimecmp) 91 | printTLogPlusArgs("clint", $format("clint >>> mtime (0x%0x) reached mtimecmp", r_mtime)); 92 | endrule 93 | // AXI4 write request handling 94 | rule writeReq; 95 | // get request 96 | let awflit <- get(shim.master.aw); 97 | let wflit <- get(shim.master.w); 98 | // pre-format data / strb 99 | Bit#(TLog#(TDiv#(data_sz, 8))) byteShftAmnt = awflit.awaddr[topBitIdx:0]; 100 | Bit#(TAdd#(3, TLog#(TDiv#(data_sz, 8)))) bitShftAmnt = zeroExtend(byteShftAmnt) << 3; 101 | Bit#(data_sz) data = wflit.wdata >> bitShftAmnt; 102 | Bit#(TDiv#(data_sz, 8)) strb = wflit.wstrb >> byteShftAmnt; 103 | // handle request 104 | AXI4Lite_BFlit#(0) bflit = defaultValue; 105 | case (awflit.awaddr[15:0]) 106 | 16'h0000: r_msip <= unpack(data[0] & strb[0]); 107 | 16'h4000: begin 108 | let cmp_bot = merge(r_mtimecmp, truncate(data), truncate(strb)); 109 | `ifndef XLEN64 // 32-bit only 110 | let newval = merge(cmp_bot, zeroExtend(cmp_top) << 32, unpack(8'hF0)); 111 | `else 112 | let newval = cmp_bot; 113 | `endif 114 | r_mtimecmp <= newval; 115 | r_mtip[1] <= False; 116 | end 117 | `ifndef XLEN64 // 32-bit only 118 | 16'h4004: 119 | cmp_top <= merge(truncateLSB(r_mtimecmp), truncate(data), truncate(strb)); 120 | `endif 121 | 16'hBFF8: bflit.bresp = SLVERR; 122 | default: bflit.bresp = SLVERR; 123 | endcase 124 | // put response 125 | wRsp.enq(bflit); 126 | // debug 127 | printTLogPlusArgs("clint", $format("clint >>> ", fshow(awflit))); 128 | printTLogPlusArgs("clint", $format("clint >>> ", fshow(wflit))); 129 | printTLogPlusArgs("clint", $format("clint >>> ", fshow(bflit))); 130 | endrule 131 | rule writeRsp; 132 | shim.master.b.put(wRsp.first); 133 | wRsp.deq; 134 | endrule 135 | // AXI4 read request handling 136 | rule readReq; 137 | // get request 138 | let arflit <- get(shim.master.ar); 139 | // pre-format data / strb 140 | Bit#(TLog#(TDiv#(data_sz, 8))) byteShftAmnt = arflit.araddr[topBitIdx:0]; 141 | Bit#(TAdd#(3, TLog#(TDiv#(data_sz, 8)))) bitShftAmnt = zeroExtend(byteShftAmnt) << 3; 142 | // handle request 143 | AXI4Lite_RFlit#(data_sz, 0) rflit = defaultValue; 144 | case (arflit.araddr[15:0]) 145 | 16'h0000: rflit.rdata = zeroExtend(pack(r_msip)) << bitShftAmnt; 146 | 16'h4000: rflit.rdata = zeroExtend(r_mtimecmp) << bitShftAmnt; 147 | 16'hBFF8: rflit.rdata = zeroExtend(r_mtime) << bitShftAmnt; 148 | `ifndef XLEN64 // 32-bit only 149 | 16'h4004: rflit.rdata = zeroExtend(r_mtimecmp >> 32) << bitShftAmnt; 150 | 16'hBFFC: rflit.rdata = zeroExtend(r_mtime >> 32) << bitShftAmnt; 151 | `endif 152 | default: rflit.rresp = SLVERR; 153 | endcase 154 | // put response 155 | rRsp.enq(rflit); 156 | // debug 157 | printTLogPlusArgs("clint", $format("clint >>> ", fshow(arflit))); 158 | printTLogPlusArgs("clint", $format("clint >>> ", fshow(rflit))); 159 | endrule 160 | rule readRsp; 161 | // put response 162 | shim.master.r.put(rRsp.first); 163 | rRsp.deq; 164 | endrule 165 | // wire up interfaces 166 | interface axiLiteSlave = shim.slave; 167 | method peekMSIP = r_msip; 168 | method peekMTIP = r_mtip[0]; 169 | endmodule 170 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_TraceUtils.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | //import BlueUtils :: *; 30 | //import RVBS_BasicTypes :: *; 31 | //import RVBS_StateTypes :: *; 32 | 33 | /////////////////// 34 | // Logging utils // 35 | //////////////////////////////////////////////////////////////////////////////// 36 | 37 | // pretty printing and logging utils 38 | function Fmt gpRegName(Bit#(5) r) = $format("x%0d", r); 39 | function Fmt abiRegName(Bit#(5) r) = case (r) 40 | 0: $format("zero"); 41 | 1: $format("ra"); 42 | 2: $format("sp"); 43 | 3: $format("gp"); 44 | 4: $format("tp"); 45 | 5, 6, 7: $format("t%0d", r - 5); 46 | 8: $format("s0/fp"); 47 | 9: $format("s1"); 48 | 10, 11, 12, 13, 14, 15, 16, 17: $format("a%0d", r - 10); 49 | 18, 19, 20, 21, 22, 23, 24, 25, 26, 27: $format("s%0d", r - 16); 50 | 28, 29, 30, 31: $format("t%0d", r - 25); 51 | endcase; 52 | function Fmt bothRegName(Bit#(5) r) = 53 | $format(gpRegName(r), "(", abiRegName(r), ")"); 54 | `ifdef PRINT_ABI_REG_NAME 55 | //function Fmt rName(Bit#(5) r) = abiRegName(r); 56 | function Fmt rName(Bit#(5) r) = bothRegName(r); 57 | `else 58 | //function Fmt rName(Bit#(5) r) = gpRegName(r); 59 | function Fmt rName(Bit#(5) r) = bothRegName(r); 60 | `endif 61 | `ifdef RVXCHERI 62 | typedef union tagged { 63 | Bit#(5) SCR; 64 | Bit#(5) CR; 65 | Bit#(5) GPR; 66 | } TraceRegType; 67 | function Fmt traceReg(TraceRegType idx) = case (idx) matches 68 | tagged SCR .scr: specialCapName(scr); 69 | tagged CR .cr: $format("c%0d", cr); 70 | tagged GPR .gpr: rName(gpr); 71 | endcase; 72 | function Fmt specialCapName(Bit#(5) idx) = case (idx) 73 | 0: $format("pcc"); 74 | 1: $format("ddc"); 75 | `ifdef RVN 76 | 4: $format("utcc"); 77 | 5: $format("utdc"); 78 | 6: $format("uscratchc"); 79 | 7: $format("uepcc"); 80 | `endif 81 | `ifdef SUPERVISOR_MODE 82 | 12: $format("stcc"); 83 | 13: $format("stdc"); 84 | 14: $format("sscratchc"); 85 | 15: $format("sepcc"); 86 | `endif 87 | 28: $format("mtcc"); 88 | 29: $format("mtdc"); 89 | 30: $format("mscratchc"); 90 | 31: $format("mepcc"); 91 | default: $format("unknown"); 92 | endcase; 93 | `endif 94 | 95 | // CSRs logging 96 | function Fmt csrName(Bit#(12) idx) = case (idx) 97 | `ifdef USER_MODE 98 | /* 99 | 12'h000: $format("ustatus"); 100 | 12'h004: $format("uie"); 101 | 12'h005: $format("utvec"); 102 | 12'h040: $format("uscratch"); 103 | 12'h041: $format("uepc"); 104 | 12'h042: $format("ucause"); 105 | 12'h043: $format("utval"); 106 | 12'h044: $format("uip"); 107 | */ 108 | `endif 109 | //12'h001: $format("fflags"); 110 | //12'h002: $format("frm"); 111 | //12'h003: $format("fcsr"); 112 | `ifdef SUPERVISOR_MODE 113 | 12'h100: $format("sstatus"); 114 | 12'h102: $format("sedeleg"); 115 | 12'h103: $format("sideleg"); 116 | 12'h104: $format("sie"); 117 | 12'h105: $format("stvec"); 118 | //12'h106: $format("scounteren"); 119 | 12'h140: $format("sscratch"); 120 | 12'h141: $format("sepc"); 121 | 12'h142: $format("scause"); 122 | 12'h143: $format("stval"); 123 | 12'h144: $format("sip"); 124 | 12'h180: $format("satp"); 125 | `endif 126 | 12'h300: $format("mstatus"); 127 | 12'h301: $format("misa"); 128 | 12'h302: $format("medeleg"); 129 | 12'h303: $format("mideleg"); 130 | 12'h304: $format("mie"); 131 | 12'h305: $format("mtvec"); 132 | //12'h306: $format("mcounteren"); 133 | //12'h323, 12'h324: // TODO through to 12'h33F 134 | // $format("mhpmevent%0d", idx - 12'h320); 135 | 12'h340: $format("mscratch"); 136 | 12'h341: $format("mepc"); 137 | 12'h342: $format("mcause"); 138 | 12'h343: $format("mtval"); 139 | 12'h344: $format("mip"); 140 | 12'h3A0, 12'h3A1, 12'h3A2, 12'h3A3: 141 | $format("pmpcfg%0d", idx - 12'h3A0); 142 | 12'h3B0, 12'h3B1, 12'h3B2, 12'h3B3, 12'h3B4, 12'h3B5, 12'h3B6, 12'h3B7, 12'h3B8, 12'h3B9, 12'h3BA, 12'h3BB, 12'h3BC, 12'h3BD, 12'h3BE, 12'h3BF: 143 | $format("pmpaddr%0d", idx - 12'h3B0); 144 | //12'7A0: $format("tselect"); 145 | //12'7A1: $format("tdata1"); 146 | //12'7A2: $format("tdata2"); 147 | //12'7A3: $format("tdata3"); 148 | //12'7B0: $format("dcsr"); 149 | //12'7B1: $format("dpc"); 150 | //12'7B2: $format("dscratch"); 151 | //12'hB00: $format("mcycle"); 152 | //12'hB02: $format("minstret"); 153 | //12'hB03, 12'hB04, 12'hB05, 12'hB06, 12'hB07, 12'hB08, 12'hB09, 12'hB0A, 12'hB0B, 12'hB0C, 12'hB0D, 12'hB0E, 12'hB0F: // TODO through to 12'hB1F 154 | // $format("mhpmcounter%0d", idx - 12'hB00); 155 | `ifndef XLEN64 156 | //12'hB80: $format("mcycleh"); 157 | //12'hB82: $format("minsreth"); 158 | //12'hB83, 12'hB84, 12'hB85, 12'hB86, 12'hB87, 12'hB88, 12'hB89, 12'hB8A, 12'hB8B, 12'hB8C, 12'hB8D, 12'hB8E, 12'hB8F: // TODO through to 12'hB9F 159 | // $format("hpmcounter%0dh", idx - 12'hB80); 160 | `endif 161 | 12'hC00: $format("cycle"); 162 | //12'hC01: $format("time"); 163 | //12'hC02: $format("insret"); 164 | //12'hC03, 12'hC04, 12'hC05, 12'hC06, 12'hC07, 12'hC08, 12'hC09, 12'hC0A, 12'hC0B, 12'hC0C, 12'hC0D, 12'hC0E, 12'hC0F: // TODO through to 12'hC1F 165 | // $format("hpmcounter%0d", idx - 12'hC00); 166 | `ifndef XLEN64 167 | //12'hC80: $format("cycleh"); 168 | //12'hC81: $format("timeh"); 169 | //12'hC82: $format("insreth"); 170 | //12'hC83, 12'hC84, 12'hC85, 12'hC86, 12'hC87, 12'hC88, 12'hC89, 12'hC8A, 12'hC8B, 12'hC8C, 12'hC8D, 12'hC8E, 12'hC8F: // TODO through to 12'hC9F 171 | // $format("hpmcounter%0dh", idx - 12'hC80); 172 | `endif 173 | 12'hF11: $format("mvendorid"); 174 | 12'hF12: $format("marchid"); 175 | 12'hF13: $format("mimpid"); 176 | 12'hF14: $format("mhartid"); 177 | default: $format("unknown"); 178 | endcase; 179 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_Zicsr.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | 30 | import Vector :: *; 31 | import Printf :: *; 32 | 33 | import Recipe :: *; 34 | import BID :: *; 35 | import BlueBasics :: *; 36 | import BlueUtils :: *; 37 | import BitPat :: *; 38 | 39 | import RVBS_Types :: *; 40 | import RVBS_Trap :: *; 41 | import RVBS_TraceUtils :: *; 42 | import RVBS_TraceInsts :: *; 43 | import RVBS_MemAccess :: *; 44 | 45 | ////////////////////////////////////////////// 46 | // Control and Status Register Instructions // 47 | //////////////////////////////////////////////////////////////////////////////// 48 | 49 | /* 50 | I-type 51 | 52 | 31 20 19 15 14 12 11 7 6 0 53 | +-------------------------------------+--------+--------+--------+----------+ 54 | | imm[11:0] | rs1 | funct3 | rd | opcode | 55 | +-------------------------------------+--------+--------+--------+----------+ 56 | */ 57 | 58 | `define instCSRCommon\ 59 | Bool shouldTrap; // is the csr access authorized?\ 60 | shouldTrap = s.currentPrivLvl < toPrivLvl(r.idx[9:8]); // privilege level access\ 61 | shouldTrap = shouldTrap || (r.rEffects != NOWRITE && r.idx[11:10] == 2'b11); // writes to read-only registers\ 62 | shouldTrap = shouldTrap || (r.idx == 12'h180 && s.currentPrivLvl == S && s.csrs.mstatus.tvm); // satp register accessed with TVM = 1\ 63 | if (shouldTrap) raiseException(s, IllegalInst);\ 64 | else begin\ 65 | // XXX for some reason, bluespec doesn't like this way to write it:\ 66 | // s.rGPR(rd) <- s.csrs.req(r);\ 67 | let mval <- s.csrs.req(r);\ 68 | if (mval matches tagged Valid .val) s.wGPR(rd, val);\ 69 | else raiseException(s, IllegalInst);\ 70 | end 71 | 72 | // funct3 = CSRRW = 001 73 | // opcode = 1110011 74 | // pseudo-op CSRW 75 | function Action instrCSRRW(RVState s, Bit#(12) imm, Bit#(5) rs1, Bit#(5) rd) = action 76 | /* TODO 77 | `If rd = x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read.` 78 | Do the write side effect take place ? 79 | */ 80 | let r = (rd == 0) ? rwCSRReqNoRead(imm, s.rGPR(rs1)) : rwCSRReq(imm, s.rGPR(rs1)); 81 | `instCSRCommon 82 | //logInst(s, fmtInstI("csrrw", rd, rs1, imm), csrName(imm)); 83 | logInst(s, fmtInstI("csrrw", rd, rs1, imm), $format("rs1 (0x%0x) into ", s.rGPR(rs1), csrName(imm))); 84 | endaction; 85 | 86 | // funct3 = CSRRS = 010 87 | // opcode = 1110011 88 | // pseudo-op CSRR 89 | // XXX RDCYCLE[H], RDTIME[H], RDINSTRET[H] 90 | function Action instrCSRRS(RVState s, Bit#(12) imm, Bit#(5) rs1, Bit#(5) rd) = action 91 | /* TODO 92 | `if rs1 = x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSR.` 93 | Do the read side effect take place ? 94 | */ 95 | let r = (rs1 == 0) ? rsCSRReqNoWrite(imm, s.rGPR(rs1)) : rsCSRReq(imm, s.rGPR(rs1)); 96 | `instCSRCommon 97 | //logInst(s, fmtInstI("csrrs", rd, rs1, imm), csrName(imm)); 98 | logInst(s, fmtInstI("csrrs", rd, rs1, imm), $format("rs1 (0x%0x) into ", s.rGPR(rs1), csrName(imm))); 99 | endaction; 100 | 101 | // funct3 = CSRRC = 011 102 | // opcode = 1110011 103 | function Action instrCSRRC(RVState s, Bit#(12) imm, Bit#(5) rs1, Bit#(5) rd) = action 104 | /* TODO 105 | `if rs1 = x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects that might otherwise occur on a CSR write, such as raising illegal instruction exceptions on accesses to read-only CSR.` 106 | Do the read side effect take place ? 107 | */ 108 | let r = (rs1 == 0) ? rcCSRReqNoWrite(imm, s.rGPR(rs1)) : rcCSRReq(imm, s.rGPR(rs1)); 109 | `instCSRCommon 110 | //logInst(s, fmtInstI("csrrc", rd, rs1, imm), csrName(imm)); 111 | logInst(s, fmtInstI("csrrc", rd, rs1, imm), $format("rs1 (0x%0x) into ", s.rGPR(rs1), csrName(imm))); 112 | endaction; 113 | 114 | // funct3 = CSRRWI = 101 115 | // opcode = 1110011 116 | function Action instrCSRRWI(RVState s, Bit#(12) imm, Bit#(5) zimm, Bit#(5) rd) = action 117 | /* TODO 118 | `if rd = x0, then the instruction shall not read the CSR and shall not cause any of the side-effects that might occur on a CSR read.` 119 | Do the write side effect take place ? 120 | */ 121 | let r = (rd == 0) ? rwCSRReqNoRead(imm, zeroExtend(zimm)) : rwCSRReq(imm, zeroExtend(zimm)); 122 | `instCSRCommon 123 | logInst(s, fmtInstI("csrrwi", rd, zimm, imm), csrName(imm)); 124 | endaction; 125 | 126 | // funct3 = CSRRSI = 110 127 | // opcode = 1110011 128 | function Action instrCSRRSI(RVState s, Bit#(12) imm, Bit#(5) zimm, Bit#(5) rd) = action 129 | /* TODO 130 | `if the the uimm[4:0] (zimm) field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write.` 131 | Do the read side effect take place ? 132 | */ 133 | let r = (zimm == 0) ? rsCSRReqNoWrite(imm, zeroExtend(zimm)) : rsCSRReq(imm, zeroExtend(zimm)); 134 | `instCSRCommon 135 | logInst(s, fmtInstI("csrrsi", rd, zimm, imm), csrName(imm)); 136 | endaction; 137 | 138 | // funct3 = CSRRCI = 111 139 | // opcode = 1110011 140 | function Action instrCSRRCI(RVState s, Bit#(12) imm, Bit#(5) zimm, Bit#(5) rd) = action 141 | /* TODO 142 | `if the the uimm[4:0] (zimm) field is zero, then these instructions will not write to the CSR, and shall not cause any of the side effects that might otherwise occur on a CSR write.` 143 | Do the read side effect take place ? 144 | */ 145 | let r = (zimm == 0) ? rcCSRReqNoWrite(imm, zeroExtend(zimm)) : rcCSRReq(imm, zeroExtend(zimm)); 146 | `instCSRCommon 147 | logInst(s, fmtInstI("csrrci", rd, zimm, imm), csrName(imm)); 148 | endaction; 149 | 150 | `undef instCSRCommon 151 | 152 | module [ISADefModule] mkExt_Zicsr#(RVState s) (); 153 | 154 | defineInstEntry("csrrw", pat(v, v, n(3'b001), v, n(7'b1110011)), instrCSRRW(s)); 155 | defineInstEntry("csrrs", pat(v, v, n(3'b010), v, n(7'b1110011)), instrCSRRS(s)); 156 | defineInstEntry("csrrc", pat(v, v, n(3'b011), v, n(7'b1110011)), instrCSRRC(s)); 157 | defineInstEntry("csrrwi", pat(v, v, n(3'b101), v, n(7'b1110011)), instrCSRRWI(s)); 158 | defineInstEntry("csrrsi", pat(v, v, n(3'b110), v, n(7'b1110011)), instrCSRRSI(s)); 159 | defineInstEntry("csrrci", pat(v, v, n(3'b111), v, n(7'b1110011)), instrCSRRCI(s)); 160 | 161 | endmodule 162 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_64_C.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Printf :: *; 30 | import List :: *; 31 | 32 | import BID :: *; 33 | import Recipe :: *; 34 | import BlueUtils :: *; 35 | import BitPat :: *; 36 | 37 | import RVBS_Types :: *; 38 | import RVBS_Trap :: *; 39 | import RVBS_Base_RV64I :: *; 40 | import RVBS_MemAccess :: *; 41 | 42 | // RVC 3-bit reg identifier to RVI 5-bit reg identifier 43 | function Bit#(5) regID (Bit#(3) x) = {2'b01, x}; 44 | // BitPat guarded variable predicates 45 | function Bool ez (Bit#(n) x) = x == 0; 46 | function Bool eq2 (Bit#(n) x) = x == 2; 47 | function Bool neq (Bit#(n) x, Bit#(n) y) = x != y; 48 | function Bool nez (Bit#(n) x) = x != 0; 49 | function Bool n0_n2 (Bit#(n) x) = x != 0 && x != 2; 50 | function Bool nzimm (Bit#(16) x) = x[12] != 0 || x[6:2] != 0; 51 | 52 | ///////////////////////////////// 53 | // Load and Store Instructions // 54 | //////////////////////////////////////////////////////////////////////////////// 55 | 56 | ////////////////////////////////////////// 57 | // Stack-Pointer-Based Loads and Stores // 58 | ////////////////////////////////////////// 59 | 60 | /* 61 | CI-type 62 | 63 | 15 13 12 11 7 6 2 1 0 64 | +--------+-----+-------------+--------------+----+ 65 | | funct3 | imm | rd/rs1 | imm | op | 66 | +--------+-----+-------------+--------------+----+ 67 | 68 | */ 69 | 70 | // funct3 = C.LDSP = 011 71 | // op = C2 = 10 72 | function Recipe instrC_LDSP (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(2) imm4_3, Bit#(3) imm8_6) = 73 | load(s, LoadArgs{name: "ld", numBytes: 8, sgnExt: True}, zeroExtend({imm8_6, imm5, imm4_3, 3'b000}), 2, rd); 74 | 75 | /* 76 | CSS-type 77 | 78 | 15 13 12 7 6 2 1 0 79 | +--------+-------------------+--------------+----+ 80 | | funct3 | imm | rs2 | op | 81 | +--------+-------------------+--------------+----+ 82 | 83 | */ 84 | 85 | // funct3 = C.SDSP = 111 86 | // op = C2 = 10 87 | function Recipe instrC_SDSP (RVState s, Bit#(3) imm5_3, Bit#(3) imm8_6, Bit#(5) rs2) = 88 | store(s, StrArgs{name: "sd", numBytes: 8}, zeroExtend({imm8_6,imm5_3[2]}), rs2, 2, {imm5_3[1:0], 3'b000}); 89 | 90 | ///////////////////////////////////// 91 | // Register-Based Loads and Stores // 92 | ///////////////////////////////////// 93 | 94 | /* 95 | CL-type 96 | 97 | 15 13 12 10 9 7 6 5 4 2 1 0 98 | +--------+-------+----------+-----+---------+----+ 99 | | funct3 | imm | rs1' | imm | rd' | op | 100 | +--------+-------+----------+-----+---------+----+ 101 | 102 | */ 103 | 104 | // funct3 = C.LD = 011 105 | // op = C0 = 00 106 | function Recipe instrC_LD (RVState s, Bit#(3) o5_3, Bit#(3) rs1_, Bit#(2) o7_6, Bit#(3) rd_) = 107 | load(s, LoadArgs{name: "ld", numBytes: 8, sgnExt: True}, zeroExtend({o7_6, o5_3, 3'b000}), regID(rs1_), regID(rd_)); 108 | 109 | /* 110 | CS-type 111 | 112 | 15 13 12 10 9 7 6 5 4 2 1 0 113 | +--------+-------+----------+-----+---------+----+ 114 | | funct3 | imm | rs1' | imm | rs2' | op | 115 | +--------+-------+----------+-----+---------+----+ 116 | 117 | */ 118 | 119 | // funct3 = C.SD = 111 120 | // op = C0 = 00 121 | function Recipe instrC_SD (RVState s, Bit#(3) o5_3, Bit#(3) rs1_, Bit#(2) o7_6, Bit#(3) rs2_) = 122 | store(s, StrArgs{name: "sd", numBytes: 8}, zeroExtend({o7_6, o5_3[2]}), regID(rs2_), regID(rs1_), {o5_3[1:0], 3'b000}); 123 | 124 | /////////////////////////////////////////// 125 | // Integer Register-Immediate Operations // 126 | /////////////////////////////////////////// 127 | 128 | /* 129 | CI-type 130 | 131 | 15 13 12 11 7 6 2 1 0 132 | +--------+-----+-------------+--------------+----+ 133 | | funct3 | imm | rd/rs1 | imm | op | 134 | +--------+-----+-------------+--------------+----+ 135 | 136 | */ 137 | 138 | // funct3 = C.ADDIW = 001 139 | // op = C1 = 01 140 | function Action instrC_ADDIW (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(5) imm4_0) = 141 | instrADDIW(s, signExtend({imm5, imm4_0}), rd, rd); 142 | 143 | ////////////////////////////////////////// 144 | // Integer Register-Register Operations // 145 | ////////////////////////////////////////// 146 | 147 | /* 148 | CS-type 149 | 150 | 15 10 9 7 6 5 4 2 1 0 151 | +----------------+----------+-----+---------+----+ 152 | | funct6 | rs1' |funct| rs2' | op | 153 | +----------------+----------+-----+---------+----+ 154 | 155 | */ 156 | 157 | // funct6 = C.ADDW = 100111 158 | // funct = 01 159 | // op = C1 = 01 160 | function Action instrC_ADDW (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 161 | instrADDW(s, regID(rs2_), regID(rd_), regID(rd_)); 162 | 163 | // funct6 = C.SUBW = 100111 164 | // funct = 00 165 | // op = C1 = 01 166 | function Action instrC_SUBW (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 167 | instrSUBW(s, regID(rs2_), regID(rd_), regID(rd_)); 168 | 169 | //////////////////////////////////////////////////////////////////////////////// 170 | 171 | // funct3 = C.SLLI = 000 172 | // op = C2 = 10 173 | function Action instrC_SLLI64 (RVState s, Bit#(1) i5, Bit#(5) rd, Bit#(5) i4_0) = 174 | instrSLLI64(s, zeroExtend({i5, i4_0}), rd, rd); 175 | 176 | // funct3 = C.SRLI = 100 177 | // funct2 = 00 178 | // op = C1 = 01 179 | function Action instrC_SRLI64 (RVState s, Bit#(1) i5, Bit#(3) rd_, Bit#(5) i4_0) = 180 | instrSRLI64 (s, zeroExtend({i5,i4_0}), regID(rd_), regID(rd_)); 181 | 182 | // funct3 = C.SRAI = 100 183 | // funct2 = 01 184 | // op = C1 = 01 185 | function Action instrC_SRAI64 (RVState s, Bit#(1) i5, Bit#(3) rd_, Bit#(5) i4_0) = 186 | instrSRAI64 (s, zeroExtend({i5,i4_0}), regID(rd_), regID(rd_)); 187 | 188 | module [ISADefModule] mkExt_64_C#(RVState s) (); 189 | 190 | defineInstEntry("c.ldsp", pat(n(3'b011), v, gv(neq(0)), v, v, n(2'b10)), instrC_LDSP(s)); 191 | defineInstEntry("c.sdsp", pat(n(3'b111), v, v, v, n(2'b10)), instrC_SDSP(s)); 192 | defineInstEntry("c.ld", pat(n(3'b011), v, v, v, v, n(2'b00)), instrC_LD(s)); 193 | defineInstEntry("c.sd", pat(n(3'b111), v, v, v, v, n(2'b00)), instrC_SD(s)); 194 | defineInstEntry("c.addiw", pat(n(3'b001), v, gv(nez), v, n(2'b01)), instrC_ADDIW(s)); 195 | defineInstEntry("c.slli", pat(n(3'b000), v, gv(nez), v, n(2'b10)), instrC_SLLI64(s)); 196 | defineInstEntry("c.srli", pat(n(3'b100), v, n(2'b00), v, v, n(2'b01)), instrC_SRLI64(s)); 197 | defineInstEntry("c.srai", pat(n(3'b100), v, n(2'b01), v, v, n(2'b01)), instrC_SRAI64(s)); 198 | defineInstEntry("c.addw", pat(n(6'b100111), v, n(2'b01), v, n(2'b01)), instrC_ADDW(s)); 199 | defineInstEntry("c.subw", pat(n(6'b100111), v, n(2'b00), v, n(2'b01)), instrC_SUBW(s)); 200 | 201 | endmodule 202 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_State.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import ConfigReg :: *; 30 | import Vector :: *; 31 | import SpecialFIFOs :: *; 32 | 33 | import BlueUtils :: *; 34 | import SourceSink :: *; 35 | import MasterSlave :: *; 36 | import Recipe :: *; 37 | import RVBS_TraceUtils :: *; 38 | import RVBS_Types :: *; 39 | import RVBS_CSRs :: *; 40 | import RVBS_Trap :: *; 41 | `ifdef PMP 42 | import RVBS_PMP :: *; 43 | `endif 44 | `ifdef SUPERVISOR_MODE 45 | import RVBS_VMTranslate :: *; 46 | `endif 47 | `ifdef RVXCHERI 48 | import CHERICap :: *; 49 | `endif 50 | 51 | `ifdef RVFI_DII 52 | import RVFI_DII_Bridge :: *; 53 | import FIFO :: *; 54 | `endif 55 | 56 | //////////////////////////////// 57 | // RISC-V architectural state // 58 | //////////////////////////////////////////////////////////////////////////////// 59 | 60 | module [Module] mkState#( 61 | VAddr reset_pc, 62 | RVMem imem 63 | , RVMem dmem 64 | `ifdef SUPERVISOR_MODE 65 | , RVMem ivmmem 66 | , RVMem dvmmem 67 | `endif 68 | `ifdef RVFI_DII 69 | `ifdef RVXCHERI 70 | , RVFI_DII_Bridge#(XLEN, 64, 0) rvfi_dii_bridge 71 | `else 72 | , RVFI_DII_Bridge#(XLEN, XLEN, 0) rvfi_dii_bridge 73 | `endif 74 | `endif 75 | ) (RVState); 76 | RVState s; 77 | 78 | //s.currentPrivLvl <- mkReg(M); 79 | s.currentPrivLvl <- mkConfigReg(M); 80 | s.currentXLEN = case (s.currentPrivLvl) 81 | M: s.csrs.misa.mxl; 82 | `ifdef XLEN64 // MAX_XLEN > 32 83 | S: s.csrs.mstatus.sxl; 84 | U: s.csrs.mstatus.uxl; 85 | `else 86 | S, U: XL32; 87 | `endif 88 | default: XLUNK; 89 | endcase; 90 | // basic state 91 | s.pc <- mkArchReg(reset_pc); 92 | s.instByteSz <- mkBypassRegU; 93 | s.pendingIFetchException <- mkConfigCReg(3, Invalid); 94 | s.pendingException <- mkCReg(2, Invalid); 95 | s.pendingMemException <- mkCReg(2, Invalid); 96 | `ifdef RVXCHERI 97 | s.pendingIFetchCapException <- mkConfigCReg(3, Invalid); 98 | s.pendingCapException <- mkCReg(2, Invalid); 99 | s.pendingMemCapException <- mkCReg(2, Invalid); 100 | `endif 101 | `ifdef RVXCHERI 102 | CapType nCap = nullCap; 103 | CapType yCap = almightyCap; 104 | s.regFile <- mkRegFileInitZ(nCap, nCap); 105 | function readGPR(i); return getAddr(s.regFile.r[i]); endfunction 106 | s.rGPR = readGPR; 107 | function writeGPR(i, x) = action 108 | s.regFile.r[i] <= nullWithAddr(x); 109 | printTLogPlusArgs("itrace", $format(rName(i)," <= 0x%0x", x)); 110 | endaction; 111 | s.wGPR = writeGPR; 112 | function readCR(i); return s.regFile.r[i]; endfunction 113 | s.rCR = readCR; 114 | function writeCR(i, x) = action 115 | s.regFile.r[i] <= x; 116 | printTLogPlusArgs("itrace", $format("c%0d <= ", i, showCHERICap(x))); 117 | endaction; 118 | s.wCR = writeCR; 119 | `else 120 | s.regFile <- mkRegFileZ; 121 | function readGPR(i); return s.regFile.r[i]; endfunction 122 | s.rGPR = readGPR; 123 | function writeGPR(i, x) = action 124 | s.regFile.r[i] <= x; 125 | printTLogPlusArgs("itrace", $format(rName(i), " <= 0x%0x", x)); 126 | endaction; 127 | s.wGPR = writeGPR; 128 | `endif 129 | s.csrs <- mkCSRs(); 130 | `ifdef RVXCHERI 131 | // CHERI specific state 132 | s.pcc <- mkArchReg(setAddr(yCap, reset_pc).value); 133 | s.ddc <- mkArchReg(yCap); 134 | `ifdef RVN 135 | s.utcc <- mkArchReg(yCap); 136 | s.utdc <- mkArchReg(nCap); 137 | s.uscratchc <- mkArchReg(nCap); 138 | s.uepcc <- mkArchReg(yCap); 139 | `endif 140 | `ifdef SUPERVISOR_MODE 141 | s.stcc <- mkArchReg(yCap); 142 | s.stdc <- mkArchReg(nCap); 143 | s.sscratchc <- mkArchReg(nCap); 144 | s.sepcc <- mkArchReg(yCap); 145 | `endif 146 | s.mtcc <- mkArchReg(yCap); 147 | s.mtdc <- mkArchReg(nCap); 148 | s.mscratchc <- mkArchReg(nCap); 149 | s.mepcc <- mkArchReg(yCap); 150 | function getCapSpecial(idx) = case (idx) 151 | 0: Valid(tuple4(U, False, True, asIfc(s.pcc))); 152 | 1: Valid(tuple4(U, False, False, asIfc(s.ddc))); 153 | `ifdef RVN 154 | 4: Valid(tuple4(U, True, False, asIfc(s.utcc))); 155 | 5: Valid(tuple4(U, True, False, asIfc(s.utdc))); 156 | 6: Valid(tuple4(U, True, False, asIfc(s.uscratchc))); 157 | 7: Valid(tuple4(U, True, False, asIfc(s.uepcc))); 158 | `endif 159 | `ifdef SUPERVISOR_MODE 160 | 12: Valid(tuple4(S, True, False, asIfc(s.stcc))); 161 | 13: Valid(tuple4(S, True, False, asIfc(s.stdc))); 162 | 14: Valid(tuple4(S, True, False, asIfc(s.sscratchc))); 163 | 15: Valid(tuple4(S, True, False, asIfc(s.sepcc))); 164 | `endif 165 | 28: Valid(tuple4(M, True, False, asIfc(s.mtcc))); 166 | 29: Valid(tuple4(M, True, False, asIfc(s.mtdc))); 167 | 30: Valid(tuple4(M, True, False, asIfc(s.mscratchc))); 168 | 31: Valid(tuple4(M, True, False, asIfc(s.mepcc))); 169 | default: Invalid; 170 | endcase; 171 | s.getCSpecial = getCapSpecial; 172 | `endif 173 | function Action upPC(VAddr newpc) = action 174 | s.pc <= newpc; 175 | `ifdef RVXCHERI 176 | Exact#(CapType) tmp = setOffset(s.pcc, newpc); 177 | //XXX TODO check rep somehow? 178 | s.pcc <= tmp.value; 179 | `endif 180 | endaction; 181 | s.updatePC = upPC; 182 | // Memory interfaces 183 | s.readMem <- mkBypassFIFOF; 184 | s.writeMem <- mkBypassFIFOF; 185 | s.imem = imem; 186 | s.dmem = dmem; 187 | `ifdef SUPERVISOR_MODE 188 | s.ivmmem = ivmmem; 189 | s.dvmmem = dvmmem; 190 | `endif 191 | // PMP lookup interfaces 192 | `ifdef PMP 193 | function preInstView(x) = x.preInstView[0]; 194 | let pmpcfgs = concat(map(preInstView, s.csrs.pmpcfg)); 195 | let pmpaddrs = map(preInstView, s.csrs.pmpaddr); 196 | PMPLookup pmp0 <- mkPMPLookup(pmpcfgs, pmpaddrs, s.currentPrivLvl); 197 | PMPLookup pmp1 <- mkPMPLookup(pmpcfgs, pmpaddrs, s.currentPrivLvl); 198 | `ifdef SUPERVISOR_MODE 199 | /* 200 | PMPLookup ipmp[2] <- virtualize(pmp0, 2); 201 | PMPLookup dpmp[2] <- virtualize(pmp1, 2); 202 | s.ipmp = ipmp[1]; 203 | s.dpmp = dpmp[1]; 204 | s.ivmpmp = ipmp[0]; 205 | s.dvmpmp = dpmp[0]; 206 | */ 207 | s.ipmp = pmp0; 208 | s.dpmp = pmp1; 209 | s.ivmpmp <- mkPMPLookup(pmpcfgs, pmpaddrs, s.currentPrivLvl); 210 | s.dvmpmp <- mkPMPLookup(pmpcfgs, pmpaddrs, s.currentPrivLvl); 211 | `else 212 | s.ipmp = pmp0; 213 | s.dpmp = pmp1; 214 | `endif 215 | `endif 216 | // Virtual Memory lookup interfaces 217 | `ifdef SUPERVISOR_MODE 218 | `ifdef PMP 219 | s.ivm <- mkVMLookup(s.csrs, s.ivmmem, s.ivmpmp); 220 | s.dvm <- mkVMLookup(s.csrs, s.dvmmem, s.dvmpmp); 221 | `else 222 | s.ivm <- mkVMLookup(s.csrs, s.ivmmem); 223 | s.dvm <- mkVMLookup(s.csrs, s.dvmmem); 224 | `endif 225 | `endif 226 | `ifdef RVFI_DII 227 | s.iFF <- mkFIFO; 228 | s.count <- mkReg(0); 229 | s.exc_tgt <- mkCReg(2, Invalid); 230 | s.mem_addr <- mkCReg(2, 0); 231 | s.mem_wdata <- mkCReg(2, 0); 232 | s.mem_wmask <- mkCReg(2, 0); 233 | s.rvfi_dii_bridge = rvfi_dii_bridge; 234 | `endif 235 | 236 | return s; 237 | endmodule 238 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_BasicTypes.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | // static parameters 30 | Bool static_HAS_M_MODE = True; 31 | 32 | `ifdef SUPERVISOR_MODE 33 | Bool static_HAS_S_MODE = True; 34 | `else 35 | Bool static_HAS_S_MODE = False; 36 | `endif 37 | 38 | `ifdef USER_MODE 39 | Bool static_HAS_U_MODE = True; 40 | `else 41 | Bool static_HAS_U_MODE = False; 42 | `endif 43 | 44 | Bool static_HAS_I_EXT = True; 45 | 46 | `ifdef RVM 47 | Bool static_HAS_M_EXT = True; 48 | `else 49 | Bool static_HAS_M_EXT = False; 50 | `endif 51 | 52 | `ifdef RVC 53 | Bool static_HAS_C_EXT = True; 54 | `else 55 | Bool static_HAS_C_EXT = False; 56 | `endif 57 | 58 | `ifdef RVN 59 | Bool static_HAS_N_EXT = True; 60 | `else 61 | Bool static_HAS_N_EXT = False; 62 | `endif 63 | 64 | /////////////////////////////////// 65 | // Utility modules and functions // 66 | //////////////////////////////////////////////////////////////////////////////// 67 | 68 | `ifdef XLEN64 69 | typedef 64 XLEN; 70 | `else 71 | typedef 32 XLEN; 72 | `endif 73 | 74 | //TODO for SLL instruction, use something like this: 75 | // typedef TSub#(TLog#(XLEN), 1) BitShAmnt; 76 | 77 | // casts between types in the same Bits class 78 | function a cast (b x) provisos (Bits#(a,n), Bits#(b,n)) = unpack(pack(x)); 79 | 80 | // alignment test 81 | `ifdef RVC 82 | function Bool isInstAligned(Bit#(sz) x) provisos (Add#(1, a__, sz)) = x[0] == 0; 83 | `else 84 | function Bool isInstAligned(Bit#(sz) x) provisos (Add#(2, a__, sz)) = x[1:0] == 0; 85 | `endif 86 | 87 | // privilege levels 88 | typedef enum {U = 2'b00, S = 2'b01, Res = 2'b10, M = 2'b11} PrivLvl deriving (Bits, Eq, FShow); 89 | function PrivLvl toPrivLvl(Bit#(2) x) = unpack(x); 90 | instance Ord#(PrivLvl); 91 | function Ordering compare(PrivLvl a, PrivLvl b); 92 | if (a == b) return EQ; 93 | else if (a == Res) return LT; 94 | else if (b == Res) return GT; 95 | else return compare(pack(a), pack(b)); 96 | endfunction 97 | endinstance 98 | 99 | // effective XLEN mode 100 | typedef enum {XLUNK = 2'b00, XL32 = 2'b01, XL64 = 2'b10, XL128 = 2'b11} XLMode deriving (Bits, Eq, FShow); 101 | instance Literal#(XLMode); 102 | function fromInteger (x) = case (x) 103 | 32: XL32; 104 | 64: XL64; 105 | 128: XL128; 106 | default: XLUNK; 107 | endcase; 108 | function inLiteralRange (x, i); 109 | return (i == 32 || x == 64 || x == 128); 110 | endfunction 111 | endinstance 112 | `ifdef XLEN64 113 | XLMode nativeXLEN = XL64; 114 | `else 115 | XLMode nativeXLEN = XL32; 116 | `endif 117 | 118 | // machine interrupt/exception codes 119 | typedef enum { 120 | USoftInt = 0, SSoftInt = 1, MSoftInt = 3, 121 | UTimerInt = 4, STimerInt = 5, MTimerInt = 7, 122 | UExtInt = 8, SExtInt = 9, MExtInt = 11 123 | } IntCode deriving (Bits, Eq, FShow); 124 | typedef enum { 125 | InstAddrAlign = 0, InstAccessFault = 1, IllegalInst = 2, 126 | Breakpoint = 3, LoadAddrAlign = 4, LoadAccessFault = 5, 127 | StrAMOAddrAlign = 6, StrAMOAccessFault = 7, 128 | ECallFromU = 8, ECallFromS = 9, ECallFromM = 11, 129 | InstPgFault = 12, LoadPgFault = 13, StrAMOPgFault = 15 130 | `ifdef RVXCHERI 131 | , CHERIFault = 32 132 | `endif 133 | } ExcCode deriving (Bits, Eq, FShow); 134 | typedef union tagged { 135 | IntCode Interrupt; 136 | ExcCode Exception; 137 | } TrapCode deriving (Eq); 138 | instance Bits#(TrapCode, XLEN); 139 | function Bit#(XLEN) pack (TrapCode c) = case (c) matches // n must be at least 4 + 1 140 | tagged Interrupt .i: {1'b1, zeroExtend(pack(i))}; 141 | tagged Exception .e: {1'b0, zeroExtend(pack(e))}; 142 | endcase; 143 | function TrapCode unpack (Bit#(XLEN) c) = (c[valueOf(XLEN)-1] == 1'b1) ? 144 | tagged Interrupt unpack(truncate(c)) : 145 | tagged Exception unpack(truncate(c)); 146 | endinstance 147 | instance FShow#(TrapCode); 148 | function Fmt fshow(TrapCode cause) = case (cause) matches 149 | tagged Interrupt .i: $format(fshow(i) + $format(" (interrupt %0d)", pack(i))); 150 | tagged Exception .e: $format(fshow(e) + $format(" (exception %0d)", pack(e))); 151 | endcase; 152 | endinstance 153 | //function Bool isValidTrapCode(TrapCode c) = case (c) matches 154 | function Bool isValidTrapCode(Bit#(XLEN) c) = case (unpack(c)) matches 155 | tagged Interrupt .i: case (i) 156 | USoftInt, SSoftInt, MSoftInt, 157 | UTimerInt, STimerInt, MTimerInt, 158 | UExtInt, SExtInt, MExtInt: True; 159 | default: False; 160 | endcase 161 | tagged Exception .e: case (e) 162 | InstAddrAlign, InstAccessFault, IllegalInst, 163 | Breakpoint, LoadAddrAlign, LoadAccessFault, 164 | StrAMOAddrAlign, StrAMOAccessFault, 165 | ECallFromU, ECallFromS, ECallFromM, 166 | InstPgFault, LoadPgFault, StrAMOPgFault 167 | `ifdef RVXCHERI 168 | , CHERIFault 169 | `endif 170 | : True; 171 | default: False; 172 | endcase 173 | endcase; 174 | `ifdef RVXCHERI 175 | // RVXCHERI exception codes 176 | typedef enum { 177 | CapExcNone = 'h00, // None 178 | CapExcLength = 'h01, // Length Violation 179 | CapExcTag = 'h02, // Tag Violation 180 | CapExcSeal = 'h03, // Seal Violation 181 | CapExcType = 'h04, // Type Violation 182 | CapExcCall = 'h05, // Call Trap 183 | CapExcRet = 'h06, // Return Trap 184 | CapExcUnderflowTSS = 'h07, // Underflow of trusted system stack 185 | CapExcUser = 'h08, // User-defined Permision Violation 186 | CapExcTLBNoStore = 'h09, // TLB prohibits store capability 187 | CapExcInexact = 'h0a, // Requested bounds cannot be represented exactly 188 | CapExcGlobal = 'h10, // Global Violation 189 | CapExcPermExe = 'h11, // Permit_Execute Violation 190 | CapExcPermLoad = 'h12, // Permit_Load Violation 191 | CapExcPermStore = 'h13, // Permit_Store Violation 192 | CapExcPermLoadCap = 'h14, // Permit_Load_Capability Violation 193 | CapExcPermStoreCap = 'h15, // Permit_Store_Capability Violation 194 | CapExcPermStoreLocalCap = 'h16, // Permit_Store_Local_Capability Violation 195 | CapExcPermSeal = 'h17, // Permit_Seal Violation 196 | CapExcAccessSysReg = 'h18, // Access_System_Registers Violation 197 | CapExcPermCCall = 'h19, // Premit_CCall Violation 198 | CapExcPermCCallIDC = 'h1a, // Premit_CCall IDC Violation 199 | CapExcPermUnseal = 'h1c // Premit_Unseal Violation 200 | } CapExcCode deriving (Bits, Eq, FShow); 201 | function Fmt showCapCause(CapExcCode cause) = $format(fshow(cause)," (%0d)", pack(cause)); 202 | `endif 203 | typedef struct { 204 | ExcCode excCode; 205 | Bit#(XLEN) tval; 206 | `ifdef RVXCHERI 207 | CapExcCode capExcCode; 208 | Bit#(6) capIdx; 209 | `endif 210 | } ExcToken deriving (Bits, Eq, FShow); 211 | function ExcToken craftExcToken(ExcCode code, Bit#(XLEN) val) = ExcToken { 212 | excCode: code 213 | , tval: val 214 | `ifdef RVXCHERI 215 | , capExcCode: ? 216 | , capIdx: ? 217 | `endif 218 | }; 219 | `ifdef RVXCHERI 220 | function ExcToken craftCapExcToken(CapExcCode code, Bit#(6) idx, Bit#(XLEN) val) = ExcToken { 221 | excCode: CHERIFault, 222 | tval: val, 223 | capExcCode: code, 224 | capIdx: idx 225 | }; 226 | `endif 227 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #- 2 | # Copyright (c) 2018 Alexandre Joannou 3 | # All rights reserved. 4 | # 5 | # This software was developed by SRI International and the University of 6 | # Cambridge Computer Laboratory (Department of Computer Science and 7 | # Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | # DARPA SSITH research programme. 9 | # 10 | # @BERI_LICENSE_HEADER_START@ 11 | # 12 | # Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | # license agreements. See the NOTICE file distributed with this work for 14 | # additional information regarding copyright ownership. BERI licenses this 15 | # file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | # "License"); you may not use this file except in compliance with the 17 | # License. You may obtain a copy of the License at: 18 | # 19 | # http://www.beri-open-systems.org/legal/license-1-0.txt 20 | # 21 | # Unless required by applicable law or agreed to in writing, Work distributed 22 | # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | # CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | # specific language governing permissions and limitations under the License. 25 | # 26 | # @BERI_LICENSE_HEADER_END@ 27 | # 28 | 29 | RVFIDIIDIR = BSV-RVFI-DII 30 | BIDDIR = BID 31 | RECIPEDIR = $(BIDDIR)/Recipe 32 | BITPATDIR = $(BIDDIR)/BitPat 33 | BLUESTUFFDIR = $(BIDDIR)/BlueStuff 34 | AXIDIR = $(BLUESTUFFDIR)/AXI 35 | BLUEBASICSDIR = $(BLUESTUFFDIR)/BlueBasics 36 | BLUEUTILSDIR = $(BLUESTUFFDIR)/BlueUtils 37 | SOCKETUTILSDIR = $(BLUESTUFFDIR)/SocketPacketUtils 38 | RVBSSRCDIR = src 39 | CHERICAPLIBDIR = $(RVBSSRCDIR)/rvbs/cheri-cap-lib 40 | CHERISOCDIR = $(RVBSSRCDIR)/toplevels/CHERISOC 41 | CHERISOCPATH = $(CHERISOCDIR):$(CHERISOCDIR)/PISM/src:%/Libraries/TLM3:%/Libraries/Axi:$(CHERISOCDIR)/TagController/TagController:$(CHERISOCDIR)/TagController/TagController/CacheCore 42 | BSVPATH = +:$(RVBSSRCDIR):$(RVBSSRCDIR)/rvbs:$(RVBSSRCDIR)/toplevels:$(BIDDIR):$(RECIPEDIR):$(BITPATDIR):$(BLUESTUFFDIR):$(AXIDIR):$(BLUEBASICSDIR):$(BLUEUTILSDIR):$(CHERICAPLIBDIR):$(CHERISOCPATH):$(RVFIDIIDIR) 43 | 44 | RVBSSRCS = $(wildcard $(RVBSSRCDIR)/rvbs/*.bsv) 45 | RVBSSRCS += $(wildcard $(RVBSSRCDIR)/*.bsv) 46 | 47 | BSCFLAGS = -p $(BSVPATH) -check-assert 48 | 49 | ifdef MEM_SIZE 50 | BSCFLAGS += -D MEM_SIZE=$(MEM_SIZE) 51 | endif 52 | ifdef MEM_IMG 53 | BSCFLAGS += -D MEM_IMG="\"$(MEM_IMG)\"" 54 | endif 55 | ifdef MEM_DELAY 56 | BSCFLAGS += -D MEM_DELAY 57 | endif 58 | 59 | ifdef NO_LOGS 60 | BSCFLAGS += -D NO_LOGS 61 | endif 62 | ifdef PRINT_ABI_REG_NAME 63 | BSCFLAGS += -D PRINT_ABI_REG_NAME 64 | endif 65 | ifdef FULL_ITRACE 66 | BSCFLAGS += -D FULL_ITRACE 67 | endif 68 | 69 | RVBSNAME := rvbs 70 | BSCFLAGS += -D XLEN32 71 | ifeq ($(XLEN),64) 72 | BSCFLAGS += -D XLEN64 73 | RVBSNAME := $(RVBSNAME)-rv64 74 | else 75 | RVBSNAME := $(RVBSNAME)-rv32 76 | endif 77 | RVBSNAME := $(RVBSNAME)I 78 | ifeq ($(RVM),1) 79 | BSCFLAGS += -D RVM 80 | RVBSNAME := $(RVBSNAME)M 81 | endif 82 | ifeq ($(RVC),1) 83 | BSCFLAGS += -D RVC 84 | RVBSNAME := $(RVBSNAME)C 85 | endif 86 | ifeq ($(RVN),1) 87 | BSCFLAGS += -D RVN 88 | USER_MODE = 1 89 | RVBSNAME := $(RVBSNAME)N 90 | endif 91 | ifeq ($(RVZICSR),1) 92 | BSCFLAGS += -D RVZICSR 93 | RVBSNAME := $(RVBSNAME)Zicsr 94 | endif 95 | ifeq ($(RVZIFENCEI),1) 96 | BSCFLAGS += -D RVZIFENCEI 97 | RVBSNAME := $(RVBSNAME)Zifencei 98 | endif 99 | ifeq ($(RVXCHERI),1) 100 | BSCFLAGS += -D RVXCHERI -D RISCV 101 | RVBSNAME := $(RVBSNAME)Xcheri 102 | endif 103 | ifeq ($(SUPERVISOR_MODE),1) 104 | BSCFLAGS += -D SUPERVISOR_MODE 105 | USER_MODE = 1 106 | RVBSNAME := $(RVBSNAME)-s 107 | endif 108 | ifeq ($(USER_MODE),1) 109 | BSCFLAGS += -D USER_MODE 110 | RVBSNAME := $(RVBSNAME)u 111 | endif 112 | ifeq ($(PMP),1) 113 | BSCFLAGS += -D PMP 114 | RVBSNAME := $(RVBSNAME)-pmp 115 | endif 116 | 117 | # generated files directories 118 | BUILDDIR = build 119 | BDIR = $(BUILDDIR)/$(RVBSNAME)-bdir 120 | SIMDIR = $(BUILDDIR)/$(RVBSNAME)-simdir 121 | 122 | OUTPUTDIR = output 123 | VDIR = $(OUTPUTDIR)/$(RVBSNAME)-vdir 124 | INFODIR = $(OUTPUTDIR)/$(RVBSNAME)-info 125 | 126 | BSCFLAGS += -show-schedule -sched-dot 127 | #BSCFLAGS += -show-rule-rel \* \* 128 | #BSCFLAGS += -steps-warn-interval n 129 | BSCFLAGS += -steps-warn-interval 3000000 130 | #BSCFLAGS += +RTS -K40M -RTS 131 | #BSCFLAGS += -show-range-conflict 132 | BSCFLAGS += +RTS -K60M -RTS 133 | 134 | BSC = bsc 135 | #XXX Bluespec 2018 is not compatible with gcc > 4.9 136 | #XXX This is actually problematic when using $test$plusargs/strings or something? 137 | #CC = gcc-4.8 138 | #CXX = g++-4.8 139 | 140 | all: sim isa-test rvfi-dii verilog 141 | 142 | ifeq ($(RVXCHERI),1) 143 | TOPSIM = $(RVBSSRCDIR)/toplevels/Top_cheri.bsv 144 | BSCFLAGS += -D MEM128 145 | ifeq ($(XLEN),64) 146 | BSCFLAGS += -D CAP128 147 | else 148 | BSCFLAGS += -D CAP64 149 | endif 150 | SIMFLAGS = -D BLUESIM -L . -l pism 151 | SIMDEP = $(TOPSIM) $(RVBSSRCDIR) link-pism 152 | CLEANSIMDEP = clean-link-pism 153 | link-pism: 154 | $(MAKE) -C $(CHERISOCDIR)/PISM/src/pismdev pism 155 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/libpism.so 156 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/dram.so 157 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/ethercap.so 158 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/uart.so 159 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/fb.so 160 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/sdcard.so 161 | ln -fs $(CHERISOCDIR)/PISM/src/pismdev/virtio_block.so 162 | ln -fs $(CHERISOCDIR)/PISM/memoryconfig 163 | clean-link-pism: 164 | $(MAKE) -C $(CHERISOCDIR)/PISM/src/pismdev clean 165 | rm -f libpism.so 166 | rm -f dram.so 167 | rm -f ethercap.so 168 | rm -f uart.so 169 | rm -f fb.so 170 | rm -f sdcard.so 171 | rm -f virtio_block.so 172 | rm -f memoryconfig 173 | else 174 | TOPSIM = $(RVBSSRCDIR)/toplevels/Top_sim.bsv 175 | SIMDEP = $(TOPSIM) $(RVBSSRCDIR) 176 | endif 177 | sim: $(SIMDEP) 178 | mkdir -p $(INFODIR)-sim $(BDIR)-sim $(SIMDIR)-sim $(OUTPUTDIR) 179 | $(BSC) $(BSCFLAGS) $(SIMFLAGS) -bdir $(BDIR)-sim -simdir $(SIMDIR)-sim -info-dir $(INFODIR)-sim -sim -g mkRVBS_sim -u $< 180 | CC=$(CC) CXX=$(CXX) $(BSC) $(BSCFLAGS) $(SIMFLAGS) -bdir $(BDIR)-sim -simdir $(SIMDIR)-sim -info-dir $(INFODIR)-sim -sim -o $(OUTPUTDIR)/$(RVBSNAME)-sim -e mkRVBS_sim $(BLUEUTILSDIR)/*.c $(SOCKETUTILSDIR)/*.c 181 | 182 | isa-test: $(RVBSSRCDIR)/toplevels/Top_isa_test.bsv $(RVBSSRCS) 183 | mkdir -p $(INFODIR)-isa-test $(BDIR)-isa-test $(SIMDIR)-isa-test $(OUTPUTDIR) 184 | $(BSC) $(BSCFLAGS) -bdir $(BDIR)-isa-test -simdir $(SIMDIR)-isa-test -info-dir $(INFODIR)-isa-test -sim -g mkRVBS_isa_test -u $< 185 | CC=$(CC) CXX=$(CXX) $(BSC) $(BSCFLAGS) -bdir $(BDIR)-isa-test -simdir $(SIMDIR)-isa-test -info-dir $(INFODIR)-isa-test -sim -o $(OUTPUTDIR)/$(RVBSNAME)-isa-test -e mkRVBS_isa_test $(BLUEUTILSDIR)/*.c $(SOCKETUTILSDIR)/*.c 186 | 187 | rvfi-dii: $(RVBSSRCDIR)/toplevels/Top_rvfi_dii.bsv $(RVBSSRCS) 188 | mkdir -p $(INFODIR)-rvfi-dii $(BDIR)-rvfi-dii $(SIMDIR)-rvfi-dii $(OUTPUTDIR) 189 | $(BSC) $(BSCFLAGS) -D RVFI_DII -bdir $(BDIR)-rvfi-dii -simdir $(SIMDIR)-rvfi-dii -info-dir $(INFODIR)-rvfi-dii -sim -g mkRVBS_rvfi_dii -u $< 190 | CC=$(CC) CXX=$(CXX) $(BSC) $(BSCFLAGS) -bdir $(BDIR)-rvfi-dii -simdir $(SIMDIR)-rvfi-dii -info-dir $(INFODIR)-rvfi-dii -sim -o $(OUTPUTDIR)/$(RVBSNAME)-rvfi-dii -e mkRVBS_rvfi_dii $(BLUEUTILSDIR)/*.c $(SOCKETUTILSDIR)/*.c 191 | 192 | verilog: $(RVBSSRCS) 193 | mkdir -p $(INFODIR)-verilog $(BDIR)-verilog $(VDIR)-verilog 194 | $(BSC) $(BSCFLAGS) -bdir $(BDIR)-verilog -vdir $(VDIR)-verilog -info-dir $(INFODIR)-verilog -opt-undetermined-vals -unspecified-to X -D NO_LOGS -verilog -g mkRVBS_synth -u $(RVBSSRCDIR)/RVBS_Wrappers.bsv 195 | 196 | .PHONY: clean clean-sim clean-isa-test clean-rvfi-dii clean-verilog 197 | clean: clean-sim clean-isa-test clean-rvfi-dii clean-verilog 198 | rm -rf $(BUILDDIR) 199 | clean-sim: $(CLEANSIMDEP) 200 | rm -rf $(BDIR)-sim $(SIMDIR)-sim 201 | clean-isa-test: 202 | rm -rf $(BDIR)-isa-test $(SIMDIR)-isa-test 203 | clean-rvfi-dii: 204 | rm -rf $(BDIR)-rvfi-dii $(SIMDIR)-rvfi-dii 205 | clean-verilog: 206 | rm -rf $(BDIR)-verilog 207 | 208 | .PHONY: mrproper mrproper-sim mrproper-isa-test mrproper-rvfi-dii mrproper-verilog 209 | mrproper: mrproper-sim mrproper-isa-test mrproper-rvfi-dii mrproper-verilog clean 210 | rm -rf $(OUTPUTDIR) 211 | mrproper-sim: clean-sim 212 | #rm -rf $(INFODIR)-sim $(VDIR) $(OUTPUTDIR)-sim $(BUILDDIR)-sim 213 | rm -rf $(INFODIR)-sim 214 | mrproper-isa-test: clean-isa-test 215 | rm -rf $(INFODIR)-isa-test 216 | mrproper-rvfi-dii: clean-rvfi-dii 217 | rm -rf $(INFODIR)-rvfi-dii 218 | mrproper-verilog: clean-verilog 219 | rm -rf $(INFODIR)-verilog $(VDIR)-verilog 220 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_TraceInsts.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import BID :: *; 30 | import BlueUtils :: *; 31 | import RVBS_StateTypes :: *; 32 | import RVBS_BasicTypes :: *; 33 | import RVBS_TraceUtils :: *; 34 | 35 | function Action itrace (RVState s, Fmt msg) = 36 | `ifdef FULL_ITRACE 37 | printTLogPlusArgs("itrace", $format("pc: 0x%0x -- ", s.pc, msg, " -- ", fullReport(s))); 38 | `else 39 | printTLogPlusArgs("itrace", $format("pc: 0x%0x -- ", s.pc, msg)); 40 | `endif 41 | 42 | typeclass LogInst#(type a); a logInst; endtypeclass 43 | 44 | instance LogInst#(function Action f(RVState s, Fmt y)); 45 | function logInst(s, msg) = itrace(s, msg); 46 | endinstance 47 | 48 | instance LogInst#(function Action f(RVState s, Fmt y, Fmt z)); 49 | function logInst(s, msg0, msg1) = itrace(s, $format(msg0, " \t--\t", msg1)); 50 | endinstance 51 | 52 | instance LogInst#(function Action f(RVState s, Fmt y, String z)); 53 | function logInst(s, msg0, msg1) = itrace(s, $format(msg0, " \t--\t", msg1)); 54 | endinstance 55 | 56 | /* 57 | I-type 58 | 59 | 31 20 19 15 14 12 11 7 6 0 60 | +-------------------------------------+--------+--------+--------+----------+ 61 | | imm[11:0] | rs1 | funct3 | rd | opcode | 62 | +-------------------------------------+--------+--------+--------+----------+ 63 | 64 | function a patIType (Bit#(3) funct3, Bit#(7) opcode) = 65 | pat(v, v, n(funct3), v, n(opcode)) 66 | // RHS arguments: (Bit#(12) imm11_0, Bit#(5) rs1, Bit#(5) rd) 67 | 68 | I-type - shifts by a constant 69 | 70 | 31 25 24 20 19 15 14 12 11 7 6 0 71 | +------------------+------------------+--------+--------+--------+----------+ 72 | | imm[11:5] | imm[4:0] | rs1 | funct3 | rd | opcode | 73 | +------------------+------------------+--------+--------+--------+----------+ 74 | 75 | function a patITypeShamt (Bit#(7) imm_11_5, Bit#(3) funct3, Bit#(7) opcode) = 76 | pat(n(imm_11_5), v, v, n(funct3), v, n(opcode)) 77 | // RHS arguments: (Bit#(7) imm11_5, Bit#(5) imm4_0, Bit#(5) rs1, Bit#(5) rd) 78 | */ 79 | function Fmt fmtInstI(String i, Bit#(5) rd, Bit#(5) rs1, Bit#(12) imm) = 80 | $format(i, "\t", rName(rd), ", ", rName(rs1), ", 0x%0x", imm); 81 | /* 82 | R-type 83 | 84 | 31 25 24 20 19 15 14 12 11 7 6 0 85 | +----------------------------+--------+--------+--------+--------+----------+ 86 | | funct7 | rs2 | rs1 | funct3 | rd | opcode | 87 | +----------------------------+--------+--------+--------+--------+----------+ 88 | 89 | function BitPat#() patRType (Bit#(7) funct7, Bit#(3) funct3, Bit#(7) opcode) = 90 | return pat(n(funct7), v, v, n(funct3), v, n(opcode)) 91 | // RHS arguments: (Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) 92 | */ 93 | function Fmt fmtInstR(String i, Bit#(5) rd, Bit#(5) rs1, Bit#(5) rs2) = 94 | $format(i, "\t", rName(rd), ", ", rName(rs1), ", ", rName(rs2)); 95 | /* 96 | U-type 97 | 98 | 31 12 11 7 6 0 99 | +-------------------------------------------------------+--------+----------+ 100 | | imm[31:12] | rd | opcode | 101 | +-------------------------------------------------------+--------+----------+ 102 | 103 | function a patUType (Bit#(7) opcode) = 104 | pat(v, v, n(opcode)) 105 | // RHS arguments: (Bit#(20) imm31_12, Bit#(5) rd) 106 | */ 107 | function Fmt fmtInstU(String i, Bit#(5) rd, Bit#(20) imm) = 108 | $format(i, "\t", rName(rd), ", 0x%0x", imm); 109 | /* 110 | J-type 111 | 112 | 31 30 21 20 19 12 11 7 6 0 113 | +-------+------------------+-------+--------------------+--------+----------+ 114 | |imm[20]| imm[10:1] |imm[11]| imm[19:12] | rd | opcode | 115 | +-------+------------------+-------+--------------------+--------+----------+ 116 | 117 | function a patJType (Bit#(7) opcode) = 118 | pat(v, v, v, v, v, n(opcode)) 119 | // RHS arguments: (Bit#(1) imm20, Bit#(10) imm10_1, Bit#(1) imm11, Bit#(8) imm19_12, Bit#(5) rd) 120 | */ 121 | function Fmt fmtInstJ(String i, Bit#(5) rd, Bit#(XLEN) imm) = 122 | $format(i, "\t", rName(rd), ", 0x%0x", imm); 123 | /* 124 | B-type 125 | 126 | 31 30 25 24 20 19 15 14 12 11 8 7 6 0 127 | +-------+----------+--------+--------+--------+----------+-------+----------+ 128 | |imm[12]| imm[10:5]| rs2 | rs1 | funct3 | imm[4:1] |imm[11]| opcode | 129 | +-------+----------+--------+--------+--------+----------+-------+----------+ 130 | 131 | function a patBType (Bit#(3) funct3, Bit#(7) opcode) = 132 | pat(v, v, v, v, n(funct3), v, v, n(opcode)) 133 | // RHS arguments: (Bit#(1) imm12, Bit#(6) imm10_5, Bit#(5) rs2, Bit#(5) rs1, Bit#(4) imm4_1, Bit#(1) imm11) 134 | */ 135 | function Fmt fmtInstB(String i, Bit#(5) rs1, Bit#(5) rs2, Bit#(XLEN) imm) = 136 | $format(i, "\t", rName(rs1),", ", rName(rs2), ", 0x%0x", imm); 137 | /* 138 | S-type 139 | 140 | 31 25 24 20 19 15 14 12 11 7 6 0 141 | +----------------------------+--------+--------+--------+--------+----------+ 142 | | imm[11:5] | rs2 | rs1 | funct3 |imm[4:0]| opcode | 143 | +----------------------------+--------+--------+--------+--------+----------+ 144 | 145 | function a patSType (Bit#(3) funct3, Bit#(7) opcode) = 146 | pat(v, v, v, n(funct3), v, n(opcode)) 147 | // RHS arguments: (Bit#(7) imm11_5, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) imm4_0) 148 | */ 149 | function Fmt fmtInstS(String i, Bit#(5) rs1, Bit#(5) rs2, Bit#(XLEN) imm) = 150 | $format(i, "\t", rName(rs1),", ", rName(rs2), ", 0x%0x", imm); 151 | 152 | `ifdef RVXCHERI 153 | /* 154 | Three-op-type 155 | 156 | 31 25 24 20 19 15 14 12 11 7 6 0 157 | +----------------------------+---------+--------+-------+--------+----------+ 158 | | funct7 | {r,c}s2 | cs1 | 0 | {r,c}d | 0x5b | 159 | +----------------------------+---------+--------+-------+--------+----------+ 160 | 161 | */ 162 | function Fmt fmtInstXcheri3op(String i, TraceRegType rd_cd, 163 | TraceRegType cs1, 164 | TraceRegType rs_cs2) = 165 | $format(i, "\t", traceReg(rd_cd), ", ", traceReg(cs1), ", ", traceReg(rs_cs2)); 166 | /* 167 | SrcDst-type 168 | 169 | 31 25 24 20 19 15 14 12 11 7 6 0 170 | +---------------------------+--------+---------+-------+--------+----------+ 171 | | 0x7f | func | {r,c}s1 | 0 | {r,c}d | 0x5b | 172 | +---------------------------+--------+---------+-------+--------+----------+ 173 | 174 | */ 175 | function Fmt fmtInstXcheriSrcDst(String i, TraceRegType rd_cd, TraceRegType rs_cs1) = 176 | $format(i, "\t", traceReg(rd_cd), ", ", traceReg(rs_cs1)); 177 | /* 178 | Store-type 179 | 180 | 31 25 24 20 19 15 14 12 11 7 6 0 181 | +---------------------------+---------+---------+-------+--------+----------+ 182 | | 0x7c | {r,c}s2 | {r,c}s1 | 0 | func | 0x5b | 183 | +---------------------------+---------+---------+-------+--------+----------+ 184 | 185 | */ 186 | function Fmt fmtInstXcheriStore(String i, TraceRegType rs_cs1, TraceRegType rs_cs2) = 187 | $format(i, "\t", traceReg(rs_cs2), ", ", traceReg(rs_cs1)); 188 | `endif 189 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Base_RV64I.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Vector :: *; 30 | import Printf :: *; 31 | 32 | import Recipe :: *; 33 | import BID :: *; 34 | import BlueBasics :: *; 35 | import BlueUtils :: *; 36 | import BitPat :: *; 37 | 38 | import RVBS_Types :: *; 39 | import RVBS_Trap :: *; 40 | import RVBS_TraceUtils :: *; 41 | import RVBS_TraceInsts :: *; 42 | import RVBS_MemAccess :: *; 43 | 44 | //////////////////////////////////////// 45 | // Integer Computational Instructions // 46 | //////////////////////////////////////////////////////////////////////////////// 47 | 48 | ///////////////////////////////////////////// 49 | // Integer Register-Immediate Instructions // 50 | ///////////////////////////////////////////// 51 | /* 52 | I-type 53 | 54 | 31 20 19 15 14 12 11 7 6 0 55 | +-------------------------------------+--------+--------+--------+----------+ 56 | | imm[11:0] | rs1 | funct3 | rd | opcode | 57 | +-------------------------------------+--------+--------+--------+----------+ 58 | */ 59 | 60 | // funct3 = ADDIW = 000 61 | // opcode = OP-IMM-32 = 0011011 62 | // XXX pseudo-op: SEXT.W 63 | function Action instrADDIW (RVState s, Bit#(12) imm, Bit#(5) rs1, Bit#(5) rd) = action 64 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] + signExtend(imm))); 65 | logInst(s, fmtInstI("addiw", rd, rs1, imm)); 66 | endaction; 67 | 68 | /* 69 | I-type - shifts by a constant 70 | 71 | 31 25 24 20 19 15 14 12 11 7 6 0 72 | +------------------+------------------+--------+--------+--------+----------+ 73 | | imm[11:5] | imm[4:0] | rs1 | funct3 | rd | opcode | 74 | +------------------+------------------+--------+--------+--------+----------+ 75 | */ 76 | 77 | // imm[11:6] = 000000 78 | // funct3 = SLLI = 001 79 | // opcode = OP-IMM = 0010011 80 | function Action instrSLLI64 (RVState s, Bit#(6) imm5_0, Bit#(5) rs1, Bit#(5) rd) = action 81 | // TODO check MXL and imm[5] for exception in RV32I mode 82 | s.wGPR(rd, s.rGPR(rs1) << imm5_0); 83 | logInst(s, fmtInstI("slli", rd, rs1, zeroExtend(imm5_0))); 84 | endaction; 85 | 86 | // imm[11:6] = 000000 87 | // funct3 = SRLI = 101 88 | // opcode = OP-IMM = 0010011 89 | function Action instrSRLI64 (RVState s, Bit#(6) imm5_0, Bit#(5) rs1, Bit#(5) rd) = action 90 | // TODO check MXL and imm[5] for exception in RV32I mode 91 | s.wGPR(rd, s.rGPR(rs1) >> imm5_0); 92 | logInst(s, fmtInstI("srli", rd, rs1, zeroExtend(imm5_0))); 93 | endaction; 94 | 95 | // imm[11:6] = 010000 96 | // funct3 = SRAI = 101 97 | // opcode = OP-IMM = 0010011 98 | function Action instrSRAI64 (RVState s, Bit#(6) imm5_0, Bit#(5) rs1, Bit#(5) rd) = action 99 | // TODO check MXL and imm[5] for exception in RV32I mode 100 | s.wGPR(rd, arithRightShift(s.rGPR(rs1), imm5_0)); 101 | logInst(s, fmtInstI("srai", rd, rs1, zeroExtend(imm5_0))); 102 | endaction; 103 | 104 | // imm[11:5] = 0000000 105 | // funct3 = SLLIW = 001 106 | // opcode = OP-IMM-32 = 0011011 107 | function Action instrSLLIW (RVState s, Bit#(5) imm4_0, Bit#(5) rs1, Bit#(5) rd) = action 108 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] << imm4_0)); 109 | logInst(s, fmtInstI("slliw", rd, rs1, zeroExtend(imm4_0))); 110 | endaction; 111 | 112 | // imm[11:5] = 0000000 113 | // funct3 = SRLIW = 101 114 | // opcode = OP-IMM-32 = 0011011 115 | function Action instrSRLIW (RVState s, Bit#(5) imm4_0, Bit#(5) rs1, Bit#(5) rd) = action 116 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] >> imm4_0)); 117 | logInst(s, fmtInstI("srliw", rd, rs1, zeroExtend(imm4_0))); 118 | endaction; 119 | 120 | // imm[11:5] = 0100000 121 | // funct3 = SRAIW = 101 122 | // opcode = OP-IMM-32 = 0011011 123 | function Action instrSRAIW (RVState s, Bit#(5) imm4_0, Bit#(5) rs1, Bit#(5) rd) = action 124 | s.wGPR(rd, signExtend(arithRightShift(s.rGPR(rs1)[31:0], imm4_0))); 125 | logInst(s, fmtInstI("sraiw", rd, rs1, zeroExtend(imm4_0))); 126 | endaction; 127 | 128 | ////////////////////////////////////////// 129 | // Integer Register-Register Operations // 130 | ////////////////////////////////////////// 131 | /* 132 | R-type 133 | 134 | 31 25 24 20 19 15 14 12 11 7 6 0 135 | +----------------------------+--------+--------+--------+--------+----------+ 136 | | funct7 | rs2 | rs1 | funct3 | rd | opcode | 137 | +----------------------------+--------+--------+--------+--------+----------+ 138 | */ 139 | 140 | // funct7 = 0000000 141 | // funct3 = ADDW = 000 142 | // opcode = OP-32 = 0111011 143 | function Action instrADDW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 144 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] + s.rGPR(rs2)[31:0])); 145 | logInst(s, fmtInstR("addw", rd, rs1, rs2)); 146 | endaction; 147 | 148 | // funct7 = 0100000 149 | // funct3 = SUBW = 000 150 | // opcode = OP-32 = 0111011 151 | function Action instrSUBW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 152 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] - s.rGPR(rs2)[31:0])); 153 | logInst(s, fmtInstR("subw", rd, rs1, rs2)); 154 | endaction; 155 | 156 | // funct7 = 0000000 157 | // funct3 = SLLW = 001 158 | // opcode = OP-32 = 0111011 159 | function Action instrSLLW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 160 | Bit#(5) shiftAmnt = truncate(s.rGPR(rs2)); 161 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] << shiftAmnt)); 162 | logInst(s, fmtInstR("sllw", rd, rs1, rs2)); 163 | endaction; 164 | 165 | // funct7 = 0000000 166 | // funct3 = SRLW = 101 167 | // opcode = OP-32 = 0111011 168 | function Action instrSRLW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 169 | Bit#(5) shiftAmnt = truncate(s.rGPR(rs2)); 170 | s.wGPR(rd, signExtend(s.rGPR(rs1)[31:0] >> shiftAmnt)); 171 | logInst(s, fmtInstR("srlw", rd, rs1, rs2)); 172 | endaction; 173 | 174 | // funct7 = 0100000 175 | // funct3 = SRAW = 101 176 | // opcode = OP-32 = 0111011 177 | function Action instrSRAW (RVState s, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) rd) = action 178 | Bit#(5) shiftAmnt = truncate(s.rGPR(rs2)); 179 | s.wGPR(rd, signExtend(arithRightShift(s.rGPR(rs1)[31:0], shiftAmnt))); 180 | logInst(s, fmtInstR("sraw", rd, rs1, rs2)); 181 | endaction; 182 | 183 | module [ISADefModule] mkBase_RV64I#(RVState s) (); 184 | 185 | defineInstEntry("addiw", pat(v, v, n(3'b000), v, n(7'b0011011)), instrADDIW(s)); 186 | defineInstEntry("slli", pat(n(6'b000000), v, v, n(3'b001), v, n(7'b0010011)), instrSLLI64(s)); 187 | defineInstEntry("srli", pat(n(6'b000000), v, v, n(3'b101), v, n(7'b0010011)), instrSRLI64(s)); 188 | defineInstEntry("srai", pat(n(6'b010000), v, v, n(3'b101), v, n(7'b0010011)), instrSRAI64(s)); 189 | defineInstEntry("slliw", pat(n(7'b0000000), v, v, n(3'b001), v, n(7'b0011011)), instrSLLIW(s)); 190 | defineInstEntry("srliw", pat(n(7'b0000000), v, v, n(3'b101), v, n(7'b0011011)), instrSRLIW(s)); 191 | defineInstEntry("sraiw", pat(n(7'b0100000), v, v, n(3'b101), v, n(7'b0011011)), instrSRAIW(s)); 192 | defineInstEntry("addw", pat(n(7'b0000000), v, v, n(3'b000), v, n(7'b0111011)), instrADDW(s)); 193 | defineInstEntry("subw", pat(n(7'b0100000), v, v, n(3'b000), v, n(7'b0111011)), instrSUBW(s)); 194 | defineInstEntry("sllw", pat(n(7'b0000000), v, v, n(3'b001), v, n(7'b0111011)), instrSLLW(s)); 195 | defineInstEntry("srlw", pat(n(7'b0000000), v, v, n(3'b101), v, n(7'b0111011)), instrSRLW(s)); 196 | defineInstEntry("sraw", pat(n(7'b0100000), v, v, n(3'b101), v, n(7'b0111011)), instrSRAW(s)); 197 | defineInstEntry("lwu", pat(v, v, n(3'b110), v, n(7'b0000011)), load(s, LoadArgs{name: "lwu", numBytes: 4, sgnExt: False})); 198 | defineInstEntry("ld", pat(v, v, n(3'b011), v, n(7'b0000011)), load(s, LoadArgs{name: "ld", numBytes: 8, sgnExt: True})); 199 | defineInstEntry("sd", pat(v, v, v, n(3'b011), v, n(7'b0100011)), store(s, StrArgs{name: "sd", numBytes: 8})); 200 | 201 | endmodule 202 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_VMTranslate.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import FIFOF :: *; 30 | import SpecialFIFOs :: *; 31 | //import UniqueWrappers :: * ; 32 | 33 | import BlueBasics :: *; 34 | import BlueUtils :: *; 35 | import Recipe :: *; 36 | import RVBS_BasicTypes :: *; 37 | import RVBS_MemTypes :: *; 38 | import RVBS_CSRTypes :: *; 39 | import RVBS_PMPTypes :: *; 40 | import RVBS_VMTranslateTypes :: *; 41 | 42 | interface PageWalker; 43 | method Action lookup (AddrReq#(VAddr) r); 44 | endinterface 45 | 46 | `ifndef XLEN64 // MAX_XLEN = 32 47 | 48 | ///////////////// 49 | // Sv32 walker // 50 | ///////////////// 51 | 52 | `define PTESIZE 4 53 | `define PAGESIZE 2**12 54 | 55 | typedef struct { 56 | Bit#(10) vpn1; 57 | Bit#(10) vpn0; 58 | Bit#(12) pgoffset; 59 | } Sv32VAddr deriving (Bits, FShow); 60 | 61 | typedef struct { 62 | Bit#(12) ppn1; 63 | Bit#(10) ppn0; 64 | Bit#(12) pgoffset; 65 | } Sv32PAddr deriving (Bits, FShow); 66 | 67 | typedef struct { 68 | Bit#(12) ppn1; 69 | Bit#(10) ppn0; 70 | Bit#(2) rsw; 71 | Bool d; 72 | Bool a; 73 | Bool g; 74 | Bool u; 75 | Bool x; 76 | Bool w; 77 | Bool r; 78 | Bool v; 79 | } Sv32PTE deriving (Bits, FShow); 80 | 81 | module [Module] mkSv32PageWalker#( 82 | FIFOF#(Either#(ExcToken, PAddr)) rsp 83 | , SATP satp 84 | , RVMem mem 85 | `ifdef PMP 86 | , PMPLookup pmp 87 | `endif 88 | ) (PageWalker); 89 | 90 | // required page walker mechanism "variable" 91 | Reg#(Bool) activeLookup[2] <- mkCReg(2, False); 92 | Reg#(Bit#(1)) i[2] <- mkCReg(2, 1); 93 | Reg#(Sv32PAddr) a[2] <- mkCReg(2, ?); 94 | Reg#(Sv32VAddr) va[2] <- mkCReg(2, ?); 95 | Reg#(RVMemReqType) rType[2] <- mkCReg(2, ?); 96 | //PulseWire startReq <- mkPulseWire; 97 | 98 | // physical memory request machine 99 | // XXX TODO sort out physical memory addr width (34) 100 | PAddr pteAddr = unpack(pack(a[1]) + (((i[1] == 1) ? zeroExtend(va[1].vpn1) : zeroExtend(va[1].vpn0)) << log2(`PTESIZE))); 101 | RecipeFSM memReq <- mkRecipeFSM(rPar(rBlock( 102 | `ifdef PMP 103 | action 104 | pmp.sink.put(Right(AddrReq{ 105 | addr: pteAddr, 106 | numBytes: `PTESIZE, 107 | reqType: rType[1] 108 | })); 109 | endaction, action 110 | let r <- get(pmp.source); 111 | let e_req = case (r) matches 112 | tagged Left .excTok: 113 | return Left(excTok); 114 | tagged Right .checkedAddr: 115 | return Right(RVReadReq{addr: checkedAddr, numBytes: `PTESIZE}); 116 | endcase; 117 | `else 118 | action 119 | let e_req = Right(RVReadReq{addr: pteAddr, numBytes: `PTESIZE}); 120 | `endif 121 | printTLogPlusArgs("debug", $format("DEBUG - a[1] = 0x%0x", a[1])); 122 | printTLogPlusArgs("debug", $format("DEBUG - i[1] = %0d", i[1])); 123 | printTLogPlusArgs("debug", $format("DEBUG - va[1].vpn1 = 0x%0x", va[1].vpn1)); 124 | printTLogPlusArgs("debug", $format("DEBUG - va[1].vpn0 = 0x%0x", va[1].vpn0)); 125 | printTLogPlusArgs("debug", $format("DEBUG - log2(PTESIZE) = %0d", log2(`PTESIZE))); 126 | //printTLogPlusArgs("vmem", $format("VMEM - Sv32 mem access, sending ", fshow(e_req))); 127 | mem.sink.put(e_req); 128 | endaction 129 | ))); 130 | 131 | // rule observing the received pte 132 | let pgFault = case (rType[1]) 133 | READ: return LoadPgFault; 134 | WRITE: return StrAMOPgFault; 135 | IFETCH: return InstPgFault; 136 | endcase; 137 | let pgFaultRsp = Left(craftExcToken(pgFault)); 138 | rule checkPTE (activeLookup[1]); 139 | printTLogPlusArgs("vmem", $format("VMEM - Sv32 checkPTE rule")); 140 | function finishLookup(x) = action 141 | //printTLogPlusArgs("vmem", $format("VMEM - Sv32 checkPTE rule - returning ", fshow(x))); 142 | activeLookup[1] <= False; 143 | rsp.enq(x); 144 | endaction; 145 | let tmp <- get(mem.source); 146 | case (tmp) matches 147 | tagged Left .excTok: begin $display("Received a non read response when fetching a PTE"); $finish(0); end 148 | tagged Right .memRsp: case (memRsp) matches 149 | `ifndef RVXCHERI 150 | tagged RVReadRsp .r: begin 151 | `else 152 | tagged RVReadRsp {._, .r}: begin 153 | `endif 154 | Sv32PTE pte = unpack(truncate(r)); 155 | printTLogPlusArgs("vmem", $format("VMEM - Sv32 checkPTE rule - ", fshow(pte))); 156 | // invalid pte 157 | if (!pte.v || (!pte.r && pte.w)) finishLookup(pgFaultRsp); 158 | // leaf pte 159 | else if (pte.r || pte.x) begin 160 | finishLookup(Right({pte.ppn1, (i[1] > 0) ? va[1].vpn0 : pte.ppn0, va[1].pgoffset})); 161 | // TODO more checks on pte and stuff 162 | //if(exc) rsp.enq(exc); 163 | //else rsp.enq(PAddr); 164 | // non leaf pte 165 | end else begin 166 | if (i[0] == 0) finishLookup(pgFaultRsp); 167 | else begin 168 | i[0] <= i[0] - 1; 169 | a[0] <= unpack(zeroExtend({pte.ppn1, pte.ppn0}) << log2(`PAGESIZE)); 170 | //startReq.send(); 171 | memReq.trigger; 172 | end 173 | end 174 | end 175 | default: begin $display("Received a non read response when fetching a PTE"); $finish(0); end 176 | endcase 177 | endcase 178 | endrule 179 | 180 | //rule doStartReq (startReq); 181 | // memReq.start(); 182 | //endrule 183 | 184 | // lookup method 185 | method Action lookup (AddrReq#(VAddr) r) if (!activeLookup[0]); 186 | i[0] <= 1; 187 | a[0] <= unpack(zeroExtend(satp.ppn) << log2(`PAGESIZE)); 188 | va[0] <= unpack(r.addr); 189 | rType[0] <= r.reqType; 190 | activeLookup[0] <= True; 191 | //startReq.send(); 192 | memReq.trigger; 193 | printTLogPlusArgs("vmem", "VMEM - Sv32 starting lookup"); 194 | endmethod 195 | 196 | endmodule 197 | 198 | `endif 199 | 200 | module [Module] mkVMLookup#(CSRs csrs 201 | , RVMem mem 202 | `ifdef PMP 203 | , PMPLookup pmp 204 | `endif 205 | ) (VMLookup); 206 | // local module instances 207 | let rsp <- mkBypassFIFOF; 208 | `ifndef XLEN64 // MAX_XLEN = 32 209 | PageWalker sv32PageWalker <- mkSv32PageWalker( 210 | rsp 211 | , csrs.satp 212 | , mem 213 | `ifdef PMP 214 | , pmp 215 | `endif 216 | ); 217 | `endif 218 | // lookup method 219 | function Action lookup (AddrReq#(VAddr) req) = action 220 | // TODO 221 | printTLogPlusArgs("vmem", $format("VMEM - lookup ", fshow(req))); 222 | printTLogPlusArgs("vmem", $format("VMEM - lookup ", fshow(csrs.satp))); 223 | case (csrs.satp.mode) 224 | BARE: begin 225 | rsp.enq(Right(toPAddr(req.addr))); 226 | printTLogPlusArgs("vmem", $format("VMEM - BARE mode, returning ", fshow(toPAddr(req.addr)))); 227 | end 228 | `ifdef XLEN64 // MAX_XLEN > 32 229 | `else // MAX_XLEN = 32 230 | SV32: sv32PageWalker.lookup(req); 231 | `endif 232 | default: begin $display("Unsupported STAP mode for translation. Should not happen."); $finish(0); end // XXX TODO add assertion 233 | endcase 234 | endaction; 235 | // build the lookup interface 236 | interface sink = interface Sink; 237 | method canPut = rsp.notFull; 238 | method put (e_req) = case (e_req) matches 239 | tagged Left .excTok: action 240 | printTLogPlusArgs("vmem", $format("VMEM - incomming exception %s, pass it down", fshow(excTok))); 241 | rsp.enq(Left(excTok)); // always pass down incomming exception without further side effects 242 | endaction 243 | tagged Right .req: lookup(req); 244 | //else rsp.enq(AddrRsp {addr: toPAddr(req.addr), mExc: Invalid}); 245 | endcase; 246 | endinterface; 247 | interface source = toSource(rsp); 248 | 249 | endmodule 250 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_StateTypes.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | `ifdef RVXCHERI 30 | `define RISCV 31 | //XXX TODO FIXME add a typeclass method that handles getting otypeMax 32 | `ifdef XLEN64 33 | `define CAP128 34 | //typedef 64 CC_ADDR; 35 | //typedef 46 CC_BOUNDS; 36 | //typedef 6 CC_EXP; 37 | typedef 18 CC_OTYPE; 38 | `else 39 | `define CAP64 40 | //typedef 32 CC_ADDR; 41 | //typedef 16 CC_BOUNDS; 42 | //typedef 6 CC_EXP; 43 | typedef 4 CC_OTYPE; 44 | `endif 45 | import CHERICap :: *; 46 | import CHERICC_Fat :: *; 47 | //import CHERICC :: *; 48 | `endif 49 | 50 | import Vector :: *; 51 | import FIFOF :: *; 52 | 53 | import BID :: *; 54 | import BlueUtils :: *; 55 | import Recipe :: *; 56 | import RVBS_BasicTypes :: *; 57 | import RVBS_MemTypes :: *; 58 | import RVBS_CSRTypes :: *; 59 | import RVBS_TraceUtils :: *; 60 | `ifdef PMP 61 | import RVBS_PMPTypes :: *; 62 | `endif 63 | `ifdef SUPERVISOR_MODE 64 | import RVBS_VMTranslateTypes :: *; 65 | `endif 66 | `ifdef RVFI_DII 67 | import RVFI_DII :: *; 68 | import ClientServer :: *; 69 | import GetPut :: *; 70 | import FIFO :: *; 71 | `endif 72 | 73 | //////////////////////////////// 74 | // RISC-V architectural state // 75 | //////////////////////////////////////////////////////////////////////////////// 76 | 77 | `ifdef RVXCHERI 78 | //typedef CHERICCCap#(CC_ADDR, CC_BOUNDS, CC_EXP, CC_OTYPE) CapType; 79 | typedef CapPipe CapType; 80 | typedef TAdd#(XLEN, XLEN) CapNoValidSz; 81 | typedef TDiv#(CapNoValidSz, 8) CapByteSz; 82 | Bit#(CC_OTYPE) otypeMax = ~0; 83 | // Capability handle helper types 84 | typedef union tagged { 85 | Tuple2#(Bit#(5), CapType) CapAccessHandle; 86 | VAddr DDCAccessHandle; 87 | VAddr PCCAccessHandle; 88 | } MemAccessHandle deriving (Bits); 89 | 90 | function Tuple3#(Bit#(6), CapType, VAddr) unpackHandle(CapType ddc, CapType pcc, MemAccessHandle h); 91 | Bit#(6) idx = ?; 92 | CapType cap = ?; 93 | VAddr vaddr = ?; 94 | case (h) matches 95 | tagged CapAccessHandle {.h_idx, .h_cap}: begin 96 | idx = zeroExtend(h_idx); 97 | cap = h_cap; 98 | vaddr = getAddr(cap); 99 | end 100 | tagged DDCAccessHandle .h_addr: begin 101 | idx = 6'b100001; // this is DDC 102 | cap = ddc; 103 | vaddr = truncate(getBase(cap)) + h_addr; 104 | end 105 | tagged PCCAccessHandle .h_addr: begin 106 | idx = 6'b100000; // this is PCC 107 | cap = pcc; 108 | vaddr = truncate(getBase(cap)) + h_addr; 109 | end 110 | endcase 111 | return tuple3(idx, cap, vaddr); 112 | endfunction 113 | 114 | function Bool inCapMode (CapType cap) = getFlags(cap)[0] == 1; 115 | 116 | `endif 117 | 118 | // state type 119 | typedef struct { 120 | Reg#(PrivLvl) currentPrivLvl; 121 | XLMode currentXLEN; 122 | 123 | ArchReg#(VAddr) pc; 124 | function Action f(VAddr newpc) updatePC; 125 | Reg#(VAddr) instByteSz; 126 | Array#(Reg#(Maybe#(ExcCode))) pendingIFetchException; 127 | Array#(Reg#(Maybe#(Tuple2#(ExcCode, Maybe#(Bit#(XLEN)))))) pendingException; 128 | Array#(Reg#(Maybe#(Tuple2#(ExcCode, Bit#(XLEN))))) pendingMemException; 129 | `ifdef RVXCHERI 130 | Array#(Reg#(Maybe#(Tuple2#(Bit#(6), CapExcCode)))) pendingIFetchCapException; 131 | Array#(Reg#(Maybe#(Tuple2#(Bit#(6), CapExcCode)))) pendingCapException; 132 | Array#(Reg#(Maybe#(Tuple2#(Bit#(6), CapExcCode)))) pendingMemCapException; 133 | `endif 134 | `ifdef RVXCHERI 135 | ArchRegFile#(32, CapType) regFile; 136 | `else 137 | ArchRegFile#(32, Bit#(XLEN)) regFile; 138 | `endif 139 | function Bit#(XLEN) f(Bit#(5) idx) rGPR; 140 | function Action f(Bit#(5) idx, Bit#(XLEN) data) wGPR; 141 | `ifdef RVXCHERI 142 | function CapType f(Bit#(5) idx) rCR; 143 | function Action f(Bit#(5) idx, CapType data) wCR; 144 | `endif 145 | CSRs csrs; 146 | `ifdef RVXCHERI 147 | ArchReg#(CapType) pcc; 148 | ArchReg#(CapType) ddc; 149 | `ifdef RVN 150 | ArchReg#(CapType) utcc; 151 | ArchReg#(CapType) utdc; 152 | ArchReg#(CapType) uscratchc; 153 | ArchReg#(CapType) uepcc; 154 | `endif 155 | `ifdef SUPERVISOR_MODE 156 | ArchReg#(CapType) stcc; 157 | ArchReg#(CapType) stdc; 158 | ArchReg#(CapType) sscratchc; 159 | ArchReg#(CapType) sepcc; 160 | `endif 161 | ArchReg#(CapType) mtcc; 162 | ArchReg#(CapType) mtdc; 163 | ArchReg#(CapType) mscratchc; 164 | ArchReg#(CapType) mepcc; 165 | function Maybe#(Tuple4#(PrivLvl, Bool,Bool,ArchReg#(CapType))) f(Bit#(5) idx) getCSpecial; 166 | FIFOF#(Tuple6#(MemAccessHandle, VAddr, Bit#(5), BitPO#(4), Bool, Bool)) readMem; 167 | FIFOF#(Tuple5#(MemAccessHandle, VAddr, BitPO#(4), Bit#(128), Bool)) writeMem; 168 | `else 169 | FIFOF#(Tuple5#(VAddr, VAddr, Bit#(5), BitPO#(4), Bool)) readMem; 170 | FIFOF#(Tuple4#(VAddr, VAddr, BitPO#(4), Bit#(128))) writeMem; 171 | `endif 172 | RVMem imem; 173 | RVMem dmem; 174 | RVMem ivmmem; 175 | RVMem dvmmem; 176 | `ifdef PMP 177 | PMPLookup ipmp; 178 | PMPLookup dpmp; 179 | `ifdef SUPERVISOR_MODE 180 | PMPLookup ivmpmp; 181 | PMPLookup dvmpmp; 182 | `endif 183 | `endif 184 | `ifdef SUPERVISOR_MODE 185 | VMLookup ivm; 186 | VMLookup dvm; 187 | `endif 188 | `ifdef RVFI_DII 189 | FIFO#(Bit#(InstWidth)) iFF; 190 | Reg#(Bit#(64)) count; 191 | Array#(Reg#(Maybe#(VAddr))) exc_tgt; 192 | Array#(Reg#(VAddr)) mem_addr; 193 | Array#(Reg#(Bit#(DMemWidth))) mem_wdata; 194 | Array#(Reg#(Bit#(TDiv#(DMemWidth, 8)))) mem_wmask; 195 | `ifdef RVXCHERI 196 | RVFI_DII_Bridge#(XLEN, 64, 0) rvfi_dii_bridge; 197 | `else 198 | RVFI_DII_Bridge#(XLEN, XLEN, 0) rvfi_dii_bridge; 199 | `endif 200 | `endif 201 | } RVState; 202 | 203 | // State instance 204 | instance State#(RVState); 205 | 206 | function lightReport = fullReport; 207 | function fullReport (s); 208 | Fmt str = $format("regfile\n"); 209 | `ifdef RVXCHERI 210 | for (Integer i = 0; i < 32; i = i + 1) 211 | str = str + $format(rName(fromInteger(i)),": ", showCHERICap(s.regFile.r[i])); 212 | `else 213 | for (Integer i = 0; i < 6; i = i + 1) begin 214 | for (Integer j = 0; j < 5; j = j + 1) begin 215 | Bit#(5) ridx = fromInteger(i*5+j); 216 | str = str + $format(rName(ridx),": 0x%8x\t", s.regFile.r[ridx]); 217 | end 218 | str = str + $format("\n"); 219 | end 220 | str = str + $format(rName(5'd30),": 0x%8x\t", s.regFile.r[30]); 221 | str = str + $format(rName(5'd31),": 0x%8x", s.regFile.r[31]); 222 | `endif 223 | str = str + $format("\npc = 0x%8x", s.pc); 224 | str = str + $format(" - privilege mode = ", fshow(s.currentPrivLvl)); 225 | return str; 226 | endfunction 227 | function commit (s) = action 228 | `ifdef RVFI_DII 229 | // first do the RVFI_DII reporting 230 | s.iFF.deq; 231 | s.count <= s.count + 1; 232 | // TODO Update to new BSV-RVFI-DII bridge and parameterize the struct on XLEN 233 | s.rvfi_dii_bridge.client.report.put(RVFI_DII_Execution{ 234 | rvfi_order: s.count, 235 | rvfi_trap: isValid(s.exc_tgt[1]), 236 | rvfi_halt: ?, 237 | rvfi_intr: ?, 238 | rvfi_insn: s.iFF.first, 239 | rvfi_rs1_addr: ?, 240 | rvfi_rs2_addr: ?, 241 | rvfi_rs1_data: ?, 242 | rvfi_rs2_data: ?, 243 | rvfi_pc_rdata: s.pc, 244 | rvfi_pc_wdata: isValid(s.exc_tgt[1]) ? s.exc_tgt[1].Valid : s.pc.late, 245 | rvfi_mem_wdata: zeroExtend(s.mem_wdata[1]), 246 | rvfi_rd_addr: s.regFile.rd_idx, 247 | `ifdef RVXCHERI 248 | rvfi_rd_wdata: getAddr(s.regFile.rd_new_val), 249 | `else 250 | rvfi_rd_wdata: s.regFile.rd_new_val, 251 | `endif 252 | rvfi_mem_addr: s.mem_addr[1], 253 | rvfi_mem_rmask: ?, 254 | rvfi_mem_wmask: zeroExtend(s.mem_wmask[1]), 255 | rvfi_mem_rdata: ? 256 | }); 257 | // reset the cregs 258 | s.exc_tgt[1] <= Invalid; 259 | s.mem_addr[1] <= 0; 260 | s.mem_wdata[1] <= 0; 261 | s.mem_wmask[1] <= 0; 262 | `endif 263 | // perform architectural stateful changes 264 | s.pc.commit; 265 | s.regFile.commit; 266 | `ifdef RVXCHERI 267 | s.pcc.commit; 268 | s.ddc.commit; 269 | `ifdef RVN 270 | s.utcc.commit; 271 | s.utdc.commit; 272 | s.uscratchc.commit; 273 | s.uepcc.commit; 274 | `endif 275 | `ifdef SUPERVISOR_MODE 276 | s.stcc.commit; 277 | s.stdc.commit; 278 | s.sscratchc.commit; 279 | s.sepcc.commit; 280 | `endif 281 | s.mtcc.commit; 282 | s.mtdc.commit; 283 | s.mscratchc.commit; 284 | s.mepcc.commit; 285 | `endif 286 | endaction; 287 | 288 | endinstance 289 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_RVCommon.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import FIFOF :: *; 30 | import SpecialFIFOs :: *; 31 | 32 | import BID :: *; 33 | import BlueBasics :: *; 34 | import BlueUtils :: *; 35 | import BitPat :: *; 36 | import Recipe :: *; 37 | import RVBS_Trap :: *; 38 | import RVBS_Types :: *; 39 | import RVBS_MemAccess :: *; 40 | import RVBS_TraceInsts :: *; 41 | 42 | `ifdef RVFI_DII 43 | import RVFI_DII_Bridge :: *; 44 | import FIFO :: *; 45 | import ClientServer :: *; 46 | import GetPut :: *; 47 | `endif 48 | 49 | `ifdef RVXCHERI 50 | import CHERICap :: *; 51 | `endif 52 | 53 | module [ISADefModule] mkRVCommon#(RVState s) (Empty); 54 | 55 | // instanciate memory access state machines 56 | match {.dataReadRules, .dataReadFSM} <- mkRecipeFSMSlaveRules(doReadMemCore( 57 | `ifdef SUPERVISOR_MODE 58 | s.dvm, 59 | `endif 60 | `ifdef PMP 61 | s.dpmp, 62 | `endif 63 | s.dmem 64 | )); 65 | match {.dataWriteRules, .dataWriteFSM} <- mkRecipeFSMSlaveRules( 66 | doWriteMemCore( 67 | `ifdef SUPERVISOR_MODE 68 | s.dvm, 69 | `endif 70 | `ifdef PMP 71 | s.dpmp, 72 | `endif 73 | s.dmem 74 | )); 75 | addRules(rJoinMutuallyExclusive(dataReadRules, dataWriteRules)); 76 | 77 | // Memory commons 78 | `ifdef RVXCHERI 79 | match {.rHandle, .rOffset, .rDest, .rNumBytes, .rSgnExt, .rCapAccess} = s.readMem.first; 80 | match {.rCapIdx, .rCap, .rVaddr} = unpackHandle(s.ddc, s.pcc, rHandle); 81 | match {.wHandle, .wOffset, .wNumBytes, .wData, .wCapAccess} = s.writeMem.first; 82 | match {.wCapIdx, .wCap, .wVaddr} = unpackHandle(s.ddc, s.pcc, wHandle); 83 | `else 84 | match {.rVaddr, .rOffset, .rDest, .rNumBytes, .rSgnExt} = s.readMem.first; 85 | match {.wVaddr, .wOffset, .wNumBytes, .wData} = s.writeMem.first; 86 | `endif 87 | let readAddr = rVaddr + rOffset; 88 | let writeAddr = wVaddr + wOffset; 89 | // call back for read responses 90 | function readCallBack(rsp) = action 91 | case (rsp) matches 92 | tagged Left .excTok: raiseMemTokException(s, excTok); 93 | tagged Right .memRsp: case (memRsp) matches 94 | tagged RVReadRsp .r: begin 95 | `ifdef RVXCHERI 96 | match {.captag, .data} = r; 97 | Bit#(CapNoValidSz) capData = truncate(data); 98 | CapType newCap = fromMem(tuple2(captag == 1, capData)); 99 | `else 100 | let data = r; 101 | `endif 102 | let topIdx = {readBitPO(rNumBytes), 3'b000}; 103 | Bool isNeg = unpack(data[topIdx-1]); 104 | Bit#(XLEN) mask = (~0) << topIdx; 105 | `ifdef RVXCHERI 106 | if (rCapAccess) s.wCR(rDest, newCap); 107 | else 108 | `endif 109 | s.wGPR(rDest, (rSgnExt && isNeg) ? truncate(data) | mask : truncate(data) & ~mask); 110 | logInst(s, $format("load")); 111 | end 112 | tagged RVBusError: action raiseMemException(s, LoadAccessFault, readAddr); endaction 113 | endcase 114 | endcase 115 | endaction; 116 | // call back for write responses 117 | function writeCallBack(rsp) = action 118 | case (rsp) matches 119 | tagged Left .excTok: raiseMemTokException(s, excTok); 120 | tagged Right .memRsp: case (memRsp) matches 121 | tagged RVWriteRsp: logInst(s, $format("store")); 122 | tagged RVBusError: action raiseMemException(s, StrAMOAccessFault, writeAddr); endaction 123 | endcase 124 | endcase 125 | endaction; 126 | // prepare exception tokens 127 | let rExcTok = Invalid; 128 | let wExcTok = Invalid; 129 | `ifdef RVXCHERI 130 | // check for potential capability exceptions 131 | let m_rCapExc = memCapChecks(READ, rCap, readAddr, rNumBytes, rCapAccess); 132 | if (isValid(m_rCapExc)) rExcTok = Valid(ExcToken{ 133 | excCode: CHERIFault, 134 | tval: 0, 135 | capExcCode: m_rCapExc.Valid, 136 | capIdx: rCapIdx 137 | }); 138 | let m_wCapExc = memCapChecks(WRITE, wCap, writeAddr, wNumBytes, wCapAccess); 139 | if (isValid(m_wCapExc)) wExcTok = Valid(ExcToken{ 140 | excCode: CHERIFault, 141 | tval: 0, 142 | capExcCode: m_wCapExc.Valid, 143 | capIdx: wCapIdx 144 | }); 145 | `endif 146 | // handle mem requests on epilogue 147 | defineEpiEntry(rOneMatch(list(s.readMem.notEmpty, s.writeMem.notEmpty), 148 | list( 149 | // handle reads 150 | rFastSeq(rBlock( 151 | dataReadFSM.sink.put(tuple4(rExcTok, READ, readAddr, rNumBytes)), 152 | action 153 | let rsp <- get(dataReadFSM.source); 154 | readCallBack(rsp); 155 | s.readMem.deq; 156 | endaction 157 | )), 158 | // handle writes 159 | rFastSeq(rBlock( 160 | action 161 | `ifdef RVXCHERI 162 | dataWriteFSM.sink.put(tuple5(wExcTok, writeAddr, wNumBytes, wData, wCapAccess)); 163 | `else 164 | dataWriteFSM.sink.put(tuple4(wExcTok, writeAddr, wNumBytes, wData)); 165 | `endif 166 | `ifdef RVFI_DII 167 | s.mem_addr[0] <= writeAddr; 168 | s.mem_wdata[0] <= truncate(wData); 169 | s.mem_wmask[0] <= ~((~0) << readBitPO(wNumBytes)); 170 | `endif 171 | endaction, action 172 | let rsp <- get(dataWriteFSM.source); 173 | writeCallBack(rsp); 174 | s.writeMem.deq; 175 | endaction 176 | )) 177 | ), 178 | rAct(noAction))); 179 | endmodule 180 | 181 | // Instruction fetch 182 | //////////////////////////////////////////////////////////////////////////////// 183 | module [ISADefModule] mkRVIFetch#(RVState s) (); 184 | // memory read recipe function 185 | let iFetchFF <- mkBypassFIFOF; 186 | let iFetchCore = doReadMemCore( 187 | `ifdef SUPERVISOR_MODE 188 | s.ivm, 189 | `endif 190 | `ifdef PMP 191 | s.ipmp, 192 | `endif 193 | s.imem 194 | ); 195 | // preparing exception token 196 | let excTok = Invalid; 197 | `ifdef RVXCHERI 198 | let m_ifetchCapExc = ifetchCapChecks(s.pcc, getBase(s.pcc) + s.pc, 4, False); 199 | if (isValid(m_ifetchCapExc)) excTok = Valid(ExcToken{ 200 | excCode: CHERIFault, 201 | tval: 0, 202 | capExcCode: m_ifetchCapExc.Valid, 203 | capIdx: 6'b100000 // this is PCC 204 | }); 205 | `endif 206 | function Recipe instFetch(RVState s, Sink#(Bit#(InstWidth)) snk); 207 | // call back for ifetch responses 208 | function ifetchCallBack(rsp) = action 209 | let newInst = 'h00000013; // default to NOP (defined as addi, x0, x0, 0) 210 | case (rsp) matches 211 | tagged Left .excTok: raiseIFetchTokException(s, excTok); 212 | tagged Right .memRsp: case (memRsp) matches 213 | tagged RVReadRsp .val: begin 214 | `ifdef RVXCHERI 215 | match {.captag, .data} = val; 216 | `else 217 | let data = val; 218 | `endif 219 | let newInstSz = (data[1:0] == 2'b11) ? 4 : 2; 220 | asIfc(s.pc.early) <= s.pc + newInstSz; 221 | s.instByteSz <= newInstSz; 222 | newInst = truncate(data); 223 | end 224 | default: begin 225 | raiseIFetchException(s, InstAccessFault); 226 | end 227 | endcase 228 | endcase 229 | snk.put(newInst); 230 | endaction; 231 | `ifdef RVXCHERI 232 | let newpc = s.pc.late + getBase(s.pcc); 233 | `else 234 | let newpc = s.pc.late; 235 | `endif 236 | return rFastSeq(rBlock( 237 | iFetchCore(tuple4(excTok, IFETCH, s.pc.late, 4), toSink(iFetchFF)), 238 | action 239 | let rsp <- get(iFetchFF); 240 | ifetchCallBack(rsp); 241 | endaction 242 | )); 243 | endfunction 244 | // instruction fetching definition 245 | defineFetchInstEntry(instFetch(s)); 246 | endmodule 247 | 248 | `ifdef RVFI_DII 249 | // RVFI-DII Instruction fetch 250 | //////////////////////////////////////////////////////////////////////////////// 251 | module [ISADefModule] mkRVIFetch_RVFI_DII#(RVState s) (); 252 | function Recipe instFetch(RVState s, Sink#(Bit#(InstWidth)) snk) = 253 | rPipe(rBlock(action 254 | let inst <- s.rvfi_dii_bridge.client.getInst(0); 255 | s.iFF.enq(inst); 256 | endaction, action 257 | asIfc(s.pc.early) <= s.pc + 4; 258 | s.instByteSz <= 4; 259 | snk.put(s.iFF.first); 260 | endaction 261 | )); 262 | // instruction fetching definition 263 | defineFetchInstEntry(instFetch(s)); 264 | endmodule 265 | `endif 266 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_MemAccess.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import FIFOF :: *; 30 | 31 | import Recipe :: *; 32 | import BlueUtils :: *; 33 | import BlueBasics :: *; 34 | 35 | import RVBS_Types :: *; 36 | import RVBS_Trap :: *; 37 | 38 | ///////////////////////////////// 39 | // Load and Store Instructions // 40 | //////////////////////////////////////////////////////////////////////////////// 41 | 42 | /* 43 | I-type 44 | 45 | 31 20 19 15 14 12 11 7 6 0 46 | +-------------------------------------+--------+--------+--------+----------+ 47 | | imm[11:0] | rs1 | funct3 | rd | opcode | 48 | +-------------------------------------+--------+--------+--------+----------+ 49 | */ 50 | function Recipe load(RVState s, LoadArgs args, Bit#(12) imm, Bit#(5) rs1, Bit#(5) rd) = 51 | readData(s, args, s.rGPR(rs1), signExtend(imm), rd); 52 | 53 | /* 54 | S-type 55 | 56 | 31 25 24 20 19 15 14 12 11 7 6 0 57 | +----------------------------+--------+--------+--------+--------+----------+ 58 | | imm[11:5] | rs2 | rs1 | funct3 |imm[4:0]| opcode | 59 | +----------------------------+--------+--------+--------+--------+----------+ 60 | */ 61 | function Recipe store(RVState s, StrArgs args, Bit#(7) imm11_5, Bit#(5) rs2, Bit#(5) rs1, Bit#(5) imm4_0); 62 | Bit#(XLEN) imm = {signExtend(imm11_5), imm4_0}; 63 | return writeData(s, args, zeroExtend(s.rGPR(rs2)), s.rGPR(rs1), signExtend(imm)); 64 | endfunction 65 | 66 | /////////////////// 67 | // inner helpers // 68 | //////////////////////////////////////////////////////////////////////////////// 69 | 70 | function Either#(ExcToken, a) excOrArg (Maybe#(ExcToken) m_tok, a x); 71 | if (isValid(m_tok)) return Left(m_tok.Valid); 72 | else return Right(x); 73 | endfunction 74 | 75 | `ifdef RVXCHERI 76 | import CHERICap :: *; 77 | `endif 78 | 79 | `ifdef RVXCHERI 80 | function Maybe#(CapExcCode) memCapChecks( 81 | RVMemReqType reqType, 82 | CapType cap, 83 | VAddr vaddr, 84 | BitPO#(4) numBytes, 85 | Bool capAccess); 86 | if (!isValidCap(cap)) return Valid(CapExcTag); 87 | else if (isSealed(cap)) return Valid(CapExcSeal); 88 | else if (reqType == READ && !getHardPerms(cap).permitLoad) return Valid(CapExcPermLoad); 89 | else if (reqType == WRITE && !getHardPerms(cap).permitStore) return Valid(CapExcPermStore); 90 | else if (reqType == READ && capAccess && !getHardPerms(cap).permitLoadCap) return Valid(CapExcPermLoadCap); 91 | else if (reqType == WRITE && capAccess && !getHardPerms(cap).permitStoreCap) return Valid(CapExcPermStoreCap); 92 | else if (zeroExtend(vaddr) < getBase(cap)) return Valid(CapExcLength); 93 | else if (zeroExtend(vaddr) + zeroExtend(readBitPO(numBytes)) > getTop(cap)) return Valid(CapExcLength); 94 | else return Invalid; 95 | endfunction 96 | function Maybe#(CapExcCode) ifetchCapChecks( 97 | CapType cap, 98 | VAddr vaddr, 99 | BitPO#(4) numBytes, 100 | Bool capAccess); 101 | if (!isValidCap(cap)) return Valid(CapExcTag); 102 | else if (isSealed(cap)) return Valid(CapExcSeal); 103 | else if (!getHardPerms(cap).permitExecute) return Valid(CapExcPermExe); 104 | else if (zeroExtend(vaddr) < getBase(cap)) return Valid(CapExcLength); 105 | else if (zeroExtend(vaddr) + zeroExtend(readBitPO(numBytes)) > getTop(cap)) return Valid(CapExcLength); 106 | else return Invalid; 107 | endfunction 108 | `endif 109 | 110 | // Read access 111 | //////////////////////////////////////////////////////////////////////////////// 112 | 113 | function Recipe doReadMemCore( 114 | `ifdef SUPERVISOR_MODE 115 | VMLookup vm, 116 | `endif 117 | `ifdef PMP 118 | PMPLookup pmp, 119 | `endif 120 | RVMem mem, 121 | Tuple4#(Maybe#(ExcToken), RVMemReqType, VAddr, BitPO#(4)) args, 122 | Sink#(Either#(ExcToken, RVMemRsp)) rspSink 123 | ); 124 | match {.m_excToken, .reqType, .vaddr, .numBytes} = args; 125 | return rPipe(rBlock( 126 | rFastSeq(rBlock(action 127 | `ifdef SUPERVISOR_MODE 128 | let req = excOrArg(m_excToken, aReq(reqType, vaddr, numBytes)); 129 | vm.sink.put(req); 130 | endaction, action 131 | let rAddr <- get(vm.source); 132 | `else 133 | let rAddr = excOrArg(m_excToken, toPAddr(vaddr)); 134 | `endif 135 | `ifdef PMP 136 | let req = craftAReq(reqType, rAddr, numBytes); 137 | pmp.sink.put(req); 138 | endaction, action 139 | let rAddr <- get(pmp.source); 140 | `endif 141 | Either#(ExcToken, RVMemReq) req = case (rAddr) matches 142 | tagged Left .excTok: return Left(excTok); 143 | tagged Right .checkedAddr: 144 | return Right(RVReadReq {addr: checkedAddr, numBytes: numBytes}); 145 | endcase; 146 | mem.sink.put(req); 147 | if (req matches tagged Right .r) 148 | printTPlusArgs("memTrace", $format("sending read request: ", fshow(r))); 149 | endaction)), action 150 | let rsp <- get(mem.source); 151 | rspSink.put(rsp); 152 | endaction)); 153 | endfunction 154 | 155 | function Recipe readData( 156 | RVState s, 157 | LoadArgs args, 158 | VAddr vaddr, 159 | VAddr offset, 160 | Bit#(5) dest 161 | ) = 162 | `ifndef RVXCHERI 163 | rAct(s.readMem.enq(tuple5(vaddr, offset, dest, fromInteger(args.numBytes), args.sgnExt))); 164 | `else 165 | rAct(s.readMem.enq(tuple6(DDCAccessHandle(vaddr), offset, dest, fromInteger(args.numBytes), args.sgnExt, False))); 166 | `endif 167 | 168 | `ifdef RVXCHERI 169 | function Recipe readCap( 170 | RVState s, 171 | LoadArgs args, 172 | VAddr vaddr, 173 | VAddr offset, 174 | Bit#(5) dest 175 | ) = rAct(s.readMem.enq(tuple6(DDCAccessHandle(vaddr), offset, dest, fromInteger(args.numBytes), args.sgnExt, True))); 176 | 177 | function Recipe capReadData( 178 | RVState s, 179 | LoadArgs args, 180 | Bit#(5) capIdx, 181 | VAddr offset, 182 | Bit#(5) dest 183 | ) = rAct(s.readMem.enq(tuple6(CapAccessHandle(tuple2(capIdx, s.rCR(capIdx))), offset, dest, fromInteger(args.numBytes), args.sgnExt, False))); 184 | 185 | function Recipe capReadCap( 186 | RVState s, 187 | LoadArgs args, 188 | Bit#(5) capIdx, 189 | VAddr offset, 190 | Bit#(5) dest 191 | ) = rAct(s.readMem.enq(tuple6(CapAccessHandle(tuple2(capIdx, s.rCR(capIdx))), offset, dest, fromInteger(args.numBytes), args.sgnExt, True))); 192 | `endif 193 | 194 | // Write access 195 | //////////////////////////////////////////////////////////////////////////////// 196 | 197 | function Recipe doWriteMemCore( 198 | `ifdef SUPERVISOR_MODE 199 | VMLookup vm, 200 | `endif 201 | `ifdef PMP 202 | PMPLookup pmp, 203 | `endif 204 | RVMem mem, 205 | `ifndef RVXCHERI 206 | Tuple4#(Maybe#(ExcToken), VAddr, BitPO#(4), Bit#(128)) args, 207 | `else 208 | Tuple5#(Maybe#(ExcToken), VAddr, BitPO#(4), Bit#(128), Bool) args, 209 | `endif 210 | Sink#(Either#(ExcToken, RVMemRsp)) rspSink 211 | ); 212 | `ifndef RVXCHERI 213 | match {.m_excToken, .vaddr, .numBytes, .wdata} = args; 214 | `else 215 | match {.m_excToken, .vaddr, .numBytes, .wdata, .capWrite} = args; 216 | `endif 217 | return rFastSeq(rBlock(action 218 | `ifdef SUPERVISOR_MODE 219 | let req = excOrArg(m_excToken, aReqWrite(vaddr, numBytes)); 220 | vm.sink.put(req); 221 | endaction, action 222 | let rsp <- get(vm.source); 223 | `else 224 | let rsp = excOrArg(m_excToken, toPAddr(vaddr)); 225 | `endif 226 | `ifdef PMP 227 | let req = craftAReq(WRITE, rsp, numBytes); 228 | pmp.sink.put(req); 229 | endaction, action 230 | let rsp <- get(pmp.source); 231 | `endif 232 | let req = case (rsp) matches 233 | tagged Left .excTok: return Left(excTok); 234 | tagged Right .checkedAddr: 235 | return Right(RVWriteReq{ 236 | addr: checkedAddr, 237 | byteEnable: ~((~0) << readBitPO(numBytes)), 238 | data: wdata 239 | `ifdef RVXCHERI 240 | , captag: pack(capWrite) 241 | `endif 242 | }); 243 | endcase; 244 | mem.sink.put(req); 245 | if (req matches tagged Right .r) 246 | printTPlusArgs("memTrace", $format("sending write request: ", fshow(r))); 247 | endaction, action 248 | let rsp <- get(mem.source); 249 | rspSink.put(rsp); 250 | endaction)); 251 | endfunction 252 | 253 | function Recipe writeData( 254 | RVState s, 255 | StrArgs args, 256 | Bit#(128) wdata, 257 | VAddr vaddr, 258 | VAddr offset 259 | ) = 260 | `ifndef RVXCHERI 261 | rAct(s.writeMem.enq(tuple4(vaddr, offset, fromInteger(args.numBytes), wdata))); 262 | `else 263 | rAct(s.writeMem.enq(tuple5(DDCAccessHandle(vaddr), offset, fromInteger(args.numBytes), wdata, False))); 264 | `endif 265 | 266 | `ifdef RVXCHERI 267 | function Recipe writeCap( 268 | RVState s, 269 | StrArgs args, 270 | CapType cap, 271 | VAddr vaddr, 272 | VAddr offset 273 | ); 274 | match {.capTag, .capBits} = toMem(cap); 275 | return rAct(s.writeMem.enq(tuple5( 276 | DDCAccessHandle(vaddr), 277 | offset, 278 | fromInteger(args.numBytes), 279 | zeroExtend(capBits), 280 | capTag))); 281 | endfunction 282 | 283 | function Recipe capWriteData( 284 | RVState s, 285 | StrArgs args, 286 | Bit#(128) wdata, 287 | Bit#(5) capIdx, 288 | VAddr offset 289 | ) = rAct(s.writeMem.enq(tuple5(CapAccessHandle(tuple2(capIdx, s.rCR(capIdx))), offset, fromInteger(args.numBytes), wdata, False))); 290 | 291 | function Recipe capWriteCap( 292 | RVState s, 293 | StrArgs args, 294 | CapType wcap, 295 | Bit#(5) capIdx, 296 | VAddr offset 297 | ); 298 | match {.capTag, .capBits} = toMem(wcap); 299 | return rAct(s.writeMem.enq(tuple5( 300 | CapAccessHandle(tuple2(capIdx, s.rCR(capIdx))), 301 | offset, 302 | fromInteger(args.numBytes), 303 | zeroExtend(capBits), 304 | capTag))); 305 | endfunction 306 | `endif 307 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_CSRs.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import DefaultValue :: *; 30 | import ConfigReg :: *; 31 | import Vector :: *; 32 | 33 | import BlueUtils :: *; 34 | import RVBS_Types :: *; 35 | `ifdef PMP 36 | import RVBS_PMPTypes :: *; 37 | `endif 38 | 39 | ////////////////////////////// 40 | // CSR_Ifc's implementation // 41 | ////////////////////////////// 42 | 43 | module mkCSRCore#(Integer m, Integer n, module#(Reg#(csr_t)) mkTheCSR)(CSR_Ifc#(csr_t)) 44 | provisos (Bits#(csr_t, csr_sz)); 45 | // internal module decalration 46 | Reg#(csr_t) r <- mkTheCSR; 47 | Wire#(csr_t) pre[m] <- mkDCWire(m, r._read); 48 | Wire#(csr_t) inst[2] <- mkDCWire(2, (m > 0) ? pre[m-1]._read : r._read); 49 | Wire#(csr_t) post[n] <- mkDCWire(n, inst[1]._read); 50 | RWire#(csr_t) last <- mkRWire; 51 | 52 | // update the register 53 | rule update_reg; case (last.wget) matches 54 | tagged Valid .newVal: r <= newVal; 55 | tagged Invalid: r <= (n > 0) ? post[n-1]._read : inst[1]._read; 56 | endcase endrule 57 | 58 | // populating interfaces 59 | interface preInstView = pre; 60 | interface instView = interface Reg; 61 | method _read = inst[0]._read; 62 | method _write = inst[1]._write; 63 | endinterface; 64 | interface postInstView = post; 65 | method _read = r._read; 66 | method _write = last.wset; 67 | endmodule 68 | 69 | module mkCSR#(csr_t dflt)(CSR_Ifc#(csr_t)) provisos (Bits#(csr_t, csr_sz)); 70 | let ifc <- mkCSRCore(0,0,mkConfigReg(dflt)); 71 | return ifc; 72 | endmodule 73 | module mkCSRU(CSR_Ifc#(csr_t)) provisos (Bits#(csr_t, csr_sz)); 74 | let ifc <- mkCSRCore(0,0,mkConfigRegU); 75 | return ifc; 76 | endmodule 77 | module mkCSRUndef#(String name)(CSR_Ifc#(csr_t)) provisos (Bits#(csr_t, csr_sz)); 78 | Reg#(csr_t) r <- mkRegUndef(name); 79 | interface preInstView = ?; 80 | interface instView = ?; 81 | interface postInstView = ?; 82 | method _read = r._read; 83 | method _write = r._write; 84 | endmodule 85 | 86 | ////////////////////////// 87 | // CSRs' implementation // 88 | //////////////////////////////////////////////////////////////////////////////// 89 | module mkCSRs(CSRs); 90 | 91 | // instance of the CSRs struct 92 | CSRs csrs; 93 | 94 | // machine information registers 95 | ////////////////////////////////////////////////////////////////////////////// 96 | csrs.mvendorid <- mkCSR(defaultValue); // mvendorid 12'hF11 97 | //csrs.marchid <- mkCSR(0); // marchid 12'hF12 98 | // XXX recently allocated marchid: https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md 99 | csrs.marchid <- mkCSR(10); // marchid 12'hF12 100 | csrs.mimpid <- mkCSR(0); // mimpid 12'hF13 101 | csrs.mhartid <- mkCSR(0); // mhartid 12'hF14 102 | 103 | // machine trap setup registers 104 | ////////////////////////////////////////////////////////////////////////////// 105 | csrs.mstatus <- mkCSR(defaultValue); // mstatus 12'h300 106 | csrs.misa <- mkCSR(defaultValue); // misa 12'h301 107 | csrs.medeleg <- mkCSRUndef("medeleg"); 108 | csrs.mideleg <- mkCSRUndef("mideleg"); 109 | if (static_HAS_S_MODE || (static_HAS_U_MODE && static_HAS_N_EXT)) begin 110 | csrs.medeleg <- mkCSR(defaultValue); // medeleg 12'h302 111 | csrs.mideleg <- mkCSR(defaultValue); // mideleg 12'h303 112 | end 113 | csrs.mie <- mkCSR(defaultValue); // mie 12'h304 114 | csrs.mtvec <- mkCSR(defaultValue); // mtvec 12'h305 115 | // mcounteren 12'h306 116 | 117 | // machine trap handling 118 | ////////////////////////////////////////////////////////////////////////////// 119 | csrs.mscratch <- mkCSRU; // mscratch 12'h340 120 | csrs.mepc <- mkCSR(defaultValue); // mepc 12'h341 121 | csrs.mcause <- mkCSRU; // mcause 12'h342 122 | csrs.mtval <- mkCSRU; // mtval 12'h343 123 | csrs.mip <- mkCSRCore(1, 0, mkConfigReg(defaultValue)); // mip 12'h344 124 | 125 | // machine protection and translation 126 | ////////////////////////////////////////////////////////////////////////////// 127 | `ifdef PMP 128 | // pmpcfg0 12'h3A0 129 | // pmpcfg1 12'h3A1 (RV32 only) 130 | // pmpcfg2 12'h3A2 131 | // pmpcfg3 12'h3A3 (RV32 only) 132 | // pmpaddr0 12'h3B0 133 | // pmpaddr1 12'h3B1 134 | // ... 135 | // pmpaddr15 12'h3BF 136 | csrs.pmpcfg <- replicateM(mkCSRCore(1,0,mkPMPCfgIfcReg)); 137 | csrs.pmpaddr <- replicateM(mkCSRCore(1,0,mkConfigReg(defaultValue))); 138 | `endif 139 | 140 | // machine counter / timers 141 | ////////////////////////////////////////////////////////////////////////////// 142 | // mcycle 12'hB00 143 | // minsret 12'hB02 144 | // mhpmcounter3 12'hB03 (and 12'hB83 in RV32) 145 | // mhpmcounter4 12'hB04 (and 12'hB84 in RV32) 146 | // ... 147 | // mhpmcounter31 12'B1F (and 12'hB9F in RV32) 148 | 149 | // machine counter setup 150 | ////////////////////////////////////////////////////////////////////////////// 151 | // mhpmevent3 12'h323 152 | // mhpmevent4 12'h324 153 | // ... 154 | // mhpmevent31 12'h33F 155 | 156 | // debug / trace registers (shared with debug mode) 157 | ////////////////////////////////////////////////////////////////////////////// 158 | // tselect 12'h7A0 159 | // tdata1 12'h7A1 160 | // tdata2 12'h7A2 161 | // tdata3 12'h7A3 162 | 163 | // debug mode registers 164 | ////////////////////////////////////////////////////////////////////////////// 165 | // dcsr 12'h7B0 166 | // dpc 12'h7B1 167 | // dscratch 12'h7B2 168 | 169 | `ifdef SUPERVISOR_MODE 170 | // supervisor trap setup 171 | ////////////////////////////////////////////////////////////////////////////// 172 | // sstatus 12'h100 -- S-view of mstatus 173 | csrs.sedeleg <- mkCSRUndef("medeleg"); 174 | csrs.sideleg <- mkCSRUndef("sideleg"); 175 | if (static_HAS_U_MODE && static_HAS_N_EXT) begin 176 | csrs.sedeleg <- mkCSR(defaultValue); // sedeleg 12'h102 177 | csrs.sideleg <- mkCSR(defaultValue); // sideleg 12'h103 178 | end 179 | // sie 12'h104 -- S-view of mie 180 | csrs.stvec <- mkCSR(defaultValue); // stvec 12'h105 181 | // TODO scounteren 12'h106 182 | 183 | // supervisor trap handling 184 | ////////////////////////////////////////////////////////////////////////////// 185 | csrs.sscratch <- mkCSRU; // sscratch 12'h140 186 | csrs.sepc <- mkCSR(defaultValue); // sepc 12'h141 187 | csrs.scause <- mkCSRU; // scause 12'h142 188 | csrs.stval <- mkCSRU; // stval 12'h143 189 | // sip 12'h144 -- S-view of mip 190 | 191 | // supervisor protection and translation 192 | ////////////////////////////////////////////////////////////////////////////// 193 | csrs.satp <- mkCSR(defaultValue); // satp 12h'180 194 | `endif 195 | 196 | // user trap setup registers 197 | ////////////////////////////////////////////////////////////////////////////// 198 | // ustatus 12'h000 199 | // uie 12'h004 200 | // utvec 12'h005 201 | 202 | // user trap handling 203 | ////////////////////////////////////////////////////////////////////////////// 204 | // uscratch 12'h040 205 | // uepc 12'h041 206 | // ucause 12'h042 207 | // utval 12'h043 208 | // uip 12'h044 209 | 210 | // user counters/timers 211 | ////////////////////////////////////////////////////////////////////////////// 212 | csrs.cycle <- mkCSR(0); // cycle 12'hC00 (and 12'hC80 in RV32) 213 | rule cycle_count; 214 | csrs.cycle <= csrs.cycle + 1; 215 | endrule 216 | // time 12'hC01 (and 12'hC81 in RV32) 217 | // csrs.instret <- mkCommittedInstCnt; // insret 12'hC02 (and 12'hC82 in RV32) 218 | // hpmcounter3 12'hC03 (and 12'hC83 in RV32) 219 | // hpmcounter4 12'hC04 (and 12'hC84 in RV32) 220 | // ... 221 | // hpmcounter31 12'hC1F (and 12'hC9F in RV32) 222 | 223 | // XXX for debug purposes: 224 | csrs.ctrl <- mkCSR(0); // ctrl 12'hCC0 225 | 226 | // IRQs 227 | Wire#(Bool) msip_w <- mkDWire(csrs.mip.msip); 228 | Wire#(Bool) mtip_w <- mkDWire(csrs.mip.mtip); 229 | Wire#(Bool) meip_w <- mkDWire(csrs.mip.meip); 230 | function doSetMSIP(irq) = action msip_w <= irq; endaction; 231 | csrs.setMSIP = doSetMSIP; 232 | function doSetMTIP(irq) = action mtip_w <= irq; endaction; 233 | csrs.setMTIP = doSetMTIP; 234 | function doSetMEIP(irq) = action meip_w <= irq; endaction; 235 | csrs.setMEIP = doSetMEIP; 236 | rule setIRQs; 237 | let new_mip = csrs.mip; 238 | new_mip.msip = msip_w; 239 | new_mip.mtip = mtip_w; 240 | new_mip.meip = meip_w; 241 | asReg(csrs.mip.preInstView[0]) <= new_mip; 242 | endrule 243 | 244 | // CSR requests 245 | function ActionValue#(Bit#(XLEN)) readUpdateCSR(Reg#(csr_t) csr, CSRReq r) 246 | provisos (FShow#(csr_t), Bits#(csr_t, XLEN), 247 | LegalizeRead#(csr_t), LegalizeWrite#(csr_t)) = actionvalue 248 | csr_t tmpval = legalizeRead(csr); 249 | Bit#(XLEN) retval = pack(tmpval); 250 | if (r.rEffects != NOWRITE) begin 251 | csr_t newval = ?; 252 | case (r.rType) 253 | RW: newval = unpack(r.val); 254 | RS: newval = unpack(pack(csr) | r.val); 255 | RC: newval = unpack(pack(csr) & ~r.val); 256 | endcase 257 | //printTLogPlusArgs("CSRs", $format("newval before legalize: 0x%0x", newval)); 258 | csr_t newcsr = legalizeWrite(pack(csr), newval); 259 | //printTLogPlusArgs("CSRs", $format("newval after legalize: 0x%0x", pack(newcsr))); 260 | csr <= newcsr; 261 | printTLogPlusArgs("CSRs", $format(fshow(csr) + $format(" -> ") + fshow(newcsr))); 262 | end else printTLogPlusArgs("CSRs", $format("reading value 0x%0x from CSR", retval)); 263 | return retval; 264 | endactionvalue; 265 | function ActionValue#(csr_t0) readUpdateMultiViewCSR(Reg#(csr_t1) csr, CSRReq r) 266 | provisos(FShow#(csr_t1), Bits#(csr_t1, XLEN), Bits#(csr_t0, XLEN), 267 | Lower#(csr_t1, csr_t0), Lift#(csr_t0, csr_t1)) = actionvalue 268 | csr_t0 retval = lower(csr); 269 | if (r.rEffects != NOWRITE) begin 270 | csr_t0 newval = ?; 271 | case (r.rType) 272 | RW: newval = unpack(r.val); 273 | RS: newval = unpack(pack(csr) | r.val); 274 | RC: newval = unpack(pack(csr) & ~r.val); 275 | endcase 276 | csr_t1 newcsr = lift(pack(csr), newval); 277 | csr <= newcsr; 278 | printTLogPlusArgs("CSRs", $format(fshow(csr) + $format(" -> ") + fshow(newcsr))); 279 | end else printTLogPlusArgs("CSRs", $format("reading value 0x%0x from CSR", retval)); 280 | return retval; 281 | endactionvalue; 282 | function ActionValue#(Maybe#(Bit#(XLEN))) req (CSRReq r) = actionvalue 283 | Bit#(XLEN) ret = ?; 284 | Bool doTrap = False; 285 | `define CSRUpdate(x) ret <- readUpdateCSR(x,r); 286 | `define MVCSRUpdate(x, y) begin x tmp <- readUpdateMultiViewCSR(y,r); ret = pack(tmp); end 287 | case (r.idx) matches// TODO sort out individual behaviours for each CSR 288 | `ifdef SUPERVISOR_MODE 289 | 12'h100: `MVCSRUpdate(SStatus, csrs.mstatus.instView) 290 | 12'h102 &&& (static_HAS_U_MODE && static_HAS_N_EXT): 291 | `CSRUpdate(csrs.sedeleg.instView) 292 | 12'h103 &&& (static_HAS_U_MODE && static_HAS_N_EXT): 293 | `CSRUpdate(csrs.sideleg.instView) 294 | 12'h104: `MVCSRUpdate(SIE, csrs.mie.instView) 295 | 12'h105: `CSRUpdate(csrs.stvec.instView) 296 | 12'h140: `CSRUpdate(csrs.sscratch.instView) 297 | 12'h141: `CSRUpdate(csrs.sepc.instView) 298 | 12'h142: `CSRUpdate(csrs.scause.instView) 299 | 12'h143: `CSRUpdate(csrs.stval.instView) 300 | 12'h144: `MVCSRUpdate(SIP, csrs.mip.instView) 301 | 12'h180: `CSRUpdate(csrs.satp.instView) 302 | `endif 303 | 12'h300: `MVCSRUpdate(MStatus, csrs.mstatus.instView) 304 | 12'h301: `CSRUpdate(csrs.misa.instView) 305 | 12'h302 &&& (static_HAS_S_MODE || (static_HAS_U_MODE && static_HAS_N_EXT)): 306 | `CSRUpdate(csrs.medeleg.instView) 307 | 12'h303 &&& (static_HAS_S_MODE || (static_HAS_U_MODE && static_HAS_N_EXT)): 308 | `CSRUpdate(csrs.mideleg.instView) 309 | 12'h304: `MVCSRUpdate(MIE, csrs.mie.instView) 310 | 12'h305: `CSRUpdate(csrs.mtvec.instView) 311 | 12'h340: `CSRUpdate(csrs.mscratch.instView) 312 | 12'h341: `CSRUpdate(csrs.mepc.instView) 313 | 12'h342: `CSRUpdate(csrs.mcause.instView) 314 | 12'h343: `CSRUpdate(csrs.mtval.instView) 315 | 12'h344: `MVCSRUpdate(MIP, csrs.mip.instView) 316 | `ifdef PMP 317 | `ifdef XLEN64 318 | 12'h3A0: `CSRUpdate(csrs.pmpcfg[0].instView) 319 | 12'h3A2: `CSRUpdate(csrs.pmpcfg[1].instView) 320 | `else 321 | .x &&& (12'h3A0 >= x && x <= 12'h3A3): 322 | `CSRUpdate(csrs.pmpcfg[x - 12'h3A0].instView) 323 | `endif 324 | .x &&& (12'h3B0 >= x && x <= 12'h3BF): 325 | `CSRUpdate(csrs.pmpaddr[x - 12'h3B0].instView) 326 | `endif 327 | 12'hF11: `CSRUpdate(csrs.mvendorid.instView) 328 | 12'hF12: `CSRUpdate(csrs.marchid.instView) 329 | 12'hF13: `CSRUpdate(csrs.mimpid.instView) 330 | 12'hF14: `CSRUpdate(csrs.mhartid.instView) 331 | 12'hC00: ret = csrs.cycle.instView[valueOf(XLEN)-1:0]; 332 | //12'hC02: ret = csrs.instret[valueOf(XLEN)-1:0]; 333 | // RV32I only 334 | //'hC80: ret = cycle[63:32]; 335 | //XXX hack for test suite 336 | 12'hCC0: begin // test success 337 | csrs.ctrl[7:0] <= r.val[7:0]; 338 | if (genC) begin $display("TEST SUCCESS"); $finish(0); end 339 | end 340 | 12'hCC1: if (genC) begin $display("TEST FAILURE"); $finish(0); end // test failure 341 | default: begin 342 | doTrap = True; 343 | printLog($format("CSR 0x%0x unimplemented - ", r.idx, fshow(r))); 344 | end 345 | endcase 346 | return (doTrap) ? Invalid : Valid(ret); 347 | endactionvalue; 348 | csrs.req = req; 349 | 350 | return csrs; 351 | 352 | endmodule 353 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Ext_32_C.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import Printf :: *; 30 | import List :: *; 31 | 32 | import BID :: *; 33 | import Recipe :: *; 34 | import BlueUtils :: *; 35 | import BitPat :: *; 36 | 37 | import RVBS_Types :: *; 38 | import RVBS_Trap :: *; 39 | import RVBS_Base_RV32I :: *; 40 | import RVBS_MemAccess :: *; 41 | 42 | // RVC 3-bit reg identifier to RVI 5-bit reg identifier 43 | function Bit#(5) regID (Bit#(3) x) = {2'b01, x}; 44 | // BitPat guarded variable predicates 45 | function Bool ez (Bit#(n) x) = x == 0; 46 | function Bool eq2 (Bit#(n) x) = x == 2; 47 | function Bool neq (Bit#(n) x, Bit#(n) y) = x != y; 48 | function Bool nez (Bit#(n) x) = x != 0; 49 | function Bool n0_n2 (Bit#(n) x) = x != 0 && x != 2; 50 | function Bool nzimm (Bit#(16) x) = x[12] != 0 || x[6:2] != 0; 51 | 52 | function Action instrC_Illegal(RVState s) = action 53 | printTLogPlusArgs("itrace", $format("pc: 0x%0x -- c.illegal", s.pc)); 54 | Bit#(XLEN) tval = 0; 55 | raiseException(s, IllegalInst, tval); 56 | endaction; 57 | 58 | ///////////////////////////////// 59 | // Load and Store Instructions // 60 | //////////////////////////////////////////////////////////////////////////////// 61 | 62 | ////////////////////////////////////////// 63 | // Stack-Pointer-Based Loads and Stores // 64 | ////////////////////////////////////////// 65 | 66 | /* 67 | CI-type 68 | 69 | 15 13 12 11 7 6 2 1 0 70 | +--------+-----+-------------+--------------+----+ 71 | | funct3 | imm | rd/rs1 | imm | op | 72 | +--------+-----+-------------+--------------+----+ 73 | 74 | */ 75 | 76 | // funct3 = C.LWSP = 010 77 | // op = C2 = 10 78 | function Recipe instrC_LWSP (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(3) imm4_2, Bit#(2) imm7_6) = 79 | load(s, LoadArgs{name: "lw", numBytes: 4, sgnExt: True}, zeroExtend({imm7_6, imm5, imm4_2, 2'b00}), 2, rd); 80 | 81 | //TODO C.LQSP 82 | //TODO C.FLWSP 83 | //TODO C.FLDSP 84 | 85 | /* 86 | CSS-type 87 | 88 | 15 13 12 7 6 2 1 0 89 | +--------+-------------------+--------------+----+ 90 | | funct3 | imm | rs2 | op | 91 | +--------+-------------------+--------------+----+ 92 | 93 | */ 94 | 95 | // funct3 = C.SWSP = 110 96 | // op = C2 = 10 97 | function Recipe instrC_SWSP (RVState s, Bit#(4) imm5_2, Bit#(2) imm7_6, Bit#(5) rs2) = 98 | store(s, StrArgs{name: "sw", numBytes: 4}, zeroExtend({imm7_6,imm5_2[3]}), rs2, 2, {imm5_2[2:0], 2'b00}); 99 | 100 | //TODO C.SQSP 101 | //TODO C.FSWSP 102 | //TODO C.FSDSP 103 | 104 | ///////////////////////////////////// 105 | // Register-Based Loads and Stores // 106 | ///////////////////////////////////// 107 | 108 | /* 109 | CL-type 110 | 111 | 15 13 12 10 9 7 6 5 4 2 1 0 112 | +--------+-------+----------+-----+---------+----+ 113 | | funct3 | imm | rs1' | imm | rd' | op | 114 | +--------+-------+----------+-----+---------+----+ 115 | 116 | */ 117 | 118 | // funct3 = C.LW = 010 119 | // op = C0 = 00 120 | function Recipe instrC_LW (RVState s, Bit#(3) o5_3, Bit#(3) rs1_, Bit#(1) o2, Bit#(1) o6, Bit#(3) rd_) = 121 | load(s, LoadArgs{name: "lw", numBytes: 4, sgnExt: True}, zeroExtend({o6, o5_3, o2, 2'b00}), regID(rs1_), regID(rd_)); 122 | 123 | //TODO C.LQ 124 | //TODO C.FLW 125 | //TODO C.FLD 126 | 127 | /* 128 | CS-type 129 | 130 | 15 13 12 10 9 7 6 5 4 2 1 0 131 | +--------+-------+----------+-----+---------+----+ 132 | | funct3 | imm | rs1' | imm | rs2' | op | 133 | +--------+-------+----------+-----+---------+----+ 134 | 135 | */ 136 | 137 | // funct3 = C.SW = 110 138 | // op = C0 = 00 139 | function Recipe instrC_SW (RVState s, Bit#(3) o5_3, Bit#(3) rs1_, Bit#(1) o2, Bit#(1) o6, Bit#(3) rs2_) = 140 | store(s, StrArgs{name: "sw", numBytes: 4}, zeroExtend({o6, o5_3[2]}), regID(rs2_), regID(rs1_), {o5_3[1:0], o2, 2'b00}); 141 | 142 | //TODO C.SQ 143 | //TODO C.FSW 144 | //TODO C.FSD 145 | 146 | /////////////////////////////////// 147 | // Control Transfer Instructions // 148 | //////////////////////////////////////////////////////////////////////////////// 149 | 150 | /* 151 | CJ-type 152 | 153 | 15 13 12 2 1 0 154 | +--------+----------------------------------+----+ 155 | | funct3 | imm | op | 156 | +--------+----------------------------------+----+ 157 | 158 | */ 159 | 160 | // funct3 = C.J = 101 161 | // op = C1 = 01 162 | function Action instrC_J (RVState s, Bit#(11) i) = action 163 | Bit#(20) i20 = {signExtend(i[10]),i[6],i[8:7],i[4],i[5],i[0],i[9],i[3:1]}; 164 | instrJAL(s, i20[19], i20[9:0], i20[10], i20[18:11], 0); 165 | endaction; 166 | 167 | `ifndef XLEN64 168 | // funct3 = C.JAL = 001 169 | // op = C1 = 01 170 | function Action instrC_JAL (RVState s, Bit#(11) i) = action 171 | Bit#(20) i20 = {signExtend(i[10]),i[6],i[8:7],i[4],i[5],i[0],i[9],i[3:1]}; 172 | instrJAL(s, i20[19], i20[9:0], i20[10], i20[18:11], 1); 173 | endaction; 174 | `endif 175 | 176 | /* 177 | CR-type 178 | 179 | 15 12 11 7 6 2 1 0 180 | +-------------+--------------+--------------+----+ 181 | | funct4 | rd/rs1 | rs2 | op | 182 | +-------------+--------------+--------------+----+ 183 | 184 | */ 185 | 186 | //XXX use for rs2 ? 187 | 188 | // funct4 = C.JR = 1000 189 | // op = C2 = 10 190 | function Action instrC_JR (RVState s, Bit#(5) rs1, Bit#(5) rs2) = 191 | instrJALR(s, 0, rs1, 0); 192 | 193 | // funct4 = C.JALR = 1001 194 | // op = C2 = 10 195 | function Action instrC_JALR (RVState s, Bit#(5) rs1, Bit#(5) rs2) = 196 | instrJALR(s, 0, rs1, 1); 197 | 198 | /* 199 | CB-type 200 | 201 | 15 13 12 10 9 7 6 2 1 0 202 | +--------+----------+--------+--------------+----+ 203 | | funct3 | offset | rs1' | offset | op | 204 | +--------+----------+--------+--------------+----+ 205 | 206 | */ 207 | 208 | // funct3 = C.BEQZ = 110 209 | // op = C1 = 01 210 | function Action instrC_BEQZ (RVState s, Bit#(3) i7_5, Bit#(3) rs1_, Bit#(5) i4_0) = action 211 | Bit#(12) o = signExtend({i7_5[2], i4_0[4:3], i4_0[0], i7_5[1:0], i4_0[2:1]}); 212 | instrBEQ(s, o[11], o[9:4], 0, regID(rs1_), o[3:0], o[10]); 213 | endaction; 214 | 215 | // funct3 = C.BNEZ = 111 216 | // op = C1 = 01 217 | function Action instrC_BNEZ (RVState s, Bit#(3) i7_5, Bit#(3) rs1_, Bit#(5) i4_0) = action 218 | Bit#(12) o = signExtend({i7_5[2], i4_0[4:3], i4_0[0], i7_5[1:0], i4_0[2:1]}); 219 | instrBNE(s, o[11], o[9:4], 0, regID(rs1_), o[3:0], o[10]); 220 | endaction; 221 | 222 | //////////////////////////////////////// 223 | // Integer Computational Instructions // 224 | //////////////////////////////////////////////////////////////////////////////// 225 | 226 | ////////////////////////////////////////////// 227 | // Integer Constant-Generation Instructions // 228 | ////////////////////////////////////////////// 229 | 230 | /* 231 | CI-type 232 | 233 | 15 13 12 11 7 6 2 1 0 234 | +--------+-----+-------------+--------------+----+ 235 | | funct3 | imm | rd/rs1 | imm | op | 236 | +--------+-----+-------------+--------------+----+ 237 | 238 | */ 239 | 240 | // funct3 = C.LI = 010 241 | // op = C1 = 01 242 | function Action instrC_LI (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(5) imm4_0) = 243 | instrADDI(s, signExtend({imm5, imm4_0}), 0, rd); 244 | 245 | // funct3 = C.LUI = 011 246 | // op = C1 = 01 247 | function Action instrC_LUI (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(5) imm4_0) = 248 | instrLUI(s, signExtend({imm5, imm4_0}), rd); 249 | 250 | /////////////////////////////////////////// 251 | // Integer Register-Immediate Operations // 252 | /////////////////////////////////////////// 253 | 254 | /* 255 | CI-type 256 | 257 | 15 13 12 11 7 6 2 1 0 258 | +--------+-----+-------------+--------------+----+ 259 | | funct3 | imm | rd/rs1 | imm | op | 260 | +--------+-----+-------------+--------------+----+ 261 | 262 | */ 263 | 264 | // funct3 = C.ADDI = 000 265 | // op = C1 = 01 266 | function Action instrC_ADDI (RVState s, Bit#(1) imm5, Bit#(5) rd, Bit#(5) imm4_0) = 267 | instrADDI(s, signExtend({imm5, imm4_0}), rd, rd); 268 | 269 | // funct3 = C.ADDI16SP = 011 270 | // op = C1 = 01 271 | function Action instrC_ADDI16SP (RVState s, Bit#(1) i5, Bit#(5) rd, Bit#(5) i4_0) = 272 | instrADDI(s, signExtend({i5, i4_0[2:1], i4_0[3], i4_0[0], i4_0[4], 4'b0000}), 2, 2); 273 | 274 | // funct3 = C.SLLI = 000 275 | // op = C2 = 10 276 | function Action instrC_SLLI (RVState s, Bit#(1) i5, Bit#(5) rd, Bit#(5) i4_0) = 277 | instrSLLI(s, zeroExtend(i4_0), rd, rd); 278 | 279 | `ifndef XLEN128 280 | /* 281 | CIW-type 282 | 283 | 15 13 12 5 4 2 1 0 284 | +--------+------------------------+---------+----+ 285 | | funct3 | imm | rd' | op | 286 | +--------+------------------------+---------+----+ 287 | 288 | */ 289 | 290 | // funct3 = C.ADDI4SPN = 000 291 | // op = C0 = 00 292 | function Action instrC_ADDI4SPN (RVState s, Bit#(8) i, Bit#(3) rd_) = 293 | instrADDI(s, zeroExtend({i[5:2], i[7:6], i[0], i[1], 2'b00}), 2, regID(rd_)); 294 | `endif 295 | 296 | /* 297 | CB-type 298 | 299 | 15 13 12 11 10 9 7 6 2 1 0 300 | +--------+----+--------+----------+---------+----+ 301 | | funct3 | i5 | funct2 | rd'/rs1' | i4_0 | op | 302 | +--------+----+--------+----------+---------+----+ 303 | 304 | */ 305 | 306 | // funct3 = C.SRLI = 100 307 | // funct2 = 00 308 | // op = C1 = 01 309 | function Action instrC_SRLI (RVState s, Bit#(1) i5, Bit#(3) rd_, Bit#(5) i4_0) = 310 | instrSRLI (s, zeroExtend(i4_0), regID(rd_), regID(rd_)); 311 | 312 | // funct3 = C.SRAI = 100 313 | // funct2 = 01 314 | // op = C1 = 01 315 | function Action instrC_SRAI (RVState s, Bit#(1) i5, Bit#(3) rd_, Bit#(5) i4_0) = 316 | instrSRAI (s, zeroExtend(i4_0), regID(rd_), regID(rd_)); 317 | 318 | // funct3 = C.ANDI = 100 319 | // funct2 = 10 320 | // op = C1 = 01 321 | function Action instrC_ANDI (RVState s, Bit#(1) i5, Bit#(3) rd_, Bit#(5) i4_0) = 322 | instrANDI (s, signExtend({i5, i4_0}), regID(rd_), regID(rd_)); 323 | 324 | ////////////////////////////////////////// 325 | // Integer Register-Register Operations // 326 | ////////////////////////////////////////// 327 | 328 | /* 329 | CR-type 330 | 331 | 15 12 11 7 6 2 1 0 332 | +-------------+--------------+--------------+----+ 333 | | funct4 | rd/rs1 | rs2 | op | 334 | +-------------+--------------+--------------+----+ 335 | 336 | */ 337 | 338 | // funct4 = C.MV = 1000 339 | // op = C2 = 10 340 | function Action instrC_MV (RVState s, Bit#(5) rd, Bit#(5) rs2) = 341 | instrADD(s, rs2, 0, rd); 342 | 343 | // funct4 = C.ADD = 1001 344 | // op = C2 = 10 345 | function Action instrC_ADD (RVState s, Bit#(5) rd, Bit#(5) rs2) = 346 | instrADD(s, rs2, rd, rd); 347 | 348 | /* 349 | CS-type 350 | 351 | 15 10 9 7 6 5 4 2 1 0 352 | +----------------+----------+-----+---------+----+ 353 | | funct6 | rs1' |funct| rs2' | op | 354 | +----------------+----------+-----+---------+----+ 355 | 356 | */ 357 | 358 | // funct6 = C.AND = 100011 359 | // funct = 11 360 | // op = C1 = 01 361 | function Action instrC_AND (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 362 | instrAND(s, regID(rs2_), regID(rd_), regID(rd_)); 363 | 364 | // funct6 = C.OR = 100011 365 | // funct = 10 366 | // op = C1 = 01 367 | function Action instrC_OR (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 368 | instrOR(s, regID(rs2_), regID(rd_), regID(rd_)); 369 | 370 | // funct6 = C.XOR = 100011 371 | // funct = 01 372 | // op = C1 = 01 373 | function Action instrC_XOR (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 374 | instrXOR(s, regID(rs2_), regID(rd_), regID(rd_)); 375 | 376 | // funct6 = C.SUB = 100011 377 | // funct = 00 378 | // op = C1 = 01 379 | function Action instrC_SUB (RVState s, Bit#(3) rd_, Bit#(3) rs2_) = 380 | instrSUB(s, regID(rs2_), regID(rd_), regID(rd_)); 381 | 382 | //////////////////////////////////////////////////////////////////////////////// 383 | 384 | module [ISADefModule] mkExt_32_C#(RVState s) (); 385 | 386 | defineInstEntry("c.lwsp", pat(n(3'b010), v, gv(nez), v, v, n(2'b10)), instrC_LWSP(s)); 387 | defineInstEntry("c.swsp", pat(n(3'b110), v, v, v, n(2'b10)), instrC_SWSP(s)); 388 | defineInstEntry("c.lw", pat(n(3'b010), v, v, v, v, v, n(2'b00)), instrC_LW(s)); 389 | defineInstEntry("c.sw", pat(n(3'b110), v, v, v, v, v, n(2'b00)), instrC_SW(s)); 390 | defineInstEntry("c.j", pat(n(3'b101), v, n(2'b01)), instrC_J(s)); 391 | `ifndef XLEN64 392 | defineInstEntry("c.jal", pat(n(3'b001), v, n(2'b01)), instrC_JAL(s)); 393 | `endif 394 | defineInstEntry("c.jr", pat(n(4'b1000), gv(nez), gv(ez), n(2'b10)), instrC_JR(s)); 395 | defineInstEntry("c.jalr", pat(n(4'b1001), gv(nez), gv(ez), n(2'b10)), instrC_JALR(s)); 396 | defineInstEntry("c.beqz", pat(n(3'b110), v, v, v, n(2'b01)), instrC_BEQZ(s)); 397 | defineInstEntry("c.bnez", pat(n(3'b111), v, v, v, n(2'b01)), instrC_BNEZ(s)); 398 | defineInstEntry("c.li", pat(n(3'b010), v, gv(nez), v, n(2'b01)), instrC_LI(s)); 399 | defineInstEntry("c.lui", guarded(pat(n(3'b011), v, gv(n0_n2), v, n(2'b01)), nzimm), instrC_LUI(s)); 400 | defineInstEntry("c.addi", guarded(pat(n(3'b000), v, gv(nez), v, n(2'b01)), nzimm), instrC_ADDI(s)); 401 | defineInstEntry("c.addi16sp", guarded(pat(n(3'b011), v, gv(eq2), v, n(2'b01)), nzimm), instrC_ADDI16SP(s)); 402 | defineInstEntry("c.slli", pat(n(3'b000), gv(ez), gv(nez), v, n(2'b10)), instrC_SLLI(s)); 403 | `ifndef XLEN128 404 | defineInstEntry("c.addi4spn", pat(n(3'b000), gv(nez), v, n(2'b00)), instrC_ADDI4SPN(s)); 405 | `endif 406 | defineInstEntry("c.srli", pat(n(3'b100), gv(ez), n(2'b00), v, v, n(2'b01)), instrC_SRLI(s)); 407 | defineInstEntry("c.srai", pat(n(3'b100), gv(ez), n(2'b01), v, v, n(2'b01)), instrC_SRAI(s)); 408 | defineInstEntry("c.andi", pat(n(3'b100), v, n(2'b10), v, v, n(2'b01)), instrC_ANDI(s)); 409 | defineInstEntry("c.mv", pat(n(4'b1000), gv(nez), gv(nez), n(2'b10)), instrC_MV(s)); 410 | defineInstEntry("c.add", pat(n(4'b1001), gv(nez), gv(nez), n(2'b10)), instrC_ADD(s)); 411 | defineInstEntry("c.and", pat(n(6'b100011), v, n(2'b11), v, n(2'b01)), instrC_AND(s)); 412 | defineInstEntry("c.or", pat(n(6'b100011), v, n(2'b10), v, n(2'b01)), instrC_OR(s)); 413 | defineInstEntry("c.xor", pat(n(6'b100011), v, n(2'b01), v, n(2'b01)), instrC_XOR(s)); 414 | defineInstEntry("c.sub", pat(n(6'b100011), v, n(2'b00), v, n(2'b01)), instrC_SUB(s)); 415 | // Defined Illegal Instruction 416 | defineInstEntry("illegal", pat(n(16'h0000)), instrC_Illegal(s)); 417 | // NOP Instruction 418 | defineInstEntry("c.nop", pat(n(3'b000), gv(ez), gv(ez), gv(ez), n(2'b01)), instrC_ADDI(s)); 419 | // Breakpoint Instruction 420 | defineInstEntry("c.ebreak", pat(n(4'b1001), n(10'b0), n(2'b10)), instrEBREAK(s)); 421 | 422 | endmodule 423 | -------------------------------------------------------------------------------- /src/rvbs/RVBS_Trap.bsv: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2019 Alexandre Joannou 3 | * All rights reserved. 4 | * 5 | * This software was developed by SRI International and the University of 6 | * Cambridge Computer Laboratory (Department of Computer Science and 7 | * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 8 | * DARPA SSITH research programme. 9 | * 10 | * @BERI_LICENSE_HEADER_START@ 11 | * 12 | * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor 13 | * license agreements. See the NOTICE file distributed with this work for 14 | * additional information regarding copyright ownership. BERI licenses this 15 | * file to you under the BERI Hardware-Software License, Version 1.0 (the 16 | * "License"); you may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * 19 | * http://www.beri-open-systems.org/legal/license-1-0.txt 20 | * 21 | * Unless required by applicable law or agreed to in writing, Work distributed 22 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 23 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 24 | * specific language governing permissions and limitations under the License. 25 | * 26 | * @BERI_LICENSE_HEADER_END@ 27 | */ 28 | 29 | import BID :: *; 30 | import Recipe :: *; 31 | import BlueUtils :: *; 32 | import BitPat :: *; 33 | import RVBS_Types :: *; 34 | import RVBS_TraceInsts :: *; 35 | 36 | //////////////// 37 | // Trap logic // 38 | //////////////////////////////////////////////////////////////////////////////// 39 | 40 | // Global Interrupt-Enable and Privilege stack push 41 | function Action pushStatusStack(CSR_Ifc#(Status) status, PrivLvl from, PrivLvl to) = action 42 | Status newval = status; 43 | case (to) 44 | M: begin 45 | newval.mie = False; 46 | newval.mpie = status.mie; 47 | newval.mpp = pack(from); 48 | end 49 | S: begin 50 | newval.sie = False; 51 | newval.spie = status.sie; 52 | newval.spp = truncate(pack(from)); 53 | end 54 | U: begin 55 | newval.uie = False; 56 | newval.upie = status.uie; 57 | end 58 | default: noAction; 59 | endcase 60 | status <= newval; 61 | endaction; 62 | // Global Interrupt-Enable and Privilege stack pop 63 | function ActionValue#(PrivLvl) popStatusStack(CSR_Ifc#(Status) status, PrivLvl from) = actionvalue 64 | Status newval = status; 65 | PrivLvl to = from; 66 | case (from) 67 | M: begin 68 | newval.mie = newval.mpie; 69 | to = unpack(newval.mpp); 70 | newval.mpie = True; 71 | newval.mpp = (static_HAS_U_MODE) ? pack(U) : pack(M); 72 | end 73 | S: begin 74 | newval.sie = newval.spie; 75 | to = unpack({1'b0, newval.spp}); 76 | newval.spie = True; 77 | newval.spp = (static_HAS_U_MODE) ? truncate(pack(U)): truncate(pack(M)); // XXX check spec here... Shouldn't it be "lowest supported priv mode" rather than "U if supported, M otherwise"? 78 | end 79 | U: newval.uie = newval.upie; // (and stay in U-mode) 80 | default: noAction; 81 | endcase 82 | status <= newval; 83 | return to; 84 | endactionvalue; 85 | 86 | function Action general_trap(RVState s, PrivLvl toLvl, TrapCode trapCode, VAddr epc 87 | `ifdef RVXCHERI 88 | , Tuple2#(Bit#(6), CapExcCode) capCause, CapType epcc 89 | `endif 90 | ) = action 91 | // Global Interrupt-Enable Stack and latch current privilege level 92 | pushStatusStack(s.csrs.mstatus, s.currentPrivLvl, toLvl); 93 | // others 94 | case (toLvl) 95 | M: begin 96 | s.csrs.mcause <= trapCode; 97 | s.csrs.mepc.addr <= truncateLSB(epc); 98 | `ifdef RVXCHERI 99 | //XXX TODO Handle ccsr cause field 100 | s.mepcc <= epcc; 101 | `endif 102 | end 103 | `ifdef SUPERVISOR_MODE 104 | S: begin 105 | s.csrs.scause <= trapCode; 106 | s.csrs.sepc.addr <= truncateLSB(epc); 107 | end 108 | `endif 109 | `ifdef RVN 110 | U: begin 111 | // TODO s.csrs.ucause <= trapCode; 112 | // TODO s.csrs.uepc.addr <= truncateLSB(epc); 113 | end 114 | `endif 115 | default: terminateSim(s, $format("TRAP INTO UNKNOWN PRIVILEGE MODE ", fshow(s.currentPrivLvl))); 116 | endcase 117 | s.currentPrivLvl <= M; 118 | endaction; 119 | 120 | function Action raiseIFetchException(RVState s, ExcCode code) = action 121 | s.pendingIFetchException[1] <= Valid(code); 122 | endaction; 123 | 124 | typeclass RaiseException#(type a); a raiseException; endtypeclass 125 | 126 | instance RaiseException#(function Action f(RVState s, ExcCode code)); 127 | function Action raiseException(RVState s, ExcCode code) = action 128 | s.pendingException[0] <= Valid(tuple2(code, Invalid)); 129 | endaction; 130 | endinstance 131 | 132 | instance RaiseException#(function Action f(RVState s, ExcCode code, Bit#(XLEN) tval)); 133 | function Action raiseException(RVState s, ExcCode code, Bit#(XLEN) tval) = action 134 | s.pendingException[0] <= Valid(tuple2(code, Valid(tval))); 135 | endaction; 136 | endinstance 137 | 138 | function Action raiseMemException(RVState s, ExcCode code, Bit#(XLEN) tval) = action 139 | s.pendingMemException[0] <= Valid(tuple2(code, tval)); 140 | endaction; 141 | 142 | `ifdef RVXCHERI 143 | import CHERICap :: *; 144 | 145 | typeclass RaiseCapException#(type a); a raiseCapException; endtypeclass 146 | 147 | instance RaiseCapException#(function Action f(RVState s, CapExcCode exc, Bit#(6) idx)); 148 | function raiseCapException(s, exc, idx) = action 149 | s.pendingCapException[0] <= Valid(tuple2(idx, exc)); 150 | raiseException(s, CHERIFault); 151 | endaction; 152 | endinstance 153 | 154 | instance RaiseCapException#(function Action f(RVState s, CapExcCode exc, Bit#(5) idx)); 155 | function raiseCapException(s, exc, idx) = raiseCapException(s, exc, {1'b0, idx}); 156 | endinstance 157 | 158 | typeclass RaiseMemCapException#(type a); a raiseMemCapException; endtypeclass 159 | 160 | instance RaiseMemCapException#(function Action f(RVState s, CapExcCode exc, Bit#(6) idx)); 161 | function raiseMemCapException(s, exc, idx) = action 162 | s.pendingMemCapException[0] <= Valid(tuple2(idx, exc)); 163 | raiseMemException(s, CHERIFault, (msb(idx) == 1) ? 0 : getAddr(s.rCR(truncate(idx)))); // TODO update the address to look into special cap regs 164 | endaction; 165 | endinstance 166 | 167 | instance RaiseMemCapException#(function Action f(RVState s, CapExcCode exc, Bit#(5) idx)); 168 | function raiseMemCapException(s, exc, idx) = raiseMemCapException(s, exc, {1'b0, idx}); 169 | endinstance 170 | 171 | instance RaiseMemCapException#(function Recipe f(a x, b y, c z)) provisos (RaiseMemCapException#(function Action g(a x, b y, c z))); 172 | function raiseMemCapException(x, y, z) = rAct(raiseMemCapException(x, y, z)); 173 | endinstance 174 | 175 | typeclass RaiseIFetchCapException#(type a); a raiseIFetchCapException; endtypeclass 176 | 177 | instance RaiseIFetchCapException#(function Action f(RVState s, CapExcCode exc)); 178 | function raiseIFetchCapException(s, exc) = action 179 | s.pendingIFetchCapException[1] <= Valid(tuple2(0, exc)); 180 | raiseIFetchException(s, CHERIFault); 181 | endaction; 182 | endinstance 183 | 184 | instance RaiseIFetchCapException#(function Recipe f(a x, b y)) provisos (RaiseIFetchCapException#(function Action g(a x, b y))); 185 | function raiseIFetchCapException(x, y) = rAct(raiseIFetchCapException(x, y)); 186 | endinstance 187 | `endif 188 | 189 | function Action raiseMemTokException(RVState s, ExcToken excToken) = action 190 | `ifdef RVXCHERI 191 | if (excToken.excCode == CHERIFault) 192 | raiseMemCapException(s, excToken.capExcCode, excToken.capIdx); 193 | else 194 | `endif 195 | raiseMemException(s, excToken.excCode, excToken.tval); 196 | endaction; 197 | 198 | function Action raiseIFetchTokException(RVState s, ExcToken excToken) = action 199 | `ifdef RVXCHERI 200 | if (excToken.excCode == CHERIFault) 201 | raiseIFetchCapException(s, excToken.capExcCode); 202 | else 203 | `endif 204 | raiseIFetchException(s, excToken.excCode); 205 | endaction; 206 | 207 | function Maybe#(IntCode) checkIRQ (RVState s); 208 | Bool lvl_ie = case (s.currentPrivLvl) 209 | M: s.csrs.mstatus.mie; 210 | S: s.csrs.mstatus.sie; 211 | U: s.csrs.mstatus.uie; 212 | default: True; 213 | endcase; 214 | Maybe#(IntCode) intCode = Invalid; 215 | if (lvl_ie) begin 216 | // order: MEI, MSI, MTI, SEI, SSI, STI, UEI, USI, UTI 217 | if (s.csrs.mip.meip && s.csrs.mie.meie) intCode = Valid(MExtInt); 218 | else if (s.csrs.mip.msip && s.csrs.mie.msie) intCode = Valid(MSoftInt); 219 | else if (s.csrs.mip.mtip && s.csrs.mie.mtie) intCode = Valid(MTimerInt); 220 | else if (s.csrs.mip.seip && s.csrs.mie.seie) intCode = Valid(SExtInt); 221 | else if (s.csrs.mip.ssip && s.csrs.mie.ssie) intCode = Valid(SSoftInt); 222 | else if (s.csrs.mip.stip && s.csrs.mie.stie) intCode = Valid(STimerInt); 223 | else if (s.csrs.mip.ueip && s.csrs.mie.ueie) intCode = Valid(UExtInt); 224 | else if (s.csrs.mip.usip && s.csrs.mie.usie) intCode = Valid(USoftInt); 225 | else if (s.csrs.mip.utip && s.csrs.mie.utie) intCode = Valid(UTimerInt); 226 | end 227 | return intCode; 228 | endfunction 229 | 230 | function Action assignM (Reg#(a) r, ActionValue#(a) av) = 231 | action a tmp <- av; r <= tmp; endaction; 232 | 233 | module [ISADefModule] mkRVTrap#(RVState s) (); 234 | /* 235 | I-type 236 | 237 | 31 20 19 15 14 12 11 7 6 0 238 | +-------------------------------------+--------+--------+--------+----------+ 239 | | funct12 | rs1 | funct3 | rd | opcode | 240 | +-------------------------------------+--------+--------+--------+----------+ 241 | */ 242 | 243 | // funct12 = MRET = 001100000010 244 | // rs1 = 00000 245 | // funct3 = PRIV = 000 246 | // rd = 00000 247 | // opcode = SYSTEM = 1110011 248 | function Action instrMRET () = action 249 | if (s.currentPrivLvl < M) begin 250 | raiseException(s, IllegalInst); 251 | logInst(s, $format("mret")); 252 | end else begin 253 | PrivLvl toLvl <- popStatusStack(s.csrs.mstatus, M); 254 | s.currentPrivLvl <= toLvl; 255 | let tgt = pack(s.csrs.mepc); 256 | `ifdef RVXCHERI 257 | s.pcc <= s.mepcc; 258 | tgt = getOffset(s.mepcc); 259 | `endif 260 | s.pc <= tgt; 261 | logInst(s, $format("mret"), fshow(s.currentPrivLvl) + $format(" -> ") + fshow(toLvl)); 262 | end 263 | endaction; 264 | defineInstEntry("mret", pat(n(12'b001100000010), n(5'b00000), n(3'b000), n(5'b00000), n(7'b1110011)), instrMRET); 265 | 266 | `ifdef SUPERVISOR_MODE 267 | // funct12 = SRET = 000100000010 268 | // rs1 = 00000 269 | // funct3 = PRIV = 000 270 | // rd = 00000 271 | // opcode = SYSTEM = 1110011 272 | function Action instrSRET () = action 273 | if (s.currentPrivLvl < S || (s.currentPrivLvl == S && s.csrs.mstatus.tsr)) begin 274 | raiseException(s, IllegalInst); 275 | logInst(s, $format("sret")); 276 | end else begin 277 | PrivLvl toLvl <- popStatusStack(s.csrs.mstatus, S); 278 | s.currentPrivLvl <= toLvl; 279 | let tgt = pack(s.csrs.sepc); 280 | `ifdef RVXCHERI 281 | s.pcc <= s.sepcc; 282 | tgt = getOffset(s.sepcc); 283 | `endif 284 | s.pc <= tgt; 285 | logInst(s, $format("sret"), fshow(s.currentPrivLvl) + $format(" -> ") + fshow(toLvl)); 286 | end 287 | endaction; 288 | defineInstEntry("sret", pat(n(12'b000100000010), n(5'b00000), n(3'b000), n(5'b00000), n(7'b1110011)), instrSRET); 289 | `endif 290 | 291 | `ifdef USER_MODE 292 | //XXX TODO N extension... 293 | // funct12 = URET = 000000000010 294 | // rs1 = 00000 295 | // funct3 = PRIV = 000 296 | // rd = 00000 297 | // opcode = SYSTEM = 1110011 298 | function Action instrURET () = action 299 | if (s.currentPrivLvl < U || !static_HAS_N_EXT) raiseException(s, IllegalInst); 300 | else assignM(s.currentPrivLvl, popStatusStack(s.csrs.mstatus, U)); 301 | // trace 302 | logInst(s, $format("uret")); 303 | endaction; 304 | defineInstEntry("uret", pat(n(12'b000000000010), n(5'b00000), n(3'b000), n(5'b00000), n(7'b1110011)), instrURET); 305 | `endif 306 | 307 | // funct12 = WFI = 000100000101 308 | // rs1 = 00000 309 | // funct3 = PRIV = 000 310 | // rd = 00000 311 | // opcode = SYSTEM = 1110011 312 | function Action instrWFI () = action 313 | Bool limit_reached = True; 314 | case (s.currentPrivLvl) matches 315 | U &&& (!static_HAS_N_EXT): action raiseException(s, IllegalInst); endaction 316 | S &&& (s.csrs.mstatus.tw && limit_reached): action raiseException(s, IllegalInst); endaction 317 | default: noAction; 318 | endcase 319 | logInst(s, $format("wfi"), $format("IMPLEMENTED AS NOP")); 320 | endaction; 321 | defineInstEntry("wfi", pat(n(12'b000100000101), n(5'b00000), n(3'b000), n(5'b00000), n(7'b1110011)), instrWFI); 322 | 323 | // general functionalities 324 | ////////////////////////////////////////////////////////////////////////////// 325 | Maybe#(IntCode) irqCode = checkIRQ(s); 326 | Bool isTrap = isValid(s.pendingIFetchException[2]) || 327 | isValid(s.pendingException[1]) || 328 | isValid(s.pendingMemException[1]) || 329 | isValid(irqCode); 330 | defineInterEntry(Guarded { guard: isTrap, val: action 331 | // general info 332 | let isIFetchException = isValid(s.pendingIFetchException[0]); 333 | let isStdException = isValid(s.pendingException[0]); 334 | let isMemException = isValid(s.pendingMemException[0]); 335 | let isException = isStdException || isMemException; 336 | let ifetchexc = s.pendingIFetchException[0].Valid; 337 | match {.exc, .maybe_tval} = s.pendingException[0].Valid; 338 | match {.memexc, .memexc_tval} = s.pendingMemException[0].Valid; 339 | TrapCode code = Interrupt(irqCode.Valid); 340 | `ifdef RVXCHERI 341 | Tuple2#(Bit#(6), CapExcCode) capExc = tuple2(0, CapExcNone); 342 | `endif 343 | if (isIFetchException) begin 344 | code = Exception(ifetchexc); 345 | `ifdef RVXCHERI 346 | capExc = fromMaybe(capExc, s.pendingIFetchCapException[0]); 347 | `endif 348 | end else if (isStdException) begin 349 | code = Exception(exc); 350 | `ifdef RVXCHERI 351 | capExc = fromMaybe(capExc, s.pendingCapException[0]); 352 | `endif 353 | end else if (isMemException) begin 354 | code = Exception(memexc); 355 | `ifdef RVXCHERI 356 | capExc = fromMaybe(capExc, s.pendingMemCapException[0]); 357 | `endif 358 | end 359 | // handle general trap behaviour 360 | let epc = s.pc; 361 | if (code matches tagged Interrupt ._) epc = s.pc.late; 362 | `ifdef RVXCHERI 363 | let epcc = s.pcc; 364 | if (code matches tagged Interrupt ._) epcc = s.pcc.late; 365 | // XXX assert that the setOffset is safe 366 | epcc = setOffset(epcc, epc); 367 | `endif 368 | general_trap(s, M, code, epc 369 | `ifdef RVXCHERI 370 | , capExc, epcc.value 371 | `endif 372 | ); 373 | // potential tval latching 374 | let new_mtval = 0; 375 | if (isStdException && isValid(maybe_tval)) new_mtval = maybe_tval.Valid; 376 | else if (isMemException) new_mtval = memexc_tval; 377 | s.csrs.mtval <= new_mtval; 378 | // handle pc update 379 | Bit#(XLEN) tgt = {s.csrs.mtvec.base, 2'b00}; 380 | TVecMode mode = s.csrs.mtvec.mode; 381 | `ifdef RVXCHERI 382 | asReg(s.pcc.late) <= s.mtcc; 383 | TVec tmp = unpack(getOffset(s.mtcc)); 384 | tgt = {tmp.base, 2'b00}; 385 | mode = tmp.mode; 386 | `endif 387 | case (mode) matches 388 | Direct: tgt = tgt; 389 | Vectored &&& isException: tgt = tgt; 390 | Vectored &&& (!isException): tgt = tgt + zeroExtend({pack(irqCode.Valid),2'b00}); 391 | default: terminateSim(s, $format("TRAP WITH UNKNOWN MODE ", fshow(mode))); 392 | endcase 393 | asReg(s.pc.late) <= tgt; 394 | // prepare trace message 395 | Fmt msg = $format(">>> TRAP <<< -- mcause <= ", fshow(code), ", mepc <= 0x%0x, mtval <= 0x%0x, pc <= 0x%0x", s.pc, new_mtval, tgt); 396 | `ifdef RVXCHERI 397 | msg = $format(msg, ", pcc <= ", showCHERICap(s.mtcc)); 398 | if (code matches tagged Exception .c &&& c == CHERIFault) begin 399 | msg = $format(msg, ", CHERI fault idx: %0d, CHERI fault: ", tpl_1(capExc), showCapCause(tpl_2(capExc))); 400 | end 401 | `endif 402 | // reset transient state 403 | s.pendingIFetchException[0] <= Invalid; 404 | s.pendingException[0] <= Invalid; 405 | s.pendingMemException[0] <= Invalid; 406 | `ifdef RVXCHERI 407 | s.pendingIFetchCapException[0] <= Invalid; 408 | s.pendingCapException[0] <= Invalid; 409 | s.pendingMemCapException[0] <= Invalid; 410 | `endif 411 | `ifdef RVFI_DII 412 | s.exc_tgt[0] <= Valid(tgt); 413 | `endif 414 | // tracing 415 | printTLogPlusArgs("itrace", msg); 416 | endaction}); 417 | 418 | endmodule 419 | --------------------------------------------------------------------------------