Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ycai
simbricks
Commits
d7e300bd
Commit
d7e300bd
authored
Jun 12, 2020
by
Antoine Kaufmann
Browse files
corundum: checkpoint
parent
3db9ec7d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
249 additions
and
26 deletions
+249
-26
corundum/coord.h
corundum/coord.h
+98
-0
corundum/corundum_verilator.cpp
corundum/corundum_verilator.cpp
+104
-10
corundum/debug.h
corundum/debug.h
+5
-0
corundum/dma.cpp
corundum/dma.cpp
+19
-4
corundum/dma.h
corundum/dma.h
+12
-6
corundum/mem.cpp
corundum/mem.cpp
+10
-5
corundum/rtl/interface.v
corundum/rtl/interface.v
+1
-1
No files found.
corundum/coord.h
0 → 100644
View file @
d7e300bd
#ifndef COORD_H_
#define COORD_H_
#include <deque>
#include <map>
#include <iostream>
#include "debug.h"
class
DMAOp
;
void
pci_dma_issue
(
DMAOp
*
op
);
void
pci_msi_issue
(
uint8_t
vec
);
class
PCICoordinator
{
protected:
struct
PCIOp
{
union
{
DMAOp
*
dma_op
;
uint32_t
msi_vec
;
};
bool
isDma
;
bool
ready
;
};
std
::
deque
<
PCIOp
*>
queue
;
std
::
map
<
DMAOp
*
,
PCIOp
*>
dmamap
;
void
process
()
{
PCIOp
*
op
;
while
(
!
queue
.
empty
())
{
op
=
queue
.
front
();
if
(
!
op
->
ready
)
break
;
queue
.
pop_front
();
if
(
!
op
->
isDma
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
"issuing msi "
<<
op
->
msi_vec
<<
std
::
endl
;
#endif
pci_msi_issue
(
op
->
msi_vec
);
}
else
{
#ifdef COORD_DEBUG
std
::
cout
<<
"issuing dma "
<<
op
->
dma_op
<<
std
::
endl
;
#endif
pci_dma_issue
(
op
->
dma_op
);
dmamap
.
erase
(
op
->
dma_op
);
}
delete
op
;
}
}
public:
void
dma_register
(
DMAOp
*
dma_op
,
bool
ready
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
"registering dma op "
<<
dma_op
<<
" "
<<
ready
<<
std
::
endl
;
#endif
PCIOp
*
op
=
new
PCIOp
;
op
->
dma_op
=
dma_op
;
op
->
isDma
=
true
;
op
->
ready
=
ready
;
queue
.
push_back
(
op
);
dmamap
[
dma_op
]
=
op
;
process
();
}
void
dma_mark_ready
(
DMAOp
*
op
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
"readying dma op "
<<
op
<<
std
::
endl
;
#endif
dmamap
[
op
]
->
ready
=
true
;
process
();
}
void
msi_enqueue
(
uint32_t
vec
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
"enqueuing MSI "
<<
vec
<<
std
::
endl
;
#endif
PCIOp
*
op
=
new
PCIOp
;
op
->
msi_vec
=
vec
;
op
->
isDma
=
false
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
process
();
}
};
#endif
corundum/corundum_verilator.cpp
View file @
d7e300bd
...
...
@@ -11,7 +11,9 @@ extern "C" {
#include "verilated.h"
#include "verilated_vcd_c.h"
#include "debug.h"
#include "corundum.h"
#include "coord.h"
#include "dma.h"
#include "mem.h"
...
...
@@ -408,6 +410,7 @@ void pci_dma_issue(DMAOp *op)
pci_dma_pending
.
insert
(
op
);
}
static
void
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
)
{
DMAOp
*
op
=
(
DMAOp
*
)
(
uintptr_t
)
rc
->
req_id
;
...
...
@@ -591,11 +594,13 @@ class EthernetTx {
send
->
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SEND
|
COSIM_ETH_PROTO_D2N_OWN_NET
;
#ifdef ETH_DEBUG
std
::
cerr
<<
"EthernetTx: packet len="
<<
std
::
hex
<<
packet_len
<<
" "
;
for
(
size_t
i
=
0
;
i
<
packet_len
;
i
++
)
{
std
::
cerr
<<
(
unsigned
)
packet_buf
[
i
]
<<
" "
;
}
std
::
cerr
<<
std
::
endl
;
#endif
}
void
step
()
...
...
@@ -643,11 +648,13 @@ class EthernetRx {
packet_len
=
len
;
memcpy
(
packet_buf
,
data
,
len
);
#ifdef ETH_DEBUG
std
::
cerr
<<
"EthernetRx: packet len="
<<
std
::
hex
<<
packet_len
<<
" "
;
for
(
size_t
i
=
0
;
i
<
packet_len
;
i
++
)
{
std
::
cerr
<<
(
unsigned
)
packet_buf
[
i
]
<<
" "
;
}
std
::
cerr
<<
std
::
endl
;
#endif
}
void
step
()
...
...
@@ -656,18 +663,24 @@ class EthernetRx {
// we have data to send
if
(
packet_off
!=
0
&&
!
top
.
rx_axis_tready
)
{
// no ready signal, can't advance
std
::
cerr
<<
"eth rx: no ready"
<<
std
::
endl
;
}
else
if
(
packet_off
==
packet_len
)
{
// done with packet
#ifdef ETH_DEBUG
std
::
cerr
<<
"EthernetRx: finished packet"
<<
std
::
endl
;
#endif
top
.
rx_axis_tvalid
=
0
;
top
.
rx_axis_tlast
=
0
;
packet_off
=
packet_len
=
0
;
}
else
{
// put out more packet data
#ifdef ETH_DEBUG
std
::
cerr
<<
"EthernetRx: push flit "
<<
packet_off
<<
std
::
endl
;
#endif
top
.
rx_axis_tkeep
=
0
;
top
.
rx_axis_tdata
=
0
;
for
(
size_t
i
=
0
;
i
<
8
&&
packet_off
<
packet_len
;
i
++
)
{
size_t
i
;
for
(
i
=
0
;
i
<
8
&&
packet_off
<
packet_len
;
i
++
)
{
top
.
rx_axis_tdata
|=
((
uint64_t
)
packet_buf
[
packet_off
])
<<
(
i
*
8
);
top
.
rx_axis_tkeep
|=
(
1
<<
i
);
...
...
@@ -714,12 +727,89 @@ static void poll_n2d(EthernetRx &rx)
nicif_n2d_next
();
}
static
void
msi_issue
(
uint8_t
vec
)
#if 0
class PCICoordinator {
protected:
struct PCIOp {
union {
DMAOp *dma_op;
uint32_t msi_vec;
};
bool isDma;
bool ready;
};
Vinterface ⊤
std::deque<PCIOp *> queue;
std::map<DMAOp *, PCIOp *> dmamap;
void process()
{
PCIOp *op;
while (queue.empty()) {
op = queue.front();
if (!op->ready)
break;
queue.pop_front();
if (!op->isDma) {
pci_msi_issue(op->msi_vec);
delete op;
} else {
pci_dma_issue(op->dma_op);
dmamap.erase(op->dma_op);
delete op;
}
}
}
public:
PCICoordinator(Vinterface &top_)
: top(top_)
{
}
void dma_register(DMAOp *dma_op, bool ready)
{
PCIOp *op = new PCIOp;
op->dma_op = vec;
op->isDma = true;
op->ready = ready;
queue.push_back(op);
dmamap[op] = dma_op;
process();
}
void dma_mark_ready(DMAOp *op)
{
dmamap[op]->ready = true;
process();
}
void msi_enqueue(uint32_t vec)
{
PCIOp *op = new PCIOp;
op->msi_vec = vec;
op->isDma = false;
op->ready = true;
queue.push_back(op);
process();
}
};
#endif
void
pci_msi_issue
(
uint8_t
vec
)
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
nicsim_d2h_alloc
();
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
;
#ifdef MSI_DEBUG
std
::
cerr
<<
"MSI interrupt vec="
<<
(
int
)
vec
<<
std
::
endl
;
#endif
intr
=
&
msg
->
interrupt
;
intr
->
vector
=
vec
;
...
...
@@ -730,16 +820,19 @@ static void msi_issue(uint8_t vec)
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
static
void
msi_step
(
Vinterface
&
top
)
static
void
msi_step
(
Vinterface
&
top
,
PCICoordinator
&
coord
)
{
if
(
!
top
.
msi_irq
)
return
;
#ifdef MSI_DEBUG
std
::
cerr
<<
"msi_step: MSI interrupt raw vec="
<<
(
int
)
top
.
msi_irq
<<
std
::
endl
;
#endif
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
{
if
(
!
((
1ULL
<<
i
)
&
top
.
msi_irq
))
continue
;
msi_issue
(
i
);
coord
.
msi_enqueue
(
i
);
}
}
...
...
@@ -884,10 +977,11 @@ int main(int argc, char *argv[])
MemWriter
mem_data_writer
(
p_mem_write_data_dma
);
MemReader
mem_data_reader
(
p_mem_read_data_dma
);
DMAReader
dma_read_ctrl
(
"read ctrl"
,
p_dma_read_ctrl
,
mem_control_writer
);
DMAWriter
dma_write_ctrl
(
"write ctrl"
,
p_dma_write_ctrl
,
mem_control_reader
);
DMAReader
dma_read_data
(
"read data"
,
p_dma_read_data
,
mem_data_writer
);
DMAWriter
dma_write_data
(
"write data"
,
p_dma_write_data
,
mem_data_reader
);
PCICoordinator
pci_coord
;
DMAReader
dma_read_ctrl
(
"read ctrl"
,
p_dma_read_ctrl
,
mem_control_writer
,
pci_coord
);
DMAWriter
dma_write_ctrl
(
"write ctrl"
,
p_dma_write_ctrl
,
mem_control_reader
,
pci_coord
);
DMAReader
dma_read_data
(
"read data"
,
p_dma_read_data
,
mem_data_writer
,
pci_coord
);
DMAWriter
dma_write_data
(
"write data"
,
p_dma_write_data
,
mem_data_reader
,
pci_coord
);
EthernetTx
tx
(
*
top
);
EthernetRx
rx
(
*
top
);
...
...
@@ -930,7 +1024,7 @@ int main(int argc, char *argv[])
tx
.
step
();
rx
.
step
();
msi_step
(
*
top
);
msi_step
(
*
top
,
pci_coord
);
/* raising edge */
top
->
clk
=
!
top
->
clk
;
...
...
corundum/debug.h
0 → 100644
View file @
d7e300bd
//#define COORD_DEBUG 1
//#define ETH_DEBUG 1
//#define MSI_DEBUG 1
//#define DMA_DEBUG 1
//#define MEM_DEBUG 1
corundum/dma.cpp
View file @
d7e300bd
#include <iostream>
#include "debug.h"
#include "corundum.h"
#include "dma.h"
#include "mem.h"
void
DMAReader
::
step
()
{
p
.
dma_ready
=
1
;
...
...
@@ -17,11 +19,14 @@ void DMAReader::step()
op
->
tag
=
p
.
dma_tag
;
op
->
write
=
false
;
pending
.
insert
(
op
);
/*std::cout << "dma[" << label << "] op " << op->dma_addr << " -> " <<
#ifdef DMA_DEBUG
std
::
cout
<<
"dma["
<<
label
<<
"] op "
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
" len=" << op->len << " tag=" << (int) op->tag << std::endl;*/
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
#endif
pci_dma_issue
(
op
);
coord
.
dma_register
(
op
,
true
);
}
p
.
dma_status_valid
=
0
;
...
...
@@ -64,10 +69,14 @@ void DMAWriter::step()
op
->
tag
=
p
.
dma_tag
;
op
->
write
=
true
;
pending
.
insert
(
op
);
#ifdef DMA_DEBUG
std
::
cout
<<
"dma write ["
<<
label
<<
"] op "
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
#endif
coord
.
dma_register
(
op
,
false
);
mr
.
op_issue
(
op
);
}
...
...
@@ -76,7 +85,9 @@ void DMAWriter::step()
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
#ifdef DMA_DEBUG
std
::
cout
<<
"dma write ["
<<
label
<<
"] status complete "
<<
op
->
dma_addr
<<
std
::
endl
;
#endif
p
.
dma_status_valid
=
1
;
p
.
dma_status_tag
=
op
->
tag
;
...
...
@@ -87,12 +98,16 @@ void DMAWriter::step()
void
DMAWriter
::
pci_op_complete
(
DMAOp
*
op
)
{
#ifdef DMA_DEBUG
std
::
cout
<<
"dma write ["
<<
label
<<
"] pci complete "
<<
op
->
dma_addr
<<
std
::
endl
;
#endif
completed
.
push_back
(
op
);
}
void
DMAWriter
::
mem_op_complete
(
DMAOp
*
op
)
{
#ifdef DMA_DEBUG
std
::
cout
<<
"dma write ["
<<
label
<<
"] mem complete "
<<
op
->
dma_addr
<<
std
::
endl
;
pci_dma_issue
(
op
);
#endif
coord
.
dma_mark_ready
(
op
);
}
corundum/dma.h
View file @
d7e300bd
...
...
@@ -7,6 +7,9 @@
#include "Vinterface.h"
#include "verilated.h"
#include "debug.h"
#include "coord.h"
#define MAX_DMA_LEN 2048
class
DMAEngine
;
...
...
@@ -56,9 +59,10 @@ struct DMAOp {
class
DMAEngine
{
protected:
DMAPorts
&
p
;
PCICoordinator
&
coord
;
DMAEngine
(
DMAPorts
&
p_
)
:
p
(
p_
)
{
}
DMAEngine
(
DMAPorts
&
p_
,
PCICoordinator
&
coord_
)
:
p
(
p_
)
,
coord
(
coord_
)
{
}
public:
virtual
void
pci_op_complete
(
DMAOp
*
op
)
=
0
;
...
...
@@ -73,8 +77,9 @@ class DMAReader : public DMAEngine {
MemWriter
&
mw
;
public:
DMAReader
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemWriter
&
mw_
)
:
DMAEngine
(
p_
),
label
(
label_
),
mw
(
mw_
)
DMAReader
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemWriter
&
mw_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mw
(
mw_
)
{
}
...
...
@@ -91,8 +96,9 @@ class DMAWriter : public DMAEngine {
MemReader
&
mr
;
public:
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
)
:
DMAEngine
(
p_
),
label
(
label_
),
mr
(
mr_
)
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mr
(
mr_
)
{
}
...
...
corundum/mem.cpp
View file @
d7e300bd
#include <iostream>
#include "debug.h"
#include "mem.h"
#include "dma.h"
...
...
@@ -49,6 +50,8 @@ void MemWriter::step()
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
p
.
mem_valid
=
0
;
for
(
size_t
i
=
0
;
i
<
data_byte_width
/
4
;
i
++
)
p
.
mem_data
[
i
]
=
0
;
/* put data bytes in the right places */
...
...
@@ -57,9 +60,6 @@ void MemWriter::step()
data_byte_width
-
data_offset
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
size_t
byte_off
=
off
%
4
;
// first clear data byte
p
.
mem_data
[
off
/
4
]
&=
~
(
0xffu
<<
(
byte_off
*
8
));
// then set data byte
p
.
mem_data
[
off
/
4
]
|=
(((
uint32_t
)
cur
->
data
[
i
])
<<
(
byte_off
*
8
));
p
.
mem_be
[
off
/
32
]
|=
(
1
<<
(
off
%
32
));
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
...
...
@@ -96,7 +96,9 @@ void MemReader::step()
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
if
(
cur
&&
p
.
mem_resvalid
)
{
#ifdef MEM_DEBUG
std
::
cerr
<<
"completed read from: "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
#endif
p
.
mem_valid
=
0
;
/*for (size_t i = 0; i < 32; i++)
std::cerr << " val = " << p.mem_data[i] << std::endl;*/
...
...
@@ -118,11 +120,12 @@ void MemReader::step()
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
#ifdef MEM_DEBUG
std
::
cerr
<<
"issuing read from "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
std
::
cerr
<<
" off="
<<
data_offset
<<
std
::
endl
;
#endif
/*if (cur->len > data_byte_width - data_offset) {
std::cerr << "MemReader::step: cannot be written in one cycle TODO" << std::endl;
...
...
@@ -168,6 +171,8 @@ void MemReader::step()
void
MemReader
::
op_issue
(
DMAOp
*
op
)
{
#ifdef MEM_DEBUG
std
::
cerr
<<
"enqueued read from "
<<
op
->
ram_addr
<<
std
::
endl
;
#endif
pending
.
push_back
(
op
);
}
corundum/rtl/interface.v
View file @
d7e300bd
...
...
@@ -103,7 +103,7 @@ module interface #
// Log desc block size field width
parameter
LOG_BLOCK_SIZE_WIDTH
=
2
,
/* this one is not explicitly set */
// Enable PTP timestamping
parameter
PTP_TS_ENABLE
=
1
,
parameter
PTP_TS_ENABLE
=
0
,
// PTP timestamp width
parameter
PTP_TS_WIDTH
=
96
,
// Enable TX checksum offload
...
...
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