Skip to content

Commit

Permalink
ISA V1.2 complete, unit tests completed, toolchain update
Browse files Browse the repository at this point in the history
  • Loading branch information
sy2002 committed Aug 22, 2015
1 parent 5a2885e commit 1862eba
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 38 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ nexys4ddr/webtalk_impact.xml
nexys4ddr/iseconfig
impact.xsl
impact_impact.xwbt
qasm2rom
tools/qasm2rom
register_file.sym
qnice
qasm
emulator/qnice
tools/qasm
*.lis
*.out
*.rom
31 changes: 22 additions & 9 deletions emulator/qnice.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ typedef struct statistic_data

int gbl$memory[MEMORY_SIZE], gbl$registers[REGMEM_SIZE], gbl$debug = FALSE, gbl$verbose = FALSE,
gbl$normal_operands[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, gbl$gather_statistics = FALSE, gbl$enable_uart = TRUE,
gbl$ctrl_c = FALSE;
gbl$ctrl_c = FALSE, gbl$breakpoint = -1;
char *gbl$normal_mnemonics[] = {"MOVE", "ADD", "ADDC", "SUB", "SUBC", "SHL", "SHR", "SWAP",
"NOT", "AND", "OR", "XOR", "CMP", "", "HALT"},
*gbl$branch_mnemonics[] = {"ABRA", "ASUB", "RBRA", "RSUB"},
Expand Down Expand Up @@ -550,28 +550,28 @@ int execute()
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 + source_1;
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 2: /* ADDC */
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 + source_1 + ((read_register(14) >> 2) & 1); /* Take carry into account */
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 3: /* SUB */
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 - source_1;
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 4: /* SUBC */
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 - source_1 - ((read_register(14) >> 2) & 1); /* Take carry into account */
update_status_bits(destination, source_0, source_1, MODIFY_ALL);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 5: /* SHL */
source_0 = read_source_operand(source_mode, source_regaddr, FALSE);
Expand Down Expand Up @@ -612,21 +612,21 @@ int execute()
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 & source_1;
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 10: /* OR */
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 | source_1;
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 11: /* XOR */
source_0 = read_source_operand(destination_mode, destination_regaddr, TRUE);
source_1 = read_source_operand(source_mode, source_regaddr, FALSE);
destination = source_0 ^ source_1;
update_status_bits(destination, source_0, source_1, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);
write_destination(destination_mode, destination_regaddr, destination, FALSE);
write_destination(destination_mode, destination_regaddr, destination, TRUE);
break;
case 12: /* CMP */
source_0 = read_source_operand(destination_mode, destination_regaddr, FALSE);
Expand Down Expand Up @@ -682,6 +682,13 @@ int execute()
return TRUE;
}

if (read_register(15) == gbl$breakpoint)
{
printf("Breakpoint reached: %04X\n", address);
return TRUE;
}


