URL
https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk
Subversion Repositories openrisc_2011-10-31
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk
- from Rev 499 to Rev 500
- ↔ Reverse comparison
Rev 499 → Rev 500
/orpsocv2/bench/sysc/include/UartSC.h
42,16 → 42,27
sc_out < bool > uartrx; |
|
// Init function |
void initUart(int clk_freq_hz, int uart_baud); |
void initUart(int uart_baud); |
// Transmit (from ORPSoC) handling function |
void checkTx(); |
// Receieve (in ORPSoC) generation function |
void driveRx(); |
// Check keyboard for entry |
int kbhit(); |
// Enable canonical mode on console |
void nonblock(int state); |
|
private: |
int clocks_per_bit; |
uint8_t current_char; |
int counter; |
int bits_received; |
int ns_per_bit; |
|
int rx_state; |
int rx_counter; |
int rx_bits_sent; |
char rx_char; |
|
}; // UartSC () |
|
#endif // UART_SC__H |
/orpsocv2/bench/sysc/src/UartSC.cpp
24,12 → 24,18
|
#include <iostream> |
#include <iomanip> |
#include <cmath> |
|
#include "UartSC.h" |
|
//#define UART_SC_DEBUG |
|
// Keep disabled for now, to stop any portability problems cropping up. |
//#define UART_SC_STDIN_ENABLE |
|
#ifdef UART_SC_STDIN_ENABLE |
#include <termios.h> |
#endif |
|
SC_HAS_PROCESS(UartSC); |
|
//! Constructor for the Uart system C model |
37,83 → 43,215
//! @param[in] name Name of this module, passed to the parent constructor. |
// Todo: Probably some sort of scaler parameter |
|
UartSC::UartSC(sc_core::sc_module_name name): |
sc_module(name) |
UartSC::UartSC(sc_core::sc_module_name uart): |
sc_module(uart) |
{ |
|
SC_METHOD(checkTx); |
#ifdef UART_SC_STDIN_ENABLE |
SC_THREAD(driveRx); |
#endif |
SC_THREAD(checkTx); |
dont_initialize(); |
sensitive << clk.pos(); |
//sensitive << uarttx; |
sensitive << uarttx; |
|
} // UartSC () |
|
void |
UartSC::initUart(int clk_freq_hz, // Presume in NS |
int uart_baud) |
UartSC::initUart(int uart_baud) |
{ |
// Calculate number of clocks per UART bit |
clocks_per_bit = (int)(clk_freq_hz / uart_baud); |
// Calculate number of ns per UART bit |
ns_per_bit = (int) ((long long)1000000000/(long long)uart_baud); |
bits_received = 0; |
|
// Init state of RX |
rx_state = 0; |
|
// Set input, ORPSoC's RX, line to high |
uartrx.write(true); |
|
|
#ifdef UART_SC_DEBUG |
printf |
("UartSC Initialised: Sys. clk. freq.: %d Hz, Baud: %d, cpb: %d\n", |
clk_freq_hz, uart_baud, clocks_per_bit); |
("UartSC Initialised: Baud: %d, ns per bit: %d\n", |
uart_baud, ns_per_bit); |
#endif |
} |
|
// Maybe do this with threads instead?! |
void UartSC::checkTx() |
// Some C from |
// http://cc.byexamples.com/2007/04/08/non-blocking-user-input-in-loop-without-ncurses/ |
// |
int UartSC::kbhit() |
{ |
#ifdef UART_SC_STDIN_ENABLE |
struct timeval tv; |
fd_set fds; |
tv.tv_sec = 0; |
tv.tv_usec = 0; |
FD_ZERO(&fds); |
FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 |
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); |
return FD_ISSET(STDIN_FILENO, &fds); |
#else |
return 0; |
#endif |
} |
|
#define NB_ENABLE 1 |
#define NB_DISABLE 0 |
|
// The following is apparently VERY Linux-centric. Maybe a ncurses version could |
// be handy if this gets used on various platforms. |
void UartSC::nonblock(int state) |
{ |
#ifdef UART_SC_STDIN_ENABLE |
struct termios ttystate; |
|
//get the terminal state |
tcgetattr(STDIN_FILENO, &ttystate); |
|
if (state==NB_ENABLE) |
{ |
//turn off canonical mode |
ttystate.c_lflag &= ~ICANON; |
//minimum of number input read. |
ttystate.c_cc[VMIN] = 1; |
} |
else if (state==NB_DISABLE) |
{ |
//turn on canonical mode |
ttystate.c_lflag |= ICANON; |
} |
//set the terminal attributes. |
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); |
#endif |
} |
|
|
|
void UartSC::driveRx() |
{ |
static char c; |
|
UartSC::nonblock(NB_ENABLE); |
|
while(1) |
{ |
if (rx_state == 0) // Waiting for a character input from user |
{ |
|
// Do we have a character on input? |
//c=cin.peek(); |
|
|
if (kbhit()) |
{ |
|
c = fgetc(stdin); |
#ifdef UART_SC_DEBUG |
//printf("Uart TX activity: level is : 0x%x\n", uarttx.read()&1); |
cout << "UartSC::driveRX got " << c << endl; |
#endif |
rx_state++; |
} |
|
// Check the number of bits received |
if (bits_received == 0) { |
// Check if tx is low |
if ((uarttx.read() & 1) == 0) { |
// Line pulled low, begin receive of new char |
current_char = 0; |
// Start |
counter = 1; |
bits_received++; // We got the start bit |
wait(1000000, SC_NS); |
|
} |
else if (rx_state == 1) |
{ |
#ifdef UART_SC_DEBUG |
cout << "UartSC checkTx: got start bit at time " << |
sc_time_stamp() << endl; |
cout << "UartSC::driveRX start-bit " << c << endl; |
#endif |
// Start bit - low |
uartrx.write(false); |
rx_state++; |
// Wait a bit |
wait(ns_per_bit, SC_NS); |
} |
} else if (bits_received > 0 && bits_received < 9) { |
// Check the counter - see if it's time to sample the line |
// We do an extra half-bit delay on first bit read |
if (((bits_received == 1) && |
(counter == (clocks_per_bit + (clocks_per_bit / 2)))) || |
((bits_received > 1) && (counter == clocks_per_bit))) { |
//printf("UartSC checkTx: read bit %d as 0x%x at time", bits_received, uarttx.read()&1); |
//cout << sc_time_stamp() << endl; |
else if (rx_state > 1 && rx_state < 10) |
{ |
#ifdef UART_SC_DEBUG |
cout << "UartSC::driveRX bit " << rx_state-2 << " " << |
(c & (1 << rx_state-2)) << endl; |
#endif |
|
// Shift in the current value of the tx into our char |
current_char |= |
((uarttx.read() & 1) << (bits_received - 1)); |
// Reset the counter |
counter = 1; |
if (c & (1 << rx_state-2)) |
uartrx.write(true); |
else |
uartrx.write(false); |
|
rx_state++; |
|
// Wait a bit |
wait(ns_per_bit, SC_NS); |
} |
else if (rx_state == 10) |
{ |
#ifdef UART_SC_DEBUG |
cout << "UartSC::driveRX stop bit" << endl; |
#endif |
rx_state = 0; |
// Stop bit |
uartrx.write(true); |
// Wait a bit |
wait(ns_per_bit + (ns_per_bit/2), SC_NS); |
|
} |
} |
} |
|
|
// Maybe do this with threads instead?! |
void UartSC::checkTx() |
{ |
while(1){ |
|
// Check the number of bits received |
if (bits_received == 0) { |
// Check if tx is low |
if ((uarttx.read() & 1) == 0) { |
|
// Line pulled low, begin receive of new char |
current_char = 0; |
|
//counter = 1; |
|
bits_received++; // We got the start bit |
|
// Now wait until next bit |
wait(ns_per_bit, SC_NS); |
#ifdef UART_SC_DEBUG |
cout << "UartSC checkTx: got start bit at time " |
<< sc_time_stamp() << endl; |
#endif |
} |
else |
// Nothing yet - keep waiting |
wait(ns_per_bit/2, SC_NS); |
|
} else if (bits_received > 0 && bits_received < 9) { |
|
current_char |= ((uarttx.read() & 1) << |
(bits_received - 1)); |
|
// Increment bit number |
bits_received++; |
} else |
counter++; |
} else if (bits_received == 9) { |
// Now check for stop bit 1 |
if (counter == clocks_per_bit) { |
// Check that the value is 1 - this should be the stop bit |
|
// Wait for next bit |
wait(ns_per_bit, SC_NS); |
|
|
} else if (bits_received == 9) { |
|
// Now check for stop bit 1 |
if ((uarttx.read() & 1) != 1) { |
printf("UART TX framing error at time\n"); |
cout << sc_time_stamp() << endl; |
|
// Perhaps do something else here to deal with this |
|
// Perhaps do something else here to deal with |
// this. |
bits_received = 0; |
counter = 0; |
} else { |
} |
else |
{ |
// Print the char |
#ifdef UART_SC_DEBUG |
printf("Char received: 0x%2x time: ", |
120,14 → 258,13
current_char); |
cout << sc_time_stamp() << endl; |
#endif |
// cout'ing the char didn't work for some systems - jb 090613ol |
// cout'ing the char didn't work for some |
// systems. |
//cout << current_char; |
printf("%c", current_char); |
|
|
bits_received = 0; |
counter = 0; |
} |
} else |
counter++; |
} |
} |
} |
/orpsocv2/bench/sysc/src/OrpsocMain.cpp
355,7 → 355,7
|
#ifdef UART0 |
// Init the UART function |
uart->initUart(50000000, 115200); |
uart->initUart(115200); |
#endif |
|
if (do_program_file_load) // Did the user specify a file to load? |
/orpsocv2/sim/bin/Makefile
428,7 → 428,7
|
# This file name corresponds to the VMEM file the RAM models will attempt to |
# load via $readmemh(). |
SIM_VMEM_IMAGE ?=sram.vmem |
SIM_DIR_VMEM_IMAGE ?=sram.vmem |
|
ifeq ($(USER_ELF),) |
ELF_FILE=$(TEST_SW_DIR)/$(TEST).elf |
448,12 → 448,12
# If USER_ELF was specified, then we need a slightly different way of |
# generating the VMEM file from it than a usual test |
ifeq ($(USER_ELF),) |
$(SIM_VMEM_IMAGE): $(VMEM_FILE) |
$(SIM_DIR_VMEM_IMAGE): $(VMEM_FILE) |
$(Q)if [ -L $@ ]; then unlink $@; fi |
$(Q)if [ -e $@ ]; then rm $@; fi |
$(Q)ln -s $< $@ |
else |
$(SIM_VMEM_IMAGE): $(USER_ELF) |
$(SIM_DIR_VMEM_IMAGE): $(USER_ELF) |
$(Q)$(MAKE) -C $(SW_DIR)/lib \ |
USER_ELF_BIN=`pwd`/$(ELF_FILE_NOTDIR_BASENAME).bin \ |
USER_ELF_VMEM=`pwd`/$(ELF_FILE_NOTDIR_BASENAME).vmem \ |
468,7 → 468,7
USER_VMEM_NOTDIR=$(notdir $(USER_VMEM)) |
TEST=$(basename $(USER_VMEM_NOTDIR)) |
|
$(SIM_VMEM_IMAGE): $(VMEM_FILE) |
$(SIM_DIR_VMEM_IMAGE): $(VMEM_FILE) |
cp -v $< $@ |
|
endif |
477,7 → 477,7
|
|
.PHONY : sw-vmem sw-elf |
sw-vmem: $(SIM_VMEM_IMAGE) |
sw-vmem: $(SIM_DIR_VMEM_IMAGE) |
|
$(TEST_SW_DIR)/$(TEST).vmem: |
$(Q) echo; echo "\t### Compiling software ###"; echo; |
535,7 → 535,7
$(Q)rm -f $(TEST_DEFINES_VLG) |
|
clean-sim-test-sw: |
$(Q)if [ -L $(SIM_VMEM_IMAGE) ]; then unlink $(SIM_VMEM_IMAGE); fi |
$(Q)if [ -L $(SIM_DIR_VMEM_IMAGE) ]; then unlink $(SIM_DIR_VMEM_IMAGE); fi |
|
clean-sw: |
$(Q) echo; echo "\t### Cleaning simulation sw directories ###"; echo; |
/orpsocv2/boards/xilinx/ml501/sim/bin/Makefile
432,7 → 432,7
|
|
.PHONY: rtl-test |
rtl-test: clean-sim-test-sw sw clean-test-defines $(TEST_DEFINES_VLG) \ |
rtl-test: clean-sim-test-sw sw-vmem clean-test-defines $(TEST_DEFINES_VLG) \ |
$(SIMULATOR) |
|
# Run an RTL test followed by checking of generated results |
480,13 → 480,13
BOARD_SW_TEST_DIR=$(BOARD_SW_DIR)/tests/$(TEST_MODULE)/sim |
COMMON_SW_TEST_DIR=$(COMMON_SW_DIR)/tests/$(TEST_MODULE)/sim |
# Do this by testing for the file's existence |
SW_TEST_DIR=$(shell if [ -e $(BOARD_SW_TEST_DIR)/$(TEST).[cS] ]; then echo $(BOARD_SW_TEST_DIR); else echo $(COMMON_SW_TEST_DIR); fi) |
TEST_SW_DIR=$(shell if [ -e $(BOARD_SW_TEST_DIR)/$(TEST).[cS] ]; then echo $(BOARD_SW_TEST_DIR); else echo $(COMMON_SW_TEST_DIR); fi) |
|
print-test-sw-dir: |
@echo; echo "\tTest software is in the following path"; echo; |
@echo $(BOARD_SW_DIR); echo; |
@echo $(BOARD_SW_TEST_DIR); echo; |
@echo $(SW_TEST_DIR); echo; |
@echo $(TEST_SW_DIR); echo; |
|
print-sw-tests: |
$(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib print-sw-tests |
499,44 → 499,88
# Set PRELOAD_RAM=1 to preload the system memory - be sure the bootROM program |
# chosen in board.h is the one booting from the reset vector. |
ifeq ($(PRELOAD_RAM), 1) |
SIM_SW_IMAGE ?=sram.vmem |
SIM_DIR_VMEM_IMAGE ?=sram.vmem |
else |
SIM_SW_IMAGE ?=flash.in |
SIM_DIR_VMEM_IMAGE ?=flash.in |
endif |
|
# Amount to pad the image we'll load into the SPI flash |
HEX_IMAGE_PADDING ?=0x1c0000 |
# Ability to bypass all stuffing around involved with generating software and |
# directly specify an ELF |
ifeq ($(USER_ELF),) |
ELF_FILE=$(TEST_SW_DIR)/$(TEST).elf |
else |
ELF_FILE=$(USER_ELF) |
ELF_FILE_NOTDIR=$(notdir $(USER_ELF)) |
ELF_FILE_NOTDIR_BASENAME=$(basename $(ELF_FILE_NOTDIR)) |
endif |
|
.PHONY : sw |
sw: $(SIM_SW_IMAGE) |
|
# Rules allowing user to specify a pre-existing VMEM file to load into the |
# simulation, instead of compiling a test. |
ifeq ($(USER_VMEM),) |
|
flash.in: $(SW_TEST_DIR)/$(TEST).flashin |
$(Q)if [ -L $@ ]; then unlink $@; fi |
$(Q)ln -s $< $@ |
|
sram.vmem: $(SW_TEST_DIR)/$(TEST).vmem |
ifeq ($(PRELOAD_RAM), 1) |
VMEM_FILE ?= $(TEST_SW_DIR)/$(TEST).vmem |
else |
VMEM_FILE ?= $(TEST_SW_DIR)/$(TEST).flashin |
endif |
.PHONY: $(VMEM_FILE) |
|
|
# If USER_ELF was specified, then we need a slightly different way of |
# generating the VMEM file from it than a usual test |
ifeq ($(USER_ELF),) |
$(SIM_DIR_VMEM_IMAGE): $(VMEM_FILE) |
$(Q)if [ -L $@ ]; then unlink $@; fi |
$(Q)if [ -e $@ ]; then rm $@; fi |
$(Q)ln -s $< $@ |
else # !($(USER_ELF),) - USER_ELF set on command line |
$(SIM_DIR_VMEM_IMAGE): $(USER_ELF) |
$(Q)$(MAKE) -C $(COMMON_SW_DIR)/lib \ |
USER_ELF_BIN=`pwd`/$(ELF_FILE_NOTDIR_BASENAME).bin \ |
USER_ELF_VMEM=`pwd`/$(ELF_FILE_NOTDIR_BASENAME).vmem \ |
gen-user-elf-vmem |
$(Q)cp -v $(ELF_FILE_NOTDIR_BASENAME).vmem $@ |
|
.PHONY: $(SW_TEST_DIR)/$(TEST).flashin |
$(SW_TEST_DIR)/$(TEST).flashin: |
TEST=$(ELF_FILE_NOTDIR_BASENAME) |
endif |
|
else # !($(USER_VMEM),) - USER_VMEM set on command line |
VMEM_FILE=$(USER_VMEM) |
USER_VMEM_NOTDIR=$(notdir $(USER_VMEM)) |
TEST=$(basename $(USER_VMEM_NOTDIR)) |
|
$(SIM_DIR_VMEM_IMAGE): $(VMEM_FILE) |
cp -v $< $@ |
|
endif |
|
|
# Amount to pad the image we'll load into the SPI flash for ML501 sims |
HEX_IMAGE_PADDING ?=0x1c0000 |
|
.PHONY : sw-vmem sw-elf |
sw-vmem: $(SIM_DIR_VMEM_IMAGE) |
|
.PHONY: $(TEST_SW_DIR)/$(TEST).flashin |
$(TEST_SW_DIR)/$(TEST).flashin: |
$(Q) echo; echo "\t### Compiling software ###"; echo; |
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).flashin \ |
$(Q)$(MAKE) -C $(TEST_SW_DIR) $(TEST).flashin \ |
HEX_IMAGE_PADDING=$(HEX_IMAGE_PADDING) |
|
.PHONY: $(SW_TEST_DIR)/$(TEST).vmem |
$(SW_TEST_DIR)/$(TEST).vmem: |
.PHONY: $(TEST_SW_DIR)/$(TEST).vmem |
$(TEST_SW_DIR)/$(TEST).vmem: |
$(Q) echo; echo "\t### Compiling software ###"; echo; |
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).vmem |
$(Q)$(MAKE) -C $(TEST_SW_DIR) $(TEST).vmem |
|
# Create test software disassembly |
|
sw-dis: $(SW_TEST_DIR)/$(TEST).dis |
sw-dis: $(TEST_SW_DIR)/$(TEST).dis |
$(Q)cp -v $< . |
|
$(SW_TEST_DIR)/$(TEST).dis: |
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).dis |
$(TEST_SW_DIR)/$(TEST).dis: |
$(Q)$(MAKE) -C $(TEST_SW_DIR) $(TEST).dis |
|
# |
# Cleaning rules |
558,7 → 602,7
$(Q)rm -f $(TEST_DEFINES_VLG) |
|
clean-sim-test-sw: |
$(Q)if [ -e $(SIM_SW_IMAGE) ]; then unlink $(SIM_SW_IMAGE); fi |
$(Q)if [ -L $(SIM_DIR_VMEM_IMAGE) ]; then unlink $(SIM_DIR_VMEM_IMAGE); fi |
|
clean-sw: |
$(Q) echo; echo "\t### Cleaning simulation sw directories ###"; echo; |