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/bench
    from Rev 197 to Rev 202
    Reverse comparison

Rev 197 → Rev 202

/asm/Makefile
4,15 → 4,42
#
# Project: Zip CPU -- a small, lightweight, RISC CPU soft core
#
# Purpose: This makefile builds the various assembler level test benches
# that exist.
# Purpose: To direct and simplify the build of a variety of simple assembly
# language test programs which will use one (or both) of the
# ZipCPU simulators.
#
# Targets include:
#
# hellosim
# Using the SIM instruction, prints Hello World to the screen.
#
# simuart
# Same as hellosim, but without using the SIM instruction. This
# *should* be able to run successfully on a verilated or
# synthesized hardware, although I hvae yet to test it there.
#
# simtest
# A set of simple tests designed to demonstrate if the simulator
# works or not.
#
# clean
# Removes the object file directory and any executables that have
# been created.
#
# None of the files/targets below have any dependencies, or if they did,
# GCC can't determine them, so thus there is no make depends step.
#
# To actually run one of these programs, list the program on the command
# line with the ZipCPU simulator, zsim.
#
#
#
# Creator: Dan Gisselquist, Ph.D.
# Gisselquist Technology, LLC
#
################################################################################
#
# Copyright (C) 2015, 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
24,6 → 51,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
#
30,42 → 62,72
#
################################################################################
#
all: zipdhry.z testdiv.z wdt.z halttest.z zipdhry.txt nullpc.txt poptest.txt
ZDIR := ../../sw/zasm
ZASM := $(ZDIR)/zasm
ZDMP := $(ZDIR)/zdump
LIBS := ../../sw/lib
INCS := -I$(ZDIR)/
.PHONY: all
all: $(OBJDIR)/ hellosim simtest simuart cmptest
 
dump: zipdhry.txt testdiv.txt
CC := zip-gcc
CPP := zip-cpp
AS := zip-as
LD := zip-ld
OBJDUMP := zip-objdump
OBJDIR := obj-zip
CFLAGS := -O3
LIBD := ../../sw/install/cross-tools/zip/lib
LIBS := -L$(LIBD) -lzipbasic
LDSCRIPT:= ../zipsim.ld
 
halttest.z: halttest.S
$(ZASM) $(INCS) $^ -o $@
zipdhry.z: zipdhry.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S
$(ZASM) $(INCS) $^ -o $@
zipdhry.txt: zipdhry.z
$(ZDMP) zipdhry.z > zipdhry.txt
$(OBJDIR)/%.o: %.c $(OBJDIR)/
$(CC) $(CFLAGS) -c $< -o $@
 
nullpc.z: nullpc.s
$(ZASM) $(INCS) $^ -o $@
nullpc.txt: nullpc.z
$(ZDMP) nullpc.z > nullpc.txt
$(OBJDIR)/%.o: %.s $(OBJDIR)/
$(AS) $< -o $@
 
poptest.z: poptest.s
$(ZASM) $(INCS) $^ -o $@
poptest.txt: poptest.z
$(ZDMP) poptest.z > poptest.txt
%.txt: %
$(OBJDUMP) -dr $< > $@
 
wdt.z: wdt.S
$(ZASM) $(INCS) $^ -o $@
#
# hellosim
#
# This is an assembly version of Hello World that uses the new SIM instructions.
# It should fail with an illegal instruction error if it is ever tried on an
# RTL-synthesized implementation
#
hellosim: $(OBJDIR)/hellosim.o
$(LD) -T $(LDSCRIPT) $< -o $@
 
.PHONY: testdiv
testdiv: testdiv.z
testdiv.z: testdiv.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S
$(ZASM) $(INCS) $^ -o $@
#
# simuart
#
# This is an assembly version of Hello World that uses the UART in the
# process. It doesn't use newlib or any other support tools, just binutils.
#
simuart: $(OBJDIR)/simuart.o
$(LD) -T $(LDSCRIPT) $< -o $@
 
