OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.