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
  • master
1 result

Target

Select target project
  • roberto/cmips
  • vsbc14/killer
  • laps15/cmips
3 results
Select Git revision
  • Strozzi
  • jedian
  • jedian1806
  • master
4 results
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
cMIPS is a synthesizable VHDL model for the 5-stage pipeline, MIPS32r2 core. cMIPS is a synthesizable VHDL model for the 5-stage pipeline, MIPS32r2 core.
......
...@@ -54,6 +54,7 @@ exit 1 ...@@ -54,6 +54,7 @@ exit 1
if [ $# = 0 ] ; then usage ; exit 1 ; fi if [ $# = 0 ] ; then usage ; exit 1 ; fi
miffile=false miffile=false
pacMem_changed=false
verbose=false verbose=false
names=false names=false
unset mem_map unset mem_map
...@@ -86,7 +87,9 @@ while true ; do ...@@ -86,7 +87,9 @@ while true ; do
;; ;;
-n) names=true -n) names=true
;; ;;
-mif|-m) miffile=true -mif | -syn ) miffile=true
;;
-new ) pacMem_changed=true
;; ;;
-x) set -x -x) set -x
;; ;;
...@@ -101,9 +104,26 @@ done ...@@ -101,9 +104,26 @@ done
if [ -z $inp ] ; then usage ; exit 1 ; fi 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 "${bin}"/edMemory.sh -v || errorED || exit 1
fi fi
......
#!/bin/bash #!/bin/bash
## ------------------------------------------------------------------------ ## ------------------------------------------------------------------------
## cMIPS, Roberto Hexsel, 30set2013, rev 08jan2015 ## cMIPS, Roberto Hexsel, 30set2013, rev 08jan2015, 04apr2017
## ------------------------------------------------------------------------ ## ------------------------------------------------------------------------
# set -x # set -x
...@@ -19,19 +19,57 @@ EOF ...@@ -19,19 +19,57 @@ EOF
exit 1 exit 1
} }
errorCOMPILING() errorCOMPILING()
{ {
cat <<EOF cat <<EOF
$0: error in compiling VHDL sources $0: error in compiling VHDL sources
remove cMIPS/vhdl/.last_import and cMIPS/vhdl/work-obj93.cf
and re-compile
EOF EOF
exit 1 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 if [ ! -v tree ] ; then
# you must set the location of the cMIPS root directory in the variable tree # you must set the location of the cMIPS root directory in the variable tree
...@@ -44,13 +82,20 @@ fi ...@@ -44,13 +82,20 @@ fi
bin="${tree}"/bin bin="${tree}"/bin
include="${tree}"/include include="${tree}"/include
srcVHDL="${tree}"/vhdl srcVHDL="${tree}"/vhdl
# obj="${tree}"/obj
c_ld="${include}"/cMIPS.ld c_ld="${include}"/cMIPS.ld
c_s="${include}"/cMIPS.s c_s="${include}"/cMIPS.s
c_h="${include}"/cMIPS.h 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\ if [ $pkg_vhd -nt $c_ld -o\
$pkg_vhd -nt $c_s -o\ $pkg_vhd -nt $c_s -o\
...@@ -59,6 +104,9 @@ if [ $pkg_vhd -nt $c_ld -o\ ...@@ -59,6 +104,9 @@ if [ $pkg_vhd -nt $c_ld -o\
"${bin}"/edMemory.sh -v || errorED || exit 1 "${bin}"/edMemory.sh -v || errorED || exit 1
fi fi
if [ $pacMem_changed ] ; then
"${bin}"/edMemory.sh -v || errorED || exit 1
fi
cd "${srcVHDL}" cd "${srcVHDL}"
...@@ -66,7 +114,7 @@ simulator=tb_cmips ...@@ -66,7 +114,7 @@ simulator=tb_cmips
pkg="packageWires.vhd packageMemory.vhd packageExcp.vhd" 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 # build simulator
#ghdl --clean #ghdl --clean
...@@ -74,16 +122,14 @@ src="aux.vhd altera.vhd macnica.vhd cache.vhd instrcache.vhd sdram.vhd ram.vhd r ...@@ -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}"/packageMemory.vhd || exit 1
#ghdl -a --ieee=standard "${srcVHDL}"/packageExcp.vhd || exit 1 #ghdl -a --ieee=standard "${srcVHDL}"/packageExcp.vhd || exit 1
#for F in ${src} ; do #for F in ${src} ; do
# if [ ! -s ${F}.o -o "${srcVHDL}"/${F}.vhd -nt ${F}.o ] ; then # if [ ! -s ${F%.vhd}.o -o "${srcVHDL}"/${F} -nt ${F%.vhd}.o ] ; then
# ghdl -a --ieee=standard "${srcVHDL}"/${F}.vhd || exit 1 # ghdl -a --ieee=standard "${srcVHDL}"/${F} || exit 1
# fi # fi
#done #done
# #
#ghdl -c "${srcVHDL}"/*.vhd -e ${simulator} || exit 1 #ghdl -c "${srcVHDL}"/*.vhd -e ${simulator} || exit 1
# NOTE: when you add a new sourcefile to this project, you must include it # 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 # 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. # a good idea to remove ./.last_import to force a full rebuild.
......
...@@ -37,6 +37,7 @@ OPTIONS: ...@@ -37,6 +37,7 @@ OPTIONS:
-W Pass -Wall on to GCC -W Pass -Wall on to GCC
-mif Generate output file ROM.mif for Altera's FPGAs -mif Generate output file ROM.mif for Altera's FPGAs
-syn Compile for synthesis, else for simulation -syn Compile for synthesis, else for simulation
-new Automagically update all addresses (packageMemory.vhd changed)
EOF EOF
} }
...@@ -57,6 +58,7 @@ if [ $# = 0 ] ; then usage ; exit 1 ; fi ...@@ -57,6 +58,7 @@ if [ $# = 0 ] ; then usage ; exit 1 ; fi
miffile=false miffile=false
synth=false synth=false
pacMem_changed=false
verbose=false verbose=false
names=true names=true
unset memory_map unset memory_map
...@@ -84,9 +86,10 @@ while true ; do ...@@ -84,9 +86,10 @@ while true ; do
;; ;;
-n) names=false -n) names=false
;; ;;
-mif) miffile=true -mif | -syn ) synth=true
miffile=true
;; ;;
-syn) synth=true -new ) pacMem_changed=true
;; ;;
-x) set -x -x) set -x
;; ;;
...@@ -111,11 +114,26 @@ c_h="${include}"/cMIPS.h ...@@ -111,11 +114,26 @@ c_h="${include}"/cMIPS.h
c_s="${include}"/cMIPS.s c_s="${include}"/cMIPS.s
c_io="${include}"/cMIPSio c_io="${include}"/cMIPSio
# c_start="${include}"/start ## see below for synthesis version # 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 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_ld -o\
$pkg_vhd -nt $c_s ] ; then $pkg_vhd -nt $c_s ] ; then
"${bin}"/edMemory.sh -v || errorED || exit 1 "${bin}"/edMemory.sh -v || errorED || exit 1
...@@ -130,13 +148,6 @@ dat=data.bin ...@@ -130,13 +148,6 @@ dat=data.bin
if [ $verbose = true ]; then memory_map="-Map ${inp}.map" ; fi 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}" \ (mips-gcc -O${level} $warn -DcMIPS -mno-gpopt -I"${include}" \
-S ${src} $S -o ${asm} || exit 1) && \ -S ${src} $S -o ${asm} || exit 1) && \
...@@ -149,8 +160,8 @@ mips-ld -EL -e _start ${memory_map} -I "${include}" --script $c_ld \ ...@@ -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 -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 .text -O binary $elf $bin && \
mips-objcopy -S -j .data -j .rodata -j .rodata1 -j .data1 \ mips-objcopy -S -j .data -j .data1 -j .lit8 -j .lit4 -j .sdata \
-j .sdata -j .lit8 -j .lit4 -j .sbss -j .bss -j .PT \ -j .sbss -j .bss -j .rodata1 -j .rodata -j .PT \
-O binary $elf $dat || exit 1 -O binary $elf $dat || exit 1
if [ $names = true ] ; then if [ $names = true ] ; then
...@@ -162,8 +173,8 @@ fi ...@@ -162,8 +173,8 @@ fi
if [ $? == 0 -a $verbose = true ]; then if [ $? == 0 -a $verbose = true ]; then
mips-objdump -z -D -EL $reg_names --show-raw-insn \ mips-objdump -z -D -EL $reg_names --show-raw-insn \
--section .text --section .data \ --section .text --section .data \
--section .rodata --section .sdata --section .sbss \ --section .sdata --section .sbss \
--section .bss --section .PT $elf --section .bss --section .rodata --section .PT $elf
fi fi
if [ $? == 0 -a $miffile = true ] ; then if [ $? == 0 -a $miffile = true ] ; then
......
...@@ -86,6 +86,15 @@ then ...@@ -86,6 +86,15 @@ then
fi fi
done 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 # set up address for base of Page Table
VAR=x_DATA_MEM_SZ VAR=x_DATA_MEM_SZ
NEW=$(egrep -h ${VAR} "${dfn}" | sed -n -e '/reg32/s/.*x"\(.*\)".*/\1/p') NEW=$(egrep -h ${VAR} "${dfn}" | sed -n -e '/reg32/s/.*x"\(.*\)".*/\1/p')
......
...@@ -26,6 +26,7 @@ unset WAVE ...@@ -26,6 +26,7 @@ unset WAVE
length=1 length=1
unit=m unit=m
gtkwconf=pipe gtkwconf=pipe
synth=
touch input.data input.txt serial.inp touch input.data input.txt serial.inp
...@@ -42,6 +43,7 @@ OPTIONS: ...@@ -42,6 +43,7 @@ OPTIONS:
-n send simulator output do /dev/null, else to v_cMIPS.vcd -n send simulator output do /dev/null, else to v_cMIPS.vcd
-w invoke GTKWAVE -- stdin will not read input from keyboard -w invoke GTKWAVE -- stdin will not read input from keyboard
-v F gtkwave configuration file (e.g. pipe.sav, default v.sav) -v F gtkwave configuration file (e.g. pipe.sav, default v.sav)
-syn run simulation with synthesis RAM/ROM addresses
EOF EOF
} }
...@@ -60,6 +62,8 @@ while true ; do ...@@ -60,6 +62,8 @@ while true ; do
;; ;;
-w) WAVE=true -w) WAVE=true
;; ;;
-syn | -mif ) synth="-syn"
;;
-v) gtkwconf=$2 -v) gtkwconf=$2
shift shift
;; ;;
...@@ -77,15 +81,15 @@ gfile=${gtkwconf%%.sav} ...@@ -77,15 +81,15 @@ gfile=${gtkwconf%%.sav}
sav="${tree}"/${gfile}.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}" options="--ieee-asserts=disable --stop-time=${length}${unit}s --vcd=${visual}"
if [ -v $WAVE ] ; then if [ -v $WAVE ] ; then
## simulator must be exec'd so it can read from the standard input ## simulator must be exec'd so it can read from the standard input
exec "${simulator}" $options exec "${simulator}" $options --vcd-nodate
else else
...@@ -95,5 +99,5 @@ fi ...@@ -95,5 +99,5 @@ fi
# --wave=${visual%.vcd}.ghw ## --wave=${visual%.vcd}.ghw
### ###
### this file in NOT a shell script, ### 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: # 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 http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.gz
wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.2.tar.gz wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
wget ftp://ftp.gmplib.org/pub/gmp/gmp-6.0.0.tar.bz2 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 # and, according to instructions in
# http://gcc.gnu.org/install/prerequisites.html # 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); # 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... # OTOH, if you are very lucky, the libraries installed by aptitude will do...
# fetch all the auxiliary programs -- this assumes a Debian installation # fetch all the auxiliary programs -- this assumes a Debian installation
aptitude install make flex bison libgmp-dev libmpfr-dev libmpc-dev g++ aptitude install make flex bison libgmp-dev libmpfr-dev libmpc-dev g++
# clean up any aliases/function replacements for /bin/ls
unset ls unset ls
# make sure the installed files are read-exec by all # make sure the installed files are read-exec by all
...@@ -33,12 +39,17 @@ COMPILER=gcc-5.1.0 ...@@ -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/binutils/${BINUTILS}.tar.bz2
wget -c http://ftp.gnu.org/gnu/gcc/${COMPILER}/${COMPILER}.tar.gz 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 # set the installation pathname as PREFIX so that {bin,lib,man} are put there
# make sure you have write permission to /opt/cross, # make sure you have write permission to /opt/cross,
# else perform the "make install" steps as root (with umask 022) # else perform the "make install" steps as root (with umask 022)
export PREFIX=/opt/cross/ export PREFIX=/opt/cross/
export TARGET=mips export TARGET=mips
## build and install binutils (takes a few minutes)
tar -xvjf ${BINUTILS}.tar.bz2 tar -xvjf ${BINUTILS}.tar.bz2
cd ${BINUTILS} cd ${BINUTILS}
./configure --target=$TARGET --prefix=$PREFIX --disable-nls ./configure --target=$TARGET --prefix=$PREFIX --disable-nls
...@@ -49,10 +60,20 @@ make ...@@ -49,10 +60,20 @@ make
make install make install
cd .. cd ..
## build and install GCC (takes rather more than a few minutes)
tar -xvzf ${COMPILER}.tar.gz tar -xvzf ${COMPILER}.tar.gz
cd ${COMPILER} 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 export PATH=$PATH:$PREFIX/bin
./configure --target=$TARGET --prefix=$PREFIX --disable-nls \ ./configure --target=$TARGET --prefix=$PREFIX --disable-nls \
...@@ -66,6 +87,7 @@ cd .. ...@@ -66,6 +87,7 @@ cd ..
# once GCC and Binutils are compiled and installed, all that is needed is # 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 # 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 PATH=${PATH}:${PREFIX}/bin
export MANPATH=${MANPATH}:${PREFIX}/man export MANPATH=${MANPATH}:${PREFIX}/man
...@@ -83,7 +105,7 @@ 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 # 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. # 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 # dpkg --ignore-depends=ghdl*.deb --ignore-depends=libgnat-4.6 -i ghdl*.deb
# #
......
...@@ -10,21 +10,31 @@ ...@@ -10,21 +10,31 @@
#define x_IO_ADDR_MASK (0 - x_IO_ADDR_RANGE) #define x_IO_ADDR_MASK (0 - x_IO_ADDR_RANGE)
#define IO_PRINT_ADDR x_IO_BASE_ADDR; #define IO_PRINT_ADDR x_IO_BASE_ADDR
#define IO_STDOUT_ADDR (x_IO_BASE_ADDR + 1 * x_IO_ADDR_RANGE); #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_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_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_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_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_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_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_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_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_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_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 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 print(int);
extern void to_stdout(char c); extern void to_stdout(char c);
extern int from_stdin(void); extern int from_stdin(void);
...@@ -33,19 +43,25 @@ extern void writeInt(int); ...@@ -33,19 +43,25 @@ extern void writeInt(int);
extern void writeClose(void); extern void writeClose(void);
extern int readInt(int*); extern int readInt(int*);
extern void dumpRAM(void); 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 startCounter(int, int);
extern void stopCounter(void); extern void stopCounter(void);
extern int readCounter(void); extern int readCounter(void);
extern void enableInterr(void); // internal counter, CP0 register COUNT
extern void disableInterr(void); extern int startCount(void);
extern int stopCount(void);
extern char *memcpy(char*, const char*, int); extern int readCount(void);
extern char *memset(char*, const int, int);
// LCD display (Macnica board)
#define LCDprint(n) LCDint((n))
extern void LCDinit(void); extern void LCDinit(void);
extern int LCDprobe(void); extern int LCDprobe(void);
extern int LCDset(int); extern int LCDset(int);
...@@ -53,14 +69,24 @@ extern int LCDput(int); ...@@ -53,14 +69,24 @@ extern int LCDput(int);
extern void LCDclr(void); extern void LCDclr(void);
extern void LCDtopLine(void); extern void LCDtopLine(void);
extern void LCDbotLine(void); extern void LCDbotLine(void);
extern void LCDgotoxy(int, int);
extern void LCDputc(char);
extern void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot); 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 KBDget(void);
extern int SWget(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 { typedef struct sStats {
int dc_ref; // data cache references int dc_ref; // data cache references
int dc_rd_hit; // data cache read-hits int dc_rd_hit; // data cache read-hits
......
...@@ -28,8 +28,6 @@ SECTIONS ...@@ -28,8 +28,6 @@ SECTIONS
_edata = . ; /* end of data constant (from Xinu) */ _edata = . ; /* end of data constant (from Xinu) */
} > ram } > ram
.data1 : { *(.data1) } > ram .data1 : { *(.data1) } > ram
.rodata : { *(.rodata .rodata.*) } > ram
.rodata1 : { *(.rodata1) } > ram
.lit8 : { *(.lit8) } > ram .lit8 : { *(.lit8) } > ram
.lit4 : { *(.lit4) } > ram .lit4 : { *(.lit4) } > ram
.sdata : { *(.sdata .sdata.*) } > ram .sdata : { *(.sdata .sdata.*) } > ram
...@@ -37,12 +35,18 @@ SECTIONS ...@@ -37,12 +35,18 @@ SECTIONS
.bss : .bss :
{ {
*(.bss .bss.*) *(COMMON) *(.bss .bss.*) *(COMMON)
} > ram
.rodata1 : { *(.rodata1) } > ram
.rodata :
{
*(.rodata .rodata.*)
_end = . ; /* end of image constant (from Xinu) */ _end = . ; /* end of image constant (from Xinu) */
} > ram } > ram
start_RAM = 0x00040000; /* x_DATA_BASE_ADDR */
end_RAM = 0x00020000; /* x_DATA_MEM_SZ */ end_RAM = 0x00020000; /* x_DATA_MEM_SZ */
half_RAM = (end_RAM / 2); half_RAM = (end_RAM >> 1);
base_PT = ( _bdata + half_RAM ); base_PT = ( start_RAM + half_RAM );
.PT base_PT : { *(.PT) } > ram .PT base_PT : { *(.PT) } > ram
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
.set HW_dsp7seg_addr,(x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE) .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_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_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 # see vhdl/packageMemory.vhd for addresses
.set x_EXCEPTION_0000,0x00000130 .set x_EXCEPTION_0000,0x00000130
...@@ -28,25 +29,6 @@ ...@@ -28,25 +29,6 @@
.set x_EXCEPTION_BFC0,0x000004E0 .set x_EXCEPTION_BFC0,0x000004E0
.set x_ENTRY_POINT, 0x00000500 .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_index, $0
.set c0_random, $1 .set c0_random, $1
...@@ -70,10 +52,17 @@ ...@@ -70,10 +52,17 @@
# reset: COP0 present, at exception level, all else disabled # 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 # 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 # 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) { ...@@ -232,10 +232,13 @@ int SWget(void) {
#define LCD_write_delay 750/4 // 15us / 20ns #define LCD_write_delay 750/4 // 15us / 20ns
#define LCD_busy 0x80 #define LCD_busy 0x80
#define LCD_LINE_TWO 0x40 // RAM address for second line
void LCDinit(void) { void LCDinit(void) {
int *IO = (int *)IO_LCD_ADDR; 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 *IO = 0b00110000; // x30 = wake-up
cmips_delay(LCD_delay_30us); cmips_delay(LCD_delay_30us);
...@@ -265,11 +268,11 @@ void LCDinit(void) { ...@@ -265,11 +268,11 @@ void LCDinit(void) {
*IO = 0b00001111; // x0f displayON/OFF: Off, cur=on, blnk=on *IO = 0b00001111; // x0f displayON/OFF: Off, cur=on, blnk=on
cmips_delay(LCD_oper_delay); 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 *IO = 0b00000001; // x01 clear display -- DELAY=0.6ms
cmips_delay(LCD_clear_delay); cmips_delay(LCD_clear_delay);
*IO = 0b00000110; // x06 entry mode: blink, noShift, addrs++
cmips_delay(LCD_oper_delay);
} }
// check LCD's status register // check LCD's status register
...@@ -284,13 +287,14 @@ int LCDset(int cmd) { ...@@ -284,13 +287,14 @@ int LCDset(int cmd) {
volatile int s; volatile int s;
*IO = cmd; *IO = cmd;
cmips_delay(LCD_oper_delay);
s = *IO; s = *IO;
while ( (s & LCD_busy) != 0) { s = *IO; }; // still busy? while ( (s & LCD_busy) != 0) { s = *IO; }; // still busy?
return(s); return(s);
} }
// put a character on the current position // write a "raw" character on the current position
int LCDput(int c) { int LCDput(int c) {
int *IO = (int *)IO_LCD_ADDR; int *IO = (int *)IO_LCD_ADDR;
volatile int s; volatile int s;
...@@ -321,16 +325,94 @@ void LCDbotLine(void) { ...@@ -321,16 +325,94 @@ void LCDbotLine(void) {
*IO = 0b11000000; // xc0 RAMaddrs=40, cursor at home on BOTTOM LINE *IO = 0b11000000; // xc0 RAMaddrs=40, cursor at home on BOTTOM LINE
cmips_delay(LCD_clear_delay); 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 // 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 *IO = (int *)IO_DSP7SEG_ADDR;
int w, dot1, dot0, dig1, dig0; int leds, dot1, dot0, dig1, dig0;
dot1 = (MSdot != 0 ? 1 << 9 : 0); dot1 = (MSdot != 0 ? 1 << 9 : 0);
dot0 = (lsdot != 0 ? 1 << 8 : 0); dot0 = (lsdot != 0 ? 1 << 8 : 0);
...@@ -338,7 +420,9 @@ void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot) { ...@@ -338,7 +420,9 @@ void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot) {
dig1 = (MSD & 0xf) << 4; dig1 = (MSD & 0xf) << 4;
dig0 = (lsd & 0xf); 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) { ...@@ -379,4 +463,3 @@ int readCounter(void) {
}; //-------------------------------------------------------------------- }; //--------------------------------------------------------------------
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
.set noat # do not use register $1 as $at .set noat # do not use register $1 as $at
.align 2 .align 2
.set M_StatusIEn,0x0000ff13 # STATUS.intEn=1, user mode, EXL=1 .set M_StatusIEn,0x0000ff11 # STATUS.intEn=1, user mode, EXL=0
# 0xff13 = -237
#================================================================ #================================================================
# interrupt handler for external counter attached to IP5=HW3 # interrupt handler for external counter attached to IP5=HW3
...@@ -58,9 +57,6 @@ extCounter: ...@@ -58,9 +57,6 @@ extCounter:
# lw $a1, 1*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
eret # Return from interrupt eret # Return from interrupt
.end extCounter .end extCounter
#---------------------------------------------------------------- #----------------------------------------------------------------
...@@ -70,70 +66,93 @@ extCounter: ...@@ -70,70 +66,93 @@ extCounter:
# interrupt handler for UART attached to IP6=HW4 # interrupt handler for UART attached to IP6=HW4
# for UART's address see vhdl/packageMemory.vhd # for UART's address see vhdl/packageMemory.vhd
# #
.global Ud, _uart_buff
.bss .bss
.align 2 .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: Ud:
rx_hd: .space 4 rx_hd: .space 4 # reception queue head index
rx_tl: .space 4 rx_tl: .space 4 # tail index
rx_q: .space 16 # reception queue and pointers rx_q: .space 16 # reception queue
tx_hd: .space 4 tx_hd: .space 4 # transmission queue head index
tx_tl: .space 4 tx_tl: .space 4 # tail index
tx_q: .space 16 # transmission queue and pointers tx_q: .space 16 # transmission queue
nrx: .space 4 # characters in RX_queue nrx: .space 4 # characters in RX_queue
ntx: .space 4 # spaces left in TX_queue ntx: .space 4 # spaces left in TX_queue
_uart_buff: .space 16*4 # up to 16 registers to be saved here _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_rx_irq,0x08
.set UART_tx_irq,0x10 .set UART_tx_irq,0x10
.equ UCTRL,0 # UART registers
.equ USTAT,4
.equ UINTER,8
.equ UDATA,12
.text .text
.set noreorder .set noreorder
.global UARTinterr .global UARTinterr
.ent 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: 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 lui $k0, %hi(_uart_buff) # get buffer's address
ori $k0, $k0, %lo(_uart_buff) ori $k0, $k0, %lo(_uart_buff)
sw $a0, 5*4($k0) # save registers $a0,$a1, others? sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0) sw $a1, 6*4($k0)
sw $a2, 7*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr) ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request lw $k1, USTAT($a0) # Read status
nop
sw $k1, 0*4($k0) # and save UART status to memory sw $k1, 0*4($k0) # and save UART status to memory
#---------------------------------- li $a1, UART_rx_irq # remove interrupt request
# while you are developing the complete handler, sw $a1, UINTER($a0)
# uncomment the line below and comment out lines up to UARTret
# .include "../tests/handlerUART.s"
#----------------------------------
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 beq $a1, $zero, UARTret # no, ignore it and return
nop nop
# handle reception # handle reception
lw $a1, 4($a0) # Read data from device lw $a1, UDATA($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 2*4($k0) # and return from interrupt 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 addiu $a1, $zero, 1
sw $a1, 3*4($k0) # Signal new arrival sw $a1, 1*4($a2) # set flag to signal new arrival
UARTret: UARTret:
lw $a2, 7*4($k0)
lw $a1, 6*4($k0) # restore registers $a0,$a1, others? lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0) 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 eret # Return from interrupt
.end UARTinterr .end UARTinterr
#---------------------------------------------------------------- #----------------------------------------------------------------
...@@ -147,18 +166,69 @@ UARTret: ...@@ -147,18 +166,69 @@ UARTret:
.global countCompare .global countCompare
.ent countCompare .ent countCompare
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 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 eret # Return from interrupt
.end countCompare .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 # functions to enable and disable interrupts, both return STATUS
.text .text
...@@ -169,7 +239,7 @@ enableInterr: ...@@ -169,7 +239,7 @@ enableInterr:
mfc0 $v0, c0_status # Read STATUS register mfc0 $v0, c0_status # Read STATUS register
ori $v0, $v0, 1 # and enable interrupts ori $v0, $v0, 1 # and enable interrupts
mtc0 $v0, c0_status mtc0 $v0, c0_status
nop ehb
jr $ra # return updated STATUS jr $ra # return updated STATUS
nop nop
.end enableInterr .end enableInterr
...@@ -180,7 +250,7 @@ disableInterr: ...@@ -180,7 +250,7 @@ disableInterr:
addiu $v1, $zero, -2 # and disable interrupts addiu $v1, $zero, -2 # and disable interrupts
and $v0, $v0, $v1 # -2 = 0xffff.fffe and $v0, $v0, $v1 # -2 = 0xffff.fffe
mtc0 $v0, c0_status mtc0 $v0, c0_status
nop ehb
jr $ra # return updated STATUS jr $ra # return updated STATUS
nop nop
.end disableInterr .end disableInterr
...@@ -189,11 +259,11 @@ disableInterr: ...@@ -189,11 +259,11 @@ disableInterr:
#================================================================ #================================================================
## TLB handlers ## TLB handlers
## page table entry is { EntryLo0 int0 EntryLo1 int1 } ## page table entry is { EntryLo0, int0, EntryLo1, int1 }
## int{0,1} is ## int{0,1} is
## { fill_31..6, Modified_5, Used_4, Writable_3, eXecutable_2, ## { fill_31..6, Modified_5, Used_4, Writable_3, eXecutable_2,
## Status_10 }, ## 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 ...@@ -304,8 +374,6 @@ M_sec_mem: # print message and abort simulation
# (a) fix the fault by (re)loading the mapping into TLB[4]; # (a) fix the fault by (re)loading the mapping into TLB[4];
# (b) check permissions in PT entry and (maybe) kill the process. # (b) check permissions in PT entry and (maybe) kill the process.
# #
.global _excp_saves
.global _excp_0180ret
.global handle_TLBL .global handle_TLBL
.global _PT .global _PT
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2)) .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 ...@@ -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) # returns 0 if V_addr purged, 1 if V_addr not in TLB (probe failure)
# #
.text .text
.global TLB_purge
.set noreorder .set noreorder
.ent TLB_purge .ent TLB_purge
TLB_purge: TLB_purge:
...@@ -430,18 +496,98 @@ pu_miss: jr $ra ...@@ -430,18 +496,98 @@ pu_miss: jr $ra
# delays processing by approx 4*$a0 processor cycles # delays processing by approx 4*$a0 processor cycles
.text .text
.set noreorder .set noreorder
.global cmips_delay .global cmips_delay, delay_cycle, delay_us, delay_ms
.ent cmips_delay .ent cmips_delay
delay_cycle:
cmips_delay: cmips_delay:
addiu $a0, $a0, -1 beq $a0, $zero, _d_cye
nop nop
bne $a0, $zero, cmips_delay _d_cy: addiu $a0, $a0, -1
nop nop
jr $ra bne $a0, $zero, _d_cy
nop
_d_cye: jr $ra
nop nop
.end cmips_delay .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" # print a message from within "the kernel"
...@@ -493,7 +639,7 @@ k_for: lbu $a0, 0($a1) ...@@ -493,7 +639,7 @@ k_for: lbu $a0, 0($a1)
.equ kmsg_interr,0 .equ kmsg_interr,0
.equ kmsg_excep,1 .equ kmsg_excep,1
.data .section .rodata
.align 2 .align 2
_kmsg_interr: .asciiz "\n\t00 - interrupt\n\n" _kmsg_interr: .asciiz "\n\t00 - interrupt\n\n"
_kmsg_excep: .asciiz "\n\t01 - exception\n\n" _kmsg_excep: .asciiz "\n\t01 - exception\n\n"
...@@ -502,11 +648,19 @@ _kmsg_seg_fault: .asciiz "\n\t03 - segmentation fault\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" _kmsg_sec_mem: .asciiz "\n\t04 - in secondary memory\n\n"
.global _kmsg_list .global _kmsg_list
.data .section .rodata
.align 2 .align 2
_kmsg_list: _kmsg_list:
.word _kmsg_interr,_kmsg_excep, _kmsg_prot_viol, _kmsg_seg_fault .word _kmsg_interr,_kmsg_excep, _kmsg_prot_viol, _kmsg_seg_fault
.word _kmsg_sec_mem .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: ...@@ -51,7 +51,7 @@ _start:
# #
# the page table is located at the middle of the RAM # 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 TOP_OF_RAM, (x_DATA_BASE_ADDR + x_DATA_MEM_SZ)
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2)) .set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2))
...@@ -117,7 +117,6 @@ _start: ...@@ -117,7 +117,6 @@ _start:
sw $a1, 0($a0) # write to PT[ _PTV ].entryLo0 sw $a1, 0($a0) # write to PT[ _PTV ].entryLo0
sw $a2, 8($a0) # write to PT[ _PTV ].entryLo1 sw $a2, 8($a0) # write to PT[ _PTV ].entryLo1
# pin down first five TLB entries: ROM[0], I/O, RAM[0], stack, PgTbl # pin down first five TLB entries: ROM[0], I/O, RAM[0], stack, PgTbl
li $k0, 5 li $k0, 5
mtc0 $k0, c0_wired mtc0 $k0, c0_wired
...@@ -132,10 +131,10 @@ _start: ...@@ -132,10 +131,10 @@ _start:
la $sp, (MIDDLE_RAM - 16) la $sp, (MIDDLE_RAM - 16)
# set STATUS, cop0, hw interrupts IRQ7,IRQ6,IRQ5 enabled, user mode # set STATUS, c0, hw interrupts IRQ7,IRQ6,IRQ5 enabled, user mode
li $k0, cop0_STATUS_normal li $k0, c0_status_normal
mtc0 $k0, c0_status mtc0 $k0, c0_status
ehb
jal main # on returning from main(), MUST go into exit() jal main # on returning from main(), MUST go into exit()
nop # to stop the simulation. nop # to stop the simulation.
...@@ -170,7 +169,6 @@ _excp_0000: ...@@ -170,7 +169,6 @@ _excp_0000:
mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element
ehb ehb
tlbwr # update TLB tlbwr # update TLB
mfc0 $zero, c0_cause # clear excCode in Cause
eret eret
.end _excp_0000 .end _excp_0000
...@@ -204,6 +202,7 @@ _excp_0100: ...@@ -204,6 +202,7 @@ _excp_0100:
## area to save up to 16 registers ## area to save up to 16 registers
.bss .bss
.align 2 .align 2
.global _excp_saves, _excp_0180ret
.comm _excp_saves 16*4 .comm _excp_saves 16*4
# _excp_saves[0]=CAUSE, [1]=STATUS, [2]=ASID, # _excp_saves[0]=CAUSE, [1]=STATUS, [2]=ASID,
# [8]=$ra, [9]=$a0, [10]=$a1, [11]=$a2, [12]=$a3 # [8]=$ra, [9]=$a0, [10]=$a1, [11]=$a2, [12]=$a3
...@@ -211,7 +210,7 @@ _excp_0100: ...@@ -211,7 +210,7 @@ _excp_0100:
.text .text
.set noreorder .set noreorder
.set noat .set noat
.global _excp_saves, _excp_0180ret .global _excp_0180ret
.global handle_Mod, handle_TLBL, handle_TLBS .global handle_Mod, handle_TLBL, handle_TLBS
.org x_EXCEPTION_0180,0 # exception vector_180 .org x_EXCEPTION_0180,0 # exception vector_180
...@@ -225,10 +224,11 @@ _excp_0180: ...@@ -225,10 +224,11 @@ _excp_0180:
sw $k0, 0*4($k1) sw $k0, 0*4($k1)
andi $k0, $k0, 0x3f # keep only the first 16 ExceptionCodes & b"00" 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) lui $k1, %hi(excp_tbl)
ori $k1, $k1, %lo(excp_tbl) ori $k1, $k1, %lo(excp_tbl)
add $k1, $k1, $k0 add $k1, $k1, $k0
nop
jr $k1 jr $k1
nop nop
...@@ -253,32 +253,23 @@ excp_tbl: # see Table 8-25, pg 95,96 ...@@ -253,32 +253,23 @@ excp_tbl: # see Table 8-25, pg 95,96
nop nop
wait 0x07 # 7 DBE addr error -- abort simulation wait 0x07 # 7 DBE addr error -- abort simulation
nop nop
wait 0x08 # j h_syscall # 8 -- abort simulation
j h_syscall # 8
nop nop
wait 0x09 # j h_breakpoint # 9 -- abort simulation
j h_breakpoint # 9
nop nop
wait 0x0a # j h_RI # 10 reserved instruction -- abort simulation
j h_RI # 10 reserved instruction
nop nop
wait 0x0b # j h_CpU # 11 coprocessor unusable -- abort simulation
j h_CpU # 11 coprocessor unusable
nop nop
wait 0x0c # j h_Ov # 12 overflow -- abort simulation
j h_Ov # 12 overflow
nop nop
wait 0x0d # 13 trap -- abort simulation wait 0x0d # 13 trap -- abort simulation
nop nop
wait 0x0e # reserved, should never get here -- abort simulation wait 0x0e # reserved, should never get here -- abort simulation
nop nop
wait 0x0f # FP exception, should never get here -- abort simulation wait 0x0f # FP exception, should never get here -- abort simulation
nop nop
h_TLBS: h_TLBS:
h_syscall: h_syscall:
h_breakpoint: h_breakpoint:
...@@ -290,10 +281,10 @@ _excp_0180ret: ...@@ -290,10 +281,10 @@ _excp_0180ret:
lui $k1, %hi(_excp_saves) # Read previous contents of STATUS lui $k1, %hi(_excp_saves) # Read previous contents of STATUS
ori $k1, $k1, %lo(_excp_saves) ori $k1, $k1, %lo(_excp_saves)
lw $k0, 1*4($k1) lw $k0, 1*4($k1)
# mfc0 $k0, c0_status
# and do not modify its contents # and do not modify its contents
ori $k0, $k0, M_StatusIEn # and keeping user/kernel mode ori $k0, $k0, M_StatusIEn # and keep user/kernel mode
mtc0 $k0, c0_status # -239 = 0xffff.ff11 mtc0 $k0, c0_status # but enable all interrupts
ehb
eret # Return from exception eret # Return from exception
.end _excp_0180 .end _excp_0180
...@@ -309,7 +300,7 @@ _excp_0180ret: ...@@ -309,7 +300,7 @@ _excp_0180ret:
.extern extCounter # IRQ5 - hwIRQ3, see vhdl/tb_cMIPS.vhd .extern extCounter # IRQ5 - hwIRQ3, see vhdl/tb_cMIPS.vhd
.set M_CauseIM,0x0000ff00 # keep bits 15..8 -> IM = IP .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 .set noreorder
...@@ -317,20 +308,20 @@ _excp_0180ret: ...@@ -317,20 +308,20 @@ _excp_0180ret:
.ent _excp_0200 .ent _excp_0200
_excp_0200: _excp_0200:
mfc0 $k0, c0_cause mfc0 $k0, c0_cause
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
mfc0 $k1, c0_status mfc0 $k1, c0_status
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
and $k0, $k0, $k1 # and mask with IM bits and $k0, $k0, $k1 # and mask with IM bits
srl $k0, $k0, 10 # keep only 3 MS bits of IP (irq7..5) 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 lui $k1, %hi(handlers_tbl) # plus displacement in j-table of 8 bytes
ori $k1, $k1, %lo(handlers_tbl) ori $k1, $k1, %lo(handlers_tbl)
add $k1, $k1, $k0 add $k1, $k1, $k0
nop
jr $k1 jr $k1
nop nop
## the code for each handler must repeat the exception return ## the code for each handler must contain an exception return
## sequence shown below in excp_0200ret. ## such as the sequence shown below, in excp_0200ret.
handlers_tbl: handlers_tbl:
j dismiss # no request: 000 j dismiss # no request: 000
nop nop
...@@ -358,10 +349,10 @@ dismiss: # No pending request, must have been noise ...@@ -358,10 +349,10 @@ dismiss: # No pending request, must have been noise
_excp_0200ret: _excp_0200ret:
mfc0 $k0, c0_status # Read STATUS register mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # except for re-enabling interrupts ori $k0, $k0, M_StatusIEn # and re-enable interrupts
mtc0 $k0, c0_status # as it was on interrupt entry mtc0 $k0, c0_status # else keep as it was on int entry
ehb
eret # Return from interrupt eret # Return from interrupt
nop
.end _excp_0200 .end _excp_0200
#---------------------------------------------------------------- #----------------------------------------------------------------
...@@ -419,8 +410,6 @@ PT_update: ...@@ -419,8 +410,6 @@ PT_update:
##=============================================================== ##===============================================================
## Page Table ## Page Table
## ##
...@@ -431,14 +420,14 @@ PT_update: ...@@ -431,14 +420,14 @@ PT_update:
## Status: 00=unmapped, 01=mapped, 10=in_secondary_storage, 11=undef ## Status: 00=unmapped, 01=mapped, 10=in_secondary_storage, 11=undef
## ##
.section .PT,"aw",@progbits .section .PT,"aw",@progbits
.align 4
.global _PT .global _PT
## ( ( (x_INST_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000011 d,v,g ## ( ( (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) ## 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 # PT[0], ROM
PTbase: .word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011 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 @@ ...@@ -10,7 +10,6 @@
.align 2 .align 2
.extern main .extern main
.global _start, _exit, exit .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 .set MMU_WIRED, 2 ### do not change mapping for base of ROM, I/O
...@@ -26,11 +25,11 @@ _start: nop ...@@ -26,11 +25,11 @@ _start: nop
# needed so systems without a page table will not break # needed so systems without a page table will not break
# read TLB[4] and write it to TLB[2] # read TLB[4] and write it to TLB[2]
li $k0, 4 li $k0, 4
mtc0 $k0, cop0_Index mtc0 $k0, c0_index
ehb ehb
tlbr tlbr
li $k1, 2 li $k1, 2
mtc0 $k1, cop0_Index mtc0 $k1, c0_index
ehb ehb
tlbwi tlbwi
...@@ -38,37 +37,36 @@ _start: nop ...@@ -38,37 +37,36 @@ _start: nop
# then set another mapping onto TLB[4], to avoid replicated entries # then set another mapping onto TLB[4], to avoid replicated entries
li $a0, ( (x_DATA_BASE_ADDR + 8*4096) >>12 ) li $a0, ( (x_DATA_BASE_ADDR + 8*4096) >>12 )
sll $a2, $a0, 12 # tag for RAM[8,9] double-page 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 ) li $a0, ((x_DATA_BASE_ADDR + 8*4096) >>12 )
sll $a1, $a0, 6 # RAM[8] (even) sll $a1, $a0, 6 # RAM[8] (even)
ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 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 ) li $a0, ( (x_DATA_BASE_ADDR + 9*4096) >>12 )
sll $a1, $a0, 6 # RAM[9] (odd) sll $a1, $a0, 6 # RAM[9] (odd)
ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, cop0_EntryLo1 mtc0 $a1, c0_entrylo1
# and write it to TLB[4] # and write it to TLB[4]
li $k0, 4 li $k0, 4
mtc0 $k0, cop0_Index mtc0 $k0, c0_index
tlbwi tlbwi
# pin down first four TLB entries: ROM[0], RAM[0], stack and I/O # pin down first four TLB entries: ROM[0], RAM[0], stack and I/O
li $k0, 4 li $k0, 4
mtc0 $k0, cop0_Wired mtc0 $k0, c0_wired
# initialize SP at top of RAM: ramTop - 16 # initialize SP at top of RAM: RAM[1] - 16
li $sp, ((x_DATA_BASE_ADDR+x_DATA_MEM_SZ) - 16) li $sp, ((x_DATA_BASE_ADDR + (2*4096)) - 16)
# set STATUS, cop0, hw interrupt IRQ7,IRQ6,IRQ5 enabled, user mode # set STATUS, cop0, hw interrupt IRQ7,IRQ6,IRQ5 enabled, user mode
li $k0, 0x1000e011 li $k0, 0x1000e011
mtc0 $k0, cop0_STATUS mtc0 $k0, c0_status
j main j main
nop nop
...@@ -78,18 +76,67 @@ _start: nop ...@@ -78,18 +76,67 @@ _start: nop
## ##
exit: exit:
_exit: la $k0, HW_dsp7seg_addr # 7 segment display _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 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 nop
.end _start .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 ## exception vector_0000 TLBrefill
## ##
.text
.org x_EXCEPTION_0000,0 .org x_EXCEPTION_0000,0
_excp_0000: _excp_0000:
la $k0, HW_dsp7seg_addr # 7 segment display la $k0, HW_dsp7seg_addr # 7 segment display
...@@ -120,23 +167,95 @@ h0100: j h0100 # wait forever ...@@ -120,23 +167,95 @@ h0100: j h0100 # wait forever
.org x_EXCEPTION_0180,0 .org x_EXCEPTION_0180,0
_excp_0180: _excp_0180:
la $k0, HW_dsp7seg_addr # 7 segment display 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 sw $k1, 0($k0) # write to 7 segment display
h0180: j h0180 # wait forever h0180: j h0180 # wait forever
nop 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 ## 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: _excp_0200:
la $k0, HW_dsp7seg_addr # 7 segment display mfc0 $k0, c0_cause
li $k1, 0x0366 # display .6.6 andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
sw $k1, 0($k0) # write to 7 segment display mfc0 $k1, c0_status
h0200: j h0200 # wait forever 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 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 ...@@ -153,6 +272,7 @@ hBFC0: j hBFC0 # wait forever
##================================================================ ##================================================================
## ##
##=============================================================== ##===============================================================
## main(), normal code starts below -- do not edit next line ## 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 ...@@ -10,7 +10,7 @@ _start: nop
## set STATUS, cop0, no interrupts enabled, user mode ## set STATUS, cop0, no interrupts enabled, user mode
li $k0, 0x10000010 li $k0, 0x10000010
mtc0 $k0, cop0_STATUS mtc0 $k0, c0_status
j main j main
nop nop
...@@ -32,7 +32,7 @@ _exit: nop # flush pipeline ...@@ -32,7 +32,7 @@ _exit: nop # flush pipeline
.org x_EXCEPTION_0000,0 .org x_EXCEPTION_0000,0
_excp_0000: _excp_0000:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
...@@ -42,7 +42,7 @@ _excp_0000: ...@@ -42,7 +42,7 @@ _excp_0000:
.org x_EXCEPTION_0100,0 .org x_EXCEPTION_0100,0
_excp_0100: _excp_0100:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
...@@ -80,7 +80,7 @@ excp_180: ...@@ -80,7 +80,7 @@ excp_180:
.org x_EXCEPTION_0200,0 .org x_EXCEPTION_0200,0
_excp_0200: _excp_0200:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
......
...@@ -9,7 +9,7 @@ _start: nop ...@@ -9,7 +9,7 @@ _start: nop
li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8
## set STATUS, cop0, no interrupts enabled, user mode ## set STATUS, cop0, no interrupts enabled, user mode
li $k0, cop0_STATUS_normal li $k0, c0_status_normal
mtc0 $k0, c0_status mtc0 $k0, c0_status
j main j main
...@@ -33,7 +33,7 @@ _exit: nop # flush pipeline ...@@ -33,7 +33,7 @@ _exit: nop # flush pipeline
.org x_EXCEPTION_0000,0 .org x_EXCEPTION_0000,0
_excp_0000: _excp_0000:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
...@@ -43,7 +43,7 @@ _excp_0000: ...@@ -43,7 +43,7 @@ _excp_0000:
.org x_EXCEPTION_0100,0 .org x_EXCEPTION_0100,0
_excp_0100: _excp_0100:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
...@@ -97,7 +97,7 @@ _excp_0200: ...@@ -97,7 +97,7 @@ _excp_0200:
.org x_EXCEPTION_BFC0,0 .org x_EXCEPTION_BFC0,0
_excp_BFC0: _excp_BFC0:
la $k0, x_IO_BASE_ADDR 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 sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation
nop nop
nop nop
......