Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cMIPS
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Roberto Hexsel
cMIPS
Commits
de9f9e78
Commit
de9f9e78
authored
Apr 11, 2016
by
Roberto Hexsel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
moved IO addresses to include SDRAM
parent
fbafc894
Pipeline
#2372
skipped
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
204 additions
and
73 deletions
+204
-73
cMIPS/tests/lwFWDsw.s
cMIPS/tests/lwFWDsw.s
+5
-0
cMIPS/tests/mmu_tlbwi.expected
cMIPS/tests/mmu_tlbwi.expected
+3
-3
cMIPS/vhdl/packageMemory.vhd
cMIPS/vhdl/packageMemory.vhd
+6
-1
cMIPS/vhdl/sdram.vhd
cMIPS/vhdl/sdram.vhd
+64
-45
cMIPS/vhdl/tb_cMIPS.vhd
cMIPS/vhdl/tb_cMIPS.vhd
+126
-24
No files found.
cMIPS/tests/lwFWDsw.s
View file @
de9f9e78
...
...
@@ -21,6 +21,11 @@ snd: sw $3, 4($15) # mem[i+1] <= count
slt
$
8
,
$
3
,
$
9
#
reached
10
rounds
?
bne
$
8
,
$
0
,
snd
#
no
,
continue
nop
nop
nop
nop
nop
wait
nop
.
end
_start
cMIPS/tests/mmu_tlbwi.expected
View file @
de9f9e78
...
...
@@ -8,9 +8,9 @@
00000007
00000047
1
0f
000000
00
3c
0007
00
3c
0047
3c
000000
00
f0
0007
00
f0
0047
2
00014000
00001016
...
...
cMIPS/vhdl/packageMemory.vhd
View file @
de9f9e78
...
...
@@ -44,9 +44,11 @@ package p_MEMORY is
constant
x_INST_MEM_SZ
:
reg32
:
=
x"00004000"
;
constant
x_DATA_BASE_ADDR
:
reg32
:
=
x"00010000"
;
constant
x_DATA_MEM_SZ
:
reg32
:
=
x"00008000"
;
constant
x_IO_BASE_ADDR
:
reg32
:
=
x"
0F
000000"
;
constant
x_IO_BASE_ADDR
:
reg32
:
=
x"
3c
000000"
;
constant
x_IO_MEM_SZ
:
reg32
:
=
x"00002000"
;
constant
x_IO_ADDR_RANGE
:
reg32
:
=
x"00000020"
;
constant
x_SDRAM_BASE_ADDR
:
reg32
:
=
x"04000000"
;
constant
x_SDRAM_MEM_SZ
:
reg32
:
=
x"02000000"
;
constant
x_EXCEPTION_0000
:
reg32
:
=
x"00000130"
;
-- TLBrefill
constant
x_EXCEPTION_0100
:
reg32
:
=
x"00000200"
;
-- CacheError
constant
x_EXCEPTION_0180
:
reg32
:
=
x"00000280"
;
-- generalExcpHandler
...
...
@@ -63,6 +65,9 @@ package p_MEMORY is
constant
DATA_BASE_ADDR
:
integer
:
=
to_integer
(
signed
(
x_DATA_BASE_ADDR
));
constant
DATA_MEM_SZ
:
integer
:
=
to_integer
(
signed
(
x_DATA_MEM_SZ
));
constant
SDRAM_BASE_ADDR
:
integer
:
=
to_integer
(
signed
(
x_SDRAM_BASE_ADDR
));
constant
SDRAM_MEM_SZ
:
integer
:
=
to_integer
(
signed
(
x_SDRAM_MEM_SZ
));
constant
IO_BASE_ADDR
:
integer
:
=
to_integer
(
signed
(
x_IO_BASE_ADDR
));
constant
IO_MEM_SZ
:
integer
:
=
to_integer
(
signed
(
x_IO_MEM_SZ
));
constant
IO_ADDR_RANGE
:
integer
:
=
to_integer
(
signed
(
x_IO_ADDR_RANGE
));
...
...
cMIPS/vhdl/sdram.vhd
View file @
de9f9e78
...
...
@@ -56,8 +56,13 @@ entity SDRAM_controller is
saddr
:
out
reg12
;
-- ram side address
sdata
:
inout
reg16
);
-- ram side data
constant
REFRESH_doit
:
integer
:
=
704
;
-- force a refresh every 704 cycles
-- constant RESET_INTERVAL : integer := 5000; -- reset after 100us = 5.000*20n
-- constant REFRESH_INTERVAL : integer := 704;-- do a refresh every 704 cycles
constant
RESET_INTERVAL
:
integer
:
=
5
;
-- reset after 100us = 5.000*20n
constant
REFRESH_INTERVAL
:
integer
:
=
7
;
-- do a refresh every 704 cycles
subtype
cmd_index
is
integer
range
0
to
13
;
constant
cDSL
:
cmd_index
:
=
0
;
...
...
@@ -85,10 +90,40 @@ entity SDRAM_controller is
end
record
;
type
t_cmd_mem
is
array
(
0
to
12
)
of
t_cmd_type
;
end
entity
SDRAM_controller
;
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- fake SDRAM controller for Macnica's development board Mercurio IV
-- IS42S16320B, 512Mbit SDRAM, 146MHz, 32Mx16bit
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
architecture
fake
of
SDRAM_controller
is
begin
rdy
<=
'1'
;
hDout
<=
(
others
=>
'X'
);
cke
<=
'1'
;
scs
<=
'1'
;
ras
<=
'1'
;
cas
<=
'1'
;
we
<=
'1'
;
dqm0
<=
'1'
;
dqm1
<=
'1'
;
ba0
<=
'1'
;
ba1
<=
'1'
;
saddr
<=
(
others
=>
'X'
);
sdata
<=
(
others
=>
'X'
);
end
architecture
fake
;
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- real SDRAM controller for Macnica's development board Mercurio IV
-- IS42S16320B, 512Mbit SDRAM, 146MHz, 32Mx16bit
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
architecture
simple
of
SDRAM_controller
is
constant
cmd_table
:
t_cmd_mem
:
=
(
-- page 9
...
...
@@ -133,7 +168,7 @@ architecture simple of SDRAM_controller is
st_idle
);
-- 54
signal
curr_st
,
next_st
:
ctrl_state
;
signal
ctrl_dbg_st
:
integer
;
-- for debugging only
signal
ctrl_dbg_st
,
cmd_dbg
:
integer
;
-- for debugging only
signal
reset_done
,
same_row
,
do_refresh
,
refresh_done
:
boolean
:
=
FALSE
;
signal
is_accs
,
is_rd
,
is_wr
:
boolean
:
=
FALSE
;
...
...
@@ -153,8 +188,13 @@ begin -- simple
cas
<=
command
.
cas
;
we
<=
command
.
we
;
cmd_dbg
<=
command
.
cmd
;
-- DEBUG only
saddr
(
10
)
<=
addr
(
10
)
when
command
.
cmd
=
cACT
else
command
.
a10
;
saddr
(
9
downto
0
)
<=
b"1000100000"
when
command
.
cmd
=
cMRS
else
addr
(
9
downto
0
);
U_address
:
registerN
generic
map
(
26
,
b"00"
&
x"000000"
)
port
map
(
clk2x
,
rst
,
hcs
,
haddr
,
addr
);
...
...
@@ -344,7 +384,7 @@ begin -- simple
elsif
is_rd
then
next_st
<=
st_rdcol
;
elsif
is_wr
then
next_st
<=
st_
rd
col
;
next_st
<=
st_
wr
col
;
else
next_st
<=
st_idle
;
end
if
;
...
...
@@ -352,7 +392,7 @@ begin -- simple
assert
false
report
"CTRL stateMachine broken"
&
integer
'image
(
ctrl_state
'pos
(
curr_st
))
severity
failure
;
end
case
;
end
process
U_CTRL_st_transitions
;
---------------------------
---------
end
process
U_CTRL_st_transitions
;
---------------------------
...
...
@@ -395,13 +435,17 @@ begin -- simple
do_refresh
<=
FALSE
;
cnt
:
=
0
;
elsif
rising_edge
(
clk2x
)
then
if
cnt
>
REFRESH_
doit
then
if
cnt
>
REFRESH_
INTERVAL
then
if
refresh_done
then
do_refresh
<=
FALSE
;
cnt
:
=
0
;
else
do_refresh
<=
TRUE
;
-- add some hysteresis
cnt
:
=
cnt
+
1
;
-- to accomodate slow commands
if
cnt
=
1023
then
cnt
:
=
0
;
else
cnt
:
=
cnt
+
1
;
-- to accomodate slow commands
end
if
;
end
if
;
else
do_refresh
<=
FALSE
;
...
...
@@ -412,17 +456,19 @@ begin -- simple
-- do wait for 100us after reset
U_rst_100us
:
process
variable
cnt
:
integer
range
0
to
16383
:
=
0
;
begin
-- process clk2x
reset_done
<=
FALSE
;
wait
until
rst
=
'1'
;
cnt
:
=
0
;
wait
until
rising_edge
(
clk2x
);
cnt
:
=
cnt
+
1
;
if
cnt
=
10000
then
-- 100us elapsed
reset_done
<=
TRUE
;
wait
;
U_rst_100us
:
process
(
rst
,
clk2x
)
variable
cnt
:
integer
range
0
to
(
8
*
1024
-
1
):
=
0
;
begin
if
rst
=
'0'
then
reset_done
<=
FALSE
;
cnt
:
=
0
;
elsif
rising_edge
(
clk2x
)
then
if
cnt
>=
RESET_INTERVAL
then
-- 100us elapsed
reset_done
<=
TRUE
;
cnt
:
=
0
;
else
cnt
:
=
cnt
+
1
;
end
if
;
end
if
;
end
process
U_rst_100us
;
...
...
@@ -431,30 +477,3 @@ end simple;
-- ---------------------------------------------------------------------
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- fake SDRAM controller for Macnica's development board Mercurio IV
-- IS42S16320B, 512Mbit SDRAM, 146MHz, 32Mx16bit
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
architecture
fake
of
SDRAM_controller
is
begin
rdy
<=
'1'
;
hDout
<=
(
others
=>
'X'
);
cke
<=
'1'
;
scs
<=
'1'
;
ras
<=
'1'
;
cas
<=
'1'
;
we
<=
'1'
;
dqm0
<=
'1'
;
dqm1
<=
'1'
;
ba0
<=
'1'
;
ba1
<=
'1'
;
saddr
<=
(
others
=>
'X'
);
sdata
<=
(
others
=>
'X'
);
end
architecture
fake
;
cMIPS/vhdl/tb_cMIPS.vhd
View file @
de9f9e78
...
...
@@ -187,6 +187,14 @@ architecture TB of tb_cMIPS is
dev_select
:
out
std_logic_vector
);
end
component
ram_addr_decode
;
component
sdram_addr_decode
is
port
(
rst
:
in
std_logic
;
cpu_d_aVal
:
in
std_logic
;
addr
:
in
std_logic_vector
;
aVal
:
out
std_logic
;
dev_select
:
out
std_logic_vector
);
end
component
sdram_addr_decode
;
component
io_addr_decode
is
port
(
clk
:
in
std_logic
;
rst
:
in
std_logic
;
...
...
@@ -373,6 +381,26 @@ architecture TB of tb_cMIPS is
outclk
:
OUT
STD_LOGIC
);
end
component
mf_altclkctrl
;
-- use fake / behavioral
for
U_I_CACHE
:
I_cache
use
entity
work
.
I_cache
(
fake
);
-- use simulation / rtl
for
U_ROM
:
ROM
use
entity
work
.
ROM
(
simulation
);
-- use simulation / rtl
for
U_RAM
:
RAM
use
entity
work
.
RAM
(
simulation
);
-- use fake / behavioral
for
U_D_CACHE
:
D_cache
use
entity
work
.
D_cache
(
fake
);
-- use fake / rtl
for
U_FPU
:
FPU
use
entity
work
.
FPU
(
rtl
);
-- use fake / simple
for
U_SDRAMc
:
SDRAM_controller
use
entity
work
.
SDRAM_controller
(
simple
);
...
...
@@ -384,9 +412,11 @@ architecture TB of tb_cMIPS is
signal
cpu_i_aVal
,
cpu_i_wait
,
wr
,
cpu_d_aVal
,
cpu_d_wait
:
std_logic
;
signal
nmi
,
i_busError
,
d_busError
:
std_logic
;
signal
irq
:
reg6
;
signal
inst_aVal
,
inst_wait
,
rom_rdy
:
std_logic
:
=
'1'
;
signal
inst_aVal
,
inst_wait
,
rom_rdy
:
std_logic
;
signal
data_aVal
,
data_wait
,
ram_rdy
,
mem_wr
:
std_logic
;
signal
cpu_xfer
,
mem_xfer
,
dev_select
,
dev_select_ram
,
dev_select_io
:
reg4
;
signal
sdram_aVal
,
sdram_rdy
,
sdram_wr
:
std_logic
;
signal
cpu_xfer
,
mem_xfer
:
reg4
;
signal
dev_select
,
dev_select_ram
,
dev_select_io
,
dev_select_sdram
:
reg4
;
signal
io_print_sel
:
std_logic
:
=
'1'
;
signal
io_stdout_sel
:
std_logic
:
=
'1'
;
signal
io_stdin_sel
:
std_logic
:
=
'1'
;
...
...
@@ -401,7 +431,7 @@ architecture TB of tb_cMIPS is
signal
io_lcd_sel
,
io_lcd_wait
:
std_logic
:
=
'1'
;
signal
d_cache_d_out
,
stdin_d_out
,
read_d_out
,
counter_d_out
:
reg32
;
signal
fpu_d_out
,
uart_d_out
,
sstats_d_out
,
keybd_d_out
:
reg32
;
signal
lcd_d_out
:
reg32
;
signal
lcd_d_out
,
sdram_d_out
:
reg32
;
signal
counter_irq
:
std_logic
;
signal
io_wait
,
not_waiting
:
std_logic
;
...
...
@@ -428,7 +458,6 @@ architecture TB of tb_cMIPS is
signal
hcs
:
std_logic
;
-- host side chip select (=0)
signal
sdram_rdy
:
std_logic
;
-- host side chip select (=0)
signal
haddr
:
reg26
;
-- host side address
signal
hDinp
:
reg32
;
-- host side data input
signal
hDout
:
reg32
;
-- host side data output
...
...
@@ -525,7 +554,10 @@ begin -- TB
U_DATA_ADDR_DEC
:
ram_addr_decode
port
map
(
rst
,
cpu_d_aVal
,
d_addr
,
data_aVal
,
dev_select_ram
);
dev_select
<=
dev_select_io
or
dev_select_ram
;
U_SDRAM_ADDR_DEC
:
sdram_addr_decode
port
map
(
rst
,
cpu_d_aVal
,
d_addr
,
sdram_aVal
,
dev_select_sdram
);
dev_select
<=
dev_select_io
or
dev_select_ram
;
-- or dev_select_sdram;
with
dev_select
select
cpu_data_inp
<=
d_cache_d_out
when
b"0001"
,
...
...
@@ -537,6 +569,7 @@ begin -- TB
sstats_d_out
when
b"1010"
,
keybd_d_out
when
b"1100"
,
lcd_d_out
when
b"1101"
,
-- sdram_d_out when b"1110",
(
others
=>
'X'
)
when
others
;
U_D_CACHE
:
d_cache
...
...
@@ -552,7 +585,8 @@ begin -- TB
mem_addr
,
datram_out
,
datram_inp
,
mem_xfer
,
dump_ram
);
U_SDRAMc
:
SDRAM_controller
port
map
(
rst
,
clk
,
hcs
,
sdram_rdy
,
wr
,
cpu_xfer
,
haddr
,
hDinp
,
hDout
,
(
rst
,
clk
,
sdram_aVal
,
sdram_rdy
,
wr
,
cpu_xfer
,
d_addr
(
25
downto
0
),
hDinp
,
hDout
,
sdcke
,
sdscs
,
sdras
,
sdcas
,
sdwe
,
sddqm0
,
sddqm1
,
sdba0
,
sdba1
,
sdaddr
,
sddata
);
...
...
@@ -859,6 +893,7 @@ end architecture behavioral;
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- I/O address decoding
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
...
...
@@ -996,31 +1031,98 @@ end architecture behavioral;
-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
use
work
.
all
;
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- SDRAM address decoding
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
library
IEEE
;
use
IEEE
.
std_logic_1164
.
all
;
use
IEEE
.
numeric_std
.
all
;
use
work
.
p_wires
.
all
;
use
work
.
p_memory
.
all
;
configuration
CFG_TB
of
TB_CMIPS
is
for
TB
entity
sdram_addr_decode
is
-- CPU side triggers access
port
(
rst
:
in
std_logic
;
cpu_d_aVal
:
in
std_logic
;
-- CPU data addr valid (active=0)
addr
:
in
reg32
;
-- CPU address
aVal
:
out
std_logic
;
-- data address (act=0)
dev_select
:
out
reg4
);
-- select input to CPU
constant
LO_ADDR
:
integer
:
=
log2_ceil
(
SDRAM_BASE_ADDR
);
constant
HI_ADDR
:
integer
:
=
log2_ceil
(
SDRAM_BASE_ADDR
+
SDRAM_MEM_SZ
-
1
);
constant
in_r
:
std_logic_vector
(
HI_ADDR
downto
LO_ADDR
)
:
=
(
others
=>
'1'
);
constant
ng_r
:
std_logic_vector
(
HI_ADDR
downto
LO_ADDR
)
:
=
(
others
=>
'0'
);
constant
oth
:
std_logic_vector
(
HI_SEL_BITS
downto
HI_ADDR
+
1
):
=
(
others
=>
'1'
);
constant
ng_o
:
std_logic_vector
(
HI_SEL_BITS
downto
HI_ADDR
+
1
):
=
(
others
=>
'0'
);
end
entity
sdram_addr_decode
;
architecture
behavioral
of
sdram_addr_decode
is
-- use fake / behavioral
for
U_I_CACHE
:
I_cache
use
entity
work
.
I_cache
(
fake
);
end
for
;
constant
all_0
:
std_logic_vector
(
31
downto
0
)
:
=
(
others
=>
'0'
);
constant
a_hi
:
std_logic_vector
(
31
downto
HI_ADDR
+
1
)
:
=
(
others
=>
'0'
);
constant
a_lo
:
std_logic_vector
(
LO_ADDR
-1
downto
0
)
:
=
(
others
=>
'0'
);
constant
a_bits
:
std_logic_vector
(
HI_ADDR
downto
LO_ADDR
)
:
=
(
others
=>
'1'
);
constant
a_mask
:
std_logic_vector
:
=
a_hi
&
a_bits
&
a_lo
;
-- use simulation / rtl
for
U_ROM
:
ROM
use
entity
work
.
ROM
(
simulation
);
end
for
;
constant
LO_RAM
:
natural
:
=
0
;
constant
HI_RAM
:
natural
:
=
log2_ceil
(
SDRAM_MEM_SZ
-1
);
constant
r_hi
:
std_logic_vector
(
31
downto
HI_RAM
+
1
)
:
=
(
others
=>
'1'
);
constant
r_lo
:
std_logic_vector
(
HI_RAM
downto
LO_RAM
)
:
=
(
others
=>
'0'
);
constant
r_mask
:
std_logic_vector
:
=
r_hi
&
r_lo
;
signal
in_range
:
boolean
;
-- use simulation / rtl
for
U_RAM
:
RAM
use
entity
work
.
RAM
(
simulation
);
end
for
;
constant
SDRAM_ADDR_BOTTOM
:
natural
:
=
to_integer
(
signed
(
x_SDRAM_BASE_ADDR
(
HI_SEL_BITS
downto
LO_SEL_BITS
)));
constant
SDRAM_ADDR_RANGE
:
natural
:
=
(
to_integer
(
signed
(
x_SDRAM_BASE_ADDR
(
HI_SEL_BITS
downto
LO_SEL_BITS
)))
+
to_integer
(
signed
(
x_SDRAM_MEM_SZ
(
HI_SEL_BITS
downto
LO_SEL_BITS
))));
constant
SDRAM_ADDR_TOP
:
natural
:
=
SDRAM_ADDR_BOTTOM
+
SDRAM_ADDR_RANGE
;
begin
-- use fake / behavioral
for
U_D_CACHE
:
D_cache
use
entity
work
.
D_cache
(
fake
);
end
for
;
-- this is ONLY acceptable for simulations;
-- computing these differences is TOO expensive for synthesis
in_range
<=
(
(
to_integer
(
signed
(
addr
(
HI_SEL_BITS
downto
LO_SEL_BITS
)))
>=
SDRAM_ADDR_BOTTOM
)
and
(
to_integer
(
signed
(
addr
(
HI_SEL_BITS
downto
LO_SEL_BITS
)))
<
SDRAM_ADDR_TOP
)
);
aVal
<=
'0'
when
(
cpu_d_aVal
=
'0'
and
in_range
)
else
'1'
;
-- use fake / rtl
for
U_FPU
:
FPU
use
entity
work
.
FPU
(
rtl
);
end
for
;
-- use fake / simple
for
U_SDRAMc
:
SDRAM_controller
use
entity
work
.
SDRAM_controller
(
fake
);
end
for
;
dev_select
<=
b"1110"
when
(
cpu_d_aVal
=
'0'
and
in_range
)
else
b"0000"
;
assert
true
-- cpu_d_aVal = '1'
report
"e "
&
SLV32HEX
(
addr
)
&
" addr "
&
SLV2str
(
addr
(
15
downto
0
))
&
LF
&
" LO_AD "
&
integer
'image
(
LO_ADDR
)
&
" HI_AD "
&
integer
'image
(
HI_ADDR
)
&
" a_hi "
&
SLV2STR
(
a_hi
)
&
" a_lo "
&
SLV2STR
(
a_lo
)
&
" a_bits "
&
SLV2STR
(
a_bits
)
&
" a_mask "
&
SLV32HEX
(
a_mask
)
&
LF
&
" LO_RAM "
&
integer
'image
(
LO_RAM
)
&
" HI_RAM "
&
integer
'image
(
HI_RAM
)
&
" r_hi "
&
SLV2STR
(
r_hi
)
&
" r_lo "
&
SLV2STR
(
r_lo
)
&
" r_mask "
&
SLV32HEX
(
r_mask
)
severity
NOTE
;
end
architecture
behavioral
;
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
use
work
.
all
;
configuration
CFG_TB
of
TB_CMIPS
is
for
TB
end
for
;
end
configuration
CFG_TB
;
-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
...
...
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