testdiv.txt: testdiv.z
$(ZDMP) testdiv.z > testdiv.txt
#
# simtest
#
# This is just a simple series of instruction tests that should be able to be
# used to determine whether the simulator has a basic amount of functionality.
# Because the test includes #define, #ifdef, and #endif statements, though, it
# needs to be run through the C pre-processor before it can go through the
# assembler. Hence the build is a tocuh trickier, but still simple enough.
#
$(OBJDIR)/simtest.o: simtest.s $(OBJDIR)/
$(CPP) $< > $(OBJDIR)/simtest.s
$(AS) $(OBJDIR)/simtest.s -o $@
 
simtest: $(OBJDIR)/simtest.o
$(LD) -T $(LDSCRIPT) $< -o $@
 
cmptest: $(OBJDIR)/cmptest.o
$(LD) -T $(LDSCRIPT) -Map=map.txt $< -o $@
 
 
$(OBJDIR)/:
@bash -c "if [[ ! -e $(OBJDIR) ]]; then mkdir -p $(OBJDIR)/; fi"
 
.PHONY: clean
clean:
rm -rf *.z zipdhry.txt testdiv.txt
rm -rf $(OBJDIR)/
rm -rf hellosim simuart simtest
/asm/cputest.c
33,7 → 33,10
///////////////////////////////////////////////////////////////////////////////
//
//
#ifndef NULL
#define NULL (void *)0
#endif
 
volatile int *const UARTTX = (volatile int *)0x010b,
* const UART_CTRL = (int *)0x0107;
// #define ZIPSYS
60,6 → 63,13
void zip_save_context(int *);
void zip_halt(void);
 
 
void txchr(char v);
void txstr(const char *str);
void txhex(int num);
void tx4hex(int num);
 
 
asm("\t.section\t.start\n"
"\t.global\t_start\n"
"\t.type\t_start,@function\n"
110,7 → 120,7
 
 
extern int run_test(void *pc, void *stack);
asm("\t.global\trun_test\n"
asm("\t.text\n\t.global\trun_test\n"
"\t.type\trun_test,@function\n"
"run_test:\n"
"\tCLR\tR3\n"
125,11 → 135,11
"\tMOV\tR3,uR8\n"
"\tMOV\tR3,uR9\n"
"\tMOV\tR3,uR10\n"
"\tMOV\tR1,uR11\n"
"\tMOV\tR1,uR12\n"
"\tMOV\tR2,uSP\n"
"\tMOV\t0x20+R3,uCC\n"
"\tMOV\tR1,uPC\n"
"\tMOV\tR3,uR11\n"
"\tMOV\tR3,uR12\n"
"\tMOV\tR2,uSP\n" // uSP = stack
"\tMOV\t0x20+R3,uCC\n" // Clear uCC of all but the GIE bit
"\tMOV\tR1,uPC\n" // uPC = pc
"\tRTU\n"
"test_return:\n"
"\tMOV\tuR1,R1\n"
137,8 → 147,39
// Works with 5 NOOPS, works with 3 NOOPS, works with 1 NOOP
"\tJMP\tR0\n");
 
extern int idle_test(void);
asm("\t.text\n\t.global\tidle_test\n"
"\t.type\tidle_test,@function\n"
"idle_test:\n"
"\tCLR\tR1\n"
"\tMOV\tidle_loop(PC),uR0\n"
"\tMOV\tR1,uR1\n"
"\tMOV\tR1,uR2\n"
"\tMOV\tR1,uR3\n"
"\tMOV\tR1,uR4\n"
"\tMOV\tR1,uR5\n"
"\tMOV\tR1,uR6\n"
"\tMOV\tR1,uR7\n"
"\tMOV\tR1,uR8\n"
"\tMOV\tR1,uR9\n"
"\tMOV\tR1,uR10\n"
"\tMOV\tR1,uR11\n"
"\tMOV\tR1,uR12\n"
"\tMOV\tR1,uSP\n"
"\tMOV\t0x20+R1,uCC\n"
"\tMOV\tidle_loop(PC),uPC\n"
"\tWAIT\n"
"\tMOV uPC,R1\n"
"\tCMP idle_loop(PC),R1\n"
"\tLDI 0,R1\n"
"\tLDI.NZ 1,R1\n"
"\nRETN\n"
"idle_loop:\n"
"\tWAIT\n"
"\tBRA idle_loop\n");
 
void break_one(void);
asm("\t.global\tbreak_one\n"
asm("\t.text\n\t.global\tbreak_one\n"
"\t.type\tbreak_one,@function\n"
"break_one:\n"
"\tLDI\t0,R1\n"
148,7 → 189,7
 
void break_two(void);
// Can we stop a break before we hit it?
asm("\t.global\tbreak_two\n"
asm("\t.text\n\t.global\tbreak_two\n"
"\t.type\tbreak_two,@function\n"
"break_two:\n"
"\tLDI\t0,R1\n"
156,7 → 197,7
"\tBREAK\n");
 
void early_branch_test(void);
asm("\t.global\tearly_branch_test\n"
asm("\t.text\n\t.global\tearly_branch_test\n"
"\t.type\tearly_branch_test,@function\n"
"early_branch_test:\n"
"\tLDI\t1,R1\n"
202,7 → 243,7
"\tJMP\tR0");
 
void trap_test_and(void);
asm("\t.global\ttrap_test_and\n"
asm("\t.text\n\t.global\ttrap_test_and\n"
"\t.type\ttrap_test_and,@function\n"
"trap_test_and:\n"
"\tLDI\t0,R1\n"
211,7 → 252,7
"\tJMP\tR0");
 
void trap_test_clr(void);
asm("\t.global\ttrap_test_clr\n"
asm("\t.text\n\t.global\ttrap_test_clr\n"
"\t.type\ttrap_test_clr,@function\n"
"trap_test_clr:\n"
"\tLDI\t0,R1\n"
220,7 → 261,7
"\tJMP\tR0");
 
void overflow_test(void);
asm("\t.global\toverflow_test\n"
asm("\t.text\n\t.global\toverflow_test\n"
"\t.type\toverflow_test,@function\n"
"overflow_test:\n"
"\tLDI\t0,R1\n"
254,7 → 295,7
 
 
void carry_test(void);
asm("\t.global\tcarry_test\n"
asm("\t.text\n\t.global\tcarry_test\n"
"\t.type\tcarry_test,@function\n"
"carry_test:\n"
"\tLDI\t0,R1\n"
283,7 → 324,7
"\tJMP\tR0");
 
void loop_test(void);
asm("\t.global\tloop_test\n"
asm("\t.text\n\t.global\tloop_test\n"
"\t.type\tloop_test,@function\n"
"loop_test:\n"
"\tLDI\t0,R1\n"
341,7 → 382,7
// Test whether or not LSL, LSR, and ASR instructions work, together with their
// carry flags
void shift_test(void);
asm("\t.global\tshift_test\n"
asm("\t.text\n\t.global\tshift_test\n"
"\t.type\tshift_test,@function\n"
"shift_test:\n"
"\tLDI\t0,R1\n"
408,7 → 449,7
"\tJMP\tR0");
 
int sw_brev(int v);
asm("\t.global\tsw_brev\n"
asm("\t.text\n\t.global\tsw_brev\n"
"\t.type\tsw_brev,@function\n"
"sw_brev:\n"
"\tSUB\t2,SP\n"
431,7 → 472,7
"\tJMP\tR0");
 
void pipeline_stack_test(void);
asm("\t.global\tpipeline_stack_test\n"
asm("\t.text\n\t.global\tpipeline_stack_test\n"
"\t.type\tpipeline_stack_test,@function\n"
"pipeline_stack_test:\n"
"\tSUB\t1,SP\n"
473,7 → 514,7
);
 
void pipeline_stack_test_component(void);
asm("\t.global\tpipeline_stack_test_component\n"
asm("\t.text\n\t.global\tpipeline_stack_test_component\n"
"\t.type\tpipeline_stack_test_component,@function\n"
"pipeline_stack_test_component:\n"
"\tSUB\t13,SP\n"
521,7 → 562,7
 
//mpy_test
void mpy_test(void);
asm("\t.global\tmpy_test\n"
asm("\t.text\n\t.global\tmpy_test\n"
"\t.type\tmpy_test,@function\n"
"mpy_test:\n"
"\tCLR\tR1\n"
553,10 → 594,153
// Second test ... whatever that might be
"\tJMP\tR0\n");
 
unsigned soft_mpyuhi(unsigned, unsigned);
int soft_mpyshi(int,int);
 
unsigned hard_mpyuhi(unsigned, unsigned);
asm("\t.text\n\t.global\thard_mpyuhi\n"
"\t.type\thard_mpyuhi,@function\n"
"hard_mpyuhi:\n"
"\tNOOP\n"
"\tNOOP\n"
"\tMPYUHI\tR2,R1\n"
"\tRETN\n");
 
int hard_mpyshi(int, int);
asm("\t.text\n\t.global\thard_mpyshi\n"
"\t.type\thard_mpyshi,@function\n"
"hard_mpyshi:\n"
"\tMPYSHI\tR2,R1\n"
"\tRETN\n");
 
void debugmpy(char *str, int a, int b, int s, int r) {
#ifdef HAVE_SCOPE
// Trigger the scope, if it hasn't been triggered yet
// but ... dont reset it if it has been.
*SCOPE = TRIGGER_SCOPE_NOW;
#endif
txstr("\r\n"); txstr(str); txhex(a);
txstr(" x "); txhex(b);
txstr(" = "); txhex(s);
txstr("(Soft) = "); txhex(r);
txstr("(Hard)\r\n");
}
 
int mpyhi_test(void) {
int a = 0xf97e27ab, b = 0;
 
while(b<0x6fffffff) {
int r, sr;
 
sr = soft_mpyuhi(a, b);
r = hard_mpyuhi(a,b);
if (r != sr) {
debugmpy("MPYUHI: ", a,b,sr,r);
return 1;
}
 
sr = soft_mpyshi(a, b);
r = hard_mpyshi(a,b);
if (r != sr) {
debugmpy("MPYSHI: ", a,b,sr,r);
return 2;
}
 
sr = soft_mpyshi(-a, b);
r = hard_mpyshi(-a,b);
if (r != sr) {
debugmpy("MPYSHI-NEG: ", -a,b,sr,r);
return 3;
}
 
b += 0x197e2*7;
}
 
return 0;
}
 
unsigned soft_mpyuhi(unsigned a, unsigned b) {
unsigned alo, ahi, blo, bhi;
unsigned rhi, rlhi, rllo;
 
alo = (a & 0x0ffff);
ahi = (a>>16)& 0x0ffff;
blo = (b & 0x0ffff);
bhi = (b>>16)& 0x0ffff;
 
rhi = 0;
rlhi = 0;
rllo = 0;
 
for(int i=0; i<16; i++) {
if (b&(1<<i)) {
unsigned slo, shi, sup;
slo = (alo << i);
shi = (ahi << i);
shi |= (slo>>16) & 0x0ffff;
slo &= 0x0ffff;
sup = (shi>>16)&0x0ffff;
shi &= 0x0ffff;
 
rhi += sup;
rlhi += shi;
rllo += slo;
 
rlhi += (rllo >> 16)&0x0ffff;
rllo &= 0x0ffff;
 
rhi += (rlhi >> 16)&0x0ffff;
rlhi &= 0x0ffff;
}
}
 
for(int i=16; i<32; i++) {
if (b&(1<<i)) {
unsigned slo, shi, sup;
slo = (alo << (i-16));
shi = (ahi << (i-16));
shi |= (slo>>16) & 0x0ffff;
slo &= 0x0ffff;
sup = (shi>>16)&0x0ffff;
shi &= 0x0ffff;
 
rhi += sup << 16;
rhi += shi;
rlhi += slo;
 
rhi += (rlhi >> 16)&0x0ffff;
rlhi &= 0x0ffff;
}
}
 
return rhi;
}
 
int soft_mpyshi(int a, int b) {
unsigned sgn, r, p;
 
sgn = ((a^b)>>31)&0x01;
 
if (a<0) a = -a;
if (b<0) b = -b;
 
p = a * b;
 
// This will only fail if the lower 32-bits of of a*b are 0,
// at which point our following negation won't capture the carry it
// needs.
r = soft_mpyuhi(a, b);
 
r = (sgn)?(r^-1):r;
if ((sgn)&&(p==0))
r += 1;
return r;
}
 
//brev_test
//pipeline_test -- used to be called pipeline memory race conditions
void pipeline_test(void);
asm("\t.global\tpipeline_test\n"
asm("\t.text\n\t.global\tpipeline_test\n"
"\t.type\tpipeline_test,@function\n"
"pipeline_test:\n"
"\tSUB\t2,SP\n"
606,7 → 790,7
 
//mempipe_test
void mempipe_test(void);
asm("\t.global\tmempipe_test\n"
asm("\t.text\n\t.global\tmempipe_test\n"
"\t.type\tmempipe_test,@function\n"
"mempipe_test:\n"
"\tSUB\t4,SP\n"
643,7 → 827,7
 
//cexec_test
void cexec_test(void);
asm("\t.global\tcexec_test\n"
asm("\t.text\n\t.global\tcexec_test\n"
"\t.type\tcexec_test,@function\n"
"cexec_test:\n"
"\tSUB\t1,SP\n"
667,7 → 851,7
//
//nowaitpipe_test
void nowaitpipe_test(void);
asm("\t.global\tnowaitpipe_test\n"
asm("\t.text\n\t.global\tnowaitpipe_test\n"
"\t.type\tnowaitpipe_test,@function\n"
"nowaitpipe_test:\n"
"\tSUB\t2,SP\n"
742,7 → 926,7
 
//bcmem_test
void bcmem_test(void);
asm("\t.global\tbcmem_test\n"
asm("\t.text\n.global\tbcmem_test\n"
"\t.type\tbcmem_test,@function\n"
"bcmem_test:\n"
"\tSUB\t1,SP\n"
773,7 → 957,21
"\tADD\t1,SP\n"
"\tJMP\tR0\n");
 
// The illegal instruction test. Specifically, illegal instructions cannot be
// allowed to execute. The PC must, upon completion, point to the illegal
// instruction that caused the exception.
//
// To create our illegal instruction, we assume that the only the three
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a
// fourth instruction to create.
void ill_test(void);
asm("\t.text\n.global\till_test\n"
"\t.type\till_test,@function\n"
"ill_test:\n"
"\t.word\t0x7ff00000\n"
"\tJMP\tR0\n");
 
//
// The CC register has some ... unique requirements associated with it.
// Particularly, flags are unavailable until after an ALU operation completes,
// and they can't really be bypassed for the CC register. After writeback,
787,7 → 985,7
// issues.
//
void ccreg_test(void);
asm("\t.global\tccreg_test\n"
asm("\t.text\n.global\tccreg_test\n"
"\t.type\tccreg_test,@function\n"
"ccreg_test:\n"
// First test: If we try to change the fixed bits, will they change
847,11 → 1045,15
*PIC = 0; // Turn interrupts back off, lest they confuse the test
}
 
asm("\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
 
__attribute__((noinline))
void txchr(char v) {
wait(INT_UARTTX);
if (zip_cc() & CC_GIE) {
while(*UARTTX & 0x100)
;
} else
wait(INT_UARTTX);
*UARTTX = v;
}
 
876,6 → 1078,22
}
 
__attribute__((noinline))
void tx4hex(int num) {
if (num & 0xffff0000){
txhex(num);
return;
} for(int ds=12; ds>=0; ds-=4) {
int ch;
ch = (num >> ds)&0x0f;
if (ch >= 10)
ch = 'A'+ch-10;
else
ch += '0';
txchr(ch);
}
}
 
__attribute__((noinline))
void txreg(const char *name, int val) {
txstr(name); // 4 characters
txstr("0x"); // 2 characters
895,7 → 1113,7
// Trigger the scope, if it hasn't already triggered. Otherwise,
// if it has triggered, don't clear it.
#ifdef HAVE_SCOPE
*SCOPE = 0x8f000004;
*SCOPE = TRIGGER_SCOPE_NOW;
#endif
 
MARKSTOP;
935,7 → 1153,12
txreg("uPC : ", context[15]);
txstr("\r\n\r\n");
 
asm("\tBUSY");
// While previous versions of cputest.c called zip_busy(), here we
// reject that notion for the simple reason that zip_busy may not
// necessarily halt any Verilator simulation. Instead, we try to
// halt the CPU.
while(1)
zip_halt();
}
 
void testid(const char *str) {
966,31 → 1189,26
#ifdef HAVE_COUNTER
*COUNTER = 0;
#endif
#ifdef HAVE_SCOPE
*SCOPE = PREPARE_SCOPE;
#endif
 
// #define STACKTEST asm("CMP\t16108,SP\n\tHALT.NZ\n")
#define STACKTEST
STACKTEST;
 
// *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit
*UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit
//
STACKTEST;
 
txstr("\r\n");
txstr("Running CPU self-test\n");
txstr("Running CPU self-test\r\n");
txstr("-----------------------------------\r\n");
 
int tnum = 0;
STACKTEST;
 
// Test break instruction in user mode
// Make sure the break works as designed
testid("Break test #1"); MARKSTART;
STACKTEST;
 
if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50))
test_fails(start_time, &testlist[tnum]);
STACKTEST;
 
save_context(context);
if ((context[15] != (int)break_one+1)||(0==(zip_ucc()&0x80)))
997,8 → 1215,6
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
 
STACKTEST;
 
// Test break instruction in user mode
// Make sure that a decision on the clock prior won't still cause a
// break condition
1055,12 → 1271,6
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
 
// MPY_TEST
testid("Multiply test"); MARKSTART;
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
 
// BREV_TEST
//testid("BREV/stack test"); MARKSTART;
//if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1098,11 → 1308,20
txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
 
// Illegal Instruction test
testid("Illegal Instruction test"); MARKSTART;
testid("Ill Instruction test, NULL PC"); MARKSTART;
if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0;
 
// Illegal Instruction test
testid("Ill Instruction test, two"); MARKSTART;
if ((run_test(ill_test, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
test_fails(start_time, &testlist[tnum]);
save_context(context);
if (context[15] != (int)&ill_test)
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0;
 
// Pipeline memory race condition test
// DIVIDE test
 
1118,9 → 1337,20
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0;
 
// MPY_TEST
testid("Multiply test"); MARKSTART;
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
 
// MPYxHI_TEST
testid("Multiply HI-word test"); MARKSTART;
if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&0x01d90))
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
txstr("\r\n");
txstr("-----------------------------------\r\n");
txstr("All tests passed. Halting CPU.\n");
txstr("All tests passed. Halting CPU.\r\n");
zip_halt();
}
 
/asm/zipdhry.S
252,13 → 252,12
BRA copy_next_char
 
end_strcpy:
STO R2,(R0)
CMP 0,R2
STO.NZ R2,(R0)
STO.NZ R3,1(R0)
CMP.NZ 0,R3
STO.NZ R3,1(R0)
STO.NZ R4,2(R0)
CMP.NZ 0,R4
STO.NZ R4,2(R0)
CMP.NZ 0,R5
STO.NZ R5,3(R0)
 
LOD (SP),R2
/cpp/Makefile
4,92 → 4,21
#
# 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.
# Purpose: To direct and simplify the build of a variety of simple test
# programs which will use one (or both) of the ZipCPU simulators.
#
# This simulator depends upon the ncurses library.
# Targets include:
#
# Useful targets of this makefile include:
# helloworld
#
# 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.
#
# 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
#
################################################################################
#
# Copyright (C) 2015-2016, 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
101,6 → 30,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
#
107,55 → 41,43
#
################################################################################
#
all: zippy_tb pdump div_tb mpy_tb
.PHONY: all
all: helloworld
 
CXX := g++
FLAGS := -Wall -Og -g
ZASM := ../../sw/zasm
RTLD := ../../rtl
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"')
VROOT := $(VERILATOR_ROOT)
INCS := -I$(RTLD)/obj_dir/ -I$(RTLD) -I$(VROOT)/include -I$(ZASM)
SOURCES := zippy_tb.cpp memsim.cpp twoc.cpp $(ZASM)/zopcodes.cpp $(ZASM)/zparser.cpp
VLIB := $(VROOT)/include/verilated.cpp
RAWLIB := $(VLIB) $(RTLD)/obj_dir/Vzipsystem__ALL.a
LIBS := $(RAWLIB) -lncurses -lelf
TESTF := $(ZASM)/z.out
DHRYSTONEF := ../asm/zipdhry.z
CC := zip-gcc
OBJDUMP := zip-objdump
OBJDIR := obj-zip
CFLAGS := -O3
LIBD := ../../sw/install/cross-tools/zip/lib
LIBS := -L$(LIBD) -lzipbasic
SOURCES:= helloworld.c
LDSCRIPT:= ../zipsim.ld
 
zippy_tb: $(SOURCES) $(RAWLIB) $(ZASM)/zopcodes.h $(ZASM)/zparser.h testb.h
zippy_tb: $(RTLD)/cpudefs.h
$(CXX) $(FLAGS) $(INCS) $(SOURCES) $(LIBS) -o $@
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
 
div_tb: div_tb.cpp twoc.cpp $(VLIB) $(RTLD)/obj_dir/Vdiv__ALL.a testb.h
$(CXX) $(FLAGS) $(INCS) div_tb.cpp twoc.cpp $(VLIB) $(RTLD)/obj_dir/Vdiv__ALL.a -o $@
helloworld: $(OBJDIR)/helloworld.o
$(CC) -T $(LDSCRIPT) $(CFLAGS) $(LIBD)/crt0.o $(LIBS) $< -o $@
 
mpy_tb: mpy_tb.cpp twoc.cpp $(VLIB) $(RTLD)/obj_dir/Vcpuops__ALL.a testb.h
$(CXX) $(FLAGS) $(INCS) mpy_tb.cpp twoc.cpp $(VLIB) $(RTLD)/obj_dir/Vcpuops__ALL.a -o $@
helloworld.txt: helloworld
$(OBJDUMP) -dr $< > $@
 
zipmmu_tb: zipmmu_tb.cpp $(VLIB) ../rtl/obj_dir/Vzipmmu_tb__ALL.a
$(CXX) $(FLAGS) $(INCS) -I ../rtl/obj_dir zipmmu_tb.cpp $(VLIB) ../rtl/obj_dir/Vzipmmu_tb__ALL.a -o $@
define build-depends
$(CC) $(CFLAGS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt
sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
@rm -f $(OBJDIR)/xdepends.txt
endef
 
pdump: pdump.cpp $(ZASM)/zopcodes.cpp $(ZASM)/zparser.cpp
pdump: $(ZASM)/zopcodes.h $(ZASM)/zparser.h testb.h twoc.cpp
$(CXX) $(FLAGS) $(INCS) pdump.cpp $(ZASM)/zopcodes.cpp $(ZASM)/zparser.cpp twoc.cpp -lelf -o $@
tags: $(SOURCES)
@ctags $(SOURCES)
 
.PHONY: stest
stest: zippy_tb
./zippy_tb -s $(TESTF)
.PHONY: depends
depends: tags $(OBJDIR)/
$(build-depends)
 
.PHONY: itest
itest: zippy_tb
./zippy_tb $(TESTF)
$(OBJDIR)/:
@bash -c "if [[ ! -e $(OBJDIR) ]]; then mkdir -p $(OBJDIR)/; fi"
 
.PHONY: test
test: zippy_tb stest
./zippy_tb -a $(TESTF)
 
.PHONY: dhrystone
dhrystone: zippy_tb
./zippy_tb -a $(DHRYSTONEF)
 
.PHONY: clean
clean:
rm ./zippy_tb pdump div_tb mpy_tb
rm -rf helloworld

powered by: WebSVN 2.1.0

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