Skip to content

Commit 1862eba

Browse files
committed
ISA V1.2 complete, unit tests completed, toolchain update
1 parent 5a2885e commit 1862eba

File tree

9 files changed

+162
-38
lines changed

9 files changed

+162
-38
lines changed

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ nexys4ddr/webtalk_impact.xml
55
nexys4ddr/iseconfig
66
impact.xsl
77
impact_impact.xwbt
8-
qasm2rom
8+
tools/qasm2rom
99
register_file.sym
10-
qnice
11-
qasm
10+
emulator/qnice
11+
tools/qasm
1212
*.lis
1313
*.out
1414
*.rom

emulator/qnice.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ typedef struct statistic_data
7373

7474
int gbl$memory[MEMORY_SIZE], gbl$registers[REGMEM_SIZE], gbl$debug = FALSE, gbl$verbose = FALSE,
7575
gbl$normal_operands[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, gbl$gather_statistics = FALSE, gbl$enable_uart = TRUE,
76-
gbl$ctrl_c = FALSE;
76+
gbl$ctrl_c = FALSE, gbl$breakpoint = -1;
7777
char *gbl$normal_mnemonics[] = {"MOVE", "ADD", "ADDC", "SUB", "SUBC", "SHL", "SHR", "SWAP",
7878
"NOT", "AND", "OR", "XOR", "CMP", "", "HALT"},
7979
*gbl$branch_mnemonics[] = {"ABRA", "ASUB", "RBRA", "RSUB"},
@@ -550,28 +550,28 @@ int execute()
550550
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
551551
destination = source_0 + source_1;
552552
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
553-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
553+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
554554
break;
555555
case 2: /* ADDC */
556556
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
557557
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
558558
destination = source_0 + source_1 + ((read_register(14) >> 2) & 1); /* Take carry into account */
559559
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
560-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
560+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
561561
break;
562562
case 3: /* SUB */
563563
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
564564
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
565565
destination = source_0 - source_1;
566566
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
567-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
567+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
568568
break;
569569
case 4: /* SUBC */
570570
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
571571
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
572572
destination = source_0 - source_1 - ((read_register(14) >> 2) & 1); /* Take carry into account */
573573
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
574-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
574+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
575575
break;
576576
case 5: /* SHL */
577577
source_0 = read_source_operand(source_mode, source_regaddr, FALSE);
@@ -612,21 +612,21 @@ int execute()
612612
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
613613
destination = source_0 & source_1;
614614
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
615-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
615+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
616616
break;
617617
case 10: /* OR */
618618
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
619619
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
620620
destination = source_0 | source_1;
621621
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
622-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
622+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
623623
break;
624624
case 11: /* XOR */
625625
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
626626
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
627627
destination = source_0 ^ source_1;
628628
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
629-
write_destination(destination_mode, destination_regaddr, destination, FALSE);
629+
write_destination(destination_mode, destination_regaddr, destination, TRUE);
630630
break;
631631
case 12: /* CMP */
632632
source_0 = read_source_operand(destination_mode, destination_regaddr, FALSE);
@@ -682,6 +682,13 @@ int execute()
682682
return TRUE;
683683
}
684684

