OpenCores
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 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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.