forked from CTSRD-CHERI/Flute
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSoC_Map.bsv
329 lines (256 loc) · 10.3 KB
/
SoC_Map.bsv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
// Copyright (c) 2013-2020 Bluespec, Inc. All Rights Reserved
//-
// RVFI_DII + CHERI modifications:
// Copyright (c) 2018-19 Peter Rugg
// AXI (user fields) modifications:
// Copyright (c) 2019 Alexandre Joannou
// Copyright (c) 2019 Peter Rugg
// Copyright (c) 2019 Jonathan Woodruff
// All rights reserved.
//
// This software was developed by SRI International and the University of
// Cambridge Computer Laboratory (Department of Computer Science and
// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
// DARPA SSITH research programme.
//-
package SoC_Map;
// ================================================================
// This module defines the overall 'address map' of the SoC, showing
// the addresses serviced by each slave IP, and which addresses are
// memory vs. I/O.
// ***** WARNING! WARNING! WARNING! *****
// During system integration, this address map should be identical to
// the system interconnect settings (e.g., routing of requests between
// masters and slaves). This map is also needed by software so that
// it knows how to address various IPs.
// This module contains no state; it just has constants, and so can be
// freely instantiated at multiple places in the SoC module hierarchy
// at no hardware cost. It allows this map to be defined in one
// place and shared across the SoC.
// ================================================================
// Exports
export SoC_Map_IFC (..), mkSoC_Map;
// export fn_addr_in_range;
export Num_Masters;
export imem_master_num;
export dmem_master_num;
export accel0_master_num;
export Num_Slaves;
export Wd_SId;
export boot_rom_slave_num;
export mem0_controller_slave_num;
export uart0_slave_num;
export accel0_slave_num;
export other_peripherals_slave_num;
export N_External_Interrupt_Sources;
export n_external_interrupt_sources;
export irq_num_uart0;
export irq_num_accel0;
// ================================================================
// Bluespec library imports
import Routable :: *; // For Range
// ================================================================
// Project imports
import Fabric_Defs :: *; // Only for type Fabric_Addr
`ifdef ISA_CHERI
import CHERICap :: *;
import CHERICC_Fat :: *;
`endif
`ifdef RVFI_DII
import RVFI_DII :: *;
`endif
import ISA_Decls :: *;
// ================================================================
// Interface and module for the address map
interface SoC_Map_IFC;
(* always_ready *) method Range#(Wd_Addr) m_near_mem_io_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_plic_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_uart0_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_other_peripherals_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_boot_rom_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_mem0_controller_addr_range;
(* always_ready *) method Range#(Wd_Addr) m_tcm_addr_range;
(* always_ready *)
method Bool m_is_mem_addr (Fabric_Addr addr);
(* always_ready *)
method Bool m_is_IO_addr (Fabric_Addr addr);
(* always_ready *)
method Bool m_is_near_mem_IO_addr (Fabric_Addr addr);
(* always_ready *) method Bit #(XLEN) m_pc_reset_value;
(* always_ready *) method Bit #(XLEN) m_mtvec_reset_value;
// Non-maskable interrupt vector
(* always_ready *) method Bit #(XLEN) m_nmivec_reset_value;
`ifdef ISA_CHERI
(* always_ready *) method CapReg m_pcc_reset_value;
(* always_ready *) method CapReg m_ddc_reset_value;
(* always_ready *) method CapReg m_mtcc_reset_value;
(* always_ready *) method CapReg m_mepcc_reset_value;
`endif
endinterface
// ================================================================
(* synthesize *)
module mkSoC_Map (SoC_Map_IFC);
// ----------------------------------------------------------------
// Near_Mem_IO (including CLINT, the core-local interruptor)
let near_mem_io_addr_range = Range {
base: 'h_0200_0000,
size: 'h_0000_C000 // 48K
};
// ----------------------------------------------------------------
// PLIC
let plic_addr_range = Range {
base: 'h0C00_0000,
size: 'h0040_0000 // 4M
};
// ----------------------------------------------------------------
// UART 0
let uart0_addr_range = Range {
base: 'hC000_0000,
size: 'h0000_0080 // 128
};
// ----------------------------------------------------------------
// ACCEL 0
`ifdef INCLUDE_ACCEL0
Fabric_Addr accel0_addr_base = 'hC000_2000;
Fabric_Addr accel0_addr_size = 'h0000_1000; // 4K
Fabric_Addr accel0_addr_lim = accel0_addr_base + accel0_addr_size;
function Bool fn_is_accel0_addr (Fabric_Addr addr);
return ((accel0_addr_base <= addr) && (addr < accel0_addr_lim));
endfunction
`endif
// ----------------------------------------------------------------
// Other peripherals 0 (e.g. to be added in Vivado block design)
let other_peripherals_addr_range = Range {
base: 'hC000_3000,
size: 'h0000_4000
};
// ----------------------------------------------------------------
// Boot ROM
let boot_rom_addr_range = Range {
base: 'h_0000_1000,
size: 'h_0000_1000 // 4K
};
// ----------------------------------------------------------------
// Main Mem Controller 0
let mem0_controller_addr_range = Range {
base: 'h_8000_0000,
size: 'h_4000_0000 // 1 GB
};
// ----------------------------------------------------------------
// Tightly-coupled memory ('TCM'; optional)
`ifdef Near_Mem_TCM
// Integer kB_per_TCM = 'h4; // 4KB
// Integer kB_per_TCM = 'h40; // 64KB
// Integer kB_per_TCM = 'h80; // 128KB
// Integer kB_per_TCM = 'h400; // 1 MB
Integer kB_per_TCM = 'h4000; // 16 MB
`else
Integer kB_per_TCM = 0;
`endif
Integer bytes_per_TCM = kB_per_TCM * 'h400;
let tcm_addr_range = Range {
base: 'h_0000_0000,
size: fromInteger (bytes_per_TCM)
};
`ifdef RVFI_DII
let rvfi_cached = Range {
base: 'h_8000_0000,
size: fromInteger(valueOf(RVFI_DII_Mem_Size))
};
function Bool fn_is_mem_addr (Fabric_Addr addr);
return (inRange(rvfi_cached, addr));
endfunction
function Bool fn_is_IO_addr (Fabric_Addr addr);
return False;
endfunction
`else
// ----------------------------------------------------------------
// Memory address predicate
// Identifies memory addresses in the Fabric.
// (Caches need this information to cache these addresses.)
function Bool fn_is_mem_addr (Fabric_Addr addr);
return ( inRange(boot_rom_addr_range, addr)
|| inRange(mem0_controller_addr_range, addr)
|| inRange(tcm_addr_range, addr)
);
endfunction
// ----------------------------------------------------------------
// I/O address predicate
// Identifies I/O addresses in the Fabric.
// (Caches need this information to avoid cacheing these addresses.)
function Bool fn_is_IO_addr (Fabric_Addr addr);
return ( inRange(near_mem_io_addr_range, addr)
|| inRange(plic_addr_range, addr)
|| inRange(uart0_addr_range, addr)
|| inRange(other_peripherals_addr_range, addr));
endfunction
`endif
// ----------------------------------------------------------------
// PC, MTVEC and NMIVEC reset values
`ifdef RVFI_DII
Bit #(XLEN) pc_reset_value = 'h8000_0000;
Bit #(XLEN) mtvec_reset_value = 'h0000;
`else
Bit #(XLEN) pc_reset_value = rangeBase(boot_rom_addr_range);
Bit #(XLEN) mtvec_reset_value = 'h1000; // TODO
`endif
// Non-maskable interrupt vector
Bit #(XLEN) nmivec_reset_value = ?; // TODO
`ifdef ISA_CHERI
CapPipe almightyPipe = almightyCap;
CapReg pcc_reset_value = cast(setOffset(almightyPipe, pc_reset_value).value);
CapReg ddc_reset_value = almightyCap;
CapReg mtcc_reset_value = cast(setOffset(almightyPipe, mtvec_reset_value).value);
CapReg mepcc_reset_value = almightyCap;
`endif
// ================================================================
// INTERFACE
method Range#(Wd_Addr) m_near_mem_io_addr_range = near_mem_io_addr_range;
method Range#(Wd_Addr) m_plic_addr_range = plic_addr_range;
method Range#(Wd_Addr) m_uart0_addr_range = uart0_addr_range;
method Range#(Wd_Addr) m_other_peripherals_addr_range = other_peripherals_addr_range;
method Range#(Wd_Addr) m_boot_rom_addr_range = boot_rom_addr_range;
method Range#(Wd_Addr) m_mem0_controller_addr_range = mem0_controller_addr_range;
method Range#(Wd_Addr) m_tcm_addr_range = tcm_addr_range;
method Bool m_is_mem_addr (Fabric_Addr addr) = fn_is_mem_addr (addr);
method Bool m_is_IO_addr (Fabric_Addr addr) = fn_is_IO_addr (addr);
method Bool m_is_near_mem_IO_addr (Fabric_Addr addr) = inRange (near_mem_io_addr_range, addr);
method Bit #(XLEN) m_pc_reset_value = pc_reset_value;
method Bit #(XLEN) m_mtvec_reset_value = mtvec_reset_value;
// Non-maskable interrupt vector
method Bit #(XLEN) m_nmivec_reset_value = nmivec_reset_value;
`ifdef ISA_CHERI
method CapReg m_pcc_reset_value = pcc_reset_value;
method CapReg m_ddc_reset_value = ddc_reset_value;
method CapReg m_mtcc_reset_value = mtcc_reset_value;
method CapReg m_mepcc_reset_value = mepcc_reset_value;
`endif
endmodule
Integer imem_master_num = 0;
Integer dmem_master_num = 1;
Integer accel0_master_num = 2;
Integer boot_rom_slave_num = 0;
Integer mem0_controller_slave_num = 1;
Integer uart0_slave_num = 2;
Integer accel0_slave_num = 3;
`ifdef INCLUDE_ACCEL0
typedef 3 Num_Masters;
typedef 5 Num_Slaves;
Integer other_peripherals_slave_num = 4;
`else
typedef 2 Num_Masters;
typedef 4 Num_Slaves;
Integer other_peripherals_slave_num = 3;
`endif
// ================================================================
// Width of fabric 'id' buses
typedef TAdd#(Wd_MId_ext, TLog#(Num_Masters)) Wd_SId;
// ================================================================
// Interrupt request numbers (== index in to vector of
// interrupt-request lines in Core)
typedef 16 N_External_Interrupt_Sources;
Integer n_external_interrupt_sources = valueOf (N_External_Interrupt_Sources);
Integer irq_num_uart0 = 0;
Integer irq_num_accel0 = 1;
// ================================================================
endpackage