Skip to content

Commit d3195ef

Browse files
committed
hw: add wfi trampoline bootrom
1 parent 7d59aab commit d3195ef

File tree

11 files changed

+123
-12
lines changed

11 files changed

+123
-12
lines changed

.github/scripts/check_sim.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
LOG_FILE=$1
99

1010
expected_lines=(
11-
"\[CORE\] Start fetching instructions"
11+
"\[CORE\] Waking core via CLINT msip"
1212
"\[JTAG\] Halting hart 0"
1313
"\[JTAG\] Resumed hart 0"
1414
"\[UART\] Hello World!"

Bender.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ sources:
3939
files:
4040
# Level 1
4141
- rtl/core_wrap.sv
42+
- rtl/bootrom/bootrom.sv
4243
- rtl/soc_ctrl/soc_ctrl_regs.sv
4344
- rtl/gpio/gpio_reg_top.sv
4445
- rtl/gpio/gpio.sv

rtl/bootrom/bootrom.sv

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2024 ETH Zurich and University of Bologna.
2+
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
// SPDX-License-Identifier: SHL-0.51
4+
//
5+
// Authors:
6+
// - Philippe Sauter <phsauter@iis.ee.ethz.ch>
7+
8+
`include "common_cells/registers.svh"
9+
10+
/// Bootrom containing a WFI trampoline.
11+
/// After reset the core fetches from here, enables the M-mode interrupt
12+
/// executes WFI, and waits until woken by CLINT msip.
13+
/// On wake it clears msip, reads the boot address from soc_ctrl and jumps there.
14+
module bootrom #(
15+
/// The OBI configuration for all ports.
16+
parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig,
17+
/// OBI request type
18+
parameter type obi_req_t = logic,
19+
/// OBI response type
20+
parameter type obi_rsp_t = logic
21+
) (
22+
input logic clk_i,
23+
input logic rst_ni,
24+
input obi_req_t obi_req_i,
25+
output obi_rsp_t obi_rsp_o
26+
);
27+
28+
// Bootrom contents (9 words, 36 bytes)
29+
// https://godbolt.org/z/MP5ejvzdf
30+
localparam int unsigned RomSize = 9;
31+
localparam logic [31:0] RomData [RomSize] = '{
32+
32'h00800293, // addi t0, zero, 8 # t0 = 8 (MSIE bit)
33+
32'h30429073, // csrw mie, t0 # Enable M-mode software interrupt
34+
32'h10500073, // wfi # Sleep until interrupt
35+
32'h020402b7, // lui t0, 0x02040 # t0 = CLINT base (0x02040000)
36+
32'h0002a023, // sw zero, 0(t0) # Clear msip
37+
32'h30401073, // csrw mie, zero # Disable interrupts
38+
32'h030002b7, // lui t0, 0x03000 # t0 = SOC_CTRL base (0x03000000)
39+
32'h0002a283, // lw t0, 0(t0) # t0 = boot address
40+
32'h00028067 // jalr zero, 0(t0) # Jump to boot address
41+
};
42+
43+
localparam int unsigned AddressWidth = cf_math_pkg::idx_width(RomSize) +2; // in bytes
44+
45+
// Handle OBI requests
46+
logic we_d, we_q; // delayed to the response phase
47+
logic req_d, req_q; // delayed to the response phase
48+
logic [ObiCfg.IdWidth-1:0] id_d, id_q; // delayed to the response phase
49+
logic [AddressWidth-1:0] read_addr_d, read_addr_q; // delayed to the response phase (word addr)
50+
51+
assign req_d = obi_req_i.req;
52+
assign we_d = obi_req_i.a.we;
53+
assign id_d = obi_req_i.a.aid;
54+
assign read_addr_d = obi_req_i.a.addr[AddressWidth-1:2];
55+
56+
// Latch request for one-cycle response
57+
`FF(req_q, req_d, '0, clk_i, rst_ni)
58+
`FF(we_q, we_d, '0, clk_i, rst_ni)
59+
`FF(id_q, id_d, '0, clk_i, rst_ni)
60+
`FF(read_addr_q, read_addr_d, '0, clk_i, rst_ni)
61+
62+
// Address range check
63+
logic in_range;
64+
assign in_range = (read_addr_q < RomSize);
65+
66+
always_comb begin
67+
obi_rsp_o = '0;
68+
obi_rsp_o.gnt = 1'b1; // always grant
69+
obi_rsp_o.rvalid = req_q;
70+
obi_rsp_o.r.rid = id_q;
71+
if (we_q || !in_range) begin
72+
// write request or out of range
73+
obi_rsp_o.r.rdata = 32'hBADCAB1E;
74+
obi_rsp_o.r.err = 1'b1;
75+
end else begin
76+
obi_rsp_o.r.rdata = RomData[read_addr_q];
77+
obi_rsp_o.r.err = 1'b0;
78+
end
79+
end
80+
81+
endmodule

rtl/croc_domain.sv

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ module croc_domain import croc_pkg::*; #(
5050
logic sram_impl; // soc_ctrl -> SRAM config signals
5151
logic debug_req;
5252
logic fetch_enable;
53-
logic [31:0] boot_addr;
5453

5554
// interrupts (irqs)
5655
logic clint_timer_irq;
@@ -162,6 +161,10 @@ module croc_domain import croc_pkg::*; #(
162161
// CLINT bus
163162
sbr_obi_req_t clint_obi_req;
164163
sbr_obi_rsp_t clint_obi_rsp;
164+
165+
// Bootrom bus
166+
sbr_obi_req_t bootrom_obi_req;
167+
sbr_obi_rsp_t bootrom_obi_rsp;
165168

166169
// Fanout to individual peripherals
167170
assign error_obi_req = all_periph_obi_req[PeriphError];
@@ -176,8 +179,10 @@ module croc_domain import croc_pkg::*; #(
176179
assign all_periph_obi_rsp[PeriphGpio] = gpio_obi_rsp;
177180
assign timer_obi_req = all_periph_obi_req[PeriphTimer];
178181
assign all_periph_obi_rsp[PeriphTimer] = timer_obi_rsp;
179-
assign clint_obi_req = all_periph_obi_req[PeriphClint];
180-
assign all_periph_obi_rsp[PeriphClint] = clint_obi_rsp;
182+
assign clint_obi_req = all_periph_obi_req[PeriphClint];
183+
assign all_periph_obi_rsp[PeriphClint] = clint_obi_rsp;
184+
assign bootrom_obi_req = all_periph_obi_req[PeriphBootrom];
185+
assign all_periph_obi_rsp[PeriphBootrom] = bootrom_obi_rsp;
181186

182187

183188
// -----------------
@@ -194,7 +199,7 @@ module croc_domain import croc_pkg::*; #(
194199
.timer_irq_i ( clint_timer_irq ),
195200
.software_irq_i ( clint_software_irq ),
196201

197-
.boot_addr_i ( boot_addr ),
202+
.boot_addr_i ( BootromAddr ),
198203

199204
.instr_req_o ( core_instr_obi_req.req ),
200205
.instr_gnt_i ( core_instr_obi_rsp.gnt ),
@@ -477,7 +482,6 @@ module croc_domain import croc_pkg::*; #(
477482
.rst_ni,
478483
.obi_req_i ( soc_ctrl_obi_req ),
479484
.obi_rsp_o ( soc_ctrl_obi_rsp ),
480-
.boot_addr_o ( boot_addr ),
481485
.fetch_en_o ( fetch_en_reg ),
482486
.sram_dly_o ( sram_impl )
483487
);
@@ -555,6 +559,18 @@ module croc_domain import croc_pkg::*; #(
555559
.overflow_o ( ) // Not connected
556560
);
557561

562+
// Bootrom
563+
bootrom #(
564+
.ObiCfg ( SbrObiCfg ),
565+
.obi_req_t ( sbr_obi_req_t ),
566+
.obi_rsp_t ( sbr_obi_rsp_t )
567+
) i_bootrom (
568+
.clk_i,
569+
.rst_ni,
570+
.obi_req_i ( bootrom_obi_req ),
571+
.obi_rsp_o ( bootrom_obi_rsp )
572+
);
573+
558574
// Peripheral space error subordinate
559575
obi_err_sbr #(
560576
.ObiCfg ( SbrObiCfg ),

rtl/croc_pkg.sv

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,18 @@ package croc_pkg;
108108
PeriphUart = 3,
109109
PeriphGpio = 4,
110110
PeriphTimer = 5,
111-
PeriphClint = 6
111+
PeriphBootrom = 6,
112+
PeriphClint = 7
112113
} periph_outputs_e;
113114

114115
/// Address map given to the peripheral mux
115-
localparam addr_map_rule_t [5:0] periph_addr_map = '{
116+
localparam addr_map_rule_t [6:0] periph_addr_map = '{
116117
'{ idx: PeriphDebug, start_addr: 32'h0000_0000, end_addr: 32'h0004_0000 },
117118
'{ idx: PeriphSocCtrl, start_addr: 32'h0300_0000, end_addr: 32'h0300_1000 },
118119
'{ idx: PeriphUart, start_addr: 32'h0300_2000, end_addr: 32'h0300_3000 },
119120
'{ idx: PeriphGpio, start_addr: 32'h0300_5000, end_addr: 32'h0300_6000 },
120121
'{ idx: PeriphTimer, start_addr: 32'h0300_A000, end_addr: 32'h0300_B000 },
122+
'{ idx: PeriphBootrom, start_addr: 32'h0200_0000, end_addr: 32'h0200_4000 },
121123
'{ idx: PeriphClint, start_addr: 32'h0204_0000, end_addr: 32'h0208_0000 }
122124
};
123125

@@ -137,6 +139,8 @@ package croc_pkg;
137139
return addr;
138140
endfunction
139141

142+
localparam bit [31:0] BootromAddr = get_periph_start_addr(PeriphBootrom);
143+
140144

141145
///////////////////////////////////////////
142146
// Interconnect Types and Configurations //

rtl/soc_ctrl/soc_ctrl_regs.sv

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ module soc_ctrl_regs #(
1515
input obi_req_t obi_req_i,
1616
output obi_rsp_t obi_rsp_o,
1717
// To hardware
18-
output logic [31:0] boot_addr_o,
1918
output logic fetch_en_o,
2019
output logic sram_dly_o
2120
);
@@ -44,7 +43,6 @@ module soc_ctrl_regs #(
4443
assign obi_req_d = obi_req_i;
4544

4645
// Output assignment
47-
assign boot_addr_o = boot_addr_q;
4846
assign fetch_en_o = fetch_en_q;
4947
assign sram_dly_o = sram_dly_q;
5048

rtl/test/tb_croc_pkg.sv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,7 @@ package tb_croc_pkg;
3030
localparam bit [31:0] FetchEnAddr = SocCtrlBaseAddr + soc_ctrl_regs_pkg::SOC_CTRL_FETCHEN_OFFSET;
3131
localparam bit [31:0] CoreStatusAddr = SocCtrlBaseAddr + soc_ctrl_regs_pkg::SOC_CTRL_CORESTATUS_OFFSET;
3232

33+
// CLINT base address (msip register is at offset 0)
34+
localparam bit [31:0] ClintBaseAddr = croc_pkg::get_periph_start_addr(croc_pkg::PeriphClint);
35+
3336
endpackage

rtl/test/tb_croc_soc.sv

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,17 @@ module tb_croc_soc #(
134134

135135
// write test value to sram
136136
i_vip.jtag_write_reg32(SramBaseAddr, 32'h1234_5678, 1'b1);
137-
// load binary to sram
138-
i_vip.jtag_load_hex(binary_path);
139137

140138
$display("@%t | [CORE] Start fetching instructions", $time);
141139
fetch_en = 1'b1;
142140

141+
// load binary to sram
142+
i_vip.jtag_load_hex(binary_path);
143+
144+
// wake core from WFI by writing to CLINT msip
145+
$display("@%t | [CORE] Waking core via CLINT msip", $time);
146+
i_vip.jtag_write_reg32(ClintBaseAddr, 32'h1);
147+
143148
// halt core
144149
i_vip.jtag_halt();
145150

verilator/croc.f

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
../rtl/clint/clint_reg_pkg.sv
157157
../rtl/obi_timer/obi_timer_reg_pkg.sv
158158
../rtl/core_wrap.sv
159+
../rtl/bootrom/bootrom.sv
159160
../rtl/soc_ctrl/soc_ctrl_regs.sv
160161
../rtl/gpio/gpio_reg_top.sv
161162
../rtl/gpio/gpio.sv

vsim/compile_rtl.tcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ if {[catch { vlog -incr -sv \
350350
"+incdir+$ROOT/rtl/common_cells/include" \
351351
"+incdir+$ROOT/rtl/obi/include" \
352352
"$ROOT/rtl/core_wrap.sv" \
353+
"$ROOT/rtl/bootrom/bootrom.sv" \
353354
"$ROOT/rtl/soc_ctrl/soc_ctrl_regs.sv" \
354355
"$ROOT/rtl/gpio/gpio_reg_top.sv" \
355356
"$ROOT/rtl/gpio/gpio.sv" \

0 commit comments

Comments
 (0)