Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
Hydra - a radiation-tolerant SoC
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Projects
Hydra - a radiation-tolerant SoC
Commits
645cf505
Commit
645cf505
authored
2 years ago
by
Tristan Gingold
Browse files
Options
Downloads
Patches
Plain Diff
Add lock-step mode
parent
fb094809
Branches
Branches containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
hdl/rtl/hydra_core.vhd
+69
-32
69 additions, 32 deletions
hdl/rtl/hydra_core.vhd
hdl/rtl/hydra_triple_cpu.vhd
+58
-23
58 additions, 23 deletions
hdl/rtl/hydra_triple_cpu.vhd
sw/sf2-test/main.c
+43
-13
43 additions, 13 deletions
sw/sf2-test/main.c
with
170 additions
and
68 deletions
hdl/rtl/hydra_core.vhd
+
69
−
32
View file @
645cf505
...
...
@@ -83,15 +83,16 @@ architecture arch of hydra_core is
return
x
;
end
function
f_x_to_zero
;
signal
cpu_rst
:
std_logic
;
signal
cpu_rst
:
std_logic
_vector
(
1
to
3
)
;
signal
cpu_rst_err
:
std_logic
;
signal
cpu_sync
:
std_logic_vector
(
1
to
3
);
signal
im_addr
:
std_logic_vector
(
31
downto
0
);
signal
im_data
,
im1_data
:
std_logic_vector
(
31
downto
0
);
signal
im_rd
,
im_valid
:
std_logic
;
signal
im1_done
,
im1_dm_en
,
im1_err
:
std_logic
;
signal
im2_err
,
im2_valid
:
std_logic
;
signal
err_cpu
:
std_logic
;
signal
err_cpu
_dm
:
std_logic
;
signal
dm_addr
,
dm_data_s
,
dm_data_l
:
std_logic_vector
(
31
downto
0
);
signal
dm_data_select
:
std_logic_vector
(
3
downto
0
);
...
...
@@ -121,6 +122,8 @@ architecture arch of hydra_core is
signal
nbr_dram_ecc_uncorr
:
std_logic_vector
(
31
downto
0
);
signal
iram_ecc_err
,
iram_ecc_fatal
:
std_logic
;
signal
dram_ecc_err
,
dram_ecc_fatal
:
std_logic
;
signal
nbr_cpu_data_err
:
std_logic_vector
(
31
downto
0
);
signal
nbr_cpu_iaddr_err
:
std_logic_vector
(
31
downto
0
);
signal
reset_cause_cpu
,
reset_cause_ecc
,
reset_cause_wd
:
std_logic
;
signal
dram_scrub_period
,
iram_scrub_period
:
std_logic_vector
(
15
downto
0
);
...
...
@@ -129,15 +132,19 @@ architecture arch of hydra_core is
signal
wd_period_wr
,
wd_key_wr
,
wd_timeout
:
std_logic
;
signal
force_divergence
,
force_divergence_d
,
dm_force_divergence
:
std_logic
;
begin
cpu_rst
<=
cpu_rst_err
or
(
not
cpu_rst_n_i
);
signal
cpu_wr
:
std_logic
;
type
t_state
is
(
S_VOTER
,
S_LOCK
);
signal
state
:
t_state
;
signal
cpu_recovery
,
cpu_recovery_in
:
std_logic
;
begin
dwb_o
<=
dwb_out
;
U_cpu_core
:
entity
work
.
hydra_triple_cpu
inst_cpus
:
entity
work
.
hydra_triple_cpu
port
map
(
clk_i
=>
clk_sys_i
,
rst_i
=>
cpu_rst
,
cpu_
rst_i
=>
cpu_rst
,
im_addr_o
=>
im_addr
,
im_rd_o
=>
im_rd
,
im_data_i
=>
im_data
,
...
...
@@ -151,8 +158,9 @@ begin
dm_load_done_i
=>
dm_load_done
,
dm_store_done_i
=>
dm_store_done
,
cpu_sync_o
=>
cpu_sync
,
dm_force_divergence_i
=>
dm_force_divergence
,
err_cpu_
o
=>
err_cpu
);
err_cpu_
dm_o
=>
err_cpu
_dm
);
-- Add registers on uRV data bus
process
(
clk_sys_i
)
...
...
@@ -170,7 +178,6 @@ begin
end
if
;
end
process
;
inst_iram
:
entity
work
.
hydra_iram
generic
map
(
g_RAM_LOG_SIZE
=>
g_IRAM_LOG_SIZE
,
...
...
@@ -416,7 +423,7 @@ begin
-- Timeout
wd_timeout
<=
'1'
;
wd_counter
<=
wd_period
;
elsif
cpu_rst
=
'1'
or
(
wd_key_wr
=
'1'
and
wd_key_val
=
x"c0423bc9"
)
then
elsif
cpu_rst
=
"111"
or
(
wd_key_wr
=
'1'
and
wd_key_val
=
x"c0423bc9"
)
then
-- Key -> reload
-- Also restart the watchdog if the cpu is reset.
wd_counter
<=
wd_period
;
...
...
@@ -429,27 +436,8 @@ begin
end
if
;
end
process
;
-- Supervisor
p_sv
:
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
then
reset_cause_cpu
<=
'0'
;
reset_cause_ecc
<=
'0'
;
reset_cause_wd
<=
'0'
;
cpu_rst_err
<=
'0'
;
else
cpu_rst_err
<=
'0'
;
if
dram_ecc_fatal
=
'1'
or
iram_ecc_fatal
=
'1'
or
wd_timeout
=
'1'
or
err_cpu
=
'1'
then
-- Reset CPU on error.
cpu_rst_err
<=
'1'
;
reset_cause_cpu
<=
err_cpu
;
reset_cause_ecc
<=
dram_ecc_fatal
or
iram_ecc_fatal
;
reset_cause_wd
<=
wd_timeout
;
end
if
;
end
if
;
end
if
;
end
process
;
-- Any fatal error that should reset cpus
cpu_rst_err
<=
dram_ecc_fatal
or
iram_ecc_fatal
or
wd_timeout
;
inst_sv_regs
:
entity
work
.
hydra_supervisor_regs
port
map
(
...
...
@@ -460,9 +448,11 @@ begin
reset_cause_cpu_i
=>
reset_cause_cpu
,
reset_cause_ecc_i
=>
reset_cause_ecc
,
reset_cause_watchdog_i
=>
reset_cause_wd
,
cpu_status_i
=>
"000"
,
cpu_status_i
=>
cpu_rst
,
cpu_boot_done_i
=>
'0'
,
cpu_recovery_i
=>
'0'
,
cpu_recovery_i
=>
cpu_recovery
,
cpu_recovery_o
=>
cpu_recovery_in
,
cpu_wr_o
=>
cpu_wr
,
force_divergence_i
=>
x"00000000"
,
force_divergence_rd_o
=>
force_divergence
,
wd_period_i
=>
wd_period
,
...
...
@@ -478,4 +468,51 @@ begin
iram_scrub_period_o
=>
iram_scrub_period
,
dram_scrub_period_o
=>
dram_scrub_period
);
process
(
clk_sys_i
)
is
begin
if
rising_edge
(
clk_sys_i
)
then
if
rst_n_i
=
'0'
or
cpu_rst_n_i
=
'0'
then
state
<=
S_VOTER
;
cpu_rst
<=
(
others
=>
'1'
);
cpu_recovery
<=
'0'
;
nbr_cpu_data_err
<=
(
others
=>
'0'
);
nbr_cpu_iaddr_err
<=
(
others
=>
'0'
);
reset_cause_cpu
<=
'0'
;
reset_cause_ecc
<=
'0'
;
reset_cause_wd
<=
'0'
;
else
case
state
is
when
S_VOTER
=>
cpu_rst
<=
"000"
;
-- Software can clear recovery flag.
if
cpu_wr
=
'1'
and
cpu_recovery_in
=
'0'
then
cpu_recovery
<=
'0'
;
end
if
;
if
err_cpu_dm
=
'1'
then
nbr_cpu_data_err
<=
std_logic_vector
(
unsigned
(
nbr_cpu_data_err
)
+
1
);
end
if
;
if
cpu_sync
=
"110"
or
cpu_sync
=
"101"
or
cpu_sync
=
"011"
then
-- Disable the cpu out of sync.
cpu_rst
<=
not
cpu_sync
;
nbr_cpu_iaddr_err
<=
std_logic_vector
(
unsigned
(
nbr_cpu_iaddr_err
)
+
1
);
state
<=
S_LOCK
;
end
if
;
when
S_LOCK
=>
if
cpu_wr
=
'1'
and
cpu_recovery_in
=
'1'
then
cpu_recovery
<=
'1'
;
end
if
;
end
case
;
if
cpu_sync
=
"000"
or
cpu_rst_err
=
'1'
or
(
err_cpu_dm
=
'1'
and
state
=
S_LOCK
)
then
-- Fatal error
cpu_rst
<=
(
others
=>
'1'
);
reset_cause_cpu
<=
not
cpu_rst_err
;
reset_cause_ecc
<=
dram_ecc_fatal
or
iram_ecc_fatal
;
reset_cause_wd
<=
wd_timeout
;
state
<=
S_VOTER
;
end
if
;
end
if
;
end
if
;
end
process
;
end
arch
;
This diff is collapsed.
Click to expand it.
hdl/rtl/hydra_triple_cpu.vhd
+
58
−
23
View file @
645cf505
...
...
@@ -6,7 +6,7 @@ use work.urv_pkg.all;
entity
hydra_triple_cpu
is
port
(
clk_i
:
in
std_logic
;
rst_i
:
in
std_logic
;
cpu_
rst_i
:
in
std_logic
_vector
(
3
downto
1
)
;
im_data_i
:
in
std_logic_vector
(
31
downto
0
);
im_valid_i
:
in
std_logic
;
im_addr_o
:
out
std_logic_vector
(
31
downto
0
);
...
...
@@ -19,25 +19,27 @@ entity hydra_triple_cpu is
dm_data_select_o
:
out
std_logic_vector
(
3
downto
0
);
dm_store_o
:
out
std_logic
;
dm_load_o
:
out
std_logic
;
-- True when a cpu is in sync with at least another one.
-- (ie same outputs on the instruction bus)
cpu_sync_o
:
out
std_logic_vector
(
3
downto
1
);
-- If set, will give different values to each cpu.
dm_force_divergence_i
:
in
std_logic
;
-- Set to 1 if an output differs
err_cpu_o
:
out
std_logic
);
-- Set to 1 if an output differs
on the data bus
err_cpu_
dm_
o
:
out
std_logic
);
end
entity
hydra_triple_cpu
;
architecture
arch
of
hydra_triple_cpu
is
type
t_slv32_x3
is
array
(
1
to
3
)
of
std_logic_vector
(
31
downto
0
);
type
t_slv4_x3
is
array
(
1
to
3
)
of
std_logic_vector
(
3
downto
0
);
subtype
t_sl_x3
is
std_logic_vector
(
1
to
3
);
subtype
t_sl_x3
is
std_logic_vector
(
3
down
to
1
);
signal
im_addr
,
dm_addr
,
dm_data_s
,
dm_data_l
:
t_slv32_x3
;
signal
err_im_addr
,
err_dm_addr
,
err_dm_data_s
:
std_logic
;
signal
dm_data_select
:
t_slv4_x3
;
signal
err_dm_data_select
:
std_logic
;
signal
im_rd
,
dm_store
,
dm_load
:
t_sl_x3
;
signal
err_dm_store
,
err_dm_load
,
err_im_rd
:
std_logic
;
signal
en_im
,
en
_dm_load
,
en
_dm_store
:
std_logic
;
signal
ok_dm_addr
,
ok_dm_data
,
ok_dm_select
,
ok
_dm_load
,
ok
_dm_store
,
ok_dm
:
std_logic
_vector
(
3
downto
1
)
;
begin
gen_triple
:
for
i
in
1
to
3
generate
inst_cpu
:
urv_cpu
...
...
@@ -49,7 +51,7 @@ begin
)
port
map
(
clk_i
=>
clk_i
,
rst_i
=>
rst_i
,
rst_i
=>
cpu_
rst_i
(
i
)
,
irq_i
=>
'0'
,
im_addr_o
=>
im_addr
(
i
),
im_rd_o
=>
im_rd
(
i
),
...
...
@@ -82,7 +84,7 @@ begin
b
=>
im_addr
(
2
),
c
=>
im_addr
(
3
),
res
=>
im_addr_o
,
err
=>
err_im_addr
err
=>
open
);
inst_voter_dm_addr
:
entity
work
.
voter_vec_status
...
...
@@ -94,7 +96,7 @@ begin
b
=>
dm_addr
(
2
),
c
=>
dm_addr
(
3
),
res
=>
dm_addr_o
,
err
=>
err_dm_addr
err
=>
open
);
inst_voter_dm_data_s
:
entity
work
.
voter_vec_status
...
...
@@ -106,7 +108,7 @@ begin
b
=>
dm_data_s
(
2
),
c
=>
dm_data_s
(
3
),
res
=>
dm_data_s_o
,
err
=>
err_dm_data_s
err
=>
open
);
inst_voter_dm_data_select
:
entity
work
.
voter_vec_status
...
...
@@ -118,38 +120,71 @@ begin
b
=>
dm_data_select
(
2
),
c
=>
dm_data_select
(
3
),
res
=>
dm_data_select_o
,
err
=>
err_dm_data_select
err
=>
open
);
inst_voter_im_rd
:
entity
work
.
voter_status
port
map
(
inp
=>
im_rd
,
res
=>
im_rd_o
,
err
=>
err_im_rd
err
=>
open
);
inst_voter_dm_load
:
entity
work
.
voter_status
port
map
(
inp
=>
dm_load
,
res
=>
dm_load_o
,
err
=>
err_dm_load
err
=>
open
);
inst_voter_dm_store
:
entity
work
.
voter_status
port
map
(
inp
=>
dm_store
,
res
=>
dm_store_o
,
err
=>
err_dm_store
err
=>
open
);
dm_data_l
(
1
)
<=
dm_data_l_i
when
dm_force_divergence_i
=
'0'
else
x"0000_0001"
;
dm_data_l
(
2
)
<=
dm_data_l_i
when
dm_force_divergence_i
=
'0'
else
x"0000_0002"
;
dm_data_l
(
3
)
<=
dm_data_l_i
when
dm_force_divergence_i
=
'0'
else
x"0000_0004"
;
en_im
<=
im_rd
(
1
)
or
im_rd
(
2
)
or
im_rd
(
3
);
en_dm_load
<=
dm_load
(
1
)
or
dm_load
(
2
)
or
dm_load
(
3
);
en_dm_store
<=
dm_store
(
1
)
or
dm_store
(
2
)
or
dm_store
(
3
);
err_cpu_o
<=
(
en_im
and
err_im_addr
)
or
err_im_rd
or
((
en_dm_load
or
en_dm_store
)
and
err_dm_addr
)
or
(
en_dm_store
and
(
err_dm_data_s
or
err_dm_data_select
))
or
err_dm_load
or
err_dm_store
;
gen_s
:
for
i
in
0
to
2
generate
constant
n0
:
natural
:
=
1
+
i
;
constant
n1
:
natural
:
=
1
+
(
i
+
1
)
mod
3
;
constant
n2
:
natural
:
=
1
+
(
i
+
2
)
mod
3
;
begin
cpu_sync_o
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
im_rd
(
n0
)
=
'0'
and
(
im_rd
(
n1
)
=
'0'
or
im_rd
(
n2
)
=
'0'
))
or
(
im_rd
(
n0
)
=
'1'
and
((
im_rd
(
n1
)
=
'1'
and
im_addr
(
n1
)
=
im_addr
(
n0
))
or
(
im_rd
(
n2
)
=
'1'
and
im_addr
(
n2
)
=
im_addr
(
n0
))))
else
'0'
;
ok_dm_addr
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
dm_load
(
n0
)
=
'0'
and
(
dm_load
(
n1
)
=
'0'
or
dm_load
(
n2
)
=
'0'
))
or
(
dm_store
(
n0
)
=
'0'
and
(
dm_store
(
n1
)
=
'0'
or
dm_store
(
n2
)
=
'0'
))
or
(((
dm_load
(
n0
)
=
'1'
and
dm_load
(
n1
)
=
'1'
)
or
(
dm_store
(
n0
)
=
'1'
and
dm_store
(
n1
)
=
'1'
))
and
dm_addr
(
n0
)
=
dm_addr
(
n1
))
or
(((
dm_load
(
n0
)
=
'1'
and
dm_load
(
n2
)
=
'1'
)
or
(
dm_store
(
n0
)
=
'1'
and
dm_store
(
n2
)
=
'1'
))
and
dm_addr
(
n0
)
=
dm_addr
(
n2
))
else
'0'
;
ok_dm_data
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
dm_store
(
n0
)
=
'0'
and
(
dm_store
(
n1
)
=
'0'
or
dm_store
(
n2
)
=
'0'
))
or
((
dm_store
(
n0
)
=
'1'
and
dm_store
(
n1
)
=
'1'
)
and
dm_data_s
(
n0
)
=
dm_data_s
(
n1
))
or
((
dm_store
(
n0
)
=
'1'
and
dm_store
(
n2
)
=
'1'
)
and
dm_data_s
(
n0
)
=
dm_data_s
(
n2
))
else
'0'
;
ok_dm_select
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
dm_store
(
n0
)
=
'0'
and
(
dm_store
(
n1
)
=
'0'
or
dm_store
(
n2
)
=
'0'
))
or
((
dm_store
(
n0
)
=
'1'
and
dm_store
(
n1
)
=
'1'
)
and
dm_data_select
(
n0
)
=
dm_data_select
(
n1
))
or
((
dm_store
(
n0
)
=
'1'
and
dm_store
(
n2
)
=
'1'
)
and
dm_data_select
(
n0
)
=
dm_data_select
(
n2
))
else
'0'
;
ok_dm_store
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
dm_store
(
n0
)
=
dm_store
(
n1
))
or
(
dm_store
(
n0
)
=
dm_store
(
n2
))
else
'0'
;
ok_dm_load
(
n0
)
<=
'1'
when
cpu_rst_i
(
n0
)
=
'1'
or
(
dm_load
(
n0
)
=
dm_load
(
n1
))
or
(
dm_load
(
n0
)
=
dm_load
(
n2
))
else
'0'
;
ok_dm
(
n0
)
<=
ok_dm_addr
(
n0
)
and
ok_dm_data
(
n0
)
and
ok_dm_select
(
n0
)
and
ok_dm_store
(
n0
)
and
ok_dm_load
(
n0
);
end
generate
;
err_cpu_dm_o
<=
'1'
when
ok_dm
/=
"111"
else
'0'
;
end
arch
;
This diff is collapsed.
Click to expand it.
sw/sf2-test/main.c
+
43
−
13
View file @
645cf505
...
...
@@ -14,6 +14,29 @@
#define SUPERVISOR ((volatile struct hydra_supervisor_regs *)SUPERVISOR_BASE)
#define WD_KEY 0xc0423bc9
static
enum
t_test
{
TEST_WD
,
TEST_CPU0_ERR
}
cur_test
;
static
void
uart_init
(
void
)
{
/* Unreset UART 0 */
*
(
volatile
unsigned
*
)
SYS_RESET
&=
0xffffff7f
;
/* Select baud. */
*
(
volatile
unsigned
*
)
UART_LCR
=
0x80
;
/* Set baudrate */
*
(
volatile
unsigned
*
)
UART_DLR
=
0x36
;
*
(
volatile
unsigned
*
)
UART_DMR
=
0x00
;
/* start operation. */
*
(
volatile
unsigned
*
)
UART_LCR
=
0x03
;
}
static
void
uart_raw_putc
(
unsigned
char
c
)
{
...
...
@@ -88,24 +111,16 @@ ram_test(void)
int
main
(
void
)
{
/* Unreset UART 0 */
*
(
volatile
unsigned
*
)
SYS_RESET
&=
0xffffff7f
;
/* Select baud. */
*
(
volatile
unsigned
*
)
UART_LCR
=
0x80
;
/* Set baudrate */
*
(
volatile
unsigned
*
)
UART_DLR
=
0x36
;
*
(
volatile
unsigned
*
)
UART_DMR
=
0x00
;
/* start operation. */
*
(
volatile
unsigned
*
)
UART_LCR
=
0x03
;
uart_init
();
uart_puts
(
"Rst: "
);
unsigned
v
=
SUPERVISOR
->
reset_cause
;
uart_put_hex_digit
(
v
&
0x0f
);
uart_putc
(
'\n'
);
/* On the first reset, v=0 (no cause), so watchdog won't be restarted
and will expire during ram test.
On later reset, there is always a reset cause. */
if
(
v
)
SUPERVISOR
->
wd_key
=
WD_KEY
;
...
...
@@ -115,7 +130,22 @@ main (void)
uart_puts
(
"Error
\n
"
);
}
/* Read a different value. */
/* Read a different value.
This will trigger a vote and a data error increment. */
v
=
SUPERVISOR
->
force_divergence
;
uart_put_hex_digit
(
v
&
0x0f
);
/* Force divergence by executing different code. */
v
=
SUPERVISOR
->
force_divergence
;
if
(
v
!=
1
)
uart_putc
(
'D'
);
/* Must be in lock-step. */
v
=
SUPERVISOR
->
cpu
;
uart_put_hex_digit
(
v
&
0x0f
);
/* Force a data error in lock-step.
This will generate a reset. */
v
=
SUPERVISOR
->
force_divergence
;
uart_put_hex_digit
(
v
&
0x0f
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment