Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • roberto/cmips
  • vsbc14/killer
  • laps15/cmips
3 results
Select Git revision
Show changes
Commits on Source (31)
Showing
with 1573 additions and 221 deletions
The repository was moved to https://github.com/rhexsel/cmips
This repo will not be updated.
28th april 2017.
cMIPS
cMIPS is a synthesizable VHDL model for the 5-stage pipeline, MIPS32r2 core.
......
......@@ -54,6 +54,7 @@ exit 1
if [ $# = 0 ] ; then usage ; exit 1 ; fi
miffile=false
pacMem_changed=false
verbose=false
names=false
unset mem_map
......@@ -86,7 +87,9 @@ while true ; do
;;
-n) names=true
;;
-mif|-m) miffile=true
-mif | -syn ) miffile=true
;;
-new ) pacMem_changed=true
;;
-x) set -x
;;
......@@ -101,9 +104,26 @@ done
if [ -z $inp ] ; then usage ; exit 1 ; fi
pkg_vhd="${srcVHDL}"/packageMemory.vhd
# pkg_vhd="${srcVHDL}"/packageMemory.vhd
if [ $miffile = true ]; then
S="-D FOR_SYNTHESIS" ;
pkg_vhd="${srcVHDL}"/packageMemory_fpga.vhd
(cd $srcVHDL ; ln -s -f packageMemory_fpga.vhd packageMemory.vhd)
# ln -sf ${srcVHDL}/packageMemory_fpga.vhd $pkg_vhd
# touch $pkg_vhd
else
S="-U FOR_SYNTHESIS" ;
pkg_vhd="${srcVHDL}"/packageMemory_simu.vhd
(cd $srcVHDL ; ln -s -f packageMemory_simu.vhd packageMemory.vhd)
# ln -sf ${srcVHDL}/packageMemory_simu.vhd $pkg_vhd
# touch $pkg_vhd
fi
if [ $pkg_vhd -nt $c_ld -o $pkg_vhd -nt $c_s ] ; then
if [ $pacMem_changed -o\
$pkg_vhd -nt $c_ld -o\
$pkg_vhd -nt $c_s ] ; then
"${bin}"/edMemory.sh -v || errorED || exit 1
fi
......
#!/bin/bash
## ------------------------------------------------------------------------
## cMIPS, Roberto Hexsel, 30set2013, rev 08jan2015
## cMIPS, Roberto Hexsel, 30set2013, rev 08jan2015, 04apr2017
## ------------------------------------------------------------------------
# set -x
......@@ -19,19 +19,57 @@ EOF
exit 1
}
errorCOMPILING()
{
cat <<EOF
$0: error in compiling VHDL sources
remove cMIPS/vhdl/.last_import and cMIPS/vhdl/work-obj93.cf
and re-compile
EOF
exit 1
}
usage()
{
cat << EOF
usage: $0 [options]
creates VHDL simulator
OPTIONS:
-h Show this message
-syn Compile for Macnica's board, else for simulation
-new Automagically update all addresses (packageMemory.vhd changed)
-x turn on "set -x"
EOF
}
synth=false
pacMem_changed=false
while true ; do
case "$1" in
-h) usage ; exit 1
;;
-syn | -mif ) synth=true
;;
-new ) pacMem_changed=true
;;
-x) set -x
;;
*) break ; #usage
# echo " invalid option: $1"; exit 1
;;
esac
shift
done
if [ ! -v tree ] ; then
# you must set the location of the cMIPS root directory in the variable tree
......@@ -44,13 +82,20 @@ fi
bin="${tree}"/bin
include="${tree}"/include
srcVHDL="${tree}"/vhdl
# obj="${tree}"/obj
c_ld="${include}"/cMIPS.ld
c_s="${include}"/cMIPS.s
c_h="${include}"/cMIPS.h
pkg_vhd="$srcVHDL/packageMemory.vhd"
if [ $synth = true ] ; then
pkg_vhd="$srcVHDL/packageMemory_fpga.vhd"
(cd $srcVHDL ; ln -s -f packageMemory_fpga.vhd packageMemory.vhd)
else
pkg_vhd="$srcVHDL/packageMemory_simu.vhd"
(cd $srcVHDL ; ln -s -f packageMemory_simu.vhd packageMemory.vhd)
fi
if [ $pkg_vhd -nt $c_ld -o\
$pkg_vhd -nt $c_s -o\
......@@ -59,6 +104,9 @@ if [ $pkg_vhd -nt $c_ld -o\
"${bin}"/edMemory.sh -v || errorED || exit 1
fi
if [ $pacMem_changed ] ; then
"${bin}"/edMemory.sh -v || errorED || exit 1
fi
cd "${srcVHDL}"
......@@ -66,7 +114,7 @@ simulator=tb_cmips
pkg="packageWires.vhd packageMemory.vhd packageExcp.vhd"
src="aux.vhd altera.vhd macnica.vhd cache.vhd instrcache.vhd sdram.vhd ram.vhd rom.vhd units.vhd io.vhd uart.vhd fpu.vhd pipestages.vhd exception.vhd core.vhd tb_cMIPS.vhd"
src="aux.vhd altera.vhd macnica.vhd cache.vhd instrcache.vhd sdram.vhd ram.vhd rom.vhd units.vhd SDcard.vhd io.vhd uart.vhd fpu.vhd pipestages.vhd exception.vhd core.vhd tb_cMIPS.vhd"
# build simulator
#ghdl --clean
......@@ -74,16 +122,14 @@ src="aux.vhd altera.vhd macnica.vhd cache.vhd instrcache.vhd sdram.vhd ram.vhd r
#ghdl -a --ieee=standard "${srcVHDL}"/packageMemory.vhd || exit 1
#ghdl -a --ieee=standard "${srcVHDL}"/packageExcp.vhd || exit 1
#for F in ${src} ; do
# if [ ! -s ${F}.o -o "${srcVHDL}"/${F}.vhd -nt ${F}.o ] ; then
# ghdl -a --ieee=standard "${srcVHDL}"/${F}.vhd || exit 1
# if [ ! -s ${F%.vhd}.o -o "${srcVHDL}"/${F} -nt ${F%.vhd}.o ] ; then
# ghdl -a --ieee=standard "${srcVHDL}"/${F} || exit 1
# fi
#done
#
#ghdl -c "${srcVHDL}"/*.vhd -e ${simulator} || exit 1
# NOTE: when you add a new sourcefile to this project, you must include it
# with "ghdl -i newFile.vhd" so that ghdl learns about it. It may be
# a good idea to remove ./.last_import to force a full rebuild.
......
......@@ -37,6 +37,7 @@ OPTIONS:
-W Pass -Wall on to GCC
-mif Generate output file ROM.mif for Altera's FPGAs
-syn Compile for synthesis, else for simulation
-new Automagically update all addresses (packageMemory.vhd changed)
EOF
}
......@@ -57,6 +58,7 @@ if [ $# = 0 ] ; then usage ; exit 1 ; fi
miffile=false
synth=false
pacMem_changed=false
verbose=false
names=true
unset memory_map
......@@ -84,9 +86,10 @@ while true ; do
;;
-n) names=false
;;
-mif) miffile=true
-mif | -syn ) synth=true
miffile=true
;;
-syn) synth=true
-new ) pacMem_changed=true
;;
-x) set -x
;;
......@@ -111,11 +114,26 @@ c_h="${include}"/cMIPS.h
c_s="${include}"/cMIPS.s
c_io="${include}"/cMIPSio
# c_start="${include}"/start ## see below for synthesis version
c_hndlrs="${include}"/handlers
# c_hndlrs="${include}"/handlers ## see below for synthesis version
pkg_vhd="${srcVHDL}"/packageMemory.vhd
if [ $pkg_vhd -nt $c_h -o\
if [ $synth = true ]; then
S="-D FOR_SYNTHESIS" ;
c_start="${include}"/syn_start
c_hndlrs="${include}"/syn_handlers
pkg_vhd="${srcVHDL}"/packageMemory_fpga.vhd
(cd $srcVHDL ; ln -s -f packageMemory_fpga.vhd packageMemory.vhd)
else
S="-U FOR_SYNTHESIS" ;
c_start="${include}"/start
c_hndlrs="${include}"/handlers
pkg_vhd="${srcVHDL}"/packageMemory_simu.vhd
(cd $srcVHDL ; ln -s -f packageMemory_simu.vhd packageMemory.vhd)
fi
if [ $pacMem_changed -o\
$pkg_vhd -nt $c_h -o\
$pkg_vhd -nt $c_ld -o\
$pkg_vhd -nt $c_s ] ; then
"${bin}"/edMemory.sh -v || errorED || exit 1
......@@ -130,13 +148,6 @@ dat=data.bin
if [ $verbose = true ]; then memory_map="-Map ${inp}.map" ; fi
if [ $synth = true ]; then
S="-D FOR_SYNTHESIS" ;
c_start="${include}"/syn_start
else
S="-U FOR_SYNTHESIS" ;
c_start="${include}"/start
fi
(mips-gcc -O${level} $warn -DcMIPS -mno-gpopt -I"${include}" \
-S ${src} $S -o ${asm} || exit 1) && \
......@@ -149,8 +160,8 @@ mips-ld -EL -e _start ${memory_map} -I "${include}" --script $c_ld \
-o $elf ${c_start}.o ${c_hndlrs}.o ${c_io}.o $obj || exit 1
mips-objcopy -S -j .text -O binary $elf $bin && \
mips-objcopy -S -j .data -j .rodata -j .rodata1 -j .data1 \
-j .sdata -j .lit8 -j .lit4 -j .sbss -j .bss -j .PT \
mips-objcopy -S -j .data -j .data1 -j .lit8 -j .lit4 -j .sdata \
-j .sbss -j .bss -j .rodata1 -j .rodata -j .PT \
-O binary $elf $dat || exit 1
if [ $names = true ] ; then
......@@ -162,8 +173,8 @@ fi
if [ $? == 0 -a $verbose = true ]; then
mips-objdump -z -D -EL $reg_names --show-raw-insn \
--section .text --section .data \
--section .rodata --section .sdata --section .sbss \
--section .bss --section .PT $elf
--section .sdata --section .sbss \
--section .bss --section .rodata --section .PT $elf
fi
if [ $? == 0 -a $miffile = true ] ; then
......
......@@ -86,6 +86,15 @@ then
fi
done
# set up address for base of Page Table
VAR=x_DATA_BASE_ADDR
NEW=$(egrep -h ${VAR} "${dfn}" | sed -n -e '/reg32/s/.*x"\(.*\)".*/\1/p')
OLD=$(egrep -h ${VAR} "${lnk}" | sed -n -e 's/.* = 0x\(.*\); .*/\1/p')
# echo -n -e "$NEW $OLD\n"
if [ -n "$OLD" ] ; then
sed -i -e '/'$VAR'/s/'$OLD'/'$NEW'/' "${lnk}"
fi
# set up address for base of Page Table
VAR=x_DATA_MEM_SZ
NEW=$(egrep -h ${VAR} "${dfn}" | sed -n -e '/reg32/s/.*x"\(.*\)".*/\1/p')
......
......@@ -26,6 +26,7 @@ unset WAVE
length=1
unit=m
gtkwconf=pipe
synth=
touch input.data input.txt serial.inp
......@@ -42,6 +43,7 @@ OPTIONS:
-n send simulator output do /dev/null, else to v_cMIPS.vcd
-w invoke GTKWAVE -- stdin will not read input from keyboard
-v F gtkwave configuration file (e.g. pipe.sav, default v.sav)
-syn run simulation with synthesis RAM/ROM addresses
EOF
}
......@@ -60,6 +62,8 @@ while true ; do
;;
-w) WAVE=true
;;
-syn | -mif ) synth="-syn"
;;
-v) gtkwconf=$2
shift
;;
......@@ -77,15 +81,15 @@ gfile=${gtkwconf%%.sav}
sav="${tree}"/${gfile}.sav
"${bin}"/build.sh || exit 1
"${bin}"/build.sh $synth || exit 1
options="--ieee-asserts=disable --stop-time=${length}${unit}s --vcd=${visual}"
if [ -v $WAVE ] ; then
## simulator must be exec'd so it can read from the standard input
exec "${simulator}" $options
exec "${simulator}" $options --vcd-nodate
else
......@@ -95,5 +99,5 @@ fi
# --wave=${visual%.vcd}.ghw
## --wave=${visual%.vcd}.ghw
###
### this file in NOT a shell script,
### yet it was written to make it easy for cutting-n-pasting with the pointer
### yet it was written to make it easy for cutting-n-pasting with the mouse
###
# to compile GCC, these three libraries may have to be fetched:
wget http://www.mpfr.org/mpfr-current/mpfr-3.1.3.tar.gz
wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.2.tar.gz
wget ftp://ftp.gmplib.org/pub/gmp/gmp-6.0.0.tar.bz2
wget http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.gz
wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
wget ftp://ftp.gmplib.org/pub/gmp/gmp-6.1.2.tar.bz2
# it is (very) likely that new(er) versions have been released; please
# fetch the new(est) versions.
# and, according to instructions in
# http://gcc.gnu.org/install/prerequisites.html
# expand the tarballs into the directory with GCC sources, change their
# after you downloaded and expanded the GCC sources, expand the three
# tarballs into the directory with GCC sources, change their
# directory names to mpfr mpc gmp (removing the version suffixes);
# these libraries are then compiled along with GCC
# then these libraries will be automagically compiled as part of GCC.
# OTOH, if you are very lucky, the libraries installed by aptitude will do...
# fetch all the auxiliary programs -- this assumes a Debian installation
aptitude install make flex bison libgmp-dev libmpfr-dev libmpc-dev g++
# clean up any aliases/function replacements for /bin/ls
unset ls
# make sure the installed files are read-exec by all
......@@ -33,12 +39,17 @@ COMPILER=gcc-5.1.0
wget -c http://ftp.gnu.org/gnu/binutils/${BINUTILS}.tar.bz2
wget -c http://ftp.gnu.org/gnu/gcc/${COMPILER}/${COMPILER}.tar.gz
# the cross-compiler will be installed in /opt/cross so it does not,
# in any way, conflicts with the native GCC or binutils.
# set the installation pathname as PREFIX so that {bin,lib,man} are put there
# make sure you have write permission to /opt/cross,
# else perform the "make install" steps as root (with umask 022)
export PREFIX=/opt/cross/
export TARGET=mips
## build and install binutils (takes a few minutes)
tar -xvjf ${BINUTILS}.tar.bz2
cd ${BINUTILS}
./configure --target=$TARGET --prefix=$PREFIX --disable-nls
......@@ -49,10 +60,20 @@ make
make install
cd ..
## build and install GCC (takes rather more than a few minutes)
tar -xvzf ${COMPILER}.tar.gz
cd ${COMPILER}
# you may want/need to expand the libraries' tarballs at this point
# you may want/need to expand the libraries' tarballs at this point,
# by doing
# [[ do not copy these commands unless versions are same as shown below ]]
# tar -xvjf ../gmp-6.1.2.tar.bz2
# mv gmp-6.1.2/ gmp
# tar -xvzf ../mpc-1.0.3.tar.gz
# mv mpc-1.0.3/ mpc
# tar -xxvf ../mpfr-3.1.5.tar.xz
# mv mpfr-3.1.5/ mpfr
export PATH=$PATH:$PREFIX/bin
./configure --target=$TARGET --prefix=$PREFIX --disable-nls \
......@@ -66,6 +87,7 @@ cd ..
# once GCC and Binutils are compiled and installed, all that is needed is
# for you to add the new path to your PATH, preferably in your ~/.bashrc
# do not forget to substitute ${PREFIX} by /opt/cross in ~/.bashrc
export PATH=${PATH}:${PREFIX}/bin
export MANPATH=${MANPATH}:${PREFIX}/man
......@@ -83,7 +105,7 @@ export MANPATH=${MANPATH}:${PREFIX}/man
# to download the .deb files onto the same directory as ghdl*.deb
#
# When doing dpkg -i ghdl*.deb it will whine and complain about versions.
# What I have done is to use the following DANGEROUS and RISKY command:
# What I have done is to use the following RISKY command:
#
# dpkg --ignore-depends=ghdl*.deb --ignore-depends=libgnat-4.6 -i ghdl*.deb
#
......
......@@ -10,21 +10,31 @@
#define x_IO_ADDR_MASK (0 - x_IO_ADDR_RANGE)
#define IO_PRINT_ADDR x_IO_BASE_ADDR;
#define IO_STDOUT_ADDR (x_IO_BASE_ADDR + 1 * x_IO_ADDR_RANGE);
#define IO_STDIN_ADDR (x_IO_BASE_ADDR + 2 * x_IO_ADDR_RANGE);
#define IO_READ_ADDR (x_IO_BASE_ADDR + 3 * x_IO_ADDR_RANGE);
#define IO_WRITE_ADDR (x_IO_BASE_ADDR + 4 * x_IO_ADDR_RANGE);
#define IO_COUNT_ADDR (x_IO_BASE_ADDR + 5 * x_IO_ADDR_RANGE);
#define IO_FPU_ADDR (x_IO_BASE_ADDR + 6 * x_IO_ADDR_RANGE);
#define IO_UART_ADDR (x_IO_BASE_ADDR + 7 * x_IO_ADDR_RANGE);
#define IO_STATS_ADDR (x_IO_BASE_ADDR + 8 * x_IO_ADDR_RANGE);
#define IO_DSP7SEG_ADDR (x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE);
#define IO_KEYBD_ADDR (x_IO_BASE_ADDR +10 * x_IO_ADDR_RANGE);
#define IO_LCD_ADDR (x_IO_BASE_ADDR +11 * x_IO_ADDR_RANGE);
#define IO_PRINT_ADDR x_IO_BASE_ADDR
#define IO_STDOUT_ADDR (x_IO_BASE_ADDR + 1 * x_IO_ADDR_RANGE)
#define IO_STDIN_ADDR (x_IO_BASE_ADDR + 2 * x_IO_ADDR_RANGE)
#define IO_READ_ADDR (x_IO_BASE_ADDR + 3 * x_IO_ADDR_RANGE)
#define IO_WRITE_ADDR (x_IO_BASE_ADDR + 4 * x_IO_ADDR_RANGE)
#define IO_COUNT_ADDR (x_IO_BASE_ADDR + 5 * x_IO_ADDR_RANGE)
#define IO_FPU_ADDR (x_IO_BASE_ADDR + 6 * x_IO_ADDR_RANGE)
#define IO_UART_ADDR (x_IO_BASE_ADDR + 7 * x_IO_ADDR_RANGE)
#define IO_STATS_ADDR (x_IO_BASE_ADDR + 8 * x_IO_ADDR_RANGE)
#define IO_DSP7SEG_ADDR (x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
#define IO_KEYBD_ADDR (x_IO_BASE_ADDR +10 * x_IO_ADDR_RANGE)
#define IO_LCD_ADDR (x_IO_BASE_ADDR +11 * x_IO_ADDR_RANGE)
#define IO_SDC_ADDR (x_IO_BASE_ADDR +12 * x_IO_ADDR_RANGE)
extern void exit(int);
extern void cmips_delay(int);
extern void delay_cycle(int);
extern void delay_us(int);
extern void delay_ms(int);
extern void enableInterr(void);
extern void disableInterr(void);
extern void print(int);
extern void to_stdout(char c);
extern int from_stdin(void);
......@@ -33,19 +43,25 @@ extern void writeInt(int);
extern void writeClose(void);
extern int readInt(int*);
extern void dumpRAM(void);
extern int print_sp(void);
extern int print_status(void);
extern int print_cause(void);
extern void cmips_delay(int);
extern char *memcpy(char*, const char*, int);
extern char *memset(char*, const int, int);
// external counter (peripheral)
extern void startCounter(int, int);
extern void stopCounter(void);
extern int readCounter(void);
extern void enableInterr(void);
extern void disableInterr(void);
extern char *memcpy(char*, const char*, int);
extern char *memset(char*, const int, int);
// internal counter, CP0 register COUNT
extern int startCount(void);
extern int stopCount(void);
extern int readCount(void);
// LCD display (Macnica board)
#define LCDprint(n) LCDint((n))
extern void LCDinit(void);
extern int LCDprobe(void);
extern int LCDset(int);
......@@ -53,14 +69,24 @@ extern int LCDput(int);
extern void LCDclr(void);
extern void LCDtopLine(void);
extern void LCDbotLine(void);
extern void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot);
extern void LCDgotoxy(int, int);
extern void LCDputc(char);
extern void LCDint(unsigned int);
extern void LCDshort(unsigned short);
extern void LCDbyte(unsigned char);
// 7-segment display and keyboard (Macnica board)
extern void DSP7SEGput(int, int, int, int, int);
extern int KBDget(void);
extern int SWget(void);
// RGB led color for DSP7SEGput (color must be in [0,7]
#define l_RED 0x4
#define l_GREEN 0x2
#define l_BLUE 0x1
// struct to access the system statistics "peripheral"
// struct to access the cache system statistics "peripheral"
typedef struct sStats {
int dc_ref; // data cache references
int dc_rd_hit; // data cache read-hits
......
......@@ -28,8 +28,6 @@ SECTIONS
_edata = . ; /* end of data constant (from Xinu) */
} > ram
.data1 : { *(.data1) } > ram
.rodata : { *(.rodata .rodata.*) } > ram
.rodata1 : { *(.rodata1) } > ram
.lit8 : { *(.lit8) } > ram
.lit4 : { *(.lit4) } > ram
.sdata : { *(.sdata .sdata.*) } > ram
......@@ -37,12 +35,18 @@ SECTIONS
.bss :
{
*(.bss .bss.*) *(COMMON)
} > ram
.rodata1 : { *(.rodata1) } > ram
.rodata :
{
*(.rodata .rodata.*)
_end = . ; /* end of image constant (from Xinu) */
} > ram
start_RAM = 0x00040000; /* x_DATA_BASE_ADDR */
end_RAM = 0x00020000; /* x_DATA_MEM_SZ */
half_RAM = (end_RAM / 2);
base_PT = ( _bdata + half_RAM );
half_RAM = (end_RAM >> 1);
base_PT = ( start_RAM + half_RAM );
.PT base_PT : { *(.PT) } > ram
}
......@@ -19,6 +19,7 @@
.set HW_dsp7seg_addr,(x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
.set HW_keybd_addr, (x_IO_BASE_ADDR + 10 * x_IO_ADDR_RANGE)
.set HW_lcd_addr, (x_IO_BASE_ADDR + 11 * x_IO_ADDR_RANGE)
.set HW_sdc_addr, (x_IO_BASE_ADDR + 12 * x_IO_ADDR_RANGE)
# see vhdl/packageMemory.vhd for addresses
.set x_EXCEPTION_0000,0x00000130
......@@ -28,25 +29,6 @@
.set x_EXCEPTION_BFC0,0x000004E0
.set x_ENTRY_POINT, 0x00000500
.set cop0_Index, $0
.set cop0_Random, $1
.set cop0_EntryLo0,$2
.set cop0_EntryLo1,$3
.set cop0_Context ,$4
.set cop0_PageMask,$5
.set cop0_Wired, $6
.set cop0_BadVAddr,$8
.set cop0_COUNT ,$9
.set cop0_EntryHi ,$10
.set cop0_COMPARE ,$11
.set cop0_STATUS ,$12
.set cop0_CAUSE ,$13
.set cop0_EPC, $14
.set cop0_CONFIG, $16
.set cop0_CONFIG_f0,0
.set cop0_CONFIG_f1,1
.set cop0_LLAddr, $17
.set cop0_ErrorPC, $30
.set c0_index, $0
.set c0_random, $1
......@@ -70,10 +52,17 @@
# reset: COP0 present, at exception level, all else disabled
.set cop0_STATUS_reset,0x10000002
.set c0_status_reset,0x10000002
# normal state: COP0 present, user mode, all IRQs enabled
.set cop0_STATUS_normal,0x1000ff11
.set c0_status_normal,0x1000ff11
# reset: COUNTER stopped, use special interrVector, no interrupts
.set cop0_CAUSE_reset, 0x0880007c
.set c0_cause_reset, 0x0880007c
.equ led_RED, 0x4000
.equ led_GRE, 0x2000
.equ led_BLU, 0x1000
.equ led_OFF, 0x0FFF
......@@ -232,10 +232,13 @@ int SWget(void) {
#define LCD_write_delay 750/4 // 15us / 20ns
#define LCD_busy 0x80
#define LCD_LINE_TWO 0x40 // RAM address for second line
void LCDinit(void) {
int *IO = (int *)IO_LCD_ADDR;
cmips_delay(LCD_reset_cycles); // wait for LCD controller to reset
cmips_delay(LCD_reset_cycles); // wait 50ms for LCD controller to reset
*IO = 0b00110000; // x30 = wake-up
cmips_delay(LCD_delay_30us);
......@@ -265,11 +268,11 @@ void LCDinit(void) {
*IO = 0b00001111; // x0f displayON/OFF: Off, cur=on, blnk=on
cmips_delay(LCD_oper_delay);
*IO = 0b00000110; // x06 entry mode: blink, noShift, addrs++
cmips_delay(LCD_oper_delay);
*IO = 0b00000001; // x01 clear display -- DELAY=0.6ms
cmips_delay(LCD_clear_delay);
*IO = 0b00000110; // x06 entry mode: blink, noShift, addrs++
cmips_delay(LCD_oper_delay);
}
// check LCD's status register
......@@ -284,13 +287,14 @@ int LCDset(int cmd) {
volatile int s;
*IO = cmd;
cmips_delay(LCD_oper_delay);
s = *IO;
while ( (s & LCD_busy) != 0) { s = *IO; }; // still busy?
return(s);
}
// put a character on the current position
// write a "raw" character on the current position
int LCDput(int c) {
int *IO = (int *)IO_LCD_ADDR;
volatile int s;
......@@ -321,16 +325,94 @@ void LCDbotLine(void) {
*IO = 0b11000000; // xc0 RAMaddrs=40, cursor at home on BOTTOM LINE
cmips_delay(LCD_clear_delay);
}
// set cursor at position (x,y)
void LCDgotoxy(int x, int y) {
int address;
if(y != 1)
address = LCD_LINE_TWO;
else
address = 0;
address += (x - 1);
LCDset( 0x80 | (address & 0x7f) ); // write to control register
}
// write a "cooked" character to the display
void LCDputc(char c) {
switch (c) {
case '\f' : LCDset(1); cmips_delay(LCD_clear_delay); break;
case '\n' : LCDgotoxy(1,2); break;
case '\b' : LCDset(0x10); break;
default : LCDput(c); break;
}
}
#define conv(c) ((c<10)?((c)+0x30):((c)+('a'-10)))
// write an integer to the display
void LCDint(unsigned int n) {
int k;
k = (n >>28);
LCDput( conv(k) );
k = (n<< 4)>>28;
LCDput( conv(k) );
k = (n<< 8)>>28;
LCDput( conv(k) );
k = (n<<12)>>28;
LCDput( conv(k) );
k = (n<<16)>>28;
LCDput( conv(k) );
k = (n<<20)>>28;
LCDput( conv(k) );
k = (n<<24)>>28;
LCDput( conv(k) );
k = (n<<28)>>28;
LCDput( conv(k) );
}
// write a short to the display
void LCDshort(unsigned short n) {
int k;
k = (n >>12);
LCDput( conv(k) );
k = (n<< 4)>>12;
LCDput( conv(k) );
k = (n<< 8)>>12;
LCDput( conv(k) );
k = (n<<12)>>12;
LCDput( conv(k) );
}
// write a char to the display
void LCDbyte(unsigned char n) {
int k;
k = (n >>4);
LCDput( conv(k) );
k = (n<< 4)>>4;
LCDput( conv(k) );
}
//-----------------------------------------------------------------------
//=======================================================================
// 7 segment display
//=======================================================================
// 7 segment display and RGB leds
// rgb values are in [0,7], stored in bits R=bit14, G=bit13, B=bit12
// MSdigit bits bit7..4, lsDigit bit3..0, MSD dot bit9, lsD dot bit8
void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot) {
//=======================================================================
void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot, int rgb) {
int *IO = (int *)IO_DSP7SEG_ADDR;
int w, dot1, dot0, dig1, dig0;
int leds, dot1, dot0, dig1, dig0;
dot1 = (MSdot != 0 ? 1 << 9 : 0);
dot0 = (lsdot != 0 ? 1 << 8 : 0);
......@@ -338,7 +420,9 @@ void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot) {
dig1 = (MSD & 0xf) << 4;
dig0 = (lsd & 0xf);
*IO = dot1 | dot0 | dig1 | dig0;
leds = (rgb & 0x07) <<12;
*IO = leds | dot1 | dot0 | dig1 | dig0;
}
//-----------------------------------------------------------------------
......@@ -379,4 +463,3 @@ int readCounter(void) {
}; //--------------------------------------------------------------------
......@@ -5,8 +5,7 @@
.set noat # do not use register $1 as $at
.align 2
.set M_StatusIEn,0x0000ff13 # STATUS.intEn=1, user mode, EXL=1
# 0xff13 = -237
.set M_StatusIEn,0x0000ff11 # STATUS.intEn=1, user mode, EXL=0
#================================================================
# interrupt handler for external counter attached to IP5=HW3
......@@ -58,9 +57,6 @@ extCounter:
# lw $a1, 1*4($k1)
#----------------------------------
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
eret # Return from interrupt
.end extCounter
#----------------------------------------------------------------
......@@ -70,70 +66,93 @@ extCounter:
# interrupt handler for UART attached to IP6=HW4
# for UART's address see vhdl/packageMemory.vhd
#
.global Ud, _uart_buff
.bss
.align 2
.global Ud
.equ RXHD,0
.equ RXTL,4
.equ RX_Q,8
.equ TXHD,24
.equ TXTL,28
.equ TXQ,32
.equ NRX,48
.equ NTX,52
Ud:
rx_hd: .space 4
rx_tl: .space 4
rx_q: .space 16 # reception queue and pointers
tx_hd: .space 4
tx_tl: .space 4
tx_q: .space 16 # transmission queue and pointers
rx_hd: .space 4 # reception queue head index
rx_tl: .space 4 # tail index
rx_q: .space 16 # reception queue
tx_hd: .space 4 # transmission queue head index
tx_tl: .space 4 # tail index
tx_q: .space 16 # transmission queue
nrx: .space 4 # characters in RX_queue
ntx: .space 4 # spaces left in TX_queue
_uart_buff: .space 16*4 # up to 16 registers to be saved here
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=$v0, [3]=$v1,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
.set UART_rx_irq,0x08
.set UART_tx_irq,0x10
.equ UCTRL,0 # UART registers
.equ USTAT,4
.equ UINTER,8
.equ UDATA,12
.text
.set noreorder
.global UARTinterr
.ent UARTinterr
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
UARTinterr:
#----------------------------------------------------------------
# While you are developing the complete handler, uncomment the
# line below
#
# .include "../tests/handlerUART.s"
#
# Your new handler should be self-contained and do the
# return-from-exception. To do that, copy the lines below up
# to, but excluding, ".end UARTinterr", to yours handlerUART.s.
#----------------------------------------------------------------
lui $k0, %hi(_uart_buff) # get buffer's address
ori $k0, $k0, %lo(_uart_buff)
sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0)
sw $a2, 7*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request
nop
lw $k1, USTAT($a0) # Read status
sw $k1, 0*4($k0) # and save UART status to memory
#----------------------------------
# while you are developing the complete handler,
# uncomment the line below and comment out lines up to UARTret
# .include "../tests/handlerUART.s"
#----------------------------------
li $a1, UART_rx_irq # remove interrupt request
sw $a1, UINTER($a0)
andi $a1, $k1, UART_rx_irq # Is this reception?
and $a1, $k1, $a1 # Is this reception?
beq $a1, $zero, UARTret # no, ignore it and return
nop
# handle reception
lw $a1, 4($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 2*4($k0) # and return from interrupt
lw $a1, UDATA($a0) # Read data from device
lui $a2, %hi(Ud) # get address for data & flag
ori $a2, $a2, %lo(Ud)
sw $a1, 0*4($a2) # and return from interrupt
addiu $a1, $zero, 1
sw $a1, 3*4($k0) # Signal new arrival
sw $a1, 1*4($a2) # set flag to signal new arrival
UARTret:
lw $a2, 7*4($k0)
lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0)
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status
eret # Return from interrupt
.end UARTinterr
#----------------------------------------------------------------
......@@ -147,18 +166,69 @@ UARTret:
.global countCompare
.ent countCompare
countCompare:
mfc0 $k1,c0_count # read COMPARE and clear IRQ
mfc0 $k1,c0_count # read COUNT
addiu $k1,$k1,num_cycles # set next interrupt in so many ticks
mtc0 $k1,c0_compare
mtc0 $k1,c0_compare # write to COMPARE to clear IRQ
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
eret # Return from interrupt
.end countCompare
#----------------------------------------------------------------
#================================================================
# startCount enables the COUNT register, returns new CAUSE
# CAUSE.dc <= 0 to enable counting
#----------------------------------------------------------------
.text
.set noreorder
.global startCount
.ent startCount
startCount:
mfc0 $v0, c0_cause
lui $v1, 0xf7ff
ori $v1, $v1, 0xffff
and $v0, $v0, $v1
mtc0 $v0, c0_cause
ehb
jr $ra
nop
.end startCount
#----------------------------------------------------------------
#================================================================
# stopCount disables the COUNT register, returns new CAUSE
# CAUSE.dc <= 1 to disable counting
#----------------------------------------------------------------
.text
.set noreorder
.global stopCount
.ent stopCount
stopCount:
mfc0 $v0, c0_cause
lui $v1, 0x0800
or $v0, $v0, $v1
jr $ra
mtc0 $v0, c0_cause
.end stopCount
#----------------------------------------------------------------
#================================================================
# readCount returns the value of the COUNT register
#----------------------------------------------------------------
.text
.set noreorder
.global readCount
.ent readCount
readCount:
mfc0 $v0, c0_count
jr $ra
nop
.end readCount
#----------------------------------------------------------------
#================================================================
# functions to enable and disable interrupts, both return STATUS
.text
......@@ -169,7 +239,7 @@ enableInterr:
mfc0 $v0, c0_status # Read STATUS register
ori $v0, $v0, 1 # and enable interrupts
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end enableInterr
......@@ -180,7 +250,7 @@ disableInterr:
addiu $v1, $zero, -2 # and disable interrupts
and $v0, $v0, $v1 # -2 = 0xffff.fffe
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end disableInterr
......@@ -189,11 +259,11 @@ disableInterr:
#================================================================
## TLB handlers
## page table entry is { EntryLo0 int0 EntryLo1 int1 }
## page table entry is { EntryLo0, int0, EntryLo1, int1 }
## int{0,1} is
## { fill_31..6, Modified_5, Used_4, Writable_3, eXecutable_2,
## Status_10 },
## Status is 00=unmapped, 01=mapped, 10=secondary_storage
## Status: 00=unmapped, 01=mapped, 10=secondary_storage, 11=panic
#================================================================
......@@ -304,8 +374,6 @@ M_sec_mem: # print message and abort simulation
# (a) fix the fault by (re)loading the mapping into TLB[4];
# (b) check permissions in PT entry and (maybe) kill the process.
#
.global _excp_saves
.global _excp_0180ret
.global handle_TLBL
.global _PT
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2))
......@@ -386,8 +454,6 @@ L_ret: lw $a0, 9*4($k1) # nothing else to do, return
# returns 0 if V_addr purged, 1 if V_addr not in TLB (probe failure)
#
.text
.global TLB_purge
.set noreorder
.ent TLB_purge
TLB_purge:
......@@ -430,18 +496,98 @@ pu_miss: jr $ra
# delays processing by approx 4*$a0 processor cycles
.text
.set noreorder
.global cmips_delay
.global cmips_delay, delay_cycle, delay_us, delay_ms
.ent cmips_delay
delay_cycle:
cmips_delay:
addiu $a0, $a0, -1
beq $a0, $zero, _d_cye
nop
bne $a0, $zero, cmips_delay
_d_cy: addiu $a0, $a0, -1
nop
jr $ra
bne $a0, $zero, _d_cy
nop
_d_cye: jr $ra
nop
.end cmips_delay
#----------------------------------------------------------------
#================================================================
# delays processing by $a0 times 1 microsecond
# loop takes 5 cycles = 100ns @ 50MHz
# 1.000ns / 100 = 10
.text
.set noreorder
.ent delay_us
delay_us:
beq $a0, $zero, _d_use
nop
li $v0, 10
mult $v0, $a0
nop
mflo $a0
sra $a0, $a0, 1
_d_us: addiu $a0, $a0, -1
nop
nop
bne $a0, $zero, _d_us
nop
_d_use: jr $ra
nop
.end delay_us
#----------------------------------------------------------------
#================================================================
# delays processing by $a0 times 1 mili second
# loop takes 5 cycles = 100ns @ 50MHz
# 1.000.000ns / 100 = 10.000
.text
.set noreorder
.ent delay_ms
delay_ms:
beq $a0, $zero, _d_mse
nop
li $v0, 10000
mul $a0, $v0, $a0
nop
_d_ms: addiu $a0, $a0, -1
nop
nop
bne $a0, $zero, _d_ms
nop
_d_mse: jr $ra
nop
.end delay_ms
#----------------------------------------------------------------
##
## read contents of control registers (for debugging)
##
.global print_sp, print_status, print_cause
.ent print_sp
print_sp:
jr $ra
move $v0, $sp
.end print_sp
.ent print_status
print_status:
mfc0 $v0, c0_status
nop
jr $ra
nop
.end print_status
.ent print_cause
print_cause:
mfc0 $v0, c0_cause
nop
jr $ra
nop
.end print_cause
#----------------------------------------------------------------
#================================================================
# print a message from within "the kernel"
......@@ -493,7 +639,7 @@ k_for: lbu $a0, 0($a1)
.equ kmsg_interr,0
.equ kmsg_excep,1
.data
.section .rodata
.align 2
_kmsg_interr: .asciiz "\n\t00 - interrupt\n\n"
_kmsg_excep: .asciiz "\n\t01 - exception\n\n"
......@@ -502,11 +648,19 @@ _kmsg_seg_fault: .asciiz "\n\t03 - segmentation fault\n\n"
_kmsg_sec_mem: .asciiz "\n\t04 - in secondary memory\n\n"
.global _kmsg_list
.data
.section .rodata
.align 2
_kmsg_list:
.word _kmsg_interr,_kmsg_excep, _kmsg_prot_viol, _kmsg_seg_fault
.word _kmsg_sec_mem
##
## need this so the allocation of the PageTable does not break B^(
##
.section .data
.align 2
_end_of_data:
.word 0
#----------------------------------------------------------------
......@@ -51,7 +51,7 @@ _start:
#
# the page table is located at the middle of the RAM
# bottom half is reserved for "RAM memory", top for page table
# bottom half is reserved for "RAM memory", top half is for PTable
#
.set TOP_OF_RAM, (x_DATA_BASE_ADDR + x_DATA_MEM_SZ)
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2))
......@@ -117,7 +117,6 @@ _start:
sw $a1, 0($a0) # write to PT[ _PTV ].entryLo0
sw $a2, 8($a0) # write to PT[ _PTV ].entryLo1
# pin down first five TLB entries: ROM[0], I/O, RAM[0], stack, PgTbl
li $k0, 5
mtc0 $k0, c0_wired
......@@ -132,10 +131,10 @@ _start:
la $sp, (MIDDLE_RAM - 16)
# set STATUS, cop0, hw interrupts IRQ7,IRQ6,IRQ5 enabled, user mode
li $k0, cop0_STATUS_normal
# set STATUS, c0, hw interrupts IRQ7,IRQ6,IRQ5 enabled, user mode
li $k0, c0_status_normal
mtc0 $k0, c0_status
ehb
jal main # on returning from main(), MUST go into exit()
nop # to stop the simulation.
......@@ -170,7 +169,6 @@ _excp_0000:
mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element
ehb
tlbwr # update TLB
mfc0 $zero, c0_cause # clear excCode in Cause
eret
.end _excp_0000
......@@ -204,6 +202,7 @@ _excp_0100:
## area to save up to 16 registers
.bss
.align 2
.global _excp_saves, _excp_0180ret
.comm _excp_saves 16*4
# _excp_saves[0]=CAUSE, [1]=STATUS, [2]=ASID,
# [8]=$ra, [9]=$a0, [10]=$a1, [11]=$a2, [12]=$a3
......@@ -211,7 +210,7 @@ _excp_0100:
.text
.set noreorder
.set noat
.global _excp_saves, _excp_0180ret
.global _excp_0180ret
.global handle_Mod, handle_TLBL, handle_TLBS
.org x_EXCEPTION_0180,0 # exception vector_180
......@@ -225,10 +224,11 @@ _excp_0180:
sw $k0, 0*4($k1)
andi $k0, $k0, 0x3f # keep only the first 16 ExceptionCodes & b"00"
sll $k0, $k0, 1 # displacement in vector is 8 bytes
sll $k0, $k0, 1 # displacement in vector with 8 bytes/element
lui $k1, %hi(excp_tbl)
ori $k1, $k1, %lo(excp_tbl)
add $k1, $k1, $k0
nop
jr $k1
nop
......@@ -253,32 +253,23 @@ excp_tbl: # see Table 8-25, pg 95,96
nop
wait 0x07 # 7 DBE addr error -- abort simulation
nop
j h_syscall # 8
wait 0x08 # j h_syscall # 8 -- abort simulation
nop
j h_breakpoint # 9
wait 0x09 # j h_breakpoint # 9 -- abort simulation
nop
j h_RI # 10 reserved instruction
wait 0x0a # j h_RI # 10 reserved instruction -- abort simulation
nop
j h_CpU # 11 coprocessor unusable
wait 0x0b # j h_CpU # 11 coprocessor unusable -- abort simulation
nop
j h_Ov # 12 overflow
wait 0x0c # j h_Ov # 12 overflow -- abort simulation
nop
wait 0x0d # 13 trap -- abort simulation
nop
wait 0x0e # reserved, should never get here -- abort simulation
nop
wait 0x0f # FP exception, should never get here -- abort simulation
nop
h_TLBS:
h_syscall:
h_breakpoint:
......@@ -290,10 +281,10 @@ _excp_0180ret:
lui $k1, %hi(_excp_saves) # Read previous contents of STATUS
ori $k1, $k1, %lo(_excp_saves)
lw $k0, 1*4($k1)
# mfc0 $k0, c0_status
# and do not modify its contents
ori $k0, $k0, M_StatusIEn # and keeping user/kernel mode
mtc0 $k0, c0_status # -239 = 0xffff.ff11
ori $k0, $k0, M_StatusIEn # and keep user/kernel mode
mtc0 $k0, c0_status # but enable all interrupts
ehb
eret # Return from exception
.end _excp_0180
......@@ -309,7 +300,7 @@ _excp_0180ret:
.extern extCounter # IRQ5 - hwIRQ3, see vhdl/tb_cMIPS.vhd
.set M_CauseIM,0x0000ff00 # keep bits 15..8 -> IM = IP
.set M_StatusIEn,0xff11 # user mode, enable all interrupts
.set M_StatusIEn,0xff11 # user mode, enable all interrupts, EXL=0
.set noreorder
......@@ -317,20 +308,20 @@ _excp_0180ret:
.ent _excp_0200
_excp_0200:
mfc0 $k0, c0_cause
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
mfc0 $k1, c0_status
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
and $k0, $k0, $k1 # and mask with IM bits
srl $k0, $k0, 10 # keep only 3 MS bits of IP (irq7..5)
lui $k1, %hi(handlers_tbl) # plus displacement in j-table of 8 bytes
ori $k1, $k1, %lo(handlers_tbl)
add $k1, $k1, $k0
nop
jr $k1
nop
## the code for each handler must repeat the exception return
## sequence shown below in excp_0200ret.
## the code for each handler must contain an exception return
## such as the sequence shown below, in excp_0200ret.
handlers_tbl:
j dismiss # no request: 000
nop
......@@ -358,10 +349,10 @@ dismiss: # No pending request, must have been noise
_excp_0200ret:
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # except for re-enabling interrupts
mtc0 $k0, c0_status # as it was on interrupt entry
ori $k0, $k0, M_StatusIEn # and re-enable interrupts
mtc0 $k0, c0_status # else keep as it was on int entry
ehb
eret # Return from interrupt
nop
.end _excp_0200
#----------------------------------------------------------------
......@@ -419,8 +410,6 @@ PT_update:
##===============================================================
## Page Table
##
......@@ -431,14 +420,14 @@ PT_update:
## Status: 00=unmapped, 01=mapped, 10=in_secondary_storage, 11=undef
##
.section .PT,"aw",@progbits
.align 4
.global _PT
## ( ( (x_INST_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000011 d,v,g
_PT:
##
## ROM mappings, intLo{01} = U=M=W=0, X=1, S=10 (or 00) = 6 (or 4)
##
.org (_PT + (x_INST_BASE_ADDR >>13)*16)
_PT: .org (_PT + (x_INST_BASE_ADDR >>13)*16)
# PT[0], ROM
PTbase: .word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011
......
# interrupt handlers
.include "cMIPS.s"
.text
.set noreorder # do not reorder instructions
.set noat # do not use register $1 as $at
.align 2
.set M_StatusIEn,0x0000e011 # STATUS.intEn=1, user mode, EXL=0
#================================================================
# interrupt handler for external counter attached to IP5=HW3
# for extCounter address see vhdl/packageMemory.vhd
#
# counter set to interrupt 4 times per second (12,500,000*20ns)
#
.bss
.align 2
.global _counter_val # accumulate number of interrupts
_counter_val: .space 4
_counter_saves: .space 8*4 # area to save up to 8 registers
# _counter_saves[0]=$a0, [1]=$a1, [2]=$a2, [3]=$a3, ...
.set HW_counter_value,(0xc0000000 | 0x00bebc20) # 12,500,000
.text
.set noreorder
.global extCounter
.ent extCounter
extCounter:
lui $k0, %hi(HW_counter_addr)
ori $k0, $k0, %lo(HW_counter_addr)
sw $zero, 0($k0) # Reset counter, remove interrupt request
#----------------------------------
# if you change this handler, then save additional registers
# lui $k1, %hi(_counter_saves)
# ori $k1, $k1, %lo(_counter_saves)
# sw $a0, 0*4($k1)
# sw $a1, 1*4($k1)
#----------------------------------
lui $k1, %hi(HW_counter_value)
ori $k1, $k1, %lo(HW_counter_value)
sw $k1, 0($k0) # Reload counter so it starts again
lui $k0, %hi(_counter_val) # Increment interrupt event counter
ori $k0, $k0, %lo(_counter_val)
lw $k1,0($k0)
nop
addiu $k1,$k1,1
sw $k1,0($k0)
#----------------------------------
# if you changed this handler, then restore those same registers
# lui $k1, %hi(_counter_saves)
# ori $k1, $k1, %lo(_counter_saves)
# lw $a0, 0*4($k1)
# lw $a1, 1*4($k1)
#----------------------------------
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
ehb
eret # Return from interrupt
.end extCounter
#----------------------------------------------------------------
#================================================================
# interrupt handler for UART attached to IP6=HW4
# for UART's address see vhdl/packageMemory.vhd
#
.global Ud, _uart_buff
.bss
.align 2
Ud:
rx_hd: .space 4
rx_tl: .space 4
rx_q: .space 16 # reception queue and pointers
tx_hd: .space 4
tx_tl: .space 4
tx_q: .space 16 # transmission queue and pointers
nrx: .space 4 # characters in RX_queue
ntx: .space 4 # spaces left in TX_queue
_uart_buff: .space 16*4 # up to 16 registers to be saved here
.set UART_rx_irq,0x08
.set UART_tx_irq,0x10
.text
.set noreorder
.global UARTinterr
.ent UARTinterr
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
UARTinterr:
lui $k0, %hi(_uart_buff) # get buffer's address
ori $k0, $k0, %lo(_uart_buff)
sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request
nop
sw $k1, 0*4($k0) # and save UART status to memory
#----------------------------------
# while you are developing the complete handler,
# uncomment the line below and comment out lines up to UARTret
# .include "../tests/handlerUART.s"
#----------------------------------
andi $a1, $k1, UART_rx_irq # Is this reception?
beq $a1, $zero, UARTret # no, ignore it and return
nop
# handle reception
lw $a1, 4($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 2*4($k0) # and return from interrupt
addiu $a1, $zero, 1
sw $a1, 3*4($k0) # Signal new arrival
UARTret:
lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0)
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
eret # Return from interrupt
.end UARTinterr
#----------------------------------------------------------------
#================================================================
# handler for COUNT-COMPARE registers -- IP7=HW5
.text
.set noreorder
.equ num_cycles, 64
.global countCompare
.ent countCompare
countCompare:
mfc0 $k1,c0_count # read COUNT
addiu $k1,$k1,num_cycles # set next interrupt in so many ticks
mtc0 $k1,c0_compare # write to COMPARE to clear IRQ
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
eret # Return from interrupt
.end countCompare
#----------------------------------------------------------------
#================================================================
# startCount enables the COUNT register, returns new CAUSE
# CAUSE.dc <= 0 to enable counting
#----------------------------------------------------------------
.text
.set noreorder
.global startCount
.ent startCount
startCount:
mfc0 $v0, c0_cause
lui $v1, 0xf7ff
ori $v1, $v1, 0xffff
and $v0, $v0, $v1
jr $ra
mtc0 $v0, c0_cause
.end startCount
#----------------------------------------------------------------
#================================================================
# stopCount disables the COUNT register, returns new CAUSE
# CAUSE.dc <= 1 to disable counting
#----------------------------------------------------------------
.text
.set noreorder
.global stopCount
.ent stopCount
stopCount:
mfc0 $v0, c0_cause
lui $v1, 0x0800
or $v0, $v0, $v1
jr $ra
mtc0 $v0, c0_cause
.end stopCount
#----------------------------------------------------------------
#================================================================
# readCount returns the value of the COUNT register
#----------------------------------------------------------------
.text
.set noreorder
.global readCount
.ent readCount
readCount:
mfc0 $v0, c0_count
jr $ra
nop
.end readCount
#----------------------------------------------------------------
#================================================================
# functions to enable and disable interrupts, both return STATUS
.text
.set noreorder
.global enableInterr,disableInterr
.ent enableInterr
enableInterr:
mfc0 $v0, c0_status # Read STATUS register
ori $v0, $v0, 1 # and enable interrupts
mtc0 $v0, c0_status
nop
jr $ra # return updated STATUS
nop
.end enableInterr
.ent disableInterr
disableInterr:
mfc0 $v0, c0_status # Read STATUS register
addiu $v1, $zero, -2 # and disable interrupts
and $v0, $v0, $v1 # -2 = 0xffff.fffe
mtc0 $v0, c0_status
nop
jr $ra # return updated STATUS
nop
.end disableInterr
#----------------------------------------------------------------
#================================================================
## TLB handlers
## page table entry is { EntryLo0, int0, EntryLo1, int1 }
## int{0,1} is
## { fill_31..6, Modified_5, Used_4, Writable_3, eXecutable_2,
## Status_10 },
## Status: 00=unmapped, 01=mapped, 10=secondary_storage, 11=panic
#================================================================
#================================================================
# handle TLB Modified exception -- store to page with bit dirty=0
#
# (a) fix TLB entry, by setting dirty=1 ;
# (b) check permissions in PT entry and (maybe) kill the process
# OR mark PT entry as Used and Modified, then
# update TLB entry.
#
.global _excp_saves
.global _excp_0180ret
.global handle_Mod
.set noreorder
.ent handle_Mod
handle_Mod: # EntryHi points to offending TLB entry
tlbp # what is the offender's index?
lui $k1, %hi(_excp_saves)
ori $k1, $k1, %lo(_excp_saves)
sw $a0, 9*4($k1) # save registers
sw $a1, 10*4($k1)
sw $a2, 11*4($k1)
mfc0 $a0, c0_badvaddr
andi $a0, $a0, 0x1000 # check if even or odd page
beq $a0, $zero, M_even
mfc0 $a0, c0_context
M_odd: addi $a2, $a0, 12 # address for odd entry
mfc0 $k0, c0_entrylo1
ori $k0, $k0, 0x0004 # mark TLB entry as dirty/writable
j M_test
mtc0 $k0, c0_entrylo1
M_even: addi $a2, $a0, 4 # address for even entry
mfc0 $k0, c0_entrylo0
ori $k0, $k0, 0x0004 # mark TLB entry as dirty/writable
mtc0 $k0, c0_entrylo0
M_test: lw $a1, 0($a2) # read PT[badVAddr]
mfc0 $k0, c0_badvaddr # get faulting address
andi $a0, $a1, 0x0001 # check if page is mapped
beq $a0, $zero, M_seg_fault # no, abort simulation
nop
andi $a0, $a1, 0x0008 # check if page is writable
beq $a0, $zero, M_prot_viol # no, abort simulation
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem # yes, abort simulation
nop
mfc0 $a0, c0_epc # check if fault is on an instruction
beq $a0, $k0, M_prot_viol # k0 is badVAddr, if so, abort
nop
ori $a1, $a1, 0x0030 # mark PT entry as modified, used
sw $a1, 0($a2)
tlbwi # write entry with dirty bit=1 back to TLB
lw $a0, 9*4($k1) # restore saved registers and return
lw $a1, 10*4($k1)
j _excp_0180ret
lw $a2, 11*4($k1)
M_seg_fault: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 3 # segmentation fault
nop
nop
nop
wait 0x41
M_prot_viol: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 2 # protection violation
nop
nop
nop
wait 0x42
M_sec_mem: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 4 # secondary memory
nop
nop
nop
wait 0x43
.end handle_Mod
#----------------------------------------------------------------
#================================================================
# handle TLB Load exception: double-fault caused by a TLB miss
# to the Page Table -- mapping pointing to PT is not on TLB
#
# (a) fix the fault by (re)loading the mapping into TLB[4];
# (b) check permissions in PT entry and (maybe) kill the process.
#
.global handle_TLBL
.global _PT
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2))
.ent handle_TLBL
handle_TLBL: # EntryHi points to offending TLB entry
tlbp # probe it to find the offender's index
lui $k1, %hi(_excp_saves)
ori $k1, $k1, %lo(_excp_saves)
sw $a0, 9*4($k1)
sw $a1, 10*4($k1)
sw $a2, 11*4($k1)
mfc0 $a0, c0_badvaddr
la $a1, (_PT + (x_INST_BASE_ADDR >>13)*16)
slt $a2, $a0, $a1 # a2 <- (badVAddr <= PageTable)
bne $a2, $zero, L_chks # fault is not to PageTable
nop
# this is same code as in start.s
# get physical page number for two pages at the bottom of PageTable
la $a0, ( MIDDLE_RAM >>13 )<<13
mtc0 $a0, c0_entryhi # tag for bottom double-page
la $a0, ( (MIDDLE_RAM + 0*4096) >>12 )<<6
ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, c0_entrylo0 # bottom page (even)
la $a0, ( (MIDDLE_RAM + 1*4096) >>12 )<<6
ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, c0_entrylo1 # bottom page + 1 (odd)
# and write it to TLB[4]
li $k0, 4
mtc0 $k0, c0_index
tlbwi
j L_ret # all work done, return
nop
L_chks: andi $a0, $a0, 0x1000 # check if even or odd page
beq $a0, $zero, L_even
mfc0 $a0, c0_context
L_odd: j L_test
addi $a2, $a0, 12 # address for odd intLo1 entry
L_even: addi $a2, $a0, 4 # address for even intLo0 entry
L_test: lw $a1, 0($a2) # get intLo{0,1}
mfc0 $k0, c0_badvaddr # get faulting address for printing
andi $a0, $a1, 0x0001 # check if page is mapped
beq $a0, $zero, M_seg_fault # no, abort simulation
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem # yes, abort simulation
nop
ori $a1, $a1, 0x0010 # mark PT entry as used
sw $a1, 0($a2)
# if this were handler_TLBS, now is the time to also mark the
# PT entry as Modified
L_ret: lw $a0, 9*4($k1) # nothing else to do, return
lw $a1, 10*4($k1)
j _excp_0180ret
lw $a2, 11*4($k1)
.end handle_TLBL
#----------------------------------------------------------------
#================================================================
# purge an entry from the TLB
# int TLB_purge(void *V_addr)
# returns 0 if V_addr purged, 1 if V_addr not in TLB (probe failure)
#
.text
.set noreorder
.ent TLB_purge
TLB_purge:
srl $a0, $a0, 13 # clear out in-page address bits
sll $a0, $a0, 13 #
mtc0 $a0, c0_entryhi
nop
tlbp # probe the TLB
nop
mfc0 $a0, c0_index # check for hit
srl $a0, $a0, 31 # keeo only MSbit
bne $a0, $zero, pu_miss # address not in TLB
move $v0, $a0 # V_addr not in TLB
tlbr # read the entry
li $a0, -8192 # -8192 = 0xffff.e000
mtc0 $a0, c0_entryhi # and write an un-mapped address to tag
addi $v0, $zero, -3 # -3 = 0xffff.fffd to clear valid bit
mfc0 $a0, c0_entrylo0 # invalidate the mappings
and $a0, $v0, $a0
mtc0 $a0, c0_entrylo0
mfc0 $a0, c0_entrylo1
and $a0, $v0, $a0
mtc0 $a0, c0_entrylo1
move $v0, $zero # V_addr was purged from TLB
tlbwi # write invalid mappings to TLB
ehb
pu_miss: jr $ra
nop
.end TLB_purge
##---------------------------------------------------------------
#================================================================
# delays processing by approx 4*$a0 processor cycles
.text
.set noreorder
.global cmips_delay, delay_cycle, delay_us, delay_ms
.ent cmips_delay
delay_cycle:
cmips_delay:
addiu $a0, $a0, -1
nop
bne $a0, $zero, cmips_delay
nop
jr $ra
nop
.end cmips_delay
#----------------------------------------------------------------
#================================================================
# delays processing by $a0 times 1 microsecond
# loop takes 5 cycles = 100ns @ 50MHz
# 1.000ns / 100 = 10
.text
.set noreorder
.ent delay_us
delay_us:
li $v0, 10
mult $v0, $a0
nop
mflo $a0
sra $a0, $a0, 1
_d_us: addiu $a0, $a0, -1
nop
nop
bne $a0, $zero, _d_us
nop
jr $ra
nop
.end delay_us
#----------------------------------------------------------------
#================================================================
# delays processing by $a0 times 1 milisecond
# loop takes 5 cycles = 100ns @ 50MHz
# 1.000.000ns / 100 = 10.000
.text
.set noreorder
.ent delay_ms
delay_ms:
li $v0, 10000
mul $a0, $v0, $a0
nop
_d_ms: addiu $a0, $a0, -1
nop
nop
bne $a0, $zero, _d_ms
nop
jr $ra
nop
.end delay_ms
#----------------------------------------------------------------
#================================================================
# print a message from within "the kernel"
# void cmips_kmsg( $k1 )
# this function preserves registers other than k0,k1
#
.bss
.align 2
_kmsg_saves: .space 4*4 # area to save 4 registers
# _kmsg_saves[0]=$a0, [1]=$a1, [2]=$a2, [3]=$a3
.text
.align 2
.set noreorder
.set noat
.equ stdout,(x_IO_BASE_ADDR + 1*x_IO_ADDR_RANGE);
.global cmips_kmsg
.ent cmips_kmsg
cmips_kmsg:
lui $k0, %hi(_kmsg_saves)
ori $k0, $k0, %lo(_kmsg_saves)
sw $a0, 0*4($k0)
sw $a1, 1*4($k0)
sw $a2, 2*4($k0)
lui $a1, %hi(_kmsg_list)
ori $a1, $a1, %lo(_kmsg_list)
sll $k1, $k1, 2 # adjust index onto table
addu $a1, $a1, $k1
lw $a1, 0($a1) # de-reference pointer
lui $a2, %hi(stdout)
ori $a2, $a2, %lo(stdout)
k_for: lbu $a0, 0($a1)
addiu $a1, $a1, 1
bne $a0, $zero, k_for
sb $a0, 0($a2) # send it to simulator's stdout
lw $a0, 0*4($k0)
lw $a1, 1*4($k0)
jr $ra
lw $a2, 2*4($k0)
.end cmips_kmsg
.equ kmsg_interr,0
.equ kmsg_excep,1
.section .rodata
.align 2
_kmsg_interr: .asciiz "\n\t00 - interrupt\n\n"
_kmsg_excep: .asciiz "\n\t01 - exception\n\n"
_kmsg_prot_viol: .asciiz "\n\t02 - protection violation\n\n"
_kmsg_seg_fault: .asciiz "\n\t03 - segmentation fault\n\n"
_kmsg_sec_mem: .asciiz "\n\t04 - in secondary memory\n\n"
.global _kmsg_list
.section .rodata
.align 2
_kmsg_list:
.word _kmsg_interr,_kmsg_excep, _kmsg_prot_viol, _kmsg_seg_fault
.word _kmsg_sec_mem
##
## need this so the allocation of the PageTable does not break B^(
##
.section .data
.align 2
_end_of_data:
.word 0
#----------------------------------------------------------------
......@@ -10,7 +10,6 @@
.align 2
.extern main
.global _start, _exit, exit
.global _excp_0000, _excp_0100, _excp_0180, _excp_0200, _excp_BFC0
.set MMU_WIRED, 2 ### do not change mapping for base of ROM, I/O
......@@ -26,11 +25,11 @@ _start: nop
# needed so systems without a page table will not break
# read TLB[4] and write it to TLB[2]
li $k0, 4
mtc0 $k0, cop0_Index
mtc0 $k0, c0_index
ehb
tlbr
li $k1, 2
mtc0 $k1, cop0_Index
mtc0 $k1, c0_index
ehb
tlbwi
......@@ -38,37 +37,36 @@ _start: nop
# then set another mapping onto TLB[4], to avoid replicated entries
li $a0, ( (x_DATA_BASE_ADDR + 8*4096) >>12 )
sll $a2, $a0, 12 # tag for RAM[8,9] double-page
mtc0 $a2, cop0_EntryHi
mtc0 $a2, c0_entryhi
li $a0, ((x_DATA_BASE_ADDR + 8*4096) >>12 )
sll $a1, $a0, 6 # RAM[8] (even)
ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, cop0_EntryLo0
mtc0 $a1, c0_entrylo0
li $a0, ( (x_DATA_BASE_ADDR + 9*4096) >>12 )
sll $a1, $a0, 6 # RAM[9] (odd)
ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, cop0_EntryLo1
mtc0 $a1, c0_entrylo1
# and write it to TLB[4]
li $k0, 4
mtc0 $k0, cop0_Index
mtc0 $k0, c0_index
tlbwi
# pin down first four TLB entries: ROM[0], RAM[0], stack and I/O
li $k0, 4
mtc0 $k0, cop0_Wired
mtc0 $k0, c0_wired
# initialize SP at top of RAM: ramTop - 16
li $sp, ((x_DATA_BASE_ADDR+x_DATA_MEM_SZ) - 16)
# initialize SP at top of RAM: RAM[1] - 16
li $sp, ((x_DATA_BASE_ADDR + (2*4096)) - 16)
# set STATUS, cop0, hw interrupt IRQ7,IRQ6,IRQ5 enabled, user mode
li $k0, 0x1000e011
mtc0 $k0, cop0_STATUS
mtc0 $k0, c0_status
j main
nop
......@@ -78,18 +76,67 @@ _start: nop
##
exit:
_exit: la $k0, HW_dsp7seg_addr # 7 segment display
li $k1, 0x0311 # display .1.1
li $k1, 0x1300 # display .0.0, RED led
sw $k1, 0($k0) # write to 7 segment display
li $k0, 0x10000010
mtc0 $k0, c0_status # disable interrupts
nop
j exit # wait forever
hexit: j hexit # wait forever
nop
.end _start
##
## read contents of control registers (for debugging)
##
.global print_sp, print_status, print_cause
.ent print_sp
print_sp:
jr $ra
move $v0, $sp
.end print_sp
.ent print_status
print_status:
mfc0 $v0, c0_status
nop
jr $ra
nop
.end print_status
.ent print_cause
print_cause:
mfc0 $v0, c0_cause
nop
jr $ra
nop
.end print_cause
##
##================================================================
## area to save up to 16 registers
.data
.align 2
.global _excp_saves
.comm _excp_saves 16*4
##===============================================================
## Page Table (empty for synthesis, address must be declared)
##
## .section .PT,"aw",@progbits, .org (x_DATA_BASE_ADDR+2*4096)
## .align 4
.global _PT
.comm _PT 4
##
##================================================================
## exception vector_0000 TLBrefill
##
.text
.org x_EXCEPTION_0000,0
_excp_0000:
la $k0, HW_dsp7seg_addr # 7 segment display
......@@ -120,23 +167,95 @@ h0100: j h0100 # wait forever
.org x_EXCEPTION_0180,0
_excp_0180:
la $k0, HW_dsp7seg_addr # 7 segment display
li $k1, 0x0377 # display .7.7
mfc0 $k1, c0_cause
andi $k1, $k1, 0x07f # display .7.7
sw $k1, 0($k0) # write to 7 segment display
h0180: j h0180 # wait forever
nop
##
##================================================================
## exception return address (should never get here)
##
.global _excp_0180ret
_excp_0180ret:
la $k0, HW_dsp7seg_addr # 7 segment display
li $k1, 0x0344 # display .4.4
sw $k1, 0($k0) # write to 7 segment display
heret: j heret # wait forever
nop
##
##===============================================================
## interrupt handlers at exception vector 0200
##
.org x_EXCEPTION_0200,0
# declare all handlers here, these must be in file syn_handlers.s
.extern countCompare # IRQ7 = hwIRQ5, Cop0 counter
.extern UARTinterr # IRQ6 - hwIRQ4, see vhdl/tb_cMIPS.vhd
.extern extCounter # IRQ5 - hwIRQ3, see vhdl/tb_cMIPS.vhd
.set M_CauseIM,0x0000e000 # keep bits 15..8 -> IM = IP
.set M_StatusIEn,0xe011 # user mode, enable all interrupts, EXL=0
.set noreorder
.org x_EXCEPTION_0200,0 # exception vector_200, interrupt handlers
.ent _excp_0200
_excp_0200:
la $k0, HW_dsp7seg_addr # 7 segment display
li $k1, 0x0366 # display .6.6
sw $k1, 0($k0) # write to 7 segment display
h0200: j h0200 # wait forever
mfc0 $k0, c0_cause
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
mfc0 $k1, c0_status
and $k0, $k0, $k1 # and mask with IM bits
srl $k0, $k0, 10 # keep only 3 MS bits of IP (irq7..5)
lui $k1, %hi(handlers_tbl) # plus displacement in j-table of 8 bytes
ori $k1, $k1, %lo(handlers_tbl)
add $k1, $k1, $k0
nop
jr $k1
nop
## the code for each handler must repeat the exception return
## sequence shown below in excp_0200ret.
handlers_tbl:
j dismiss # no request: 000
nop
j extCounter # lowest priority, IRQ5: 001
nop
j UARTinterr # mid priority, IRQ6: 01x
nop
j UARTinterr
nop
j countCompare # highest priority, IRQ7: 1xx
nop
j countCompare
nop
j countCompare
nop
j countCompare
nop
dismiss: # No pending request, must have been noise
# do nothing and return
_excp_0200ret:
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # and re-enable interrupts
mtc0 $k0, c0_status # else keep as it was on int entry
eret # Return from interrupt
nop
.end _excp_0200
#-----------------------------------------------------------------
##
......@@ -153,6 +272,7 @@ hBFC0: j hBFC0 # wait forever
##================================================================
##
##===============================================================
## main(), normal code starts below -- do not edit next line
......
[*]
[*] GTKWave Analyzer v3.3.37 (w)1999-2012 BSI
[*] Wed Aug 17 13:40:37 2016
[*]
[dumpfile] "/home/roberto/cMIPS/v_cMIPS.vcd"
[dumpfile_mtime] "Wed Aug 17 13:34:05 2016"
[dumpfile_size] 6865336
[savefile] "/home/roberto/cMIPS/pipe_MAX.sav"
[timestart] 183000000
[size] 1201 876
[pos] 445 -1
*-26.000000 262800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] u_core.
[treeopen] u_core.u_alu.
[treeopen] u_fpu.
[treeopen] u_lcd_display.
[sst_width] 210
[signals_width] 214
[sst_expanded] 1
[sst_vpaned_height] 278
@28
clk
@200
-== FETCH ======
@22
u_core.pc[31:0]
@28
u_core.pcsel[1:0]
@22
u_core.pcincd[31:0]
u_core.br_target[31:0]
u_core.j_target[31:0]
@28
u_core.br_stall
u_core.jr_stall
u_core.lw_stall
u_core.sw_stall
@200
-== DECOD =====
@22
u_core.rf_instruction[31:0]
u_core.opcode[5:0]
@24
u_core.a_rs[4:0]
u_core.a_rt[4:0]
u_core.a_rd[4:0]
u_core.a_c[4:0]
@200
-== EXEC =======
@24
u_core.u_alu.operation[31:0]
u_core.ex_a_c[4:0]
@22
u_core.alu_inp_a[31:0]
u_core.alu_inp_b[31:0]
u_core.result[31:0]
@200
-== MEM =======
@28
cpu_d_aval
wr
u_core.b_sel[3:0]
@22
d_addr[31:0]
u_core.data_inp[31:0]
u_core.data_out[31:0]
@200
-== WR BACK =====
@24
u_core.wb_muxc[2:0]
@22
u_core.wb_pc_p8[31:0]
u_core.wb_a[31:0]
u_core.wb_mem_data[31:0]
u_core.wb_cop0_val[31:0]
u_core.wb_result[31:0]
u_core.wb_hi[31:0]
u_core.wb_lo[31:0]
@29
u_core.wb_wreg
@24
u_core.wb_a_c[4:0]
@22
u_core.wb_c[31:0]
[pattern_trace] 1
[pattern_trace] 0
[*]
[*] GTKWave Analyzer v3.3.37 (w)1999-2012 BSI
[*] Wed Aug 17 13:32:42 2016
[*]
[dumpfile] "/home/roberto/cMIPS/v_cMIPS.vcd"
[dumpfile_mtime] "Wed Aug 17 13:18:43 2016"
[dumpfile_size] 6865336
[savefile] "/home/roberto/cMIPS/pipe_Med.sav"
[timestart] 183000000
[size] 1201 960
[pos] -1 -1
*-26.000000 262800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] u_core.
[treeopen] u_core.u_alu.
[treeopen] u_fpu.
[treeopen] u_lcd_display.
[sst_width] 210
[signals_width] 214
[sst_expanded] 1
[sst_vpaned_height] 309
@28
clk
@200
-== FETCH ======
@22
u_core.pc[31:0]
u_core.instr_fetched[31:0]
@28
u_core.pcsel[1:0]
@22
u_core.pcincd[31:0]
u_core.br_target[31:0]
u_core.j_target[31:0]
@200
-== DECOD ======
@22
u_core.rf_instruction[31:0]
u_core.opcode[5:0]
@24
u_core.a_rs[4:0]
u_core.a_rt[4:0]
u_core.a_rd[4:0]
u_core.a_c[4:0]
@200
-== EXEC =======
@24
u_core.u_alu.operation[31:0]
@200
-forward into A
@22
u_core.mm_result[31:0]
u_core.wb_c[31:0]
u_core.ex_a[31:0]
u_core.alu_inp_a[31:0]
@200
-forward into B
@22
u_core.mm_result[31:0]
u_core.wb_c[31:0]
u_core.ex_b[31:0]
u_core.ex_displ32[31:0]
u_core.alu_inp_b[31:0]
u_core.result[31:0]
@200
-== MEM =======
@28
cpu_d_aval
wr
u_core.b_sel[3:0]
@22
d_addr[31:0]
u_core.data_inp[31:0]
@200
-forward to mem
@22
u_core.mm_b[31:0]
u_core.wb_c[31:0]
u_core.data_out[31:0]
@200
-== WR BACK =====
@24
u_core.wb_muxc[2:0]
@22
u_core.wb_rd_data[31:0]
u_core.wb_result[31:0]
u_core.wb_hi[31:0]
u_core.wb_lo[31:0]
u_core.wb_c[31:0]
@24
u_core.wb_a_c[4:0]
@28
u_core.wb_wreg
[pattern_trace] 1
[pattern_trace] 0
[*]
[*] GTKWave Analyzer v3.3.37 (w)1999-2012 BSI
[*] Wed Aug 17 13:11:28 2016
[*]
[dumpfile] "/home/roberto/cMIPS/v_cMIPS.vcd"
[dumpfile_mtime] "Wed Aug 17 13:06:45 2016"
[dumpfile_size] 6865336
[savefile] "/home/roberto/cMIPS/pipe_min.sav"
[timestart] 1038600000
[size] 1201 673
[pos] -1 -1
*-26.000000 262800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] u_core.
[treeopen] u_core.u_alu.
[treeopen] u_fpu.
[treeopen] u_lcd_display.
[sst_width] 210
[signals_width] 214
[sst_expanded] 1
[sst_vpaned_height] 197
@28
clk
@200
- fetch
@22
u_core.pc[31:0]
@200
-
- decode, reg fetch
@22
u_core.rf_instruction[31:0]
u_core.opcode[5:0]
@24
u_core.a_rs[4:0]
u_core.a_rt[4:0]
u_core.a_rd[4:0]
u_core.a_c[4:0]
@200
-
- exec
@24
u_core.u_alu.operation[31:0]
@22
u_core.alu_inp_a[31:0]
u_core.alu_inp_b[31:0]
u_core.result[31:0]
@200
-
- memory
@28
cpu_d_aval
u_core.b_sel[3:0]
wr
@22
d_addr[31:0]
u_core.data_inp[31:0]
u_core.data_out[31:0]
@200
-
- write-back
@28
u_core.wb_wreg
@25
u_core.wb_a_c[4:0]
@22
u_core.wb_c[31:0]
[pattern_trace] 1
[pattern_trace] 0
......@@ -10,7 +10,7 @@ _start: nop
## set STATUS, cop0, no interrupts enabled, user mode
li $k0, 0x10000010
mtc0 $k0, cop0_STATUS
mtc0 $k0, c0_status
j main
nop
......@@ -32,7 +32,7 @@ _exit: nop # flush pipeline
.org x_EXCEPTION_0000,0
_excp_0000:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......@@ -42,7 +42,7 @@ _excp_0000:
.org x_EXCEPTION_0100,0
_excp_0100:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......@@ -80,7 +80,7 @@ excp_180:
.org x_EXCEPTION_0200,0
_excp_0200:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......
......@@ -9,7 +9,7 @@ _start: nop
li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8
## set STATUS, cop0, no interrupts enabled, user mode
li $k0, cop0_STATUS_normal
li $k0, c0_status_normal
mtc0 $k0, c0_status
j main
......@@ -33,7 +33,7 @@ _exit: nop # flush pipeline
.org x_EXCEPTION_0000,0
_excp_0000:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......@@ -43,7 +43,7 @@ _excp_0000:
.org x_EXCEPTION_0100,0
_excp_0100:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......@@ -97,7 +97,7 @@ _excp_0200:
.org x_EXCEPTION_BFC0,0
_excp_BFC0:
la $k0, x_IO_BASE_ADDR
mfc0 $k1, cop0_CAUSE
mfc0 $k1, c0_cause
sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop
nop
......