URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc
- from Rev 484 to Rev 485
- ↔ Reverse comparison
Rev 484 → Rev 485
/trunk/orpsocv2/bench/verilog/include/or1200_monitor_defines.v
0,0 → 1,88
|
// |
// Top of TB |
// |
`define TB_TOP orpsoc_testbench |
|
// |
// Top of DUT |
// |
`define DUT_TOP `TB_TOP.dut |
|
// |
// Top of OR1200 inside test bench |
// |
`define OR1200_TOP `DUT_TOP.or1200_top0 |
|
// |
// Define to enable lookup file generation |
// |
//`define OR1200_MONITOR_LOOKUP |
|
// |
// Define to enable SPR access log file generation |
// |
//`define OR1200_MONITOR_SPRS |
|
// |
// Enable logging of state during execution |
// |
//`define OR1200_MONITOR_EXEC_STATE |
|
// |
// Enable disassembly of instructions in execution state log |
// |
//`define OR1200_MONITOR_EXEC_LOG_DISASSEMBLY |
|
// |
// Enable verbose report l.nops (to both general log file and stdout) |
// |
`define OR1200_MONITOR_VERBOSE_NOPS |
|
// |
// Enable monitoring of control and execution flow (experimental) |
// |
//`define OR1200_SYSTEM_CHECKER |
|
// Can either individually enable things above, or usually have the scripts |
// running the simulation pass the PROCESSOR_MONITOR_ENABLE_LOGS define to |
// enable them all. |
|
`ifdef PROCESSOR_MONITOR_ENABLE_LOGS |
`define OR1200_MONITOR_EXEC_STATE |
`define OR1200_MONITOR_SPRS |
`define OR1200_MONITOR_LOOKUP |
`endif |
|
// |
// Memory coherence checking (double check instruction in fetch stage against |
// what is in memory.) Useful for cache controller development. |
// |
//`define MEM_COHERENCE_CHECK |
|
// |
// Top of OR1200 inside test bench |
// |
`define CPU or1200 |
`define CPU_cpu or1200_cpu |
`define CPU_rf or1200_rf |
`define CPU_except or1200_except |
`define CPU_ctrl or1200_ctrl |
`define CPU_sprs or1200_sprs |
`define CPU_immu_top or1200_immu_top |
`define CPU_immu_tlb or1200_immu_tlb |
`define CPU_CORE_CLK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.clk |
|
|
`define OR1K_OPCODE_POS 31:26 |
`define OR1K_J_BR_IMM_POS 25:0 |
`define OR1K_RD_POS 25:21 |
`define OR1K_RA_POS 20:16 |
`define OR1K_RB_POS 15:11 |
`define OR1K_ALU_OP_POS 3:0 |
|
`define OR1K_SHROT_OP_POS 7:6 |
`define OR1K_SHROTI_IMM_POS 5:0 |
`define OR1K_SF_OP 25:21 |
|
`define OR1K_XSYNC_OP_POS 25:21 |
/trunk/orpsocv2/bench/verilog/or1200_monitor.v
37,98 → 37,10
|
`include "timescale.v" |
`include "or1200_defines.v" |
`include "orpsoc-testbench-defines.v" |
`include "or1200_monitor_defines.v" |
`include "test-defines.v" |
|
// |
// Top of TB |
// |
`define TB_TOP orpsoc_testbench |
|
// |
// Top of DUT |
// |
`define DUT_TOP `TB_TOP.dut |
|
// |
// Top of OR1200 inside test bench |
// |
`define OR1200_TOP `DUT_TOP.or1200_top0 |
|
// |
// Define to enable lookup file generation |
// |
//`define OR1200_MONITOR_LOOKUP |
|
// |
// Define to enable SPR access log file generation |
// |
//`define OR1200_MONITOR_SPRS |
|
// |
// Enable logging of state during execution |
// |
//`define OR1200_MONITOR_EXEC_STATE |
|
// |
// Enable disassembly of instructions in execution state log |
// |
//`define OR1200_MONITOR_EXEC_LOG_DISASSEMBLY |
|
// |
// Enable verbose report l.nops (to both general log file and stdout) |
// |
`define OR1200_MONITOR_VERBOSE_NOPS |
|
// |
// Enable monitoring of control and execution flow (experimental) |
// |
//`define OR1200_SYSTEM_CHECKER |
|
// Can either individually enable things above, or usually have the scripts |
// running the simulation pass the PROCESSOR_MONITOR_ENABLE_LOGS define to |
// enable them all. |
|
`ifdef PROCESSOR_MONITOR_ENABLE_LOGS |
`define OR1200_MONITOR_EXEC_STATE |
`define OR1200_MONITOR_SPRS |
`define OR1200_MONITOR_LOOKUP |
`endif |
|
// |
// Memory coherence checking (double check instruction in fetch stage against |
// what is in memory.) Useful for cache controller development. |
// |
//`define MEM_COHERENCE_CHECK |
|
// |
// Top of OR1200 inside test bench |
// |
`define CPU or1200 |
`define CPU_cpu or1200_cpu |
`define CPU_rf or1200_rf |
`define CPU_except or1200_except |
`define CPU_ctrl or1200_ctrl |
`define CPU_sprs or1200_sprs |
`define CPU_immu_top or1200_immu_top |
`define CPU_immu_tlb or1200_immu_tlb |
`define CPU_CORE_CLK `OR1200_TOP.`CPU_cpu.`CPU_ctrl.clk |
|
|
`define OR1K_OPCODE_POS 31:26 |
`define OR1K_J_BR_IMM_POS 25:0 |
`define OR1K_RD_POS 25:21 |
`define OR1K_RA_POS 20:16 |
`define OR1K_RB_POS 15:11 |
`define OR1K_ALU_OP_POS 3:0 |
|
`define OR1K_SHROT_OP_POS 7:6 |
`define OR1K_SHROTI_IMM_POS 5:0 |
`define OR1K_SF_OP 25:21 |
|
`define OR1K_XSYNC_OP_POS 25:21 |
|
|
module or1200_monitor; |
|
integer fexe; |
280,6 → 192,10
for(i=`OR1200_MONITOR_CRASH_TRACE_SIZE-1;i>=0;i=i-1) begin |
$fdisplay(fgeneral, "%h\t%h",addr_trace[i], insn_trace[i]); |
end |
$display("*"); |
$display("* or1200_monitor : OR1200 crash detected (suspected CPU PC corruption)"); |
$display("*"); |
|
#100 $finish; |
end |
else |
/trunk/orpsocv2/rtl/verilog/include/or1200_defines.v
1764,10 → 1764,18
|
/////////////////////////////////////////////////////////////////////////////// |
// Boot Address Selection // |
// This only changes where the initial reset occurs. EPH setting is still // |
// used to determine where vectors are located. // |
// // |
// Allows a definable boot address, potentially different to the usual reset // |
// vector to allow for power-on code to be run, if desired. // |
// // |
// OR1200_BOOT_ADR should be the 32-bit address of the boot location // |
// OR1200_BOOT_PCREG_DEFAULT should be ((OR1200_BOOT_ADR-4)>>2) // |
// // |
// For default reset behavior uncomment the settings under the "Boot 0x100" // |
// comment below. // |
// // |
/////////////////////////////////////////////////////////////////////////////// |
// Boot from 0xf0000100 |
// Boot from 0xf0000100 |
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f |
//`define OR1200_BOOT_ADR 32'hf0000100 |
// Boot from 0x100 |
/trunk/orpsocv2/rtl/verilog/or1200/or1200_dpram.v
112,9 → 112,10
// verilator public |
input [aw-1:0] gpr_no; |
input [dw-1:0] value; |
|
mem[gpr_no] = value; |
|
begin |
mem[gpr_no] = value; |
set_gpr = 0; |
end |
endfunction // get_gpr |
|
// |
/trunk/orpsocv2/rtl/verilog/orpsoc_top/orpsoc_top.v
668,7 → 668,7
// ROM |
// |
//////////////////////////////////////////////////////////////////////// |
|
`ifdef BOOTROM |
rom rom0 |
( |
.wb_dat_o (wbs_i_rom0_dat_o), |
682,6 → 682,10
.wb_rst (wb_rst)); |
|
defparam rom0.addr_width = wbs_i_rom0_addr_width; |
`else // !`ifdef BOOTROM |
assign wbs_i_rom0_dat_o = 0; |
assign wbs_i_rom0_ack_o = 0; |
`endif // !`ifdef BOOTROM |
|
assign wbs_i_rom0_err_o = 0; |
assign wbs_i_rom0_rty_o = 0; |
725,14 → 729,14
.wbm1_err_o (wbs_d_mc0_err_o), |
.wbm1_rty_o (wbs_d_mc0_rty_o), |
// Wishbone slave interface 2 |
.wbm2_dat_i (0), |
.wbm2_adr_i (0), |
.wbm2_sel_i (0), |
.wbm2_cti_i (0), |
.wbm2_bte_i (0), |
.wbm2_we_i (0), |
.wbm2_cyc_i (0), |
.wbm2_stb_i (0), |
.wbm2_dat_i (32'd0), |
.wbm2_adr_i (32'd0), |
.wbm2_sel_i (4'd0), |
.wbm2_cti_i (3'd0), |
.wbm2_bte_i (2'd0), |
.wbm2_we_i (1'd0), |
.wbm2_cyc_i (1'd0), |
.wbm2_stb_i (1'd0), |
.wbm2_dat_o (), |
.wbm2_ack_o (), |
.wbm2_err_o (), |
/trunk/orpsocv2/rtl/verilog/ethmac/eth_wishbone.v
1257,7 → 1257,7
if(Reset) |
TxStartFrm_wb <= 1'b0; |
else |
if(TxBDReady & ~StartOccured & (TxBufferFull | TxLengthEq0)) |
if(TxBDReady & ~StartOccured & (TxBufferAlmostFull | TxBufferFull| TxLengthEq0)) |
TxStartFrm_wb <= 1'b1; |
else |
if(TxStartFrm_syncb2) |
/trunk/orpsocv2/rtl/verilog/ethmac/eth_fifo.v
64,9 → 64,9
output [CNT_WIDTH-1:0] cnt; |
|
|
|
reg [CNT_WIDTH-1:0] read_pointer; |
reg [CNT_WIDTH-1:0] cnt; |
reg final_read; |
reg final_read; |
|
always @ (posedge clk or posedge reset) |
begin |
113,11 → 113,7
else if (write) |
waddr <= waddr + 1; |
|
reg read_reg; |
always @(posedge clk) |
read_reg <= read; |
|
always @(posedge clk) |
if (reset) |
raddr <= 0; |
else if (clear) |
153,11 → 149,27
assign empty = ~(|cnt); |
assign almost_empty = cnt==1; |
assign full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-1); |
assign almost_full = &cnt[CNT_WIDTH-1:0]; |
//assign almost_full = &cnt[CNT_WIDTH-1:0]; |
assign almost_full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-2); |
|
|
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
read_pointer <= 0; |
else |
if(clear) |
// Begin read pointer at 1 |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, 1'b1}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
end |
|
|
`else // !`ifdef ETH_FIFO_GENERIC |
|
reg [CNT_WIDTH-1:0] read_pointer; |
|
reg [CNT_WIDTH-1:0] write_pointer; |
|
|
167,8 → 179,7
read_pointer <= 0; |
else |
if(clear) |
//read_pointer <= { {(CNT_WIDTH-1){1'b0}}, read}; |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, 1'b1}; |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, read}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
186,15 → 197,81
write_pointer <= write_pointer + 1'b1; |
end |
|
`ifdef ETH_FIFO_XILINX |
xilinx_dist_ram_16x32 fifo |
( .data_out(data_out), |
.we(write & ~full), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer), |
.wclk(clk) |
); |
`ifdef ETH_FIFO_XILINX |
|
generate |
if (CNT_WIDTH==4) |
begin |
xilinx_dist_ram_16x32 fifo |
( .data_out(data_out), |
.we(write & ~full), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==4) |
else if (CNT_WIDTH==6) |
begin |
|
wire [DATA_WIDTH-1:0] data_out0; |
wire [DATA_WIDTH-1:0] data_out1; |
wire [DATA_WIDTH-1:0] data_out2; |
wire [DATA_WIDTH-1:0] data_out3; |
|
wire ramsel0,ramsel1,ramsel2,ramsel3; |
|
assign ramsel0 = (read_pointer[5:4]==2'b00); |
assign ramsel1 = (read_pointer[5:4]==2'b01); |
assign ramsel2 = (read_pointer[5:4]==2'b10); |
assign ramsel3 = (read_pointer[5:4]==2'b11); |
|
assign data_out = ramsel3 ? data_out3 : |
ramsel2 ? data_out2 : |
ramsel1 ? data_out1 : data_out0; |
|
xilinx_dist_ram_16x32 fifo0 |
( .data_out(data_out0), |
.we((write & ~full) & ramsel0), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo1 |
( .data_out(data_out1), |
.we(write & ~full & ramsel1), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo2 |
( .data_out(data_out2), |
.we(write & ~full & ramsel2), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo3 |
( .data_out(data_out3), |
.we(write & ~full & ramsel3), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==6) |
endgenerate |
|
|
|
|
|
`else // !ETH_FIFO_XILINX |
`ifdef ETH_ALTERA_ALTSYNCRAM |
altera_dpram_16x32 altera_dpram_16x32_inst |
/trunk/orpsocv2/doc/orpsoc.texi
62,6 → 62,7
* Board Designs:: |
* ORDB1A3PE1500:: |
* ML501:: |
* Generic Designs:: |
* Software:: |
* GNU Free Documentation License:: The license for this documentation |
* Index:: |
433,10 → 434,15
@item SIMULATOR |
Specify simulator to use. Default is Icarus Verilog, can be set to @code{modelsim} to use Mentor Graphics' Modelsim. No others are supported right now. |
|
@item MGC_NO_VOPT |
When using Modelsim (specifying @code{SIMULATOR=modelsim}), if the version does not include the individual @code{vopt} executable, specify @code{MGC_NO_VOPT=1} when compiling. |
|
@end table |
|
|
|
|
|
@node Reference Design Cycle Accurate |
@subsection Cycle Accurate |
@cindex cycle accurate simulation of reference design |
1353,7 → 1359,30
|
See the ML501 schematic (http://www.xilinx.com/support/documentation/boards_and_kits/ml501_20061010_bw.pdf) for more details on these headers, and refer to the pinouts in the ML501 UCF, in the board's @code{backend/par/bin/ml501.ucf} file. |
|
|
@c **************************************************************************** |
@c Generic Design build chapter |
@c **************************************************************************** |
|
@node Generic |
@chapter Generic |
@cindex Generic design information |
|
@menu |
* Overview:: |
@end menu |
|
|
@node Generic Build Overview |
@section Overview |
|
The paths under @code{boards/generic} contain designs similar to the reference design, in that they are not technology specific, and used for development of certain features of the processor, or peripherals. |
|
An example is the fault tolerance testing build, in @code{boards/generic/ft}, which implements some custom modules in the testbench and ORPSoC top level design, and is in general a very minimal system just for testing. |
|
Additional builds, testing certain parts of the technology, can be developed here. |
|
@c **************************************************************************** |
@c Software section |
@c **************************************************************************** |
|
/trunk/orpsocv2/sim/bin/Makefile
97,7 → 97,6
RTL_SIM_DIR=$(SIM_DIR) |
RTL_SIM_RUN_DIR=$(RTL_SIM_DIR)/run |
RTL_SIM_BIN_DIR=$(RTL_SIM_DIR)/bin |
RTL_SIM_SRC_DIR=$(RTL_SIM_DIR)/src |
RTL_SIM_RESULTS_DIR=$(RTL_SIM_DIR)/out |
|
# Testbench paths |
174,9 → 173,32
# If VCD dump is desired, tell Modelsim not to optimise |
# away everything. |
ifeq ($(VCD), 1) |
#VOPT_ARGS=-voptargs="+acc=rnp" |
# If certain versions of modelsim don't have the vopt executable, define |
# MGC_NO_VOPT=1 when running. |
ifeq ($(MGC_NO_VOPT), 1) |
MGC_VSIM_ARGS +=-voptargs="+acc=rnp" |
MGC_VOPT_CMD=echo |
MGC_VSIM_TGT=orpsoc_testbench |
else |
VOPT_ARGS=+acc=rnpqv |
MGC_VOPT_CMD= vopt $(QUIET) $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -o tb |
MGC_VSIM_TGT=tb |
endif |
|
else |
|
ifeq ($(MGC_NO_VOPT), 1) |
MGC_VSIM_ARGS += -vopt |
MGC_VOPT_CMD=echo |
MGC_VSIM_TGT=orpsoc_testbench |
else |
VOPT_ARGS=+acc=rnpqv |
MGC_VOPT_CMD= vopt $(QUIET) $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -o tb |
MGC_VSIM_TGT=tb |
endif |
|
|
endif |
# VSIM commands |
# Suppressed warnings - 3009: Failed to open $readmemh() file |
# Suppressed warnings - 3009: Module 'blah' does not have a `timescale |
183,7 → 205,7
# directive in effect, but previous modules do. |
# Suppressed warnings - 8598: Non-positive replication multiplier inside |
# concat. Replication will be ignored |
MGC_VSIM_ARGS= -suppress 7 -suppress 3009 -suppress 8598 -c $(QUIET) \ |
MGC_VSIM_ARGS += -suppress 7 -suppress 3009 -suppress 8598 -c $(QUIET) \ |
-do "set StdArithNoWarnings 1; run -all; exit" |
# Options required when VPI option used |
ifeq ($(VPI), 1) |
283,7 → 305,6
modelsim_dut.scr: rtl $(RTL_VERILOG_SRC) $(RTL_VERILOG_INCLUDES) \ |
$(BOOTROM_VERILOG) |
$(Q)echo "+incdir+"$(RTL_VERILOG_INCLUDE_DIR) > $@; |
$(Q)echo "+incdir+"$(RTL_SIM_SRC_DIR) >> $@; |
$(Q)echo "+incdir+"$(BOOTROM_SW_DIR) >> $@; |
$(Q)echo "+incdir+"$(BENCH_VERILOG_INCLUDE_DIR) >> $@; |
$(Q)echo "+libext+.v" >> $@; |
302,9 → 323,7
echo "-y "$$path >> $@; \ |
done |
$(Q)echo "+incdir+"$(RTL_VERILOG_INCLUDE_DIR) >> $@; |
$(Q)echo "+incdir+"$(RTL_SIM_SRC_DIR) >> $@; |
$(Q)echo "+libext+.v" >> $@; |
$(Q)echo "-y" $(RTL_SIM_SRC_DIR) >> $@; |
$(Q)for vsrc in $(BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done |
$(Q)echo >> $@ |
|
321,9 → 340,9
$(MODELSIM): modelsim_bench.scr $(TEST_DEFINES_VLG) $(MGC_VPI_LIB) work |
$(Q)echo; echo "\t### Compiling testbench ###"; echo |
$(Q)vlog $(QUIET) -nologo -incr $(BENCH_TOP) -f $< |
$(Q)vopt $(QUIET) $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -o tb |
$(Q)$(MGC_VOPT_CMD) |
$(Q)echo; echo "\t### Launching simulation ###"; echo |
$(Q)vsim $(MGC_VSIM_ARGS) tb |
$(Q)vsim $(VOPT_ARGS) $(MGC_VSIM_ARGS) $(MGC_VSIM_TGT) |
|
# |
# Icarus Verilog simulator build and run rules |
334,7 → 353,6
$(Q)echo "# Icarus Verilog simulation script" > $@ |
$(Q)echo "# Auto generated. Any alterations will be written over!" >> $@ |
$(Q)echo "+incdir+"$(RTL_VERILOG_INCLUDE_DIR) > $@; |
$(Q)echo "+incdir+"$(RTL_SIM_SRC_DIR) >> $@; |
$(Q)echo "+incdir+"$(BENCH_VERILOG_DIR) >> $@; |
$(Q)echo "+incdir+"$(BOOTROM_SW_DIR) >> $@; |
$(Q)for path in $(BENCH_VERILOG_SRC_SUBDIRS); do \ |
346,7 → 364,6
$(Q)for module in $(RTL_VERILOG_MODULES); do \ |
echo "-y " $(RTL_VERILOG_DIR)/$$module >> $@; \ |
done |
$(Q)echo "-y" $(RTL_SIM_SRC_DIR) >> $@; |
$(Q)echo "-y" $(BENCH_VERILOG_DIR) >> $@; |
$(Q)echo $(BENCH_TOP) >> $@; |
$(Q) echo >> $@ |
/trunk/orpsocv2/sw/utils/marksec
File deleted
trunk/orpsocv2/sw/utils/marksec
Property changes :
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: trunk/orpsocv2/sw/utils/merge2srec
===================================================================
--- trunk/orpsocv2/sw/utils/merge2srec (revision 484)
+++ trunk/orpsocv2/sw/utils/merge2srec (nonexistent)
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-LINE_NB=`wc -l < $1`
-MIN=`expr $LINE_NB - 1`
-
-head -$MIN $1 > out.exo
-
-cat $2 >> out.exo
-tail -1 $1 >> out.exo
-
trunk/orpsocv2/sw/utils/merge2srec
Property changes :
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: trunk/orpsocv2/sw/tests/or1200/sim/or1200-dctest.c
===================================================================
--- trunk/orpsocv2/sw/tests/or1200/sim/or1200-dctest.c (revision 484)
+++ trunk/orpsocv2/sw/tests/or1200/sim/or1200-dctest.c (revision 485)
@@ -14,8 +14,7 @@
#define LOOPS 64
#define WORD_STRIDE 8
-// Memory area to test at
-#define TEST_BASE 0x600000 /* 6MB */
+extern unsigned long _stack;
unsigned long int my_lfsr;
@@ -29,6 +28,8 @@
main()
{
+ unsigned long stack_top = (unsigned long) &_stack;
+
// Check data cache is present and enabled
if (!(mfspr(SPR_UPR)& SPR_UPR_DCP) | !(mfspr(SPR_SR) & SPR_SR_DCE))
{
@@ -37,7 +38,7 @@
return 0;
}
- volatile char* ptr = (volatile char*) TEST_BASE;
+ volatile char* ptr = (volatile char*) (stack_top + 256);
int i;
ptr[0] = 0xab;
@@ -99,7 +100,7 @@
// init LFSR
my_lfsr = RAND_LFSR_SEED;
- volatile unsigned long int *lptr = (volatile unsigned long int*) TEST_BASE;
+ volatile unsigned long int *lptr = (volatile unsigned long int*) (stack_top + 256);
for(i=0;i
/trunk/orpsocv2/sw/tests/or1200/sim/or1200-mmu.c
94,7 → 94,7
// Set this to 1 to enable the IMMU tests |
#define DO_IMMU_TESTS 1 |
// Set this to 1 to enable the DMMU tests |
#define DO_DMMU_TESTS 1 |
#define DO_DMMU_TESTS 0 |
|
// Symbols defined in linker script |
extern unsigned long _endtext; |
114,7 → 114,9
will be used for testing */ |
#define RAM_START 0x00000000 |
// Assume only 2MB memory |
#define RAM_SIZE 0x00200000 |
#ifndef RAM_SIZE |
# define RAM_SIZE 0x00200000 |
#endif |
|
#define VM_BASE 0xc0000000 |
|
/trunk/orpsocv2/sw/lib/include/printf.h
1,6 → 1,8
#ifndef _PRINTF_H_ |
#define _PRINTF_H_ |
|
int sprintf(char* str, const char *fmt, ...); |
|
#define PRINTFBUFFER_SIZE 512 |
extern char PRINTFBUFFER[PRINTFBUFFER_SIZE]; // Declare a global printf buffer |
//int vfnprintf ( char *stream, size_t n, const char *format, va_list arg); |
/trunk/orpsocv2/sw/lib/printf.c
663,6 → 663,17
/* NOTREACHED */ |
} |
|
int |
sprintf(char* str, const char *fmt, ...) |
{ |
va_list args; |
|
va_start(args, fmt); |
|
return vfnprintf(str, 1024, fmt, args); |
|
} |
|
#include "printf.h" |
|
// Actual printf function we call, with static buffer of 512 bytes |
/trunk/orpsocv2/sw/board/include/board.h
20,4 → 20,13
// |
#define TICKS_PER_SEC 100 |
|
|
// |
// UART driver configuration |
// |
#define UART_NUM_CORES 1 |
#define UART_BASE_ADDRESSES_CSV UART0_BASE |
#define UART_BAUD_RATES_CSV UART0_BAUD_RATE |
|
|
#endif |
/trunk/orpsocv2/sw/drivers/simple-spi/simple-spi.c
9,8 → 9,15
#include "simple-spi.h" |
#include "cpu-utils.h" |
|
const int spi_base_adr[1] = {SPI0_BASE}; |
|
const int spi_base_adr[1] = { |
#ifdef SPI0_BASE |
SPI0_BASE |
#else |
0 |
#endif |
}; |
|
void |
spi_core_enable(int core) |
{ |
/trunk/orpsocv2/sw/drivers/or1200/crt0.S
35,6 → 35,37
/* ---[ 0x100: RESET exception ]----------------------------------------- */ |
.org 0x100 |
l.movhi r0, 0 |
l.movhi r1, 0 |
l.movhi r2, 0 |
l.movhi r3, 0 |
l.movhi r4, 0 |
l.movhi r5, 0 |
l.movhi r6, 0 |
l.movhi r7, 0 |
l.movhi r8, 0 |
l.movhi r9, 0 |
l.movhi r10, 0 |
l.movhi r11, 0 |
l.movhi r12, 0 |
l.movhi r13, 0 |
l.movhi r14, 0 |
l.movhi r15, 0 |
l.movhi r16, 0 |
l.movhi r17, 0 |
l.movhi r18, 0 |
l.movhi r19, 0 |
l.movhi r20, 0 |
l.movhi r21, 0 |
l.movhi r22, 0 |
l.movhi r23, 0 |
l.movhi r24, 0 |
l.movhi r25, 0 |
l.movhi r26, 0 |
l.movhi r27, 0 |
l.movhi r28, 0 |
l.movhi r29, 0 |
l.movhi r30, 0 |
l.movhi r31, 0 |
/* Clear status register, set supervisor mode */ |
l.ori r1, r0, SPR_SR_SM |
l.mtspr r0, r1, SPR_SR |
290,11 → 321,6
|
.L10: |
|
/* Initialise stack */ |
/* LOAD_SYMBOL_2_GPR(r1, _stack) |
l.addi r2, r0, -3 |
l.and r1, r1, r2 |
*/ |
/* Clear BSS */ |
LOAD_SYMBOL_2_GPR(r28, _bss_start) |
LOAD_SYMBOL_2_GPR(r30, _bss_end) |
304,12 → 330,10
l.bf 1b |
l.addi r28, r28, 4 |
|
|
/* Initialise UART in a C function */ |
/*l.jal _uart_init |
l.nop*/ |
|
|
/* Jump to main program entry point (argc = argv = 0) */ |
CLEAR_GPR(r3) |
CLEAR_GPR(r4) |
/trunk/orpsocv2/sw/drivers/uart/uart.c
2,8 → 2,13
#include "board.h" |
#include "uart.h" |
|
const int UART_BASE_ADR[1] = {UART0_BASE}; |
const int UART_BAUDS[1] = {UART0_BAUD_RATE}; |
#ifdef UART_NUM_CORES |
const int UART_BASE_ADR[UART_NUM_CORES] = {UART_BASE_ADDRESSES_CSV}; |
const int UART_BAUDS[UART_NUM_CORES] = {UART_BAUD_RATES_CSV}; |
#else |
const int UART_BASE_ADR[1] = {0}; |
const int UART_BAUDS[1] = {0}; |
#endif |
|
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
|
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/rtl/verilog/orpsoc_top/orpsoc_top.v
1001,7 → 1001,7
wire [10:0] or1200_dbg_wp_o; |
wire or1200_dbg_bp_o; |
wire or1200_dbg_rst; |
|
|
wire or1200_clk, or1200_rst; |
wire sig_tick; |
|
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/sw/Makefile.inc
8,7 → 8,8
# Figure out actual path the common software directory |
SW_ROOT=$(BOARD_SW_ROOT)/$(PROJ_ROOT)/sw |
|
# Set the BOARD_PATH to point to the root of this board build |
# Set the BOARD to be the path within the board/ path of the project that goes |
# to this project. |
BOARD=actel/ordb1a3pe1500 |
|
# Set RTL_VERILOG_INCLUDE_DIR so software |
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/sw/board/include/board.h
15,11 → 15,14
// Uncomment the appropriate bootloader define. This will effect the bootrom.S |
// file, which is compiled and converted into Verilog for inclusion at |
// synthesis time. See bootloader/bootloader.S for details on each option. |
|
#ifndef PRELOAD_RAM |
#define BOOTROM_SPI_FLASH |
//#define BOOTROM_GOTO_RESET |
//#define BOOTROM_LOOP_AT_ZERO |
//#define BOOTROM_LOOP_IN_ROM |
#else |
#define BOOTROM_GOTO_RESET |
#endif |
|
// |
// Defines for each core (memory map base, OR1200 interrupt line number, etc.) |
91,4 → 94,18
// |
#define TICKS_PER_SEC 100 |
|
// |
// UART driver initialisation |
// |
#define UART_NUM_CORES 3 |
|
#define UART_BASE_ADDRESSES_CSV \ |
UART0_BASE, UART2_BASE, UART2_BASE |
|
#define UART_BAUD_RATES_CSV \ |
UART0_BAUD_RATE, UART1_BAUD_RATE, UART1_BAUD_RATE |
|
|
|
|
#endif |
/trunk/orpsocv2/boards/xilinx/ml501/bench/verilog/include/eth_stim.v
76,7 → 76,7
parameter eth_stim_num_rx_only_packet_size = 60; |
parameter eth_stim_num_rx_only_packet_size_change = 2'b01; // 2'b01: Increment |
parameter eth_stim_num_rx_only_packet_size_change_amount = 127; |
parameter eth_stim_num_rx_only_IPG = 180_000_000; // ps |
parameter eth_stim_num_rx_only_IPG = 800_000; // ps |
|
// Do call/response test |
reg eth_stim_do_rx_reponse_to_tx; |
95,7 → 95,7
|
// Use the smallest possible IPG |
parameter eth_stim_use_min_IPG = 0; |
parameter eth_stim_IPG_delay_max = 500_000_000; // Maximum 500uS ga |
parameter eth_stim_IPG_delay_max = 100_000_000; // Maximum 100 us |
//parameter eth_stim_IPG_delay_max = 100_000_000; // Maximum 100mS between packets |
parameter eth_stim_IPG_min_10mb = 9600_000; // 9.6 uS |
parameter eth_stim_IPG_min_100mb = 800_000; // 860+~100 = 960 nS 100MBit min IPG |
/trunk/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/ethmac_defines.v
45,9 → 45,9
`define ETH_MBIST_CTRL_WIDTH 3 // width of MBIST control bus |
|
// Generic FIFO implementation - hopefully synthesizable with Synplify |
`define ETH_FIFO_GENERIC |
//`define ETH_FIFO_GENERIC |
// Ethernet implemented in Xilinx Chips (uncomment following lines) |
// `define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo |
`define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo |
// `define ETH_XILINX_RAMB4 // Selection of the used memory for Buffer descriptors |
// Core is going to be implemented in Virtex FPGA and contains Virtex |
// specific elements. |
186,9 → 186,10
|
// Defines for ethernet TX fifo size - impacts FPGA resource usage |
//`define ETH_TX_FULL_PACKET_FIFO // Full 1500 byte TX buffer - uncomment this |
//`define ETH_TX_256BYTE_FIFO // 256 byte TX buffer - uncomment this |
//`define ETH_TX_128BYTE_FIFO // 128 byte TX buffer - uncomment this |
`define ETH_TX_256BYTE_FIFO // 256 byte TX buffer - uncomment this |
//`define ETH_TX_512BYTE_FIFO // 512 byte TX buffer - uncomment this |
`define ETH_TX_1KBYTE_FIFO // 1024 byte TX buffer - uncomment this |
//`define ETH_TX_1KBYTE_FIFO // 1024 byte TX buffer - uncomment this |
|
`ifdef ETH_TX_FULL_PACKET_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 9 |
206,19 → 207,22
`define ETH_TX_FIFO_CNT_WIDTH 6 |
`define ETH_TX_FIFO_DEPTH 64 |
`else |
`ifdef ETH_TX_128BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 5 |
`define ETH_TX_FIFO_DEPTH 32 |
`else |
// Default is 64 bytes |
`define ETH_TX_FIFO_CNT_WIDTH 4 |
`define ETH_TX_FIFO_DEPTH 16 |
`define ETH_TX_FIFO_CNT_WIDTH 4 |
`define ETH_TX_FIFO_DEPTH 16 |
`endif |
`endif |
`endif |
`endif // !`ifdef ETH_TX_512BYTE_FIFO |
`endif // !`ifdef ETH_TX_512BYTE_FIFO |
`endif // !`ifdef ETH_TX_FULL_PACKET_FIFO |
|
|
|
// Settings for RX FIFO |
`define ETH_RX_FIFO_CNT_WIDTH 8 |
`define ETH_RX_FIFO_DEPTH 256 |
//`define ETH_RX_FIFO_CNT_WIDTH 8 |
//`define ETH_RX_FIFO_DEPTH 256 |
//`define ETH_RX_FIFO_CNT_WIDTH 7 |
//`define ETH_RX_FIFO_DEPTH 128 |
//`define ETH_RX_FIFO_CNT_WIDTH 6 |
225,8 → 229,8
//`define ETH_RX_FIFO_DEPTH 64 |
//`define ETH_RX_FIFO_CNT_WIDTH 5 |
//`define ETH_RX_FIFO_DEPTH 32 |
//`define ETH_RX_FIFO_CNT_WIDTH 4 |
//`define ETH_RX_FIFO_DEPTH 16 |
`define ETH_RX_FIFO_CNT_WIDTH 4 |
`define ETH_RX_FIFO_DEPTH 16 |
|
`define ETH_RX_FIFO_DATA_WIDTH 32 |
|
243,7 → 247,6
// Undefine this to enable bursting for RX (writing to memory) |
`define ETH_RX_BURST_EN |
|
|
// WISHBONE interface is Revision B3 compliant (uncomment when needed) |
`define ETH_WISHBONE_B3 |
|
252,4 → 255,4
|
// Define this to allow reading of the Wishbone control state machine on reg |
// address 0x58 |
`define WISHBONE_DEBUG |
//`define WISHBONE_DEBUG |
/trunk/orpsocv2/boards/xilinx/ml501/sw/tests/ethmac/sim/ethmac-rxtxcallresponse.c
0,0 → 1,681
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC transmit test code //// |
//// //// |
//// Description //// |
//// Send packets while receiving packets //// |
//// //// |
//// Test data comes from pre-calculated array of random values, //// |
//// MAC TX buffer pointers are set to addresses in this array, //// |
//// saving copying the data around before transfers. //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
static int next_tx_buf_num; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x01000000 |
|
|
#define RXBUFF_PREALLOC 1 |
#define TXBUFF_PREALLOC 1 |
//#undef RXBUFF_PREALLOC |
//#undef TXBUFF_PREALLOC |
|
/* The transmitter timeout |
*/ |
#define TX_TIMEOUT (2*HZ) |
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 16 |
#define OETH_TXBD_NUM 16 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
/* Buffer size |
*/ |
#define OETH_RX_BUFF_SIZE 0x600-4 |
#define OETH_TX_BUFF_SIZE 0x600-4 |
|
/* Buffer size (if not XXBUF_PREALLOC |
*/ |
#define MAX_FRAME_SIZE 1518 |
|
/* The buffer descriptors track the ring buffers. |
*/ |
struct oeth_private { |
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM]; |
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM]; |
|
unsigned short tx_next; /* Next buffer to be sent */ |
unsigned short tx_last; /* Next buffer to be checked if packet sent */ |
unsigned short tx_full; /* Buffer ring fuul indicator */ |
unsigned short rx_cur; /* Next buffer to be checked if packet |
received */ |
|
oeth_regs *regs; /* Address of controller registers. */ |
oeth_bd *rx_bd_base; /* Address of Rx BDs. */ |
oeth_bd *tx_bd_base; /* Address of Tx BDs. */ |
|
// struct net_device_stats stats; |
}; |
|
#define PHYNUM 7 |
|
// Data array of data to transmit, tx_data_array[] |
//#include "eth-rxtx-data.h" // Not used |
int tx_data_pointer; |
|
|
void |
eth_mii_write(char phynum, short regnum, short data) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miitx_data = data; |
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
} |
|
short |
eth_mii_read(char phynum, short regnum) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miicommand = OETH_MIICOMMAND_RSTAT; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
|
return regs->miirx_data; |
} |
|
|
|
// Wait here until all packets have been transmitted |
void |
wait_until_all_tx_clear(void) |
{ |
int i; |
volatile oeth_bd *tx_bd; |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
int some_tx_waiting = 1; |
|
while (some_tx_waiting) |
{ |
some_tx_waiting = 0; |
/* Go through the TX buffs, search for unused one */ |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
|
// Looking for buffer ready for transmit |
if((tx_bd[i].len_status & OETH_TX_BD_READY)) |
some_tx_waiting = 1; |
|
} |
} |
} |
|
|
void |
ethphy_set_10mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 10Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit |
cr &= ~BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethphy_set_100mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 100Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr |= BMCR_ANENABLE; // Clear auto negotiate bit |
cr |= BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* Reset MII mode module */ |
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */ |
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */ |
regs->miimoder = 0x64; /* Clock divider for MII Management interface */ |
|
/* Reset the controller. |
*/ |
regs->moder = OETH_MODER_RST; /* Reset ON */ |
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ |
|
/* Setting TXBD base to OETH_TXBD_NUM. |
*/ |
regs->tx_bd_num = OETH_TXBD_NUM; |
|
|
/* Set min/max packet length |
*/ |
regs->packet_len = 0x00400600; |
|
/* Set IPGT register to recomended value |
*/ |
regs->ipgt = 0x12; |
|
/* Set IPGR1 register to recomended value |
*/ |
regs->ipgr1 = 0x0000000c; |
|
/* Set IPGR2 register to recomended value |
*/ |
regs->ipgr2 = 0x00000012; |
|
/* Set COLLCONF register to recomended value |
*/ |
regs->collconf = 0x000f003f; |
|
/* Set control module mode |
*/ |
#if 0 |
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; |
#else |
regs->ctrlmoder = 0; |
#endif |
|
/* Clear MIIM registers */ |
regs->miitx_data = 0; |
regs->miiaddress = 0; |
regs->miicommand = 0; |
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1; |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5; |
|
/* Clear all pending interrupts |
*/ |
regs->int_src = 0xffffffff; |
|
/* Promisc, IFG, CRCEn |
*/ |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD; |
|
/* Enable interrupt sources. |
*/ |
|
regs->int_mask = OETH_INT_MASK_TXB | |
OETH_INT_MASK_TXE | |
OETH_INT_MASK_RXF | |
OETH_INT_MASK_RXE | |
OETH_INT_MASK_BUSY | |
OETH_INT_MASK_TXC | |
OETH_INT_MASK_RXC; |
|
// Buffer setup stuff |
volatile oeth_bd *tx_bd, *rx_bd; |
int i,j,k; |
|
/* Initialize TXBD pointer |
*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
|
/* Initialize RXBD pointer |
*/ |
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Preallocated ethernet buffer setup */ |
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */ |
|
// Setup TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable RX and TX in MAC |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; |
|
next_tx_buf_num = 0; // init tx buffer pointer |
|
return; |
} |
|
// Enable RX in ethernet MAC |
void |
oeth_enable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder |= OETH_MODER_RXEN; |
} |
|
// Disable RX in ethernet MAC |
void |
oeth_disable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder &= ~(OETH_MODER_RXEN); |
} |
|
|
/* Setup buffer descriptors with data */ |
/* length is in BYTES */ |
void tx_packet(void* data, int length) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
volatile int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
/* Clear all of the status flags. |
*/ |
tx_bd->len_status &= ~OETH_TX_BD_STATS; |
|
/* If the frame is short, tell CPM to pad it. |
*/ |
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ |
if (length <= ETH_ZLEN) |
tx_bd->len_status |= OETH_TX_BD_PAD; |
else |
tx_bd->len_status &= ~OETH_TX_BD_PAD; |
|
#ifdef _ETH_RXTX_DATA_H_ |
// Set the address pointer to the place |
// in memory where the data is and transmit from there |
|
tx_bd->addr = (char*) &tx_data_array[tx_data_pointer&~(0x3)]; |
|
tx_data_pointer += length + 1; |
if (tx_data_pointer > (255*1024)) |
tx_data_pointer = 0; |
|
|
#else |
if (data){ |
//Copy the data into the transmit buffer, byte at a time |
char* data_p = (char*) data; |
char* data_b = (char*) tx_bd->addr; |
for(i=0;i<length;i++) |
{ |
data_b[i] = data_p[i]; |
} |
} |
#endif |
|
/* Set the length of the packet's data in the buffer descriptor */ |
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) | |
((length&0xffff) << 16); |
|
/* Send it on its way. Tell controller its ready, interrupt when sent |
* and to put the CRC on the end. |
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
|
return; |
|
|
} |
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
return; |
} |
|
|
|
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
rx_done++; |
} |
} |
} |
} |
|
|
|
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
|
/* set our test variable */ |
tx_done++; |
|
} |
} |
return; |
} |
|
// A function and defines to fill and transmit a packet |
#define MAX_TX_BUFFER 1532 |
static char tx_buffer[MAX_TX_BUFFER]; |
|
void |
fill_and_tx_call_packet(int size, int response_time) |
{ |
int i; |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (volatile oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
// Use rand() function to generate data for transmission |
// Assumption: ethernet buffer descriptors are 4byte aligned |
char* data_b = (char*) tx_bd->addr; |
// We will fill with words until there' less than a word to go |
int words_to_fill = size / sizeof(unsigned int); |
|
unsigned int* data_w = (unsigned int*) data_b; |
|
// Put first word as size of packet, second as response time |
data_w[0] = size; |
data_w[1] = response_time; |
|
for(i=2;i<words_to_fill;i++) |
data_w[i] = rand(); |
|
// Point data_b to offset wher word fills ended |
data_b += (words_to_fill * sizeof(unsigned int)); |
|
int leftover_size = size - (words_to_fill * sizeof(unsigned int)); |
|
for(i=0;i<leftover_size;i++) |
{ |
data_b[i] = rand() & 0xff; |
} |
|
tx_packet((void*)0, size); |
} |
|
// Send a packet, the very first byte of which will be read by the testbench |
// and used to indicate which test we'll use. |
void |
send_ethmac_rxtx_test_init_packet(char test) |
{ |
char cmd_tx_buffer[40]; |
cmd_tx_buffer[0] = test; |
tx_packet(cmd_tx_buffer, 40); // Smallest packet that can be sent (I think) |
} |
|
// Loop to check if a number is prime by doing mod divide of the number |
// to test by every number less than it |
int |
is_prime_number(unsigned long n) |
{ |
unsigned long c; |
if (n < 2) return 0; |
for(c=2;c<n;c++) |
if ((n % c) == 0) |
return 0; |
return 1; |
} |
|
|
int |
main () |
{ |
tx_data_pointer = 0; |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
/* Enable CPU timer */ |
cpu_enable_timer(); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */ |
|
/* clear tx_done, the tx interrupt handler will set it when it's been |
transmitted */ |
tx_done = 0; |
rx_done = 0; |
|
ethphy_set_100mbit(0); |
|
send_ethmac_rxtx_test_init_packet(0x0); // 0x0 - call response test |
|
#define ETH_TX_MIN_PACKET_SIZE 512 |
#define ETH_TX_NUM_PACKETS (ETH_TX_MIN_PACKET_SIZE + 20) |
|
//int response_time = 150000; // Response time before response packet it sent |
// back (should be in nanoseconds). |
int response_time = 0; |
|
unsigned long num_to_check; |
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
|
// Wait a moment for the RX packet check to complete before switching off RX |
for(num_to_check=0;num_to_check=1000;num_to_check++); |
|
oeth_disable_rx(); |
|
// Now for 10mbit mode... |
ethphy_set_10mbit(0); |
|
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
oeth_disable_rx(); |
|
// Go back to 100-mbit mode |
ethphy_set_100mbit(0); |
|
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
exit(0x8000000d); |
|
} |
/trunk/orpsocv2/boards/xilinx/ml501/sw/tests/ethmac/sim/ethmac-rxtx.c
0,0 → 1,671
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC transmit test code //// |
//// //// |
//// Description //// |
//// Send packets while receiving packets //// |
//// //// |
//// Test data comes from pre-calculated array of random values, //// |
//// MAC TX buffer pointers are set to addresses in this array, //// |
//// saving copying the data around before transfers. //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
static int next_tx_buf_num; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x200000; |
|
|
#define RXBUFF_PREALLOC 1 |
#define TXBUFF_PREALLOC 1 |
//#undef RXBUFF_PREALLOC |
//#undef TXBUFF_PREALLOC |
|
/* The transmitter timeout |
*/ |
#define TX_TIMEOUT (2*HZ) |
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 16 |
#define OETH_TXBD_NUM 16 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
/* Buffer size |
*/ |
#define OETH_RX_BUFF_SIZE 0x600-4 |
#define OETH_TX_BUFF_SIZE 0x600-4 |
|
/* Buffer size (if not XXBUF_PREALLOC |
*/ |
#define MAX_FRAME_SIZE 1518 |
|
/* The buffer descriptors track the ring buffers. |
*/ |
struct oeth_private { |
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM]; |
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM]; |
|
unsigned short tx_next; /* Next buffer to be sent */ |
unsigned short tx_last; /* Next buffer to be checked if packet sent */ |
unsigned short tx_full; /* Buffer ring fuul indicator */ |
unsigned short rx_cur; /* Next buffer to be checked if packet |
received */ |
|
oeth_regs *regs; /* Address of controller registers. */ |
oeth_bd *rx_bd_base; /* Address of Rx BDs. */ |
oeth_bd *tx_bd_base; /* Address of Tx BDs. */ |
|
// struct net_device_stats stats; |
}; |
|
#define PHYNUM 7 |
|
// Data array of data to transmit, tx_data_array[] |
//#include "eth-rxtx-data.h" // Not used |
int tx_data_pointer; |
|
|
void |
eth_mii_write(char phynum, short regnum, short data) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miitx_data = data; |
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
} |
|
short |
eth_mii_read(char phynum, short regnum) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miicommand = OETH_MIICOMMAND_RSTAT; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
|
return regs->miirx_data; |
} |
|
|
|
// Wait here until all packets have been transmitted |
void |
wait_until_all_tx_clear(void) |
{ |
int i; |
volatile oeth_bd *tx_bd; |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
int some_tx_waiting = 1; |
|
while (some_tx_waiting) |
{ |
some_tx_waiting = 0; |
/* Go through the TX buffs, search for unused one */ |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
|
// Looking for buffer ready for transmit |
if((tx_bd[i].len_status & OETH_TX_BD_READY)) |
some_tx_waiting = 1; |
|
} |
} |
} |
|
|
void |
ethphy_set_10mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 10Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit |
cr &= ~BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethphy_set_100mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 100Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr |= BMCR_ANENABLE; // Clear auto negotiate bit |
cr |= BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* Reset MII mode module */ |
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */ |
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */ |
regs->miimoder = 0x64; /* Clock divider for MII Management interface */ |
|
/* Reset the controller. |
*/ |
regs->moder = OETH_MODER_RST; /* Reset ON */ |
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ |
|
/* Setting TXBD base to OETH_TXBD_NUM. |
*/ |
regs->tx_bd_num = OETH_TXBD_NUM; |
|
|
/* Set min/max packet length |
*/ |
regs->packet_len = 0x00400600; |
|
/* Set IPGT register to recomended value |
*/ |
regs->ipgt = 0x12; |
|
/* Set IPGR1 register to recomended value |
*/ |
regs->ipgr1 = 0x0000000c; |
|
/* Set IPGR2 register to recomended value |
*/ |
regs->ipgr2 = 0x00000012; |
|
/* Set COLLCONF register to recomended value |
*/ |
regs->collconf = 0x000f003f; |
|
/* Set control module mode |
*/ |
#if 0 |
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; |
#else |
regs->ctrlmoder = 0; |
#endif |
|
/* Clear MIIM registers */ |
regs->miitx_data = 0; |
regs->miiaddress = 0; |
regs->miicommand = 0; |
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1; |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5; |
|
/* Clear all pending interrupts |
*/ |
regs->int_src = 0xffffffff; |
|
/* Promisc, IFG, CRCEn |
*/ |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD; |
|
/* Enable interrupt sources. |
*/ |
|
regs->int_mask = OETH_INT_MASK_TXB | |
OETH_INT_MASK_TXE | |
OETH_INT_MASK_RXF | |
OETH_INT_MASK_RXE | |
OETH_INT_MASK_BUSY | |
OETH_INT_MASK_TXC | |
OETH_INT_MASK_RXC; |
|
// Buffer setup stuff |
volatile oeth_bd *tx_bd, *rx_bd; |
int i,j,k; |
|
/* Initialize TXBD pointer |
*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
|
/* Initialize RXBD pointer |
*/ |
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Preallocated ethernet buffer setup */ |
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */ |
|
// Setup TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable RX and TX in MAC |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; |
|
next_tx_buf_num = 0; // init tx buffer pointer |
|
return; |
} |
|
// Enable RX in ethernet MAC |
void |
oeth_enable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder |= OETH_MODER_RXEN; |
} |
|
// Disable RX in ethernet MAC |
void |
oeth_disable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder &= ~(OETH_MODER_RXEN); |
} |
|
|
/* Setup buffer descriptors with data */ |
/* length is in BYTES */ |
void tx_packet(void* data, int length) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
volatile int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
/* Clear all of the status flags. |
*/ |
tx_bd->len_status &= ~OETH_TX_BD_STATS; |
|
/* If the frame is short, tell CPM to pad it. |
*/ |
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ |
if (length <= ETH_ZLEN) |
tx_bd->len_status |= OETH_TX_BD_PAD; |
else |
tx_bd->len_status &= ~OETH_TX_BD_PAD; |
|
#ifdef _ETH_RXTX_DATA_H_ |
// Set the address pointer to the place |
// in memory where the data is and transmit from there |
|
tx_bd->addr = (char*) &tx_data_array[tx_data_pointer&~(0x3)]; |
|
tx_data_pointer += length + 1; |
if (tx_data_pointer > (255*1024)) |
tx_data_pointer = 0; |
|
|
#else |
if (data){ |
//Copy the data into the transmit buffer, byte at a time |
char* data_p = (char*) data; |
char* data_b = (char*) tx_bd->addr; |
for(i=0;i<length;i++) |
{ |
data_b[i] = data_p[i]; |
} |
} |
#endif |
|
/* Set the length of the packet's data in the buffer descriptor */ |
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) | |
((length&0xffff) << 16); |
|
/* Send it on its way. Tell controller its ready, interrupt when sent |
* and to put the CRC on the end. |
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
|
return; |
|
|
} |
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
return; |
} |
|
|
|
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
rx_done++; |
} |
} |
} |
} |
|
|
|
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
|
/* set our test variable */ |
tx_done++; |
|
} |
} |
return; |
} |
|
// A function and defines to fill and transmit a packet |
#define MAX_TX_BUFFER 1532 |
static char tx_buffer[MAX_TX_BUFFER]; |
|
void |
fill_and_tx_packet(int size) |
{ |
int i; |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (volatile oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
// Use rand() function to generate data for transmission |
// Assumption: ethernet buffer descriptors are 4byte aligned |
char* data_b = (char*) tx_bd->addr; |
// We will fill with words until there' less than a word to go |
int words_to_fill = size / sizeof(unsigned int); |
|
unsigned int* data_w = (unsigned int*) data_b; |
|
for(i=0;i<words_to_fill;i++) |
data_w[i] = rand(); |
|
// Point data_b to offset wher word fills ended |
data_b += (words_to_fill * sizeof(unsigned int)); |
|
int leftover_size = size - (words_to_fill * sizeof(unsigned int)); |
|
for(i=0;i<leftover_size;i++) |
{ |
data_b[i] = rand() & 0xff; |
} |
|
tx_packet((void*)0, size); |
} |
|
// Send a packet, the very first byte of which will be read by the testbench |
// and used to indicate which test we'll use. |
void |
send_ethmac_rxtx_test_init_packet(char test) |
{ |
char cmd_tx_buffer[40]; |
cmd_tx_buffer[0] = test; |
tx_packet(cmd_tx_buffer, 40); // Smallest packet that can be sent (I think) |
} |
|
// Loop to check if a number is prime by doing mod divide of the number |
// to test by every number less than it |
int |
is_prime_number(unsigned long n) |
{ |
unsigned long c; |
if (n < 2) return 0; |
for(c=2;c<n;c++) |
if ((n % c) == 0) |
return 0; |
return 1; |
} |
|
|
int |
main () |
{ |
tx_data_pointer = 0; |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
/* Enable CPU timer */ |
cpu_enable_timer(); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */ |
|
/* clear tx_done, the tx interrupt handler will set it when it's been |
transmitted */ |
tx_done = 0; |
rx_done = 0; |
|
ethphy_set_100mbit(0); |
|
send_ethmac_rxtx_test_init_packet(0xff); // Test value of 0xFF |
|
//oeth_enable_rx(); |
|
#define ETH_TX_MIN_PACKET_SIZE 512 |
#define ETH_TX_NUM_PACKETS (ETH_TX_MIN_PACKET_SIZE + 32) |
|
unsigned long num_to_check; |
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_packet(num_to_check); |
|
oeth_disable_rx(); |
|
// Now for 10mbit mode... |
ethphy_set_10mbit(0); |
|
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_packet(num_to_check); |
|
oeth_disable_rx(); |
|
// Go back to 100-mbit mode |
ethphy_set_100mbit(0); |
|
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_packet(num_to_check); |
|
exit(0x8000000d); |
|
} |
/trunk/orpsocv2/boards/xilinx/ml501/sw/tests/ethmac/sim/ethmac-rx.c
0,0 → 1,470
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC test code //// |
//// //// |
//// Description //// |
//// Do ethernet receive path testing //// |
//// Relies on testbench to provide simulus - expects at least //// |
//// 256 packets to be sent. //// |
//// //// |
//// Author(s): //// |
//// - Julius Baxter, julius@opencores.org //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
void oeth_dump_bds(); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
/* Function to calculate checksum of ping responses we send */ |
unsigned short calculate_checksum(char* dats, unsigned int len) ; |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x200000; |
|
#define RXBUFF_PREALLOC 1 |
#define TXBUFF_PREALLOC 1 |
|
/* The transmitter timeout |
*/ |
#define TX_TIMEOUT (2*HZ) |
|
/* Buffer number (must be 2^n) |
* Note: if changing these, must also change settings in eth_stim.v testbench |
* file! |
*/ |
#define OETH_RXBD_NUM 16 |
#define OETH_TXBD_NUM 16 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
/* Buffer size |
*/ |
#define OETH_RX_BUFF_SIZE 0x600 |
#define OETH_TX_BUFF_SIZE 0x600 |
|
/* Buffer size (if not XXBUF_PREALLOC |
*/ |
#define MAX_FRAME_SIZE 1518 |
|
/* The buffer descriptors track the ring buffers. |
*/ |
struct oeth_private { |
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM]; |
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM]; |
|
unsigned short tx_next; /* Next buffer to be sent */ |
unsigned short tx_last; /* Next buffer to be checked if packet sent */ |
unsigned short tx_full; /* Buffer ring fuul indicator */ |
unsigned short rx_cur; /* Next buffer to be checked if packet received */ |
|
oeth_regs *regs; /* Address of controller registers. */ |
oeth_bd *rx_bd_base; /* Address of Rx BDs. */ |
oeth_bd *tx_bd_base; /* Address of Tx BDs. */ |
|
// struct net_device_stats stats; |
}; |
|
|
char CHECKSUM_BUFFER[OETH_RX_BUFF_SIZE]; // Big enough to hold a packet |
|
#define PHYNUM 7 |
|
void ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* Reset MII mode module */ |
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */ |
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */ |
regs->miimoder = 0x64; /* Clock divider for MII Management interface */ |
|
/* Reset the controller. |
*/ |
regs->moder = OETH_MODER_RST; /* Reset ON */ |
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ |
|
/* Setting TXBD base to OETH_TXBD_NUM. |
*/ |
regs->tx_bd_num = OETH_TXBD_NUM; |
|
|
/* Set min/max packet length |
*/ |
regs->packet_len = 0x00400600; |
|
/* Set IPGT register to recomended value |
*/ |
regs->ipgt = 0x12; |
|
/* Set IPGR1 register to recomended value |
*/ |
regs->ipgr1 = 0x0000000c; |
|
/* Set IPGR2 register to recomended value |
*/ |
regs->ipgr2 = 0x00000012; |
|
/* Set COLLCONF register to recomended value |
*/ |
regs->collconf = 0x000f003f; |
|
/* Set control module mode |
*/ |
#if 0 |
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; |
#else |
regs->ctrlmoder = 0; |
#endif |
|
/* Clear MIIM registers */ |
regs->miitx_data = 0; |
regs->miiaddress = 0; |
regs->miicommand = 0; |
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1; |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5; |
|
/* Clear all pending interrupts |
*/ |
regs->int_src = 0xffffffff; |
|
/* Promisc, IFG, CRCEn |
*/ |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD; |
|
/* Enable interrupt sources. |
*/ |
|
regs->int_mask = OETH_INT_MASK_TXB | |
OETH_INT_MASK_TXE | |
OETH_INT_MASK_RXF | |
OETH_INT_MASK_RXE | |
OETH_INT_MASK_BUSY | |
OETH_INT_MASK_TXC | |
OETH_INT_MASK_RXC; |
|
// Buffer setup stuff |
volatile oeth_bd *tx_bd, *rx_bd; |
int i,j,k; |
|
/* Initialize TXBD pointer |
*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
|
/* Initialize RXBD pointer |
*/ |
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Preallocated ethernet buffer setup */ |
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */ |
|
// Setup TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable just the receiver |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= OETH_MODER_RXEN /* | OETH_MODER_TXEN*/; |
|
return; |
} |
|
void |
ethmac_halt(void) |
{ |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
// Disable receive and transmit |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
|
} |
|
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
return; |
} |
|
|
|
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
/* Looking for buffer descriptors marked not empty */ |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ |
/* Check status for errors. |
*/ |
report(i); |
report(rx_bdp[i].len_status); |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
//exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* |
* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
// Do a bit of work - ie. copy it, process it |
memcpy(CHECKSUM_BUFFER, rx_bdp[i].addr, pkt_len); |
report(0xc4eccccc); |
report(calculate_checksum(CHECKSUM_BUFFER, pkt_len)); |
|
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
rx_done++; |
report(rx_done); |
} |
} |
} |
} |
|
// Calculate checksum on received data. |
// From http://lkml.indiana.edu/hypermail/linux/kernel/9612.3/0060.html |
unsigned short calculate_checksum(char* dats, unsigned int len) |
{ |
unsigned int itr; |
unsigned long accum = 0; |
unsigned long longsum; |
|
// Sum all pairs of data |
for(itr=0;itr<(len & ~0x1);itr+=2) |
accum += (unsigned long)(((dats[itr]<<8)&0xff00)|(dats[itr+1]&0x00ff)); |
|
if (len & 0x1) // Do leftover |
accum += (unsigned long) ((dats[itr-1]<<8)&0xff00); |
|
longsum = (unsigned long) (accum & 0xffff); |
longsum += (unsigned long) (accum >> 16); // Sum the carries |
longsum += (longsum >> 16); |
return (unsigned short)((longsum ^ 0xffff) & 0xffff); |
|
} |
|
|
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
|
/* set our test variable */ |
tx_done = 1; |
|
} |
} |
return; |
} |
|
// Loop to check if a number is prime by doing mod divide of the number |
// to test by every number less than it |
int |
is_prime_number(unsigned long n) |
{ |
unsigned long c; |
if (n < 2) return 0; |
for(c=2;c<n;c++) |
if ((n % c) == 0) |
return 0; |
return 1; |
} |
|
int |
main () |
{ |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
/* Enable CPU timer */ |
cpu_enable_timer(); |
|
rx_done = 0; |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX in MODER */ |
|
#define NUM_PRIMES_TO_CHECK 1000 |
#define RX_TEST_LENGTH_PACKETS 12 |
|
char prime_check_results[NUM_PRIMES_TO_CHECK]; |
unsigned long num_to_check; |
|
for(num_to_check=2;num_to_check<NUM_PRIMES_TO_CHECK;num_to_check++) |
{ |
prime_check_results[num_to_check-2] |
= (char) is_prime_number(num_to_check); |
report(num_to_check | (0x1e<<24)); |
report(prime_check_results[num_to_check-2] | (0x2e<<24)); |
// Check number of packets received, testbench will hopefully send at |
// least this many packets |
if (rx_done >= (RX_TEST_LENGTH_PACKETS - 1)) |
exit(0x8000000d); |
} |
|
ethmac_halt(); |
|
exit(0x8000000d); |
|
return 0; |
} |
/trunk/orpsocv2/boards/xilinx/ml501/sw/tests/ethmac/sim/ethmac-tx.c
0,0 → 1,589
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC transmit test code //// |
//// //// |
//// Description //// |
//// Transmits packets, testing both 100mbit and 10mbit modes. //// |
//// Expects testbench to be checking each packet sent. //// |
//// Define, ETH_TX_TEST_LENGTH, set further down, controls how //// |
//// many packets the test will send. //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
static int next_tx_buf_num; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x200000; |
|
#define RXBUFF_PREALLOC 1 |
#define TXBUFF_PREALLOC 1 |
//#undef RXBUFF_PREALLOC |
//#undef TXBUFF_PREALLOC |
|
/* The transmitter timeout |
*/ |
#define TX_TIMEOUT (2*HZ) |
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 16 |
#define OETH_TXBD_NUM 16 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
/* Buffer size |
*/ |
#define OETH_RX_BUFF_SIZE 0x600 - 4 |
#define OETH_TX_BUFF_SIZE 0x600 - 4 |
|
/* Buffer size (if not XXBUF_PREALLOC |
*/ |
#define MAX_FRAME_SIZE 1518 |
|
/* The buffer descriptors track the ring buffers. |
*/ |
struct oeth_private { |
|
unsigned short tx_next;/* Next buffer to be sent */ |
unsigned short tx_last;/* Next buffer to be checked if packet sent */ |
unsigned short tx_full;/* Buffer ring fuul indicator */ |
unsigned short rx_cur; /* Next buffer to check if packet received */ |
|
oeth_regs *regs; /* Address of controller registers. */ |
oeth_bd *rx_bd_base; /* Address of Rx BDs. */ |
oeth_bd *tx_bd_base; /* Address of Tx BDs. */ |
|
// struct net_device_stats stats; |
}; |
|
|
// Data array of data to transmit, tx_data_array[] |
// Not included in ORPSoC - #include "eth-rxtx-data.h" |
//int tx_data_pointer; |
|
#define PHYNUM 7 |
|
void |
eth_mii_write(char phynum, short regnum, short data) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miitx_data = data; |
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
} |
|
short |
eth_mii_read(char phynum, short regnum) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miicommand = OETH_MIICOMMAND_RSTAT; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
|
return regs->miirx_data; |
} |
|
|
// Wait here until all packets have been transmitted |
void wait_until_all_tx_clear(void) |
{ |
|
int i; |
volatile oeth_bd *tx_bd; |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
int some_tx_waiting = 1; |
|
while (some_tx_waiting) |
{ |
some_tx_waiting = 0; |
/* Go through the TX buffs, search for unused one */ |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
|
if((tx_bd[i].len_status & OETH_TX_BD_READY)) // Looking for buffer ready for transmit |
some_tx_waiting = 1; |
|
} |
} |
|
} |
|
|
void |
ethphy_set_10mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 10Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit |
cr &= ~BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethphy_set_100mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 100Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr |= BMCR_ANENABLE; // Clear auto negotiate bit |
cr |= BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* Reset MII mode module */ |
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */ |
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */ |
regs->miimoder = 0x64; /* Clock divider for MII Management interface */ |
|
/* Reset the controller. |
*/ |
regs->moder = OETH_MODER_RST; /* Reset ON */ |
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ |
|
/* Setting TXBD base to OETH_TXBD_NUM. |
*/ |
regs->tx_bd_num = OETH_TXBD_NUM; |
|
|
/* Set min/max packet length |
*/ |
regs->packet_len = 0x00400600; |
|
/* Set IPGT register to recomended value |
*/ |
regs->ipgt = 0x12; |
|
/* Set IPGR1 register to recomended value |
*/ |
regs->ipgr1 = 0x0000000c; |
|
/* Set IPGR2 register to recomended value |
*/ |
regs->ipgr2 = 0x00000012; |
|
/* Set COLLCONF register to recomended value |
*/ |
regs->collconf = 0x000f003f; |
|
/* Set control module mode |
*/ |
#if 0 |
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; |
#else |
regs->ctrlmoder = 0; |
#endif |
|
/* Clear MIIM registers */ |
regs->miitx_data = 0; |
regs->miiaddress = 0; |
regs->miicommand = 0; |
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1; |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5; |
|
/* Clear all pending interrupts |
*/ |
regs->int_src = 0xffffffff; |
|
/* Promisc, IFG, CRCEn |
*/ |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD; |
|
/* Enable interrupt sources. |
*/ |
|
regs->int_mask = OETH_INT_MASK_TXB | |
OETH_INT_MASK_TXE | |
OETH_INT_MASK_RXF | |
OETH_INT_MASK_RXE | |
OETH_INT_MASK_BUSY | |
OETH_INT_MASK_TXC | |
OETH_INT_MASK_RXC; |
|
// Buffer setup stuff |
volatile oeth_bd *tx_bd, *rx_bd; |
int i,j,k; |
|
/* Initialize TXBD pointer |
*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
|
/* Initialize RXBD pointer |
*/ |
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Preallocated ethernet buffer setup */ |
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */ |
|
// Setup TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable JUST the transmiter |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= /*OETH_MODER_RXEN |*/ OETH_MODER_TXEN; |
|
next_tx_buf_num = 0; // init tx buffer pointer |
|
return; |
} |
|
|
|
/* Setup buffer descriptors with data */ |
/* length is in BYTES */ |
void tx_packet(void* data, int length) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
volatile int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
/* Clear all of the status flags. |
*/ |
tx_bd->len_status &= ~OETH_TX_BD_STATS; |
|
/* If the frame is short, tell CPM to pad it. |
*/ |
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ |
if (length <= ETH_ZLEN) |
tx_bd->len_status |= OETH_TX_BD_PAD; |
else |
tx_bd->len_status &= ~OETH_TX_BD_PAD; |
|
if (data){ |
//Copy the data into the transmit buffer, byte at a time |
char* data_p = (char*) data; |
char* data_b = (char*) tx_bd->addr; |
for(i=0;i<length;i++) |
{ |
data_b[i] = data_p[i]; |
} |
} |
|
/* Set the length of the packet's data in the buffer descriptor */ |
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) | |
((length&0xffff) << 16); |
|
/* Send it on its way. Tell controller its ready, interrupt when sent |
* and to put the CRC on the end. |
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
|
return; |
|
} |
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
return; |
} |
|
|
|
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
/* Do something here with the data - copy it into userspace, perhaps*/ |
|
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
rx_done++; |
} |
} |
} |
} |
|
|
|
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
|
/* set our test variable */ |
tx_done++; |
|
} |
} |
return; |
} |
|
// A function and defines to fill and transmit a packet |
#define MAX_TX_BUFFER 1532 |
static char tx_buffer[MAX_TX_BUFFER]; |
|
void |
fill_and_tx_packet(int size) |
{ |
int i; |
char tx_byte; |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
// Use rand() function to generate data for transmission |
// Assumption: ethernet buffer descriptors are 4byte aligned |
char* data_b = (char*) tx_bd->addr; |
// We will fill with words until there' less than a word to go |
int words_to_fill = size/ sizeof(unsigned int); |
unsigned int* data_w = (unsigned int*) data_b; |
|
for(i=0;i<words_to_fill;i++) |
data_w[i] = rand(); |
|
// Point data_b to offset wher word fills ended |
data_b += (words_to_fill * sizeof(unsigned int)); |
|
int leftover_size = size - (words_to_fill * sizeof(unsigned int)); |
|
for(i=0;i<leftover_size;i++) |
{ |
data_b[i] = rand()&0xff; |
} |
|
tx_packet((void*)0, size); |
} |
|
int |
main () |
{ |
int i; |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */ |
|
/* clear tx_done, the tx interrupt handler will set it when it's been transmitted */ |
tx_done = 0; |
rx_done = 0; |
|
ethphy_set_100mbit(0); |
|
#ifndef ETH_TX_TEST_LENGTH |
# define ETH_TX_START_LENGTH 40 |
# define ETH_TX_TEST_LENGTH 1024 |
# define ETH_TX_TEST_LENGTH_INCREMENT 21 |
//# define ETH_TX_TEST_LENGTH OETH_TX_BUFF_SIZE |
#endif |
|
for(i=ETH_TX_START_LENGTH;i<ETH_TX_TEST_LENGTH; |
i+=ETH_TX_TEST_LENGTH_INCREMENT) |
fill_and_tx_packet(i); |
|
ethphy_set_10mbit(0); |
|
for(i=ETH_TX_START_LENGTH;i<ETH_TX_TEST_LENGTH; |
i+=ETH_TX_TEST_LENGTH_INCREMENT) |
fill_and_tx_packet(i); |
|
exit(0x8000000d); |
|
|
} |
/trunk/orpsocv2/boards/xilinx/ml501/sw/tests/ethmac/sim/Makefile
0,0 → 1,14
# Set the path to our board's root directory |
BOARD_SW_ROOT=../../.. |
|
include $(BOARD_SW_ROOT)/Makefile.inc |
|
%.dis: %.elf |
$(Q)$(OR32_OBJDUMP) -d $< > $@ |
|
%.bin: %.elf |
$(Q)$(OR32_OBJCOPY) -O binary $< $@ |
|
clean: |
$(Q)rm -f *.elf *.bin *.vmem *.flashin *.dis |
|
/trunk/orpsocv2/boards/xilinx/ml501/sw/board/include/board.h
62,4 → 62,14
// |
#define TICKS_PER_SEC 100 |
|
|
|
// |
// UART driver configuration |
// |
#define UART_NUM_CORES 1 |
#define UART_BASE_ADDRESSES_CSV UART0_BASE |
#define UART_BAUD_RATES_CSV UART0_BAUD_RATE |
|
|
#endif |