Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393_sata
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393_sata
Commits
17e832f8
Commit
17e832f8
authored
Jan 19, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on AHCI FSM code generator
parent
4bf4f348
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
945 additions
and
210 deletions
+945
-210
ahci_ctrl_stat.v
ahci/ahci_ctrl_stat.v
+1
-1
ahci_dma.v
ahci/ahci_dma.v
+33
-7
ahci_dma_wr_fifo.v
ahci/ahci_dma_wr_fifo.v
+3
-1
ahci_fis_receive.v
ahci/ahci_fis_receive.v
+52
-18
ahci_fis_transmit.v
ahci/ahci_fis_transmit.v
+1
-1
ahci_fsm.v
ahci/ahci_fsm.v
+9
-2
ahci_top.v
ahci/ahci_top.v
+32
-7
action_decoder.v
generated/action_decoder.v
+111
-0
condition_mux.v
generated/condition_mux.v
+117
-0
ahci_fsm_sequence.py
helpers/ahci_fsm_sequence.py
+585
-172
link.v
host/link.v
+1
-1
No files found.
ahci/ahci_ctrl_stat.v
View file @
17e832f8
...
...
@@ -124,7 +124,7 @@ module ahci_ctrl_stat #(
input
ssts_det_ndnp
,
// no device detected, phy communication not established
input
ssts_det_dnp
,
// device detected, but phy communication not established
input
ssts_det_dp
,
// device detected, phy communication established
input
ssts_det_offline
,
// device offline
input
ssts_det_offline
,
// device offline
or BIST
output
[
3
:
0
]
ssts_det
,
// current value of PxSSTS.DET
// SCR2:SControl (written by software only)
...
...
ahci/ahci_dma.v
View file @
17e832f8
...
...
@@ -65,11 +65,11 @@ module ahci_dma (
// After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
// not forwarding them to the output
output
prd_done
,
// prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction)
output
prd_irq
,
// prd interrupt, if enabled
output
prd_done
,
//
@mclk
prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction)
input
prd_irq_clear
,
// reset pending prd_irq
output
reg
prd_irq_pend
,
// prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
output
reg
cmd_busy
,
// all commands
output
cmd_done
,
output
cmd_done
,
// @ mclk
// Data System memory -> HBA interface @ mclk
output
[
31
:
0
]
sys_out
,
// 32-bit data from the system memory to HBA (dma data)
...
...
@@ -81,6 +81,8 @@ module ahci_dma (
output
sys_nfull
,
// internal FIFO has room for more data (will decide - how big reserved space to keep)
input
sys_we
,
output
extra_din
,
// all DRDs are transferred to memory, but FIFO has some data. Valid when transfer is stopped
// axi_hp signals write channel
// write address
output
[
31
:
0
]
afi_awaddr
,
...
...
@@ -228,8 +230,10 @@ module ahci_dma (
reg
[
3
:
0
]
dev_rd_id
;
reg
[
5
:
0
]
afi_id
;
// common for 3 channels
assign
prd_done
=
done_dev_wr
||
done_dev_rd
;
assign
prd_irq
=
data_irq
&&
prd_done
;
wire
fifo_nempty_mclk
;
reg
en_extra_din_r
;
// assign prd_done = done_dev_wr || done_dev_rd;
assign
cmd_done_hclk
=
((
ct_busy_r
==
2'b10
)
&&
(
prdtl_mclk
==
0
))
||
done_flush
||
done_dev_rd
;
assign
ct_done
=
(
ct_busy_r
==
2'b10
)
;
assign
first_prd_fetch
=
ct_over_prd_enabled
==
2'b01
;
...
...
@@ -269,7 +273,7 @@ module ahci_dma (
assign
afi_arburst
=
2'h1
;
assign
afi_arqos
=
4'h0
;
assign
afi_rdissuecap1en
=
1'b0
;
assign
extra_din
=
en_extra_din_r
&&
fifo_nempty_mclk
;
always
@
(
posedge
mclk
)
begin
if
(
ct_re
)
ct_data
<=
ct_data_ram
[
ct_addr
]
;
if
(
ctba_ld
)
ctba_r
<=
ctba
[
31
:
7
]
;
...
...
@@ -291,6 +295,13 @@ module ahci_dma (
else
if
(
set_axi_wr_cache_mode
)
afi_awcache
<=
axi_wr_cache_mode
;
prd_start_r
<=
prd_start
;
if
(
mrst
||
prd_irq_clear
||
cmd_start
||
cmd_abort
)
prd_irq_pend
<=
0
;
else
if
(
data_irq
&&
prd_done
)
prd_irq_pend
<=
1
;
if
(
mrst
||
cmd_start
||
cmd_abort
)
en_extra_din_r
<=
0
;
else
if
(
cmd_done
)
en_extra_din_r
<=
1
;
end
...
...
@@ -472,6 +483,7 @@ module ahci_dma (
.
dout_wstb
(
afi_wstb4
)
,
// output[3:0] reg
.
done
(
done_dev_rd
)
,
// output reg
.
busy
()
,
// output
.
fifo_nempty_mclk
(
fifo_nempty_mclk
)
,
// output reg
.
din
(
sys_in
)
,
// input[31:0]
.
din_rdy
(
sys_nfull
)
,
// output
.
din_avail
(
sys_we
)
// input
...
...
@@ -535,5 +547,19 @@ module ahci_dma (
.
busy
()
// output
)
;
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
)
prd_done_mclk_i
(
.
rst
(
hrst
)
,
// input
.
src_clk
(
hclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
in_pulse
(
done_dev_wr
||
done_dev_rd
)
,
// input
.
out_pulse
(
prd_done
)
,
// output
.
busy
()
// output
)
;
endmodule
ahci/ahci_dma_wr_fifo.v
View file @
17e832f8
...
...
@@ -59,7 +59,7 @@ module ahci_dma_wr_fifo#(
// last_prd was not set
output
busy
,
// output done_flush, // finished last PRD (indicated by last_prd @ start), data left module
output
reg
fifo_nempty_mclk
,
// to detect extra data from FIS, has some latency - only valid after read is stopped
// mclk domain
input
[
31
:
0
]
din
,
output
din_rdy
,
// can accept data from HBA (multiple dwords, so reasonable latency is OK)
...
...
@@ -268,6 +268,8 @@ module ahci_dma_wr_fifo#(
if
(
fifo_wr
&&
!
waddr
[
0
])
fifo0_ram
[
waddr
[
ADDRESS_BITS
:
1
]]
<=
din
;
if
(
fifo_wr
&&
waddr
[
0
])
fifo1_ram
[
waddr
[
ADDRESS_BITS
:
1
]]
<=
din
;
fifo_nempty_mclk
<=
(
fifo_full
[
raddr
[
ADDRESS_BITS
:
1
]]
^
raddr
[
ADDRESS_BITS
])
;
// only valid after read is stopped
end
...
...
ahci/ahci_fis_receive.v
View file @
17e832f8
...
...
@@ -35,7 +35,10 @@ module ahci_fis_receive#(
input
hba_rst
,
// @posedge mclk - sync reset
input
mclk
,
// for command/status
// Control Interface
output
reg
fis_first_vld
,
// fis_first contains valid FIS header, reset by get_*
output
reg
fis_first_vld
,
// fis_first contains valid FIS header, reset by get_*
// Debug features
output
fis_first_invalid
,
// Some data available from FIFO, but not FIS head
input
fis_first_flush
,
// Skip FIFO data until empty or FIS head
// Receiving FIS
input
get_dsfis
,
input
get_psfis
,
...
...
@@ -49,6 +52,8 @@ module ahci_fis_receive#(
output
reg
fis_ok
,
// FIS done, checksum OK reset by starting a new get FIS
output
reg
fis_err
,
// FIS done, checksum ERROR reset by starting a new get FIS
output
fis_ferr
,
// FIS done, fatal error - FIS too long
input
dma_prds_done
,
// dma is done - check if FIS is done (some data may get stuck in dma FIFO - reported separately)
output
fis_extra
,
// all wanted data got, FIS may have extra data (non-fatal). Does not deny fis_ok
input
set_update_sig
,
// when set, enables update_sig (and resets itself)
output
pUpdateSig
,
// state variable
output
reg
sig_available
,
// device signature a ailable
...
...
@@ -74,13 +79,14 @@ module ahci_fis_receive#(
output
[
7
:
0
]
tfd_sts
,
// Current PxTFD status field (updated after regFIS and SDB - certain fields)
// tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR
output
[
7
:
0
]
tfd_err
,
// Current PxTFD error field (updated after regFIS and SDB)
output
reg
fis_i
,
// value of "I" field in received regsD2H or SDB FIS
output
reg
fis_i
,
// value of "I" field in received regsD2H or SDB FIS
or DMA Setup FIS
output
reg
sdb_n
,
// value of "N" field in received SDB FIS
output
reg
dma_a
,
// value of "A" field in received DMA Setup FIS
output
reg
dma_d
,
// value of "D" field in received DMA Setup FIS
output
reg
pio_i
,
// value of "I" field in received PIO Setup FIS
output
reg
pio_d
,
// value of "D" field in received PIO Setup FIS
output
[
7
:
0
]
pio_es
,
// value of PIO E_Status
output
reg
sactive0
,
// bit 0 of sActive DWORD received in SDB FIS
// Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
output
[
31
:
2
]
xfer_cntr
,
// transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
output
reg
xfer_cntr_zero
,
// valid next cycle
...
...
@@ -144,6 +150,7 @@ localparam DATA_TYPE_ERR = 3;
wire
dma_in_start
;
wire
dma_in_stop
;
wire
dma_skipping_extra
;
// skipping extra FIS data not needed for DMA
reg
dma_in
;
reg
[
1
:
0
]
was_data_in
;
reg
[
11
:
0
]
data_in_dwords_r
;
...
...
@@ -160,7 +167,8 @@ localparam DATA_TYPE_ERR = 3;
reg
fis_rec_run
;
// running received FIS
reg
is_data_fis
;
wire
is_FIS_HEAD
=
data_in_ready
&&
(
hba_data_in_type
==
DATA_TYPE_FIS_HEAD
)
;
wire
is_FIS_HEAD
=
data_in_ready
&&
(
hba_data_in_type
==
DATA_TYPE_FIS_HEAD
)
;
wire
is_FIS_NOT_HEAD
=
data_in_ready
&&
(
hba_data_in_type
!=
DATA_TYPE_FIS_HEAD
)
;
wire
data_in_ready
=
hba_data_in_valid
&&
(
hba_data_in_many
||
!
(
|
was_data_in
||
hba_data_in_ready
)
)
;
...
...
@@ -173,7 +181,7 @@ localparam DATA_TYPE_ERR = 3;
reg
[
5
:
0
]
reg_ds
;
reg
[
4
:
0
]
reg_ps
;
reg
reg_d2h
;
reg
reg_sdb
;
reg
[
1
:
0
]
reg_sdb
;
reg
[
31
:
2
]
xfer_cntr_r
;
reg
[
31
:
2
]
prdbc_r
;
...
...
@@ -192,15 +200,23 @@ localparam DATA_TYPE_ERR = 3;
reg
pUpdateSig_r
=
1
;
// state variable
reg
[
31
:
0
]
sig_r
;
// signature register, save at
reg
fis_extra_r
;
reg
fis_first_invalid_r
;
reg
fis_first_flushing_r
;
// Forward data to DMA (dev->mem) engine
assign
dma_in_valid
=
dma_in_ready
&&
(
hba_data_in_type
==
DATA_TYPE_DMA
)
&&
data_in_ready
&&
!
too_long_err
;
assign
dma_in_stop
=
dma_in
&&
data_in_ready
&&
(
hba_data_in_type
!=
DATA_TYPE_DMA
)
;
// ||
assign
dma_in_valid
=
dma_in_ready
&&
(
hba_data_in_type
==
DATA_TYPE_DMA
)
&&
data_in_ready
&&
!
too_long_err
;
// Will also try to skip to the end of too long FIS
assign
dma_skipping_extra
=
(
fis_extra_r
||
too_long_err
)
&&
(
hba_data_in_type
==
DATA_TYPE_DMA
)
&&
data_in_ready
;
assign
dma_in_stop
=
dma_in
&&
data_in_ready
&&
(
hba_data_in_type
!=
DATA_TYPE_DMA
)
;
// ||
assign
reg_we_w
=
wreg_we_r
&&
!
dwords_over
&&
fis_save
;
assign
dma_in_start
=
is_data_fis
&&
wreg_we_r
;
assign
hba_data_in_ready
=
dma_in_valid
||
wreg_we_r
||
fis_end_r
[
0
]
;
assign
hba_data_in_ready
=
dma_in_valid
||
dma_skipping_extra
||
wreg_we_r
||
fis_end_r
[
0
]
||
(
is_FIS_NOT_HEAD
&&
fis_first_flushing_r
)
;
assign
fis_ferr
=
too_long_err
;
...
...
@@ -214,6 +230,11 @@ localparam DATA_TYPE_ERR = 3;
assign
pio_es
=
pio_es_r
;
assign
pUpdateSig
=
pUpdateSig_r
;
assign
fis_extra
=
fis_extra_r
;
assign
fis_first_invalid
=
fis_first_invalid_r
;
always
@
(
posedge
mclk
)
begin
if
(
hba_rst
||
dma_in_stop
)
dma_in
<=
0
;
else
if
(
dma_in_start
)
dma_in
<=
1
;
...
...
@@ -227,6 +248,11 @@ localparam DATA_TYPE_ERR = 3;
if
(
hba_rst
)
too_long_err
<=
0
;
// it is a fatal error, only reset
else
if
((
dma_in_valid
&&
data_in_dwords_r
[
11
])
||
(
wreg_we_r
&&
dwords_over
))
too_long_err
<=
1
;
if
(
hba_rst
||
dma_in_start
)
fis_extra_r
<=
0
;
else
if
(
data_in_ready
&&
(
hba_data_in_type
==
DATA_TYPE_DMA
)
&&
dma_prds_done
)
fis_extra_r
<=
1
;
if
(
get_fis
)
begin
reg_addr_r
<=
(
{
ADDRESS_BITS
{
get_dsfis
}}
&
(
FB_OFFS32
+
DSFIS32
))
|
...
...
@@ -243,7 +269,7 @@ localparam DATA_TYPE_ERR = 3;
(
{
4
{
get_ignore
}}
&
IGNORE_LENM1
)
;
// save signature FIS to memory if waiting (if not - ignore FIS)
// for non-signature /non-data - obey pcmd_fre
fis_save
<=
(
pUpdateSig_r
||
get_rfis
)
||
(
pcmd_fre
&&
!
get_data_fis
&&
!
get_ignore
)
;
fis_save
<=
(
pUpdateSig_r
&&
get_rfis
)
||
(
pcmd_fre
&&
!
get_data_fis
&&
!
get_ignore
)
;
is_data_fis
<=
get_data_fis
;
store_sig
<=
(
get_rfis
)
?
1
:
0
;
...
...
@@ -258,7 +284,7 @@ localparam DATA_TYPE_ERR = 3;
reg_ds
<=
reg_ds
<<
1
;
reg_ps
<=
reg_ps
<<
1
;
reg_d2h
<=
0
;
reg_sdb
<=
0
;
reg_sdb
<=
reg_sdb
<<
1
;
end
...
...
@@ -303,7 +329,7 @@ localparam DATA_TYPE_ERR = 3;
// Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ??
else
if
(
reg_ps
[
0
])
tf_err_sts
<=
{
hba_data_in
[
31
:
24
]
,
hba_data_in
[
23
:
16
]
};
else
if
(
update_pio
)
tf_err_sts
<=
{
pio_err_r
,
pio_es_r
};
else
if
(
reg_sdb
)
tf_err_sts
<=
{
hba_data_in
[
15
:
8
]
,
tf_err_sts
[
7
]
,
hba_data_in
[
6
:
4
]
,
tf_err_sts
[
3
]
,
hba_data_in
[
2
:
0
]
};
else
if
(
reg_sdb
[
0
])
tf_err_sts
<=
{
hba_data_in
[
15
:
8
]
,
tf_err_sts
[
7
]
,
hba_data_in
[
6
:
4
]
,
tf_err_sts
[
3
]
,
hba_data_in
[
2
:
0
]
};
else
if
(
clear_bsy_drq
||
set_bsy
||
clear_bsy_set_drq
)
tf_err_sts
<=
tf_err_sts
&
{
8'hff
,
clear_bsy_drq
,
3'h7
,
clear_bsy_drq
,
3'h7
}
|
{
8'h0
,
set_bsy
,
3'h0
,
clear_bsy_set_drq
,
3'h0
};
else
if
(
set_sts_7f
||
set_sts_80
)
tf_err_sts
<=
{
tf_err_sts
[
15
:
8
]
,
set_sts_80
,{
7
{
set_sts_7f
}}}
;
...
...
@@ -315,24 +341,26 @@ localparam DATA_TYPE_ERR = 3;
else
if
(
update_sig_r
)
reg_addr
<=
PXSIG_OFFS32
;
else
if
(
update_prdbc_r
)
reg_addr
<=
CLB_OFFS32
+
1
;
// location of PRDBC
if
(
reg_d2h
||
reg_sdb
||
reg_ds
[
0
])
fis_i
<=
hba_data_in
[
14
]
;
if
(
reg_d2h
||
reg_sdb
[
0
]
||
reg_ds
[
0
])
fis_i
<=
hba_data_in
[
14
]
;
if
(
reg_sdb
)
sdb_n
<=
hba_data_in
[
15
]
;
if
(
reg_ds
[
0
])
{
dma_a
,
dma_d
}
<=
{
hba_data_in
[
15
]
,
hba_data_in
[
13
]
};
if
(
reg_ps
[
0
])
{
pio_i
,
pio_d
}
<=
{
hba_data_in
[
14
]
,
hba_data_in
[
13
]
};
if
(
hba_rst
)
pio_err_r
<=
0
;
else
if
(
reg_ps
[
0
])
pio_err_r
<=
hba_data_in
[
31
:
24
]
;
if
(
hba_rst
)
pio_err_r
<=
0
;
else
if
(
reg_ps
[
0
])
pio_err_r
<=
hba_data_in
[
31
:
24
]
;
if
(
hba_rst
)
pio_es_r
<=
0
;
else
if
(
reg_ps
[
3
])
pio_es_r
<=
hba_data_in
[
31
:
24
]
;
if
(
hba_rst
)
pio_es_r
<=
0
;
else
if
(
reg_ps
[
3
])
pio_es_r
<=
hba_data_in
[
31
:
24
]
;
if
(
reg_sdb
[
1
])
sactive0
<=
hba_data_in
[
0
]
;
if
(
hba_rst
||
reg_sdb
||
clear_xfer_cntr
)
xfer_cntr_r
[
31
:
2
]
<=
0
;
if
(
hba_rst
||
reg_sdb
[
0
]
||
clear_xfer_cntr
)
xfer_cntr_r
[
31
:
2
]
<=
0
;
else
if
(
reg_ps
[
4
]
||
reg_ds
[
5
])
xfer_cntr_r
[
31
:
2
]
<=
{
reg_ds
[
5
]
?
hba_data_in
[
31
:
16
]
:
16'b0
,
hba_data_in
[
15
:
2
]
}
+
hba_data_in
[
1
]
;
// round up
else
if
(
decr_dwc
)
xfer_cntr_r
[
31
:
2
]
<=
{
xfer_cntr_r
[
31
:
2
]
}
-
{
18'b0
,
decr_DXC_dw
[
11
:
0
]
};
if
(
hba_rst
||
reg_sdb
||
reg_ps
[
4
]
||
reg_ds
[
5
])
prdbc_r
[
31
:
2
]
<=
0
;
else
if
(
decr_dwc
)
prdbc_r
[
31
:
2
]
<=
{
prdbc_r
[
31
:
2
]
}
+
{
18'b0
,
decr_DXC_dw
[
11
:
0
]
};
if
(
hba_rst
||
reg_sdb
[
0
]
||
reg_ps
[
4
]
||
reg_ds
[
5
])
prdbc_r
[
31
:
2
]
<=
0
;
else
if
(
decr_dwc
)
prdbc_r
[
31
:
2
]
<=
{
prdbc_r
[
31
:
2
]
}
+
{
18'b0
,
decr_DXC_dw
[
11
:
0
]
};
xfer_cntr_zero
<=
xfer_cntr_r
[
31
:
2
]
==
0
;
...
...
@@ -352,6 +380,12 @@ localparam DATA_TYPE_ERR = 3;
// Maybe it is not needed if the fsm will send this pulse?
// data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK);
if
(
hba_rst
||
get_fis_busy_r
)
fis_first_invalid_r
<=
0
;
else
fis_first_invalid_r
<=
is_FIS_NOT_HEAD
;
if
(
!
fis_first_invalid_r
)
fis_first_flushing_r
<=
0
;
else
if
(
fis_first_flush
)
fis_first_flushing_r
<=
1
;
end
endmodule
ahci/ahci_fis_transmit.v
View file @
17e832f8
...
...
@@ -75,7 +75,7 @@ module ahci_fis_transmit #(
input
dma_ct_busy
,
// dma module is busy reading command table from the system memory
// issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit
output
reg
dma_prd_start
,
// at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK
output
reg
dma_cmd_abort
,
// try to abort a command
TODO: Implement
output
reg
dma_cmd_abort
,
// try to abort a command
// reading out command table data from DMA module
output
reg
[
4
:
0
]
ct_addr
,
// DWORD address
...
...
ahci/ahci_fsm.v
View file @
17e832f8
...
...
@@ -148,11 +148,16 @@ module ahci_fsm
// inputs from the DMA engine
input
dma_prd_done
,
// output (finished next prd)
input
dma_prd_irq
,
// output (finished next prd and prd irq is enabled)
output
dma_prd_irq_clear
,
// reset pending prd_irq
input
dma_prd_irq_pend
,
// prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
input
dma_cmd_busy
,
// output reg (DMA engine is processing PRDs)
input
dma_cmd_done
,
// output (last PRD is over)
// Communication with ahci_fis_receive (some are unused
// Communication with ahci_fis_receive (some are unused)
// Debug features
input
fis_first_invalid
,
// Some data available from FIFO, but not FIS head
output
fis_first_flush
,
// Skip FIFO data until empty or FIS head
input
fis_first_vld
,
// fis_first contains valid FIS header, reset by 'get_*'
input
[
7
:
0
]
fis_type
,
// FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
input
[
7
:
0
]
bist_bits
,
// bits that define built-in self test
...
...
@@ -170,6 +175,7 @@ module ahci_fsm
input
fis_ok
,
// FIS done, checksum OK reset by starting a new get FIS
input
fis_err
,
// FIS done, checksum ERROR reset by starting a new get FIS
input
fis_ferr
,
// FIS done, fatal error - FIS too long
input
fis_extra
,
// more data got from FIS than DMA can accept. Does not deny fis_ok. May have latency
output
set_update_sig
,
// when set, enables get_sig (and resets itself)
input
pUpdateSig
,
// state variable
...
...
@@ -204,6 +210,7 @@ module ahci_fsm
input
pio_i
,
// value of "I" field in received PIO Setup FIS
input
pio_d
,
// value of "D" field in received PIO Setup FIS
input
[
7
:
0
]
pio_es
,
// value of PIO E_Status
input
sactive0
,
// bit 0 of sActive DWORD received in SDB FIS
// Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
input
[
31
:
2
]
xfer_cntr
,
// transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
input
xfer_cntr_zero
,
// valid next cycle
...
...
ahci/ahci_top.v
View file @
17e832f8
...
...
@@ -212,7 +212,8 @@ module ahci_top#(
wire
[
1
:
0
]
dma_ct_re
;
// input
wire
[
31
:
0
]
dma_ct_data
;
// output[31:0] reg
wire
dma_prd_done
;
// output (finished next prd)
wire
dma_prd_irq
;
// output (finished next prd and prd irq is enabled)
wire
dma_prd_irq_clear
;
// reset pending prd_irq
wire
dma_prd_irq_pend
;
// prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
wire
dma_cmd_busy
;
// output reg (DMA engine is processing PRDs)
wire
dma_cmd_done
;
// output (last PRD is over)
wire
[
31
:
0
]
dma_dout
;
// output[31:0]
...
...
@@ -220,10 +221,17 @@ module ahci_top#(
wire
dma_re
;
// input
wire
dma_in_ready
;
// output
wire
dma_we
;
// input
wire
dma_extra_din
;
// all DRDs are transferred to memory, but FIFO has some data. Valid when transfer is stopped
// ---------------------------------------
// fsm <-> ahc_fis_receive
// fsm ->
wire
frcv_first_vld
;
// To debug/recover -
wire
frcv_first_invalid
;
// Some data available from FIFO, but not FIS head
wire
frcv_first_flush
;
// Skip FIFO data until empty or FIS head
wire
frcv_get_dsfis
;
wire
frcv_get_psfis
;
wire
frcv_get_rfis
;
...
...
@@ -252,7 +260,8 @@ module ahci_top#(
wire
frcv_ok
;
// FIS done, checksum OK reset by starting a new get FIS
wire
frcv_err
;
// FIS done, checksum ERROR reset by starting a new get FIS
wire
frcv_ferr
;
// FIS done, fatal error - FIS too long
wire
frcv_extra
;
// DMA all transferred, but some data is still in left. . Does not deny frcv_ok
wire
frcv_set_update_sig
;
// when set, enables get_sig (and resets itself)
wire
frcv_pUpdateSig
;
// state variable
wire
frcv_sig_available
;
// signature data available
...
...
@@ -270,8 +279,8 @@ module ahci_top#(
wire
pio_i
;
// value of "I" field in received PIO Setup FIS
wire
pio_d
;
// value of "D" field in received PIO Setup FIS
wire
[
7
:
0
]
pio_es
;
// value of PIO E_Status
wire
pPioXfer
;
wire
sactive0
;
// bit 0 of sActive DWORD received in SDB FIS
// Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
wire
[
31
:
0
]
xfer_cntr
;
...
...
@@ -502,11 +511,16 @@ module ahci_top#(
.
pxci0_clear
(
pxci0_clear
)
,
// output
.
pxci0
(
pxci0
)
,
// input
.
dma_prd_done
(
dma_prd_done
)
,
// input
.
dma_prd_irq
(
dma_prd_irq
)
,
// input
.
dma_prd_done
(
dma_prd_done
)
,
// input
.
dma_prd_irq_clear
(
dma_prd_irq_clear
)
,
// output
.
dma_prd_irq_pend
(
dma_prd_irq_pend
)
,
// input
.
dma_cmd_busy
(
dma_cmd_busy
)
,
// input
.
dma_cmd_done
(
dma_cmd_done
)
,
// input
.
fis_first_invalid
(
frcv_first_invalid
)
,
// input
.
fis_first_flush
(
frcv_first_flush
)
,
// output
.
fis_first_vld
(
frcv_first_vld
)
,
// input
.
fis_type
(
d2h_data
[
7
:
0
])
,
// input[7:0] FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
.
bist_bits
(
d2h_data
[
23
:
16
])
,
// bits that define built-in self test
...
...
@@ -523,6 +537,7 @@ module ahci_top#(
.
fis_ok
(
frcv_ok
)
,
// input
.
fis_err
(
frcv_err
)
,
// input
.
fis_ferr
(
frcv_ferr
)
,
// input
.
fis_extra
(
frcv_extra
||
dma_extra_din
)
,
// input // more data got from FIS than DMA can accept. Does not deny fis_ok. May have latency
.
set_update_sig
(
frcv_set_update_sig
)
,
// output
.
pUpdateSig
(
frcv_pUpdateSig
)
,
// input
...
...
@@ -552,6 +567,7 @@ module ahci_top#(
.
dma_d
(
dma_d
)
,
// input
.
pio_i
(
pio_i
)
,
// input
.
pio_d
(
pio_d
)
,
// input
.
sactive0
(
sactive0
)
,
// input
.
pio_es
(
pio_es
)
,
// input[7:0]
.
xfer_cntr
(
xfer_cntr
[
31
:
2
])
,
// input[31:2]
.
xfer_cntr_zero
(
xfer_cntr_zero
)
,
// input
...
...
@@ -746,7 +762,10 @@ module ahci_top#(
.
ct_re
(
dma_ct_re
[
0
])
,
// input
.
ct_data
(
dma_ct_data
)
,
// output[31:0] reg
.
prd_done
(
dma_prd_done
)
,
// output
.
prd_irq
(
dma_prd_irq
)
,
// output
.
prd_irq_clear
(
dma_prd_irq_clear
)
,
// input
.
prd_irq_pend
(
dma_prd_irq_pend
)
,
// output reg
.
cmd_busy
(
dma_cmd_busy
)
,
// output reg
.
cmd_done
(
dma_cmd_done
)
,
// output
.
sys_out
(
dma_dout
)
,
// output[31:0]
...
...
@@ -755,7 +774,7 @@ module ahci_top#(
.
sys_in
(
d2h_data
)
,
// input[31:0]
.
sys_nfull
(
dma_in_ready
)
,
// output
.
sys_we
(
dma_we
)
,
// input
.
extra_din
(
dma_extra_din
)
,
// output reg
.
afi_awaddr
(
afi_awaddr
)
,
// output[31:0]
.
afi_awvalid
(
afi_awvalid
)
,
// output
.
afi_awready
(
afi_awready
)
,
// input
...
...
@@ -809,6 +828,8 @@ module ahci_top#(
.
mclk
(
mclk
)
,
// input
.
fis_first_vld
(
frcv_first_vld
)
,
// output reg
.
fis_first_invalid
(
frcv_first_invalid
)
,
// output
.
fis_first_flush
(
frcv_first_flush
)
,
// input
.
get_dsfis
(
frcv_get_dsfis
)
,
// input
.
get_psfis
(
frcv_get_psfis
)
,
// input
...
...
@@ -824,6 +845,9 @@ module ahci_top#(
.
fis_err
(
frcv_err
)
,
// output reg
.
fis_ferr
(
frcv_ferr
)
,
// output
.
dma_prds_done
(
dma_cmd_done
)
,
// input
.
fis_extra
(
frcv_extra
)
,
// output
.
set_update_sig
(
frcv_set_update_sig
)
,
// input
.
pUpdateSig
(
frcv_pUpdateSig
)
,
// output
.
sig_available
(
frcv_sig_available
)
,
// output reg
...
...
@@ -855,6 +879,7 @@ module ahci_top#(
.
pio_i
(
pio_i
)
,
// output reg
.
pio_d
(
pio_d
)
,
// output reg
.
pio_es
(
pio_es
)
,
// output[7:0] reg
.
sactive0
(
sactive0
)
,
// output reg
.
xfer_cntr
(
xfer_cntr
[
31
:
2
])
,
// output[31:2]
.
xfer_cntr_zero
(
xfer_cntr_zero
)
,
// output reg
.
data_in_dwords
(
data_in_dwords
)
,
// output[11:0]
...
...
generated/action_decoder.v
0 → 100644
View file @
17e832f8
/*******************************************************************************
* Module: action_decoder
* Date:2016-01-18
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Decode sequencer code to 1-hot actions
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
action_decoder
(
input
clk
,
input
enable
,
input
[
10
:
0
]
data
,
output
reg
PXSERR_DIAG_X
,
output
reg
SIRQ_DHR
,
output
reg
SIRQ_DP
,
output
reg
SIRQ_DS
,
output
reg
SIRQ_IF
,
output
reg
SIRQ_PS
,
output
reg
SIRQ_SDB
,
output
reg
SIRQ_TFE
,
output
reg
SIRQ_UF
,
output
reg
PFSM_STARTED
,
output
reg
PCMD_CR_CLEAR
,
output
reg
PCMD_CR_SET
,
output
reg
PXCI0_CLEAR
,
output
reg
PXSSTS_DET_1
,
output
reg
SSTS_DET_OFFLINE
,
output
reg
SET_UPDATE_SIG
,
output
reg
UPDATE_SIG
,
output
reg
UPDATE_ERR_STS
,
output
reg
UPDATE_PIO
,
output
reg
UPDATE_PRDBC
,
output
reg
CLEAR_BSY_DRQ
,
output
reg
CLEAR_BSY_SET_DRQ
,
output
reg
SET_BSY
,
output
reg
SET_STS_7F
,
output
reg
SET_STS_80
,
output
reg
XFER_CNTR_CLEAR
,
output
reg
DECR_DWC
,
output
reg
FIS_FIRST_FLUSH
,
output
reg
CLEAR_CMD_TO_ISSUE
,
output
reg
DMA_ABORT
,
output
reg
DMA_PRD_IRQ_CLEAR
,
output
reg
XMIT_COMRESET
,
output
reg
SEND_SYNC_ESC
,
output
reg
SET_OFFLINE
,
output
reg
R_OK
,
output
reg
R_ERR
,
output
reg
FETCH_CMD
,
output
reg
ATAPI_XMIT
,
output
reg
CFIS_XMIT
,
output
reg
DX_XMIT
,
output
reg
GET_DATA_FIS
,
output
reg
GET_DSFIS
,
output
reg
GET_IGNORE
,
output
reg
GET_PSFIS
,
output
reg
GET_RFIS
,
output
reg
GET_SDBFIS
,
output
reg
GET_UFIS
)
;
always
@
(
posedge
clk
)
begin
PXSERR_DIAG_X
<=
enable
&&
data
[
2
]
&&
data
[
0
]
;
SIRQ_DHR
<=
enable
&&
data
[
3
]
&&
data
[
0
]
;
SIRQ_DP
<=
enable
&&
data
[
4
]
&&
data
[
0
]
;
SIRQ_DS
<=
enable
&&
data
[
5
]
&&
data
[
0
]
;
SIRQ_IF
<=
enable
&&
data
[
6
]
&&
data
[
0
]
;
SIRQ_PS
<=
enable
&&
data
[
7
]
&&
data
[
0
]
;
SIRQ_SDB
<=
enable
&&
data
[
8
]
&&
data
[
0
]
;
SIRQ_TFE
<=
enable
&&
data
[
9
]
&&
data
[
0
]
;
SIRQ_UF
<=
enable
&&
data
[
10
]
&&
data
[
0
]
;
PFSM_STARTED
<=
enable
&&
data
[
2
]
&&
data
[
1
]
;
PCMD_CR_CLEAR
<=
enable
&&
data
[
3
]
&&
data
[
1
]
;
PCMD_CR_SET
<=
enable
&&
data
[
4
]
&&
data
[
1
]
;
PXCI0_CLEAR
<=
enable
&&
data
[
5
]
&&
data
[
1
]
;
PXSSTS_DET_1
<=
enable
&&
data
[
6
]
&&
data
[
1
]
;
SSTS_DET_OFFLINE
<=
enable
&&
data
[
7
]
&&
data
[
1
]
;
SET_UPDATE_SIG
<=
enable
&&
data
[
8
]
&&
data
[
1
]
;
UPDATE_SIG
<=
enable
&&
data
[
9
]
&&
data
[
1
]
;
UPDATE_ERR_STS
<=
enable
&&
data
[
10
]
&&
data
[
1
]
;
UPDATE_PIO
<=
enable
&&
data
[
3
]
&&
data
[
2
]
;
UPDATE_PRDBC
<=
enable
&&
data
[
4
]
&&
data
[
2
]
;
CLEAR_BSY_DRQ
<=
enable
&&
data
[
5
]
&&
data
[
2
]
;
CLEAR_BSY_SET_DRQ
<=
enable
&&
data
[
6
]
&&
data
[
2
]
;
SET_BSY
<=
enable
&&
data
[
7
]
&&
data
[
2
]
;
SET_STS_7F
<=
enable
&&
data
[
8
]
&&
data
[
2
]
;
SET_STS_80
<=
enable
&&
data
[
9
]
&&
data
[
2
]
;
XFER_CNTR_CLEAR
<=
enable
&&
data
[
10
]
&&
data
[
2
]
;
DECR_DWC
<=
enable
&&
data
[
4
]
&&
data
[
3
]
;
FIS_FIRST_FLUSH
<=
enable
&&
data
[
5
]
&&
data
[
3
]
;
CLEAR_CMD_TO_ISSUE
<=
enable
&&
data
[
6
]
&&
data
[
3
]
;
DMA_ABORT
<=
enable
&&
data
[
7
]
&&
data
[
3
]
;
DMA_PRD_IRQ_CLEAR
<=
enable
&&
data
[
8
]
&&
data
[
3
]
;
XMIT_COMRESET
<=
enable
&&
data
[
9
]
&&
data
[
3
]
;
SEND_SYNC_ESC
<=
enable
&&
data
[
10
]
&&
data
[
3
]
;
SET_OFFLINE
<=
enable
&&
data
[
5
]
&&
data
[
4
]
;
R_OK
<=
enable
&&
data
[
6
]
&&
data
[
4
]
;
R_ERR
<=
enable
&&
data
[
7
]
&&
data
[
4
]
;
FETCH_CMD
<=
enable
&&
data
[
8
]
&&
data
[
4
]
;
ATAPI_XMIT
<=
enable
&&
data
[
9
]
&&
data
[
4
]
;
CFIS_XMIT
<=
enable
&&
data
[
10
]
&&
data
[
4
]
;
DX_XMIT
<=
enable
&&
data
[
6
]
&&
data
[
5
]
;
GET_DATA_FIS
<=
enable
&&
data
[
7
]
&&
data
[
5
]
;
GET_DSFIS
<=
enable
&&
data
[
8
]
&&
data
[
5
]
;
GET_IGNORE
<=
enable
&&
data
[
9
]
&&
data
[
5
]
;
GET_PSFIS
<=
enable
&&
data
[
10
]
&&
data
[
5
]
;
GET_RFIS
<=
enable
&&
data
[
7
]
&&
data
[
6
]
;
GET_SDBFIS
<=
enable
&&
data
[
8
]
&&
data
[
6
]
;
GET_UFIS
<=
enable
&&
data
[
9
]
&&
data
[
6
]
;
end
endmodule
generated/condition_mux.v
0 → 100644
View file @
17e832f8
/*******************************************************************************
* Module: condition_mux
* Date:2016-01-18
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Select condition
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
condition_mux
(
input
clk
,
input
[
7
:
0
]
sel
,
output
condition
,
input
ST_NB_ND
,
input
PXCI0_NOT_CMDTOISSUE
,
input
PCTI_CTBAR_XCZ
,
input
PCTI_XCZ
,
input
NST_D2HR
,
input
NPD_NCA
,
input
CHW_DMAA
,
input
SCTL_DET_CHANGED_TO_4
,
input
SCTL_DET_CHANGED_TO_1
,
input
PXSSTS_DET_NE_3
,
input
PXSSTS_DET_EQ_1
,
input
NPCMD_FRE
,
input
FIS_OK
,
input
FIS_ERR
,
input
FIS_FERR
,
input
FIS_EXTRA
,
input
FIS_FIRST_INVALID
,
input
FR_D2HR
,
input
FIS_DATA
,
input
FIS_ANY
,
input
NB_ND_D2HR_PIO
,
input
D2HR
,
input
SDB
,
input
DMA_ACT
,
input
DMA_SETUP
,
input
BIST_ACT_FE
,
input
BIST_ACT
,
input
PIO_SETUP
,
input
NB_ND
,
input
TFD_STS_ERR
,
input
FIS_I
,
input
PIO_I
,
input
NPD
,
input
PIOX
,
input
XFER0
,
input
PIOX_XFER0
,
input
CTBAA_CTBAP
,
input
CTBAP
,
input
CTBA_B
,
input
CTBA_C
,
input
TX_ERR
,
input
SYNCESC_ERR
,
input
DMA_PRD_IRQ_PEND
,
input
X_RDY_COLLISION
)
;
wire
[
43
:
0
]
masked
;
reg
[
5
:
0
]
cond_r
;
assign
condition
=
|
cond_r
;
assign
masked
[
0
]
=
ST_NB_ND
&&
sel
[
2
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
1
]
=
PXCI0_NOT_CMDTOISSUE
&&
sel
[
3
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
2
]
=
PCTI_CTBAR_XCZ
&&
sel
[
4
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
3
]
=
PCTI_XCZ
&&
sel
[
5
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
4
]
=
NST_D2HR
&&
sel
[
6
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
5
]
=
NPD_NCA
&&
sel
[
7
]
&&
sel
[
1
]
&&
sel
[
0
]
;
assign
masked
[
6
]
=
CHW_DMAA
&&
sel
[
3
]
&&
sel
[
2
]
&&
sel
[
0
]
;
assign
masked
[
7
]
=
SCTL_DET_CHANGED_TO_4
&&
sel
[
4
]
&&
sel
[
2
]
&&
sel
[
0
]
;
assign
masked
[
8
]
=
SCTL_DET_CHANGED_TO_1
&&
sel
[
5
]
&&
sel
[
2
]
&&
sel
[
0
]
;
assign
masked
[
9
]
=
PXSSTS_DET_NE_3
&&
sel
[
6
]
&&
sel
[
2
]
&&
sel
[
0
]
;
assign
masked
[
10
]
=
PXSSTS_DET_EQ_1
&&
sel
[
7
]
&&
sel
[
2
]
&&
sel
[
0
]
;
assign
masked
[
11
]
=
NPCMD_FRE
&&
sel
[
4
]
&&
sel
[
3
]
&&
sel
[
0
]
;
assign
masked
[
12
]
=
FIS_OK
&&
sel
[
5
]
&&
sel
[
3
]
&&
sel
[
0
]
;
assign
masked
[
13
]
=
FIS_ERR
&&
sel
[
6
]
&&
sel
[
3
]
&&
sel
[
0
]
;
assign
masked
[
14
]
=
FIS_FERR
&&
sel
[
7
]
&&
sel
[
3
]
&&
sel
[
0
]
;
assign
masked
[
15
]
=
FIS_EXTRA
&&
sel
[
5
]
&&
sel
[
4
]
&&
sel
[
0
]
;
assign
masked
[
16
]
=
FIS_FIRST_INVALID
&&
sel
[
6
]
&&
sel
[
4
]
&&
sel
[
0
]
;
assign
masked
[
17
]
=
FR_D2HR
&&
sel
[
7
]
&&
sel
[
4
]
&&
sel
[
0
]
;
assign
masked
[
18
]
=
FIS_DATA
&&
sel
[
6
]
&&
sel
[
5
]
&&
sel
[
0
]
;
assign
masked
[
19
]
=
FIS_ANY
&&
sel
[
7
]
&&
sel
[
5
]
&&
sel
[
0
]
;
assign
masked
[
20
]
=
NB_ND_D2HR_PIO
&&
sel
[
7
]
&&
sel
[
6
]
&&
sel
[
0
]
;
assign
masked
[
21
]
=
D2HR
&&
sel
[
3
]
&&
sel
[
2
]
&&
sel
[
1
]
;
assign
masked
[
22
]
=
SDB
&&
sel
[
4
]
&&
sel
[
2
]
&&
sel
[
1
]
;
assign
masked
[
23
]
=
DMA_ACT
&&
sel
[
5
]
&&
sel
[
2
]
&&
sel
[
1
]
;
assign
masked
[
24
]
=
DMA_SETUP
&&
sel
[
6
]
&&
sel
[
2
]
&&
sel
[
1
]
;
assign
masked
[
25
]
=
BIST_ACT_FE
&&
sel
[
7
]
&&
sel
[
2
]
&&
sel
[
1
]
;
assign
masked
[
26
]
=
BIST_ACT
&&
sel
[
4
]
&&
sel
[
3
]
&&
sel
[
1
]
;
assign
masked
[
27
]
=
PIO_SETUP
&&
sel
[
5
]
&&
sel
[
3
]
&&
sel
[
1
]
;
assign
masked
[
28
]
=
NB_ND
&&
sel
[
6
]
&&
sel
[
3
]
&&
sel
[
1
]
;
assign
masked
[
29
]
=
TFD_STS_ERR
&&
sel
[
7
]
&&
sel
[
3
]
&&
sel
[
1
]
;
assign
masked
[
30
]
=
FIS_I
&&
sel
[
5
]
&&
sel
[
4
]
&&
sel
[
1
]
;
assign
masked
[
31
]
=
PIO_I
&&
sel
[
6
]
&&
sel
[
4
]
&&
sel
[
1
]
;
assign
masked
[
32
]
=
NPD
&&
sel
[
7
]
&&
sel
[
4
]
&&
sel
[
1
]
;
assign
masked
[
33
]
=
PIOX
&&
sel
[
6
]
&&
sel
[
5
]
&&
sel
[
1
]
;
assign
masked
[
34
]
=
XFER0
&&
sel
[
7
]
&&
sel
[
5
]
&&
sel
[
1
]
;
assign
masked
[
35
]
=
PIOX_XFER0
&&
sel
[
7
]
&&
sel
[
6
]
&&
sel
[
1
]
;
assign
masked
[
36
]
=
CTBAA_CTBAP
&&
sel
[
4
]
&&
sel
[
3
]
&&
sel
[
2
]
;
assign
masked
[
37
]
=
CTBAP
&&
sel
[
5
]
&&
sel
[
3
]
&&
sel
[
2
]
;
assign
masked
[
38
]
=
CTBA_B
&&
sel
[
6
]
&&
sel
[
3
]
&&
sel
[
2
]
;
assign
masked
[
39
]
=
CTBA_C
&&
sel
[
7
]
&&
sel
[
3
]
&&
sel
[
2
]
;
assign
masked
[
40
]
=
TX_ERR
&&
sel
[
5
]
&&
sel
[
4
]
&&
sel
[
2
]
;
assign
masked
[
41
]
=
SYNCESC_ERR
&&
sel
[
6
]
&&
sel
[
4
]
&&
sel
[
2
]
;
assign
masked
[
42
]
=
DMA_PRD_IRQ_PEND
&&
sel
[
7
]
&&
sel
[
4
]
&&
sel
[
2
]
;
assign
masked
[
43
]
=
X_RDY_COLLISION
&&
sel
[
6
]
&&
sel
[
5
]
&&
sel
[
2
]
;
always
@
(
posedge
clk
)
begin
cond_r
[
0
]
<=
|
masked
[
7
:
0
]
;
cond_r
[
1
]
<=
|
masked
[
15
:
8
]
;
cond_r
[
2
]
<=
|
masked
[
23
:
16
]
;
cond_r
[
3
]
<=
|
masked
[
31
:
24
]
;
cond_r
[
4
]
<=
|
masked
[
39
:
32
]
;
cond_r
[
5
]
<=
|
masked
[
43
:
40
]
;
end
endmodule
helpers/ahci_fsm_sequence.py
View file @
17e832f8
...
...
@@ -25,24 +25,72 @@ __maintainer__ = "Andrey Filippov"
__email__
=
"andrey@elphel.com"
__status__
=
"Development"
import
sys
import
os
import
datetime
LBL
=
"Label"
ACT
=
"Action"
IF
=
"If"
GOTO
=
"Goto"
ADR
=
"Address"
AD
D
R
=
"Address"
NOP
=
"NOP"
sequence
=
[{
LBL
:
'POR'
,
ADR
:
0x0
,
ACT
:
NOP
},
actions_cnk
=
(
11
,
2
)
# 2 hot of 8
conditions_cnk
=
(
8
,
3
)
# 3 hot of 11
#action_decoder_verilog_path=None
action_decoder_verilog_path
=
'../generated/action_decoder.v'
action_decoder_module_name
=
'action_decoder'
condition_mux_verilog_path
=
'../generated/condition_mux.v'
condition_mux_module_name
=
'condition_mux'
condition_mux_fanout
=
8
#Set actions, conditions to empty string to rebuild list. Then edit order and put here
actions
=
[
'NOP'
,
# CTRL_STAT
'PXSERR_DIAG_X'
,
'SIRQ_DHR'
,
'SIRQ_DP'
,
'SIRQ_DS'
,
'SIRQ_IF'
,
'SIRQ_PS'
,
'SIRQ_SDB'
,
'SIRQ_TFE'
,
'SIRQ_UF'
,
'PFSM_STARTED'
,
'PCMD_CR_CLEAR'
,
'PCMD_CR_SET'
,
'PXCI0_CLEAR'
,
'PXSSTS_DET_1'
,
'SSTS_DET_OFFLINE'
,
# FIS RECEIVE
'SET_UPDATE_SIG'
,
'UPDATE_SIG'
,
'UPDATE_ERR_STS'
,
'UPDATE_PIO'
,
'UPDATE_PRDBC'
,
'CLEAR_BSY_DRQ'
,
'CLEAR_BSY_SET_DRQ'
,
'SET_BSY'
,
'SET_STS_7F'
,
'SET_STS_80'
,
'XFER_CNTR_CLEAR'
,
'DECR_DWC'
,
'FIS_FIRST_FLUSH'
,
# FIS_TRANSMIT
'CLEAR_CMD_TO_ISSUE'
,
# DMA
'DMA_ABORT'
,
'DMA_PRD_IRQ_CLEAR'
,
# SATA TRANSPORT/LINK/PHY
'XMIT_COMRESET'
,
'SEND_SYNC_ESC'
,
'SET_OFFLINE'
,
'R_OK'
,
'R_ERR'
,
# FIS TRANSMIT/WAIT DONE
'FETCH_CMD*'
,
'ATAPI_XMIT*'
,
'CFIS_XMIT*'
,
'DX_XMIT*'
,
#FIS RECEIVE/WAIT DONE
'GET_DATA_FIS*'
,
'GET_DSFIS*'
,
'GET_IGNORE*'
,
'GET_PSFIS*'
,
'GET_RFIS*'
,
'GET_SDBFIS*'
,
'GET_UFIS*'
]
conditions
=
[
#COMPOSITE
'ST_NB_ND'
,
'PXCI0_NOT_CMDTOISSUE'
,
'PCTI_CTBAR_XCZ'
,
'PCTI_XCZ'
,
'NST_D2HR'
,
'NPD_NCA'
,
'CHW_DMAA'
,
# CTRL_STAT
'SCTL_DET_CHANGED_TO_4'
,
'SCTL_DET_CHANGED_TO_1'
,
'PXSSTS_DET_NE_3'
,
'PXSSTS_DET_EQ_1'
,
'NPCMD_FRE'
,
# FIS RECEIVE
'FIS_OK'
,
'FIS_ERR'
,
'FIS_FERR'
,
'FIS_EXTRA'
,
'FIS_FIRST_INVALID'
,
'FR_D2HR'
,
'FIS_DATA'
,
'FIS_ANY'
,
'NB_ND_D2HR_PIO'
,
'D2HR'
,
'SDB'
,
'DMA_ACT'
,
'DMA_SETUP'
,
'BIST_ACT_FE'
,
'BIST_ACT'
,
'PIO_SETUP'
,
'NB_ND'
,
'TFD_STS_ERR'
,
'FIS_I'
,
'PIO_I'
,
'NPD'
,
'PIOX'
,
'XFER0'
,
'PIOX_XFER0'
,
# FIS_TRANSMIT
'CTBAA_CTBAP'
,
'CTBAP'
,
'CTBA_B'
,
'CTBA_C'
,
'TX_ERR'
,
'SYNCESC_ERR'
,
# DMA
'DMA_PRD_IRQ_PEND'
,
# SATA TRANSPORT/LINK/PHY
'X_RDY_COLLISION'
]
# TODO: set/reset
#actions = []
#conditions = []
sequence
=
[{
LBL
:
'POR'
,
ADDR
:
0x0
,
ACT
:
NOP
},
{
GOTO
:
'H:Init'
},
{
LBL
:
'HBA_RST'
,
AD
R
:
0x2
,
ACT
:
NOP
},
{
LBL
:
'HBA_RST'
,
AD
DR
:
0x2
,
ACT
:
NOP
},
{
GOTO
:
'H:Init'
},
{
LBL
:
'PORT_RST'
,
AD
R
:
0x4
,
ACT
:
NOP
},
{
LBL
:
'PORT_RST'
,
AD
DR
:
0x4
,
ACT
:
NOP
},
{
GOTO
:
'H:Init'
},
{
LBL
:
'COMINIT'
,
ADR
:
0x6
,
ACT
:
NOP
},
{
LBL
:
'COMINIT'
,
AD
D
R
:
0x6
,
ACT
:
NOP
},
{
GOTO
:
'P:Cominit'
},
{
LBL
:
'ST_CLEARED'
,
AD
R
:
0x6
,
ACT
:
NOP
},
# TODO: make sure this jump is not from P:Init
{
LBL
:
'ST_CLEARED'
,
AD
DR
:
0x8
,
ACT
:
NOP
},
# TODO: make sure this jump is not from P:Init
{
GOTO
:
'P:StartBitCleared'
},
...
...
@@ -55,231 +103,596 @@ sequence = [{LBL:'POR', ADR: 0x0, ACT: NOP},
{
LBL
:
'H:Idle'
,
ACT
:
NOP
},
{
GOTO
:
'P:Init'
},
#All required actions for H* are done in hardware, just go to port initialization
{
LBL
:
'P:Init'
,
ACT
:
'PFSM'
},
# pfsm_started HBA init done, port FSM started
{
ACT
:
'PSCI0'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
ACT
:
'CLEAR_BSY_SET_DRQ'
},
# clear_bsy_set_drq
{
ACT
:
'SET_STS_7F'
},
# set_sts_7f
{
ACT
:
'SET_UPDATE_SIG'
},
# set_update_sig
{
ACT
:
'XMIT_COMRESET'
},
# Now does it on reset. See if it is possible to transmit COMRESET w/o reset
{
LBL
:
'P:Init'
,
ACT
:
'PFSM_STARTED'
},
# pfsm_started HBA init done, port FSM started
{
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
ACT
:
'CLEAR_BSY_SET_DRQ'
},
# clear_bsy_set_drq
{
ACT
:
'SET_STS_7F'
},
# set_sts_7f
{
ACT
:
'SET_UPDATE_SIG'
},
# set_update_sig
{
ACT
:
'XMIT_COMRESET'
},
# Now does it on reset. See if it is possible to transmit COMRESET w/o reset
{
GOTO
:
'P:NotRunning'
},
{
LBL
:
'P:NotRunningGarbage'
,
ACT
:
'FIS_FIRST_FLUSH'
},
# fis_first_flush (FIFO output has data, but not FIS head
#TODO - add to some error? Now silently skips
{
GOTO
:
'P:NotRunning'
},
{
LBL
:
'P:NotRunning'
,
ACT
:
'NOP'
},
# 'PSCI0'}, # pxci0_clear, - should not be here as it updates soft registers?
{
IF
:
'SCTL_DET_CHANGED_TO_4'
,
GOTO
:
'P:Offline'
},
#4
{
IF
:
'SCTL_DET_CHANGED_TO_1'
,
GOTO
:
'P:StartComm'
},
#5
{
LBL
:
'P:NotRunning'
,
ACT
:
'NOP'
},
# 'PXCI0_CLEAR'}, # pxci0_clear, - should not be here as it updates soft registers?
{
IF
:
'FIS_FIRST_INVALID'
,
GOTO
:
'P:NotRunningGarbage'
},
{
IF
:
'SCTL_DET_CHANGED_TO_4'
,
GOTO
:
'P:Offline'
},
#4
{
IF
:
'SCTL_DET_CHANGED_TO_1'
,
GOTO
:
'P:StartComm'
},
#5
# Transition 8. PxCMD.FRE written to ‘1’ from a ‘0’ and previously processed Register FIS is in receive FIFO and PxSERR.DIAG.X = ‘0’
# can not be implemented - it is too late, FIS is already gone. So as we do not move FIS receive area, there is no sense to disable FIS,
# and for the signature we'll always assume FRE is on
{
IF
:
'ST_NB_ND'
,
GOTO
:
'P:Idle'
},
#12 : PxCMD.ST & !PxTBD.STS.BSY & !PxTBD.STS.DRQ
{
IF
:
'FR_D2HR'
,
GOTO
:
'NDR:Entry'
},
#13 fis_first_vld & fis_type == 0x34 (D2H Register)
{
GOTO
:
'P:NotRunning'
},
#14
{
IF
:
'ST_NB_ND'
,
GOTO
:
'P:Idle'
},
#12 : PxCMD.ST & !PxTBD.STS.BSY & !PxTBD.STS.DRQ
{
IF
:
'FR_D2HR'
,
GOTO
:
'NDR:Entry'
},
#13 fis_first_vld & fis_type == 0x34 (D2H Register)
{
GOTO
:
'P:NotRunning'
},
#14
{
LBL
:
'P:Cominit'
,
ACT
:
'NOP'
},
# got here asynchronously from COMINIT label
{
ACT
:
'SET_STS_80'
},
# frcv_set_sts_80 (Not clear 0xff or 0x80 should be here?)
{
ACT
:
'PXSSTS_DET_1'
},
# ssts_det_dnp, // device detected, but phy communication not established
{
ACT
:
'PXSERR_DIAG_X'
},
# sirq_PC, // RO: Port Connect Change Status (pulse to set)
# {IF:'PXIE_PCE', GOTO:'P:CominitSetIS'}, # Not needed, interrupt
{
ACT
:
'SET_STS_80'
},
# frcv_set_sts_80 (Not clear 0xff or 0x80 should be here?)
{
ACT
:
'PXSSTS_DET_1'
},
# ssts_det_dnp, // device detected, but phy communication not established
{
ACT
:
'PXSERR_DIAG_X'
},
# sirq_PC, // RO: Port Connect Change Status (pulse to set)
# {IF:'PXIE_PCE', GOTO:'P:CominitSetIS'},
# Not needed, interrupt
{
GOTO
:
'P:NotRunning'
},
{
LBL
:
'P:RegFisUpdate'
,
ACT
:
'GET_RFIS
'
},
#
get_rfis
{
ACT
:
'UPDATE_SIG'
},
# update_sig
# {IF: 'PCMD_FRE', GOTO:'P:RegFisPostToMem'}, # pcmd_fre hardware always copies signature FIS to 'memory' if expected
{
GOTO
:
'P:
NotRunning
'
},
{
LBL
:
'P:RegFisUpdate'
,
ACT
:
'GET_RFIS
*'
},
#
get_rfis
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'P:
RegFisAccept
'
},
{
LBL
:
'P:RegFisPostToMem'
,
ACT
:
'NOP'
},
# Probably not needed, handled at lower level
{
LBL
:
'P:RegFisAccept'
,
ACT
:
'R_OK'
},
# send R_OK
{
ACT
:
'UPDATE_SIG'
},
# update_sig
{
ACT
:
'UPDATE_ERR_STS'
},
# update_err_sts
{
GOTO
:
'P:NotRunning'
},
{
LBL
:
'P:Offline'
,
ACT
:
'SET_OFFLINE'
},
# set_offline
# {IF: 'PCMD_FRE', GOTO:'P:RegFisPostToMem'}, # pcmd_fre hardware always copies signature FIS to 'memory' if expected
# {LBL:'P:RegFisPostToMem', ACT: 'NOP'}, # Probably not needed, handled at lower level
# { GOTO:'P:NotRunning'},
{
LBL
:
'P:Offline'
,
ACT
:
'SET_OFFLINE'
},
# set_offline
{
GOTO
:
'P:NotRunning'
},
{
LBL
:
'P:StartBitCleared'
,
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear
{
ACT
:
'DMA_ABORT'
},
# dma_cmd_abort (should eventually clear PxCMD.CR)?
{
ACT
:
'PCMD_CR_CLEAR'
},
# pcmd_cr_reset
{
ACT
:
'XFER_CNTR_CLEAR'
},
# clear_xfer_cntr
{
LBL
:
'P:Idle'
,
ACT
:
'PCMD_CR_SET'
},
# pcmd_cr_set
{
IF
:
'PXSSTS_DET_NE_3'
,
GOTO
:
'P:NotRunning'
},
# 1. ssts_det!=3, // device detected, phy communication not established
{
IF
:
'PXCI0_NOT_CMDTOISSUE'
,
GOTO
:
'P:FetchCmd'
},
# 2. pxci0 && !pCmdToIssue was pIssueSlot==32, -> p:SelectCmd
{
IF
:
'PCTI_CTBAR_XCZ'
,
GOTO
:
'CFIS:SyncEscape'
},
# 3. pCmdToIssue && ch_r && xfer_cntr_zero
{
IF
:
'FIS_DATA'
,
GOTO
:
'DR:Entry'
},
# 4. fis_first_vld && (fis_type == 'h46)
{
IF
:
'FIS'
,
GOTO
:
'NDR:Entry'
},
# 5. fis_first_vld # already assumed && ((fis_type != 'h46)
{
IF
:
'PCTI_XCZ'
,
GOTO
:
'CFIS:Xmit'
},
# 6. pCmdToIssue && xfer_cntr_zero
{
GOTO
:
'P:Idle'
},
#10. (#7-#9 PM, not implemented)
{
LBL
:
'P:StartBitCleared'
,
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear
{
ACT
:
'DMA_ABORT'
},
# dma_cmd_abort (should eventually clear PxCMD.CR)?
{
ACT
:
'PCMD_CR_CLEAR'
},
# pcmd_cr_reset
{
ACT
:
'XFER_CNTR_CLEAR'
},
# clear_xfer_cntr
{
LBL
:
'P:IdleGarbage'
,
ACT
:
'FIS_FIRST_FLUSH'
},
# fis_first_flush (FIFO output has data, but not FIS head
#TODO - add to some error? Now silently skips
{
GOTO
:
'P:Idle'
},
{
LBL
:
'P:Idle'
,
ACT
:
'PCMD_CR_SET'
},
# pcmd_cr_set
{
IF
:
'PXSSTS_DET_NE_3'
,
GOTO
:
'P:NotRunning'
},
# 1. ssts_det!=3, // device detected, phy communication not established
{
IF
:
'PXCI0_NOT_CMDTOISSUE'
,
GOTO
:
'P:FetchCmd'
},
# 2. pxci0 && !pCmdToIssue was pIssueSlot==32, -> p:SelectCmd
{
IF
:
'PCTI_CTBAR_XCZ'
,
GOTO
:
'CFIS:SyncEscape'
},
# 3. pCmdToIssue && ch_r && xfer_cntr_zero
{
IF
:
'FIS_FIRST_INVALID'
,
GOTO
:
'P:IdleGarbage'
},
{
IF
:
'FIS_DATA'
,
GOTO
:
'DR:Entry'
},
# 4. fis_first_vld && (fis_type == 'h46)
{
IF
:
'FIS_ANY'
,
GOTO
:
'NDR:Entry'
},
# 5. fis_first_vld # already assumed && ((fis_type != 'h46)
{
IF
:
'PCTI_XCZ'
,
GOTO
:
'CFIS:Xmit'
},
# 6. pCmdToIssue && xfer_cntr_zero
{
GOTO
:
'P:Idle'
},
#10. (#7-#9 PM, not implemented)
#P:SelectCmd not implemented, using single slot
{
LBL
:
'P:FetchCmd'
,
ACT
:
'FETCH_CMD
'
},
# fetch_cmd (other actions included in ahci_fis_transmit)
{
LBL
:
'P:FetchCmd'
,
ACT
:
'FETCH_CMD
*'
},
# fetch_cmd (other actions included in ahci_fis_transmit)
#ahci_fis_transmit already processes ch_p. ATAPI data is always preloaded, prd - if ch_p
{
IF
:
'CTBAA_CTBAP'
,
GOTO
:
'CFIS:PrefetchACMD'
},
#
1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
#
2. ch_p # Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
#
3. PxTFD.STS.BSY must be set before issuing a command (or now if predicted)
{
IF
:
'CTBAA_CTBAP'
,
GOTO
:
'CFIS:PrefetchACMD'
},
#
1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
#
2. ch_p # Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
#
3. PxTFD.STS.BSY must be set before issuing a command (or now if predicted)
{
LBL
:
'P:StartComm'
,
ACT
:
'SET_STS_7F'
},
# frcv_set_sts_7f
{
ACT
:
'SET_UPDATE_SIG'
},
# #frcv_set_update_sig
{
ACT
:
'XMIT_COMRESET'
},
# Now does it on reset. See if it is possible to transmit COMRESET w/o reset
{
LBL
:
'P:StartComm'
,
ACT
:
'SET_STS_7F'
},
# frcv_set_sts_7f
{
ACT
:
'SET_UPDATE_SIG'
},
# #frcv_set_update_sig
{
ACT
:
'XMIT_COMRESET'
},
# Now does it on reset. See if it is possible to transmit COMRESET w/o reset
{
IF
:
'PXSSTS_DET_EQ_1'
,
GOTO
:
'P:StartComm'
},
{
GOTO
:
'P:NotRunning'
},
#New states, because FIS needs to be read in befor R_OK
{
LBL
:
'P:OkIdle'
,
ACT
:
'R_OK'
},
# send_R_OK to device
{
GOTO
:
'P:Idle'
},
# (was directly from NDR:Accept.4
{
LBL
:
'P:OkNotRunning'
,
ACT
:
'R_OK'
},
# send_R_OK to device
{
GOTO
:
'P:NotRunning'
},
# (was directly from NDR:Accept.4
#P:PowerOn, P;PwerOff,P:PhyListening - not implemented
#FB:* - Not implemented
#PM:* - Not implemented
{
LBL
:
'PM:Aggr'
,
ACT
:
'NOP'
},
# Just as a placeholder
{
GOTO
:
'P:Idle'
},
#1
{
LBL
:
'PM:Aggr'
,
ACT
:
'NOP'
},
# Just as a placeholder
{
GOTO
:
'P:Idle'
},
#1
{
LBL
:
'NDR:Entry'
,
ACT
:
'NOP'
},
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'NDR:Accept'
},
# 4.
{
LBL
:
'NDR:IgnoreNR'
,
ACT
:
'FIS_IOGNORE'
},
# get_ignore This one is not in docs, just to empty FIS FIFO
{
GOTO
:
'P:NotRunning'
},
# (was directly from NDR:Accept.4
{
LBL
:
'NDR:IgnoreIdle'
,
ACT
:
'FIS_IOGNORE'
},
# get_ignore This one is not in docs, just to empty FIS FIFO
{
GOTO
:
'P:Idle'
},
# (was directly from NDR:Accept.4
{
LBL
:
'NDR:Accept'
,
ACT
:
'R_OK'
},
# send_R_OK to device
{
IF
:
'NB_ND_D2HR_PIO'
,
GOTO
:
'NDR:IgnoreIdle'
},
# 2 :((FIS == FIS_D2HR) || (FIS == FIS_PIO)) && !PxTBD.STS.BSY & !PxTBD.STS.DRQ
{
IF
:
'NST_D2HR'
,
GOTO
:
'P:RegFisUpdate'
},
# 3 :!ST && (FIS == FIS_D2HR) TODO: does it mean either BSY or DRQ are 1?
{
IF
:
'NPCMD_FRE'
,
GOTO
:
'NDR:IgnoreNR'
},
# 4 !pcmd_fre (docs: goto P:NotRunning, but we need to clear FIFO)
{
IF
:
'D2HR'
,
GOTO
:
'RegFIS:Entry'
},
# 5 FIS == FIS_D2HR
{
IF
:
'SDB'
,
GOTO
:
'SDB:Entry'
},
# 7 (# 6 skipped)
{
IF
:
'DMA_ACT'
,
GOTO
:
'DX:Entry'
},
# 8 FIS == FIS_DMA_ACT
{
IF
:
'DMA_SETUP'
,
GOTO
:
'DmaSet:Entry'
},
# 9 FIS == FIS_DMA_SETUP
{
IF
:
'BIST_ACT_FE'
,
GOTO
:
'BIST:FarEndLoopback'
},
#10 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{
IF
:
'BIST_ACT'
,
GOTO
:
'BIST:TestOngoing'
},
# 11 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{
IF
:
'PIO_SETUP'
,
GOTO
:
'PIO:Entry'
},
# 12 FIS == FIS_PIO_SETUP
{
GOTO
:
'UFIS:Entry'
},
# 13 Unknown FIS (else)
# {IF: 'FIS_ERR', GOTO:'ERR:Non-Fatal'}, # 1. fis_err
# {IF: 'FIS_FERR', GOTO:'ERR:Fatal'}, # 2. fis_ferr
{
GOTO
:
'NDR:Accept'
},
# 4.
{
LBL
:
'NDR:IgnoreNR'
,
ACT
:
'GET_IGNORE*'
},
# get_ignore This one is not in docs, just to empty FIS FIFO
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'P:OkIdle'
},
#
{
LBL
:
'NDR:IgnoreIdle'
,
ACT
:
'GET_IGNORE*'
},
# get_ignore This one is not in docs, just to empty FIS FIFO
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'P:OkNotRunning'
},
#
{
LBL
:
'NDR:Accept'
,
ACT
:
'NOP'
},
# ******** # send R_OK after reading in FIS: ACT: 'R_OK'}, # send_R_OK to device
{
IF
:
'NB_ND_D2HR_PIO'
,
GOTO
:
'NDR:IgnoreIdle'
},
# 2 :((FIS == FIS_D2HR) || (FIS == FIS_PIO)) && !PxTBD.STS.BSY & !PxTBD.STS.DRQ
{
IF
:
'NST_D2HR'
,
GOTO
:
'P:RegFisUpdate'
},
# 3 :!ST && (FIS == FIS_D2HR) TODO: does it mean either BSY or DRQ are 1?
{
IF
:
'NPCMD_FRE'
,
GOTO
:
'NDR:IgnoreNR'
},
# 4 !pcmd_fre (docs: goto P:NotRunning, but we need to clear FIFO)
{
IF
:
'D2HR'
,
GOTO
:
'RegFIS:Entry'
},
# 5 FIS == FIS_D2HR
{
IF
:
'SDB'
,
GOTO
:
'SDB:Entry'
},
# 7 (# 6 skipped)
{
IF
:
'DMA_ACT'
,
GOTO
:
'DX:EntryIgnore'
},
# 8 FIS == FIS_DMA_ACT
{
IF
:
'DMA_SETUP'
,
GOTO
:
'DmaSet:Entry'
},
# 9 FIS == FIS_DMA_SETUP
{
IF
:
'BIST_ACT_FE'
,
GOTO
:
'BIST:FarEndLoopback'
},
#10 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{
IF
:
'BIST_ACT'
,
GOTO
:
'BIST:TestOngoing'
},
# 11 FIS == FIS_BIST_ACT && |bist_bits TODO:get_ignore to read in FIS
{
IF
:
'PIO_SETUP'
,
GOTO
:
'PIO:Entry'
},
# 12 FIS == FIS_PIO_SETUP
{
GOTO
:
'UFIS:Entry'
},
# 13 Unknown FIS (else)
#5.3.6. Command Transfer State
{
LBL
:
'CFIS:SyncEscape'
,
ACT
:
'SEND_SYNC_ESC'
},
# syncesc_send, should wait (for syncesc_send_done)
{
ACT
:
'SET_UPDATE_SIG'
},
# set_update_sig
{
GOTO
:
'CFIS:Xmit'
},
# 1
{
LBL
:
'CFIS:Xmit'
,
ACT
:
'SET_BSY'
},
# set_bsy
{
ACT
:
'CFIS_XMIT'
},
# cfis_xmit
{
IF
:
'X_RDY_COLLISION'
,
GOTO
:
'P:Idle'
},
# 2. x_rdy_collision_pend
{
IF
:
'SYNCESC_RECV'
,
GOTO
:
'ERR:SyncEscapeRecv'
},
# 4. syncesc_recv
{
IF
:
'FIS_OK'
,
GOTO
:
'CFIS:SUCCESS'
},
# 5. fis_ok
{
GOTO
:
'ERR:Non-fatal'
},
# 6
{
LBL
:
'CFIS:Success'
,
ACT
:
'CLEAR_CMD_TO_ISSUE'
},
# clearCmdToIssue
{
IF
:
'CTBA_B'
,
GOTO
:
'BIST:TestOngoing'
},
# 1. ch_b
{
IF
:
'CTBA_C'
,
GOTO
:
'CFIS:ClearCI'
},
# 2. ch_c
{
IF
:
'CTBAA_CTBAP'
,
GOTO
:
'CFIS:PrefetchACMD'
},
# 3. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
# 4. ch_p # Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
# 6.
{
LBL
:
'CFIS:CLearCI'
,
ACT
:
'PSCI0'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
ACT
:
'CLEAR_BSY_DRQ'
},
# clear_bsy_drq
{
GOTO
:
'PM:Aggr'
},
# 1
{
LBL
:
'CFIS:SyncEscape'
,
ACT
:
'SEND_SYNC_ESC'
},
# syncesc_send, should wait (for syncesc_send_done)
{
ACT
:
'SET_UPDATE_SIG'
},
# set_update_sig
{
GOTO
:
'CFIS:Xmit'
},
# 1
{
LBL
:
'CFIS:Xmit'
,
ACT
:
'SET_BSY'
},
# set_bsy
{
ACT
:
'CFIS_XMIT*'
},
# cfis_xmit
{
IF
:
'X_RDY_COLLISION'
,
GOTO
:
'P:Idle'
},
# 2. x_rdy_collision_pend
{
IF
:
'SYNCESC_ERR'
,
GOTO
:
'ERR:SyncEscapeRecv'
},
# 4. dx_err[0] (reset by new command)
{
IF
:
'FIS_OK'
,
GOTO
:
'CFIS:Success'
},
# 5. fis_ok
{
GOTO
:
'ERR:Non-Fatal'
},
# 6
{
LBL
:
'CFIS:Success'
,
ACT
:
'CLEAR_CMD_TO_ISSUE'
},
# clearCmdToIssue
{
IF
:
'CTBA_B'
,
GOTO
:
'BIST:TestOngoing'
},
# 1. ch_b
{
IF
:
'CTBA_C'
,
GOTO
:
'CFIS:ClearCI'
},
# 2. ch_c
{
IF
:
'CTBAA_CTBAP'
,
GOTO
:
'CFIS:PrefetchACMD'
},
# 3. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
# 4. ch_p # Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
# 6.
{
LBL
:
'CFIS:ClearCI'
,
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
ACT
:
'CLEAR_BSY_DRQ'
},
# clear_bsy_drq
{
GOTO
:
'PM:Aggr'
},
# 1
# As ahci_fis_transmit processes ch_p, GOTO:'CFIS:Prefetch*' can be shortcut to GOTO:'P:Idle'
{
LBL
:
'CFIS:PrefetchACMD'
,
ACT
:
'NOP'
},
# Nothing to do as it is already in memory, fetched together with command
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
# 1. ch_p Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
# 3.
{
LBL
:
'CFIS:PrefetchACMD'
,
ACT
:
'NOP'
},
# Nothing to do as it is already in memory, fetched together with command
{
IF
:
'CTBAP'
,
GOTO
:
'CFIS:PrefetchPRD'
},
# 1. ch_p Note ch_p may be ignored or transition may be ignored
{
GOTO
:
'P:Idle'
},
# 3.
{
LBL
:
'CFIS:PrefetchPRD'
,
ACT
:
'NOP'
},
# ahci_fis_transmit processes ch_p, no more actions needed
{
GOTO
:
'P:Idle'
},
# 1.
{
LBL
:
'CFIS:PrefetchPRD'
,
ACT
:
'NOP'
},
# ahci_fis_transmit processes ch_p, no more actions needed
{
GOTO
:
'P:Idle'
},
# 1.
{
LBL
:
'CFIS:PrefetchData'
,
ACT
:
'NOP'
},
# ahci_fis_transmit-> ahci_dma prefetches data if possible
{
GOTO
:
'P:Idle'
},
# 1.
# {LBL:'CFIS:PrefetchData', ACT: 'NOP'},
# ahci_fis_transmit-> ahci_dma prefetches data if possible
# { GOTO:'P:Idle'},
# 1.
#5.3.7 ATAPI Command Transfer States
{
LBL
:
'ATAPI:Entry'
,
ACT
:
'ATAPI_XMIT
'
},
# atapi_xmit, '0->pXferAtapi[pPmpCur]' is done ahci_fis_transmit.
{
IF
:
'TX_ERR'
,
GOTO
:
'ERR:Fatal'
},
# 1. dx_err[1] (reset by new command)
{
GOTO
:
'PIO:Update'
},
# 2.
{
LBL
:
'ATAPI:Entry'
,
ACT
:
'ATAPI_XMIT
*'
},
# atapi_xmit, '0->pXferAtapi[pPmpCur]' is done ahci_fis_transmit.
{
IF
:
'TX_ERR'
,
GOTO
:
'ERR:Fatal'
},
# 1. dx_err[1] (reset by new command)
{
GOTO
:
'PIO:Update'
},
# 2.
#5.3.8 D2H Register FIS Receive States
{
LBL
:
'RegFIS:Entry'
,
ACT
:
'GET_RFIS'
},
# get_rfis
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'NB_ND'
,
GOTO
:
'RegFIS:ClearCI'
},
# 2. PxTFD.STS.BSY =’0’ and PxTFD.STS.DRQ =’0’
{
GOTO
:
'RegFIS:UpdateSig'
},
# 3.
{
LBL
:
'RegFIS:ClearCI'
,
ACT
:
'UPDATE_PRDBC'
},
# update_prdbc
{
ACT
:
'PSCI0'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
IF
:
'FIS_I'
,
GOTO
:
'RegFIS:SetIntr'
},
# 2. fis_i
{
GOTO
:
'RegFIS:UpdateSig'
},
# 3.
{
LBL
:
'RegFIS:SetIntr'
,
ACT
:
'SIRQ_DHR'
},
# sirq_DHR
{
GOTO
:
'RegFIS:UpdateSig'
},
# 2. (PxIE/IRQ is handled)
{
LBL
:
'RegFIS:Entry'
,
ACT
:
'GET_RFIS*'
},
# get_rfis
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'RegFIS:Accept'
},
#
{
LBL
:
'RegFIS:Accept'
,
ACT
:
'R_OK'
},
# send R_OK
{
ACT
:
'UPDATE_ERR_STS'
},
# update_err_sts
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'NB_ND'
,
GOTO
:
'RegFIS:ClearCI'
},
# 2. PxTFD.STS.BSY =’0’ and PxTFD.STS.DRQ =’0’
{
GOTO
:
'RegFIS:UpdateSig'
},
# 3.
{
LBL
:
'RegFIS:ClearCI'
,
ACT
:
'UPDATE_PRDBC'
},
# update_prdbc
{
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
IF
:
'FIS_I'
,
GOTO
:
'RegFIS:SetIntr'
},
# 2. fis_i
{
GOTO
:
'RegFIS:UpdateSig'
},
# 3.
{
LBL
:
'RegFIS:SetIntr'
,
ACT
:
'SIRQ_DHR'
},
# sirq_DHR
{
GOTO
:
'RegFIS:UpdateSig'
},
# 2. (PxIE/IRQ is handled)
#RegFIS:SetIS, RegFIS:GenIntr are handled by hardware, skipping
{
LBL
:
'RegFIS:UpdateSig'
,
ACT
:
'UPDATE_SIG'
},
# update_sig will only update if pUpdateSig
{
GOTO
:
'PM:Aggr'
},
# 1
{
LBL
:
'RegFIS:UpdateSig'
,
ACT
:
'UPDATE_SIG'
},
# update_sig will only update if pUpdateSig
{
GOTO
:
'PM:Aggr'
},
# 1
#RegFIS:SetSig skipped, done in RegFIS:UpdateSig
#5.3.9 PIO Setup Receive States
{
LBL
:
'PIO:Entry'
,
ACT
:
'GET_PSFIS'
},
# get_psfis, includes all steps 1..9
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'NPD_NCA'
,
GOTO
:
'DX:Entry'
},
# 2. pio_d = 0 && ch_a == 0
{
IF
:
'NPD'
,
GOTO
:
'ATAPI:Entry'
},
# 3. pio_d = 0 , "ch_a == 1" is not needed
{
GOTO
:
'P:Idle'
},
# 4
{
LBL
:
'PIO:Entry'
,
ACT
:
'GET_PSFIS*'
},
# get_psfis, includes all steps 1..9
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'PIO:Accept'
},
{
LBL
:
'PIO:Accept'
,
ACT
:
'R_OK'
},
# get_psfis, includes all steps 1..9
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'NPD_NCA'
,
GOTO
:
'DX:Entry'
},
# 2. pio_d = 0 && ch_a == 0
{
IF
:
'NPD'
,
GOTO
:
'ATAPI:Entry'
},
# 3. pio_d = 0 , "ch_a == 1" is not needed
{
GOTO
:
'P:Idle'
},
# 5.
{
LBL
:
'PIO:Update'
,
ACT
:
'UPDATE_PIO'
},
# update_pio - update PxTFD.STS and PxTFD.ERR from pio_*
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'NB_ND'
,
GOTO
:
'PIO:ClearCI'
},
# 2. PxTFD.STS.BSY =’0’ and PxTFD.STS.DRQ =’0’
{
IF
:
'PIO_I'
,
GOTO
:
'PIO:SetIntr'
},
# 3. pio_i
{
GOTO
:
'P:Idle'
},
# 5.
{
LBL
:
'PIO:ClearCI'
,
ACT
:
'UPDATE_PRDBC'
},
# update_prdbc
{
ACT
:
'PXCI0_CLEAR'
},
# pxci0_clear, reset both (pIssueSlot:=32) and PxCI[0]
{
IF
:
'PIO_I'
,
GOTO
:
'PIO:SetIntr'
},
# 2. pio_i
{
GOTO
:
'PM:Aggr'
},
# 3.
#PIO:Ccc - not implemented
{
LBL
:
'PIO:SetIntr'
,
ACT
:
'SIRQ_PS'
},
# sirq_PS
{
GOTO
:
'PM:Aggr'
},
# 1. (PxIE/IRQ is handled)
#PIO:SetIS, PIO:GenIntr are handled by hardware, skipping
#5.3.10 Data Transmit States
{
LBL
:
'DX:EntryIgnore'
,
ACT
:
'GET_IGNORE*'
},
# Read/Ignore FIS in FIFO (not in docs)
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'DX:Accept'
},
#
{
LBL
:
'DX:Accept'
,
ACT
:
'R_OK'
},
# send R_OK
{
GOTO
:
'DX:Entry'
},
#
{
LBL
:
'DX:Entry'
,
ACT
:
'DMA_PRD_IRQ_CLEAR'
},
# dma_prd_irq_clear (FIS should be accepted/confirmed)
{
IF
:
'PIOX_XFER0'
,
GOTO
:
'PIO:Update'
},
# 1. pPioXfer && xfer_cntr_zero
{
IF
:
'XFER0'
,
GOTO
:
'P:Idle'
},
# 3. xfer_cntr_zero # && !pPioXfer (implied)
{
GOTO
:
'DX:Transmit'
},
# 4.
{
LBL
:
'DX:Transmit'
,
ACT
:
'DX_XMIT*'
},
# dx_transmit
{
IF
:
'SYNCESC_ERR'
,
GOTO
:
'ERR:SyncEscapeRecv'
},
# 1. dx_err[0] (reset by new command)
{
IF
:
'TX_ERR'
,
GOTO
:
'ERR:Fatal'
},
# 1. dx_err[1] (reset by new command)
{
GOTO
:
'DX:UpdateByteCount'
},
# 3. (#2 - skipped PxFBS.EN==1)
{
LBL
:
'DX:UpdateByteCount'
,
ACT
:
'DECR_DWC'
},
# decr_dwc - decrement remaining DWORDS count, increment transferred
{
ACT
:
'UPDATE_PRDBC'
},
# update_prdbc
{
IF
:
'DMA_PRD_IRQ_PEND'
,
GOTO
:
'DX:PrdSetIntr'
},
# 1. dma_prd_irq_pend
{
IF
:
'PIOX'
,
GOTO
:
'PIO:Update'
},
# 2. pPioXfer
{
GOTO
:
'P:Idle'
},
# 4.
{
LBL
:
'DX:PrdSetIntr'
,
ACT
:
'SIRQ_DP'
},
# sirq_DP (if any PRD for this FIS requested PRD interrupt)
{
ACT
:
'DMA_PRD_IRQ_CLEAR'
},
# dma_prd_irq_clear
#DX:PrdSetIS, DX:PrdGenIntr skipped as they are handled at lower level
{
IF
:
'PIOX'
,
GOTO
:
'PIO:Update'
},
# 2. pPioXfer (#1 ->DX:PrdSetIS is handled by hardware)
{
GOTO
:
'P:Idle'
},
# 4.
# 5.3.11 Data Receive States
{
LBL
:
'DR:Entry'
,
ACT
:
'DMA_PRD_IRQ_CLEAR'
},
# dma_prd_irq_clear
{
GOTO
:
'DR:Receive'
},
{
LBL
:
'DR:Receive'
,
ACT
:
'GET_DATA_FIS*'
},
# get_data_fis
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Fatal'
},
# 3. fis_err - checking for errors first to give some time for fis_extra
# to reveal itself from the ahci_dma module (ahci_fis_receive does not need it)
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 3a. fis_ferr
{
IF
:
'FIS_EXTRA'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_extra
{
GOTO
:
'DR:UpdateByteCount'
},
# 2. fis_ok implied
{
LBL
:
'DR:UpdateByteCount'
,
ACT
:
'R_OK'
},
# send_R_OK to device
{
ACT
:
'DECR_DWC'
},
# decr_dwc - decrement remaining DWORDS count, increment transferred
{
ACT
:
'UPDATE_PRDBC'
},
# update_prdbc
{
IF
:
'DMA_PRD_IRQ_PEND'
,
GOTO
:
'DX:PrdSetIntr'
},
# 1. dma_prd_irq_pend
{
IF
:
'PIOX'
,
GOTO
:
'PIO:Update'
},
# 2. pPioXfer (#1 ->DX:PrdSetIS is handled by hardware)
{
GOTO
:
'P:Idle'
},
# 4.
# 5.3.12 DMA Setup Receive States
{
LBL
:
'DmaSet:Entry'
,
ACT
:
'GET_DSFIS*'
},
# get_dsfis
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'DmaSet:Accept'
},
#
{
LBL
:
'DmaSet:Accept'
,
ACT
:
'R_OK'
},
# send R_OK
{
IF
:
'FIS_I'
,
GOTO
:
'DmaSet:SetIntr'
},
# 1. fis_i
{
GOTO
:
'DmaSet:AutoActivate'
},
# 2.
{
LBL
:
'DmaSet:SetIntr'
,
ACT
:
'SIRQ_DS'
},
# sirq_DS DMA Setup FIS received with 'I' bit set
{
GOTO
:
'DmaSet:AutoActivate'
},
# 2. (interrupt is handled by hardware)
#DmaSet:SetIS, DmaSet:GenIntr skipped as they are handled at lower level
{
LBL
:
'DmaSet:AutoActivate'
,
ACT
:
'NOP'
},
#
{
IF
:
'CHW_DMAA'
,
GOTO
:
'DmaSet:SetIntr'
},
# 1. ch_w && dma_a
{
GOTO
:
'P:Idle'
},
# 3.
#5.3.13 Set Device Bits States
{
LBL
:
'SDB:Entry'
,
ACT
:
'GET_SDBFIS*'
},
# get_sdbfis Is in only for Native CC ?
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'SDB:Accept'
},
# 3.
{
LBL
:
'SDB:Accept'
,
ACT
:
'R_OK'
},
# get_sdbfis Is in only for Native CC ?
{
ACT
:
'UPDATE_ERR_STS'
},
# update_err_sts
{
IF
:
'TFD_STS_ERR'
,
GOTO
:
'ERR:FatalTaskfile'
},
# 1. tfd_sts[0]
{
IF
:
'FIS_I'
,
GOTO
:
'SDB:SetIntr'
},
# 3. fis_i
{
GOTO
:
'PM:Aggr'
},
# 4.
{
LBL
:
'SDB:SetIntr'
,
ACT
:
'SIRQ_SDB'
},
# sirq_SDB
{
GOTO
:
'PM:Aggr'
},
# 5.
#5.3.14 Unknown FIS Receive States
{
LBL
:
'UFIS:Entry'
,
ACT
:
'GET_UFIS*'
},
# get_ufis
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'UFIS:Accept'
},
#
{
LBL
:
'UFIS:Accept'
,
ACT
:
'R_OK'
},
# get_ufis
{
ACT
:
'SIRQ_UF'
},
# sirq_UF
{
GOTO
:
'P:Idle'
},
# 1. (IRQ states are handled)
#UFIS:SetIS, UFIS:GenIntr are handled by hardware, skipping
#5.3.15 BIST States
{
LBL
:
'BIST:FarEndLoopback'
,
ACT
:
'GET_IGNORE*'
},
# get_ignore
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'BIST:FarEndLoopbackAccept'
},
# 1. (IRQ states are handled)
{
LBL
:
'BIST:FarEndLoopbackAccept'
,
ACT
:
'R_OK'
},
# send R_OK
{
ACT
:
'SSTS_DET_OFFLINE'
},
# ssts_det_offline
{
GOTO
:
'BIST:TestLoop'
},
# 1.
{
LBL
:
'BIST:TestOngoing'
,
ACT
:
'GET_IGNORE*'
},
# get_ignore
{
IF
:
'FIS_ERR'
,
GOTO
:
'ERR:Non-Fatal'
},
# 1. fis_err
{
IF
:
'FIS_FERR'
,
GOTO
:
'ERR:Fatal'
},
# 2. fis_ferr
{
GOTO
:
'BIST:TestLoopAccept'
},
#
{
LBL
:
'BIST:TestLoopAccept'
,
ACT
:
'R_OK'
},
#
{
GOTO
:
'BIST:TestLoop'
},
#
{
LBL
:
'BIST:TestLoop'
,
ACT
:
'NOP'
},
#
{
GOTO
:
'BIST:TestLoop'
},
#
#5.3.16 Error States
{
LBL
:
'ERR:SyncEscapeRecv'
,
ACT
:
'CLEAR_BSY_DRQ'
},
# clear_bsy_drq
{
ACT
:
'SIRQ_IF'
},
# sirq_IF
{
GOTO
:
'ERR:WaitForClear'
},
{
LBL
:
'ERR:Fatal'
,
ACT
:
'R_ERR'
},
# Send R_ERR to device
{
ACT
:
'SIRQ_IF'
},
# sirq_IF
{
GOTO
:
'ERR:WaitForClear'
},
{
LBL
:
'ERR:FatalTaskfile'
,
ACT
:
'SIRQ_TFE'
},
# sirq_TFE
{
GOTO
:
'ERR:WaitForClear'
},
{
LBL
:
'ERR:WaitForClear'
,
ACT
:
'NOP'
},
#
{
GOTO
:
'ERR:WaitForClear'
},
# Loop until PxCMD.ST is cleared by software
{
LBL
:
'ERR:Non-Fatal'
,
ACT
:
'NOP'
},
# Do anything else here?
{
GOTO
:
'P:Idle'
},
#
]
def
get_cnk
(
start
,
end
,
level
):
result
=
[]
for
i
in
range
(
start
,
end
+
1
-
level
):
if
level
==
1
:
result
.
append
([
i
])
else
:
l
=
get_cnk
(
i
+
1
,
end
,
level
-
1
)
for
r
in
l
:
result
.
append
([
i
]
+
r
)
return
result
def
bin_cnk
(
n
,
k
):
bits
=
get_cnk
(
0
,
n
,
k
)
result
=
[]
for
l
in
bits
:
d
=
0
for
b
in
l
:
d
|=
(
1
<<
b
)
result
.
append
(
d
)
return
result
def
condition_mux_verilog
(
conditions
,
condition_vals
,
module_name
,
fanout
,
file
=
None
):
header_template
=
"""/*******************************************************************************
* Module:
%
s
* Date:
%
s
* Author: auto-generated file, see
%
s
* Description: Select condition
*******************************************************************************/
"""
output reg pio_i, // value of "I" field in received PIO Setup FIS
output reg pio_d, // value of "D" field in received PIO Setup FIS
output [7:0] pio_es, // value of PIO E_Status
`timescale 1ns/1ps
sirq_DHR
fis_i
update_prdbc, // update PRDBC in registers
output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields)
// tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR
module
%
s (
input clk,
input [
%2
d:0] sel,
output condition,"""
v
=
max
(
condition_vals
.
values
())
num_inputs
=
0
;
while
v
:
num_inputs
+=
1
v
>>=
1
maximal_length
=
max
([
len
(
n
)
for
n
in
conditions
])
numregs
=
(
len
(
conditions
)
+
fanout
-
1
)
//
fanout
header
=
header_template
%
(
module_name
,
datetime
.
date
.
today
()
.
isoformat
(),
os
.
path
.
basename
(
__file__
),
module_name
,
num_inputs
-
1
)
print
(
header
,
file
=
file
)
for
input_name
in
conditions
[:
len
(
conditions
)
-
1
]:
print
(
" input
%
s,"
%
(
input_name
),
file
=
file
)
print
(
" input
%
s);
\n
"
%
(
conditions
[
-
1
]),
file
=
file
)
print
(
" wire [
%2
d:0] masked;"
%
(
len
(
conditions
)
-
1
),
file
=
file
)
if
numregs
>
1
:
print
(
" reg [
%2
d:0] cond_r;
\n
"
%
(
numregs
-
1
),
file
=
file
)
else
:
print
(
" reg cond_r;
\n
"
,
file
=
file
)
if
numregs
>
1
:
print
(
" assign condition = |cond_r;
\n
"
,
file
=
file
)
else
:
print
(
" assign condition = cond_r;
\n
"
,
file
=
file
)
{LBL:'P:RegFisUpdate', ACT: 'GET_SIG'}, # update_sig
for
b
in
range
(
len
(
conditions
)):
print
(
" assign masked[
%2
d] =
%
s
%
s"
%
(
b
,
conditions
[
b
]
,
" "
*
(
maximal_length
-
len
(
conditions
[
b
]))),
end
=
""
,
file
=
file
)
d
=
condition_vals
[
conditions
[
b
]]
for
nb
in
range
(
num_inputs
-
1
,
-
1
,
-
1
):
if
d
&
(
1
<<
nb
):
print
(
" && sel[
%2
d]"
%
(
nb
),
end
=
""
,
file
=
file
)
print
(
";"
,
file
=
file
)
print
(
"
\n
always @(posedge clk) begin"
,
file
=
file
)
for
nb
in
range
(
numregs
):
ll
=
nb
*
fanout
hl
=
min
(
ll
+
fanout
,
len
(
conditions
))
-
1
if
numregs
>
1
:
print
(
" cond_r[
%2
d] <= "
%
(
nb
),
end
=
""
,
file
=
file
)
else
:
print
(
" cond_r <= "
,
end
=
""
,
file
=
file
)
if
hl
>
ll
:
print
(
"|masked[
%2
d:
%2
d];"
%
(
hl
,
ll
),
file
=
file
)
else
:
print
(
" masked[
%2
d];"
%
(
ll
),
file
=
file
)
print
(
" end"
,
file
=
file
)
print
(
"endmodule"
,
file
=
file
)
input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
{IF: 'CTBAA_CTBAP', ACT:'CFIS:PrefetchACMD'},#1. ch_a && ch_p # Note ch_p may be ignored or transition may be ignored
{IF: 'CTBAP', ACT:'CFIS:PrefetchPRD'}, #2. ch_p # Note ch_p may be ignored or transition may be ignored
def
action_decoder_verilog
(
actions
,
action_vals
,
module_name
,
file
=
None
):
header_template
=
"""/*******************************************************************************
* Module:
%
s
* Date:
%
s
* Author: auto-generated file, see
%
s
* Description: Decode sequencer code to 1-hot actions
*******************************************************************************/
`timescale 1ns/1ps
input ch_c, // Clear busy upon R_OK for this FIS
input ch_b, // Built-in self test command
input ch_r, // reset - may need to send SYNC escape before this command
input ch_p, // prefetchable - only used with non-zero PRDTL or ATAPI bit set
input ch_w, // Write: system memory -> device
input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command
input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal,
module
%
s (
input clk,
input enable,
input [
%2
d:0] data,"""
v
=
max
(
action_vals
.
values
())
num_inputs
=
0
;
while
v
:
num_inputs
+=
1
v
>>=
1
names
=
[]
for
a
in
actions
[
1
:]:
if
a
.
endswith
(
"*"
):
names
.
append
(
a
[
0
:
-
1
])
else
:
names
.
append
(
a
)
maximal_length
=
max
([
len
(
n
)
for
n
in
names
])
header
=
header_template
%
(
module_name
,
datetime
.
date
.
today
()
.
isoformat
(),
os
.
path
.
basename
(
__file__
),
module_name
,
num_inputs
-
1
)
print
(
header
,
file
=
file
)
for
output_name
in
names
[:
len
(
names
)
-
1
]:
print
(
" output reg
%
s,"
%
(
output_name
),
file
=
file
)
print
(
" output reg
%
s);
\n
"
%
(
names
[
-
1
]),
file
=
file
)
print
(
" always @(posedge clk) begin"
,
file
=
file
)
for
i
,
name
in
enumerate
(
names
):
# i is one less than action_vals index
d
=
action_vals
[
actions
[
i
+
1
]]
print
(
"
%
s"
%
(
name
+
" <= "
+
(
" "
*
(
maximal_length
-
len
(
name
)))),
end
=
""
,
file
=
file
)
print
(
"enable"
,
end
=
""
,
file
=
file
)
for
nb
in
range
(
num_inputs
-
1
,
-
1
,
-
1
):
if
d
&
(
1
<<
nb
):
print
(
" && data[
%2
d]"
%
(
nb
),
end
=
""
,
file
=
file
)
print
(
";"
,
file
=
file
)
print
(
" end"
,
file
=
file
)
print
(
"endmodule"
,
file
=
file
)
#print (sequence)
ln
=
0
while
ln
<
len
(
sequence
):
if
ADDR
in
sequence
[
ln
]:
while
ln
<
sequence
[
ln
][
ADDR
]:
sequence
.
insert
(
ln
,{})
ln
+=
1
if
sequence
[
ln
][
ADDR
]
<
ln
:
print
(
"Can not place '
%
s' at line #
%
d, it is already
%
d"
%
(
sequence
[
ln
],
sequence
[
ln
][
ADDR
],
ln
))
ln
+=
1
fis_ok
syncesc_recv
x_rdy_collision_pend
input cfis_xmit, // transmit command (wait for dma_ct_busy == 0)
labels
=
{}
jumps
=
set
()
for
ln
,
line
in
enumerate
(
sequence
):
if
LBL
in
line
:
label
=
line
[
LBL
]
if
label
in
labels
:
print
(
"Duplicate label '
%
s': line #
%
d and line #
%
d"
%
(
label
,
labels
[
label
],
ln
))
else
:
labels
[
label
]
=
ln
if
GOTO
in
line
:
jumps
.
add
(
line
[
GOTO
])
input syncesc_send_done, // "SYNC escape until the interface is quiescent..."
#Using lists, not sets to preserve order
sort_actions
=
False
sort_conditions
=
False
if
not
actions
:
sort_actions
=
True
for
ln
,
line
in
enumerate
(
sequence
):
if
ACT
in
line
:
if
not
line
[
ACT
]
in
actions
:
actions
.
append
(
line
[
ACT
])
if
not
conditions
:
sort_conditions
=
True
for
ln
,
line
in
enumerate
(
sequence
):
if
IF
in
line
:
if
not
line
[
IF
]
in
conditions
:
conditions
.
append
(
line
[
IF
])
set_update_sig
bist_bits (use get_ignore to read in BIST FIS)
get_ignore
output send_R_OK, // Should it be originated in this layer SM?
output send_R_ERR,
print
(
"Checking for undefined labels:"
)
undef_jumps
=
[]
for
label
in
jumps
:
if
not
label
in
labels
:
undef_jumps
.
append
(
label
)
if
undef_jumps
:
print
(
"Undefined jumps:"
)
for
i
,
jump
in
enumerate
(
undef_jumps
):
print
(
"
%
d: '
%
s'"
%
(
i
,
jump
))
else
:
print
(
"All jumps are to defined labels"
)
print
(
"Checking for unused labels:"
)
unused_labels
=
[]
for
label
in
labels
:
if
not
label
in
jumps
:
unused_labels
.
append
(
label
)
if
unused_labels
:
print
(
"Unused labels:"
)
for
i
,
label
in
enumerate
(
unused_labels
):
print
(
"
%
d: '
%
s'"
%
(
i
,
label
))
else
:
print
(
"All labels are used"
)
wait_actions
=
[]
fast_actions
=
[]
for
a
in
actions
:
if
a
.
endswith
(
"*"
):
# wait_actions.append(a[:len(a)-1])
wait_actions
.
append
(
a
)
else
:
fast_actions
.
append
(
a
)
if
sort_actions
:
wait_actions
.
sort
()
fast_actions
.
sort
()
if
'NOP'
in
fast_actions
:
nop
=
fast_actions
.
pop
(
fast_actions
.
index
(
'NOP'
))
fast_actions
=
[
nop
]
+
fast_actions
actions
=
fast_actions
+
wait_actions
if
sort_conditions
:
conditions
.
sort
()
#Assign values to actions
action_vals
=
{}
vals
=
bin_cnk
(
*
actions_cnk
)
for
i
,
v
in
enumerate
(
actions
):
action_vals
[
v
]
=
vals
[
i
]
#Assign values to conditions
condition_vals
=
{}
vals
=
bin_cnk
(
*
conditions_cnk
)
for
i
,
v
in
enumerate
(
conditions
):
condition_vals
[
v
]
=
vals
[
i
]
print
(
"Number of lines :
%
d"
%
(
len
(
sequence
)))
print
(
"Number of labels :
%
d"
%
(
len
(
labels
)))
print
(
"Number of actions :
%
d"
%
(
len
(
actions
)))
print
(
"Number of conditions :
%
d"
%
(
len
(
conditions
)))
#print ("\nActions:")
#for i,a in enumerate(actions):
# print ("%02d: %s"%(i,a))
print
(
"
\n
Actions that do not wait for done (
%
d):"
%
(
len
(
fast_actions
)))
for
i
,
a
in
enumerate
(
fast_actions
):
# print ("%02d: %s"%(i,a))
print
(
"
%
s"
%
(
a
))
print
(
"
\n
Actions that wait for done (
%
d):"
%
(
len
(
wait_actions
)))
for
i
,
a
in
enumerate
(
wait_actions
):
# print ("%02d: %s"%(i,a))
print
(
"
%
s"
%
(
a
))
input fis_ok, // FIS done, checksum OK reset by starting a new get FIS
input fis_err, // FIS done, checksum ERROR reset by starting a new get FIS
input fis_ferr, // FIS done, fatal error - FIS too long
input fetch_cmd, // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
print
(
"
\n
Conditions(
%
d):"
%
(
len
(
conditions
)))
for
i
,
c
in
enumerate
(
conditions
):
# print ("%02d: %s"%(i,c))
print
(
"
%
s"
%
(
c
))
input fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*'
input [7:0] fis_type, // FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
print
(
"action_vals="
,
action_vals
)
print
(
"condition_vals="
,
condition_vals
)
pcmd_cr_set, // command list run set
clear_xfer_cntr
pcmd_cr_reset
frcv_clear_xfer_cntr
dma_cmd_abort
input fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*'
input [7:0] fis_type, // FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld'
#for i, line in enumerate(sequence):
# print ("%03x: %s"%(i,line))
serr_diag_X ==0 , fis_first_vld,
(pIssueSlot==32) is the same as (pxci0 == 0), use pxci0_clear (pIssueSlot:=32)
localparam LABEL_POR = 11'h0;
localparam LABEL_HBA_RST = 11'h10;
localparam LABEL_PORT_RST = 11'h20;
if
not
action_decoder_verilog_path
:
action_decoder_verilog
(
actions
,
action_vals
,
action_decoder_module_name
)
else
:
with
open
(
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
action_decoder_verilog_path
)),
"w"
)
as
out_file
:
action_decoder_verilog
(
actions
,
action_vals
,
action_decoder_module_name
,
out_file
)
print
(
"AHCI FSM actions decoder is written to
%
s"
%
(
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
action_decoder_verilog_path
))))
if
not
condition_mux_verilog_path
:
condition_mux_verilog
(
conditions
,
condition_vals
,
condition_mux_module_name
,
condition_mux_fanout
)
else
:
with
open
(
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
condition_mux_verilog_path
)),
"w"
)
as
out_file
:
condition_mux_verilog
(
conditions
,
condition_vals
,
condition_mux_module_name
,
condition_mux_fanout
,
out_file
)
print
(
"AHCI FSM conditions multiplexer is written to
%
s"
%
(
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
condition_mux_verilog_path
))))
"""
\ No newline at end of file
#condition_mux_verilog(conditions, condition_vals, 'condition_mux',100, file=None)
\ No newline at end of file
host/link.v
View file @
17e832f8
...
...
@@ -722,7 +722,7 @@ begin
HOST_LINK_TITLE
=
"From device - received data"
;
HOST_LINK_DATA
=
data_out
;
$
display
(
"[Host] LINK: %s = %h @%t"
,
HOST_LINK_TITLE
,
HOST_LINK_DATA
,
$
time
)
;
`endif
//
`endif
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment