URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1580 to Rev 1581
- ↔ Reverse comparison
Rev 1580 → Rev 1581
/trunk/rc203soc/rtl/verilog/or1200/rtl/verilog/or1200_defines.v
44,6 → 44,9
// CVS Revision History |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.1.1.1 2004/12/13 17:15:47 jcastillo |
// Firt import of OR1200 over Celoxica RC203 platform |
// |
// Revision 1.42 2004/06/08 18:17:36 lampret |
// Non-functional changes. Coding style fixes. |
// |
315,7 → 318,7
// Target FPGA memories |
// |
//`define OR1200_ALTERA_LPM |
`define OR1200_XILINX_RAMB |
`define OR1200_XILINX_RAMB4 |
//`define OR1200_XILINX_RAM32X1D |
//`define OR1200_USE_RAM16X1D_FOR_RAM32X1D |
// |
/trunk/rc203soc/readme.rc200
0,0 → 1,26
Notes on running this design on an RC200: |
|
Building the hardware |
--------------------- |
* Synthesise using Synplicity and the script: syn/synplicity/rc200.tcl. |
|
* Place-and-route the resulting edif (rc200soc.edf) along with |
the constraint file: backend/xilinx/rc200soc.ucf |
|
* Note: I found that with ISE 7.1.04i, and Synplify Pro 8.0 I was unable meet |
the timing for a 50 MHz clock (as selected in the UCF). In practice though |
the error margin is narrow enough for the design to probably work anyway. |
|
|
Building the software |
--------------------- |
* In the jtag server source, comment out the dbg_test() procedure call in |
main(). This prevents initialisation of devices not present in this |
design. |
|
* If the or1200_defines.v file is not changed to enable the trace buffer |
(OR1200_DU_TB_IMPLEMENTED), change the gdb source by commenting out the |
call to or1k_read_trace() in remote-or1k.c:or1k_wait(). |
|
* Modify the board.h file for orpmon or hello-uart programs to reflect |
the 50MHz clock-speed. |
/trunk/rc203soc/backend/xilinx/soc.ucf
File deleted
/trunk/rc203soc/backend/xilinx/rc200soc.ucf
0,0 → 1,97
NET "clk" LOC = "E12" ; # This is connected to the 50MHz clock |
NET "clk" TNM_NET = "clk"; |
TIMESPEC "TS_clk" = PERIOD "clk" 20 ns HIGH 50 %; |
|
NET "jtag_tck" LOC = "N3" ; |
NET "jtag_tdi" LOC = "T2" ; |
NET "jtag_tdo" LOC = "R3" ; |
NET "jtag_tms" LOC = "P4" ; |
NET "jtag_tck" TNM_NET = "jtag_tck"; |
TIMESPEC "TS_jtag_tck" = PERIOD "jtag_tck" 30 ns HIGH 50 %; |
|
NET "reset" LOC = "J5" ; |
NET "sram_address[0]" LOC = "C21" ; |
NET "sram_address[1]" LOC = "C22" ; |
NET "sram_address[2]" LOC = "D21" ; |
NET "sram_address[3]" LOC = "D22" ; |
NET "sram_address[4]" LOC = "E21" ; |
NET "sram_address[5]" LOC = "F21" ; |
NET "sram_address[6]" LOC = "F22" ; |
NET "sram_address[7]" LOC = "G21" ; |
NET "sram_address[8]" LOC = "G22" ; |
NET "sram_address[9]" LOC = "H21" ; |
NET "sram_address[10]" LOC = "J21" ; |
NET "sram_address[11]" LOC = "J22" ; |
NET "sram_address[12]" LOC = "K21" ; |
NET "sram_address[13]" LOC = "K22" ; |
NET "sram_address[14]" LOC = "L22" ; |
NET "sram_address[15]" LOC = "L21" ; |
NET "sram_address[16]" LOC = "E19" ; |
NET "sram_address[17]" LOC = "E20" ; |
NET "sram_address[18]" LOC = "F19" ; |
NET "sram_address[19]" LOC = "F20" ; |
NET "sram_clk" LOC = "F12" ; |
NET "sram_data[0]" LOC = "K20" ; |
NET "sram_data[1]" LOC = "L19" ; |
NET "sram_data[2]" LOC = "L20" ; |
NET "sram_data[3]" LOC = "K18" ; |
NET "sram_data[4]" LOC = "L18" ; |
NET "sram_data[5]" LOC = "E18" ; |
NET "sram_data[6]" LOC = "F18" ; |
NET "sram_data[7]" LOC = "G18" ; |
NET "sram_data[8]" LOC = "H18" ; |
NET "sram_data[9]" LOC = "J18" ; |
NET "sram_data[10]" LOC = "J17" ; |
NET "sram_data[11]" LOC = "K17" ; |
NET "sram_data[12]" LOC = "B12" ; |
NET "sram_data[13]" LOC = "A13" ; |
NET "sram_data[14]" LOC = "B13" ; |
NET "sram_data[15]" LOC = "A14" ; |
NET "sram_data[16]" LOC = "B14" ; |
NET "sram_data[17]" LOC = "B15" ; |
NET "sram_data[18]" LOC = "A16" ; |
NET "sram_data[19]" LOC = "B16" ; |
NET "sram_data[20]" LOC = "A17" ; |
NET "sram_data[21]" LOC = "B17" ; |
NET "sram_data[22]" LOC = "B18" ; |
NET "sram_data[23]" LOC = "A19" ; |
NET "sram_data[24]" LOC = "B19" ; |
NET "sram_data[25]" LOC = "C12" ; |
NET "sram_data[26]" LOC = "D12" ; |
NET "sram_data[27]" LOC = "C13" ; |
NET "sram_data[28]" LOC = "D13" ; |
NET "sram_data[29]" LOC = "C14" ; |
NET "sram_data[30]" LOC = "D14" ; |
NET "sram_data[31]" LOC = "C15" ; |
NET "sram_nBW[0]" LOC = "J20" ; |
NET "sram_nBW[1]" LOC = "K19" ; |
NET "sram_nBW[2]" LOC = "H20" ; |
NET "sram_nBW[3]" LOC = "J19" ; |
NET "sram_nCS" LOC = "G19" ; |
NET "sram_nRW" LOC = "G20" ; |
NET "uart_srx" LOC = "U20" ; |
NET "uart_stx" LOC = "V20" ; |
NET "eth_data[0]" LOC = "M21" ; |
NET "eth_data[1]" LOC = "N22" ; |
NET "eth_data[2]" LOC = "N21" ; |
NET "eth_data[3]" LOC = "P22" ; |
NET "eth_data[4]" LOC = "P21" ; |
NET "eth_data[5]" LOC = "R21" ; |
NET "eth_data[6]" LOC = "T22" ; |
NET "eth_data[7]" LOC = "T21" ; |
NET "eth_data[8]" LOC = "U22" ; |
NET "eth_data[9]" LOC = "U21" ; |
NET "eth_data[10]" LOC = "V21" ; |
NET "eth_data[11]" LOC = "W22" ; |
NET "eth_data[12]" LOC = "W21" ; |
NET "eth_data[13]" LOC = "Y22" ; |
NET "eth_data[14]" LOC = "Y21" ; |
NET "eth_data[15]" LOC = "M17" ; |
NET "eth_address[0]" LOC = "M18" ; |
NET "eth_address[1]" LOC = "M20" ; |
NET "eth_address[2]" LOC = "M19" ; |
NET "eth_nBE[0]" LOC = "N20" ; |
NET "eth_nBE[1]" LOC = "N19" ; |
NET "eth_nWRITE" LOC = "P19" ; |
NET "eth_nREAD" LOC = "P20" ; |
NET "eth_reset" LOC = "T20" ; |
/trunk/rc203soc/backend/xilinx/rc203soc.ucf
0,0 → 1,100
NET "clk" LOC = "E13" ; |
NET "clk" TNM_NET = "clk"; |
TIMESPEC "TS_clk" = PERIOD "clk" 30 ns HIGH 50 %; |
#PACE: Start of Constraints generated by PACE |
|
#PACE: Start of PACE I/O Pin Assignments |
NET "jtag_tck" LOC = "U3" ; |
NET "jtag_tdi" LOC = "P7" ; |
NET "jtag_tdo" LOC = "Y4" ; |
NET "jtag_tms" LOC = "T8" ; |
NET "reset" LOC = "L7" ; |
NET "sram_address[0]" LOC = "E23" ; |
NET "sram_address[10]" LOC = "L23" ; |
NET "sram_address[11]" LOC = "L24" ; |
NET "sram_address[12]" LOC = "M23" ; |
NET "sram_address[13]" LOC = "M24" ; |
NET "sram_address[14]" LOC = "N24" ; |
NET "sram_address[15]" LOC = "N23" ; |
NET "sram_address[16]" LOC = "G21" ; |
NET "sram_address[17]" LOC = "G22" ; |
NET "sram_address[18]" LOC = "H21" ; |
NET "sram_address[19]" LOC = "H22" ; |
NET "sram_address[1]" LOC = "E24" ; |
NET "sram_address[2]" LOC = "F23" ; |
NET "sram_address[3]" LOC = "F24" ; |
NET "sram_address[4]" LOC = "G23" ; |
NET "sram_address[5]" LOC = "H23" ; |
NET "sram_address[6]" LOC = "H24" ; |
NET "sram_address[7]" LOC = "J23" ; |
NET "sram_address[8]" LOC = "J24" ; |
NET "sram_address[9]" LOC = "K23" ; |
NET "sram_clk" LOC = "H14" ; |
NET "sram_data[0]" LOC = "M22" ; |
NET "sram_data[10]" LOC = "L19" ; |
NET "sram_data[11]" LOC = "M19" ; |
NET "sram_data[12]" LOC = "D14" ; |
NET "sram_data[13]" LOC = "C15" ; |
NET "sram_data[14]" LOC = "D15" ; |
NET "sram_data[15]" LOC = "C16" ; |
NET "sram_data[16]" LOC = "D16" ; |
NET "sram_data[17]" LOC = "D17" ; |
NET "sram_data[18]" LOC = "C18" ; |
NET "sram_data[19]" LOC = "D18" ; |
NET "sram_data[1]" LOC = "N21" ; |
NET "sram_data[20]" LOC = "C19" ; |
NET "sram_data[21]" LOC = "D19" ; |
NET "sram_data[22]" LOC = "D20" ; |
NET "sram_data[23]" LOC = "C21" ; |
NET "sram_data[24]" LOC = "D21" ; |
NET "sram_data[25]" LOC = "E14" ; |
NET "sram_data[26]" LOC = "F14" ; |
NET "sram_data[27]" LOC = "E15" ; |
NET "sram_data[28]" LOC = "F15" ; |
NET "sram_data[29]" LOC = "E16" ; |
NET "sram_data[2]" LOC = "N22" ; |
NET "sram_data[30]" LOC = "F16" ; |
NET "sram_data[31]" LOC = "E17" ; |
NET "sram_data[3]" LOC = "M20" ; |
NET "sram_data[4]" LOC = "N20" ; |
NET "sram_data[5]" LOC = "G20" ; |
NET "sram_data[6]" LOC = "H20" ; |
NET "sram_data[7]" LOC = "J20" ; |
NET "sram_data[8]" LOC = "K20" ; |
NET "sram_data[9]" LOC = "L20" ; |
NET "sram_nBW[0]" LOC = "L22" ; |
NET "sram_nBW[1]" LOC = "M21" ; |
NET "sram_nBW[2]" LOC = "K22" ; |
NET "sram_nBW[3]" LOC = "L21" ; |
NET "sram_nCS" LOC = "J21" ; |
NET "sram_nRW" LOC = "J22" ; |
NET "uart_srx" LOC = "W22" ; |
NET "uart_stx" LOC = "Y22" ; |
NET "eth_data[0]" LOC = "P23" ; |
NET "eth_data[1]" LOC = "R24" ; |
NET "eth_data[2]" LOC = "R23" ; |
NET "eth_data[3]" LOC = "T24" ; |
NET "eth_data[4]" LOC = "T23" ; |
NET "eth_data[5]" LOC = "U23" ; |
NET "eth_data[6]" LOC = "V24" ; |
NET "eth_data[7]" LOC = "V23" ; |
NET "eth_data[8]" LOC = "W24" ; |
NET "eth_data[9]" LOC = "W23" ; |
NET "eth_data[10]" LOC = "Y23" ; |
NET "eth_data[11]" LOC = "AA24" ; |
NET "eth_data[12]" LOC = "AA23" ; |
NET "eth_data[13]" LOC = "AB24" ; |
NET "eth_data[14]" LOC = "AB23" ; |
NET "eth_data[15]" LOC = "P19" ; |
NET "eth_address[0]" LOC = "P20" ; |
NET "eth_address[1]" LOC = "P22" ; |
NET "eth_address[2]" LOC = "P21" ; |
NET "eth_nBE[0]" LOC = "R22" ; |
NET "eth_nBE[1]" LOC = "R21" ; |
NET "eth_nWRITE" LOC = "T21" ; |
NET "eth_nREAD" LOC = "T22" ; |
NET "eth_reset" LOC = "V22" ; |
|
#PACE: Start of PACE Prohibit Constraints |
|
#PACE: End of Constraints generated by PACE |
/trunk/rc203soc/syn/synplicity/rc200.tcl
0,0 → 1,130
project -new |
|
#Select FPGA |
set_option -technology VIRTEX2 |
set_option -part XC2V1000 |
set_option -grade -4 |
set_option -package FG456 |
set_option -frequency 50.0 |
|
|
# |
# Add files to project |
# |
|
|
# Memory controllers |
add_file "../../rtl/verilog/rc203/rc203_zbtcontroller.v" |
add_file "../../rtl/verilog/rc203/rc203_romcontroller.v" |
add_file "../../rtl/verilog/rc203/rc203_ethcontroller.v" |
|
# RAM wrapppers |
add_file "../RAMB4_S16_S16.v" |
add_file "../RAMB4_S4.v" |
add_file "../RAMB4_S16.v" |
|
# Dbg_interface |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_wb_defines.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_cpu.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_cpu_defines.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_cpu_registers.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_crc32_d1.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_defines.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_register.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_top.v" |
add_file "../../rtl/verilog/dbg_interface/rtl/verilog/dbg_wb.v" |
|
# Tap controller |
add_file "../../rtl/verilog/jtag/tap/rtl/verilog/tap_defines.v" |
add_file "../../rtl/verilog/jtag/tap/rtl/verilog/tap_top.v" |
|
# UART 16550 |
add_file "../../rtl/verilog/uart16550/rtl/verilog/raminfr.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_debug_if.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_defines.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_receiver.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_regs.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_rfifo.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_sync_flops.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_tfifo.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_top.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_transmitter.v" |
add_file "../../rtl/verilog/uart16550/rtl/verilog/uart_wb.v" |
|
# OR1200 (with 4KB data and instruction caches) |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_alu.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_amultp2_32x32.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_cfgr.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_cpu.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_ctrl.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dc_fsm.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dc_ram.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dc_tag.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dc_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_defines.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dmmu_tlb.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dmmu_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_du.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_except.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_freeze.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_genpc.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_gmultp2_32x32.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_ic_fsm.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_ic_ram.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_ic_tag.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_ic_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_if.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_immu_tlb.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_immu_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_iwb_biu.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_lsu.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_mem2reg.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_mult_mac.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_operandmuxes.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_pic.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_pm.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_qmem_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_reg2mem.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_rf.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_sb.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_sb_fifo.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_sprs.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_top.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_tt.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_wbmux.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_wb_biu.v" |
|
# Depending of cache size and register file type you must add or |
# remove some of this files |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_dpram_32x32.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_rfram_generic.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_tpram_32x32.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_1024x32.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_1024x32_bw.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_1024x8.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_128x32.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_2048x32.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_2048x32_bw.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_2048x8.v" |
add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_256x21.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_32x24.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_512x20.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_64x14.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_64x22.v" |
#add_file "../../rtl/verilog/or1200/rtl/verilog/or1200_spram_64x24.v" |
|
# Top files |
add_file "../../rtl/verilog/tc_top.v" |
add_file "../../rtl/verilog/soc.v" |
|
# Include or1200_defines.v path |
set_option -include_path "../../rtl/verilog/or1200/rtl/verilog/" |
|
# Results |
impl -name "./rev_1" |
set_option -result_file "./rev_1/rc200soc.edf" |
set_option -top_module soc |
|
|
#RUN |
project -run synthesis |
/trunk/rc203soc/sw/jtag/gdb2.c
0,0 → 1,583
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <stdarg.h> |
|
/* Libraries for JTAG proxy server. */ |
#include <sys/stat.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <sys/select.h> |
#include <sys/poll.h> |
#include <fcntl.h> |
#include <netdb.h> |
#include <netinet/tcp.h> |
#include <inttypes.h> |
#include <errno.h> |
|
#include "gdb.h" /* partially copied from gdb/config/or1k */ |
#include "jp.h" /* just for debug() */ |
#include "jp2.h" |
|
|
/* connection to jp2 routines */ |
int gdb_chain = -1; |
|
int gdb_read_reg(unsigned long adr, unsigned long *data) { |
debug("rr %d\n", gdb_chain); |
switch (gdb_chain) { |
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_REGISTER: return dbg_cpu0_read_ctrl(adr, (unsigned char*)data) ? ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_TRACE: *data = 0; return 0; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_write_reg(unsigned long adr, unsigned long data) { |
debug("wr %d\n", gdb_chain); |
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */ |
case SC_RISC_DEBUG: if (adr == JTAG_RISCOP) adr = 0x00; |
return dbg_cpu0_write(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_REGISTER: return dbg_cpu0_write_ctrl(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_TRACE: return 0; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_read_block(unsigned long adr, unsigned long *data, int len) { |
debug("rb %d\n", gdb_chain); |
switch (gdb_chain) { |
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_write_block(unsigned long adr, unsigned long *data, int len) { |
debug("wb %d\n", gdb_chain); |
switch (gdb_chain) { |
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_set_chain(int chain) { |
debug("set_chain %d\n", chain); |
switch (chain) { |
case SC_RISC_DEBUG: |
case SC_REGISTER: |
case SC_TRACE: |
case SC_WISHBONE: gdb_chain = chain; |
return ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
|
|
/************************ |
JTAG Server Routines |
************************/ |
|
unsigned int serverIP = 0; |
unsigned int serverPort = 0; |
unsigned int server_fd = 0; |
unsigned int gdb_fd = 0; |
static int gdb_read(void*, int); |
static int gdb_write(void*, int); |
static void ProtocolClean(int, int32_t); |
|
static int tcp_level = 0; |
|
/* Added by CZ 24/05/01 */ |
int GetServerSocket(const char* name, const char* proto, int port) { |
struct servent *service; |
struct protoent *protocol; |
struct sockaddr_in sa; |
struct hostent *hp; |
int sockfd; |
char myname[256]; |
int flags; |
char sTemp[256]; |
|
/* First, get the protocol number of TCP */ |
if (!(protocol = getprotobyname(proto))) { |
sprintf(sTemp, "Unable to load protocol \"%s\"", proto); |
perror(sTemp); |
return 0; |
} |
tcp_level = protocol->p_proto; /* Save for later */ |
|
/* If we weren't passed a non standard port, get the port |
from the services directory. */ |
if (!port && (service = getservbyname(name, protocol->p_name))) |
port = ntohs(service->s_port); |
|
/* Create the socket using the TCP protocol */ |
if ((sockfd = socket(PF_INET, SOCK_STREAM, protocol->p_proto)) < 0) { |
perror("Unable to create socket"); |
return 0; |
} |
|
flags = 1; |
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flags, sizeof(int)) < 0) { |
sprintf(sTemp, "Can not set SO_REUSEADDR option on socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* The server should also be non blocking. Get the current flags. */ |
if((flags = fcntl(sockfd, F_GETFL, 0)) < 0) { |
sprintf(sTemp, "Unable to get flags for socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* Set the nonblocking flag */ |
if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { |
sprintf(sTemp, "Unable to set flags for socket %d to value 0x%08x", |
sockfd, flags | O_NONBLOCK); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* Find out what our address is */ |
memset(&sa, 0, sizeof(struct sockaddr_in)); |
gethostname(myname, sizeof(myname)); |
if(!(hp = gethostbyname(myname))) { |
perror("Unable to read hostname"); |
close(sockfd); |
return 0; |
} |
|
/* Bind our socket to the appropriate address */ |
sa.sin_family = hp->h_addrtype; |
sa.sin_port = htons(port); |
if(bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) { |
sprintf(sTemp, "Unable to bind socket %d to port %d", sockfd, port); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
serverIP = sa.sin_addr.s_addr; |
flags = sizeof(struct sockaddr_in); |
if(getsockname(sockfd, (struct sockaddr*)&sa, &flags) < 0) { |
sprintf(sTemp, "Unable to get socket information for socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
serverPort = ntohs(sa.sin_port); |
|
/* Set the backlog to 1 connections */ |
if(listen(sockfd, 1) < 0) { |
sprintf(sTemp, "Unable to set backlog on socket %d to %d", sockfd, 1); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
return sockfd; |
} |
|
void HandleServerSocket(Boolean block) { |
struct pollfd fds[2]; |
int n; |
|
rebuild: |
n = 0; |
if(!server_fd && !gdb_fd) return; |
|
if(server_fd) { |
fds[n].fd = server_fd; |
fds[n].events = POLLIN; |
fds[n++].revents = 0; |
} |
if(gdb_fd) { |
fds[n].fd = gdb_fd; |
fds[n].events = POLLIN; |
fds[n++].revents = 0; |
} |
|
while(1) { |
switch(poll(fds, n, -1)) { |
case 0: |
case -1: |
if(errno == EINTR) continue; |
perror("poll"); |
server_fd = 0; |
return; |
default: |
/* Make sure to handle the gdb port first! */ |
if (gdb_fd && (fds[0].revents && !server_fd || fds[1].revents && server_fd)) { |
int revents = server_fd ? fds[1].revents : fds[0].revents; |
if (revents & POLLIN) GDBRequest(); |
else {/* Error Occurred */ |
fprintf(stderr, "Received flags 0x%08x on gdb socket. Shutting down.\n", revents); |
close(gdb_fd); |
gdb_fd = 0; |
} |
} |
if(fds[0].revents && server_fd) { |
if(fds[0].revents & POLLIN) { |
JTAGRequest(); |
goto rebuild; |
} else { /* Error Occurred */ |
fprintf(stderr, "Received flags 0x%08x on server. Shutting down.\n", fds[0].revents); |
close(server_fd); |
server_fd = 0; |
serverPort = 0; |
serverIP = 0; |
return; |
} |
} |
break; |
} /* End of switch statement */ |
} /* End of while statement */ |
} |
|
void JTAGRequest() { |
struct sockaddr_in sa; |
struct sockaddr* addr = (struct sockaddr*)&sa; |
int n = sizeof(struct sockaddr_in); |
int fd = accept(server_fd, addr, &n); |
int on_off = 0; /* Turn off Nagel's algorithm on the socket */ |
int flags; |
char sTemp[256]; |
|
if(fd < 0) { |
/* This is valid, because a connection could have started, |
and then terminated due to a protocol error or user |
initiation before the accept could take place. */ |
if(errno != EWOULDBLOCK && errno != EAGAIN) { |
perror("accept"); |
close(server_fd); |
server_fd = 0; |
serverPort = 0; |
serverIP = 0; |
} |
return; |
} |
|
if(gdb_fd) { |
close(fd); |
return; |
} |
|
if((flags = fcntl(fd, F_GETFL, 0)) < 0) { |
sprintf(sTemp, "Unable to get flags for gdb socket %d", fd); |
perror(sTemp); |
close(fd); |
return; |
} |
|
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { |
sprintf(sTemp, "Unable to set flags for gdb socket %d to value 0x%08x", |
fd, flags | O_NONBLOCK); |
perror(sTemp); |
close(fd); |
return; |
} |
|
if(setsockopt(fd, tcp_level, TCP_NODELAY, &on_off, sizeof(int)) < 0) { |
sprintf(sTemp, "Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", fd); |
perror(sTemp); |
close(fd); |
return; |
} |
|
gdb_fd = fd; |
} |
|
void GDBRequest() { |
JTAGProxyWriteMessage msg_write; |
JTAGProxyReadMessage msg_read; |
JTAGProxyChainMessage msg_chain; |
JTAGProxyWriteResponse resp_write; |
JTAGProxyReadResponse resp_read; |
JTAGProxyChainResponse resp_chain; |
JTAGProxyBlockWriteMessage *msg_bwrite; |
JTAGProxyBlockReadMessage msg_bread; |
JTAGProxyBlockWriteResponse resp_bwrite; |
JTAGProxyBlockReadResponse *resp_bread; |
char *buf; |
unsigned long long data; |
uint32_t command, length; |
int len, i; |
int err = 0; |
|
/* First, we must read the incomming command */ |
if(gdb_read(&command, sizeof(uint32_t)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 1"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
if(gdb_read(&length, sizeof(uint32_t)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 2"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
length = ntohl(length); |
|
/* Now, verify the protocol and implement the command */ |
switch(ntohl(command)) { |
case JTAG_COMMAND_WRITE: |
if(length != sizeof(msg_write) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_write; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 3"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_write.address = ntohl(msg_write.address); |
msg_write.data_H = ntohl(msg_write.data_H); |
msg_write.data_L = ntohl(msg_write.data_L); |
err = gdb_write_reg(msg_write.address, msg_write.data_L); |
resp_write.status = htonl(err); |
if(gdb_write(&resp_write, sizeof(resp_write)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 4"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_READ: |
if(length != sizeof(msg_read) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_read; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_read.address = ntohl(msg_read.address); |
err = gdb_read_reg(msg_read.address, (unsigned long *)&resp_read.data_L); |
resp_read.status = htonl(err); |
resp_read.data_H = 0; |
resp_read.data_L = htonl(resp_read.data_L); |
if(gdb_write(&resp_read, sizeof(resp_read)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 6"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_WRITE: |
if(length < sizeof(JTAGProxyBlockWriteMessage)-8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
if(!(buf = (char*)malloc(8+length))) { |
ProtocolClean(length, JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
msg_bwrite->address = ntohl(msg_bwrite->address); |
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters); |
for(i=0;i<msg_bwrite->nRegisters;i++) { |
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]); |
} |
err = gdb_write_block(msg_bwrite->address, (unsigned long*)msg_bwrite->data, msg_bwrite->nRegisters * 4); |
resp_bwrite.status = htonl(err); |
free(buf); |
msg_bwrite = (JTAGProxyBlockWriteMessage *)NULL; |
buf = (char *)msg_bwrite; |
if(gdb_write(&resp_bwrite, sizeof(resp_bwrite)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 4"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_READ: |
if(length != sizeof(msg_bread) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_bread; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_bread.address = ntohl(msg_bread.address); |
msg_bread.nRegisters = ntohl(msg_bread.nRegisters); |
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1); |
if(!(buf = (char*)malloc(len))) { |
ProtocolClean(0, JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
resp_bread = (JTAGProxyBlockReadResponse*)buf; |
err = gdb_read_block(msg_bread.address, (unsigned long*)resp_bread->data, msg_bread.nRegisters * 4); |
for(i=0;i<msg_bread.nRegisters;i++) { |
/* Read previous, address next one. */ |
resp_bread->data[i] = htonl(resp_bread->data[i]); |
} |
resp_bread->status = htonl(err); |
resp_bread->nRegisters = htonl(msg_bread.nRegisters); |
if(gdb_write(resp_bread, len) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 6"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
free(buf); |
resp_bread = (JTAGProxyBlockReadResponse *)NULL; |
buf = (char *)resp_bread; |
break; |
case JTAG_COMMAND_CHAIN: |
if(length != sizeof(msg_chain) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_chain; |
if(gdb_read(&buf[8], sizeof(msg_chain)-8) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 7"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_chain.chain = htonl(msg_chain.chain); |
err = gdb_set_chain(msg_chain.chain); |
resp_chain.status = htonl(err); |
if(gdb_write(&resp_chain, sizeof(resp_chain)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 8"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
default: |
perror("Unknown JTAG command."); |
ProtocolClean(length, JTAG_PROXY_COMMAND_NOT_IMPLEMENTED); |
break; |
} |
} |
|
static void ProtocolClean(int length, int32_t err) { |
char buf[4096]; |
|
err = htonl(err); |
if((gdb_read(buf, length) < 0) || (gdb_write(&err, sizeof(err)) < 0) && gdb_fd) { |
perror("gdb socket - 9"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
} |
|
static int gdb_write(void* buf, int len) { |
int n; |
char* w_buf = (char*)buf; |
struct pollfd block; |
|
while(len) { |
if((n = write(gdb_fd, w_buf, len)) < 0) { |
switch(errno) { |
case EWOULDBLOCK: /* or EAGAIN */ |
/* We've been called on a descriptor marked |
for nonblocking I/O. We better simulate |
blocking behavior. */ |
block.fd = gdb_fd; |
block.events = POLLOUT; |
block.revents = 0; |
poll(&block, 1, -1); |
continue; |
case EINTR: |
continue; |
case EPIPE: |
close(gdb_fd); |
gdb_fd = 0; |
return -1; |
default: |
return -1; |
} |
} else { |
len -= n; |
w_buf += n; |
} |
} |
return 0; |
} |
|
static int gdb_read(void* buf, int len) { |
int n; |
char* r_buf = (char*)buf; |
struct pollfd block; |
|
while(len) { |
if((n = read(gdb_fd, r_buf, len)) < 0) { |
switch(errno) { |
case EWOULDBLOCK: /* or EAGAIN */ |
/* We've been called on a descriptor marked |
for nonblocking I/O. We better simulate |
blocking behavior. */ |
block.fd = gdb_fd; |
block.events = POLLIN; |
block.revents = 0; |
poll(&block, 1, -1); |
continue; |
case EINTR: |
continue; |
default: |
return -1; |
} |
} else if(n == 0) { |
close(gdb_fd); |
gdb_fd = 0; |
return -1; |
} else { |
len -= n; |
r_buf += n; |
} |
} |
return 0; |
} |
/trunk/rc203soc/sw/jtag/jp-io.c
0,0 → 1,443
/* jp-io.c -- Low level JTAG communications |
Copyright (C) 2001 Marko Mlinar, markom@opencores.org |
|
Code for TCP/IP copied from gdb, by Chris Ziomkowski |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* This handles all the low-level io with the selected cable */ |
|
#include <stdio.h> |
#include <stdint.h> |
#include <string.h> |
#include <sys/io.h> |
#include <sys/types.h> |
#include <unistd.h> |
#include <errno.h> |
#include <stdlib.h> |
|
#include <sys/socket.h> |
#include <sys/un.h> |
|
#include "jp.h" |
|
static int jp_parallel_init(); |
static void jp_parallel_out(uint8_t value); |
static uint8_t jp_parallel_in(); |
static int jp_parallel_opt(int c, char *str); |
|
static void jp_phys_wait(); |
|
static int jp_rtl_sim_init(); |
static void jp_rtl_sim_out(uint8_t value); |
static uint8_t jp_rtl_sim_in(); |
static void jp_rtl_sim_wait(); |
static int jp_rtl_sim_opt(int c, char *str); |
|
static int jp_vpi_init(); |
static void jp_vpi_out(uint8_t value); |
static uint8_t jp_vpi_in(); |
static void jp_vpi_wait(); |
static int jp_vpi_opt(int c, char *str); |
|
static uint8_t jp_xpc3_in(); |
static void jp_xpc3_out(uint8_t value); |
|
static uint8_t jp_xess_in(); |
static void jp_xess_out(uint8_t value); |
|
static struct jtag_cable { |
const char *name; |
uint8_t (*in_func)(); |
void (*out_func)(uint8_t); |
int (*init_func)(); |
void (*wait_func)(); |
int (*opt_func)(int c, char *str); |
const char *opts; |
const char *help; |
} jtag_cables[] = { |
{ "rtl_sim", jp_rtl_sim_in, jp_rtl_sim_out, jp_rtl_sim_init, jp_rtl_sim_wait, |
jp_rtl_sim_opt, "d:", |
"-d [directory] Directory in which gdb_in.dat/gdb_out.dat may be found\n" }, |
{ "vpi", jp_vpi_in, jp_vpi_out, jp_vpi_init, jp_vpi_wait, jp_vpi_opt, "s:", |
"-s [socket] Location of socket that the vpi module created\n" }, |
{ "xpc3", jp_xpc3_in, jp_xpc3_out, jp_parallel_init, jp_phys_wait, |
jp_parallel_opt, "p:", |
"-p [port] Which port to use when communicateing with the parport hardware (eg. 0x378)\n" }, |
{ "xess", jp_xess_in, jp_xess_out, jp_parallel_init, jp_phys_wait, |
jp_parallel_opt, "p:", |
"-p [port] Which port to use when communicateing with the parport hardware (eg. 0x378)\n" }, |
{ NULL, NULL, NULL, NULL } }; |
|
static struct jtag_cable *jtag_cable_in_use = NULL; /* The current selected cable */ |
|
/* Only used for the parport */ |
static int base = 0x378; |
|
/* Only used in the vpi */ |
static int vpi_comm; |
static char *sock_loc = "/tmp/jp-vpi"; |
|
/* Only used for the rtl_sim */ |
static char *gdb_in = "gdb_in.dat"; |
static char *gdb_out = "gdb_out.dat"; |
|
void jp_out (uint8_t value) |
{ |
/* finally call the cable-specific out-function */ |
jtag_cable_in_use->out_func(value); |
|
if(!(value & 1)) |
debug("[%x%c]", (value & TDI_BIT) != 0, (value & TMS_BIT) ? '^' : '_'); |
flush_debug(); |
} |
|
/* Receive a byte from the board. */ |
uint8_t jp_in() |
{ |
int data; |
|
/* Get the data from the board */ |
data = jtag_cable_in_use->in_func(); |
|
debug(" R%01X ", data); |
flush_debug(); |
return data; |
} |
|
/* waits */ |
void jp_wait() |
{ |
jtag_cable_in_use->wait_func(); |
} |
|
/* Selects a cable for use, returns non-null on success */ |
int jp_select_cable(const char *cable) |
{ |
int i; |
|
for(i = 0; jtag_cables[i].name; i++) { |
if(!strcmp(cable, jtag_cables[i].name)) { |
jtag_cable_in_use = &jtag_cables[i]; |
return 1; |
} |
} |
|
return 0; |
} |
|
/* Calls the init-fucntion of the cable */ |
int jp_init_cable() |
{ |
return jtag_cable_in_use->init_func(); |
} |
|
/* Parses command-line options specific to the selected cable */ |
int jp_cable_opt(int c, char *str) |
{ |
return jtag_cable_in_use->opt_func(c, str); |
} |
|
const char *jp_get_cable_args() |
{ |
return jtag_cable_in_use->opts; |
} |
|
/* Prints a (short) useage message for each availible cable */ |
void jp_print_cable_help() |
{ |
int i; |
printf("Availible cables: "); |
|
for(i = 0; jtag_cables[i].name; i++) { |
if(i) |
printf(", "); |
printf(jtag_cables[i].name); |
} |
|
printf("\n\nOptions availible for the cables:\n"); |
for(i = 0; jtag_cables[i].name; i++) { |
if(!jtag_cables[i].help) |
continue; |
printf(" %s:\n %s", jtag_cables[i].name, jtag_cables[i].help); |
} |
} |
|
/*-------------------------------------[ Parallel port specific functions ]---*/ |
static int jp_parallel_init() |
{ |
if (ioperm(base, 3, 1)) { |
fprintf(stderr, "Couldn't get the port at %x\n", base); |
perror("Root privileges are required.\n"); |
return 0; |
} |
printf("Connected to parallel port at %x\n", base); |
printf("Dropping root privileges.\n"); |
setreuid(getuid(), getuid()); |
return 1; |
} |
|
static void jp_parallel_out(uint8_t value) |
{ |
outb(value, LPT_WRITE); |
} |
|
static uint8_t jp_parallel_in() |
{ |
return inb(LPT_READ); |
} |
|
static int jp_parallel_opt(int c, char *str) |
{ |
switch(c) { |
case 'p': |
if(!sscanf(str, "%x", &base)) { |
fprintf(stderr, "p parameter must have a hex number as parameter\n"); |
return 0; |
} |
break; |
default: |
fprintf(stderr, "Unknown parameter '%c'\n", c); |
return 0; |
} |
return 1; |
} |
|
/*-----------------------------------------[ Physical board wait function ]---*/ |
static void jp_phys_wait() |
{ |
/* FIXME: this needs some real TLC */ |
int i; |
volatile int j; |
for(i = 0; i < 1000; i++) |
j = i; |
} |
|
/*----------------------------------------------[ xpc3 specific functions ]---*/ |
static void jp_xpc3_out(uint8_t value) |
{ |
uint8_t out = 0; |
|
/* First convert the bits in value byte to the ones that the cable wants */ |
if(value & TCLK_BIT) |
out |= 0x02; /* D1 pin 3 */ |
if(value & TRST_BIT) |
out |= 0x10; /* Not used */ |
if(value & TDI_BIT) |
out |= 0x01; /* D0 pin 2 */ |
if(value & TMS_BIT) |
out |= 0x04; /* D2 pin 4 */ |
|
jp_parallel_out(out); |
} |
|
static uint8_t jp_xpc3_in() |
{ |
uint8_t in; |
|
in = jp_parallel_in(); |
|
if(in & 0x10) /* S6 pin 13 */ |
return 1; |
return 0; |
} |
|
/*----------------------------------------------[ xess specific functions ]---*/ |
static void jp_xess_out(uint8_t value) |
{ |
uint8_t out = 0; |
|
/* First convert the bits in value byte to the ones that the cable wants */ |
if(value & TCLK_BIT) |
out |= 0x04; /* D2 pin 4 */ |
if(value & TRST_BIT) |
out |= 0x08; /* D3 pin 5 */ |
if(value & TDI_BIT) |
out |= 0x10; /* D4 pin 6 */ |
if(value & TMS_BIT) |
out |= 0x20; /* D3 pin 5 */ |
|
jp_parallel_out(out); |
} |
|
static uint8_t jp_xess_in() |
{ |
uint8_t in; |
|
in = jp_parallel_in(); |
|
if(in & 0x20) /* S5 pin 12*/ |
return 1; |
return 0; |
} |
|
/*-------------------------------------------[ rtl_sim specific functions ]---*/ |
static int jp_rtl_sim_init() |
{ |
FILE *fin = fopen (gdb_in, "wt+"); |
if(!fin) { |
fprintf(stderr, "Can not open %s\n", gdb_in); |
return 0; |
} |
fclose(fin); |
return 1; |
} |
|
static void jp_rtl_sim_out(uint8_t value) |
{ |
FILE *fout; |
int num_read; |
int r; |
fout = fopen(gdb_in, "wt+"); |
fprintf(fout, "F\n"); |
fclose(fout); |
fout = fopen(gdb_out, "wt+"); |
fprintf(fout, "%02X\n", value); |
fclose(fout); |
do { |
fout = fopen(gdb_out, "rt"); |
r = fscanf(fout,"%x", &num_read); |
fclose(fout); |
} while(!r || (num_read != (0x10 | value))); |
} |
|
static uint8_t jp_rtl_sim_in() |
{ |
FILE *fin = 0; |
char ch; |
uint8_t data; |
while(1) { |
fin = fopen(gdb_in, "rt"); |
if(!fin) |
continue; |
ch = fgetc(fin); |
fclose(fin); |
if((ch != '0') && (ch != '1')) |
continue; |
else |
break; |
} |
data = ch == '1' ? 1 : 0; |
return data; |
} |
|
static void jp_rtl_sim_wait() |
{ |
usleep(1000); |
} |
|
static int jp_rtl_sim_opt(int c, char *str) |
{ |
switch(c) { |
case 'd': |
if(!(gdb_in = malloc(strlen(str) + 12))) { /* 12 == strlen("gdb_in.dat") + 2 */ |
fprintf(stderr, "Unable to allocate enough memory\n"); |
return 0; |
} |
if(!(gdb_out = malloc(strlen(str) + 13))) { /* 13 == strlen("gdb_out.dat") + 2 */ |
fprintf(stderr, "Unable to allocate enough memory\n"); |
free(gdb_in); |
return 0; |
} |
|
sprintf(gdb_in, "%s/gdb_in.dat", str); |
sprintf(gdb_out, "%s/gdb_out.dat", str); |
break; |
default: |
fprintf(stderr, "Unknown parameter '%c'\n", c); |
return 0; |
} |
return 1; |
} |
|
/*-----------------------------------------------[ VPI specific functions ]---*/ |
static int jp_vpi_init() |
{ |
struct sockaddr_un addr; |
|
if((vpi_comm = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { |
fprintf(stderr, "Unable to create socket (%s)\n", strerror(errno)); |
return 0; |
} |
|
addr.sun_family = AF_UNIX; |
strcpy(addr.sun_path, sock_loc); |
|
if(connect(vpi_comm, (struct sockaddr *)&addr, sizeof(addr)) == -1) { |
fprintf(stderr, "Unable to connect to %s (%s)\n", addr.sun_path, |
strerror(errno)); |
return 0; |
} |
return 1; |
} |
|
static void jp_vpi_out(uint8_t value) |
{ |
uint8_t ack; |
|
/* Send the data to the socket */ |
write(vpi_comm, &value, 1); |
|
do { |
/* Ok, read the data */ |
read(vpi_comm, &ack, 1); |
} while(ack != (value | 0x10)); |
} |
|
static uint8_t jp_vpi_in() |
{ |
uint8_t dat; |
|
/* ask vpi to send us the out-bit */ |
dat = 0x80; |
write(vpi_comm, &dat, 1); |
|
/* Wait and read the data */ |
read(vpi_comm, &dat, 1); |
|
if(dat > 1) |
fprintf(stderr, "Unexpected value: %i\n", dat); |
|
return dat; |
} |
|
static void jp_vpi_wait() |
{ |
uint8_t dat = 0x81; |
|
/* Get the sim to reply when the timeout has been reached */ |
write(vpi_comm, &dat, 1); |
|
/* block, waiting for the data */ |
read(vpi_comm, &dat, 1); |
} |
|
static int jp_vpi_opt(int c, char *str) |
{ |
switch(c) { |
case 's': |
if(!(sock_loc = strdup(str))) { |
fprintf(stderr, "Unable to allocate memory\n"); |
return 0; |
} |
break; |
default: |
fprintf(stderr, "Unknown parameter '%c'\n", c); |
return 0; |
} |
return 1; |
} |
/trunk/rc203soc/sw/jtag/jp.h
0,0 → 1,41
|
#define LPT_READ (base+1) |
#define LPT_WRITE base |
|
#define TCLK_BIT (0x01) |
#define TRST_BIT (0x02) |
#define TDI_BIT (0x04) |
#define TMS_BIT (0x08) |
#define TDO_BIT (0x20) |
#define TMS (0x02) |
#define TDI (0x01) |
|
#ifdef DEBUG |
#define debug printf |
#else |
#define debug |
#endif |
|
#ifdef DEBUG2 |
#define debug2 printf |
#else |
#define debug2 |
#endif |
|
#if (DEBUG) || (DEBUG2) |
#define flush_debug() fflush(stdout) |
#else |
#define flush_debug() |
#endif |
|
void jp_out (uint8_t value); |
uint8_t jp_in(); |
int jp_select_cable(const char *cable); |
void jp_wait(); |
int jp_cable_opt(int c, char *str); |
void jp_print_cable_help(); |
const char *jp_get_cable_args(); |
int jp_init_cable(); |
|
# define NUM_RETRIES (16) |
# define JTAG_RETRY_WAIT() usleep (1000) |
/trunk/rc203soc/sw/jtag/jp2.h
0,0 → 1,76
#ifndef _JP2_H_ |
#define _JP2_H_ |
|
#define Boolean int |
#define false 0 |
#define true 1 |
|
/* Selects crc trailer size in bits. Currently supported: 8 */ |
#define CRC_SIZE (8) |
|
/* Scan chain size in bits. */ |
#define SC_SIZE (4) |
|
#ifndef ULONGEST |
#define ULONGEST unsigned long |
#endif |
|
extern unsigned int serverPort; |
extern unsigned int server_fd; |
extern void HandleServerSocket(Boolean block); |
|
extern int err; |
extern void JTAGRequest(void); |
extern void GDBRequest(void); |
|
/* read a word from wishbone */ |
int dbg_wb_read32(unsigned long adr, unsigned long *data); |
|
/* write a word to wishbone */ |
int dbg_wb_write32(unsigned long adr, unsigned long data); |
|
/* read a block from wishbone */ |
int dbg_wb_read_block32(unsigned long adr, unsigned long *data, int len); |
|
/* write a block to wishbone */ |
int dbg_wb_write_block32(unsigned long adr, unsigned long *data, int len); |
|
/* read a register from cpu */ |
int dbg_cpu0_read(unsigned long adr, unsigned long *data); |
|
/* read a register from cpu module */ |
int dbg_cpu0_read_ctrl(unsigned long adr, unsigned char *data); |
|
/* write a cpu register */ |
int dbg_cpu0_write(unsigned long adr, unsigned long data); |
|
/* write a cpu module register */ |
int dbg_cpu0_write_ctrl(unsigned long adr, unsigned char data); |
|
|
#define DC_SIZE 4 |
#define DC_STATUS_SIZE 4 |
|
#define DC_WISHBONE 0 |
#define DC_CPU0 1 |
#define DC_CPU1 2 |
|
#define DI_GO 0 |
#define DI_READ_CMD 1 |
#define DI_WRITE_CMD 2 |
#define DI_READ_CTRL 3 |
#define DI_WRITE_CTRL 4 |
|
#define DBG_CRC_SIZE 32 |
#define DBG_CRC_POLY 0x04c11db7 |
|
#define DBG_ERR_OK 0 |
#define DBG_ERR_CRC 8 |
|
#define NUM_SOFT_RETRIES 3 |
#define NUM_HARD_RETRIES 3 |
#define NUM_ACCESS_RETRIES 10 |
|
#define CHECK(x) check(__FILE__, __LINE__, (x)) |
#endif /* _JP2_H_ */ |
|
/trunk/rc203soc/sw/jtag/gdb.h
0,0 → 1,169
/* config.h -- Simulator configuration header file |
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#ifndef GDB_H |
#define GDB_H |
|
#include <sys/types.h> |
#include <inttypes.h> |
|
/* Possible errors are listed here. */ |
enum enum_errors /* modified <chris@asics.ws> CZ 24/05/01 */ |
{ |
/* Codes > 0 are for system errors */ |
|
ERR_NONE = 0, |
ERR_CRC = -1, |
ERR_MEM = -2, |
JTAG_PROXY_INVALID_COMMAND = -3, |
JTAG_PROXY_SERVER_TERMINATED = -4, |
JTAG_PROXY_NO_CONNECTION = -5, |
JTAG_PROXY_PROTOCOL_ERROR = -6, |
JTAG_PROXY_COMMAND_NOT_IMPLEMENTED = -7, |
JTAG_PROXY_INVALID_CHAIN = -8, |
JTAG_PROXY_INVALID_ADDRESS = -9, |
JTAG_PROXY_ACCESS_EXCEPTION = -10, /* Write to ROM */ |
JTAG_PROXY_INVALID_LENGTH = -11, |
JTAG_PROXY_OUT_OF_MEMORY = -12, |
}; |
|
/* All JTAG chains. */ |
enum jtag_chains |
{ |
SC_GLOBAL, /* 0 Global BS Chain */ |
SC_RISC_DEBUG, /* 1 RISC Debug Interface chain */ |
SC_RISC_TEST, /* 2 RISC Test Chain */ |
SC_TRACE, /* 3 Trace Chain */ |
SC_REGISTER, /* Register Chain */ |
SC_WISHBONE, /* 5 Memory chain */ |
SC_BLOCK, /* Block Chains */ |
}; |
|
/* See JTAG documentation about these. */ |
#define JI_SIZE (4) |
enum jtag_instr |
{ |
JI_EXTEST, |
JI_SAMPLE_PRELOAD, |
JI_IDCODE, |
JI_CHAIN_SELECT, |
JI_INTEST, |
JI_CLAMP, |
JI_CLAMPZ, |
JI_HIGHZ, |
JI_DEBUG, |
JI_BYPASS = 0xF |
}; |
|
/* JTAG registers. */ |
#define JTAG_MODER (0x0) |
#define JTAG_TSEL (0x1) |
#define JTAG_QSEL (0x2) |
#define JTAG_SSEL (0x3) |
#define JTAG_RISCOP (0x4) |
#define JTAG_RECWP0 (0x10) |
#define JTAG_RECBP0 (0x1b) |
|
/* This is repeated from gdb tm-or1k.h There needs to be |
a better mechanism for tracking this, but I don't see |
an easy way to share files between modules. */ |
|
typedef enum { |
JTAG_COMMAND_READ = 1, |
JTAG_COMMAND_WRITE = 2, |
JTAG_COMMAND_BLOCK_READ = 3, |
JTAG_COMMAND_BLOCK_WRITE = 4, |
JTAG_COMMAND_CHAIN = 5, |
} JTAG_proxy_protocol_commands; |
|
/* Each transmit structure must begin with an integer |
which specifies the type of command. Information |
after this is variable. Make sure to have all information |
aligned properly. If we stick with 32 bit integers, it |
should be portable onto every platform. These structures |
will be transmitted across the network in network byte |
order. |
*/ |
|
typedef struct { |
uint32_t command; |
uint32_t length; |
uint32_t address; |
uint32_t data_H; |
uint32_t data_L; |
} JTAGProxyWriteMessage; |
|
typedef struct { |
uint32_t command; |
uint32_t length; |
uint32_t address; |
} JTAGProxyReadMessage; |
|
typedef struct { |
uint32_t command; |
uint32_t length; |
uint32_t address; |
int32_t nRegisters; |
uint32_t data[1]; |
} JTAGProxyBlockWriteMessage; |
|
typedef struct { |
uint32_t command; |
uint32_t length; |
uint32_t address; |
int32_t nRegisters; |
} JTAGProxyBlockReadMessage; |
|
typedef struct { |
uint32_t command; |
uint32_t length; |
uint32_t chain; |
} JTAGProxyChainMessage; |
|
/* The responses are messages specific, however convention |
states the first word should be an error code. Again, |
sticking with 32 bit integers should provide maximum |
portability. */ |
|
typedef struct { |
int32_t status; |
} JTAGProxyWriteResponse; |
|
typedef struct { |
int32_t status; |
uint32_t data_H; |
uint32_t data_L; |
} JTAGProxyReadResponse; |
|
typedef struct { |
int32_t status; |
} JTAGProxyBlockWriteResponse; |
|
typedef struct { |
int32_t status; |
int32_t nRegisters; |
uint32_t data[1]; |
/* uint32_t data[nRegisters-1] still unread */ |
} JTAGProxyBlockReadResponse; |
|
typedef struct { |
int32_t status; |
} JTAGProxyChainResponse; |
|
#endif /* GDB_H */ |
/trunk/rc203soc/sw/jtag/mc.h
0,0 → 1,111
/* mc.h -- Simulation of Memory Controller |
Copyright (C) 2001 by Marko Mlinar, markom@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
*/ |
|
/* Prototypes */ |
#ifndef __MC_H |
#define __MC_H |
|
#define N_CE (8) |
|
#define MC_CSR (0x00) |
#define MC_POC (0x04) |
#define MC_BA_MASK (0x08) |
#define MC_CSC(i) (0x10 + (i) * 8) |
#define MC_TMS(i) (0x14 + (i) * 8) |
|
#define MC_ADDR_SPACE (MC_CSC(N_CE)) |
|
/* POC register field definition */ |
#define MC_POC_EN_BW_OFFSET 0 |
#define MC_POC_EN_BW_WIDTH 2 |
#define MC_POC_EN_MEMTYPE_OFFSET 2 |
#define MC_POC_EN_MEMTYPE_WIDTH 2 |
|
/* CSC register field definition */ |
#define MC_CSC_EN_OFFSET 0 |
#define MC_CSC_MEMTYPE_OFFSET 1 |
#define MC_CSC_MEMTYPE_WIDTH 2 |
#define MC_CSC_BW_OFFSET 4 |
#define MC_CSC_BW_WIDTH 2 |
#define MC_CSC_MS_OFFSET 6 |
#define MC_CSC_MS_WIDTH 2 |
#define MC_CSC_WP_OFFSET 8 |
#define MC_CSC_BAS_OFFSET 9 |
#define MC_CSC_KRO_OFFSET 10 |
#define MC_CSC_PEN_OFFSET 11 |
#define MC_CSC_SEL_OFFSET 16 |
#define MC_CSC_SEL_WIDTH 8 |
|
#define MC_CSC_MEMTYPE_SDRAM 0 |
#define MC_CSC_MEMTYPE_SSRAM 1 |
#define MC_CSC_MEMTYPE_ASYNC 2 |
#define MC_CSC_MEMTYPE_SYNC 3 |
|
#define MC_CSR_VALID 0xFF000703LU |
#define MC_POC_VALID 0x0000000FLU |
#define MC_BA_MASK_VALID 0x000000FFLU |
#define MC_CSC_VALID 0x00FF0FFFLU |
#define MC_TMS_SDRAM_VALID 0x0FFF83FFLU |
#define MC_TMS_SSRAM_VALID 0x00000000LU |
#define MC_TMS_ASYNC_VALID 0x03FFFFFFLU |
#define MC_TMS_SYNC_VALID 0x01FFFFFFLU |
#define MC_TMS_VALID 0xFFFFFFFFLU /* reg test compat. */ |
|
/* TMS register field definition SDRAM */ |
#define MC_TMS_SDRAM_TRFC_OFFSET 24 |
#define MC_TMS_SDRAM_TRFC_WIDTH 4 |
#define MC_TMS_SDRAM_TRP_OFFSET 20 |
#define MC_TMS_SDRAM_TRP_WIDTH 4 |
#define MC_TMS_SDRAM_TRCD_OFFSET 17 |
#define MC_TMS_SDRAM_TRCD_WIDTH 4 |
#define MC_TMS_SDRAM_TWR_OFFSET 15 |
#define MC_TMS_SDRAM_TWR_WIDTH 2 |
#define MC_TMS_SDRAM_WBL_OFFSET 9 |
#define MC_TMS_SDRAM_OM_OFFSET 7 |
#define MC_TMS_SDRAM_OM_WIDTH 2 |
#define MC_TMS_SDRAM_CL_OFFSET 4 |
#define MC_TMS_SDRAM_CL_WIDTH 3 |
#define MC_TMS_SDRAM_BT_OFFSET 3 |
#define MC_TMS_SDRAM_BL_OFFSET 0 |
#define MC_TMS_SDRAM_BL_WIDTH 3 |
|
/* TMS register field definition ASYNC */ |
#define MC_TMS_ASYNC_TWWD_OFFSET 20 |
#define MC_TMS_ASYNC_TWWD_WIDTH 6 |
#define MC_TMS_ASYNC_TWD_OFFSET 16 |
#define MC_TMS_ASYNC_TWD_WIDTH 4 |
#define MC_TMS_ASYNC_TWPW_OFFSET 12 |
#define MC_TMS_ASYNC_TWPW_WIDTH 4 |
#define MC_TMS_ASYNC_TRDZ_OFFSET 8 |
#define MC_TMS_ASYNC_TRDZ_WIDTH 4 |
#define MC_TMS_ASYNC_TRDV_OFFSET 0 |
#define MC_TMS_ASYNC_TRDV_WIDTH 8 |
|
/* TMS register field definition SYNC */ |
#define MC_TMS_SYNC_TTO_OFFSET 16 |
#define MC_TMS_SYNC_TTO_WIDTH 9 |
#define MC_TMS_SYNC_TWR_OFFSET 12 |
#define MC_TMS_SYNC_TWR_WIDTH 4 |
#define MC_TMS_SYNC_TRDZ_OFFSET 8 |
#define MC_TMS_SYNC_TRDZ_WIDTH 4 |
#define MC_TMS_SYNC_TRDV_OFFSET 0 |
#define MC_TMS_SYNC_TRDV_WIDTH 8 |
|
#endif |
/trunk/rc203soc/sw/jtag/jp-io-vpi.c
0,0 → 1,279
/* jp-io-vpi.c -- JTAG communications vpi plugin |
|
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* This plugs into an rtl simulator via vpi */ |
|
#include <stdio.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <unistd.h> |
#include <stdint.h> |
#include <fcntl.h> |
#include <sys/un.h> |
#include <errno.h> |
|
#include <vpi_user.h> |
|
/* The vpi<->jp connection is `mastered' by jp1. Therefore we just sit doing |
* `nothing', waiting for jp1 to request or send us some data */ |
static uint8_t vpi_out; /* data that the sim gives to us */ |
|
static int jp_comm_m; /* The listening socket */ |
static int jp_comm; /* The socket for communitateing with jp1 */ |
|
static int jp_got_con; /* Have we got a connection ? */ |
|
static int count_comp; /* Has the predetermined cycle-count been reached ? */ |
static int jp_waiting; /* Is jp-waiting for count_comp ? */ |
|
int jp_check_con(); |
|
/*---------------------------------------------[ VPI interface to the sim ]---*/ |
/* Sends a byte from the sim */ |
int vpi_jp_out(char *xx) |
{ |
vpiHandle sys = vpi_handle(vpiSysTfCall, 0); |
vpiHandle argv = vpi_iterate(vpiArgument, sys); |
s_vpi_value value; |
|
if(!argv) { |
vpi_printf("$jp_out: missing destination argument\n"); |
vpi_free_object(argv); |
return 0; |
} |
vpiHandle dat_to = vpi_scan(argv); |
if(vpi_get(vpiType, dat_to) != vpiNet) { |
vpi_printf("$jp_out: Must have a net as argument!!\n"); |
vpi_free_object(argv); |
return 0; |
} |
|
value.format = vpiVectorVal; |
vpi_get_value(dat_to, &value); |
|
if((value.value.vector->bval & 1)) { |
vpi_free_object(argv); |
return 0; |
} |
vpi_out = value.value.vector->aval & 1; |
|
vpi_free_object(argv); |
|
return 0; |
} |
|
/* Sends a byte to the sim */ |
int vpi_jp_in(char *xx) |
{ |
int ret; |
uint8_t dat; |
s_vpi_vecval vec; |
|
s_vpi_value value; |
vpiHandle sys = vpi_handle(vpiSysTfCall, 0); |
vpiHandle argv; |
vpiHandle dat_to; |
|
vpiHandle dat_to_index; |
|
if(!jp_got_con) { |
if(!jp_check_con()) |
return 0; |
} |
|
ret = read(jp_comm, &dat, 1); |
if(!ret) |
return 0; |
if((ret == -1) && (errno == EAGAIN)) |
return 0; |
|
if(dat & 0x80) { |
switch(dat & 0x7f) { |
case 0: |
/* jp1 wants the TDO */ |
write(jp_comm, &vpi_out, 1); |
return 0; |
case 1: |
/* jp wants a time-out */ |
if(count_comp) |
write(jp_comm, &dat, 1); /* The value is irrelevent */ |
else |
jp_waiting = 1; |
return 0; |
} |
} |
|
argv = vpi_iterate(vpiArgument, sys); |
|
/* We got the data, acknowledge it and send it on to the sim */ |
if(!argv) { |
vpi_printf("$jp_in: missing destination argument\n"); |
vpi_free_object(argv); |
return 0; |
} |
dat_to = vpi_scan(argv); |
if(vpi_get(vpiType, dat_to) != vpiMemory) { |
vpi_printf("$jp_in: Must have a memory as argument!!\n"); |
vpi_free_object(argv); |
return 0; |
} |
|
value.format = vpiVectorVal; |
|
vec.aval = (dat & 0xf) | 0x10; |
vec.bval = 0; |
value.value.vector = &vec; |
dat_to_index = vpi_handle_by_index(dat_to, 0); |
vpi_put_value(dat_to_index, &value, 0, vpiNoDelay); |
|
vpi_free_object(argv); |
|
dat |= 0x10; |
write(jp_comm, &dat, 1); |
|
count_comp = 0; |
|
return 0; |
} |
|
/* tells us that we reached a predetermined cycle count */ |
int jp_wait_time(char *xx) |
{ |
uint8_t dat = 0; |
if(jp_waiting) { |
write(jp_comm, &dat, 1); |
jp_waiting = 0; |
} |
count_comp = 1; |
return 0; |
} |
|
/*---------------------------------------------------[ VPI<->jp functions ]---*/ |
int init_sock(char *xx) |
{ |
struct sockaddr_un addr; |
int ret; |
vpiHandle sys = vpi_handle(vpiSysTfCall, 0); |
vpiHandle argv = vpi_iterate(vpiArgument, sys); |
s_vpi_value value; |
|
if(!argv) { |
vpi_printf("$jp_init: missing destination argument\n"); |
return 0; |
} |
vpiHandle sock = vpi_scan(argv); |
/* |
if(vpi_get(vpiConstType, sock) != vpiStringConst) { |
vpi_printf("$jp_init: Must have a string as argument!!\n"); |
vpi_free_object(argv); |
return 0; |
} |
*/ |
|
value.format = vpiStringVal; |
vpi_get_value(sock, &value); |
|
addr.sun_family = AF_UNIX; |
strcpy(addr.sun_path, value.value.str); |
|
if((jp_comm_m = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { |
fprintf(stderr, "Unable to create comm socket\n"); |
return 0; |
} |
|
if(bind(jp_comm_m, (struct sockaddr *)&addr, sizeof(addr)) == -1) { |
fprintf(stderr, "Unable to bind to the unix socket %s\n", addr.sun_path); |
return 0; |
} |
|
if(listen(jp_comm_m, 1) == -1) { |
fprintf(stderr, "Unable to listen on %s (%s)\n", addr.sun_path, |
strerror(errno)); |
return 0; |
} |
|
ret = fcntl(jp_comm_m, F_GETFL); |
ret |= O_NONBLOCK; |
fcntl(jp_comm_m, F_SETFL, ret); |
|
jp_got_con = 0; |
jp_waiting = 0; |
printf("Just registered socket!!!\n"); |
return 0; |
} |
|
/* Checks to see if we got a connection */ |
int jp_check_con() |
{ |
int ret; |
|
if((jp_comm = accept(jp_comm_m, NULL, NULL)) == -1) { |
if(errno == EAGAIN) |
return 0; |
fprintf(stderr, "Unable to accept connection (%s)\n", strerror(errno)); |
return 0; |
} |
|
/* Set the comm socket to non-blocking */ |
ret = fcntl(jp_comm, F_GETFL); |
ret |= O_NONBLOCK; |
fcntl(jp_comm, F_SETFL, ret); |
|
jp_got_con = 1; |
return 1; |
} |
|
/*------------------------------------------------------------[ VPI stuff ]---*/ |
static void jtag_register() |
{ |
s_vpi_systf_data tf_data; |
|
tf_data.type = vpiSysTask; |
tf_data.tfname = "$jp_in"; |
tf_data.calltf = vpi_jp_in; |
tf_data.compiletf = 0; |
tf_data.sizetf = 0; |
vpi_register_systf(&tf_data); |
|
tf_data.type = vpiSysTask; |
tf_data.tfname = "$jp_out"; |
tf_data.calltf = vpi_jp_out; |
tf_data.compiletf = 0; |
tf_data.sizetf = 0; |
vpi_register_systf(&tf_data); |
|
tf_data.type = vpiSysTask; |
tf_data.tfname = "$jp_init"; |
tf_data.calltf = init_sock; |
tf_data.compiletf = 0; |
tf_data.sizetf = 0; |
vpi_register_systf(&tf_data); |
|
tf_data.type = vpiSysTask; |
tf_data.tfname = "$jp_wait_time"; |
tf_data.calltf = jp_wait_time; |
tf_data.compiletf = 0; |
tf_data.sizetf = 0; |
vpi_register_systf(&tf_data); |
} |
|
void (*vlog_startup_routines[])() = { |
jtag_register, |
0 |
}; |
/trunk/rc203soc/sw/jtag/jp2.c
0,0 → 1,1235
/* jp2-linux.c -- JTAG protocol via parallel port for linux |
Copyright(C) 2001 Marko Mlinar, markom@opencores.org |
Code for TCP/IP copied from gdb, by Chris Ziomkowski |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* Establishes jtag proxy server and communicates with parallel |
port directly. Requires root access. */ |
|
#include <assert.h> |
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <stdarg.h> |
#include <sys/stat.h> |
#include <sys/types.h> |
|
#include "mc.h" |
#include "gdb.h" |
#include "jp2.h" |
#include "jp.h" |
|
#define TC_RESET 0 |
#define TC_BRIGHT 1 |
#define TC_DIM 2 |
#define TC_UNDERLINE 3 |
#define TC_BLINK 4 |
#define TC_REVERSE 7 |
#define TC_HIDDEN 8 |
|
#define TC_BLACK 0 |
#define TC_RED 1 |
#define TC_GREEN 2 |
#define TC_YELLOW 3 |
#define TC_BLUE 4 |
#define TC_MAGENTA 5 |
#define TC_CYAN 6 |
#define TC_WHITE 7 |
|
#define SDRAM_BASE 0x00000000 |
#define SDRAM_SIZE 0x04000000 |
#define SRAM_BASE 0x40000000 |
#define SRAM_SIZE 0x04000000 // This is not ok |
|
|
int err = 0; |
int set_pc = 0; |
int set_step = 0; |
int waiting = 0; |
|
/* Scan chain info. */ |
static int chain_addr_size[] = { 0, 32, 0, 0, 5, 32, 32}; |
static int chain_data_size[] = { 0, 32, 0, 32, 32, 32, 32}; |
static int chain_is_valid[] = { 0, 1, 0, 1, 1, 1, 1}; |
static int chain_has_crc[] = { 0, 1, 0, 1, 1, 1, 1}; |
static int chain_has_rw[] = { 0, 1, 0, 0, 1, 1, 1}; |
|
/* Currently selected scan chain - just to prevent unnecessary |
transfers. */ |
static int current_chain = -1; |
|
/* The chain that should be currently selected. */ |
static int dbg_chain = -1; |
|
/* Crc of current read or written data. */ |
static int crc_r, crc_w = 0; |
|
/* Address of previous read */ |
static unsigned long prev_regno = 0; |
|
/* Generates new crc, sending in new bit input_bit */ |
static unsigned long crc_calc(unsigned long crc, int input_bit) { |
unsigned long d = (input_bit&1) ? 0xfffffff : 0x0000000; |
unsigned long crc_32 = ((crc >> 31)&1) ? 0xfffffff : 0x0000000; |
crc <<= 1; |
return crc ^ (d ^ crc_32) & DBG_CRC_POLY; |
} |
|
/* Writes TCLK=0, TRST=1, TMS=bit1, TDI=bit0 |
and TCLK=1, TRST=1, TMS=bit1, TDI=bit0 */ |
static void jp2_write_JTAG(uint8_t packet) { |
uint8_t data = TRST_BIT; |
if(packet & 1) data |= TDI_BIT; |
if(packet & 2) data |= TMS_BIT; |
|
jp_out(data); |
jp_wait(); |
crc_w = crc_calc(crc_w, packet&1); |
|
/* rise clock */ |
jp_out(data | TCLK_BIT); |
jp_wait(); |
} |
|
/* Reads TDI. */ |
static int jp2_read_JTAG() { |
uint8_t data; |
data = jp_in(); |
crc_r = crc_calc(crc_r, data); |
return data; |
} |
|
/* Writes bitstream. LS bit first if len < 0, MS bit first if len > 0. */ |
static void jp2_write_stream(ULONGEST stream, int len, int set_last_bit) { |
int i; |
if (len < 0) { |
len = -len; |
debug("writeL%d(", len); |
for(i = 0; i < len - 1; i++) |
jp2_write_JTAG((stream >> i) & 1); |
|
if(set_last_bit) jp2_write_JTAG((stream >>(len - 1))& 1 | TMS); |
else jp2_write_JTAG((stream >>(len - 1))& 1); |
} else { |
debug("write%d(", len); |
for(i = 0; i < len - 1; i++) |
jp2_write_JTAG((stream >> (len - 1 - i)) & 1); |
|
if(set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS); |
else jp2_write_JTAG((stream >> 0)& 1); |
} |
debug(")\n"); |
} |
|
/* Gets bitstream. LS bit first if len < 0, MS bit first if len > 0. */ |
static ULONGEST jp2_read_stream(unsigned long stream, int len, int set_last_bit) { |
int i; |
ULONGEST data = 0; |
if (len < 0) { |
debug("readL("); |
for(i = 0; i < len - 1; i++) { |
jp2_write_JTAG((stream >> i) & 1); /* LSB first */ |
data |= jp2_read_JTAG() << i; /* LSB first */ |
} |
|
if (set_last_bit) jp2_write_JTAG((stream >> (len - 1)) & 1 | TMS); |
else jp2_write_JTAG((stream >> (len - 1)) & 1); |
data |= jp2_read_JTAG() << (len - 1); |
} else { |
debug("read("); |
for(i = 0; i < len - 1; i++) { |
jp2_write_JTAG((stream >> (len - 1 - i)) & 1); /* MSB first */ |
data |= jp2_read_JTAG() << (len - 1 - i); /* MSB first */ |
} |
|
if (set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS); |
else jp2_write_JTAG((stream >> 0) & 1); |
data |= jp2_read_JTAG() << 0; |
} |
debug(")\n"); |
return data; |
} |
|
/* Sets scan chain. */ |
void jtag_set_ir(int ir) { |
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(TMS); /* SELECT_IR SCAN */ |
|
jp2_write_JTAG(0); /* CAPTURE_IR */ |
jp2_write_JTAG(0); /* SHIFT_IR */ |
|
/* write data, EXIT1_IR */ |
jp2_write_stream(ir, -JI_SIZE, 1); |
|
jp2_write_JTAG(TMS); /* UPDATE_IR */ |
jp2_write_JTAG(0); /* IDLE */ |
current_chain = -1; |
} |
|
/* Resets JTAG |
Writes TRST=0 |
and TRST=1 */ |
static void jp2_reset_JTAG() { |
int i; |
debug2("\nreset("); |
jp_out(0); |
JTAG_RETRY_WAIT(); |
/* In case we don't have TRST reset it manually */ |
for(i = 0; i < 8; i++) jp2_write_JTAG(TMS); |
jp_out(TRST_BIT); |
JTAG_RETRY_WAIT(); |
jp2_write_JTAG(0); |
debug2(")\n"); |
} |
|
/* Resets JTAG, and sets DEBUG scan chain */ |
static int dbg_reset() { |
int err; |
unsigned long id; |
jp2_reset_JTAG(); |
|
/* read ID */ |
jtag_set_ir(JI_IDCODE); |
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
/* read ID, EXIT1_DR */ |
crc_w = 0xffffffff; |
id = jp2_read_stream(0, 32, 1); |
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
printf("JTAG ID = %08x\n", id); |
|
/* select debug scan chain and stay in it forever */ |
jtag_set_ir(JI_DEBUG); |
current_chain = -1; |
return DBG_ERR_OK; |
} |
|
/* counts retries and returns zero if we should abort */ |
/* TODO: dinamically adjust timings for jp2 */ |
static int retry_no = 0; |
int retry_do() { |
int i, err; |
printf("RETRY\n"); |
//exit(2); |
if (retry_no >= NUM_SOFT_RETRIES) { |
if ((err = dbg_reset())) return err; |
} else { /* quick reset */ |
for(i = 0; i < 8; i++) jp2_write_JTAG(TMS); |
jp2_write_JTAG(0); /* go into IDLE state */ |
} |
if (retry_no >= NUM_SOFT_RETRIES + NUM_HARD_RETRIES) { |
retry_no = 0; |
return 0; |
} |
retry_no++; |
return 1; |
} |
|
/* resets retry counter */ |
void retry_ok() { |
retry_no = 0; |
} |
|
/* Sets scan chain. */ |
int dbg_set_chain(int chain) { |
int status, crc_generated, crc_read; |
dbg_chain = chain; |
|
try_again: |
if (current_chain == chain) return DBG_ERR_OK; |
current_chain = -1; |
debug("\n"); |
debug2("set_chain %i\n", chain); |
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
|
/* write data, EXIT1_DR */ |
crc_w = 0xffffffff; |
jp2_write_stream((chain & 0xf | (1<<DC_SIZE)), DC_SIZE + 1, 0); |
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); |
crc_r = 0xffffffff; |
status = jp2_read_stream(0, DC_STATUS_SIZE, 0); |
crc_generated = crc_r; |
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); |
|
//printf("%x %x %x\n", status, crc_read, crc_generated); |
/* CRCs must match, otherwise retry */ |
if (crc_read != crc_generated) { |
if (retry_do()) goto try_again; |
else return DBG_ERR_CRC; |
} |
/* we should read expected status value, otherwise retry */ |
if (status != 0) { |
if (retry_do()) goto try_again; |
else return status; |
} |
|
/* reset retry counter */ |
retry_ok(); |
|
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
current_chain = chain; |
return DBG_ERR_OK; |
} |
|
/* sends out a command with 32bit address and 16bit length, if len >= 0 */ |
int dbg_command(int type, unsigned long adr, int len) { |
int status, crc_generated, crc_read; |
|
try_again: |
dbg_set_chain(dbg_chain); |
debug("\n"); |
debug2("comm %i\n", type); |
|
/***** WRITEx *****/ |
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
|
/* write data, EXIT1_DR */ |
crc_w = 0xffffffff; |
jp2_write_stream((DI_WRITE_CMD & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0); |
jp2_write_stream(type, 4, 0); |
jp2_write_stream(adr, 32, 0); |
assert(len > 0); |
jp2_write_stream(len - 1, 16, 0); |
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); |
crc_r = 0xffffffff; |
status = jp2_read_stream(0, DC_STATUS_SIZE, 0); |
crc_generated = crc_r; |
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); |
|
/* CRCs must match, otherwise retry */ |
if (crc_read != crc_generated) { |
if (retry_do()) goto try_again; |
else return DBG_ERR_CRC; |
} |
/* we should read expected status value, otherwise retry */ |
if (status != 0) { |
if (retry_do()) goto try_again; |
else return status; |
} |
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
|
/* reset retry counter */ |
retry_ok(); |
return DBG_ERR_OK; |
} |
|
/* writes a ctrl reg */ |
int dbg_ctrl(int reset, int stall) { |
int status, crc_generated, crc_read; |
|
try_again: |
dbg_set_chain(dbg_chain); |
debug("\n"); |
debug2("ctrl\n"); |
|
/***** WRITEx *****/ |
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
|
/* write data, EXIT1_DR */ |
crc_w = 0xffffffff; |
jp2_write_stream((DI_WRITE_CTRL & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0); |
jp2_write_stream(reset, 1, 0); |
jp2_write_stream(stall, 1, 0); |
jp2_write_stream(0, 50, 0); |
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); |
crc_r = 0xffffffff; |
status = jp2_read_stream(0, DC_STATUS_SIZE, 0); |
crc_generated = crc_r; |
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); |
|
/* CRCs must match, otherwise retry */ |
//printf("%x %x %x\n", status, crc_read, crc_generated); |
if (crc_read != crc_generated) { |
if (retry_do()) goto try_again; |
else return DBG_ERR_CRC; |
} |
/* we should read expected status value, otherwise retry */ |
if (status != 0) { |
if (retry_do()) goto try_again; |
else return status; |
} |
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
|
/* reset retry counter */ |
retry_ok(); |
return DBG_ERR_OK; |
} |
|
/* reads control register */ |
int dbg_ctrl_read(int *reset, int *stall) { |
int status, crc_generated, crc_read; |
|
try_again: |
dbg_set_chain(dbg_chain); |
debug("\n"); |
debug2("ctrl_read\n"); |
|
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
|
/* write data, EXIT1_DR */ |
crc_w = 0xffffffff; |
jp2_write_stream(DI_READ_CTRL | (0<<DC_SIZE), DC_SIZE + 1, 0); |
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); |
crc_r = 0xffffffff; |
*reset = jp2_read_stream(0, 1, 0); |
*stall = jp2_read_stream(0, 1, 0); |
jp2_read_stream(0, 50, 0); |
status = jp2_read_stream(0, DC_STATUS_SIZE, 0); |
crc_generated = crc_r; |
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); |
|
/* CRCs must match, otherwise retry */ |
//printf("%x %x %x\n", status, crc_read, crc_generated); |
if (crc_read != crc_generated) { |
if (retry_do()) goto try_again; |
else return DBG_ERR_CRC; |
} |
/* we should read expected status value, otherwise retry */ |
if (status != 0) { |
if (retry_do()) goto try_again; |
else return status; |
} |
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
|
/* reset retry counter */ |
retry_ok(); |
return DBG_ERR_OK; |
} |
/* issues a burst read/write */ |
int dbg_go(unsigned char *data, unsigned short len, int read) { |
int status, crc_generated, crc_read; |
int i; |
|
try_again: |
dbg_set_chain(dbg_chain); |
debug("\n"); |
debug2("go len = %d\n", len); |
|
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ |
jp2_write_JTAG(0); /* CAPTURE_DR */ |
jp2_write_JTAG(0); /* SHIFT_DR */ |
|
/* write data, EXIT1_DR */ |
crc_w = 0xffffffff; |
jp2_write_stream(DI_GO | (0<<DC_SIZE), DC_SIZE + 1, 0); |
if (!read) { |
/* reverse byte ordering, since we must send in big endian */ |
for (i = 0; i < len; i++) |
jp2_write_stream(data[i], 8, 0); |
} |
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); |
crc_r = 0xffffffff; |
if (read) { |
/* reverse byte ordering, since we must send in big endian */ |
for (i = 0; i < len; i++) |
data[i] = jp2_read_stream(data[i], 8, 0); |
} |
status = jp2_read_stream(0, DC_STATUS_SIZE, 0); |
crc_generated = crc_r; |
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); |
|
/* CRCs must match, otherwise retry */ |
//printf("%x %x %x\n", status, crc_read, crc_generated); |
if (crc_read != crc_generated) { |
if (retry_do()) goto try_again; |
else return DBG_ERR_CRC; |
} |
/* we should read expected status value, otherwise retry */ |
if (status != 0) { |
if (retry_do()) goto try_again; |
else return status; |
} |
jp2_write_JTAG(TMS); /* UPDATE_DR */ |
jp2_write_JTAG(0); /* IDLE */ |
|
/* reset retry counter */ |
retry_ok(); |
return DBG_ERR_OK; |
} |
|
/* read a word from wishbone */ |
int dbg_wb_read32(unsigned long adr, unsigned long *data) { |
int err; |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x6, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err; |
*data = ntohl(*data); |
return err; |
} |
|
/* write a word to wishbone */ |
int dbg_wb_write32(unsigned long adr, unsigned long data) { |
int err; |
data = ntohl(data); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x2, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* write a word to wishbone */ |
int dbg_wb_write16(unsigned long adr, unsigned short data) { |
int err; |
data = ntohs(data); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x1, adr, 2))) return err; |
if ((err = dbg_go((unsigned char*)&data, 2, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* write a word to wishbone */ |
int dbg_wb_write8(unsigned long adr, unsigned long data) { |
int err; |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x0, adr, 1))) return err; |
if ((err = dbg_go((unsigned char*)&data, 1, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* read a block from wishbone */ |
int dbg_wb_read_block32(unsigned long adr, unsigned long *data, int len) { |
int i, err; |
//printf("%08x %08x\n", adr, len); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x6, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 1))) return err; |
for (i = 0; i < len / 4; i ++) data[i] = ntohl(data[i]); |
//printf("%08x\n", err); |
return DBG_ERR_OK; |
} |
|
/* read a block from wishbone */ |
int dbg_wb_read_block16(unsigned long adr, unsigned short *data, int len) { |
int i, err; |
//printf("%08x %08x\n", adr, len); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x5, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 1))) return err; |
for (i = 0; i < len / 2; i ++) data[i] = ntohs(data[i]); |
//printf("%08x\n", err); |
return DBG_ERR_OK; |
} |
|
/* read a block from wishbone */ |
int dbg_wb_read_block8(unsigned long adr, unsigned char *data, int len) { |
int i, err; |
//printf("%08x %08x\n", adr, len); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x4, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 1))) return err; |
//printf("%08x\n", err); |
return DBG_ERR_OK; |
} |
|
/* write a block to wishbone */ |
int dbg_wb_write_block32(unsigned long adr, unsigned long *data, int len) { |
int i, err; |
for (i = 0; i < len / 4; i ++) data[i] = ntohl(data[i]); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x2, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* write a block to wishbone */ |
int dbg_wb_write_block16(unsigned long adr, unsigned short *data, int len) { |
int i, err; |
for (i = 0; i < len / 2; i ++) data[i] = ntohs(data[i]); |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x1, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* write a block to wishbone */ |
int dbg_wb_write_block8(unsigned long adr, unsigned char *data, int len) { |
int i, err; |
if ((err = dbg_set_chain(DC_WISHBONE))) return err; |
if ((err = dbg_command(0x0, adr, len))) return err; |
if ((err = dbg_go((unsigned char*)data, len, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* read a register from cpu */ |
int dbg_cpu0_read(unsigned long adr, unsigned long *data) { |
int err; |
if ((err = dbg_set_chain(DC_CPU0))) return err; |
if ((err = dbg_command(0x6, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err; |
*data = ntohl(*data); |
return DBG_ERR_OK; |
} |
|
/* write a cpu register */ |
int dbg_cpu0_write(unsigned long adr, unsigned long data) { |
int err; |
data = ntohl(data); |
if ((err = dbg_set_chain(DC_CPU0))) return err; |
if ((err = dbg_command(0x2, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* read a register from cpu */ |
int dbg_cpu1_read(unsigned long adr, unsigned long *data) { |
int err; |
if ((err = dbg_set_chain(DC_CPU1))) return err; |
if ((err = dbg_command(0x6, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err; |
*data = ntohl(*data); |
return DBG_ERR_OK; |
} |
|
/* write a cpu register */ |
int dbg_cpu1_write(unsigned long adr, unsigned long data) { |
int err; |
data = ntohl(data); |
if ((err = dbg_set_chain(DC_CPU1))) return err; |
if ((err = dbg_command(0x2, adr, 4))) return err; |
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err; |
return DBG_ERR_OK; |
} |
|
/* write a cpu module register */ |
int dbg_cpu1_write_reg(unsigned long adr, unsigned char data) { |
int err; |
if ((err = dbg_set_chain(DC_CPU1))) return err; |
if ((err = dbg_ctrl(data & 2, data &1))) return err; |
return DBG_ERR_OK; |
} |
|
/* read a register from cpu module */ |
int dbg_cpu1_read_ctrl(unsigned long adr, unsigned char *data) { |
int err; |
int r, s; |
if ((err = dbg_set_chain(DC_CPU1))) return err; |
if ((err = dbg_ctrl_read(&r, &s))) return err; |
*data = (r << 1) | s; |
return DBG_ERR_OK; |
} |
|
/* write a cpu module register */ |
int dbg_cpu0_write_ctrl(unsigned long adr, unsigned char data) { |
int err; |
if ((err = dbg_set_chain(DC_CPU0))) return err; |
if ((err = dbg_ctrl(data & 2, data &1))) return err; |
return DBG_ERR_OK; |
} |
|
/* read a register from cpu module */ |
int dbg_cpu0_read_ctrl(unsigned long adr, unsigned char *data) { |
int err; |
int r, s; |
if ((err = dbg_set_chain(DC_CPU0))) return err; |
if ((err = dbg_ctrl_read(&r, &s))) return err; |
*data = (r << 1) | s; |
return DBG_ERR_OK; |
} |
|
void check(char *fn, int l, int i) { |
if (i != DBG_ERR_OK) { |
fprintf(stderr, "%s:%d: Jtag error %d occured; exiting.\n", fn, l, i); |
exit(1); |
} |
} |
|
|
void test_sdram (void) { |
unsigned long insn; |
unsigned long i; |
unsigned long data4_out[0x08]; |
unsigned long data4_in[0x08]; |
unsigned short data2_out[0x10]; |
unsigned short data2_in[0x10]; |
unsigned char data1_out[0x20]; |
unsigned char data1_in[0x20]; |
|
printf("Start SDRAM WR\n"); |
for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) { |
//printf("0x%x: 0x%x\n", SDRAM_BASE+i, i); |
CHECK(dbg_wb_write32(SDRAM_BASE+i, i)); |
} |
|
printf("Start SDRAM RD\n"); |
for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) { |
CHECK(dbg_wb_read32(SDRAM_BASE+i, &insn)); |
//printf("0x%x: 0x%x\n", SDRAM_BASE+i, insn); |
if (i != insn) { |
printf("SDRAM not OK"); |
exit (1); |
} |
} |
|
printf("32-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
for (i=0; i<(0x20/4); i++) { |
data4_out[i] = data4_in[i] = ((4*i+3)<<24) | ((4*i+2)<<16) | ((4*i+1)<<8) | (4*i); |
//printf("data_out = %0x\n", data4_out[i]); |
} |
|
//printf("Press a key for write\n"); getchar(); |
CHECK(dbg_wb_write_block32(SDRAM_BASE, &data4_out[0], 0x20)); |
|
// 32-bit block read is used for checking |
printf("32-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
CHECK(dbg_wb_read_block32(SDRAM_BASE, &data4_out[0], 0x20)); |
for (i=0; i<(0x20/4); i++) { |
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); |
if (data4_in[i] != data4_out[i]) { |
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data4_in[i], data4_out[i]); |
exit(1); |
} |
} |
|
printf("16-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
for (i=0; i<(0x20/2); i++) { |
data2_out[i] = data2_in[i] = ((4*i+1)<<8) | (4*i); |
//printf("data_out = %0x\n", data_out[i]); |
} |
CHECK(dbg_wb_write_block16(SDRAM_BASE, &data2_out[0], 0x20)); |
|
// 16-bit block read is used for checking |
printf("16-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
CHECK(dbg_wb_read_block16(SDRAM_BASE, &data2_out[0], 0x20)); |
for (i=0; i<(0x20/2); i++) { |
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); |
if (data2_in[i] != data2_out[i]) { |
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data2_in[i], data2_out[i]); |
exit(1); |
} |
} |
|
printf("8-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
for (i=0; i<(0x20/1); i++) { |
data1_out[i] = data1_in[i] = (4*i); |
//printf("data_out = %0x\n", data_out[i]); |
} |
CHECK(dbg_wb_write_block8(SDRAM_BASE, &data1_out[0], 0x20)); |
|
// 32-bit block read is used for checking |
printf("8-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); |
CHECK(dbg_wb_read_block8(SDRAM_BASE, &data1_out[0], 0x20)); |
for (i=0; i<(0x20/1); i++) { |
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); |
if (data1_in[i] != data1_out[i]) { |
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data1_in[i], data1_out[i]); |
exit(1); |
} |
} |
} |
|
|
void dbg_test() { |
int i; |
unsigned long npc, ppc, r1, insn, result; |
unsigned char stalled; |
#if 1 |
#define MC_BASE_ADDR 0x93000000 |
#define FLASH_BASE_ADDR 0xf0000000 |
#define FLASH_BAR_VAL FLASH_BASE_ADDR |
#define FLASH_AMR_VAL 0xf0000000 |
#define FLASH_WTR_VAL 0x00011009 |
#define FLASH_RTR_VAL 0x01002009 |
#define SDRAM_BASE_ADDR 0x00000000 |
#define SDRAM_BAR_VAL SDRAM_BASE_ADDR |
//#define SDRAM_SIZE 0x04000000 defined at the start of this program |
#define SDRAM_AMR_VAL (~(SDRAM_SIZE -1)) |
#define SDRAM_RATR_VAL 0x00000006 |
#define SDRAM_RCDR_VAL 0x00000002 |
#define SDRAM_RCTR_VAL 0x00000006 |
#define SDRAM_REFCTR_VAL 0x00000006 |
#define SDRAM_PTR_VAL 0x00000001 |
#define SDRAM_RRDR_VAL 0x00000000 |
#define SDRAM_RIR_VAL 0x000000C0 |
|
#define MC_BAR_0 0x00 |
#define MC_AMR_0 0x04 |
#define MC_WTR_0 0x30 |
#define MC_RTR_0 0x34 |
#define MC_OSR 0xe8 |
#define MC_BAR_1 0x08 |
#define MC_BAR_4 0x80 |
#define MC_AMR_1 0x0c |
#define MC_AMR_4 0x84 |
#define MC_CCR_1 0x24 |
#define MC_CCR_4 0xa0 |
#define MC_RATR 0xb0 |
#define MC_RCDR 0xc8 |
#define MC_RCTR 0xb4 |
#define MC_REFCTR 0xc4 |
#define MC_PTR 0xbc |
#define MC_RRDR 0xb8 |
#define MC_RIR 0xcc |
#define MC_ORR 0xe4 |
|
//usleep(1000000); |
|
printf("Stall 8051\n"); |
CHECK(dbg_cpu1_write_reg(0, 0x01)); // stall 8051 |
|
printf("Stall or1k\n"); |
CHECK(dbg_cpu0_write_ctrl(0, 0x01)); // stall or1k |
|
CHECK(dbg_cpu1_read_ctrl(0, &stalled)); |
if (!(stalled & 0x1)) { |
printf("8051 should be stalled\n"); // check stall 8051 |
exit(1); |
} |
|
CHECK(dbg_cpu0_read_ctrl(0, &stalled)); |
if (!(stalled & 0x1)) { |
printf("or1k should be stalled\n"); // check stall or1k |
exit(1); |
} |
|
printf("Initialize Memory Controller\n"); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_0, FLASH_BAR_VAL & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_0, FLASH_AMR_VAL & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_WTR_0, FLASH_WTR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RTR_0, FLASH_RTR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x40000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_4, SDRAM_BAR_VAL & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_4, SDRAM_AMR_VAL & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0x00bf0005)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RATR, SDRAM_RATR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCDR, SDRAM_RCDR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCTR, SDRAM_RCTR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_REFCTR, SDRAM_REFCTR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_PTR, SDRAM_PTR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RRDR, SDRAM_RRDR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RIR, SDRAM_RIR_VAL)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x5e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x5e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x7e000033)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x7e000033)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0xc0bf0005)); |
|
CHECK(dbg_wb_read32(MC_BASE_ADDR+MC_CCR_4, &insn)); |
printf("expected %x, read %x\n", 0xc0bf0005, insn); |
|
// SRAM initialized to 0x40000000 |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_1, SRAM_BASE & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_1, ~(SRAM_SIZE - 1) & 0xffff0000)); |
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_1, 0xc020001f)); |
#endif |
|
#if 1 |
#define CPU_OP_ADR 0 |
#define CPU_SEL_ADR 1 |
|
/* unstall the or1200 in highland_sys */ |
printf("Unstall or1k\n"); |
CHECK(dbg_wb_write32(0xb8070000, 2)); |
|
CHECK(dbg_cpu1_read_ctrl(0, &stalled)); |
if (!(stalled & 0x1)) { |
printf("8051 should be stalled\n"); // check stall 8051 |
exit(1); |
} |
|
printf("Stall or1k\n"); |
CHECK(dbg_cpu0_write_ctrl(0, 0x01)); // stall or1k |
|
printf("SDRAM test: \n"); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0x12345678)); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x00, &insn)); |
printf("expected %x, read %x\n", 0x12345678, insn); |
if (insn != 0x12345678) exit(1); |
|
CHECK(dbg_wb_write32(SDRAM_BASE+0x0000, 0x11112222)); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn)); |
printf("expected %x, read %x\n", 0x11112222, insn); |
if (insn != 0x11112222) exit(1); |
|
CHECK(dbg_wb_write32(SDRAM_BASE+0x0004, 0x33334444)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0008, 0x55556666)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x000c, 0x77778888)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0010, 0x9999aaaa)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0014, 0xbbbbcccc)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0018, 0xddddeeee)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x001c, 0xffff0000)); |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0020, 0xdeadbeef)); |
|
CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn)); |
printf("expected %x, read %x\n", 0x11112222, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0004, &insn)); |
printf("expected %x, read %x\n", 0x33334444, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0008, &insn)); |
printf("expected %x, read %x\n", 0x55556666, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x000c, &insn)); |
printf("expected %x, read %x\n", 0x77778888, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0010, &insn)); |
printf("expected %x, read %x\n", 0x9999aaaa, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0014, &insn)); |
printf("expected %x, read %x\n", 0xbbbbcccc, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0018, &insn)); |
printf("expected %x, read %x\n", 0xddddeeee, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x001c, &insn)); |
printf("expected %x, read %x\n", 0xffff0000, insn); |
CHECK(dbg_wb_read32(SDRAM_BASE+0x0020, &insn)); |
printf("expected %x, read %x\n", 0xdeadbeef, insn); |
|
if (insn != 0xdeadbeef) { |
printf("SDRAM test failed !!!\n"); |
exit(1); |
} |
else |
printf("SDRAM test passed\n"); |
|
printf("SRAM test: \n"); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0000, 0x11112222)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0004, 0x33334444)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0008, 0x55556666)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x000c, 0x77778888)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0010, 0x9999aaaa)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0014, 0xbbbbcccc)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0018, 0xddddeeee)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x001c, 0xffff0000)); |
CHECK(dbg_wb_write32(SRAM_BASE+0x0020, 0xdedababa)); |
|
CHECK(dbg_wb_read32(SRAM_BASE+0x0000, &insn)); |
printf("expected %x, read %x\n", 0x11112222, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0004, &insn)); |
printf("expected %x, read %x\n", 0x33334444, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0008, &insn)); |
printf("expected %x, read %x\n", 0x55556666, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x000c, &insn)); |
printf("expected %x, read %x\n", 0x77778888, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0010, &insn)); |
printf("expected %x, read %x\n", 0x9999aaaa, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0014, &insn)); |
printf("expected %x, read %x\n", 0xbbbbcccc, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0018, &insn)); |
printf("expected %x, read %x\n", 0xddddeeee, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x001c, &insn)); |
printf("expected %x, read %x\n", 0xffff0000, insn); |
CHECK(dbg_wb_read32(SRAM_BASE+0x0020, &insn)); |
printf("expected %x, read %x\n", 0xdedababa, insn); |
|
if (insn != 0xdedababa) { |
printf("SRAN test failed!!!\n"); |
exit(1); |
} |
else |
printf("SRAM test passed\n"); |
|
#if 1 |
test_sdram(); |
#endif |
|
CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0xe0000005)); /* l.xor r0,r0,r0 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x04, 0x9c200000)); /* l.addi r1,r0,0x0 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x08, 0x18400000)); /* l.movhi r2,0x4000 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x0c, 0xa8420030)); /* l.ori r2,r2,0x30 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x10, 0x9c210001)); /* l.addi r1,r1,1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x14, 0x9c210001)); /* l.addi r1,r1,1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x18, 0xd4020800)); /* l.sw 0(r2),r1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x1c, 0x9c210001)); /* l.addi r1,r1,1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x20, 0x84620000)); /* l.lwz r3,0(r2) */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x24, 0x03fffffb)); /* l.j loop2 */ |
CHECK(dbg_wb_write32(SDRAM_BASE+0x28, 0xe0211800)); /* l.add r1,r1,r3 */ |
|
CHECK(dbg_cpu0_write((0 << 11) + 17, 0x01)); /* Enable exceptions */ |
CHECK(dbg_cpu0_write((6 << 11) + 20, 0x2000)); /* Trap causes stall */ |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE)); /* Set PC */ |
CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */ |
for(i = 0; i < 11; i++) { |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* 11x Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
} |
|
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 5); |
result = npc + ppc + r1; |
|
CHECK(dbg_cpu0_write((6 << 11) + 16, 0)); /* Reset step bit */ |
CHECK(dbg_wb_read32(SDRAM_BASE + 0x28, &insn)); /* Set trap insn in delay slot */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, 0x21000001)); |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 8); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_wb_read32(SDRAM_BASE + 0x24, &insn)); /* Set trap insn in place of branch insn */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, 0x21000001)); |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x10)); /* Set PC */ |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000028, 0x00000024, 11); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn before branch insn */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001)); |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */ |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000024, 0x00000020, 24); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_wb_read32(SDRAM_BASE + 0x1c, &insn)); /* Set trap insn behind lsu insn */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, 0x21000001)); |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20)); /* Set PC */ |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000020, 0x0000001c, 49); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn very near previous one */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001)); |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x1c)); /* Set PC */ |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000024, 0x00000020, 50); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_wb_read32(SDRAM_BASE + 0x10, &insn)); /* Set trap insn to the start */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, 0x21000001)); |
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20) /* Set PC */); |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, insn)); /* Set back original insn */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000014, 0x00000010, 99); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */ |
for(i = 0; i < 5; i++) { |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
} |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000028, 0x00000024, 101); |
result = npc + ppc + r1 + result; |
|
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */ |
for(i = 0; i < 2; i++) { |
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ |
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); |
} |
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ |
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ |
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ |
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1); |
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 201); |
result = npc + ppc + r1 + result; |
printf("result = %.8lx\n", result ^ 0xdeaddae1); |
|
|
{ // 8051 TEST |
unsigned long npc[3], tmp; |
|
// WRITE ACC |
CHECK(dbg_cpu1_write(0x20e0, 0xa6)); |
|
// READ ACC |
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space |
printf("Read 8051 ACC = %0x (expected a6)\n", tmp); |
result = result + tmp; |
|
// set exception to single step to jump over a loop |
CHECK(dbg_cpu1_write(0x3010, 0xa0)); // set single step and global enable in EER |
CHECK(dbg_cpu1_write(0x3011, 0x40)); // set evec = 24'h000040 |
CHECK(dbg_cpu1_write(0x3012, 0x00)); // (already reset value) |
CHECK(dbg_cpu1_write(0x3013, 0x00)); // (already reset value) |
|
// set HW breakpoint at PC == 0x41 |
CHECK(dbg_cpu1_write(0x3020, 0x41)); // DVR0 = 24'h000041 |
CHECK(dbg_cpu1_write(0x3023, 0x39)); // DCR0 = valid, == PC |
CHECK(dbg_cpu1_write(0x3001, 0x04)); // DSR = watchpoint |
|
// flush 8051 instruction cache |
CHECK(dbg_cpu1_write(0x209f, 0x00)); |
|
// Put some instructions in ram (8-bit mode on wishbone) |
CHECK(dbg_wb_write8 (0x40, 0x04)); // inc a |
CHECK(dbg_wb_write8 (0x41, 0x03)); // rr a; |
CHECK(dbg_wb_write8 (0x42, 0x14)); // dec a; |
CHECK(dbg_wb_write8 (0x43, 0xf5)); // mov 0e5h, a; |
CHECK(dbg_wb_write8 (0x44, 0xe5)); |
|
// unstall just 8051 |
CHECK(dbg_cpu1_write_reg(0, 0)); |
|
// read PC |
CHECK(dbg_cpu1_read(0, &npc[0])); |
CHECK(dbg_cpu1_read(1, &npc[1])); |
CHECK(dbg_cpu1_read(2, &npc[2])); |
printf("Read 8051 npc = %02x%02x%02x (expected 41)\n", npc[2], npc[1], npc[0]); |
result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0]; |
|
// READ ACC |
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space |
printf("Read 8051 ACC = %0x (expected a7)\n", tmp); |
result = result + tmp; |
|
// set sigle step to stop execution |
CHECK(dbg_cpu1_write(0x3001, 0x20)); // set single step and global enable in DSR |
|
// clear DRR |
CHECK(dbg_cpu1_write(0x3000, 0x00)); // set single step and global enable in DRR |
|
// unstall just 8051 |
CHECK(dbg_cpu1_write_reg(0, 0)); |
|
// read PC |
CHECK(dbg_cpu1_read(0, &npc[0])); |
CHECK(dbg_cpu1_read(1, &npc[1])); |
CHECK(dbg_cpu1_read(2, &npc[2])); |
printf("Read 8051 npc = %02x%02x%02x (expected 42)\n", npc[2], npc[1], npc[0]); |
result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0]; |
|
// READ ACC |
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space |
printf("Read 8051 ACC = %0x (expected d3)\n", tmp); |
result = result + tmp; |
|
printf("report (%x)\n", result ^ 0x6c1 ^ 0xdeaddead); |
} |
#endif |
} |
|
int main(int argc, char *argv[]) { |
char *redirstr; |
int trace_fd = 0; |
char *s; |
int err = DBG_ERR_OK; |
|
int c; |
const char *args; |
char *port; |
char *cable; |
|
srand(getpid()); |
if ((argc < 3) || (argv[1][0] == '-') || (argv[2][0] == '-')) { |
printf("JTAG protocol via parallel port for linux.\n"); |
printf("Copyright (C) 2001 Marko Mlinar, markom@opencores.org\n\n"); |
printf("Usage: %s [cable] [JTAG port_number]\n", argv[0]); |
jp_print_cable_help(); |
return -1; |
} |
|
cable = argv[1]; |
port = argv[2]; |
|
if (!jp_select_cable(cable)) { |
fprintf(stderr,"Error selecting cable %s\n", cable); |
return -1; |
} |
|
/* Get the cable-arguments */ |
args = jp_get_cable_args(); |
|
/* Parse the cable arguments (if-any) */ |
for(;;) { |
c = getopt(argc, argv, args); |
if(c == -1) |
break; |
if(c == '?') |
return 1; |
if(!jp_cable_opt(c, optarg)) |
return 1; |
} |
if(!jp_init_cable()) |
return 1; |
|
/* Initialize a new connection to the or1k board, and make sure we are |
really connected. */ |
current_chain = -1; |
if ((err = dbg_reset())) goto error; |
|
/* Test the connection. */ |
/*dbg_test();*/ |
|
/* We have a connection. Establish server. */ |
serverPort = strtol(port,&s,10); |
if(*s) return -1; |
|
if(server_fd = GetServerSocket("or1ksim","tcp", serverPort)) { |
printf("JTAG Proxy server started on port %d\n", serverPort); |
printf("Press CTRL+c to exit.\n"); |
} else { |
fprintf(stderr,"Cannot start JTAG Proxy server on port %d\n", serverPort); |
exit(-1); |
} |
|
/* Do endless loop of checking and handle GDB requests. Ctrl-c exits. */ |
HandleServerSocket(true); |
return 0; |
error: |
fprintf(stderr,"Connection with jtag via parallel port failed (err = %d).\n", err); |
exit(-1); |
} |
|
/trunk/rc203soc/sw/jtag/Makefile
0,0 → 1,31
prefix = /usr/local |
|
CFLAGS = -g -O2 |
#CFLAGS = -g -O2 -DDEBUG2 -DDEBUG |
CC = gcc |
|
PROGRAMS = jp2 |
|
all: $(PROGRAMS) |
|
.c.o: |
$(CC) $(CFLAGS) -c $< |
|
jp2: Makefile jp2.o gdb2.o jp2.h jp-io.o jp.h |
rm -f $@ |
$(CC) -o $@ $(CFLAGS) jp2.o jp-io.o gdb2.o |
|
jp-io-vpi.vpi: jp-io-vpi.c |
iverilog-vpi jp-io-vpi.c |
|
vpi: jp-io-vpi.vpi Makefile |
|
install: all |
[ -d $(prefix)/bin ] || mkdir -p $(prefix)/bin |
for p in $(PROGRAMS) ; do \ |
/bin/rm -f $(prefix)/bin/$$p; \ |
/bin/cp -p $$p $(prefix)/bin/$$p; \ |
done |
|
clean: Makefile |
rm -f $(PROGRAMS) jp-io-vpi.vpi *.o *~ |
/trunk/rc203soc/sw/jtag/README
0,0 → 1,64
JTAG PROGRAMMING UTILITY README FOR OPENRISC 1000 |
|
NOTE: |
|
This is a modified version of JTAG utility to work with |
Celoxica boards. |
|
INTRODUCTION |
|
JP1 is a proprietary JTAG protocol. It is very simple, and perhaps |
its biggest advantage is that no special HW is needed -- only a |
parallel port cable and some buffers. It is compatible with Xilinx |
Parallel Cable III. |
|
Gdb is capable of connecting, controlling and debugging the board |
via JP1. Currently jp1 has support only for Linux. |
|
|
|
USAGE |
|
jp1 [cable] [port] <cable options> |
|
The cable parameter selects the cable to use for communicateing with the board. |
At the time of writting, cable may be one of xpc3, xess, rtl_sim or vpi. xpc3 |
assumes a xillinx parallel cable 3, rtl_sim connects to a rtl simulator, |
communicateing with it via files (slow), vpi connects to a rtl simulator via the |
vpi (faster). The port parameter specified designates TCP/IP port address where |
the server starts. Run jp1 without arguments for a list of cable specific |
options. |
|
First, start the jp1 program in root mode, e.g.: |
|
./jp1 xpc3 9999 |
|
Then start gdb and connect to it, |
using e.g.: |
|
$ or32-rtems-gdb test.or32 |
(gdb) target jtag jtag://localhost:9999 |
|
Then load the program into the memory: |
|
(gdb) load |
|
and start it up: |
|
(gdb) set $pc=0x100 |
|
You can write stepi or si, to see if things are working |
correctly: |
|
(gdb) stepi |
|
If the program counter increases, we can set the breakpoint |
and run the program with command 'continue' or 'c'. |
|
|
|
AUTHORS |
|
Simons Srot, simons@opencores.org |
Marko Mlinar, markom@opencores.org |
|
/trunk/rc203soc/sw/jtag/gdb.c
0,0 → 1,573
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <stdarg.h> |
|
/* Libraries for JTAG proxy server. */ |
#include <sys/stat.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <sys/select.h> |
#include <sys/poll.h> |
#include <fcntl.h> |
#include <netdb.h> |
#include <netinet/tcp.h> |
#include <inttypes.h> |
#include <errno.h> |
|
#include "gdb.h" /* partially copied from gdb/config/or1k */ |
#include "jp2.h" |
|
|
/* connection to jp2 routines */ |
int gdb_chain = -1; |
|
int gdb_read_reg(unsigned long adr, unsigned long *data) { |
switch (gdb_chain) { |
SC_RISC_DEBUG: return dbg_cpu_read32(adr, data) ? ERR_CRC : ERR_NONE; |
SC_REGISTER: return dbg_cpu_read_reg(adr, data) ? ERR_CRC : ERR_NONE; |
SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_write_reg(unsigned long adr, unsigned long data) { |
switch (gdb_chain) { |
SC_RISC_DEBUG: return dbg_cpu_write32(adr, data) ? ERR_CRC : ERR_NONE; |
SC_REGISTER: return dbg_cpu_write_reg(adr, data) ? ERR_CRC : ERR_NONE; |
SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_read_block(unsigned long adr, unsigned long *data, int len) { |
switch (gdb_chain) { |
SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_write_block(unsigned long adr, unsigned long *data, int len) { |
switch (gdb_chain) { |
SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
int gdb_set_chain(int chain) { |
switch (gdb_chain) { |
SC_RISC_DEBUG: |
SC_REGISTER: |
SC_WISHBONE: gdb_chain = chain; |
return ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
|
|
|
/************************ |
JTAG Server Routines |
************************/ |
|
unsigned int serverIP = 0; |
unsigned int serverPort = 0; |
unsigned int server_fd = 0; |
unsigned int gdb_fd = 0; |
static int gdb_read(void*, int); |
static int gdb_write(void*, int); |
static void ProtocolClean(int, int32_t); |
|
static int tcp_level = 0; |
|
/* Added by CZ 24/05/01 */ |
int GetServerSocket(const char* name, const char* proto, int port) { |
struct servent *service; |
struct protoent *protocol; |
struct sockaddr_in sa; |
struct hostent *hp; |
int sockfd; |
char myname[256]; |
int flags; |
char sTemp[256]; |
|
/* First, get the protocol number of TCP */ |
if (!(protocol = getprotobyname(proto))) { |
sprintf(sTemp, "Unable to load protocol \"%s\"", proto); |
perror(sTemp); |
return 0; |
} |
tcp_level = protocol->p_proto; /* Save for later */ |
|
/* If we weren't passed a non standard port, get the port |
from the services directory. */ |
if (!port && (service = getservbyname(name, protocol->p_name))) |
port = ntohs(service->s_port); |
|
/* Create the socket using the TCP protocol */ |
if ((sockfd = socket(PF_INET, SOCK_STREAM, protocol->p_proto)) < 0) { |
perror("Unable to create socket"); |
return 0; |
} |
|
flags = 1; |
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flags, sizeof(int)) < 0) { |
sprintf(sTemp, "Can not set SO_REUSEADDR option on socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* The server should also be non blocking. Get the current flags. */ |
if((flags = fcntl(sockfd, F_GETFL, 0)) < 0) { |
sprintf(sTemp, "Unable to get flags for socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* Set the nonblocking flag */ |
if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { |
sprintf(sTemp, "Unable to set flags for socket %d to value 0x%08x", |
sockfd, flags | O_NONBLOCK); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
/* Find out what our address is */ |
memset(&sa, 0, sizeof(struct sockaddr_in)); |
gethostname(myname, sizeof(myname)); |
if(!(hp = gethostbyname(myname))) { |
perror("Unable to read hostname"); |
close(sockfd); |
return 0; |
} |
|
/* Bind our socket to the appropriate address */ |
sa.sin_family = hp->h_addrtype; |
sa.sin_port = htons(port); |
if(bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) { |
sprintf(sTemp, "Unable to bind socket %d to port %d", sockfd, port); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
serverIP = sa.sin_addr.s_addr; |
flags = sizeof(struct sockaddr_in); |
if(getsockname(sockfd, (struct sockaddr*)&sa, &flags) < 0) { |
sprintf(sTemp, "Unable to get socket information for socket %d", sockfd); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
serverPort = ntohs(sa.sin_port); |
|
/* Set the backlog to 1 connections */ |
if(listen(sockfd, 1) < 0) { |
sprintf(sTemp, "Unable to set backlog on socket %d to %d", sockfd, 1); |
perror(sTemp); |
close(sockfd); |
return 0; |
} |
|
return sockfd; |
} |
|
void HandleServerSocket(Boolean block) { |
struct pollfd fds[2]; |
int n; |
|
rebuild: |
n = 0; |
if(!server_fd && !gdb_fd) return; |
|
if(server_fd) { |
fds[n].fd = server_fd; |
fds[n].events = POLLIN; |
fds[n++].revents = 0; |
} |
if(gdb_fd) { |
fds[n].fd = gdb_fd; |
fds[n].events = POLLIN; |
fds[n++].revents = 0; |
} |
|
while(1) { |
switch(poll(fds, n, -1)) { |
case 0: |
case -1: |
if(errno == EINTR) continue; |
perror("poll"); |
server_fd = 0; |
return; |
default: |
/* Make sure to handle the gdb port first! */ |
if (gdb_fd && (fds[0].revents && !server_fd || fds[1].revents && server_fd)) { |
int revents = server_fd ? fds[1].revents : fds[0].revents; |
if (revents & POLLIN) GDBRequest(); |
else {/* Error Occurred */ |
fprintf(stderr, "Received flags 0x%08x on gdb socket. Shutting down.\n", revents); |
close(gdb_fd); |
gdb_fd = 0; |
} |
} |
if(fds[0].revents && server_fd) { |
if(fds[0].revents & POLLIN) { |
JTAGRequest(); |
goto rebuild; |
} else { /* Error Occurred */ |
fprintf(stderr, "Received flags 0x%08x on server. Shutting down.\n", fds[0].revents); |
close(server_fd); |
server_fd = 0; |
serverPort = 0; |
serverIP = 0; |
return; |
} |
} |
break; |
} /* End of switch statement */ |
} /* End of while statement */ |
} |
|
void JTAGRequest() { |
struct sockaddr_in sa; |
struct sockaddr* addr = (struct sockaddr*)&sa; |
int n = sizeof(struct sockaddr_in); |
int fd = accept(server_fd, addr, &n); |
int on_off = 0; /* Turn off Nagel's algorithm on the socket */ |
int flags; |
char sTemp[256]; |
|
if(fd < 0) { |
/* This is valid, because a connection could have started, |
and then terminated due to a protocol error or user |
initiation before the accept could take place. */ |
if(errno != EWOULDBLOCK && errno != EAGAIN) { |
perror("accept"); |
close(server_fd); |
server_fd = 0; |
serverPort = 0; |
serverIP = 0; |
} |
return; |
} |
|
if(gdb_fd) { |
close(fd); |
return; |
} |
|
if((flags = fcntl(fd, F_GETFL,0)) < 0) { |
sprintf(sTemp, "Unable to get flags for gdb socket %d", fd); |
perror(sTemp); |
close(fd); |
return; |
} |
|
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { |
sprintf(sTemp, "Unable to set flags for gdb socket %d to value 0x%08x", |
fd, flags | O_NONBLOCK); |
perror(sTemp); |
close(fd); |
return; |
} |
|
if(setsockopt(fd, tcp_level, TCP_NODELAY, &on_off, sizeof(int)) < 0) { |
sprintf(sTemp, "Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", fd); |
perror(sTemp); |
close(fd); |
return; |
} |
|
gdb_fd = fd; |
} |
|
void GDBRequest() { |
JTAGProxyWriteMessage msg_write; |
JTAGProxyReadMessage msg_read; |
JTAGProxyChainMessage msg_chain; |
JTAGProxyWriteResponse resp_write; |
JTAGProxyReadResponse resp_read; |
JTAGProxyChainResponse resp_chain; |
JTAGProxyBlockWriteMessage *msg_bwrite; |
JTAGProxyBlockReadMessage msg_bread; |
JTAGProxyBlockWriteResponse resp_bwrite; |
JTAGProxyBlockReadResponse *resp_bread; |
char *buf; |
unsigned long long data; |
uint32_t command, length; |
int len, i; |
int err = 0; |
|
/* First, we must read the incomming command */ |
if(gdb_read(&command, sizeof(uint32_t)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 1"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
if(gdb_read(&length, sizeof(uint32_t)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 2"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
length = ntohl(length); |
|
/* Now, verify the protocol and implement the command */ |
switch(ntohl(command)) { |
case JTAG_COMMAND_WRITE: |
if(length != sizeof(msg_write) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_write; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 3"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_write.address = ntohl(msg_write.address); |
msg_write.data_H = ntohl(msg_write.data_H); |
msg_write.data_L = ntohl(msg_write.data_L); |
err = gdb_write_reg(msg_write.address, msg_write.data_L); |
resp_write.status = htonl(err); |
if(gdb_write(&resp_write, sizeof(resp_write)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 4"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_READ: |
if(length != sizeof(msg_read) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_read; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_read.address = ntohl(msg_read.address); |
err = gdb_read_reg(msg_read.address, (unsigned long *)&resp_read.data_L); |
resp_read.status = htonl(err); |
resp_read.data_H = 0; |
resp_read.data_L = htonl(resp_read.data_L); |
if(gdb_write(&resp_read, sizeof(resp_read)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 6"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_WRITE: |
if(length < sizeof(JTAGProxyBlockWriteMessage)-8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
if(!(buf = (char*)malloc(8+length))) { |
ProtocolClean(length, JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
msg_bwrite->address = ntohl(msg_bwrite->address); |
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters); |
for(i=0;i<msg_bwrite->nRegisters;i++) { |
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]); |
} |
err = gdb_write_block(msg_bwrite->address, (unsigned long*)msg_bwrite->data, msg_bwrite->nRegisters * 4); |
resp_bwrite.status = htonl(err); |
free(buf); |
msg_bwrite = (JTAGProxyBlockWriteMessage *)NULL; |
buf = (char *)msg_bwrite; |
if(gdb_write(&resp_bwrite, sizeof(resp_bwrite)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 4"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
case JTAG_COMMAND_BLOCK_READ: |
if(length != sizeof(msg_bread) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_bread; |
if(gdb_read(&buf[8], length) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 5"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_bread.address = ntohl(msg_bread.address); |
msg_bread.nRegisters = ntohl(msg_bread.nRegisters); |
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1); |
if(!(buf = (char*)malloc(len))) { |
ProtocolClean(0, JTAG_PROXY_OUT_OF_MEMORY); |
return; |
} |
resp_bread = (JTAGProxyBlockReadResponse*)buf; |
err = gdb_read_block(msg_bread.address, (unsigned long*)resp_bread->data, msg_bread.nRegisters * 4); |
for(i=0;i<msg_bread.nRegisters;i++) { |
/* Read previous, address next one. */ |
resp_bread->data[i] = htonl(resp_bread->data[i]); |
} |
resp_bread->status = htonl(err); |
resp_bread->nRegisters = htonl(msg_bread.nRegisters); |
if(gdb_write(resp_bread, len) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 6"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
free(buf); |
return; |
} |
free(buf); |
resp_bread = (JTAGProxyBlockReadResponse *)NULL; |
buf = (char *)resp_bread; |
break; |
case JTAG_COMMAND_CHAIN: |
if(length != sizeof(msg_chain) - 8) { |
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR); |
return; |
} |
buf = (char*)&msg_chain; |
if(gdb_read(&buf[8], sizeof(msg_chain)-8) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 7"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
msg_chain.chain = htonl(msg_chain.chain); |
err = gdb_set_chain(msg_chain.chain); |
resp_chain.status = htonl(err); |
if(gdb_write(&resp_chain, sizeof(resp_chain)) < 0) { |
if(gdb_fd) { |
perror("gdb socket - 8"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
return; |
} |
break; |
default: |
perror("Unknown JTAG command."); |
ProtocolClean(length, JTAG_PROXY_COMMAND_NOT_IMPLEMENTED); |
break; |
} |
} |
|
static void ProtocolClean(int length, int32_t err) { |
char buf[4096]; |
|
err = htonl(err); |
if((gdb_read(buf, length) < 0) || (gdb_write(&err, sizeof(err)) < 0) && gdb_fd) { |
perror("gdb socket - 9"); |
close(gdb_fd); |
gdb_fd = 0; |
} |
} |
|
static int gdb_write(void* buf, int len) { |
int n; |
char* w_buf = (char*)buf; |
struct pollfd block; |
|
while(len) { |
if((n = write(gdb_fd, w_buf, len)) < 0) { |
switch(errno) { |
case EWOULDBLOCK: /* or EAGAIN */ |
/* We've been called on a descriptor marked |
for nonblocking I/O. We better simulate |
blocking behavior. */ |
block.fd = gdb_fd; |
block.events = POLLOUT; |
block.revents = 0; |
poll(&block, 1, -1); |
continue; |
case EINTR: |
continue; |
case EPIPE: |
close(gdb_fd); |
gdb_fd = 0; |
return -1; |
default: |
return -1; |
} |
} else { |
len -= n; |
w_buf += n; |
} |
} |
return 0; |
} |
|
static int gdb_read(void* buf, int len) { |
int n; |
char* r_buf = (char*)buf; |
struct pollfd block; |
|
while(len) { |
if((n = read(gdb_fd, r_buf, len)) < 0) { |
switch(errno) { |
case EWOULDBLOCK: /* or EAGAIN */ |
/* We've been called on a descriptor marked |
for nonblocking I/O. We better simulate |
blocking behavior. */ |
block.fd = gdb_fd; |
block.events = POLLIN; |
block.revents = 0; |
poll(&block, 1, -1); |
continue; |
case EINTR: |
continue; |
default: |
return -1; |
} |
} else if(n == 0) { |
close(gdb_fd); |
gdb_fd = 0; |
return -1; |
} else { |
len -= n; |
r_buf += n; |
} |
} |
return 0; |
} |