685+
if (read_register(15) == gbl$breakpoint)
686+
{
687+
printf("Breakpoint reached: %04X\n", address);
688+
return TRUE;
689+
}
690+
691+
685692
/* write_register(15, read_register(15) + 1); */ /* Update program counter */
686693
return FALSE; /* No HALT instruction executed */
687694
}
@@ -858,6 +865,10 @@ int main(int argc, char **argv)
858865
{
859866
if (!strcmp(token, "QUIT") || !strcmp(token, "EXIT"))
860867
return 0;
868+
else if (!strcmp(token, "CB"))
869+
gbl$breakpoint = -1;
870+
else if (!strcmp(token, "SB"))
871+
printf("Breakpoint set to %04X\n", gbl$breakpoint = str2int(tokenize(NULL, delimiters)));
861872
else if (!strcmp(token, "DUMP"))
862873
{
863874
start = str2int(tokenize(NULL, delimiters));
@@ -949,6 +960,7 @@ int main(int argc, char **argv)
949960
}
950961
else if (!strcmp(token, "HELP"))
951962
printf("\n\
963+
CB Clear Breakpoint\n\
952964
DEBUG Toggle debug mode (for development only)\n\
953965
DIS <START>, <STOP> Disassemble a memory region\n\
954966
DUMP <START>, <STOP> Dump a memory area, START and STOP can be\n\
@@ -958,8 +970,9 @@ QUIT/EXIT Stop the emulator and return to the shell\n\
958970
RESET Reset the whole machine\n\
959971
RDUMP Print a register dump\n\
960972
RUN [<ADDR>] Run a program beginning at ADDR\n\
961-
SET <REG|ADDR> <VALUE> Either set a register of a memory cell\n\
973+
SET <REG|ADDR> <VALUE> Either set a register or a memory cell\n\
962974
SAVE <FILENAME> <START> <STOP> Create a loadable binary file\n\
975+
SB <ADDR> Set breakpoint to an address\n\
963976
STAT Displays some execution statistics\n\
964977
STEP [<ADDR>] Executes a single instruction at address\n\
965978
ADDR. If not address is specified the current\n\

monitor/sysdef.asm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
IO$BASE .EQU 0xFC00
2323
IO$UART0_BASE .EQU 0xFC00
2424

25+
IO$TIL_BASE .EQU 0xFF10 ; Address of TIL-display
26+
IO$TIL_MASK .EQU 0xFF11 ; Mask register of TIL display
27+
28+
2529
;
2630
; UART-registers:
2731
;

test_programs/bram.asm

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ EXE_START .EQU 0x8011 ; start address of code in RAM
1616
MOVE CODE_START, R1 ; run variable for copying: source
1717
MOVE EXE_START, R2 ; run variable for copying: dest
1818
MOVE 1, R3 ; we need to subtract 1 often
19-
SUB R1, R0 ; how many words to copy - 1
20-
; as the last opcode 2 words
19+
SUB R1, R0 ; how many words to copy
20+
; caution: if the last opcode
21+
; consists of two words, this
22+
; needs to be incremented or
23+
; the label needs to be put one
24+
; line below
2125
2226
COPY_CODE MOVE @R1++, @R2++ ; copy from src to dst
2327
SUB R3, R0 ; one less item to go
24-
RBRA COPY_CODE, !N ; R0 is #words-1, so check for !N
25-
; instead of checking for !Z
28+
RBRA COPY_CODE, !N ; R0 is decremented one time too
29+
; often so check for !N instead !Z
2630

2731
ABRA EXE_START, 1 ; execute code from RAM
2832

test_programs/brborder.asm

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
; unit test to provoke some BRAM borderline cases
2+
; done by sy2002 on August, 22nd 2015
3+
;
4+
; the unit test executes correctly, if the TIL display is showing the
5+
; following sequence of numbers having about 1 sec delay in between
6+
; ABAB, CDCD, EFEF, ACDC, CCCC, ACDC, EFEF, CDCD, FFFF, .... (repeat)
7+
8+
.ORG 0x0000
9+
10+
#include "../monitor/sysdef.asm"
11+
12+
RAMEXE .EQU 0x8000
13+
VARIABLE1 .EQU 0x80E0
14+
STACK .EQU 0x80FF
15+
16+
MOVE STACK, SP
17+
MOVE IO$TIL_BASE, R12
18+
19+
; copy part of the logic to RAM
20+
MOVE TORAM_END, R8
21+
SUB TORAM_START, R8
22+
MOVE TORAM_START, R9
23+
MOVE RAMEXE, R10
24+
ASUB COPY_CODE, 1
25+
26+
; create the first two numbers of the seq: ABAB and CDCD
27+
MOVE VARIABLE1, R0
28+
MOVE 0xABAB, @R0
29+
MOVE @R0++, R1
30+
MOVE 0xCDCD, @R0
31+
MOVE @R0++, R2
32+
33+
; create EFEF, ACDC, ACDC, EFEF, CDCD, FFFF
34+
; note that the "CCCC" is inserted in the display routine
35+
ASUB RAMEXE, 1
36+
37+
CONT_IN_ROM MOVE R1, @R12
38+
ASUB WAIT_A_SEC, 1
39+
MOVE R2, @R12
40+
ASUB WAIT_A_SEC, 1
41+
MOVE R3, @R12
42+
ASUB WAIT_A_SEC, 1
43+
MOVE R4, @R12
44+
ASUB WAIT_A_SEC, 1
45+
MOVE 0xCCCC, @R12
46+
ASUB WAIT_A_SEC, 1
47+
MOVE R5, @R12
48+
ASUB WAIT_A_SEC, 1
49+
MOVE R6, @R12
50+
ASUB WAIT_A_SEC, 1
51+
MOVE R7, @R12
52+
ASUB WAIT_A_SEC, 1
53+
MOVE R11, @R12
54+
ASUB WAIT_A_SEC, 1
55+
ABRA CONT_IN_ROM, 1
56+
57+
TORAM_START MOVE 0xEFEF, @R0
58+
MOVE @R0++, R3
59+
MOVE 0xACDC, @R0
60+
MOVE @R0, R4
61+
62+
MOVE R4, R5
63+
MOVE @--R0, R6
64+
MOVE @--R0, R7
65+
66+
; intentionally strange to trigger some bram async reset
67+
MOVE @--R0, R11
68+
MOVE R0, R10
69+
MOVE R11, @R0++
70+
MOVE 0x5454, @R0
71+
MOVE @R0, @R0
72+
ADD @R10, @R0
73+
MOVE @R0, R11
74+
RET
75+
TORAM_END .BLOCK 1
76+
77+
#include "debug_tools.asm"

test_programs/debug_tools.asm

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; utility routines for debugging
2+
; sysdef.asm needs to be included before this
3+
; done by sy2002 in August 2015
4+
5+
; copy code from one memory destination (e.g. ROM) to another (e.g. RAM)
6+
; R8: amount of instruction words to copy
7+
; R9: src, R10: dst
8+
;
9+
; CAUTION FOR R8: if the last opcode consists of two words, then better
10+
; place the label one line later, e.g. to a .BLOCK 1 statement, otherwise
11+
; the second word of the last opcode will not be copied
12+
13+
COPY_CODE MOVE @R9++, @R10++ ; copy from src to dst
14+
SUB 1, R8 ; one less item to go
15+
RBRA COPY_CODE, !N ; R0 is decremented one time too
16+
; much, so check for !N instead of
17+
; checking for !Z
18+
RET ; return from sub routine
19+
20+
; sub routine to wait for about 1 second (assuming a ~10 MIPS operation)
21+
22+
WAIT_A_SEC MOVE 0x1388, R8 ; inner wait cycles: 5.000 decimal
23+
MOVE 0x09C4, R9 ; outer wait cycles: 2.500 decimal
24+
RSUB WAIT_A_WHILE, 1 ; wait
25+
RET ; return from sub routine
26+
27+
; sub routine to wait for R8 x R9 cycles
28+
29+
WAIT_A_WHILE INCRB ; next register bank
30+
MOVE R9, R1 ; outer wait cycles
31+
WAS_WAIT_LOOP2 MOVE R8, R0 ; inner wait cycles
32+
WAS_WAIT_LOOP1 SUB 1, R0 ; dec inner wait cycles and ...
33+
RBRA WAS_WAIT_LOOP1, !Z ; ... repeat if not zero
34+
SUB 1, R1 ; dec outer wait cycles and ...
35+
RBRA WAS_WAIT_LOOP2, !Z ; ... repeat if not zero
36+
DECRB ; restore previous register bank
37+
RET ; return from sub routine

tools/qasm.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,16 +548,16 @@ int decode_operand(char *operand, int *op_code)
548548
*/
549549
int assemble()
550550
{
551-
int opcode, type, line_counter, address, i, error_counter = 0, number_of_operands, negate, flag, value, size,
552-
special_char;
551+
int opcode, type, line_counter, address = 0, i, error_counter = 0, number_of_operands, negate, flag, value, size,
552+
special_char, org_found = 0;
553553
char line[STRING_LENGTH], *p, *delimiters = " ,", *token, *sr_bits = "1XCZNVIM";
554554
data_structure *entry;
555555

556556
/* First pass: */
557557
#ifdef DEBUG
558558
printf("assemble: Starting first pass.\n");
559559
#endif
560-
for (address = line_counter = 1, entry = gbl$data; entry; entry = entry->next, line_counter++)
560+
for (line_counter = 1, entry = gbl$data; entry; entry = entry->next, line_counter++)
561561
{
562562
strcpy(line, entry->source); /* Get a local copy of the line and clean it up */
563563
entry->state = STATE$NOTHING_YET_DONE; /* Still a lot to do */

vhdl/env1_globals.vhd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use IEEE.STD_LOGIC_1164.all;
1010
package env1_globals is
1111

1212
-- file name and file size (in lines) of the file that is converted to the ROM located at 0x0000
13-
constant ROM_FILE : string := "../test_programs/bram.rom";
14-
constant ROM_SIZE : integer := 38;
13+
constant ROM_FILE : string := "../test_programs/brborder.rom";
14+
constant ROM_SIZE : integer := 101;
1515

1616
-- size of lower register bank: should be 256
1717
-- set to 16 during development for faster synthesis, routing, etc.

vhdl/qnice_cpu.vhd

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ signal Alu_V : std_logic;
190190

191191
begin
192192

193+
-- @TODO (priority 2): Completely re-do the Tristate buffer topic. The lenghty wait-state and the #0000 situation when
194+
-- writing are not necessary! As we have enough flip-flops, the Tristate handling can be done in "real-time".
195+
-- as this has probably some pretty far reaching impact, the question is when to implement this. On the other hand,
196+
-- the longer we wait, the bigger the impact will be. Some analysis with some MOVE, ADD & Co indirect @memory read/write
197+
-- scenario will for sure help and create a more clear view.
198+
193199
-- TriState buffer/driver for the 16 bit DATA bus
194200
DATA_driver : TriState_Buffer
195201
generic map
@@ -335,23 +341,6 @@ begin
335341
fsmNextCpuState <= cs_std_seq;
336342
fsmInstruction <= (others => '0');
337343

338-
-- BTW: as soon as all this works, plus some more unit tests especially for some to be found complicated BRAM borderline
339-
-- cases (e.g. ADD @R1, @R2, everything in RAM plus before and after some instructions that challenge the asyncreset),
340-
-- I should checkin the ISA V1.2 docu PDF (create a qnice/doc folder)
341-
-- check in the current assembler and stuff (inside the qnice folder), the emulator (within qnice folder, and the other
342-
-- material from there) and call it "V1.0" (before nerd session), because this is then a fully fledged
343-
-- QNICE CPU working in the initival ENV1 scenario. V1.1 could then be: plus UART plus Bernd's monitor is running.
344-
-- Later, V2.0 might be the new ISA plus another scenario than env1, e.g. QBM-1.
345-
-- the tagging in GIT/GITHUB is important, so that in a later "retro" session, we can compare ISA 1.2 in env1 with
346-
-- a full "QBM-1" computer having the new ISA (e.g. new CMP command, etc.).
347-
-- Update all tools in qnice folder to vaxman's latest material from SourceForge.
348-
349-
-- @TODO (priority 2): Completely re-do the Tristate buffer topic. The lenghty wait-state and the #0000 situation when
350-
-- writing are not necessary! As we have enough flip-flops, the Tristate handling can be done in "real-time".
351-
-- as this has probably some pretty far reaching impact, the question is when to implement this. On the other hand,
352-
-- the longer we wait, the bigger the impact will be. Some analysis with some MOVE, ADD & Co indirect @memory read/write
353-
-- scenario will for sure help and create a more clear view.
354-
355344
-- as the previous state sets the direction control to read and the address to a meaningful value
356345
-- (i.e. 0 after cs_reset or current PC afterwards), the DATA_driver will take care, that at the
357346
-- falling edge of cs_fetch's clock cycle, DATA_From_Bus will contain the next opcode

0 commit comments

Comments
 (0)