/* write_register(15, read_register(15) + 1); */ /* Update program counter */
return FALSE; /* No HALT instruction executed */
}
Expand Down Expand Up @@ -858,6 +865,10 @@ int main(int argc, char **argv)
{
if (!strcmp(token, "QUIT") || !strcmp(token, "EXIT"))
return 0;
else if (!strcmp(token, "CB"))
gbl$breakpoint = -1;
else if (!strcmp(token, "SB"))
printf("Breakpoint set to %04X\n", gbl$breakpoint = str2int(tokenize(NULL, delimiters)));
else if (!strcmp(token, "DUMP"))
{
start = str2int(tokenize(NULL, delimiters));
Expand Down Expand Up @@ -949,6 +960,7 @@ int main(int argc, char **argv)
}
else if (!strcmp(token, "HELP"))
printf("\n\
CB Clear Breakpoint\n\
DEBUG Toggle debug mode (for development only)\n\
DIS <START>, <STOP> Disassemble a memory region\n\
DUMP <START>, <STOP> Dump a memory area, START and STOP can be\n\
Expand All @@ -958,8 +970,9 @@ QUIT/EXIT Stop the emulator and return to the shell\n\
RESET Reset the whole machine\n\
RDUMP Print a register dump\n\
RUN [<ADDR>] Run a program beginning at ADDR\n\
SET <REG|ADDR> <VALUE> Either set a register of a memory cell\n\
SET <REG|ADDR> <VALUE> Either set a register or a memory cell\n\
SAVE <FILENAME> <START> <STOP> Create a loadable binary file\n\
SB <ADDR> Set breakpoint to an address\n\
STAT Displays some execution statistics\n\
STEP [<ADDR>] Executes a single instruction at address\n\
ADDR. If not address is specified the current\n\
Expand Down
4 changes: 4 additions & 0 deletions monitor/sysdef.asm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
IO$BASE .EQU 0xFC00
IO$UART0_BASE .EQU 0xFC00

IO$TIL_BASE .EQU 0xFF10 ; Address of TIL-display
IO$TIL_MASK .EQU 0xFF11 ; Mask register of TIL display


;
; UART-registers:
;
Expand Down
12 changes: 8 additions & 4 deletions test_programs/bram.asm
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ EXE_START .EQU 0x8011 ; start address of code in RAM
MOVE CODE_START, R1 ; run variable for copying: source
MOVE EXE_START, R2 ; run variable for copying: dest
MOVE 1, R3 ; we need to subtract 1 often
SUB R1, R0 ; how many words to copy - 1
; as the last opcode 2 words
SUB R1, R0 ; how many words to copy
; caution: if the last opcode
; consists of two words, this
; needs to be incremented or
; the label needs to be put one
; line below
COPY_CODE MOVE @R1++, @R2++ ; copy from src to dst
SUB R3, R0 ; one less item to go
RBRA COPY_CODE, !N ; R0 is #words-1, so check for !N
; instead of checking for !Z
RBRA COPY_CODE, !N ; R0 is decremented one time too
; often so check for !N instead !Z

ABRA EXE_START, 1 ; execute code from RAM

Expand Down
77 changes: 77 additions & 0 deletions test_programs/brborder.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
; unit test to provoke some BRAM borderline cases
; done by sy2002 on August, 22nd 2015
;
; the unit test executes correctly, if the TIL display is showing the
; following sequence of numbers having about 1 sec delay in between
; ABAB, CDCD, EFEF, ACDC, CCCC, ACDC, EFEF, CDCD, FFFF, .... (repeat)

.ORG 0x0000

#include "../monitor/sysdef.asm"

RAMEXE .EQU 0x8000
VARIABLE1 .EQU 0x80E0
STACK .EQU 0x80FF

MOVE STACK, SP
MOVE IO$TIL_BASE, R12

; copy part of the logic to RAM
MOVE TORAM_END, R8
SUB TORAM_START, R8
MOVE TORAM_START, R9
MOVE RAMEXE, R10
ASUB COPY_CODE, 1

; create the first two numbers of the seq: ABAB and CDCD
MOVE VARIABLE1, R0
MOVE 0xABAB, @R0
MOVE @R0++, R1
MOVE 0xCDCD, @R0
MOVE @R0++, R2

; create EFEF, ACDC, ACDC, EFEF, CDCD, FFFF
; note that the "CCCC" is inserted in the display routine
ASUB RAMEXE, 1

CONT_IN_ROM MOVE R1, @R12
ASUB WAIT_A_SEC, 1
MOVE R2, @R12
ASUB WAIT_A_SEC, 1
MOVE R3, @R12
ASUB WAIT_A_SEC, 1
MOVE R4, @R12
ASUB WAIT_A_SEC, 1
MOVE 0xCCCC, @R12
ASUB WAIT_A_SEC, 1
MOVE R5, @R12
ASUB WAIT_A_SEC, 1
MOVE R6, @R12
ASUB WAIT_A_SEC, 1
MOVE R7, @R12
ASUB WAIT_A_SEC, 1
MOVE R11, @R12
ASUB WAIT_A_SEC, 1
ABRA CONT_IN_ROM, 1

TORAM_START MOVE 0xEFEF, @R0
MOVE @R0++, R3
MOVE 0xACDC, @R0
MOVE @R0, R4

MOVE R4, R5
MOVE @--R0, R6
MOVE @--R0, R7

; intentionally strange to trigger some bram async reset
MOVE @--R0, R11
MOVE R0, R10
MOVE R11, @R0++
MOVE 0x5454, @R0
MOVE @R0, @R0
ADD @R10, @R0
MOVE @R0, R11
RET
TORAM_END .BLOCK 1

#include "debug_tools.asm"
37 changes: 37 additions & 0 deletions test_programs/debug_tools.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
; utility routines for debugging
; sysdef.asm needs to be included before this
; done by sy2002 in August 2015

; copy code from one memory destination (e.g. ROM) to another (e.g. RAM)
; R8: amount of instruction words to copy
; R9: src, R10: dst
;
; CAUTION FOR R8: if the last opcode consists of two words, then better
; place the label one line later, e.g. to a .BLOCK 1 statement, otherwise
; the second word of the last opcode will not be copied

COPY_CODE MOVE @R9++, @R10++ ; copy from src to dst
SUB 1, R8 ; one less item to go
RBRA COPY_CODE, !N ; R0 is decremented one time too
; much, so check for !N instead of
; checking for !Z
RET ; return from sub routine

; sub routine to wait for about 1 second (assuming a ~10 MIPS operation)

WAIT_A_SEC MOVE 0x1388, R8 ; inner wait cycles: 5.000 decimal
MOVE 0x09C4, R9 ; outer wait cycles: 2.500 decimal
RSUB WAIT_A_WHILE, 1 ; wait
RET ; return from sub routine

; sub routine to wait for R8 x R9 cycles

WAIT_A_WHILE INCRB ; next register bank
MOVE R9, R1 ; outer wait cycles
WAS_WAIT_LOOP2 MOVE R8, R0 ; inner wait cycles
WAS_WAIT_LOOP1 SUB 1, R0 ; dec inner wait cycles and ...
RBRA WAS_WAIT_LOOP1, !Z ; ... repeat if not zero
SUB 1, R1 ; dec outer wait cycles and ...
RBRA WAS_WAIT_LOOP2, !Z ; ... repeat if not zero
DECRB ; restore previous register bank
RET ; return from sub routine
6 changes: 3 additions & 3 deletions tools/qasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,16 +548,16 @@ int decode_operand(char *operand, int *op_code)
*/
int assemble()
{
int opcode, type, line_counter, address, i, error_counter = 0, number_of_operands, negate, flag, value, size,
special_char;
int opcode, type, line_counter, address = 0, i, error_counter = 0, number_of_operands, negate, flag, value, size,
special_char, org_found = 0;
char line[STRING_LENGTH], *p, *delimiters = " ,", *token, *sr_bits = "1XCZNVIM";
data_structure *entry;

/* First pass: */
#ifdef DEBUG
printf("assemble: Starting first pass.\n");
#endif
for (address = line_counter = 1, entry = gbl$data; entry; entry = entry->next, line_counter++)
for (line_counter = 1, entry = gbl$data; entry; entry = entry->next, line_counter++)
{
strcpy(line, entry->source); /* Get a local copy of the line and clean it up */
entry->state = STATE$NOTHING_YET_DONE; /* Still a lot to do */
Expand Down
4 changes: 2 additions & 2 deletions vhdl/env1_globals.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use IEEE.STD_LOGIC_1164.all;
package env1_globals is

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

-- size of lower register bank: should be 256
-- set to 16 during development for faster synthesis, routing, etc.
Expand Down
23 changes: 6 additions & 17 deletions vhdl/qnice_cpu.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ signal Alu_V : std_logic;

begin

-- @TODO (priority 2): Completely re-do the Tristate buffer topic. The lenghty wait-state and the #0000 situation when
-- writing are not necessary! As we have enough flip-flops, the Tristate handling can be done in "real-time".
-- as this has probably some pretty far reaching impact, the question is when to implement this. On the other hand,
-- the longer we wait, the bigger the impact will be. Some analysis with some MOVE, ADD & Co indirect @memory read/write
-- scenario will for sure help and create a more clear view.

-- TriState buffer/driver for the 16 bit DATA bus
DATA_driver : TriState_Buffer
generic map
Expand Down Expand Up @@ -335,23 +341,6 @@ begin
fsmNextCpuState <= cs_std_seq;
fsmInstruction <= (others => '0');

-- BTW: as soon as all this works, plus some more unit tests especially for some to be found complicated BRAM borderline
-- cases (e.g. ADD @R1, @R2, everything in RAM plus before and after some instructions that challenge the asyncreset),
-- I should checkin the ISA V1.2 docu PDF (create a qnice/doc folder)
-- check in the current assembler and stuff (inside the qnice folder), the emulator (within qnice folder, and the other
-- material from there) and call it "V1.0" (before nerd session), because this is then a fully fledged
-- QNICE CPU working in the initival ENV1 scenario. V1.1 could then be: plus UART plus Bernd's monitor is running.
-- Later, V2.0 might be the new ISA plus another scenario than env1, e.g. QBM-1.
-- the tagging in GIT/GITHUB is important, so that in a later "retro" session, we can compare ISA 1.2 in env1 with
-- a full "QBM-1" computer having the new ISA (e.g. new CMP command, etc.).
-- Update all tools in qnice folder to vaxman's latest material from SourceForge.

-- @TODO (priority 2): Completely re-do the Tristate buffer topic. The lenghty wait-state and the #0000 situation when
-- writing are not necessary! As we have enough flip-flops, the Tristate handling can be done in "real-time".
-- as this has probably some pretty far reaching impact, the question is when to implement this. On the other hand,
-- the longer we wait, the bigger the impact will be. Some analysis with some MOVE, ADD & Co indirect @memory read/write
-- scenario will for sure help and create a more clear view.

-- as the previous state sets the direction control to read and the address to a meaningful value
-- (i.e. 0 after cs_reset or current PC afterwards), the DATA_driver will take care, that at the
-- falling edge of cs_fetch's clock cycle, DATA_From_Bus will contain the next opcode
Expand Down

0 comments on commit 1862eba

Please sign in to comment.