From dea6227958993d1b4e39acfce71bcd0306e3965b Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sat, 18 Nov 2023 13:55:29 -0800 Subject: [PATCH] Add irq code tb --- .gitlab-ci.yml | 17 +++++++- hw/efinix_fpga/simulation/Makefile | 10 +++-- hw/efinix_fpga/simulation/src/sim_top.sv | 4 +- .../tbs/interrupt_controller_code_tb.sv | 35 +++++++++++++++++ hw/efinix_fpga/src/super6502.sv | 17 +++++++- sw/test_code/irq_test/Makefile | 39 +++++++++++++++++++ sw/test_code/irq_test/link.ld | 35 +++++++++++++++++ sw/test_code/irq_test/main.s | 23 +++++++++++ sw/test_code/irq_test/vectors.s | 14 +++++++ 9 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 hw/efinix_fpga/simulation/tbs/interrupt_controller_code_tb.sv create mode 100644 sw/test_code/irq_test/Makefile create mode 100644 sw/test_code/irq_test/link.ld create mode 100644 sw/test_code/irq_test/main.s create mode 100644 sw/test_code/irq_test/vectors.s diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eb2c7fa..b302e70 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -160,4 +160,19 @@ interrupt_controller sim: - cd hw/efinix_fpga/simulation - make clean - TEST_PROGRAM_NAME=mapper_test make interrupt_controller_tb - - ./interrupt_controller_tb \ No newline at end of file + - ./interrupt_controller_tb + +interrupt_controller_code sim: + tags: + - linux + - iverilog + stage: simulate + artifacts: + paths: + - hw/efinix_fpga/simulation/interrupt_controller_code.vcd + script: + - source init_env.sh + - cd hw/efinix_fpga/simulation + - make clean + - TEST_PROGRAM_NAME=mapper_test make interrupt_controller_code_tb + - ./interrupt_controller_code_tb \ No newline at end of file diff --git a/hw/efinix_fpga/simulation/Makefile b/hw/efinix_fpga/simulation/Makefile index 2d6328d..d22cccd 100644 --- a/hw/efinix_fpga/simulation/Makefile +++ b/hw/efinix_fpga/simulation/Makefile @@ -9,7 +9,8 @@ TEST_PROGRAM_NAME?=loop_test TEST_FOLDER?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME) TEST_PROGRAM?=$(REPO_TOP)/sw/test_code/$(TEST_PROGRAM_NAME)/$(TEST_PROGRAM_NAME).hex -STANDALONE_TB= interrupt_controller_tb mapper_code_tb mapper_tb +STANDALONE_TB= interrupt_controller_tb mapper_tb rtc_tb +CODE_TB= interrupt_controller_code_tb mapper_code_tb #TODO implement something like sources.list @@ -32,10 +33,10 @@ full_sim: $(TARGET) $(SD_IMAGE) vvp -i $(TARGET) -fst $(STANDALONE_TB): $(SRCS) $(TBS) - iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INC) $(SRCS) $(TBS) + iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INC) $(SRCS) tbs/$@.sv -# mapper_code_tb: $(SRCS) $(TBS) $(INIT_MEM) -# iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INC) $(SRCS) $(TBS) +$(CODE_TB): $(SRCS) $(TBS) $(INIT_MEM) + iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INC) $(SRCS) tbs/$@.sv $(TARGET): $(INIT_MEM) $(SRCS) @@ -58,4 +59,5 @@ clean: rm -rf $(INIT_MEM) rm -rf $(SD_IMAGE) rm -rf $(STANDALONE_TB) + rm -rf $(CODE_TB) rm -rf *.vcd diff --git a/hw/efinix_fpga/simulation/src/sim_top.sv b/hw/efinix_fpga/simulation/src/sim_top.sv index 237db49..48fbf94 100644 --- a/hw/efinix_fpga/simulation/src/sim_top.sv +++ b/hw/efinix_fpga/simulation/src/sim_top.sv @@ -61,6 +61,7 @@ logic w_cpu_reset; logic [15:0] w_cpu_addr; logic [7:0] w_cpu_data_from_cpu, w_cpu_data_from_dut; logic w_cpu_rdy; +logic w_cpu_irqb; logic w_cpu_we; logic w_cpu_phi2; @@ -70,7 +71,7 @@ cpu_65c02 u_cpu( .reset(~w_cpu_reset), .AB(w_cpu_addr), .RDY(w_cpu_rdy), - .IRQ('0), + .IRQ(~w_cpu_irqb), .NMI('0), .DI_s1(w_cpu_data_from_dut), .DO(w_cpu_data_from_cpu), @@ -114,6 +115,7 @@ super6502 u_dut( .cpu_rwb(~w_cpu_we), .cpu_rdy(w_cpu_rdy), .cpu_phi2(w_cpu_phi2), + .cpu_irqb(w_cpu_irqb), .uart_rx(w_dut_uart_rx), .uart_tx(w_dut_uart_tx), diff --git a/hw/efinix_fpga/simulation/tbs/interrupt_controller_code_tb.sv b/hw/efinix_fpga/simulation/tbs/interrupt_controller_code_tb.sv new file mode 100644 index 0000000..3924f69 --- /dev/null +++ b/hw/efinix_fpga/simulation/tbs/interrupt_controller_code_tb.sv @@ -0,0 +1,35 @@ +`timescale 1ns/1ps + +module interrupt_controller_code_tb(); + +sim_top u_sim_top(); + +always begin + if ( + u_sim_top.w_cpu_addr == 16'h0 && + u_sim_top.w_cpu_we == '1 + ) begin + if (u_sim_top.w_cpu_data_from_cpu == 8'h6d) begin + $display("Good finish!"); + $finish(); + end else begin + $display("Bad finish!"); + $finish_and_return(-1); + end + end + # 1; +end + +initial begin + u_sim_top.u_dut.int_in = 0; + repeat (1000) @(posedge u_sim_top.r_clk_cpu); + u_sim_top.u_dut.int_in = 1; +end + +initial begin + repeat (2000) @(posedge u_sim_top.r_clk_cpu); + $display("Timed out"); + $finish_and_return(-1); +end + +endmodule \ No newline at end of file diff --git a/hw/efinix_fpga/src/super6502.sv b/hw/efinix_fpga/src/super6502.sv index f296019..5b64c75 100644 --- a/hw/efinix_fpga/src/super6502.sv +++ b/hw/efinix_fpga/src/super6502.sv @@ -82,6 +82,7 @@ logic w_multiplier_cs; logic w_divider_cs; logic w_uart_cs; logic w_spi_cs; +logic w_irq_cs; logic [7:0] w_rom_data_out; @@ -91,6 +92,7 @@ logic [7:0] w_multiplier_data_out; logic [7:0] w_divider_data_out; logic [7:0] w_uart_data_out; logic [7:0] w_spi_data_out; +logic [7:0] w_irq_data_out; logic [7:0] w_sdram_data_out; logic [24:0] w_mapped_addr; @@ -99,6 +101,7 @@ always_comb begin w_mapper_cs = cpu_addr >= 16'h200 && cpu_addr <= 16'h21f; w_rom_cs = w_mapped_addr >= 16'hf000 && w_mapped_addr <= 16'hffff; + w_irq_cs = w_mapped_addr >= 16'heffc && w_mapped_addr <= 16'heffd; w_timer_cs = w_mapped_addr >= 16'heff8 && w_mapped_addr <= 16'heffb; w_multiplier_cs = w_mapped_addr >= 16'heff0 && w_mapped_addr <= 16'heff7; w_divider_cs = w_mapped_addr >= 16'hefe8 && w_mapped_addr <= 16'hefef; @@ -113,7 +116,8 @@ always_comb begin w_divider_cs | w_uart_cs | w_spi_cs | - w_leds_cs + w_leds_cs | + w_irq_cs ); @@ -133,6 +137,8 @@ always_comb begin cpu_data_out = w_uart_data_out; else if (w_spi_cs) cpu_data_out = w_spi_data_out; + else if (w_irq_cs) + cpu_data_out = w_irq_data_out; else if (w_sdram_cs) cpu_data_out = w_sdram_data_out; else @@ -261,13 +267,20 @@ sdram_adapter u_sdram_adapter( .o_sdr_DQM(o_sdr_DQM) ); +logic w_irq; +assign cpu_irqb = ~w_irq; +logic [255:0] int_in; + interrupt_controller u_interrupt_controller( .clk(clk_cpu), .reset(~cpu_resb), .i_data(cpu_data_in), .o_data(w_irq_data_out), + .addr(w_mapped_addr[0]), .cs(w_irq_cs), - .rwb(cpu_rwb) + .rwb(cpu_rwb), + .int_in(int_in), + .int_out(w_irq) ); diff --git a/sw/test_code/irq_test/Makefile b/sw/test_code/irq_test/Makefile new file mode 100644 index 0000000..5b4837c --- /dev/null +++ b/sw/test_code/irq_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=irq_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +%.o: %.c $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +%.o: %.s $(LISTS) + $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/irq_test/link.ld b/sw/test_code/irq_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/irq_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, file = %O; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/test_code/irq_test/main.s b/sw/test_code/irq_test/main.s new file mode 100644 index 0000000..6363b0a --- /dev/null +++ b/sw/test_code/irq_test/main.s @@ -0,0 +1,23 @@ +.export _init, _nmi_int, _irq_int + +CMD = $effc +DAT = $effd + +.code + +_nmi_int: +_irq_int: + lda #$6d + sta $00 + +_init: + lda #$20 + sta CMD + lda #$ff + sta DAT + lda #$40 + sta CMD + lda #$ff + sta DAT + cli +@end: bra @end \ No newline at end of file diff --git a/sw/test_code/irq_test/vectors.s b/sw/test_code/irq_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/irq_test/vectors.s @@ -0,0 +1,14 @@ +; --------------------------------------------------------------------------- +; vectors.s +; --------------------------------------------------------------------------- +; +; Defines the interrupt vector table. + +.import _init +.import _nmi_int, _irq_int + +.segment "VECTORS" + +.addr _nmi_int ; NMI vector +.addr _init ; Reset vector +.addr _irq_int ; IRQ/BRK vector \ No newline at end of file