URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk/sim
- from Rev 208 to Rev 209
- ↔ Reverse comparison
Rev 208 → Rev 209
/cpp/Makefile
1,37 → 1,43
################################################################################ |
# |
# Filename: Makefile |
# |
# Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
# |
# Purpose: |
# |
# Targets: |
# |
# |
# Creator: Dan Gisselquist, Ph.D. |
# Gisselquist Technology, LLC |
# |
## |
## Filename: Makefile |
## |
## Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
## |
## Purpose: |
## |
## Targets: |
## |
## |
## Creator: Dan Gisselquist, Ph.D. |
## Gisselquist Technology, LLC |
## |
################################################################################ |
# |
# Copyright (C) 2017, Gisselquist Technology, LLC |
# |
# This program is free software (firmware): you can redistribute it and/or |
# modify it under the terms of the GNU General Public License as published |
# by the Free Software Foundation, either version 3 of the License, or (at |
# your option) any later version. |
# |
# This program is distributed in the hope that it will be useful, but WITHOUT |
# ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
# for more details. |
# |
# License: GPL, v3, as defined and found on www.gnu.org, |
# http://www.gnu.org/licenses/gpl.html |
# |
# |
## |
## Copyright (C) 2017, Gisselquist Technology, LLC |
## |
## This program is free software (firmware): you can redistribute it and/or |
## modify it under the terms of the GNU General Public License as published |
## by the Free Software Foundation, either version 3 of the License, or (at |
## your option) any later version. |
## |
## This program is distributed in the hope that it will be useful, but WITHOUT |
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
## for more details. |
## |
## You should have received a copy of the GNU General Public License along |
## with this program. (It's in the $(ROOT)/doc directory. Run make with no |
## target there if the PDF file isn't present.) If not, see |
## <http://www.gnu.org/licenses/> for a copy. |
## |
## License: GPL, v3, as defined and found on www.gnu.org, |
## http://www.gnu.org/licenses/gpl.html |
## |
## |
################################################################################ |
# |
## |
## |
all: zsim |
|
CXX := g++ |
/cpp/README.md
0,0 → 1,10
## The C++ Simulator |
|
This simulator was written as part of the last instruction set change. |
|
It is now pretty much abandonware. |
|
One problem with this simulation is that it was very difficult to integrate |
peripherals and interrupts into it--more difficult than it is to integrate |
these things into a Verilog design tested with Verilator. As a result, |
there's not much useful here. |
/cpp/twoc.cpp
1,20 → 1,20
//////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: twoc.cpp |
// |
// Project: A Doubletime Pipelined FFT |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Some various two's complement related C++ helper routines. |
// Specifically, these help extract signed numbers from |
// packed bitfields, while guaranteeing that the upper bits |
// are properly sign extended (or not) as desired. |
// packed bitfields, while guaranteeing that the upper bits are properly |
// sign extended (or not) as desired. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
27,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
35,7 → 35,9
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include "twoc.h" |
|
long sbits(const long val, const int bits) { |
/cpp/twoc.h
1,8 → 1,8
//////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: twoc.h |
// |
// Project: A Doubletime Pipelined FFT |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Some various two's complement related C++ helper routines. |
// Specifically, these help extract signed numbers from |
12,9 → 12,9
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
27,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
35,7 → 35,9
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef TWOC_H |
#define TWOC_H |
|
/cpp/zipelf.cpp
215,12 → 215,13
|
r[i]->m_start = phdr.p_paddr; |
r[i]->m_len = phdr.p_filesz; |
r[i]->m_vaddr = phdr.p_vaddr; |
|
current_offset += phdr.p_filesz + sizeof(ELFSECTION); |
|
// Now, let's read in our section ... |
if (lseek(fd, phdr.p_offset, SEEK_SET) < 0) { |
fprintf(stderr, "Could not seek to file position %08lx\n", phdr.p_offset); |
fprintf(stderr, "Could not seek to file position %08lx\n", (unsigned long)phdr.p_offset); |
perror("O/S Err:"); |
exit(EXIT_FAILURE); |
} if (phdr.p_filesz > phdr.p_memsz) |
/cpp/zipelf.h
1,4 → 1,4
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: zipelf.h |
// |
10,7 → 10,7
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
24,11 → 24,16
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef ZIPELF_H |
38,7 → 43,7
|
class ELFSECTION { |
public: |
uint32_t m_start, m_len; |
uint32_t m_start, m_len, m_vaddr; |
char m_data[4]; |
}; |
|
/cpp/zsim.cpp
14,7 → 14,7
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// Copyright (C) 2015-2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
26,6 → 26,11
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
cpp
Property changes :
Added: svn:ignore
## -0,0 +1 ##
+zsim
Index: verilator/.gitignore
===================================================================
--- verilator/.gitignore (revision 208)
+++ verilator/.gitignore (revision 209)
@@ -6,3 +6,4 @@
zippy_tb
pfcache_tb
zipmmu_tb
+pfile.bin
Index: verilator/Makefile
===================================================================
--- verilator/Makefile (revision 208)
+++ verilator/Makefile (revision 209)
@@ -1,165 +1,199 @@
################################################################################
-#
-# Filename: Makefile
-#
-# Project: Zip CPU -- a small, lightweight, RISC CPU soft core
-#
-# Purpose: This makefile builds the final verilator simulation of the
-# zipsystem. Specifically, it builds the final C++ portion
-# of the simulator, and thus the final simulator executable.
-#
-# This simulator depends upon the libelf and ncurses libraries.
-#
-# Useful targets of this makefile include:
-#
-# zippy_tb (default)
-# This is the test bench program / simulator that is built by
-# this directory.
-#
-# test
-# Runs the simulator on a test program found in the trunk/sw/zasm
-# directory. That program needs to be built via 'make test' in
-# that directory before this make test will work. Changes to the
-# test itself will require a 'make test' in trunk/sw/zasm as well
-# as 'make test' in this directory.
-#
-# The test itself consists of two tests. The first, the "step"
-# test, tests whether the test works via "step"ing the CPU.
-# This would be the interface to the CPU were the CPU placed in
-# a device.
-#
-# The second test is an internal test which works by just running
-# the CPU without step instructions.
-#
-# In either case the test is over upon reaching either a HALT
-# or a BUSY instruction. A HALT instruction indicates success,
-# BUSY a failure.
-#
-# stest
-# Runs the test in "step" mode as described above.
-#
-# itest
-# Runs the test file in interactive mode. The CPU will not
-# execute any instructions without user interaction. This is
-# useful for actually debugging the test. The other two modes
-# are useful for quickly determining that the CPU does (or
-# doesn't) work.
-#
-# dhrystone
-# Runs a hand-optimized version of the dhrystone benchmark.
-# Using the instructions at the top of the dhrystone assembly
-# file, you should be able to convert the result to DMIPS or even
-# DMIPS/MHz.
-#
-# div_tb
-# A raw test bench to test the divide unit separate from the
-# rest of the CPU. This test will fail with a failed assert()
-# if unsuccessful, or complete with no error (but lots of
-# debugging output) if successful. To actually run this test,
-# you'll need to run ./div_tb (no arguments necessary).
-#
-# mpy_tb
-# A raw test bench to test the multiply instructions within the
-# cpuops (ALU) unit separate from the rest of the CPU. For more
-# details, look at the usage statement wtihin mpy_tb.
-#
-# pfcache_tb
-#
-# zipmmu_tb
-# Like div_tb, this is another raw component test bench. In this
-# case, zipmmu_tb tests whether or not the MMU works when
-# separated from the rest of the CPU.
-#
-# pdump
-# zippy_tb can be configured to produce a profile output that is
-# very useful when debugging the Dhrystone benchmark. (It is
-# so configured by default.) This file will be name pfile.bin.
-# pdump is a very simple program designed to read this file and
-# produce some (very raw) information from it. To use this,
-# type pdump and the name of the executable file, such as
-# ../asm/zipdhry.z, and examine how many times each instruction
-# was executed, and how many stalls took place between each
-# instruction and the next.
-#
-# clean
-# Removes all products of compilation--specifically zippy_tb,
-# pdump and div_tb.
-#
-#
-# Creator: Dan Gisselquist, Ph.D.
-# Gisselquist Technology, LLC
-#
+##
+## Filename: Makefile
+##
+## Project: Zip CPU -- a small, lightweight, RISC CPU soft core
+##
+## Purpose: This makefile builds the final verilator simulation of the
+## zipsystem. Specifically, it builds the final C++ portion
+## of the simulator, and thus the final simulator executable.
+##
+## This simulator depends upon the libelf and ncurses libraries.
+##
+## Useful targets of this makefile include:
+##
+## zipsys_tb (default)
+## This is the test bench program / simulator that is built by
+## this directory. This is based upon the ZipSystem.
+##
+## zipbones_tb (default)
+## This is the test bench program / simulator that is built by
+## this directory--save that this ones uses the ZipBones.
+##
+## test
+## Runs the simulator on a test program found in the trunk/sw/zasm
+## directory. That program needs to be built via 'make test' in
+## that directory before this make test will work. Changes to the
+## test itself will require a 'make test' in trunk/sw/zasm as well
+## as 'make test' in this directory.
+##
+## The test itself consists of two tests. The first, the "step"
+## test, tests whether the test works via "step"ing the CPU.
+## This would be the interface to the CPU were the CPU placed in
+## a device.
+##
+## The second test is an internal test which works by just running
+## the CPU without step instructions.
+##
+## In either case the test is over upon reaching either a HALT
+## or a BUSY instruction. A HALT instruction indicates success,
+## BUSY a failure.
+##
+## stest
+## Runs the test in "step" mode as described above.
+##
+## itest
+## Runs the test file in interactive mode. The CPU will not
+## execute any instructions without user interaction. This is
+## useful for actually debugging the test. The other two modes
+## are useful for quickly determining that the CPU does (or
+## doesn't) work.
+##
+## dhrystone
+## Runs a hand-optimized version of the dhrystone benchmark.
+## Using the instructions at the top of the dhrystone assembly
+## file, you should be able to convert the result to DMIPS or even
+## DMIPS/MHz.
+##
+## div_tb
+## A raw test bench to test the divide unit separate from the
+## rest of the CPU. This test will fail with a failed assert()
+## if unsuccessful, or complete with no error (but lots of
+## debugging output) if successful. To actually run this test,
+## you'll need to run ./div_tb (no arguments necessary).
+##
+## mpy_tb
+## A raw test bench to test the multiply instructions within the
+## cpuops (ALU) unit separate from the rest of the CPU. For more
+## details, look at the usage statement wtihin mpy_tb.
+##
+## pfcache_tb
+##
+## zipmmu_tb
+## Like div_tb, this is another raw component test bench. In this
+## case, zipmmu_tb tests whether or not the MMU works when
+## separated from the rest of the CPU.
+##
+## pdump
+## zipsys_tb can be configured to produce a profile output that is
+## very useful when debugging the Dhrystone benchmark. (It is
+## so configured by default.) This file will be name pfile.bin.
+## pdump is a very simple program designed to read this file and
+## produce some (very raw) information from it. To use this,
+## type pdump and the name of the executable file, such as
+## ../asm/zipdhry.z, and examine how many times each instruction
+## was executed, and how many stalls took place between each
+## instruction and the next.
+##
+## clean
+## Removes all products of compilation--specifically zipsys_tb,
+## pdump and div_tb.
+##
+##
+## Creator: Dan Gisselquist, Ph.D.
+## Gisselquist Technology, LLC
+##
################################################################################
-#
-# Copyright (C) 2015-2017, Gisselquist Technology, LLC
-#
-# This program is free software (firmware): you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or (at
-# your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# for more details.
-#
-# License: GPL, v3, as defined and found on www.gnu.org,
-# http://www.gnu.org/licenses/gpl.html
-#
-#
+##
+## Copyright (C) 2015-2017, Gisselquist Technology, LLC
+##
+## This program is free software (firmware): you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as published
+## by the Free Software Foundation, either version 3 of the License, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with this program. (It's in the $(ROOT)/doc directory. Run make with no
+## target there if the PDF file isn't present.) If not, see
+## for a copy.
+##
+## License: GPL, v3, as defined and found on www.gnu.org,
+## http://www.gnu.org/licenses/gpl.html
+##
+##
################################################################################
-#
-all: zippy_tb pdump div_tb mpy_tb pfcache_tb # zipmmu_tb
+##
+##
+all: zipsys_tb zipbones_tb pdump div_tb mpy_tb pfcache_tb # zipmmu_tb
CXX := g++
-CFLAGS := -Wall -Og -g
+CFLAGS := -Wall -Og -g -D__WORDSIZE=64
OBJDIR := obj-pc
ZASM := ../../sw/zasm
RTLD := ../../rtl
RTLOBJD := $(RTLD)/obj_dir
BENCHOBJD:= ../../bench/rtl/obj_dir
+ifneq ($(VERILATOR_ROOT),)
+VERILATOR:=$(VERILATOR_ROOT)/bin/verilator
+else
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"')
+endif
+export $(VERILATOR)
VROOT := $(VERILATOR_ROOT)
+VDEFS := $(shell ./vversion.sh)
VINCS := -I$(VROOT)/include -I$(VROOT)/include/vltstd
INCS := -I$(RTLOBJD) -I$(RTLD) -I$(ZASM) $(VINCS)
ZLIBSRCS:= zipelf.cpp twoc.cpp byteswap.cpp
-SOURCES := $(ZLIBSRCS) pdump.cpp zippy_tb.cpp memsim.cpp
+SOURCES := $(ZLIBSRCS) pdump.cpp zipcpu_tb.cpp memsim.cpp
ZDSMSRCS:= zopcodes.cpp
ZOBJS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(ZLIBSRCS) $(ZDSMSRCS)))
-SIMSRCS := zippy_tb.cpp memsim.cpp $(ZLIBSRCS) $(ZDMSRCS)
+SIMSRCS := memsim.cpp $(ZLIBSRCS) $(ZDMSRCS)
SIMOBJS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SIMSRCS) $(ZDSMSRCS)))
+SYSOBJS := $(OBJDIR)/zipsys_tb.o $(SIMOBJS)
+BONOBJS := $(OBJDIR)/zipbones_tb.o $(SIMOBJS)
VLSRCS := verilated.cpp verilated_vcd_c.cpp
VLOBJS := $(OBJDIR)/verilated.o $(OBJDIR)/verilated_vcd_c.o
VLIB := $(addprefix $(VROOT)/include/,$(VLSRCS))
-RAWLIB := $(RTLOBJD)/Vzipsystem__ALL.a
-LIBS := $(RAWLIB) -lncurses -lelf
-TESTF := $(ZASM)/z.out
+RAWSYSLIB := $(RTLOBJD)/Vzipsystem__ALL.a
+RAWBONLIB := $(RTLOBJD)/Vzipbones__ALL.a
+SYSLIBS := $(RAWSYSLIB) -lncurses -lelf
+BONLIBS := $(RAWBONLIB) -lncurses -lelf
+TESTF := ../../bench/asm/simtest
DHRYSTONEF := ../asm/zipdhry.z
$(OBJDIR)/%.o: %.cpp
- $(CXX) $(CFLAGS) $(INCS) -c $< -o $@
+ $(mk-objdir)
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) -c $< -o $@
+$(OBJDIR)/zipsys_tb.o: zipcpu_tb.cpp
+ $(mk-objdir)
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) -c $< -o $@
+
+$(OBJDIR)/zipbones_tb.o: zipcpu_tb.cpp
+ $(mk-objdir)
+ $(CXX) -DZIPBONES $(VDEFS) $(CFLAGS) $(INCS) -c $< -o $@
+
$(OBJDIR)/%.o: $(ZASM)/%.cpp
+ $(mk-objdir)
$(CXX) $(CFLAGS) $(INCS) -c $< -o $@
$(OBJDIR)/%.o: $(VROOT)/include/%.cpp
+ $(mk-objdir)
$(CXX) $(CFLAGS) $(INCS) -c $< -o $@
-zippy_tb: $(SIMOBJS) $(VLOBJS) $(RAWLIB)
- $(CXX) $(CFLAGS) $(INCS) $(SIMOBJS) $(VLOBJS) $(RAWLIB) $(LIBS) -o $@
+zipsys_tb: $(SYSOBJS) $(VLOBJS) $(RAWSYSLIB)
+ $(CXX) $(CFLAGS) $(INCS) $(SYSOBJS) $(VLOBJS) $(SYSLIBS) -o $@
+zipbones_tb: $(BONOBJS) $(VLOBJS) $(RAWBONLIB)
+ $(CXX) $(CFLAGS) $(INCS) $(BONOBJS) $(VLOBJS) $(BONLIBS) -o $@
+
div_tb: div_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vdiv__ALL.a testb.h
- $(CXX) $(CFLAGS) $(INCS) div_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vdiv__ALL.a -o $@
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) div_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vdiv__ALL.a -o $@
mpy_tb: mpy_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vcpuops__ALL.a testb.h
- $(CXX) $(CFLAGS) $(INCS) mpy_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vcpuops__ALL.a -o $@
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) mpy_tb.cpp twoc.cpp $(VLIB) $(RTLOBJD)/Vcpuops__ALL.a -o $@
zipmmu_tb: zipmmu_tb.cpp $(VLIB) $(BENCHOBJD)/Vzipmmu_tb__ALL.a
- $(CXX) $(CFLAGS) $(INCS) -I$(BENCHOBJD) zipmmu_tb.cpp $(VLIB) $(BENCHOBJD)/Vzipmmu_tb__ALL.a -o $@
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) -I$(BENCHOBJD) zipmmu_tb.cpp $(VLIB) $(BENCHOBJD)/Vzipmmu_tb__ALL.a -o $@
pfcache_tb: $(OBJDIR)/pfcache_tb.o $(OBJDIR)/memsim.o $(OBJDIR)/byteswap.o
pfcache_tb: $(VLIB) $(RTLOBJD)/Vpfcache__ALL.a
- $(CXX) $(CFLAGS) $(INCS) -I$(RTLOBJD) $(OBJDIR)/pfcache_tb.o $(OBJDIR)/memsim.o $(OBJDIR)/byteswap.o $(VLIB) $(RTLOBJD)/Vpfcache__ALL.a -o $@
+ $(CXX) $(CFLAGS) $(VDEFS) $(INCS) -I$(RTLOBJD) $(OBJDIR)/pfcache_tb.o $(OBJDIR)/memsim.o $(OBJDIR)/byteswap.o $(VLIB) $(RTLOBJD)/Vpfcache__ALL.a -o $@
pdump: pdump.cpp $(ZOBJS) $(OBJDIR)/zopcodes.o $(OBJDIR)/pdump.o
pdump: $(ZASM)/zopcodes.h testb.h byteswap.h zipelf.h
@@ -166,26 +200,32 @@
$(CXX) $(CFLAGS) $(INCS) $(OBJDIR)/pdump.o $(ZOBJS) -lelf -o $@
.PHONY: stest
-stest: zippy_tb
- ./zippy_tb -s $(TESTF)
+stest: zipsys_tb
+ ./zipsys_tb -s $(TESTF)
.PHONY: itest
-itest: zippy_tb
- ./zippy_tb $(TESTF)
+itest: zipsys_tb
+ ./zipsys_tb $(TESTF)
.PHONY: test
-test: zippy_tb stest
- ./zippy_tb -a $(TESTF)
+test: zipsys_tb stest
+ ./zipsys_tb -a $(TESTF)
.PHONY: dhrystone
-dhrystone: zippy_tb
- ./zippy_tb -a $(DHRYSTONEF)
+dhrystone: zipsys_tb
+ ./zipsys_tb -a $(DHRYSTONEF)
define build-depends
@echo "Building dependencies"
- @$(CXX) $(CPPFLAGS) $(INCS) -MM $(VLIB) $(SOURCES) > $(OBJDIR)/xdepends.txt
+ $(mk-objdir)
+ @$(CXX) $(CPPFLAGS) $(INCS) -MM zipcpu_tb.cpp $(VLIB) $(SOURCES) > $(OBJDIR)/sysdepends.txt
+ @$(CXX) -DZIPBONES $(CPPFLAGS) $(INCS) -MM zipcpu_tb.cpp $(VLIB) $(SOURCES) > $(OBJDIR)/bondepends.txt
+ @sed -e 's/^zipcpu_tb.o: /zipsys_tb.o: /' < $(OBJDIR)/sysdepends.txt > $(OBJDIR)/xdepends.txt
+ @sed -e 's/^zipcpu_tb.o: /zipbones_tb.o: /' < $(OBJDIR)/bondepends.txt >> $(OBJDIR)/xdepends.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
@rm $(OBJDIR)/xdepends.txt
+ @rm $(OBJDIR)/sysdepends.txt
+ @rm $(OBJDIR)/bondepends.txt
endef
tags: $(VLIB) $(SOURCES)
@@ -195,8 +235,9 @@
depends: tags $(OBJDIR)/
$(build-depends)
-$(OBJDIR)/:
+define mk-objdir
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR)/; fi"
+endef
$(OBJDIR)/depends.txt: $(OBJDIR)/ depends
@@ -203,6 +244,7 @@
.PHONY: clean
clean:
rm -rf $(OBJDIR)/
- rm -rf ./zippy_tb pdump div_tb mpy_tb
+ rm -rf ./zipsys_tb ./zipbones_tb pdump div_tb mpy_tb
+ rm -rf pfcache_tb
-include $(OBJDIR)/depends.txt
/verilator/README.md
0,0 → 1,25
## The ZipCPU's Simulator |
|
This directory contains the basic ZipCPU simulator. |
|
Ok, even this isn't the *best* simulator of the ZipCPU. While this simulator |
*is* fully functional, it only simulates the |
[ZipCPU](../../rtl/core/zipcpu.v), encased in either the |
[ZipSystem](../../rtl/zipsystem.v) |
or the [ZipBones](../../rtl/zipbones.v), |
plus [memory](memsim.cpp). This simulator doesn't handle any interactions |
with the |
[flash](http://opencores.org/project,qspiflash), the |
[serial port](https://github.com/ZipCPU/wbuart32), the |
[SD-card](https://github.com/ZipCPU/sdspi), etc. All of these interactions |
(and more) are available from the |
[simulator](https://github.com/ZipCPU/zbasic/tree/master/sim/verilated) |
within the |
[ZBasic repository](https://github.com/ZipCPU/zbasic). |
|
However, this simulator *is* very basic to the CPU's functionality. If you |
just want to know if the CPU works by itself, if it can properly execute the |
instructions given to it--even to the point of testing |
interrupts etc, then this simulation will work. It's just not fully |
functional for testing all of the other peripheral components necessary |
to make a CPU useful. |
/verilator/div_tb.cpp
1,4 → 1,4
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: div_tb.cpp |
// |
10,7 → 10,7
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
24,11 → 24,16
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <signal.h> |
42,6 → 47,22
#include "verilated.h" |
#include "Vdiv.h" |
|
#ifdef NEW_VERILATOR |
#define VVAR(A) div__DOT_ ## A |
#else |
#define VVAR(A) v__DOT_ ## A |
#endif |
|
#define r_busy VVAR(_r_busy) |
#define pre_sign VVAR(_pre_sign) |
#define r_sign VVAR(_r_sign) |
#define r_z VVAR(_r_z) |
#define r_bit VVAR(_r_bit) |
#define last_bit VVAR(_last_bit) |
#define r_dividend VVAR(_r_dividend) |
#define r_divisor VVAR(_r_divisor) |
#define vdiff VVAR(_diff) |
|
#include "testb.h" |
// #include "twoc.h" |
|
74,30 → 95,30
|
void dbgdump(void) { |
char outstr[2048], *s; |
sprintf(outstr, "Tick %4ld %s%s%s%s%s%s%s %2d(%s= 0)", |
m_tickcount, |
sprintf(outstr, "Tick %4lld %s%s%s%s%s%s%s %2d(%s= 0)", |
(unsigned long long)m_tickcount, |
(m_core->o_busy)?"B":" ", |
(m_core->v__DOT__r_busy)?"R":" ", |
(m_core->r_busy)?"R":" ", |
(m_core->o_valid)?"V":" ", |
(m_core->i_wr)?"W":" ", |
(m_core->v__DOT__pre_sign)?"+":" ", |
(m_core->v__DOT__r_sign)?"-":" ", |
(m_core->v__DOT__r_z)?"Z":" ", |
m_core->v__DOT__r_bit, |
(m_core->v__DOT__last_bit)?"=":"!"); |
(m_core->pre_sign)?"+":" ", |
(m_core->r_sign)?"-":" ", |
(m_core->r_z)?"Z":" ", |
m_core->r_bit, |
(m_core->last_bit)?"=":"!"); |
s = &outstr[strlen(outstr)]; |
sprintf(s, "%s\n%10s %40s",s, "Div",""); |
s = &s[strlen(s)]; |
bprint( s, 32, m_core->v__DOT__r_dividend); |
bprint( s, 32, m_core->r_dividend); |
s=&s[strlen(s)]; |
sprintf(s, "%s\n%10s ",s, "Div"); s = &s[strlen(s)]; |
bprint( s, 64, m_core->v__DOT__r_divisor); |
bprint( s, 64, m_core->r_divisor); |
s=&s[strlen(s)]; |
sprintf(s, "%s\n%10s %40s",s, "Q",""); s=&s[strlen(s)]; |
bprint( s, 32, m_core->o_quotient); s = &s[strlen(s)]; |
sprintf(s, "%s\n%10s %38s",s, "Diff",""); |
s=&s[strlen(s)]; |
bprint( s, 33, m_core->v__DOT__diff); s = &s[strlen(s)]; |
bprint( s, 33, m_core->vdiff); s = &s[strlen(s)]; |
strcat(s, "\n"); |
puts(outstr); |
} |
118,7 → 139,7
DIVASSERT(m_core->o_busy == 0); |
|
// Request a divide |
m_core->i_rst = 0; |
m_core->i_reset = 0; |
m_core->i_wr = 1; |
m_core->i_signed = (issigned)?1:0; |
m_core->i_numerator = n; |
/verilator/memsim.h
6,8 → 6,7
// |
// Purpose: This creates a memory like device to act on a WISHBONE bus. |
// It doesn't exercise the bus thoroughly, but does give some |
// exercise to the bus to see whether or not the bus master |
// can control it. |
// exercise to the bus to see whether or not the bus master can control it. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
28,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
/verilator/mpy_tb.cpp
1,4 → 1,4
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: mpy_tb.cpp |
// |
12,7 → 12,7
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
26,11 → 26,16
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <signal.h> |
37,6 → 42,7
#include <time.h> |
#include <unistd.h> |
#include <assert.h> |
#include <stdint.h> |
|
#include <stdlib.h> |
#include <ctype.h> |
44,6 → 50,13
#include "verilated.h" |
#include "Vcpuops.h" |
|
#ifdef NEW_VERILATOR |
#define VVAR(A) cpuops__DOT_ ## A |
#else |
#define VVAR(A) v__DOT_ ## A |
#endif |
|
|
#include "testb.h" |
#include "cpudefs.h" |
// #include "twoc.h" |
56,12 → 69,12
// ~CPUOPS_TB(void) {} |
|
// |
// Calls TESTB<>::reset to reset the core. Makes sure the i_ce line |
// Calls TESTB<>::reset to reset the core. Makes sure the i_stb line |
// is low during this reset. |
// |
void reset(void) { |
// m_flash.debug(false); |
m_core->i_ce = 0; |
m_core->i_stb = 0; |
|
TESTB<Vcpuops>::reset(); |
} |
80,10 → 93,10
// |
void dbgdump(void) { |
char outstr[2048], *s; |
sprintf(outstr, "Tick %4ld %s%s ", |
m_tickcount, |
(m_core->i_rst)?"R":" ", |
(m_core->i_ce)?"CE":" "); |
sprintf(outstr, "Tick %4lld %s%s ", |
(unsigned long long)m_tickcount, |
(m_core->i_reset)?"R":" ", |
(m_core->i_stb)?"CE":" "); |
switch(m_core->i_op) { |
case 0: strcat(outstr, " SUB"); break; |
case 1: strcat(outstr, " AND"); break; |
112,26 → 125,37
s = &outstr[strlen(outstr)]; |
|
#if(OPT_MULTIPLY==1) |
#define mpy_result VVAR(_mpy_result) |
sprintf(s, "1,MPY[][][%016lx]", |
m_core->v__DOT__mpy_result); |
(unsigned long)m_core->mpy_result); |
s = &outstr[strlen(outstr)]; |
#elif(OPT_MULTIPLY==2) |
sprintf(s, "2,MPY[%016lx][%016lx][%016lx]", |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_a_input, |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_b_input, |
m_core->v__DOT__mpy_result); |
#define MPY2VAR(A) VVAR(_thempy__DOT__IMPY__DOT__MPN1__DOT__MPY2CK__DOT_ ## A) |
#define r_mpy_a_input MPY2VAR(_r_mpy_a_input) |
#define r_mpy_b_input MPY2VAR(_r_mpy_b_input) |
#define mpy_result VVAR(_mpy_result) |
m_core->r_mpy_a_input, |
m_core->r_mpy_b_input, |
m_core->mpy_result); |
s = &outstr[strlen(outstr)]; |
#elif(OPT_MULTIPLY==3) |
sprintf(s, "3,MPY[%08x][%08x][%016lx], P[%d]", |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_a_input, |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_mpy_b_input, |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__r_smpy_result, |
m_core->v__DOT__genblk2__DOT__genblk2__DOT__genblk2__DOT__genblk1__DOT__mpypipe); |
#define MPY3VAR(A) VVAR(_thempy__DOT__IMPY__DOT__MPN1__DOT__MPN2__DOT__MPY3CK__DOT_ ## A) |
#define r_mpy_a_input MPY3VAR(_r_mpy_a_input) |
#define r_mpy_b_input MPY3VAR(_r_mpy_b_input) |
#define r_smpy_result MPY3VAR(_r_smpy_result) |
#define mpypipe MPY3VAR(_mpypipe) |
sprintf(s, "3,MPY[%08x][%08x][%016llx], P[%d]", |
m_core->r_mpy_a_input, |
m_core->r_mpy_b_input, |
(long long)m_core->r_smpy_result, |
m_core->mpypipe); |
|
#endif |
|
#if(OPT_MULTIPLY != 1) |
if (m_core->v__DOT__this_is_a_multiply_op) |
#define this_is_a_multiply_op ((m_core->i_stb)&&(((m_core->i_op&0xe) == 5)||((m_core->i_op&0x0f)==0xc))) // VVAR(_this_is_a_multiply_op) |
if (this_is_a_multiply_op) |
strcat(s, " MPY-OP"); |
#endif |
puts(outstr); |
170,7 → 194,7
// we tick things once more. |
// |
void clear_ops(void) { |
m_core->i_ce = 0; |
m_core->i_stb = 0; |
m_core->i_op = 0; |
|
do { |
189,7 → 213,7
// the CPU may need to do that if a jump is made and the pipeline needs |
// to be cleared. |
// |
unsigned op(int op, int a, int b) { |
uint32_t op(int op, int a, int b) { |
// Make sure we start witht he core idle |
if (m_core->o_valid) |
clear_ops(); |
196,18 → 220,18
|
// Set the arguments to the CPUOPS core to get a multiple |
// started |
m_core->i_ce = 1; |
m_core->i_stb = 1; |
m_core->i_op = op; |
m_core->i_a = a; |
m_core->i_b = b; |
|
unsigned long now = m_tickcount; |
uint64_t now = m_tickcount; |
|
// Tick once to get it going |
tick(); |
|
// Clear the input arguments to the multiply |
m_core->i_ce = 0; |
m_core->i_stb = 0; |
m_core->i_a = 0; |
m_core->i_b = 0; |
|
219,8 → 243,8
// be using. OPT_MULTIPLY is *supposed* to be equal to this |
// number. |
if((m_tickcount - now)!=OPT_MULTIPLY) { |
printf("%ld ticks seen, %d ticks expected\n", |
m_tickcount-now, OPT_MULTIPLY); |
printf("%lld ticks seen, %d ticks expected\n", |
(unsigned long long)(m_tickcount-now), OPT_MULTIPLY); |
dbgdump(); |
printf("TEST-FAILURE!\n"); |
closetrace(); |
240,18 → 264,20
// against a local multiply on the local (host) machine. If there's |
// any mismatch, an error message is printed and the test fails. |
void mpy_test(int a, int b) { |
const int OP_MPY = 0x08, OP_MPYSHI=0xb, OP_MPYUHI=0x0a; |
long ia, ib, sv; |
unsigned long ua, ub, uv; |
const int OP_MPY = 0x0c, OP_MPYSHI=0xb, OP_MPYUHI=0x0a; |
const bool debug = false; |
int64_t ia, ib, sv; |
uint64_t ua, ub, uv; |
unsigned r, s, u; |
|
clear_ops(); |
|
if (debug) |
printf("MPY-TEST: 0x%08x x 0x%08x\n", a, b); |
|
ia = (long)a; ib = (long)b; sv = ia * ib; |
ua = ((unsigned long)a)&0x0ffffffffu; |
ub = ((unsigned long)b)&0x0ffffffffu; |
ua = ((uint64_t)a)&0x0ffffffffu; |
ub = ((uint64_t)b)&0x0ffffffffu; |
uv = ua * ub; |
|
r = op(OP_MPY, a, b); |
262,13 → 288,13
// Let's check our answers, and see if we got the right results |
if ((r ^ sv)&0x0ffffffffu) { |
printf("TEST FAILURE(MPY), MPY #1\n"); |
printf("Comparing 0x%08x to 0x%016lx\n", r, sv); |
printf("Comparing 0x%08x to 0x%016llx\n", r, (long long)sv); |
printf("TEST-FAILURE!\n"); |
closetrace(); |
exit(EXIT_FAILURE); |
} if ((r ^ uv)&0x0ffffffffu) { |
printf("TEST FAILURE(MPY), MPY #2\n"); |
printf("Comparing 0x%08x to 0x%016lx\n", r, uv); |
printf("Comparing 0x%08x to 0x%016llx\n", r, (unsigned long long)uv); |
printf("TEST-FAILURE!\n"); |
closetrace(); |
exit(EXIT_FAILURE); |
276,13 → 302,13
|
if ((s^(sv>>32))&0x0ffffffffu) { |
printf("TEST FAILURE(MPYSHI), MPY #3\n"); |
printf("Comparing 0x%08x to 0x%016lx\n", s, sv); |
printf("Comparing 0x%08x to 0x%016llx\n", s, (long long)sv); |
printf("TEST-FAILURE!\n"); |
closetrace(); |
exit(EXIT_FAILURE); |
} if ((u^(uv>>32))&0x0ffffffffu) { |
printf("TEST FAILURE(MPYUHI), MPY #4\n"); |
printf("Comparing 0x%08x to 0x%016lx\n", u, uv); |
printf("Comparing 0x%08x to 0x%016llx\n", u, (unsigned long long)uv); |
printf("TEST-FAILURE!\n"); |
closetrace(); |
exit(EXIT_FAILURE); |
/verilator/pdump.cpp
2,7 → 2,7
// |
// Filename: pdump.cpp |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU core |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Disassemble machine code files onto the stdout file. Unlike |
// the zip-objdump program that is part of the binutils suite, this |
29,7 → 29,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
38,7 → 38,10
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <algorithm> |
#include <map> |
#include <stdio.h> |
#include <unistd.h> |
#include <ctype.h> |
54,58 → 57,43
return a.clks < b.clks; |
} |
|
typedef struct { unsigned clks, hits, addr; } insn_stat; |
|
typedef std::map<unsigned, insn_stat *> vcd_profile; |
|
void dump_file(const char *fn) { |
const int NZIP = 4096; |
char lna[NZIP], lnb[NZIP]; |
FILE *pf; |
unsigned addr=0x0100000, mina = -1, maxa = 0, |
*pfcnt = NULL, *pfclk = NULL; |
unsigned addr=0x0100000; |
vcd_profile vp; |
|
pf = fopen("pfile.bin","rb"); |
if (pf) { |
ALT *pfalt; |
unsigned buf[2], total_clks = 0; |
unsigned buf[2]; |
while(2 == fread(buf, sizeof(unsigned), 2, pf)) { |
if (mina > buf[0]) |
mina = buf[0]; |
if (maxa < buf[0]) |
maxa = buf[0]; |
addr = buf[0]; |
if (vp.count(addr)>0) { |
vp[addr]->hits++; |
vp[addr]->clks += buf[1]; |
} else { |
insn_stat *is; |
|
is = new insn_stat; |
is->hits = 1; |
is->clks = buf[1]; |
is->addr = addr; |
vp[addr] = is; |
} |
} |
|
addr = mina; |
pfcnt = new unsigned[(maxa+2-mina)]; |
pfclk = new unsigned[(maxa+2-mina)]; |
pfalt = new ALT[(maxa+2-mina)]; |
unsigned ncnt = maxa+2-mina; |
for(int i=0; i<(int)ncnt; i++) |
pfcnt[i] = pfclk[i] = 0; |
for(int i=0; i<(int)ncnt; i++) |
pfalt[i].addr = pfalt[i].clks = 0; |
|
rewind(pf); |
while(2 == fread(buf, sizeof(unsigned), 2, pf)) { |
pfcnt[buf[0]-addr]++; |
pfclk[buf[0]-addr] += buf[1]; |
pfalt[buf[0]-addr].clks += buf[1]; |
pfalt[buf[0]-addr].addr = buf[0]; |
total_clks += buf[1]; |
|
printf("%08x\n", buf[0]); |
} fclose(pf); |
|
printf("%08x (%8d) total clocks\n", total_clks, total_clks); |
|
std::sort(&pfalt[0], &pfalt[ncnt], altcmp); |
|
for(int i=0; i<(int)ncnt; i++) |
printf("%08x: %8d\n", pfalt[i].addr, pfalt[i].clks); |
} |
|
printf("%s:\n", fn); |
if (iself(fn)) { |
ELFSECTION **secpp=NULL, *secp; |
unsigned entry; |
double cpi; |
unsigned entry; |
|
elfread(fn, entry, secpp); |
for(int i=0; secpp[i]->m_len; i++) { |
secp = secpp[i]; |
112,22 → 100,27
for(unsigned j=0; j<secp->m_len; j+=4) { |
uint32_t w, a; |
|
a = secp->m_start+(j<<2); |
w = buildword((const unsigned char *)&secp->m_data[(j<<2)]); |
a = secp->m_vaddr+j; |
w = buildword((const unsigned char *)&secp->m_data[j]); |
zipi_to_double_string(a, w, lna, lnb); |
// printf("%s\n", ln); |
printf("%08x[%08x-%08x]: (0x%08x %c%c%c%c) ", |
a, maxa, mina, w, |
printf("%08x: (0x%08x %c%c%c%c) ", a, w, |
isgraph((w>>24)&0x0ff)?((w>>24)&0x0ff) : '.', |
isgraph((w>>16)&0x0ff)?((w>>16)&0x0ff) : '.', |
isgraph((w>> 8)&0x0ff)?((w>> 8)&0x0ff) : '.', |
isgraph((w )&0x0ff)?((w )&0x0ff) : '.' |
); |
if ((a>=mina)&&(a<maxa)&&(pfcnt)) |
printf("%8d %8d ", pfcnt[a-mina], pfclk[a-mina]); |
if (vp.count(a)>0) { |
insn_stat *is = vp[a]; |
cpi = is->clks / (double)is->hits; |
|
printf("%8d %8d %4.1f ", is->hits, is->clks, cpi); |
} else |
printf("%23s", ""); |
|
printf("%s\n", lna); |
if (lnb[0]) |
printf("-%24s%s\n", "", lnb); |
printf("-%50s%s\n", "", lnb); |
} |
} |
} |
/verilator/pfcache_tb.cpp
1,4 → 1,4
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: pfcache_tb.cpp |
// |
12,7 → 12,7
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2017, Gisselquist Technology, LLC |
// |
26,11 → 26,16
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <signal.h> |
74,8 → 79,8
// is low during this reset. |
// |
void reset(void) { |
m_core->i_rst = 0; |
m_core->i_pc = RAMBASE; |
m_core->i_reset = 0; |
m_core->i_pc = RAMBASE<<2; |
m_core->i_new_pc = 0; |
m_core->i_clear_cache = 1; |
m_core->i_stall_n = 1; |
139,16 → 144,16
|
TESTB<Vpfcache>::tick(); |
|
if (m_core->o_v) { |
if (m_core->o_valid) { |
uint32_t pc, insn; |
|
pc = m_core->o_pc; |
insn = m_core->o_i; |
if (insn != m_mem[pc & (RAMWORDS-1)]) { |
insn = m_core->o_insn; |
if (insn != m_mem[(pc>>2) & (RAMWORDS-1)]) { |
fprintf(stderr, "ERR: PF[%08x] = %08x != %08x\n", pc, |
insn, m_mem[pc & (RAMWORDS-1)]); |
insn, m_mem[(pc>>2) & (RAMWORDS-1)]); |
closetrace(); |
assert(insn == m_mem[pc & (RAMWORDS-1)]); |
assert(insn == m_mem[(pc>>2) & (RAMWORDS-1)]); |
} |
} |
} |
159,16 → 164,16
void fetch_insn(void) { |
uint32_t timeout = 0; |
|
if ((m_core->o_v)&&(m_core->i_stall_n)) |
if ((m_core->o_valid)&&(m_core->i_stall_n)) |
m_core->i_pc++; |
|
m_core->i_rst = 0; |
m_core->i_reset = 0; |
m_core->i_new_pc = 0; |
m_core->i_clear_cache = 0; |
m_core->i_stall_n = 1; |
do { |
tick(); |
} while((!m_core->o_v)&&(!m_core->o_illegal)&&(timeout++ < MAXTIMEOUT)); |
} while((!m_core->o_valid)&&(!m_core->o_illegal)&&(timeout++ < MAXTIMEOUT)); |
|
if (timeout >= MAXTIMEOUT) |
m_bomb = true; |
180,28 → 185,28
void skip_fetch(void) { |
uint32_t prevalid, insn; |
|
if ((m_core->o_v)&&(m_core->i_stall_n)) |
if ((m_core->o_valid)&&(m_core->i_stall_n)) |
m_core->i_pc++; |
|
m_core->i_rst = 0; |
m_core->i_reset = 0; |
m_core->i_new_pc = 0; |
m_core->i_clear_cache = 0; |
m_core->i_stall_n = 0; |
insn = m_core->o_i; |
prevalid= m_core->o_v; |
insn = m_core->o_insn; |
prevalid= m_core->o_valid; |
|
tick(); |
|
if (prevalid) { |
// if (!m_core->o_v) { |
// if (!m_core->o_valid) { |
// fprintf(stderr, "ERR: VALID dropped on stall!\n"); |
// closetrace(); |
// assert(m_core->o_v); |
// assert(m_core->o_valid); |
// } |
if (insn != m_core->o_i) { |
if (insn != m_core->o_insn) { |
fprintf(stderr, "ERR: VALID INSN CHANGED on stall!\n"); |
closetrace(); |
assert(insn == m_core->o_i); |
assert(insn == m_core->o_insn); |
} |
} |
} |
213,7 → 218,7
void jump(unsigned target) { |
uint32_t timeout = 0; |
|
m_core->i_rst = 0; |
m_core->i_reset = 0; |
m_core->i_new_pc = 1; |
m_core->i_clear_cache = 0; |
m_core->i_stall_n = 1; |
224,12 → 229,12
m_core->i_new_pc = 0; |
m_core->i_stall_n = 0; |
|
while((!m_core->o_v)&&(timeout++ < MAXTIMEOUT)) |
while((!m_core->o_valid)&&(timeout++ < MAXTIMEOUT)) |
tick(); |
|
if (timeout >= MAXTIMEOUT) |
m_bomb = true; |
if (m_core->o_v) |
if (m_core->o_valid) |
assert(m_core->o_pc == target); |
} |
}; |
249,7 → 254,7
tb->opentrace("pfcache.vcd"); |
tb->randomize_memory(); |
|
tb->jump(RAMBASE); |
tb->jump(RAMBASE<<2); |
|
// Simulate running straight through code |
for(int i=0; i<130; i++) { |
259,7 → 264,7
|
// Now, let's bounce around through the cache |
for(int j=0; j<20; j++) { |
tb->jump(RAMBASE+j); |
tb->jump((RAMBASE+j)<<2); |
for(int i=0; i<130; i++) { |
// printf("FETCH\n"); |
tb->fetch_insn(); |
298,7 → 303,7
uint32_t target = rand() & (RAMWORDS-1); |
target += RAMBASE; |
// printf("JUMP TO %08x\n", target); |
tb->jump(target); |
tb->jump(target<<2); |
} else if ((v & 3)==2) { |
// printf("SKIP\n"); |
tb->skip_fetch(); |
/verilator/testb.h
2,7 → 2,7
// |
// Filename: testb.h |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU core |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: A wrapper for a common interface to a clocked FPGA core |
// begin exercised in Verilator. |
34,6 → 34,8
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef TESTB_H |
#define TESTB_H |
|
41,11 → 43,13
#include <stdint.h> |
#include <verilated_vcd_c.h> |
|
#define TBASSERT(TB,A) do { if (!(A)) { (TB).closetrace(); } assert(A); } while(0); |
|
template <class VA> class TESTB { |
public: |
VA *m_core; |
VA *m_core; |
VerilatedVcdC* m_trace; |
unsigned long m_tickcount; |
uint64_t m_tickcount; |
|
TESTB(void) : m_trace(NULL), m_tickcount(0l) { |
m_core = new VA; |
54,7 → 58,7
eval(); // Get our initial values set properly. |
} |
virtual ~TESTB(void) { |
if (m_trace) m_trace->close(); |
closetrace(); |
delete m_core; |
m_core = NULL; |
} |
70,6 → 74,7
virtual void closetrace(void) { |
if (m_trace) { |
m_trace->close(); |
delete m_trace; |
m_trace = NULL; |
} |
} |
87,22 → 92,28
// logic depends. This forces that logic to be recalculated |
// before the top of the clock. |
eval(); |
if (m_trace) m_trace->dump(10*m_tickcount-2); |
if (m_trace) m_trace->dump((vluint64_t)(10*m_tickcount-2)); |
m_core->i_clk = 1; |
eval(); |
if (m_trace) m_trace->dump(10*m_tickcount); |
if (m_trace) m_trace->dump((vluint64_t)(10*m_tickcount)); |
m_core->i_clk = 0; |
eval(); |
if (m_trace) m_trace->dump(10*m_tickcount+5); |
|
if (m_trace) { |
m_trace->dump((vluint64_t)(10*m_tickcount+5)); |
m_trace->flush(); |
} |
} |
|
virtual void reset(void) { |
m_core->i_rst = 1; |
m_core->i_reset = 1; |
tick(); |
m_core->i_rst = 0; |
m_core->i_reset = 0; |
// printf("RESET\n"); |
} |
|
unsigned long tickcount(void) { |
return m_tickcount; |
} |
}; |
|
#endif |
/verilator/twoc.cpp
1,20 → 1,20
//////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: twoc.cpp |
// |
// Project: A Doubletime Pipelined FFT |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Some various two's complement related C++ helper routines. |
// Specifically, these help extract signed numbers from |
// packed bitfields, while guaranteeing that the upper bits |
// are properly sign extended (or not) as desired. |
// packed bitfields, while guaranteeing that the upper bits are properly |
// sign extended (or not) as desired. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
27,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
35,7 → 35,9
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include "twoc.h" |
|
long sbits(const long val, const int bits) { |
/verilator/twoc.h
1,8 → 1,8
//////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: twoc.h |
// |
// Project: A Doubletime Pipelined FFT |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Some various two's complement related C++ helper routines. |
// Specifically, these help extract signed numbers from |
12,9 → 12,9
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
27,7 → 27,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
35,7 → 35,9
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef TWOC_H |
#define TWOC_H |
|
/verilator/vversion.sh
0,0 → 1,65
#!/bin/bash |
################################################################################ |
## |
## Filename: vversion.sh |
## |
## Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
## |
## Purpose: To determine whether or not the verilator prefix for internal |
## variables is v__DOT__ or the name of the top level followed by |
## __DOT__. If it is the later, output -DNEW_VERILATOR, else be silent. |
## |
## |
## Creator: Dan Gisselquist, Ph.D. |
## Gisselquist Technology, LLC |
## |
################################################################################ |
## |
## Copyright (C) 2017, Gisselquist Technology, LLC |
## |
## This program is free software (firmware): you can redistribute it and/or |
## modify it under the terms of the GNU General Public License as published |
## by the Free Software Foundation, either version 3 of the License, or (at |
## your option) any later version. |
## |
## This program is distributed in the hope that it will be useful, but WITHOUT |
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
## for more details. |
## |
## You should have received a copy of the GNU General Public License along |
## with this program. (It's in the $(ROOT)/doc directory. Run make with no |
## target there if the PDF file isn't present.) If not, see |
## <http://www.gnu.org/licenses/> for a copy. |
## |
## License: GPL, v3, as defined and found on www.gnu.org, |
## http://www.gnu.org/licenses/gpl.html |
## |
## |
################################################################################ |
## |
## |
if [[ -x ${VERILATOR_ROOT}/bin/verilator ]]; |
then |
export VERILATOR=${VERILATOR_ROOT}/bin/verilator |
fi |
if [[ ! -x ${VERILATOR} ]]; |
then |
export VERILATOR=verilator |
fi |
if [[ ! -x `which ${VERILATOR}` ]]; |
then |
echo "Verilator not found in environment or in path" |
exit -1 |
fi |
|
VVERLINE=`${VERILATOR} -V | grep -i ^Verilator` |
VVER=`echo ${VVERLINE} | cut -d " " -f 2` |
LATER=`echo $VVER \>= 3.9 | bc` |
if [[ $LATER > 0 ]]; |
then |
echo "-DNEW_VERILATOR" |
else |
echo "-DOLD_VERILATOR" |
fi |
exit 0 |
verilator/vversion.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: verilator/zipcpu_tb.cpp
===================================================================
--- verilator/zipcpu_tb.cpp (nonexistent)
+++ verilator/zipcpu_tb.cpp (revision 209)
@@ -0,0 +1,2692 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Filename: zipcpu_tb.cpp
+//
+// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
+//
+// Purpose: A bench simulator for the CPU. Eventually, you should be
+// able to give this program the name of a piece of compiled
+// code to load into memory. For now, we hand assemble with the computers
+// help.
+//
+//
+// Creator: Dan Gisselquist, Ph.D.
+// Gisselquist Technology, LLC
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2015-2018, Gisselquist Technology, LLC
+//
+// This program is free software (firmware): you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or (at
+// your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. (It's in the $(ROOT)/doc directory. Run make with no
+// target there if the PDF file isn't present.) If not, see
+// for a copy.
+//
+// License: GPL, v3, as defined and found on www.gnu.org,
+// http://www.gnu.org/licenses/gpl.html
+//
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "verilated.h"
+#include "verilated_vcd_c.h"
+
+#ifdef ZIPBONES
+#include "Vzipbones.h"
+#define SIMCLASS Vzipbones
+#else
+#define ZIPSYSTEM
+#include "Vzipsystem.h"
+#define SIMCLASS Vzipsystem
+#endif
+
+#include "cpudefs.h"
+
+#include "testb.h"
+#include "zipelf.h"
+// #include "twoc.h"
+// #include "qspiflashsim.h"
+#include "byteswap.h"
+#include "memsim.h"
+#include "zopcodes.h"
+
+#define CMD_REG 0
+#define CMD_DATA 4
+#define CMD_GO 0
+#define CMD_GIE (1<<13)
+#define CMD_SLEEP (1<<12)
+#define CMD_CLEAR_CACHE (1<<11)
+#define CMD_HALT (1<<10)
+#define CMD_STALL (1<<9)
+#define CMD_INT (1<<7)
+#define CMD_RESET (1<<6)
+#define CMD_STEP ((1<<8)|CMD_HALT)
+#define CPU_HALT CMD_HALT
+#define CPU_sPC 15
+
+#define KEY_ESCAPE 27
+#define KEY_RETURN 10
+#define CTRL(X) ((X)&0x01f)
+
+#define MAXERR 10000
+
+
+// Some versions of Verilator require a prefix starting with the top level
+// module name, rather than v__DOT__.... For these versions of Verilator,
+// you will need to replace these variable prefixes with either
+// zipsystem__DOT__...
+// or
+// zipbones__DOT__...
+
+#ifdef NEW_VERILATOR
+#ifdef ZIPBONES
+#define VVAR(A) zipbones__DOT_ ## A
+#else
+#define VVAR(A) zipsystem__DOT_ ## A
+#endif
+#else
+#define VVAR(A) v__DOT_ ## A
+#endif
+
+#define CPUVAR(A) VVAR(_thecpu__DOT_ ##A)
+
+#ifdef OPT_DCACHE
+///
+ // dcache
+ #define MEMVAR(A) CPUVAR(_MEM_DCACHE__DOT__docache__DOT_ ## A)
+///
+#elif defined(OPT_PIPELINED_BUS_ACCESS)
+///
+ // pipemem
+ #define MEMVAR(A) CPUVAR(_NO_CACHE__DOT__MEM__DOT__domem__DOT_ ## A)
+ #define mem_wraddr MEMVAR(_wraddr)
+ #define mem_rdaddr MEMVAR(_rdaddr)
+///
+#else
+///
+ // memops
+ #define MEMVAR(A) CPUVAR(_NO_CACHE__DOT__MEM__DOT__domem__DOT_ ## A)
+#endif
+
+#define cpu_halt VVAR(_cmd_halt)
+#define cmd_reset VVAR(_cmd_reset)
+#define cmd_step VVAR(_cmd_step)
+#define cmd_addr VVAR(_cmd_addr)
+
+#ifdef OPT_SINGLE_FETCH
+#define early_branch VVAR(_thecpu__DOT__instruction_decoder__DOT__GEN_EARLY_BRANCH_LOGIC__DOT__r_early_branch)
+#else
+#define early_branch VVAR(_thecpu__DOT__instruction_decoder__DOT__GEN_EARLY_BRANCH_LOGIC__DOT__r_early_branch)
+#endif
+#define early_branch_pc VVAR(_thecpu__DOT__instruction_decoder__DOT__GEN_EARLY_BRANCH_LOGIC__DOT__r_branch_pc)
+
+#define dcdRmx VVAR(_thecpu__DOT____Vcellout__instruction_decoder____pinNumber15)
+#define dcdA VVAR(_thecpu__DOT____Vcellout__instruction_decoder____pinNumber15)
+#define dcdB VVAR(_thecpu__DOT____Vcellout__instruction_decoder____pinNumber16)
+
+#define new_pc VVAR(_thecpu__DOT__new_pc)
+#define cpu_ipc VVAR(_thecpu__DOT__ipc)
+#define cpu_upc VVAR(_thecpu__DOT__SET_USER_PC__DOT__r_upc)
+#define pf_pc VVAR(_thecpu__DOT__pf_pc)
+
+// PF
+#define pf_cyc VVAR(_thecpu__DOT__pf_cyc)
+#define pf_stb VVAR(_thecpu__DOT__pf_stb)
+#define pf_we VVAR(_thecpu__DOT__pf_we)
+#define pf_addr VVAR(_thecpu__DOT__pf_addr)
+#define pf_ack VVAR(_thecpu__DOT__pf_ack)
+#define pf_valid VVAR(_thecpu__DOT__pf_valid)
+#define pf_illegal VVAR(_thecpu__DOT__pf_illegal)
+#define pf_vmask VVAR(_thecpu__DOT__pf__DOT__valid_mask)
+#define pf_r_v VVAR(_thecpu__DOT__pf__DOT__r_v)
+// #define pf_illegal VVAR(_thecpu__DOT__pf__DOT__pf_illegal)
+#define pf_tagsrc VVAR(_thecpu__DOT__pf__DOT__rvsrc)
+#define pf_tagipc VVAR(_thecpu__DOT__pf__DOT__tagvalipc)
+#define pf_tagvallst VVAR(_thecpu__DOT__pf__DOT__tagvallst)
+#define pf_lastpc VVAR(_thecpu__DOT__pf__DOT__lastpc)
+#define pf_instruction VVAR(_thecpu__DOT__pf_instruction)
+
+// Decode
+#ifdef OPT_PIPELINED
+#define dcd_ce VVAR(_thecpu__DOT__dcd_ce)
+#else
+#define dcd_ce VVAR(_thecpu__DOT__dcd_stalled)^1
+#endif
+#define dcd_stalled VVAR(_thecpu__DOT__dcd_stalled)
+#define dcd_gie VVAR(_thecpu__DOT__SET_GIE__DOT__r_gie)
+#define dcd_illegal VVAR(_thecpu__DOT__dcd_illegal)
+#define dcd_valid VVAR(_thecpu__DOT__instruction_decoder__DOT__r_valid)
+#define dcd_opn VVAR(_thecpu__DOT__dcd_opn)
+#define dcd_rA VVAR(_thecpu__DOT__dcd_rA)
+#define dcd_rB VVAR(_thecpu__DOT__dcd_rB)
+#define dcdR VVAR(_thecpu__DOT__instruction_decoder__DOT__w_dcdR)
+#define dcdRpc VVAR(_thecpu__DOT__instruction_decoder__DOT__w_dcdR_pc)
+#define dcdRcc VVAR(_thecpu__DOT__instruction_decoder__DOT__w_dcdR_cc)
+#define dcd_wR VVAR(_thecpu__DOT__dcd_wR)
+#define dcd_pc VVAR(_thecpu__DOT__dcd_pc)
+#define dcd_wF VVAR(_thecpu__DOT__dcd_wF)
+#define dcd_M VVAR(_thecpu__DOT__dcd_M)
+
+// Op
+#define op_ce VVAR(_thecpu__DOT__op_ce)
+#define op_illegal VVAR(_thecpu__DOT__op_illegal)
+#define op_valid VVAR(_thecpu__DOT__op_valid)
+#define op_valid_mem VVAR(_thecpu__DOT__op_valid_mem)
+#define op_valid_alu VVAR(_thecpu__DOT__op_valid_alu)
+#ifdef OPT_PIPELINED
+#define op_R VVAR(_thecpu__DOT__op_R)
+#define op_stall VVAR(_thecpu__DOT__op_stall)
+#else
+#define op_R dcdR
+#endif
+#define op_wR VVAR(_thecpu__DOT__op_wR)
+#define op_wF VVAR(_thecpu__DOT__op_wF)
+
+#define master_stall VVAR(_thecpu__DOT__master_stall)
+// ALU
+#define alu_ce VVAR(_thecpu__DOT__alu_ce)
+#define alu_valid VVAR(_thecpu__DOT__alu_valid)
+// #define alu_stall VVAR(_thecpu__DOT__alu_stall)
+#define alu_wF VVAR(_thecpu__DOT__alu_wF)
+#define alu_pc_valid VVAR(_thecpu__DOT__alu_pc_valid)
+#define alu_flags VVAR(_thecpu__DOT__alu_flags)
+#define alu_wR VVAR(_thecpu__DOT__alu_wR)
+#ifdef OPT_PIPELINED
+#define alu_illegal VVAR(_thecpu__DOT__SET_ALU_ILLEGAL__DOT__r_alu_illegal)
+#else
+#define alu_illegal op_illegal
+#endif
+#define set_cond VVAR(_thecpu__DOT__set_cond)
+
+// MEM
+#define mem_valid CPUVAR(_mem_valid)
+#define mem_pc_valid CPUVAR(_mem_pc_valid)
+#define mem_ce CPUVAR(_mem_ce)
+#define mem_cyc MEMVAR(_cyc)
+#define mem_rdbusy CPUVAR(_mem_rdbusy)
+#define mem_wreg CPUVAR(_mem_wreg)
+
+// DIV
+#ifdef OPT_DIVIDE
+ #define div_valid CPUVAR(_div_valid)
+ #define div_ce CPUVAR(_div_ce)
+ #define div_busy CPUVAR(_div_busy)
+#endif
+
+//
+#define wr_reg_id CPUVAR(_wr_reg_id)
+#define wr_reg_ce CPUVAR(_wr_reg_ce)
+#define wr_gpreg_vl CPUVAR(_wr_gpreg_vl)
+#ifdef OPT_DIVIDE
+#define wr_spreg_vl CPUVAR(_wr_spreg_vl)
+#else
+#define wr_spreg_vl wr_gpreg_vl
+#endif
+#define wr_reg_ce CPUVAR(_wr_reg_ce)
+#define wr_flags_ce CPUVAR(_wr_flags_ce)
+#define w_iflags CPUVAR(_w_iflags)
+#define w_uflags CPUVAR(_w_uflags)
+
+// Op-Sim instructions
+#define cpu_sim VVAR(_thecpu__DOT__op_sim)
+#define cpu_sim_immv VVAR(_thecpu__DOT__op_sim_immv)
+
+//
+#define r_sleep VVAR(_thecpu__DOT__sleep)
+
+#define master_ce VVAR(_thecpu__DOT__master_ce)
+#define op_break VVAR(_thecpu__DOT__r_op_break)
+#define op_F VVAR(_thecpu__DOT__op_F)
+//
+#define regset VVAR(_thecpu__DOT__regset)
+#define cpu_regs regset
+
+
+#ifdef OPT_CIS
+#define dcd_phase VVAR(_thecpu__DOT__dcd_phase)
+#define op_phase VVAR(_thecpu__DOT__OPT_CIS_OP_PHASE__DOT__r_op_phase)
+#define alu_phase VVAR(_thecpu__DOT__GEN_ALU_PHASE__DOT__r_alu_phase)
+#endif
+
+#ifdef OPT_SINGLE_FETCH
+#define pf_instruction_pc VVAR(_thecpu__DOT__pf_addr)<<2
+#else
+#define pf_instruction_pc VVAR(_thecpu__DOT__pf_instruction_pc)
+#endif
+
+
+#ifdef OPT_PIPELINED
+#define op_Av VVAR(_thecpu__DOT__op_Av)
+#define op_Bv VVAR(_thecpu__DOT__op_Bv)
+#define alu_gie dcd_gie
+#define alu_pc VVAR(_thecpu__DOT__GEN_ALU_PC__DOT__r_alu_pc)
+#define op_Aid VVAR(_thecpu__DOT__op_Aid)
+#define op_Bid VVAR(_thecpu__DOT__op_Bid)
+#else
+#define op_Av VVAR(_thecpu__DOT__r_op_Av)
+#define op_Bv VVAR(_thecpu__DOT__r_op_Bv)
+#define alu_gie dcd_gie
+#define alu_pc VVAR(_thecpu__DOT__op_pc)
+#endif
+#define op_gie dcd_gie
+
+#define r_op_pc VVAR(_thecpu__DOT__op_pc)
+
+#ifdef ZIPSYSTEM
+#define dbg_cyc VVAR(_dbg_cyc)
+#define dbg_stb VVAR(_dbg_stb)
+#define dbg_we VVAR(_dbg_we)
+#define dbg_idata VVAR(_dbg_idata)
+#define cpu_stall VVAR(_cpu_stall)
+#define cpu_interrupt VVAR(_MAIN_PIC__DOT__pic__DOT__r_interrupt)
+#define cpu_idata VVAR(_cpu_idata)
+#define tick_counter m_core->VVAR(_jiffies__DOT__r_counter)
+#define dbg_addr VVAR(_dbg_addr)
+#else
+#define dbg_cyc i_dbg_cyc
+#define dbg_stb i_dbg_stb
+#define dbg_we i_dbg_we
+#define dbg_idata i_dbg_data
+#define cpu_stall i_wb_stall
+#define cpu_interrupt i_ext_int
+#define cpu_idata i_wb_data
+#define tick_counter tickcount()
+#define dbg_addr i_dbg_addr
+#endif
+
+#define r_gie VVAR(_thecpu__DOT__SET_GIE__DOT__r_gie)
+#define pic_data VVAR(_pic_data)
+#define r_value VVAR(_r_value)
+#define watchbus VVAR(_watchbus__DOT__r_value)
+#define watchdog VVAR(_watchdog__DOT__r_value)
+#define wdbus_data VVAR(_r_wdbus_data)
+#define int_state VVAR(_MAIN_PIC__DOT__pic__DOT__r_int_state)
+#define alt_int_state VVAR(_ALT_PIC__DOT__ctri__DOT__r_int_state)
+#define timer_a VVAR(_timer_a__DOT__r_value)
+#define timer_b VVAR(_timer_b__DOT__r_value)
+#define timer_c VVAR(_timer_c__DOT__r_value)
+#define jiffies VVAR(_jiffies__DOT__r_counter)
+#define utc_data VVAR(_utc_data)
+#define uoc_data VVAR(_uoc_data)
+#define upc_data VVAR(_upc_data)
+#define uic_data VVAR(_uic_data)
+#define mtc_data VVAR(_mtc_data)
+#define moc_data VVAR(_moc_data)
+#define mpc_data VVAR(_mpc_data)
+#define mic_data VVAR(_mic_data)
+
+#define r_wb_cyc_gbl MEMVAR(_r_wb_cyc_gbl)
+#define r_wb_cyc_lcl MEMVAR(_r_wb_cyc_lcl)
+#define r_wb_stb_gbl VVAR(_thecpu__DOT__mem_stb_gbl)
+#define r_wb_stb_lcl VVAR(_thecpu__DOT__mem_stb_lcl)
+#define mem_stb_gbl VVAR(_thecpu__DOT__mem_stb_gbl)
+#define mem_stb_lcl VVAR(_thecpu__DOT__mem_stb_lcl)
+#define mem_we VVAR(_thecpu__DOT__mem_we)
+#define mem_ack VVAR(_thecpu__DOT__mem_ack)
+#define mem_stall VVAR(_thecpu__DOT__mem_stall)
+#define mem_data VVAR(_thecpu__DOT__mem_data)
+#define mem_addr VVAR(_thecpu__DOT__mem_addr)
+#define mem_result VVAR(_thecpu__DOT__mem_result)
+#define op_pipe VVAR(_thecpu__DOT__GEN_OP_PIPE__DOT__r_op_pipe)
+#define dcd_pipe VVAR(_thecpu__DOT__instruction_decoder__DOT__GEN_OPIPE__DOT__r_pipe)
+#define op_A_alu VVAR(_thecpu__DOT__op_A_alu)
+#define op_B_alu VVAR(_thecpu__DOT__op_B_alu)
+#define op_A_mem VVAR(_thecpu__DOT__op_A_mem)
+#define op_B_mem VVAR(_thecpu__DOT__op_B_mem)
+#ifdef OPT_PIPELINED
+#define op_opn VVAR(_thecpu__DOT__r_op_opn)
+#else
+#define op_opn dcd_opn
+#endif
+#define alu_result VVAR(_thecpu__DOT__alu_result)
+#define alu_busy VVAR(_thecpu__DOT__doalu__DOT__r_busy)
+#define alu_reg VVAR(_thecpu__DOT__alu_reg)
+#define switch_to_interrupt VVAR(_thecpu__DOT__w_switch_to_interrupt)
+#define release_from_interrupt VVAR(_thecpu__DOT__w_release_from_interrupt)
+#define break_en VVAR(_thecpu__DOT__break_en)
+#define dcd_break VVAR(_thecpu__DOT__dcd_break)
+
+/*
+// We are just a raw CPU with memory. There is no flash.
+#define LGFLASHLEN 24
+#define FLASHBASE 0x01000000
+#define FLASHWORDS (1<>2)
+
+class SPARSEMEM {
+public:
+ bool m_valid;
+ unsigned int m_a, m_d;
+};
+
+class ZIPSTATE {
+public:
+ bool m_valid, m_gie, m_last_pc_valid;
+ unsigned int m_sR[16], m_uR[16];
+#ifdef ZIPSYSTEM
+ unsigned int m_p[20];
+#endif
+ unsigned int m_last_pc, m_pc, m_sp;
+ SPARSEMEM m_smem[5]; // Nearby stack memory
+ SPARSEMEM m_imem[5]; // Nearby instruction memory
+ ZIPSTATE(void) : m_valid(false), m_last_pc_valid(false) {}
+
+ void step(void) {
+ m_last_pc_valid = true;
+ m_last_pc = m_pc;
+ }
+};
+
+extern FILE *gbl_dbgfp;
+FILE *gbl_dbgfp = NULL;
+
+// No particular "parameters" need definition or redefinition here.
+class ZIPCPU_TB : public TESTB {
+public:
+ unsigned long m_mem_size;
+ MEMSIM m_mem;
+ // QSPIFLASHSIM m_flash;
+ FILE *m_dbgfp, *m_profile_fp;
+ bool dbg_flag, m_bomb, m_show_user_timers, m_console, m_exit;
+ int m_cursor, m_rcode;
+ unsigned long m_last_instruction_tickcount;
+ ZIPSTATE m_state;
+
+ ZIPCPU_TB(void) : m_mem_size(RAMWORDS), m_mem(m_mem_size) {
+ m_rcode = 0;
+ m_exit = false;
+ if (true) {
+ m_dbgfp = fopen("debug.txt", "w");
+ dbg_flag = true;
+ gbl_dbgfp = m_dbgfp;
+ } else {
+ m_dbgfp = NULL;
+ dbg_flag = false;
+ gbl_dbgfp = NULL;
+ }
+
+ if(true) {
+ opentrace("trace.vcd");
+ } else {
+ m_trace = NULL;
+ }
+
+ m_bomb = false;
+ m_cursor = 0;
+ m_show_user_timers = false;
+
+ m_last_instruction_tickcount = 0l;
+ if (true) {
+ m_profile_fp = fopen("pfile.bin","wb");
+ } else {
+ m_profile_fp = NULL;
+ }
+ }
+
+ ~ZIPCPU_TB(void) {
+ if (m_dbgfp)
+ fclose(m_dbgfp);
+ if (m_profile_fp)
+ fclose(m_profile_fp);
+ if (m_trace)
+ m_trace->close();
+ }
+
+ void reset(void) {
+ // m_flash.debug(false);
+ TESTB::reset();
+ }
+
+ void step(void) {
+ wb_write(CMD_REG, CMD_STEP);
+ m_state.step();
+ }
+
+ void read_raw_state(void) {
+ m_state.m_valid = false;
+ for(int i=0; i<16; i++)
+ m_state.m_sR[i] = cmd_read(i);
+ for(int i=0; i<16; i++)
+ m_state.m_uR[i] = cmd_read(i+16);
+#ifdef ZIPSYSTEM
+ for(int i=0; i<20; i++)
+ m_state.m_p[i] = cmd_read(i+32);
+#endif
+
+ m_state.m_gie = wb_read(CMD_REG) & CMD_GIE;
+ m_state.m_pc = (m_state.m_gie) ? (m_state.m_uR[15]):(m_state.m_sR[15]);
+ m_state.m_sp = (m_state.m_gie) ? (m_state.m_uR[13]):(m_state.m_sR[13]);
+
+ if (m_state.m_last_pc_valid)
+ m_state.m_imem[0].m_a = m_state.m_last_pc;
+ else
+ m_state.m_imem[0].m_a = m_state.m_pc - 1;
+ m_state.m_imem[0].m_d = m_mem[m_state.m_imem[0].m_a & 0x0fffff];
+ m_state.m_imem[0].m_valid = ((m_state.m_imem[0].m_a & 0xfff00000)==0x00100000);
+ m_state.m_imem[1].m_a = m_state.m_pc;
+ m_state.m_imem[1].m_valid = ((m_state.m_imem[1].m_a & 0xfff00000)==0x00100000);
+ m_state.m_imem[1].m_d = m_mem[m_state.m_imem[1].m_a & 0x0fffff];
+
+ for(int i=1; i<4; i++) {
+ if (!m_state.m_imem[i].m_valid) {
+ m_state.m_imem[i+1].m_valid = false;
+ m_state.m_imem[i+1].m_a = m_state.m_imem[i].m_a+1;
+ continue;
+ }
+ m_state.m_imem[i+1].m_a = zop_early_branch(
+ m_state.m_imem[i].m_a,
+ m_state.m_imem[i].m_d);
+ m_state.m_imem[i+1].m_d = m_mem[m_state.m_imem[i].m_a & 0x0fffff];
+ m_state.m_imem[i+1].m_valid = ((m_state.m_imem[i].m_a&0xfff00000)==0x00100000);
+ }
+
+ m_state.m_smem[0].m_a = m_state.m_sp;
+ for(int i=1; i<5; i++)
+ m_state.m_smem[i].m_a = m_state.m_smem[i-1].m_a+1;
+ for(int i=0; i<5; i++) {
+ m_state.m_smem[i].m_valid =
+ (m_state.m_imem[i].m_a > 0x10000);
+ m_state.m_smem[i].m_d = m_mem[m_state.m_imem[i].m_a & 0x0fffff];
+ }
+ m_state.m_valid = true;
+ }
+
+ void read_raw_state_cheating(void) {
+ m_state.m_valid = false;
+ for(int i=0; i<16; i++)
+ m_state.m_sR[i] = m_core->regset[i];
+ m_state.m_sR[14] = (m_state.m_sR[14]&0xffffe000)|m_core->w_iflags;
+ m_state.m_sR[15] = m_core->cpu_ipc;
+ for(int i=0; i<16; i++)
+ m_state.m_uR[i] = m_core->regset[i+16];
+ m_state.m_uR[14] = (m_state.m_uR[14]&0xffffe000)|m_core->w_uflags;
+ m_state.m_uR[15] = m_core->cpu_upc;
+
+ m_state.m_gie = m_core->r_gie;
+ m_state.m_pc = (m_state.m_gie) ? (m_state.m_uR[15]):(m_state.m_sR[15]);
+ m_state.m_sp = (m_state.m_gie) ? (m_state.m_uR[13]):(m_state.m_sR[13]);
+
+#ifdef ZIPSYSTEM
+ m_state.m_p[0] = m_core->pic_data;
+ m_state.m_p[1] = m_core->watchdog;
+ if (!m_show_user_timers) {
+ m_state.m_p[2] = m_core->watchbus;
+ } else {
+ // The last bus error address
+ m_state.m_p[2] = m_core->wdbus_data;
+ }
+
+ m_state.m_p[3] = m_core->alt_int_state;
+ m_state.m_p[4] = m_core->timer_a;
+ m_state.m_p[5] = m_core->timer_b;
+ m_state.m_p[6] = m_core->timer_c;
+ m_state.m_p[7] = m_core->jiffies;
+
+ m_state.m_p[ 8] = m_core->utc_data;
+ m_state.m_p[ 9] = m_core->uoc_data;
+ m_state.m_p[10] = m_core->upc_data;
+ m_state.m_p[11] = m_core->uic_data;
+
+ m_state.m_p[12] = m_core->mtc_data;
+ m_state.m_p[13] = m_core->moc_data;
+ m_state.m_p[14] = m_core->mpc_data;
+ m_state.m_p[15] = m_core->mic_data;
+#endif
+ }
+
+ void showval(int y, int x, const char *lbl, unsigned int v, bool c) {
+ if (c)
+ mvprintw(y,x, ">%s> 0x%08x<", lbl, v);
+ else
+ mvprintw(y,x, " %s: 0x%08x ", lbl, v);
+ }
+
+ void dispreg(int y, int x, const char *n, unsigned int v, bool c) {
+ // 4,4,8,1 = 17 of 20, +3 = 19
+ if (c)
+ mvprintw(y, x, ">%s> 0x%08x<", n, v);
+ else
+ mvprintw(y, x, " %s: 0x%08x ", n, v);
+ }
+
+ void dbgreg(FILE *fp, int id, const char *n, unsigned int v) {
+ /*
+ if ((id == 14)||(id == 14+16)) {
+ //char buf[64];
+ //fprintf(fp, " %s:",
+ fprintf(fp, " %s: 0x%08x ", n, v);
+ } else
+ */
+ fprintf(fp, " %s: 0x%08x ", n, v);
+ }
+
+ void showreg(int y, int x, const char *n, int r, bool c) {
+ if (r < 16)
+ dispreg(y, x, n, m_state.m_sR[r], c);
+ else
+ dispreg(y, x, n, m_state.m_uR[r-16], c);
+ move(y,x+17);
+
+#ifdef OPT_PIPELINED
+ addch( ((r == (int)(dcd_Aid()&0x01f))&&(m_core->dcd_valid)
+ &&(m_core->dcd_rA))
+ ?'a':((c)?'<':' '));
+ addch( ((r == (int)(dcd_Bid()&0x01f))&&(m_core->dcd_valid)
+ &&(m_core->dcd_rB))
+ ?'b':' ');
+ addch( ((r == m_core->wr_reg_id)
+ &&(m_core->wr_reg_ce))
+ ?'W':' ');
+#else
+ addch( ((r == m_core->wr_reg_id)
+ &&(m_core->wr_reg_ce))
+ ?'W':((c)?'<':' '));
+#endif
+ }
+
+ void showins(int y, const char *lbl, const int ce, const int valid,
+ const int gie, const int stall, const unsigned int pc,
+ const bool phase) {
+ char la[80], lb[80];
+ unsigned iv = m_mem[pc >> 2];
+ bool cisw = (iv & 0x80000000)?true:false;
+
+ if (ce)
+ mvprintw(y, 0, "Ck ");
+ else
+ mvprintw(y, 0, " ");
+ if (stall)
+ printw("Stl ");
+ else
+ printw(" ");
+ printw("%s%c 0x%08x", lbl, ((cisw)&&(phase))?'/':':', pc);
+
+ if (valid) {
+ if (gie) attroff(A_BOLD);
+ else attron(A_BOLD);
+ zipi_to_double_string(pc, iv, la, lb);
+ if ((!cisw)||(phase))
+ printw(" %-24s", la);
+ else
+ printw(" %-24s", lb);
+ } else {
+ attroff(A_BOLD);
+ printw(" (0x%08x)%28s", iv,"");
+ }
+ attroff(A_BOLD);
+ }
+
+ void dbgins(const char *lbl, const int ce, const int valid,
+ const int gie, const int stall, const unsigned int pc,
+ const bool phase, const bool illegal) {
+ char la[80], lb[80];
+
+ if (!m_dbgfp)
+ return;
+
+ if (ce)
+ fprintf(m_dbgfp, "%s Ck ", lbl);
+ else
+ fprintf(m_dbgfp, "%s ", lbl);
+ if (stall)
+ fprintf(m_dbgfp, "Stl ");
+ else
+ fprintf(m_dbgfp, " ");
+ fprintf(m_dbgfp, "0x%08x%s: ", pc, (phase)?"/P":" ");
+
+ if (valid) {
+ zipi_to_double_string(pc, m_mem[pc>>2], la, lb);
+ if ((phase)||((m_mem[pc>>2]&0x80000000)==0))
+ fprintf(m_dbgfp, " %-24s", la);
+ else
+ fprintf(m_dbgfp, " %-24s", lb);
+ } else {
+ fprintf(m_dbgfp, " (0x%08x)", m_mem[pc]);
+ } if (illegal)
+ fprintf(m_dbgfp, " (Illegal)");
+ fprintf(m_dbgfp, "\n");
+ }
+
+ void show_state(void) {
+ int ln= 0;
+
+ read_raw_state_cheating();
+
+ mvprintw(ln,0, "Peripherals-SS"); ln++;
+ printw(" %s",
+ // (m_core->pf_illegal)?"PI":" ",
+ (m_core->dcd_illegal)?"DI":" "
+ );
+
+#ifdef OPT_EARLY_BRANCHING
+ printw(" %s",
+ (m_core->early_branch)?"EB":" ");
+ if (m_core->early_branch)
+ printw(" 0x%08x", m_core->early_branch_pc);
+ else printw(" %10s", "");
+ // printw(" %s", (m_core->v__DOT__thecpu__DOT____Vcellinp__pf____pinNumber3)?"-> P3":" ");
+#endif
+
+#ifdef ZIPSYSTEM
+ showval(ln, 0, "PIC ", m_state.m_p[0], (m_cursor==0));
+ showval(ln,20, "WDT ", m_state.m_p[1], (m_cursor==1));
+ // showval(ln,40, "CACH", m_core->v__DOT__manualcache__DOT__cache_base, (m_cursor==2));
+
+ if (!m_show_user_timers) {
+ showval(ln,40, "WBUS", m_core->watchbus, false);
+ } else {
+ // showval(ln,40, "UBUS", m_core->v__DOT__r_wdbus_data, false);
+ showval(ln,40, "UBUS", m_core->watchbus, false);
+ }
+
+ showval(ln,60, "PIC2", m_state.m_p[3], (m_cursor==3));
+
+ ln++;
+ showval(ln, 0, "TMRA", m_state.m_p[4], (m_cursor==4));
+ showval(ln,20, "TMRB", m_state.m_p[5], (m_cursor==5));
+ showval(ln,40, "TMRC", m_state.m_p[6], (m_cursor==6));
+ showval(ln,60, "JIF ", m_state.m_p[7], (m_cursor==7));
+
+
+ if (!m_show_user_timers) {
+ ln++;
+ showval(ln, 0, "MTSK", m_state.m_p[12], (m_cursor==8));
+ showval(ln,20, "MOST", m_state.m_p[13], (m_cursor==9));
+ showval(ln,40, "MPST", m_state.m_p[14], (m_cursor==10));
+ showval(ln,60, "MICT", m_state.m_p[15], (m_cursor==11));
+ } else {
+ ln++;
+ showval(ln, 0, "UTSK", m_state.m_p[ 8], (m_cursor==8));
+ showval(ln,20, "UOST", m_state.m_p[ 9], (m_cursor==9));
+ showval(ln,40, "UPST", m_state.m_p[10], (m_cursor==10));
+ showval(ln,60, "UICT", m_state.m_p[11], (m_cursor==11));
+ }
+#else
+ ln += 2;
+#endif
+
+ ln++;
+ mvprintw(ln, 40, "%s %s",
+ (m_core->cpu_halt)? "CPU-HALT": " ",
+ (m_core->cmd_reset)?"CPU-RESET":" "); ln++;
+ mvprintw(ln, 40, "%s %s %s 0x%02x %s %s",
+ (m_core->cpu_halt)? "HALT": " ",
+ (m_core->cmd_reset)?"RESET":" ",
+ (m_core->cmd_step)? "STEP" :" ",
+ (m_core->cmd_addr)&0x3f,
+ (m_core->master_ce)? "*CE*" :"(ce)",
+ (m_core->cmd_reset)? "*RST*" :"(rst)");
+ if (m_core->r_gie)
+ attroff(A_BOLD);
+ else
+ attron(A_BOLD);
+ mvprintw(ln, 0, "Supervisor Registers");
+ ln++;
+
+ showreg(ln, 0, "sR0 ", 0, (m_cursor==12));
+ showreg(ln,20, "sR1 ", 1, (m_cursor==13));
+ showreg(ln,40, "sR2 ", 2, (m_cursor==14));
+ showreg(ln,60, "sR3 ", 3, (m_cursor==15)); ln++;
+
+ showreg(ln, 0, "sR4 ", 4, (m_cursor==16));
+ showreg(ln,20, "sR5 ", 5, (m_cursor==17));
+ showreg(ln,40, "sR6 ", 6, (m_cursor==18));
+ showreg(ln,60, "sR7 ", 7, (m_cursor==19)); ln++;
+
+ showreg(ln, 0, "sR8 ", 8, (m_cursor==20));
+ showreg(ln,20, "sR9 ", 9, (m_cursor==21));
+ showreg(ln,40, "sR10", 10, (m_cursor==22));
+ showreg(ln,60, "sR11", 11, (m_cursor==23)); ln++;
+
+ showreg(ln, 0, "sR12", 12, (m_cursor==24));
+ showreg(ln,20, "sSP ", 13, (m_cursor==25));
+
+ unsigned int cc = m_state.m_sR[14];
+ if (false) {
+ mvprintw(ln,40, "%ssCC : 0x%08x",
+ (m_cursor==26)?">":" ", cc);
+ } else {
+ char cbuf[32];
+
+ sprintf(cbuf, "%ssCC :%s%s%s%s%s%s%s",
+ (m_cursor==26)?">":" ",
+ (cc&0x01000)?"FE":"",
+ (cc&0x00800)?"DE":"",
+ (cc&0x00400)?"BE":"",
+ (cc&0x00200)?"TP":"",
+ (cc&0x00100)?"IL":"",
+ (cc&0x00080)?"BK":"",
+ ((m_state.m_gie==0)&&(cc&0x010))?"HLT":"");
+ mvprintw(ln,40, "%-14s",cbuf);
+ mvprintw(ln, 54, "%s%s%s%s",
+ (cc&8)?"V":" ",
+ (cc&4)?"N":" ",
+ (cc&2)?"C":" ",
+ (cc&1)?"Z":" ");
+ }
+ showval(ln,60, "sPC ", m_state.m_sR[15], (m_cursor==27));
+ mvprintw(ln,60,"%s",
+ (m_core->wr_reg_id == 0x0e)
+ &&(m_core->wr_reg_ce)
+ ?"V"
+ :(((m_core->wr_flags_ce)
+ &&(!m_core->alu_gie))?"+"
+ :" "));
+ ln++;
+
+ if (m_core->r_gie)
+ attron(A_BOLD);
+ else
+ attroff(A_BOLD);
+ mvprintw(ln, 0, "User Registers");
+ mvprintw(ln, 42, "DCDR=%02x %s%s",
+ m_core->dcdR,
+ (m_core->dcd_wR)?"W":" ",
+ (m_core->dcd_wF)?"F":" ");
+ mvprintw(ln, 62, "OPR =%02x %s%s",
+ m_core->op_R,
+ (m_core->op_wR)?"W":" ",
+ (m_core->op_wF)?"F":" ");
+ ln++;
+ showreg(ln, 0, "uR0 ", 16, (m_cursor==28));
+ showreg(ln,20, "uR1 ", 17, (m_cursor==29));
+ showreg(ln,40, "uR2 ", 18, (m_cursor==30));
+ showreg(ln,60, "uR3 ", 19, (m_cursor==31)); ln++;
+
+ showreg(ln, 0, "uR4 ", 20, (m_cursor==32));
+ showreg(ln,20, "uR5 ", 21, (m_cursor==33));
+ showreg(ln,40, "uR6 ", 22, (m_cursor==34));
+ showreg(ln,60, "uR7 ", 23, (m_cursor==35)); ln++;
+
+ showreg(ln, 0, "uR8 ", 24, (m_cursor==36));
+ showreg(ln,20, "uR9 ", 25, (m_cursor==37));
+ showreg(ln,40, "uR10", 26, (m_cursor==38));
+ showreg(ln,60, "uR11", 27, (m_cursor==39)); ln++;
+
+ showreg(ln, 0, "uR12", 28, (m_cursor==40));
+ showreg(ln,20, "uSP ", 29, (m_cursor==41));
+ cc = m_state.m_uR[14];
+ if (false) {
+ mvprintw(ln,40, "%cuCC : 0x%08x",
+ (m_cursor == 42)?'>':' ', cc);
+ } else {
+ char cbuf[32];
+ sprintf(cbuf, "%cuCC :%s%s%s%s%s%s%s",
+ (m_cursor == 42)?'>':' ',
+ (cc & 0x1000)?"FE":"",
+ (cc & 0x0800)?"DE":"",
+ (cc & 0x0400)?"BE":"",
+ (cc & 0x0200)?"TP":"",
+ (cc & 0x0100)?"IL":"",
+ (cc & 0x0040)?"ST":"",
+ ((m_state.m_gie)&&(cc & 0x010))?"SL":"");
+ mvprintw(ln,40, "%-14s",cbuf);
+ mvprintw(ln, 54, "%s%s%s%s",
+ (cc&8)?"V":" ",
+ (cc&4)?"N":" ",
+ (cc&2)?"C":" ",
+ (cc&1)?"Z":" ");
+ }
+ showval(ln,60, "uPC ", m_state.m_uR[15], (m_cursor==43));
+ mvprintw(ln,60,"%s",
+ (m_core->wr_reg_id == 0x1e)
+ &&(m_core->wr_reg_ce)
+ ?"V"
+ :(((m_core->wr_flags_ce)
+ &&(m_core->alu_gie))?"+"
+ :" "));
+
+ attroff(A_BOLD);
+ ln+=1;
+
+#ifdef OPT_SINGLE_FETCH
+ ln++;
+ mvprintw(ln, 0, "PF BUS: %3s %3s %s @0x%08x[0x%08x] -> %s %s %08x",
+ (m_core->pf_cyc)?"CYC":" ",
+ (m_core->pf_stb)?"STB":" ",
+ " ", // (m_core->pf_we )?"WE":" ",
+ (m_core->pf_addr<<2),
+ 0, // (m_core->v__DOT__thecpu__DOT__pf_data),
+ (m_core->pf_ack)?"ACK":" ",
+ " ",//(m_core->v__DOT__thecpu__DOT__pf_stall)?"STL":" ",
+ (m_core->cpu_idata)); ln++;
+#else
+#ifdef OPT_DOUBLE_FETCH
+#else
+
+ mvprintw(ln, 0, "PFCACH: v=%08x, %s%s, tag=%08x, pf_pc=%08x, lastpc=%08x",
+ m_core->pf_vmask,
+ (m_core->pf_r_v)?"V":" ",
+ (m_core->pf_illegal)?"I":" ",
+ (m_core->pf_tagsrc)
+ ?(m_core->pf_tagipc)
+ :(m_core->pf_tagvallst),
+ m_core->pf_pc,
+ m_core->pf_lastpc);
+
+#endif
+ ln++;
+ mvprintw(ln, 0, "PF BUS: %3s %3s %s @0x%08x[0x%08x] -> %s %s %08x",
+ (m_core->pf_cyc)?"CYC":" ",
+ (m_core->pf_stb)?"STB":" ",
+ " ", // (m_core->v__DOT__thecpu__DOT__pf_we )?"WE":" ",
+ (m_core->pf_addr<<2),
+ 0, // (m_core->v__DOT__thecpu__DOT__pf_data),
+ (m_core->pf_ack)?"ACK":" ",
+ (pfstall())?"STL":" ",
+ (m_core->cpu_idata)); ln++;
+#endif
+
+ mvprintw(ln, 0, "MEMBUS: %3s %3s %s @0x%08x[0x%08x] -> %s %s %08x",
+ (m_core->r_wb_cyc_gbl)?"GCY"
+ :((m_core->r_wb_cyc_lcl)?"LCY":" "),
+ (m_core->mem_stb_gbl)?"GSB"
+ :((m_core->mem_stb_lcl)?"LSB":" "),
+ (m_core->mem_we )?"WE":" ",
+ (m_core->mem_addr<<2),
+ (m_core->mem_data),
+ (m_core->mem_ack)?"ACK":" ",
+ (m_core->mem_stall)?"STL":" ",
+ (m_core->mem_result));
+// #define OPT_PIPELINED_BUS_ACCESS
+#ifdef OPT_PIPELINED_BUS_ACCESS
+#ifndef OPT_DCACHE
+ printw(" %x%x%c%c",
+ (m_core->mem_wraddr),
+ (m_core->mem_rdaddr),
+ (m_core->op_pipe)?'P':'-',
+ (mem_pipe_stalled())?'S':'-'); ln++;
+#else
+ ln++;
+#endif
+#else
+ ln++;
+#endif
+
+#define pformem_owner VVAR(_thecpu__DOT__pformem__DOT__r_a_owner)
+ mvprintw(ln, 0, "SYSBS%c: %3s %3s %s @0x%08x[0x%08x] -> %s %s %08x %s",
+ (m_core->pformem_owner)?'M':'P',
+ (m_core->o_wb_cyc)?"CYC":" ",
+ (m_core->o_wb_stb)?"STB":" ",
+ (m_core->o_wb_we )?"WE":" ",
+ (m_core->o_wb_addr<<2),
+ (m_core->o_wb_data),
+ (m_core->i_wb_ack)?"ACK":" ",
+ (m_core->i_wb_stall)?"STL":" ",
+ (m_core->i_wb_data),
+ (m_core->i_wb_err)?"(ER!)":" "); ln+=2;
+#ifdef OPT_PIPELINED_BUS_ACCESS
+ mvprintw(ln-1, 0, "Mem CE: %d = %d%d%d%d%d, stall: %d = %d%d(%d|%d%d|..)",
+ (m_core->mem_ce),
+ (m_core->master_ce), //1
+ (m_core->op_valid_mem), //0
+ (!m_core->new_pc), //1
+ // (!m_core->clear_pipeline), //1
+ (m_core->set_cond), //1
+ (!mem_stalled()), //1
+
+ (mem_stalled()),
+ (m_core->op_valid_mem),
+ (m_core->master_ce),
+ (mem_pipe_stalled()),
+ (!m_core->op_pipe),
+ (m_core->mem_cyc)
+ );
+ printw(" op_pipe = %d", m_core->dcd_pipe);
+ // mvprintw(4,4,"r_dcdI = 0x%06x",
+ // (m_core->v__DOT__thecpu__DOT__dcdI)&0x0ffffff);
+#endif
+ mvprintw(4,42,"0x%08x", m_core->pf_instruction);
+#ifdef OPT_SINGLE_CYCLE
+ printw(" A:%c%c B:%c%c",
+ (m_core->op_A_alu)?'A':'-',
+ (m_core->op_A_mem)?'M':'-',
+ (m_core->op_B_alu)?'A':'-',
+ (m_core->op_B_mem)?'M':'-');
+#else
+ printw(" A:xx B:xx");
+#endif
+ printw(" PFPC=%08x", m_core->pf_pc);
+
+
+ showins(ln, "I ",
+#ifdef OPT_PIPELINED
+ !m_core->dcd_stalled,
+#else
+ 1,
+#endif
+ m_core->pf_valid,
+ //m_core->v__DOT__thecpu__DOT__instruction_gie,
+ m_core->r_gie,
+ 0,
+ (m_core->pf_instruction_pc),
+ true); ln++;
+ // m_core->pf_pc); ln++;
+
+ showins(ln, "Dc",
+ m_core->dcd_ce, m_core->dcd_valid,
+ m_core->dcd_gie,
+#ifdef OPT_PIPELINED
+ m_core->dcd_stalled,
+#else
+ 0,
+#endif
+#ifdef OPT_CIS
+ ((m_core->dcd_phase) ?
+ (m_core->dcd_pc+2):m_core->dcd_pc) -4,
+ m_core->dcd_phase
+#else
+ m_core->dcd_pc - 4,
+ false
+#endif
+ ); ln++;
+ if (m_core->dcd_illegal)
+ mvprintw(ln-1,10,"I");
+ else if (m_core->dcd_M)
+ mvprintw(ln-1,10,"M");
+
+ showins(ln, "Op",
+ m_core->op_ce,
+ m_core->op_valid,
+ m_core->op_gie,
+#ifdef op_stall
+ m_core->op_stall,
+#else
+ 0,
+#endif
+#ifdef OPT_CIS
+ op_pc()+((m_core->op_phase)?4:0),
+ m_core->op_phase
+#else
+ op_pc(), false
+#endif
+ ); ln++;
+ if (m_core->op_illegal)
+ mvprintw(ln-1,10,"I");
+ else if (m_core->op_valid_mem)
+ mvprintw(ln-1,10,"M");
+ else if (m_core->op_valid_alu)
+ mvprintw(ln-1,10,"A");
+
+ if (m_core->op_valid_mem) {
+ showins(ln, "Mm",
+ m_core->mem_ce,
+ m_core->mem_pc_valid,
+ m_core->alu_gie,
+#ifdef OPT_PIPELINED
+ m_core->mem_stall,
+#else
+ 0,
+#endif
+ alu_pc(),
+#ifdef OPT_CIS
+ m_core->alu_phase
+#else
+ false
+#endif
+ );
+ } else {
+ showins(ln, "Al",
+ m_core->alu_ce,
+ m_core->alu_pc_valid,
+ m_core->alu_gie,
+#ifdef OPT_PIPELINED
+ alu_stall(),
+#else
+ 0,
+#endif
+ alu_pc(),
+#ifdef OPT_CIS
+ m_core->alu_phase
+#else
+ false
+#endif
+ );
+ } ln++;
+ if (m_core->wr_reg_ce)
+ mvprintw(ln-1,10,"W");
+ else if (m_core->alu_valid)
+ mvprintw(ln-1,10,(m_core->alu_wR)?"w":"V");
+ else if (m_core->mem_valid)
+ mvprintw(ln-1,10,"v");
+ else if (m_core->alu_illegal)
+ mvprintw(ln-1,10,"I");
+ // else if (m_core->v__DOT__thecpu__DOT__alu_illegal_op)
+ // mvprintw(ln-1,10,"i");
+
+ mvprintw(ln-5, 65,"%s %s",
+ (m_core->op_break)?"OB":" ",
+ (m_core->new_pc)?"CLRP":" ");
+ mvprintw(ln-4, 48,
+ (m_core->new_pc)?"new-pc":" ");
+ printw("(%s:%02x,%x)",
+ (m_core->set_cond)?"SET":" ",
+ (m_core->op_F&0x0ff),
+ (m_core->op_gie)
+ ? (m_core->w_uflags)
+ : (m_core->w_iflags));
+
+ printw("(%s%s%s:%02x)",
+ (m_core->op_wF)?"OF":" ",
+ (m_core->alu_wF)?"FL":" ",
+ (m_core->wr_flags_ce)?"W":" ",
+ (m_core->alu_flags));
+#ifdef OPT_PIPELINED
+ mvprintw(ln-3, 48, "Op(%x)%8x,%8x->",
+ m_core->op_opn,
+ m_core->op_Aid, m_core->op_Bid);
+#else
+ mvprintw(ln-3, 48, "");
+#endif
+ if (m_core->alu_valid)
+ printw("%08x", m_core->alu_result);
+ else
+ printw("%8s","");
+ mvprintw(ln-1, 48, "%s%s%s ",
+ (m_core->alu_valid)?"A"
+ :((m_core->alu_busy)?"a":" "),
+#ifdef OPT_DIVIDE
+ (m_core->div_valid)?"D"
+ :((m_core->div_busy)?"d":" "),
+ (m_core->div_valid)?"F"
+ :((m_core->div_busy)?"f":" ")
+#else
+ " ", " "
+#endif
+ );
+ if ((m_core->mem_ce)||(m_core->mem_valid)) {
+ printw("MEM: %s%s %s%s %s %-5s",
+ (m_core->op_valid_mem)?"M":" ",
+ (m_core->mem_ce)?"CE":" ",
+ (m_core->mem_we)?"Wr ":"Rd ",
+ (mem_stalled())?"PIPE":" ",
+ (m_core->mem_valid)?"V":" ",
+ zip_regstr[(m_core->mem_wreg&0x1f)^0x10]);
+ } else {
+ printw("%18s", "");
+ }
+ }
+
+ void show_user_timers(bool v) {
+ m_show_user_timers = v;
+ }
+
+ unsigned int cmd_read(unsigned int a) {
+ int errcount = 0;
+ if (m_dbgfp) {
+ dbg_flag= true;
+ fprintf(m_dbgfp, "CMD-READ(%d)\n", a);
+ }
+ wb_write(CMD_REG, CMD_HALT|(a&0x3f));
+ while(((wb_read(CMD_REG) & CMD_STALL) == 0)&&(errcount= MAXERR) {
+ endwin();
+
+ printf("ERR: errcount >= MAXERR on wb_read(a=%x)\n", a);
+ // printf("Clear-Pipeline = %d\n", m_core->v__DOT__thecpu__DOT__clear_pipeline);
+#define r_halted VVAR(_thecpu__DOT__r_halted)
+ printf("cpu-dbg-stall = %d\n", m_core->r_halted);
+ printf("pf_cyc = %d\n", m_core->pf_cyc);
+ printf("mem_cyc_gbl = %d\n", (m_core->r_wb_cyc_gbl));
+ printf("mem_cyc_lcl = %d\n", m_core->r_wb_cyc_lcl);
+ printf("op_valid = %d\n", m_core->op_valid);
+ printf("dcd_valid = %d\n", m_core->dcd_valid);
+ printf("dcd_ce = %d\n", m_core->dcd_ce);
+#ifdef OPT_PIPELINED
+ printf("dcd_stalled = %d\n", m_core->dcd_stalled);
+#endif
+ printf("pf_valid = %d\n", m_core->pf_valid);
+// #ifdef OPT_EARLY_BRANCHING
+ // printf("dcd_early_branch=%d\n", m_core->v__DOT__thecpu__DOT__instruction_decoder__DOT__genblk1__DOT__r_early_branch);
+// #endif
+
+ exit(-2);
+ }
+
+ assert(errcount < MAXERR);
+ unsigned int v = wb_read(CMD_DATA);
+
+ if (dbg_flag)
+ fprintf(m_dbgfp, "CMD-READ(%d) = 0x%08x\n", a, v);
+ dbg_flag = false;
+ return v;
+ }
+
+ void cmd_write(unsigned int a, int v) {
+ int errcount = 0;
+ if ((a&0x0f)==0x0f)
+ dbg_flag = true;
+ wb_write(CMD_REG, CMD_HALT|(a&0x3f));
+ while(((wb_read(CMD_REG) & CMD_STALL) == 0)&&(errcount < MAXERR))
+ errcount++;
+ assert(errcount < MAXERR);
+ if (dbg_flag)
+ fprintf(m_dbgfp, "CMD-WRITE(%d) <= 0x%08x\n", a, v);
+ wb_write(CMD_DATA, v);
+ }
+
+ bool halted(void) {
+ return (m_core->cpu_halt != 0);
+ }
+
+ void read_state(void) {
+ int ln= 0;
+ bool gie;
+
+ read_raw_state();
+ if (m_cursor < 0)
+ m_cursor = 0;
+#ifdef ZIPBONES
+ else if (m_cursor >= 32)
+ m_cursor = 31;
+#else
+ else if (m_cursor >= 44)
+ m_cursor = 43;
+#endif
+
+ mvprintw(ln,0, "Peripherals-RS");
+ mvprintw(ln,40,"%-40s", "CPU State: ");
+ {
+ unsigned int v = wb_read(CMD_REG);
+ mvprintw(ln,51, "");
+ if (v & 0x010000)
+ printw("EXT-INT ");
+ if ((v & 0x003000) == 0x03000)
+ printw("Halted ");
+ else if (v & 0x001000)
+ printw("Sleeping ");
+ else if (v & 0x002000)
+ printw("User Mod ");
+ if (v & 0x008000)
+ printw("Break-Enabled ");
+ if (v & 0x000080)
+ printw("PIC Enabled ");
+ } ln++;
+#ifdef ZIPSYSTEM
+ showval(ln, 0, "PIC ", m_state.m_p[0], (m_cursor==0));
+ showval(ln,20, "WDT ", m_state.m_p[1], (m_cursor==1));
+ showval(ln,40, "WBUS", m_state.m_p[2], false);
+ showval(ln,60, "PIC2", m_state.m_p[3], (m_cursor==3));
+ ln++;
+ showval(ln, 0, "TMRA", m_state.m_p[4], (m_cursor==4));
+ showval(ln,20, "TMRB", m_state.m_p[5], (m_cursor==5));
+ showval(ln,40, "TMRC", m_state.m_p[6], (m_cursor==6));
+ showval(ln,60, "JIF ", m_state.m_p[7], (m_cursor==7));
+
+ ln++;
+ if (!m_show_user_timers) {
+ showval(ln, 0, "MTSK", m_state.m_p[12], (m_cursor==8));
+ showval(ln,20, "MMST", m_state.m_p[13], (m_cursor==9));
+ showval(ln,40, "MPST", m_state.m_p[14], (m_cursor==10));
+ showval(ln,60, "MICT", m_state.m_p[15], (m_cursor==11));
+ } else {
+ showval(ln, 0, "UTSK", m_state.m_p[ 8], (m_cursor==8));
+ showval(ln,20, "UMST", m_state.m_p[ 9], (m_cursor==9));
+ showval(ln,40, "UPST", m_state.m_p[10], (m_cursor==10));
+ showval(ln,60, "UICT", m_state.m_p[11], (m_cursor==11));
+ }
+#else
+ ln += 2;
+#endif
+
+ ln++;
+ ln++;
+ unsigned int cc = m_state.m_sR[14];
+ if (m_dbgfp) fprintf(m_dbgfp, "CC = %08x, gie = %d\n", cc,
+ m_core->r_gie);
+ gie = (cc & 0x020);
+ if (gie)
+ attroff(A_BOLD);
+ else
+ attron(A_BOLD);
+ mvprintw(ln, 0, "Supervisor Registers");
+ ln++;
+
+ dispreg(ln, 0, "sR0 ", m_state.m_sR[ 0], (m_cursor==12));
+ dispreg(ln,20, "sR1 ", m_state.m_sR[ 1], (m_cursor==13));
+ dispreg(ln,40, "sR2 ", m_state.m_sR[ 2], (m_cursor==14));
+ dispreg(ln,60, "sR3 ", m_state.m_sR[ 3], (m_cursor==15)); ln++;
+
+ dispreg(ln, 0, "sR4 ", m_state.m_sR[ 4], (m_cursor==16));
+ dispreg(ln,20, "sR5 ", m_state.m_sR[ 5], (m_cursor==17));
+ dispreg(ln,40, "sR6 ", m_state.m_sR[ 6], (m_cursor==18));
+ dispreg(ln,60, "sR7 ", m_state.m_sR[ 7], (m_cursor==19)); ln++;
+
+ dispreg(ln, 0, "sR8 ", m_state.m_sR[ 8], (m_cursor==20));
+ dispreg(ln,20, "sR9 ", m_state.m_sR[ 9], (m_cursor==21));
+ dispreg(ln,40, "sR10", m_state.m_sR[10], (m_cursor==22));
+ dispreg(ln,60, "sR11", m_state.m_sR[11], (m_cursor==23)); ln++;
+
+ dispreg(ln, 0, "sR12", m_state.m_sR[12], (m_cursor==24));
+ dispreg(ln,20, "sSP ", m_state.m_sR[13], (m_cursor==25));
+
+ if (true) {
+ mvprintw(ln,40, "%ssCC : 0x%08x",
+ (m_cursor==26)?">":" ", cc);
+ } else {
+ char cbuf[32];
+ sprintf(cbuf, "%ssCC :%s%s%s%s%s%s%s",
+ (m_cursor==26)?">":" ",
+ (cc&0x01000)?"FE":"",
+ (cc&0x00800)?"DE":"",
+ (cc&0x00400)?"BE":"",
+ (cc&0x00200)?"TP":"",
+ (cc&0x00100)?"IL":"",
+ (cc&0x00080)?"BK":"",
+ ((m_state.m_gie==0)&&(cc&0x010))?"HLT":"");
+ mvprintw(ln,40, "%-14s",cbuf);
+ mvprintw(ln, 54, "%s%s%s%s",
+ (cc&8)?"V":" ",
+ (cc&4)?"N":" ",
+ (cc&2)?"C":" ",
+ (cc&1)?"Z":" ");
+ }
+ dispreg(ln,60, "sPC ", cmd_read(15), (m_cursor==27));
+ ln++;
+
+ if (gie)
+ attron(A_BOLD);
+ else
+ attroff(A_BOLD);
+ mvprintw(ln, 0, "User Registers");
+ mvprintw(ln, 42, "DCDR=%02x %s",
+ m_core->dcdR, (m_core->dcd_wR)?"W":" ");
+ mvprintw(ln, 62, "OPR =%02x %s%s",
+ m_core->op_R,
+ (m_core->op_wR)?"W":" ",
+ (m_core->op_wF)?"F":" ");
+ ln++;
+ dispreg(ln, 0, "uR0 ", m_state.m_uR[ 0], (m_cursor==28));
+ dispreg(ln,20, "uR1 ", m_state.m_uR[ 1], (m_cursor==29));
+ dispreg(ln,40, "uR2 ", m_state.m_uR[ 2], (m_cursor==30));
+ dispreg(ln,60, "uR3 ", m_state.m_uR[ 3], (m_cursor==31)); ln++;
+
+ dispreg(ln, 0, "uR4 ", m_state.m_uR[ 4], (m_cursor==32));
+ dispreg(ln,20, "uR5 ", m_state.m_uR[ 5], (m_cursor==33));
+ dispreg(ln,40, "uR6 ", m_state.m_uR[ 6], (m_cursor==34));
+ dispreg(ln,60, "uR7 ", m_state.m_uR[ 7], (m_cursor==35)); ln++;
+
+ dispreg(ln, 0, "uR8 ", m_state.m_uR[ 8], (m_cursor==36));
+ dispreg(ln,20, "uR9 ", m_state.m_uR[ 9], (m_cursor==37));
+ dispreg(ln,40, "uR10", m_state.m_uR[10], (m_cursor==38));
+ dispreg(ln,60, "uR11", m_state.m_uR[11], (m_cursor==39)); ln++;
+
+ dispreg(ln, 0, "uR12", m_state.m_uR[12], (m_cursor==40));
+ dispreg(ln,20, "uSP ", m_state.m_uR[13], (m_cursor==41));
+ cc = m_state.m_uR[14];
+ if (false) {
+ mvprintw(ln,40, "%cuCC : 0x%08x",
+ (m_cursor == 42)?'>':' ', cc);
+ } else {
+ char cbuf[32];
+ sprintf(cbuf, "%cuCC :%s%s%s%s%s%s%s",
+ (m_cursor == 42)?'>':' ',
+ (cc & 0x1000)?"FE":"",
+ (cc & 0x0800)?"DE":"",
+ (cc & 0x0400)?"BE":"",
+ (cc & 0x0200)?"TP":"",
+ (cc & 0x0100)?"IL":"",
+ (cc & 0x0040)?"ST":"",
+ ((m_state.m_gie)&&(cc & 0x010))?"SL":"");
+ mvprintw(ln,40, "%-14s", cbuf);
+ mvprintw(ln, 54, "%s%s%s%s",
+ (cc&8)?"V":" ",
+ (cc&4)?"N":" ",
+ (cc&2)?"C":" ",
+ (cc&1)?"Z":" ");
+ }
+ dispreg(ln,60, "uPC ", m_state.m_uR[15], (m_cursor==43));
+
+ attroff(A_BOLD);
+ ln+=2;
+
+ ln+=3;
+
+ showins(ln, "I ",
+#ifdef OPT_PIPELINED
+ !m_core->dcd_stalled,
+#else
+ 1,
+#endif
+ m_core->pf_valid,
+ m_core->r_gie,
+ 0,
+ m_core->pf_instruction_pc,
+ true); ln++;
+ // m_core->pf_pc); ln++;
+
+ showins(ln, "Dc",
+ m_core->dcd_ce, m_core->dcd_valid,
+ m_core->dcd_gie,
+#ifdef OPT_PIPELINED
+ m_core->dcd_stalled,
+#else
+ 0,
+#endif
+#ifdef OPT_CIS
+ ((m_core->dcd_phase) ?
+ (m_core->dcd_pc+2):m_core->dcd_pc) -4,
+ m_core->dcd_phase
+#else
+ m_core->dcd_pc-4,
+ false
+#endif
+ ); ln++;
+
+ showins(ln, "Op",
+ m_core->op_ce,
+ m_core->op_valid,
+ m_core->op_gie,
+#ifdef OPT_PIPELINED
+ m_core->op_stall,
+#else
+ 0,
+#endif
+#ifdef OPT_CIS
+ op_pc()+((m_core->op_phase)?4:0),
+ m_core->op_phase
+#else
+ op_pc(),
+ false
+#endif
+ ); ln++;
+
+ if (m_core->op_valid_mem) {
+ showins(ln, "Mm",
+ m_core->mem_ce,
+ m_core->mem_pc_valid,
+ m_core->alu_gie,
+#ifdef OPT_PIPELINED
+ m_core->mem_stall,
+#else
+ 0,
+#endif
+ alu_pc(),
+#ifdef OPT_CIS
+ m_core->alu_phase
+#else
+ false
+#endif
+ );
+ } else {
+ showins(ln, "Al",
+ m_core->alu_ce,
+ m_core->alu_pc_valid,
+ m_core->alu_gie,
+#ifdef OPT_PIPELINED
+ alu_stall(),
+#else
+ 0,
+#endif
+ alu_pc(),
+#ifdef OPT_CIS
+ m_core->alu_phase
+#else
+ false
+#endif
+ );
+ } ln++;
+ }
+
+ void tick(void) {
+ int gie = m_core->r_gie;
+ /*
+ m_core->i_qspi_dat = m_flash(m_core->o_qspi_cs_n,
+ m_core->o_qspi_sck,
+ m_core->o_qspi_dat);
+ */
+
+ int stb = m_core->o_wb_stb, maskb = (RAMBASE-1);
+ unsigned addr = m_core->o_wb_addr<<2;
+
+ m_core->i_wb_err = 0;
+ if ((addr & (~maskb))!=RAMBASE)
+ stb = 0;
+ if ((m_core->o_wb_cyc)&&(m_core->o_wb_stb)&&(!stb)) {
+ m_core->i_wb_ack = 1;
+ m_core->i_wb_err = 1;
+ m_bomb = (m_tickcount > 20);
+ if (m_dbgfp) fprintf(m_dbgfp,
+ "BOMB!! (Attempting to access %08x/%08x->%08x)\n",
+ addr, RAMBASE, ((addr)&(~maskb)));
+ } else if ((!m_core->o_wb_cyc)&&(m_core->o_wb_stb)) {
+ if (m_dbgfp) fprintf(m_dbgfp,
+ "BOMB!! (Strobe high, CYC low)\n");
+ m_bomb = true;
+ }
+
+ if ((dbg_flag)&&(m_dbgfp)) {
+ fprintf(m_dbgfp, "BUS %s %s %s @0x%08x/[0x%08x 0x%08x] %s %s\n",
+ (m_core->o_wb_cyc)?"CYC":" ",
+ (m_core->o_wb_stb)?"STB":" ",
+ (m_core->o_wb_we)?"WE":" ",
+ (m_core->o_wb_addr<<2),
+ (m_core->o_wb_data),
+ (m_core->i_wb_data),
+ (m_core->i_wb_stall)?"STALL":" ",
+ (m_core->i_wb_ack)?"ACK":" ");
+ fprintf(m_dbgfp, "DBG %s %s %s @0x%08x/%d[0x%08x] %s %s [0x%08x] %s %s %s%s%s%s%s%s%s%s%s\n",
+ (m_core->i_dbg_cyc)?"CYC":" ",
+ (m_core->i_dbg_stb)?"STB":
+ ((m_core->dbg_stb)?"DBG":" "),
+ ((m_core->i_dbg_we)?"WE":" "),
+ (m_core->i_dbg_addr),0,
+ m_core->i_dbg_data,
+ (m_core->o_dbg_ack)?"ACK":" ",
+ (m_core->o_dbg_stall)?"STALL":" ",
+ (m_core->o_dbg_data),
+ (m_core->cpu_halt)?"CPU-HALT ":"",
+ (m_core->r_halted)?"CPU-DBG_STALL":"",
+ (m_core->dcd_valid)?"DCDV ":"",
+ (m_core->op_valid)?"OPV ":"",
+ (m_core->pf_cyc)?"PCYC ":"",
+ (m_core->r_wb_cyc_gbl)?"GC":" ",
+ (m_core->r_wb_cyc_lcl)?"LC":" ",
+ (m_core->alu_wR)?"ALUW ":"",
+ (m_core->alu_ce)?"ALCE ":"",
+ (m_core->alu_valid)?"ALUV ":"",
+ (m_core->mem_valid)?"MEMV ":"");
+#ifdef ZIPSYSTEM
+ fprintf(m_dbgfp, " SYS %s %s %s @0x%08x/%d[0x%08x] %s [0x%08x]\n",
+#define sys_cyc VVAR(_sys_cyc)
+#define sys_stb VVAR(_sys_stb)
+#define sys_we VVAR(_sys_we)
+#define sys_addr VVAR(_sys_addr)
+#define sys_data VVAR(_sys_data)
+#define dbg_ack VVAR(_dbg_ack)
+#define dbg_addr VVAR(_dbg_addr)
+ (m_core->sys_cyc)?"CYC":" ",
+ (m_core->sys_stb)?"STB":" ",
+ (m_core->sys_we)?"WE":" ",
+ (m_core->sys_addr<<2),
+ (m_core->dbg_addr<<2),
+ (m_core->sys_data),
+ (m_core->dbg_ack)?"ACK":" ",
+ (m_core->cpu_idata));
+#endif
+ }
+
+ if (m_dbgfp)
+ fprintf(m_dbgfp, "CEs %d/0x%08x,%d/0x%08x DCD: ->%02x, OP: ->%02x, ALU: halt=%d ce=%d, valid=%d, wr=%d Reg=%02x, IPC=%08x, UPC=%08x\n",
+ m_core->dcd_ce,
+ m_core->dcd_pc,
+ m_core->op_ce,
+ op_pc(),
+ dcd_Aid()&0x01f,
+ m_core->op_R,
+ m_core->cpu_halt,
+ m_core->alu_ce,
+ m_core->alu_valid,
+ m_core->alu_wR,
+ m_core->alu_reg,
+ m_core->cpu_ipc,
+ m_core->cpu_upc);
+
+ if ((m_dbgfp)&&(!gie)&&(m_core->release_from_interrupt)) {
+ fprintf(m_dbgfp, "RELEASE: int=%d, %d/%02x[%08x] ?/%02x[0x%08x], ce=%d %d,%d,%d\n",
+ m_core->cpu_interrupt,
+ m_core->wr_reg_ce,
+ m_core->wr_reg_id,
+ m_core->wr_spreg_vl,
+ m_core->cmd_addr<<2,
+ m_core->dbg_idata,
+ m_core->master_ce,
+ m_core->alu_wR,
+ m_core->alu_valid,
+ m_core->mem_valid);
+ } else if ((m_dbgfp)&&(gie)&&(m_core->switch_to_interrupt)) {
+ fprintf(m_dbgfp, "SWITCH: %d/%02x[%08x] ?/%02x[0x%08x], ce=%d %d,%d,%d, F%02x,%02x\n",
+ m_core->wr_reg_ce,
+ m_core->wr_reg_id,
+ m_core->wr_spreg_vl,
+ m_core->cmd_addr<<2,
+ m_core->dbg_idata,
+ m_core->master_ce,
+ m_core->alu_wR,
+ m_core->alu_valid,
+ m_core->mem_valid,
+ m_core->w_iflags,
+ m_core->w_uflags);
+ fprintf(m_dbgfp, "\tbrk=%s %d,%d\n",
+ (m_core->master_ce)?"CE":" ",
+ m_core->break_en,
+ m_core->op_break);
+ } else if ((m_dbgfp)&&
+ ((m_core->op_break)
+ ||(m_core->alu_illegal)
+ ||(m_core->dcd_break))) {
+ fprintf(m_dbgfp, "NOT SWITCHING TO GIE (gie = %d)\n", gie);
+ fprintf(m_dbgfp, "\tbrk=%s breaken=%d,dcdbreak=%d,opbreak=%d,alu_illegal=%d\n",
+ (m_core->master_ce)?"CE":" ",
+ m_core->break_en,
+ m_core->dcd_break,
+ m_core->op_break,
+ m_core->alu_illegal);
+ }
+
+ if (m_dbgfp) {
+ // if(m_core->v__DOT__thecpu__DOT__clear_pipeline)
+ // fprintf(m_dbgfp, "\tClear Pipeline\n");
+ if(m_core->new_pc)
+ fprintf(m_dbgfp, "\tNew PC\n");
+ }
+
+ if (m_dbgfp) {
+ unsigned long v = m_tickcount;
+ fprintf(m_dbgfp, "----------- TICK (%08lx) ----------%s\n",
+ v, (m_bomb)?" BOMBED!!":"");
+ }
+ m_mem(m_core->o_wb_cyc, m_core->o_wb_stb, m_core->o_wb_we,
+ m_core->o_wb_addr & (maskb>>2), m_core->o_wb_data, m_core->o_wb_sel & 0x0f,
+ m_core->i_wb_ack, m_core->i_wb_stall,m_core->i_wb_data);
+
+ TESTB::tick();
+
+ if ((m_core->cpu_sim)
+ &&(m_core->op_valid)
+ &&(m_core->alu_ce)
+ &&(!m_core->new_pc)) {
+ execsim(m_core->cpu_sim_immv);
+ }
+
+ if ((m_dbgfp)&&(gie != m_core->r_gie)) {
+ fprintf(m_dbgfp, "SWITCH FROM %s to %s: sPC = 0x%08x uPC = 0x%08x pf_pc = 0x%08x\n",
+ (gie)?"User":"Supervisor",
+ (gie)?"Supervisor":"User",
+ m_core->cpu_ipc,
+ m_core->cpu_upc,
+ m_core->pf_pc);
+ } if (m_dbgfp) {
+#ifdef OPT_TRADITIONAL_PFCACHE
+ fprintf(m_dbgfp, "PFCACHE %s(%08x,%08x%s),%08x - %08x %s%s%s\n",
+ (m_core->new_pc)?"N":" ",
+ m_core->pf_pc,
+ m_core->early_branch_pc,
+ ((m_core->early_branch)
+ &&(m_core->dcd_valid)
+ &&(!m_core->new_pc))?"V":"-",
+ m_core->pf_lastpc,
+ m_core->pf_instruction_pc,
+ (m_core->pf_r_v)?"R":" ",
+ (m_core->pf_valid)?"V":" ",
+ (m_core->pf_illegal)?"I":" ");
+#endif
+ dbgins("Dc - ",
+ m_core->dcd_ce, m_core->dcd_valid,
+ m_core->dcd_gie,
+#ifdef OPT_PIPELINED
+ m_core->dcd_stalled,
+#else
+ 0,
+#endif
+#ifdef OPT_CIS
+ (m_core->dcd_phase)?(m_core->dcd_pc-2)
+ :(m_core->dcd_pc-4),
+ m_core->dcd_phase,
+#else
+ m_core->dcd_pc-4, false,
+#endif
+ m_core->dcd_illegal);
+ if (m_dbgfp) {
+ fprintf(m_dbgfp, "\t\t\tR[%2d] = (*Dc=%d%s)[ A[%2d], B[%2d] + %08x], dcd_pc = %08x\n",
+ m_core->dcdR,
+ m_core->dcd_opn,
+ (m_core->dcd_M)?"M":" ",
+#define dcd_I VVAR(_thecpu__DOT__dcd_I)
+ m_core->dcdB &0x0f,
+ m_core->dcdA &0x0f,
+ m_core->dcd_I,
+ m_core->dcd_pc);
+ }
+ dbgins("Op - ",
+ m_core->op_ce,
+ m_core->op_valid,
+ m_core->op_gie,
+#ifdef OPT_PIPELINED
+ m_core->op_stall,
+#else
+ 0,
+#endif
+ op_pc(),
+#ifdef OPT_CIS
+ m_core->op_phase,
+#else
+ false,
+#endif
+ m_core->op_illegal);
+ if (m_dbgfp) {
+ fprintf(m_dbgfp, "\t\t\t(*OP=%d)[ A = 0x%08x , B = 0x%08x ], op_pc= %08x\n",
+ m_core->op_opn,
+ m_core->op_Av,
+ m_core->op_Bv,
+ m_core->r_op_pc);
+ }
+ dbgins("Al - ",
+ m_core->alu_ce,
+ m_core->alu_pc_valid,
+ m_core->alu_gie,
+#ifdef OPT_PIPELINED
+ alu_stall(),
+#else
+ 0,
+#endif
+ alu_pc(),
+#ifdef OPT_CIS
+ m_core->alu_phase,
+#else
+ false,
+#endif
+ m_core->alu_illegal);
+ if (m_core->wr_reg_ce)
+ fprintf(m_dbgfp, "WB::Reg[%2x] <= %08x\n",
+ m_core->wr_reg_id,
+ m_core->wr_gpreg_vl);
+ if (m_core->wr_flags_ce)
+ fprintf(m_dbgfp, "WB::Flags <= %02x\n",
+ m_core->alu_flags);
+
+ }
+
+#ifdef OPT_DIVIDE
+ if ((m_dbgfp)&&((m_core->div_valid)
+ ||(m_core->div_ce)
+ ||(m_core->div_busy)
+ )) {
+ fprintf(m_dbgfp, "DIV: %s %s %s %s[%2x] GP:%08x/SP:%08x %s:0x%08x\n",
+ (m_core->div_ce)?"CE":" ",
+ (m_core->div_busy)?"BUSY":" ",
+ (m_core->div_valid)?"VALID":" ",
+ (m_core->wr_reg_ce)?"REG-CE":" ",
+ m_core->wr_reg_id,
+ m_core->wr_gpreg_vl,
+ m_core->wr_spreg_vl,
+ (m_core->alu_pc_valid)?"PCV":" ",
+ alu_pc());
+
+ fprintf(m_dbgfp, "ALU-PC: %08x %s %s\n",
+ alu_pc(),
+ (m_core->alu_pc_valid)?"VALID":"",
+ (m_core->alu_gie)?"ALU-GIE":"");
+ }
+#endif
+
+#ifdef ZIPSYSTEM
+#define dma_state VVAR(_dma_controller__DOT__dma_state)
+#define dc_cyc VVAR(_dc_cyc)
+#define dc_stb VVAR(_dc_stb)
+#define dc_ack VVAR(_dc_ack)
+#define dc_err VVAR(_dc_err)
+#define dc_addr VVAR(_dc_addr)
+#define dc_data VVAR(_dc_data)
+#define dma_last_read_req VVAR(_dma_controller__DOT__last_read_request)
+#define dma_last_read_ack VVAR(_dma_controller__DOT__last_read_ack)
+#define dma_nracks VVAR(_dma_controller__DOT__nracks)
+#define dma_nread VVAR(_dma_controller__DOT__nread)
+#define dma_last_write_req VVAR(_dma_controller__DOT__last_write_request)
+#define dma_last_write_ack VVAR(_dma_controller__DOT__last_write_ack)
+#define dma_nwacks VVAR(_dma_controller__DOT__nwacks)
+#define dma_nwritten VVAR(_dma_controller__DOT__nwritten)
+ if (m_core->dma_state) {
+ fprintf(m_dbgfp, "DMA[%d]%s%s%s%s@%08x,%08x [%d%d/%4d/%4d] -> [%d%d/%04d/%04d]\n",
+ m_core->dma_state,
+ (m_core->dc_cyc)?"C":" ",
+ (m_core->dc_stb)?"S":" ",
+ (m_core->dc_ack)?"A":" ",
+ (m_core->dc_err)?"E":" ",
+ m_core->dc_addr<<2,
+ (m_core->dc_data),
+ m_core->dma_last_read_req,
+ m_core->dma_last_read_ack,
+ m_core->dma_nracks,
+ m_core->dma_nread,
+ m_core->dma_last_write_req,
+ m_core->dma_last_write_ack,
+ m_core->dma_nwacks,
+ m_core->dma_nwritten);
+ }
+#endif
+ if (((m_core->alu_pc_valid)
+ ||(m_core->mem_pc_valid))
+ &&(!m_core->new_pc)) {
+ unsigned long iticks = m_tickcount - m_last_instruction_tickcount;
+ if (m_profile_fp) {
+ unsigned buf[2];
+ buf[0] = alu_pc();
+ buf[1] = iticks;
+ fwrite(buf, sizeof(unsigned), 2, m_profile_fp);
+ }
+ m_last_instruction_tickcount = m_tickcount;
+ }
+ }
+
+ bool test_success(void) {
+ if ((m_exit)&&(m_rcode == 0))
+ return true;
+ return ((!m_core->r_gie)
+ &&(m_core->r_sleep));
+ }
+
+ unsigned op_pc(void) {
+ return m_core->r_op_pc-4;
+ }
+
+ bool pfstall(void) {
+ return((!(m_core->pformem_owner))
+ ||(m_core->cpu_stall));
+ }
+ unsigned dcd_Aid(void) {
+ return (m_core->dcdA);
+ }
+ unsigned dcd_Bid(void) {
+ return (m_core->dcdB);
+ }
+
+ bool op_valid(void) {
+ return (m_core->op_valid !=0);
+ }
+
+ bool mem_busy(void) {
+ // return m_core->v__DOT__thecpu__DOT__mem_busy;
+#ifdef OPT_PIPELINED
+ return m_core->mem_cyc;
+#else
+ return 0;
+#endif
+ }
+
+ bool mem_stalled(void) {
+ bool a, b, c, d, wr_write_cc, wr_write_pc, op_gie;
+
+ wr_write_cc=((m_core->wr_reg_id&0x0f)==0x0e);
+ wr_write_pc=((m_core->wr_reg_id&0x0f)==0x0f);
+ op_gie = m_core->op_gie;
+
+#ifdef OPT_PIPELINED_BUS_ACCESS
+ //a = m_core->v__DOT__thecpu__DOT__mem_pipe_stalled;
+ a = mem_pipe_stalled();
+ b = (!m_core->op_pipe)&&(mem_busy());
+#else
+ a = false;
+ b = false;
+#endif
+ d = ((wr_write_pc)||(wr_write_cc));
+ c = ((m_core->wr_reg_ce)
+ &&(((m_core->wr_reg_id&0x010)?true:false)==op_gie)
+ &&d);
+ d =(m_core->op_valid_mem)&&((a)||(b)||(c));
+ return ((!m_core->master_ce)||(d));
+ }
+
+ unsigned alu_pc(void) {
+ /*
+ unsigned r = op_pc();
+ if (m_core->op_valid)
+ r--;
+ return r;
+ */
+ return m_core->alu_pc-4;
+ }
+
+ int alu_stall(void) {
+ bool stall;
+#ifdef OP_PIPELINED
+ stall = (m_core->master_stall)||(m_core->mem_rdbusy);
+ stall = (stall)&& m_core->op_valid_alu;
+ stall = (stall)|| ((m_core->wr_reg_ce)&&(m_core->wr_write_cc));
+#else
+ stall = (m_core->master_stall)&&(m_core->op_valid_alu);
+#endif
+ /*
+ unsigned r = op_pc();
+ if (m_core->op_valid)
+ r--;
+ return r;
+ */
+ return (stall)?1:0;
+ }
+
+#ifdef OPT_PIPELINED_BUS_ACCESS
+ bool mem_pipe_stalled(void) {
+ int r = 0;
+ r = ((m_core->r_wb_cyc_gbl)
+ ||(m_core->r_wb_cyc_lcl));
+ r = r && ((m_core->mem_stall)
+ ||(
+ ((!m_core->mem_stb_gbl)
+ &&(!m_core->mem_stb_lcl))));
+ return r;
+ // return m_core->v__DOT__thecpu__DOT__mem_pipe_stalled;
+ }
+#endif
+
+ bool test_failure(void) {
+ if ((m_exit)&&(m_rcode != 0))
+ return true;
+ if (m_core->r_sleep)
+ return false;
+ return false;
+ }
+
+ void wb_write(unsigned a, unsigned int v) {
+ int errcount = 0;
+ mvprintw(0,35, "%40s", "");
+ mvprintw(0,40, "wb_write(%d,%x)", a, v);
+ m_core->i_dbg_cyc = 1;
+ m_core->i_dbg_stb = 1;
+ m_core->i_dbg_we = 1;
+ m_core->i_dbg_addr = (a>>2) & 1;
+ m_core->i_dbg_data = v;
+
+ while((errcount++ < 100)&&(m_core->o_dbg_stall))
+ tick();
+ tick();
+
+ m_core->i_dbg_stb = 0;
+ while((errcount++ < 100)&&(!m_core->o_dbg_ack))
+ tick();
+
+ // Release the bus
+ m_core->i_dbg_cyc = 0;
+ m_core->i_dbg_stb = 0;
+ tick();
+ mvprintw(0,35, "%40s", "");
+ mvprintw(0,40, "wb_write -- complete");
+
+
+ if (errcount >= 100) {
+ if (m_dbgfp) fprintf(m_dbgfp, "WB-WRITE: ERRCount = %d, BOMB!!\n", errcount);
+ m_bomb = true;
+ }
+ }
+
+ unsigned long wb_read(unsigned a) {
+ unsigned int v;
+ int errcount = 0;
+ mvprintw(0,35, "%40s", "");
+ mvprintw(0,40, "wb_read(0x%08x)", a);
+ m_core->i_dbg_cyc = 1;
+ m_core->i_dbg_stb = 1;
+ m_core->i_dbg_we = 0;
+ m_core->i_dbg_addr = (a>>2) & 1;
+
+ while((errcount++<100)&&(m_core->o_dbg_stall))
+ tick();
+ tick();
+
+ m_core->i_dbg_stb = 0;
+ while((errcount++<100)&&(!m_core->o_dbg_ack))
+ tick();
+ v = m_core->o_dbg_data;
+
+ // Release the bus
+ m_core->i_dbg_cyc = 0;
+ m_core->i_dbg_stb = 0;
+ tick();
+
+ mvprintw(0,35, "%40s", "");
+ mvprintw(0,40, "wb_read = 0x%08x", v);
+
+ if (errcount >= 100) {
+ if (m_dbgfp) fprintf(m_dbgfp, "WB-READ: ERRCount = %d, BOMB!!\n", errcount);
+ m_bomb = true;
+ }
+ return v;
+ }
+
+ void cursor_up(void) {
+#ifdef ZIPSYSTEM
+ if (m_cursor > 3)
+ m_cursor -= 4;
+#else
+ if (m_cursor > 12+3)
+ m_cursor =- 4;
+#endif
+ } void cursor_down(void) {
+ if (m_cursor < 40)
+ m_cursor += 4;
+ } void cursor_left(void) {
+#ifdef ZIPSYSTEM
+ if (m_cursor > 0)
+ m_cursor--;
+#else
+ if (m_cursor > 12)
+ m_cursor--;
+#endif
+ else m_cursor = 43;
+ } void cursor_right(void) {
+#ifdef ZIPSYSTEM
+ if (m_cursor < 43)
+ m_cursor++;
+ else m_cursor = 0;
+#else
+ if (m_cursor < 43)
+ m_cursor++;
+ else m_cursor = 12;
+#endif
+ }
+
+ int cursor(void) { return m_cursor; }
+
+ void jump_to(ZIPI address) {
+ if (m_dbgfp)
+ fprintf(m_dbgfp, "JUMP_TO(%08x) ... Setting PC to %08x\n", address, address & -4);
+#ifdef OPT_SINGLE_FETCH
+ m_core->new_pc = 1;
+ m_core->pf_pc = address;
+#else
+ m_core->pf_pc = address & -4;
+#define pf_request_address VVAR(_thecpu__DOT__pf_request_address)
+ m_core->pf_request_address = address;
+#endif
+ // m_core->v__DOT__thecpu__DOT__clear_pipeline = 1;
+ m_core->new_pc = 1;
+ }
+
+ void dump_state(void) {
+ if (m_dbgfp)
+ dump_state(m_dbgfp);
+ }
+
+ void dump_state(FILE *fp) {
+ if (!fp)
+ return;
+ fprintf(fp, "FINAL STATE: %s\n",
+ (m_state.m_gie)?"GIE(User-Mode)":"Supervisor-mode");
+ fprintf(fp, "Supervisor Registers\n");
+ for(int i=0; i<16; i++) {
+ char str[16];
+ if (i==13)
+ sprintf(str, "sSP");
+ else if (i==14)
+ sprintf(str, "sCC");
+ else if (i==15)
+ sprintf(str, "sPC");
+ else // if (i<=12)
+ sprintf(str, "s-%2d", i);
+ dbgreg(fp, i, str, m_state.m_sR[i]);
+ if ((i&3)==3)
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "User Registers\n");
+ for(int i=0; i<16; i++) {
+ char str[16];
+ if (i==13)
+ sprintf(str, "uSP");
+ else if (i==14)
+ sprintf(str, "uCC");
+ else if (i==15)
+ sprintf(str, "uPC");
+ else // if (i<=12)
+ sprintf(str, "u-%2d", i);
+ dbgreg(fp, i, str, m_state.m_uR[i]);
+ if ((i&3)==3)
+ fprintf(fp, "\n");
+ }
+ }
+
+ void dump(const uint32_t *regp) {
+ uint32_t uccv, iccv;
+
+ if (!m_console)
+ return;
+
+ fflush(stderr);
+ fflush(stdout);
+ printf("ZIPM--DUMP: ");
+ if (m_core->r_gie)
+ printf("Interrupts-enabled\n");
+ else
+ printf("Supervisor mode\n");
+ printf("\n");
+
+ iccv = m_core->w_iflags;
+ uccv = m_core->w_uflags;
+
+ printf("sR0 : %08x ", regp[0]);
+ printf("sR1 : %08x ", regp[1]);
+ printf("sR2 : %08x ", regp[2]);
+ printf("sR3 : %08x\n",regp[3]);
+ printf("sR4 : %08x ", regp[4]);
+ printf("sR5 : %08x ", regp[5]);
+ printf("sR6 : %08x ", regp[6]);
+ printf("sR7 : %08x\n",regp[7]);
+ printf("sR8 : %08x ", regp[8]);
+ printf("sR9 : %08x ", regp[9]);
+ printf("sR10: %08x ", regp[10]);
+ printf("sR11: %08x\n",regp[11]);
+ printf("sR12: %08x ", regp[12]);
+ printf("sSP : %08x ", regp[13]);
+ printf("sCC : %08x ", iccv);
+ printf("sPC : %08x\n",regp[15]);
+
+ printf("\n");
+
+ printf("uR0 : %08x ", regp[16]);
+ printf("uR1 : %08x ", regp[17]);
+ printf("uR2 : %08x ", regp[18]);
+ printf("uR3 : %08x\n",regp[19]);
+ printf("uR4 : %08x ", regp[20]);
+ printf("uR5 : %08x ", regp[21]);
+ printf("uR6 : %08x ", regp[22]);
+ printf("uR7 : %08x\n",regp[23]);
+ printf("uR8 : %08x ", regp[24]);
+ printf("uR9 : %08x ", regp[25]);
+ printf("uR10: %08x ", regp[26]);
+ printf("uR11: %08x\n",regp[27]);
+ printf("uR12: %08x ", regp[28]);
+ printf("uSP : %08x ", regp[29]);
+ printf("uCC : %08x ", uccv);
+ printf("uPC : %08x\n",regp[31]);
+ printf("\n");
+ fflush(stderr);
+ fflush(stdout);
+ }
+
+
+ void execsim(const uint32_t imm) {
+ uint32_t *regp = m_core->cpu_regs;
+ int rbase;
+ rbase = (m_core->r_gie)?16:0;
+
+ fflush(stdout);
+ if ((imm & 0x03fffff)==0)
+ // Ignore a NOOP
+ return;
+ // fprintf(stderr, "SIM-INSN(0x%08x)\n", imm);
+ if ((imm & 0x0fffff)==0x00100) {
+ // SIM Exit(0)
+ m_rcode = 0;
+ m_exit = true;
+ } else if ((imm & 0x0ffff0)==0x00310) {
+ // SIM Exit(User-Reg)
+ int rcode;
+ rcode = regp[(imm&0x0f)+16] & 0x0ff;
+ m_rcode = rcode;
+ m_exit = true;
+ } else if ((imm & 0x0ffff0)==0x00300) {
+ // SIM Exit(Reg)
+ int rcode;
+ rcode = regp[(imm&0x0f)+rbase] & 0x0ff;
+ m_rcode = rcode;
+ m_exit = true;
+ } else if ((imm & 0x0fff00)==0x00100) {
+ // SIM Exit(Imm)
+ int rcode;
+ rcode = imm & 0x0ff;
+ m_exit = true;
+ m_rcode = rcode;
+ } else if ((imm & 0x0fffff)==0x002ff) {
+ // Full/unconditional dump
+ if (m_console) {
+ printf("SIM-DUMP\n");
+ dump(regp);
+ }
+ } else if ((imm & 0x0ffff0)==0x00200) {
+ // Dump a register
+ if (m_console) {
+ int rid = (imm&0x0f)+rbase;
+ //printf("%8lu @%08x R[%2d] = 0x%08x\n",
+ // m_time_ps/1000,
+ // m_core->cpu_ipc, rid, regp[rid]);
+ printf("R[%2d] = 0x%08x\n", rid&0x0f,regp[rid]);
+ }
+ } else if ((imm & 0x0ffff0)==0x00210) {
+ // Dump a user register
+ if (m_console) {
+ int rid = (imm&0x0f);
+ /*
+ printf("%8lu @%08x uR[%2d] = 0x%08x\n",
+ m_time_ps/1000, m_core->cpu_ipc,
+ rid, regp[rid+16]);
+ */
+ printf("uR[%2d] = 0x%08x\n",
+ rid, regp[rid+16]);
+ }
+ } else if ((imm & 0x0ffff0)==0x00230) {
+ // SOUT[User Reg]
+ if (m_console) {
+ int rid = (imm&0x0f)+16;
+ printf("%c", regp[rid]&0x0ff);
+ }
+ } else if ((imm & 0x0fffe0)==0x00220) {
+ // SOUT[User Reg]
+ if (m_console) {
+ int rid = (imm&0x0f)+rbase;
+ printf("%c", regp[rid]&0x0ff);
+ }
+ } else if ((imm & 0x0fff00)==0x00400) {
+ if (m_console) {
+ // SOUT[Imm]
+ printf("%c", imm&0x0ff);
+ }
+ } else { // if ((insn & 0x0f7c00000)==0x77800000)
+ if (m_console) {
+ uint32_t immv = imm & 0x03fffff;
+ // Simm instruction that we dont recognize
+ // if (imm)
+ // printf("SIM 0x%08x\n", immv);
+ printf("SIM 0x%08x (ipc = %08x, upc = %08x)\n", immv,
+ m_core->cpu_ipc,
+ m_core->cpu_upc);
+ }
+ } if (m_console)
+ fflush(stdout);
+ }
+
+
+};
+
+void get_value(ZIPCPU_TB *tb) {
+ int wy, wx, ra;
+ int c = tb->cursor();
+
+ wx = (c & 0x03) * 20 + 9;
+ wy = (c>>2);
+ if (wy >= 3+4)
+ wy++;
+ if (wy > 3)
+ wy += 2;
+ wy++;
+
+ if (c >= 12)
+ ra = c - 12;
+ else
+ ra = c + 32;
+
+ bool done = false;
+ char str[16];
+ int pos = 0; str[pos] = '\0';
+ while(!done) {
+ int chv = getch();
+ switch(chv) {
+ case KEY_ESCAPE:
+ pos = 0; str[pos] = '\0'; done = true;
+ break;
+ case KEY_RETURN: case KEY_ENTER: case KEY_UP: case KEY_DOWN:
+ done = true;
+ break;
+ case KEY_LEFT: case KEY_BACKSPACE:
+ if (pos > 0) pos--;
+ break;
+ case CTRL('L'): redrawwin(stdscr); break;
+ case KEY_CLEAR:
+ pos = 0;
+ break;
+ case '0': case ' ': str[pos++] = '0'; break;
+ case '1': str[pos++] = '1'; break;
+ case '2': str[pos++] = '2'; break;
+ case '3': str[pos++] = '3'; break;
+ case '4': str[pos++] = '4'; break;
+ case '5': str[pos++] = '5'; break;
+ case '6': str[pos++] = '6'; break;
+ case '7': str[pos++] = '7'; break;
+ case '8': str[pos++] = '8'; break;
+ case '9': str[pos++] = '9'; break;
+ case 'A': case 'a': str[pos++] = 'A'; break;
+ case 'B': case 'b': str[pos++] = 'B'; break;
+ case 'C': case 'c': str[pos++] = 'C'; break;
+ case 'D': case 'd': str[pos++] = 'D'; break;
+ case 'E': case 'e': str[pos++] = 'E'; break;
+ case 'F': case 'f': str[pos++] = 'F'; break;
+ }
+
+ if (pos > 8)
+ pos = 8;
+ str[pos] = '\0';
+
+ attron(A_NORMAL | A_UNDERLINE);
+ mvprintw(wy, wx, "%-8s", str);
+ if (pos > 0) {
+ attron(A_NORMAL | A_UNDERLINE | A_BLINK);
+ mvprintw(wy, wx+pos-1, "%c", str[pos-1]);
+ }
+ attrset(A_NORMAL);
+ }
+
+ if (pos > 0) {
+ int v;
+ v = strtoul(str, NULL, 16);
+ if (!tb->halted()) {
+ switch(ra) {
+ case 15:
+ tb->m_core->cpu_ipc = v;
+ if (!tb->m_core->r_gie) {
+ tb->jump_to(v);
+ // tb->m_core->v__DOT__thecpu__DOT__clear_pipeline = 1;
+ tb->m_core->alu_pc_valid = 0;
+#ifdef OPT_PIPELINED
+ // tb->m_core->v__DOT__thecpu__DOT__dcd_ce = 0;
+ tb->m_core->dcd_valid = 0;
+#endif
+ tb->m_core->op_valid = 0;
+ }
+ break;
+ case 31:
+ tb->m_core->cpu_upc = v;
+ if (tb->m_core->r_gie) {
+ tb->jump_to(v);
+ // tb->m_core->v__DOT__thecpu__DOT__clear_pipeline = 1;
+ tb->m_core->alu_pc_valid = 0;
+#ifdef OPT_PIPELINED
+ tb->m_core->dcd_valid = 0;
+#endif
+ tb->m_core->op_valid = 0;
+ }
+ break;
+#ifdef ZIPSYSTEM
+ case 32: tb->m_core->pic_data = v; break;
+ case 33: tb->m_core->watchdog = v; break;
+ // case 34: tb->m_core->v__DOT__manualcache__DOT__cache_base = v; break;
+ case 35: tb->m_core->int_state = v; break;
+ case 36: tb->m_core->timer_a = v; break;
+ case 37: tb->m_core->timer_b = v; break;
+ case 38: tb->m_core->timer_c = v; break;
+ case 39: tb->m_core->jiffies = v; break;
+ case 44: tb->m_core->utc_data = v; break;
+ case 45: tb->m_core->uoc_data = v; break;
+ case 46: tb->m_core->upc_data = v; break;
+ case 47: tb->m_core->uic_data = v; break;
+#else
+ case 32: case 33: case 34: case 35:
+ case 36: case 37: case 38: case 39:
+ case 40: case 41: case 42: case 43:
+ case 44: case 45: case 46: case 47:
+ break;
+#endif
+ default:
+ tb->m_core->regset[ra] = v;
+ break;
+ }
+ } else
+ tb->cmd_write(ra, v);
+ }
+}
+
+
+
+void usage(void) {
+ printf("USAGE: zippy_tb [-a] \n");
+ printf("\n");
+ printf("\tWhere testfile.out is an output file from the assembler.\n");
+ printf("\tThis file needs to be in a raw format and not an ELF\n");
+ printf("\texecutable. It will be inserted into memory at a memory\n");
+ printf("\taddress of 0x0100000. The memory device itself, the only\n");
+ printf("\tdevice supported by this simulator, occupies addresses from\n");
+ printf("\t0x0100000 to 0x01fffff.\n");
+ printf("\n");
+ printf("\t-a\tSets the testbench to run automatically without any\n");
+ printf("\t\tuser interaction.\n");
+ printf("\n");
+ printf("\tUser Commands:\n");
+ printf("\t\tWhen the test bench is run interactively, the following\n");
+ printf("\t\tkey strokes are recognized:\n");
+ printf("\t\t\'h\'\tHalt the processor using the external interface.\n");
+ printf("\t\t\'g\'\tLet the processor run at full throttle with no.\n");
+ printf("\t\t\tuser intervention.\n");
+ printf("\t\t\'q\'\tQuit the simulation.\n");
+ printf("\t\t\'r\'\tReset the processor.\n");
+ printf("\t\t\'s\'\tStep the CPU using the external stepping command\n");
+ printf("\t\t\tThis may consume more than one tick.\n");
+ printf("\t\t\'t\'\tClock a single tick through the system.\n");
+}
+
+bool signalled = false;
+
+void sigint(int v) {
+ signalled = true;
+}
+
+int main(int argc, char **argv) {
+ Verilated::commandArgs(argc, argv);
+ ZIPCPU_TB *tb = new ZIPCPU_TB();
+ bool autorun = false, exit_on_done = false, autostep=false;
+ ZIPI entry = RAMBASE;
+
+ signal(SIGINT, sigint);
+
+ if (argc <= 1) {
+ usage();
+ exit(-1);
+ } else {
+ for(int argn=1; argnm_len; i++) {
+ const char *data;
+
+ secp = secpp[i];
+ assert(secp->m_start >= RAMBASE);
+ assert(secp->m_start+secp->m_len <= RAMBASE+RAMWORDS);
+ assert((secp->m_len & 3)==0);
+
+ data = &secp->m_data[0];
+ tb->m_mem.load((secp->m_start-RAMBASE)>>2, data, secp->m_len);
+ }
+ } else {
+ fprintf(stderr, "No access to %s, or unknown arg\n", argv[argn]);
+ exit(-2);
+ }
+ }
+ }
+
+
+ if (autorun) {
+ bool done = false;
+
+ printf("Running in non-interactive mode\n");
+ tb->m_console = true;
+ tb->reset();
+ tb->m_core->cpu_halt = 1;
+ tb->wb_write(CMD_REG, CMD_HALT|CMD_RESET|15);
+ tb->wb_write(CMD_DATA, entry);
+ tb->wb_write(CMD_REG, 15);
+ tb->m_bomb = false;
+ while(!done) {
+ tb->tick();
+
+ /*
+ printf("PC = %08x:%08x (%08x)\n",
+ tb->m_core->cpu_ipc,
+ tb->m_core->cpu_upc,
+ tb->m_core->alu_pc);
+ */
+
+ done = (tb->test_success())||(tb->test_failure());
+ done = done || signalled;
+ }
+ } else if (autostep) {
+ bool done = false;
+
+ printf("Running in non-interactive mode, via step commands\n");
+ tb->m_console = true;
+ tb->reset();
+ tb->wb_write(CMD_REG, CMD_HALT|CMD_RESET|CPU_sPC);
+ tb->wb_write(CMD_DATA, entry);
+ tb->wb_write(CMD_REG, CPU_sPC);
+ tb->m_bomb = false;
+ while(!done) {
+ tb->wb_write(CMD_REG, CMD_STEP);
+ /*
+ printf("PC = %08x:%08x (%08x)\n",
+ tb->m_core->cpu_ipc, tb->m_core->cpu_upc,
+ tb->m_core->alu_pc);
+ */
+ done = (tb->test_success())||(tb->test_failure());
+ done = done || signalled;
+ }
+ } else { // Interactive
+ initscr();
+ raw();
+ noecho();
+ keypad(stdscr, true);
+
+ // tb->reset();
+ // for(int i=0; i<2; i++)
+ // tb->tick();
+ tb->m_core->cmd_reset = 1;
+ tb->m_core->cpu_halt = 1;
+ tb->tick();
+
+ tb->m_core->cmd_reset = 0;
+ tb->m_core->cpu_halt = 0;
+ tb->tick();
+ tb->jump_to(entry);
+ tb->tick();
+ tb->jump_to(entry);
+ tb->tick();
+ tb->jump_to(entry);
+
+
+ // For debugging purposes: do we wish to skip some number of
+ // instructions to fast forward to a time of interest??
+ for(int i=0; i<0; i++) {
+ tb->m_core->cpu_halt = 0;
+ tb->tick();
+ }
+
+ int chv = 'q';
+
+ bool done = false, halted = true, manual = true,
+ high_speed = false;
+
+ halfdelay(1);
+ // tb->wb_write(CMD_REG, CMD_HALT | CMD_RESET);
+ // while((tb->wb_read(CMD_REG) & (CMD_HALT|CMD_STALL))==(CMD_HALT|CMD_STALL))
+ // tb->show_state();
+
+ while(!done) {
+ if ((high_speed)&&(!manual)&&(!halted)) {
+ // chv = getch();
+
+ struct pollfd fds[1];
+ fds[0].fd = STDIN_FILENO;
+ fds[0].events = POLLIN;
+
+ if (poll(fds, 1, 0) > 0)
+ chv = getch();
+ else
+ chv = ERR;
+
+ } else {
+ chv = getch();
+ }
+ switch(chv) {
+ case 'h': case 'H':
+ tb->wb_write(CMD_REG, CMD_HALT);
+ if (!halted)
+ erase();
+ halted = true;
+ break;
+ case 'G':
+ high_speed = true;
+ // cbreak();
+ case 'g':
+ tb->wb_write(CMD_REG, 0);
+ if (halted)
+ erase();
+ halted = false;
+ manual = false;
+ break;
+ case 'm':
+ tb->show_user_timers(false);
+ break;
+ case 'q': case 'Q':
+ done = true;
+ break;
+ case 'r': case 'R':
+ if (manual)
+ tb->reset();
+ else
+ tb->wb_write(CMD_REG, CMD_RESET|CMD_HALT);
+ halted = true;
+ erase();
+ break;
+ case 's':
+ if (!halted)
+ erase();
+ tb->step();
+ manual = false;
+ halted = true;
+ // if (high_speed)
+ // halfdelay(1);
+ high_speed = false;
+ break;
+ case 'S':
+ if ((!manual)||(halted))
+ erase();
+ manual = true;
+ halted = true;
+ // if (high_speed)
+ // halfdelay(1);
+ high_speed = false;
+ tb->m_core->cpu_halt = 0;
+ tb->m_core->cmd_step = 1;
+ tb->eval();
+ tb->tick();
+ break;
+ case 'T': //
+ if ((!manual)||(halted))
+ erase();
+ manual = true;
+ halted = true;
+ // if (high_speed)
+ // halfdelay(1);
+ high_speed = false;
+ tb->m_core->cpu_halt = 1;
+ tb->m_core->cmd_step = 0;
+ tb->eval();
+ tb->tick();
+ break;
+ case 't':
+ if ((!manual)||(halted))
+ erase();
+ manual = true;
+ halted = false;
+ // if (high_speed)
+ // halfdelay(1);
+ high_speed = false;
+ tb->m_core->cpu_halt = 0;
+ tb->tick();
+ break;
+ case 'u':
+ tb->show_user_timers(true);
+ break;
+ case KEY_IC: case KEY_ENTER: case KEY_RETURN:
+ get_value(tb);
+ break;
+ case KEY_UP: tb->cursor_up(); break;
+ case KEY_DOWN: tb->cursor_down(); break;
+ case KEY_LEFT: tb->cursor_left(); break;
+ case KEY_RIGHT: tb->cursor_right(); break;
+ case CTRL('L'): redrawwin(stdscr); break;
+ case ERR: case KEY_CLEAR:
+ default:
+ if (!manual)
+ tb->tick();
+ }
+
+ if (manual) {
+ tb->show_state();
+ } else if (halted) {
+ if (tb->m_dbgfp)
+ fprintf(tb->m_dbgfp, "\n\nREAD-STATE ******\n");
+ tb->read_state();
+ } else
+ tb->show_state();
+
+ if (tb->m_core->i_reset)
+ done =true;
+ if ((tb->m_bomb)||(signalled))
+ done = true;
+
+ if (exit_on_done) {
+ if (tb->test_success())
+ done = true;
+ if (tb->test_failure())
+ done = true;
+ }
+ }
+ endwin();
+ }
+#ifdef MANUAL_STEPPING_MODE
+ else { // Manual stepping mode
+ tb->jump_to(entry);
+ tb->show_state();
+
+ while('q' != tolower(chv = getch())) {
+ tb->tick();
+ tb->show_state();
+
+ if (tb->test_success())
+ break;
+ else if (tb->test_failure())
+ break;
+ else if (signalled)
+ break;
+ }
+ }
+#endif
+
+ printf("\n");
+ if (tb->test_failure()) {
+ tb->dump_state();
+ }
+
+#ifdef ZIPSYSTEM
+ printf("Clocks used : %08x\n", tb->m_core->mtc_data);
+ printf("Instructions Issued : %08x\n", tb->m_core->mic_data);
+ printf("Tick Count : %08lx\n", tb->m_tickcount);
+ if (tb->m_core->mtc_data != 0)
+ printf("Instructions / Clock: %.2f\n",
+ (double)tb->m_core->mic_data
+ / (double)tb->m_core->mtc_data);
+#endif
+
+ int rcode = 0;
+ if (tb->m_bomb) {
+ printf("TEST BOMBED\n");
+ rcode = -1;
+ } else if (tb->test_success()) {
+ printf("SUCCESS!\n");
+ } else if (tb->test_failure()) {
+ rcode = -2;
+ printf("TEST FAILED!\n");
+ } else
+ printf("User quit\n");
+ delete tb;
+ exit(rcode);
+}
+
Index: verilator/zipmmu_tb.cpp
===================================================================
--- verilator/zipmmu_tb.cpp (revision 208)
+++ verilator/zipmmu_tb.cpp (revision 209)
@@ -27,6 +27,11 @@
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
+// You should have received a copy of the GNU General Public License along
+// with this program. (It's in the $(ROOT)/doc directory. Run make with no
+// target there if the PDF file isn't present.) If not, see
+// for a copy.
+//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
@@ -42,10 +47,46 @@
#include "Vzipmmu_tb.h"
#define MMUFLAG_RONW 8 // Read only (not writeable)
-#define MMUFLAG_ACCS 4 // Accessed
+#define MMUFLAG_EXE 4 // Page may be executed
#define MMUFLAG_CCHE 2 // Cachable
-#define MMUFLAG_THSP 1 // Page has this context
+#define MMUFLAG_ACCS 1 // Accessed
+#define ROFLAG 8 // This page is read-only
+#define EXFLAG 4 // This page is executable
+#define CHFLAG 2 // This page may be cached
+#define AXFLAG 1 // This page has been accessed since loading
+#define setup_stb i_ctrl_cyc_stb
+#define setup_ack o_rtn_ack
+#define setup_stall o_rtn_stall
+#define setup_data o_rtn_data
+#define mem_cyc v__DOT__mem_cyc
+#define mem_stb v__DOT__mem_stb
+#define mem_we v__DOT__mem_we
+#define mem_r_we v__DOT__mut__DOT__r_we
+#define mem_r_valid v__DOT__mut__DOT__r_valid
+#define mem_addr v__DOT__mem_addr
+#define mem_err v__DOT__mem_err
+#define wr_vtable v__DOT__mut__DOT__wr_vtable
+#define wr_ptable v__DOT__mut__DOT__wr_ptable
+#define wr_control v__DOT__mut__DOT__wr_control
+#define z_context __PVT__mut__DOT__z_context
+#define context_word v__DOT__mut__DOT__r_context_word
+#define r_pending v__DOT__mut__DOT__r_pending
+#define r_we v__DOT__mut__DOT__r_we
+#define r_valid v__DOT__mut__DOT__r_valid
+#define r_addr v__DOT__mut__DOT__r_addr
+#define r_data v__DOT__mut__DOT__r_data
+
+#define R_CONTROL 0
+#define R_STATUS 4
+#define R_TABLESZ(LGSZ) (8<>(LGPGSZ-4))<<4)&((1<::tick();
@@ -69,47 +109,43 @@
if ((m_debug)&&(writeout)) {
printf("%08lx-MMU: ", m_tickcount);
- printf("(%s%s%s%s) %08x (%s%s%s)%08x%s %s %08x/%08x %s%s%s%s%s",
- (m_core->i_ctrl_cyc_stb)?"CT":" ",
+ printf("(%s%s%s%s%s%s) %08x (%s%s%s)%08x%s %s %08x/%08x %s%s%s%s",
+ (m_core->setup_stb)?"CT":" ",
(m_core->i_wbm_cyc)?"CYC":" ",
(m_core->i_wbm_stb)?"STB":" ",
(m_core->i_wb_we)?"WE":" ",
+ (m_core->i_gie)?"IE":" ",
+ (m_core->i_exe)?"EX":" ",
(m_core->i_wb_addr),
- (m_core->v__DOT__mem_cyc)?"CYC":" ",
- (m_core->v__DOT__mem_stb)?"STB":" ",
-#define v__DOT__mem_we v__DOT__mut__DOT__r_we
- (m_core->v__DOT__mem_we)?"WE":" ",
- (m_core->v__DOT__mem_addr),
- (m_core->v__DOT__mem_err)?"ER":" ",
+ (m_core->mem_cyc)?"CYC":" ",
+ (m_core->mem_stb)?"STB":" ",
+ (m_core->mem_we)?"WE":" ",
+ (m_core->mem_addr),
+ (m_core->mem_err)?"ER":" ",
(m_core->i_wb_we)?"<-":"->",
(m_core->i_wb_we)?m_core->i_wb_data:m_core->o_rtn_data,
- (m_core->v__DOT__mem_we)?m_core->v__DOT__mut__DOT__r_data:m_core->v__DOT__mem_odata,
+ (m_core->mem_we)?m_core->r_data:m_core->v__DOT__mem_odata,
(m_core->o_rtn_stall)?"STALL":" ",
- (m_core->v__DOT__mut__DOT__setup_ack)?"S":" ",
(m_core->o_rtn_ack )?"ACK":" ",
(m_core->o_rtn_miss)?"MISS":" ",
(m_core->o_rtn_err )?"ERR":" ");
- printf("[%d,%d]",
- m_core->v__DOT__mut__DOT__wr_vtable,
- m_core->v__DOT__mut__DOT__wr_ptable);
- printf("[%d,%d,%04x]",
- m_core->v__DOT__mut__DOT__wr_control,
- m_core->v__DOT__mut__DOT__z_context,
+ printf("[%c]",
+ (m_core->wr_control)?'C'
+ :(m_core->wr_vtable)?'V'
+ :(m_core->wr_ptable)?'P'
+ :'-');
+ printf("[%c,%04x]",
+ (m_core->v__DOT__mut__DOT__kernel_context)?'K'
+ :(m_core->v__DOT__mut__DOT__z_context)?'Z':'-',
m_core->v__DOT__mut__DOT__r_context_word);
- /*
- printf("[%08x,%08x-%08x]",
- m_core->v__DOT__mut__DOT__w_vtable_reg,
- m_core->v__DOT__mut__DOT__w_ptable_reg,
- m_core->v__DOT__mut__DOT__setup_data);
- */
printf(" %s[%s%s@%08x,%08x]",
- (m_core->v__DOT__mut__DOT__r_pending)?"R":" ",
- (m_core->v__DOT__mut__DOT__r_we)?"W":" ",
- (m_core->v__DOT__mut__DOT__r_valid)?"V":" ",
- (m_core->v__DOT__mut__DOT__r_addr),
- (m_core->v__DOT__mut__DOT__r_data));
- printf("@%2x[%s%s%s][%s%s%s%s]",
+ (m_core->r_pending)?"R":" ",
+ (m_core->r_we)?"W":" ",
+ (m_core->r_valid)?"V":" ",
+ (m_core->r_addr),
+ (m_core->r_data));
+ printf("@%2x[%s%s%s][%s%s%s%s%s]",
(m_core->v__DOT__mut__DOT__s_tlb_addr),
(m_core->v__DOT__mut__DOT__s_pending)?"P":" ",
(m_core->v__DOT__mut__DOT__s_tlb_hit)?"HT":" ",
@@ -117,33 +153,37 @@
(m_core->v__DOT__mut__DOT__ro_flag)?"RO":" ",
(m_core->v__DOT__mut__DOT__simple_miss)?"SM":" ",
(m_core->v__DOT__mut__DOT__ro_miss)?"RM":" ",
+ (m_core->v__DOT__mut__DOT__exe_miss)?"EX":" ",
(m_core->v__DOT__mut__DOT__table_err)?"TE":" ");
//(m_core->v__DOT__mut__DOT__cachable)?"CH":" ");
/*
printf(" M[%016lx]",
m_core->v__DOT__mut__DOT__r_tlb_match);
- printf(" P[%3d] = 0x%08x, V=0x%08x, C=0x%08x, CTXT=%04x",
+ */
+ printf(" P[%3d%c] = 0x%03x, V=0x%03x, C=0x%04x, CTXT=%04x",
m_last_tlb_index,
+ ((m_core->v__DOT__mut__DOT__tlb_valid>>m_last_tlb_index)&1)?'V':'u',
m_core->v__DOT__mut__DOT__tlb_pdata[m_last_tlb_index],
m_core->v__DOT__mut__DOT__tlb_vdata[m_last_tlb_index],
m_core->v__DOT__mut__DOT__tlb_cdata[m_last_tlb_index],
m_core->v__DOT__mut__DOT__r_context_word);
- */
printf("\n");
}
}
void reset(void) {
- m_core->i_rst = 1;
+ m_core->i_reset = 1;
m_core->i_ctrl_cyc_stb = 0;
+ m_core->i_gie = 0;
+ m_core->i_exe = 0;
m_core->i_wbm_cyc = 0;
m_core->i_wbm_stb = 0;
tick();
- m_core->i_rst = 0;
+ m_core->i_reset = 0;
}
void wb_tick(void) {
- m_core->i_rst = 0;
+ m_core->i_reset = 0;
m_core->i_ctrl_cyc_stb = 0;
m_core->i_wbm_cyc = 0;
m_core->i_wbm_stb = 0;
@@ -153,7 +193,11 @@
}
unsigned operator[](unsigned a) {
- a &= ((1<>2)&(msk);
+// printf("OP[] ----> %08x\n", a);
return m_core->v__DOT__ram__DOT__mem[a];
}
@@ -164,12 +208,19 @@
printf("WB-READS(%08x)\n", a);
- m_core->i_ctrl_cyc_stb = 1;
+ m_core->i_ctrl_cyc_stb = 0;
m_core->i_wbm_cyc = 0;
m_core->i_wbm_stb = 0;
m_core->i_wb_we = 0;
- m_core->i_wb_addr= a;
+ m_core->i_wb_addr= a>>2;
+ if (m_core->i_gie) {
+ m_core->i_gie = 0;
+ wb_tick();
+ }
+
+ m_core->i_ctrl_cyc_stb = 1;
+
if (m_core->o_rtn_stall) {
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
tick();
@@ -209,16 +260,25 @@
printf("WB-WRITES(%08x,%08x)\n", a,v);
- m_core->i_ctrl_cyc_stb = 1;
+ m_core->i_ctrl_cyc_stb = 0;
+ m_core->i_exe = 0;
m_core->i_wbm_cyc = 0;
m_core->i_wbm_stb = 0;
m_core->i_wb_we = 1;
- m_core->i_wb_addr= a;
+ m_core->i_wb_addr= a>>2;
m_core->i_wb_data= v;
+ m_core->i_wb_sel= 15;
- if (a & 0x080)
- m_last_tlb_index = (a>>1)&0x3f;
+ if (m_core->i_gie) {
+ m_core->i_gie = 0;
+ wb_tick();
+ }
+ m_core->i_ctrl_cyc_stb = 1;
+
+ if (a & 0x0200)
+ m_last_tlb_index = (a>>3)&0x3f;
+
if (m_core->o_rtn_stall) {
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
tick();
@@ -260,7 +320,7 @@
m_core->i_wbm_cyc = 1;
m_core->i_wbm_stb = 1;
m_core->i_wb_we = 0;
- m_core->i_wb_addr= a;
+ m_core->i_wb_addr= a>>2;
if (m_core->o_rtn_stall) {
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
@@ -345,7 +405,7 @@
m_core->i_wbm_cyc = 1;
m_core->i_wbm_stb = 1;
m_core->i_wb_we = 0;
- m_core->i_wb_addr = a;
+ m_core->i_wb_addr = a>>2;
rdidx =0; cnt = 0;
inc = 1;
@@ -417,8 +477,9 @@
m_core->i_wbm_cyc = 1;
m_core->i_wbm_stb = 1;
m_core->i_wb_we = 1;
- m_core->i_wb_addr= a;
+ m_core->i_wb_addr= a>>2;
m_core->i_wb_data= v;
+ m_core->i_wb_sel= 15;
if (m_core->o_rtn_stall)
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
@@ -497,8 +558,9 @@
m_core->i_wbm_cyc = 1;
m_core->i_wbm_stb = 1;
m_core->i_wb_we = 1;
+ m_core->i_wb_sel= 15;
for(unsigned stbcnt=0; stbcnti_wb_addr= a+stbcnt;
+ m_core->i_wb_addr= (a>>2)+stbcnt;
m_core->i_wb_data= buf[stbcnt];
errcount = 0;
@@ -592,26 +654,30 @@
int LGTBL, LGPGSZ, LGCTXT;
int c;
unsigned base;
- bool hdebug = tb->debug();
+ // bool hdebug = tb->debug();
- tb->debug(false);
- c=tb->setup_read(0);
+ // tb->debug(false);
+ c=tb->setup_read(R_CONTROL);
printf("CONTEXT-REG = %08x\n", c);
LGTBL = ((c>>24)&15);
- LGPGSZ= (((c>>20)&15)+8)&31;
+ LGPGSZ= (((c>>20)&15)+10)&31; // In bytes
LGCTXT= (((c>>16)&15)+1)&31;
c &= ((1< %08xP %s%s\n",
- idx, c, va, pa,
+ printf("INSTALL[%2d] %04x:%03x[%04x]%xV -> %03x[%04x]%xP %s%s\n",
+ idx, c,
+ (va>>LGPGSZ), LOCONTEXT(c)>>4, flags,
+ (pa>>LGPGSZ), HICONTEXT(c)>>4, 0,
(flags&MMUFLAG_RONW)?"RO":" ",
(flags&MMUFLAG_CCHE)?"Cachable":"");
- tb->setup_write(base , va|(( c &0x0ff)<<4)|flags);
- tb->setup_write(base+1, pa|(((c>>8)&0x0ff)<<4)|flags);
- tb->debug(hdebug);
+ tb->setup_write(base , va|(LOCONTEXT(c))|flags);
+ tb->setup_write(base+4, pa|(HICONTEXT(c)));
+ // tb->debug(hdebug);
+ tb->tick();
+ tb->m_core->i_gie = 1;
}
int main(int argc, char **argv) {
@@ -619,6 +685,7 @@
ZIPMMU_TB *tb = new ZIPMMU_TB;
unsigned *rdbuf; // *mbuf;
unsigned mlen = (1<opentrace("zipmmu_tb.vcd");
printf("Giving the core 2 cycles to start up\n");
@@ -636,66 +703,76 @@
uload(mlen, rdbuf);
- int LGADR, LGTBL, LGPGSZ, LGCTXT, sr;
+ int LGADR, LGTBL, LGPGSZ, LGCTXT, sr, PAGESZ;
- c=tb->setup_read(0);
+ c=tb->setup_read(R_CONTROL);
printf("CONTROL-REG = %08x\n = %2d\n", c, c);
- sr = tb->setup_read(1);
+ sr = tb->setup_read(R_STATUS);
printf("STATUS-REG = %08x = %2d\n", sr, sr);
LGADR = (((c>>28)&15)+17)&31;
LGTBL = ((c>>24)&15);
- LGPGSZ= (((c>>20)&15)+8)&31;
+ LGPGSZ= (((c>>20)&15)+10)&31;
+ PAGESZ= 1ul<>16)&15)+1)&31;
printf("LGADR = %08x = %2d\n", LGADR, LGADR);
printf("LGTBL = %08x = %2d\n", LGTBL, LGTBL);
printf("LGPGSZ = %08x = %2d\n", LGPGSZ, LGPGSZ);
printf("LGCTXT = %08x = %2d\n", LGCTXT, LGCTXT);
+ printf("PAGESZ = %08x = %2d\n", PAGESZ, PAGESZ);
// First, let's make sure we can read/write the context
printf("\n\nTest: Can we read/write the context register?\n");
- tb->setup_write(0,0x01fec);
- c=tb->setup_read(0);
- printf("CONTEXT = %08x (0x1fec?)\n", c&0x0ffff);
- if ((c&0x0ffff) != 0x01fec)
+ tb->setup_write(R_CONTROL,CONTEXT);
+ c=tb->setup_read(R_CONTROL);
+ printf("CONTEXT = %04x (0x%04x)\n", c &0x0ffff, CONTEXT & 0x0ffff);
+ if ((c&0x0ffff) != CONTEXT)
goto test_failure;
// Load the table with TLB misses
printf("\n\nTest: Can we load the table with TLB misses? (%d entries)\n", (1<setup_write((2<setup_write((2<setup_write(R_VENTRY(i), (LOCONTEXT(c))
+ |(((1<setup_write(R_PENTRY(i), (HICONTEXT(c))
+ |(((1<setup_read((2<setup_read((2< %08x\n", i, v, p);
- if (v != (unsigned)(0x00f72+(((1<setup_read(R_VENTRY(i));
+ p=tb->setup_read(R_PENTRY(i));
+
+ printf("TBL[%2d] = %08x -> %08x", i, v, p);
+ printf("\tEXPECTING %08x -> %08x\n",
+ (unsigned)((LOCONTEXT(c))|(((1<m_core->i_gie = 1;
+ tb->tick();
tberr = false;
- tb->wb_write(0xffffffff, 0x0fe, &tberr);
+ tb->wb_write(0xfffffffc, 0x0fe, &tberr);
if ((!tberr)||(!tb->miss())||(tb->err())) {
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
(tberr)?"true":"false", (tb->miss())?"true":"false",
(tb->err())?"true":"false");
goto test_failure;
- }
+ } printf("-- PASS\n\n");
tberr = false;
- install_page(tb, 0, 0x0ffffffff, (1<wb_write(0xffffffff, 0x0fe, &tberr);
@@ -704,46 +781,48 @@
(tberr)?"true":"false", (tb->miss())?"true":"false",
(tb->err())?"true":"false");
goto test_failure;
- }
+ } printf("-- PASS\n\n");
tberr = false;
printf("\n\nTest: What if we make this into a writeable page?\n");
- install_page(tb, 0, 0xffffffff, (1<wb_write(0xffffffff, 0x0fe, &tberr);
+ install_page(tb, 0, 0xfffffffc, (4<m_core->i_gie = 1;
+ tb->m_core->i_exe = 0;
+ tb->wb_write(0xfffffff8, 0x0fe, &tberr);
if (tberr) {
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
(tberr)?"true":"false", (tb->miss())?"true":"false",
(tb->err())?"true":"false");
goto test_failure;
- }
+ } printf("-- PASS\n\n");
printf("\n\nTest: Is the next access done w/in a single clock?\n");
- tb->wb_write(0xfffffff7, 0xdeadbeef, &tberr);
+ tb->wb_write(0xfffffffc, 0xdeadbeef, &tberr);
if (tberr) {
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
(tberr)?"true":"false", (tb->miss())?"true":"false",
(tb->err())?"true":"false");
goto test_failure;
- }
+ } printf("-- PASS\n\n");
tberr = false;
printf("\n\nTest: What if we make this into a writeable page?\n");
- install_page(tb, 0, 0xffffffff, (1<wb_write(0xffffffff, 0x0fe, &tberr);
- if ((tberr)||((*tb)[0x0fff]!=0x0fe)) {
+ install_page(tb, 0, 0xffffffff, (4<wb_write(0xfffffffc, 0x0fe, &tberr);
+ if ((tberr)||((*tb)[0x0ffc]!=0x0fe)) {
unsigned v;
- v = ((*tb)[0x0fff]!=0x0fe);
+ v = ((*tb)[0x0ffc]!=0x0fe);
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
v, (tberr)?"true":"false", (tb->miss())?"true":"false",
(tb->err())?"true":"false");
goto test_failure;
- }
+ } printf("-- PASS\n\n");
tberr = false;
printf("\n\nTest: How about a read from the same location?\n");
{
unsigned v;
- v = tb->wb_read(0xffffffff, &tberr);
+ v = tb->wb_read(0xfffffffc, &tberr);
if ((tberr)||(v != 0x0fe)) {
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
v,
@@ -751,48 +830,49 @@
(tb->err())?"true":"false");
goto test_failure;
}
- }
+ } printf("-- PASS\n\n");
- printf("Test: Burst write, within page\n");
- tb->setup_write(0, 0x0dad);
- install_page(tb, 0, ((0x0ffffffffl)&(-(1l<setup_write(R_CONTROL, 0x0dad);
+#define TEST_VPAGE ((0x0ffffffffl)&(-(1l<wb_write(((0xffffffff)&(-(1l<wb_write(TEST_VPAGE-2*(1<miss())?"true":"false",
(tb->err())?"true":"false");
- printf("STATUS= %08x\n", tb->setup_read(1));
+ printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
goto test_failure;
} for(unsigned i=0; iwb_read(((0xffffffff)&(-(1<wb_read(TEST_VPAGE-2*(1<miss())?"true":"false",
(tb->err())?"true":"false");
- printf("STATUS= %08x\n", tb->setup_read(1));
+ printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
goto test_failure;
} for(unsigned i=0; i
verilator
Property changes :
Added: svn:ignore
## -0,0 +1,13 ##
+zipbones_tb
+zipmmu_tb
+zipsys_tb
+debug.txt
+div_tb
+mpy_tb
+obj-pc
+pdump
+pfcache_tb
+*.vcd
+*.bin
+tags
+*.vcd