Unverified Commit eb2f9e2a by Miodrag Milanović Committed by GitHub

Merge pull request #15 from SergeyDegtyar/master

Add new tests for issues #567-865
parents 6a8cb072 166b2473
......@@ -234,5 +234,111 @@ $(eval $(call template,issue_00524,issue_00524))
#issue_00527
$(eval $(call template,issue_00527,issue_00527))
#issue_00567
$(eval $(call template,issue_00567,issue_00567))
#issue_00582
$(eval $(call template,issue_00582,issue_00582))
#issue_00589
$(eval $(call template,issue_00589,issue_00589))
#issue_00594
$(eval $(call template,issue_00594,issue_00594))
#issue_00603
$(eval $(call template,issue_00603,issue_00603))
#issue_00628
$(eval $(call template,issue_00628,issue_00628))
#issue_00630
$(eval $(call template,issue_00630,issue_00630))
#issue_00635
$(eval $(call template,issue_00635,issue_00635))
#issue_00639
$(eval $(call template,issue_00639,issue_00639))
#issue_00642
$(eval $(call template,issue_00642,issue_00642))
#issue_00644
$(eval $(call template,issue_00644,issue_00644))
#issue_00655
$(eval $(call template,issue_00655,issue_00655))
#issue_00675
$(eval $(call template,issue_00675,issue_00675))
#issue_00685
$(eval $(call template,issue_00685,issue_00685))
#issue_00689
$(eval $(call template,issue_00689,issue_00689))
#issue_00699
$(eval $(call template,issue_00699,issue_00699))
#issue_00705
$(eval $(call template,issue_00705,issue_00705))
#issue_00708
$(eval $(call template,issue_00708,issue_00708))
#issue_00737
$(eval $(call template,issue_00737,issue_00737))
#issue_00763
$(eval $(call template,issue_00763,issue_00763))
#issue_00767
$(eval $(call template,issue_00767,issue_00767))
#issue_00774
$(eval $(call template,issue_00774,issue_00774))
#issue_00781
$(eval $(call template,issue_00781,issue_00781))
#issue_00785
$(eval $(call template,issue_00785,issue_00785))
#issue_00807
$(eval $(call template,issue_00807,issue_00807))
#issue_00809
$(eval $(call template,issue_00809,issue_00809))
#issue_00810
$(eval $(call template,issue_00810,issue_00810))
#issue_00814
$(eval $(call template,issue_00814,issue_00814))
#issue_00823
$(eval $(call template,issue_00823,issue_00823))
#issue_00826
$(eval $(call template,issue_00826,issue_00826))
#issue_00831
$(eval $(call template,issue_00831,issue_00831))
#issue_00835
$(eval $(call template,issue_00835,issue_00835))
#issue_00857
$(eval $(call template,issue_00857,issue_00857))
#issue_00862
$(eval $(call template,issue_00862,issue_00862))
#issue_00865 - test failed (should be ok after merge https://github.com/YosysHQ/yosys/pull/866)
$(eval $(call template,issue_00865,issue_00865))
.PHONY: all clean
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [3:0] i = 0;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
top uut (i,b);
assert_Z b_test(.clk(clk), .A(b));
endmodule
// 4-input, route-through LUT test.
module top( (* keep *) input [3:0] I, output O);
//Cell instances
SB_LUT4 #(
.LUT_INIT(16'b0100000000000000)
) LUT (
.I0(),
.I1(I[1]),
.I2(),
.I3(),
.O(O)
);
endmodule // top
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire [4:0] b;
always @(posedge clk)
begin
i = i + 1;
end
main uut (b,clk);
assert_Z b_test(.clk(clk), .A(b[0]));
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire [4:0] b;
always @(posedge clk)
begin
i = i + 1;
end
main uut (b,clk);
assert_Z b_test(.clk(clk), .A(b[0]));
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire [4:0] b;
always @(posedge clk)
begin
i = i + 1;
end
main uut (b,clk);
assert_Z b_test(.clk(clk), .A(b[0]));
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire [4:0] b;
always @(posedge clk)
begin
i = i + 1;
end
main uut (b,clk);
assert_Z b_test(.clk(clk), .A(b[0]));
endmodule
//K-input Look-Up Table
module top #(
//The Look-up Table size (number of inputs)
parameter K,
//The lut mask.
//Left-most (MSB) bit corresponds to all inputs logic one.
//Defaults to always false.
parameter LUT_MASK={2**K{1'b0}}
) (
input [K-1:0] in,
output out
);
specify
(in *> out) = "";
endspecify
assign out = LUT_MASK[in];
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17;
always @(posedge clk)
begin
i = i + 1;
end
top uut (clk,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17);
assert_Z b1_test(.clk(clk), .A(b1));
assert_Z b17_test(.clk(clk), .A(b17));
endmodule
module top (
input a,
output zro_zro, zro_not, zro_buf, zro_one,
output not_zro, not_not, not_buf, not_one,
output buf_zro, buf_not, buf_buf, buf_one,
output one_zro, one_not, one_buf, one_one,
output magic_inverter
);
localparam [6:0] KEEP = 7'b1110001;
localparam [6:0] FLIP = 7'b1101010;
SB_LUT4 #(.LUT_INIT({1'b0, KEEP, KEEP, 1'b0})) magic_zro_zro (.I0(a), .I1(a), .I2(a), .I3(a), .O(zro_zro));
SB_LUT4 #(.LUT_INIT({1'b0, KEEP, FLIP, 1'b0})) magic_zro_not (.I0(a), .I1(a), .I2(a), .I3(a), .O(zro_not));
SB_LUT4 #(.LUT_INIT({1'b0, FLIP, KEEP, 1'b0})) magic_zro_buf (.I0(a), .I1(a), .I2(a), .I3(a), .O(zro_buf));
SB_LUT4 #(.LUT_INIT({1'b0, FLIP, FLIP, 1'b0})) magic_zro_one (.I0(a), .I1(a), .I2(a), .I3(a), .O(zro_one));
SB_LUT4 #(.LUT_INIT({1'b0, KEEP, FLIP, 1'b1})) magic_not_zro (.I0(a), .I1(a), .I2(a), .I3(a), .O(not_zro));
SB_LUT4 #(.LUT_INIT({1'b0, KEEP, KEEP, 1'b1})) magic_not_not (.I0(a), .I1(a), .I2(a), .I3(a), .O(not_not));
SB_LUT4 #(.LUT_INIT({1'b0, FLIP, FLIP, 1'b1})) magic_not_buf (.I0(a), .I1(a), .I2(a), .I3(a), .O(not_buf));
SB_LUT4 #(.LUT_INIT({1'b0, FLIP, KEEP, 1'b1})) magic_not_one (.I0(a), .I1(a), .I2(a), .I3(a), .O(not_one));
SB_LUT4 #(.LUT_INIT({1'b1, FLIP, KEEP, 1'b0})) magic_buf_zro (.I0(a), .I1(a), .I2(a), .I3(a), .O(buf_zro));
SB_LUT4 #(.LUT_INIT({1'b1, FLIP, FLIP, 1'b0})) magic_buf_not (.I0(a), .I1(a), .I2(a), .I3(a), .O(buf_not));
SB_LUT4 #(.LUT_INIT({1'b1, KEEP, KEEP, 1'b0})) magic_buf_buf (.I0(a), .I1(a), .I2(a), .I3(a), .O(buf_buf));
SB_LUT4 #(.LUT_INIT({1'b1, KEEP, FLIP, 1'b0})) magic_buf_one (.I0(a), .I1(a), .I2(a), .I3(a), .O(buf_one));
SB_LUT4 #(.LUT_INIT({1'b1, FLIP, FLIP, 1'b1})) magic_one_zro (.I0(a), .I1(a), .I2(a), .I3(a), .O(one_zro));
SB_LUT4 #(.LUT_INIT({1'b1, FLIP, KEEP, 1'b1})) magic_one_not (.I0(a), .I1(a), .I2(a), .I3(a), .O(one_not));
SB_LUT4 #(.LUT_INIT({1'b1, KEEP, FLIP, 1'b1})) magic_one_buf (.I0(a), .I1(a), .I2(a), .I3(a), .O(one_buf));
SB_LUT4 #(.LUT_INIT({1'b1, KEEP, KEEP, 1'b1})) magic_one_one (.I0(a), .I1(a), .I2(a), .I3(a), .O(one_one));
not (magic_inverter, a);
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
top uut (clk,b);
assert_Z b1_test(.clk(clk), .A(b));
endmodule
module top(input in, output out);
function func;
input arg;
func = arg;
endfunction
assign out = func(in);
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg [4:0] i = 0;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
top uut (clk,b);
assert_Z b1_test(.clk(clk), .A(b));
endmodule
module top
(
input clk,
input rstn,
input en,
input [XLEN-1:0] d,
output [XLEN-1:0] q
);
parameter XLEN = 4;
module top (
input a,
input b,
output [1:0] z);
wire n1, n2;
middle M1(.a(a), .b(b), .c(n1));
assign n2 = ~n1;
assign z[0] = n2;
assign z[1] = a & b;
endmodule
module middle (
input a,
input b,
output c);
assign c = a | b;
endmodule
module top (
input a,
input b,
output [1:0] z);
wire n1, n2;
middle M1(.a(a), .b(b), .c(n1));
assign n2 = n1; // z[0] in new.v is different from that in old.v due to this line
assign z[0] = n2;
assign z[1] = a | b;
endmodule
module middle (
input a,
input b,
output c);
assign c = a | b;
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg i = 0;
reg out;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
top uut (clk,i,b);
always @(posedge clk)
out <= $past(i,9);
assert_dff b1_test(.clk(clk), .test(b), .pat(out));
endmodule
module top(clk, in, out);
parameter DEPTH=10;
input wire clk, in;
output reg out;
always @(posedge clk)
out <= $past(in,DEPTH-1);
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg i = 0;
reg out;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
top uut (clk,i,b);
always @(posedge clk)
out <= $past(i,9);
assert_dff b1_test(.clk(clk), .test(b), .pat(out));
endmodule
module top(clk, in, out);
parameter DEPTH=10;
input wire clk, in;
output reg out;
always @(posedge clk)
assert($changed(in) == (in != $past(in)));
endmodule
module testbench;
reg clk;
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
#0 clk = 0;
repeat (10000) begin
#5 clk = 1;
#5 clk = 0;
end
$display("OKAY");
end
reg i = 0;
reg out;
wire b;
always @(posedge clk)
begin
i = i + 1;
end
wire serial_tx;
reg serial_rx;
reg clk100;
reg cpu_reset;
wire eth_ref_clk;
wire user_led0;
wire user_led1;
wire user_led2;
wire user_led3;
reg user_sw0;
reg user_sw1;
reg user_sw2;
reg user_sw3;
reg user_btn0;
reg user_btn1;
reg user_btn2;
reg user_btn3;
wire spiflash_1x_cs_n;
wire spiflash_1x_mosi;
reg spiflash_1x_miso;
wire spiflash_1x_wp;
wire spiflash_1x_hold;
wire [13:0] ddram_a;
wire [2:0] ddram_ba;
wire ddram_ras_n;
wire ddram_cas_n;
wire ddram_we_n;
wire ddram_cs_n;
wire [1:0] ddram_dm;
wire [15:0] ddram_dq;
wire [1:0] ddram_dqs_p;
wire [1:0] ddram_dqs_n;
wire ddram_clk_p;
wire ddram_clk_n;
wire ddram_cke;
wire ddram_odt;
wire ddram_reset_n;
top uut (
serial_tx,
serial_rx,
clk,
cpu_reset,
eth_ref_clk,
user_led0,
user_led1,
user_led2,
user_led3,
user_sw0,
user_sw1,
user_sw2,
user_sw3,
user_btn0,
user_btn1,
user_btn2,
user_btn3,
spiflash_1x_cs_n,
spiflash_1x_mosi,
spiflash_1x_miso,
spiflash_1x_wp,
spiflash_1x_hold,
ddram_a,
ddram_ba,
ddram_ras_n,
ddram_cas_n,
ddram_we_n,
ddram_cs_n,
ddram_dm,
ddram_dq,
ddram_dqs_p,
ddram_dqs_n,
ddram_clk_p,
ddram_clk_n,
ddram_cke,
ddram_odt,
ddram_reset_n
);
endmodule
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
`ifdef LM32_CONFIG_V
`else
`define LM32_CONFIG_V
//
// EXCEPTION VECTORS BASE ADDRESS
//
// Base address for exception vectors
`define CFG_EBA_RESET 32'h00000000
// Base address for the debug exception vectors. If the DC_RE flag is
// set or the at_debug signal is asserted (see CFG_ALTERNATE_EBA) this
// will also be used for normal exception vectors.
`define CFG_DEBA_RESET 32'h10000000
// Enable exception vector remapping by external signal
//`define CFG_ALTERNATE_EBA
//
// ALU OPTIONS
//
// Enable sign-extension instructions
`define CFG_SIGN_EXTEND_ENABLED
// Shifter
// You may either enable the piplined or the multi-cycle barrel
// shifter. The multi-cycle shifter will stall the pipeline until
// the result is available after 32 cycles.
// If both options are disabled, only "right shift by one bit" is
// available.
//`define CFG_MC_BARREL_SHIFT_ENABLED
`define CFG_PL_BARREL_SHIFT_ENABLED
// Multiplier
// The multiplier is available either in a multi-cycle version or
// in a pipelined one. The multi-cycle multiplier stalls the pipe
// for 32 cycles. If both options are disabled, multiply operations
// are not supported.
//`define CFG_MC_MULTIPLY_ENABLED
`define CFG_PL_MULTIPLY_ENABLED
// Enable the multi-cycle divider. Stalls the pipe until the result
// is ready after 32 cycles. If disabled, the divide operation is not
// supported.
`define CFG_MC_DIVIDE_ENABLED
//
// INTERRUPTS
//
// Enable support for 32 hardware interrupts
`define CFG_INTERRUPTS_ENABLED
// Enable level-sensitive interrupts. The interrupt line status is
// reflected in the IP register, which is then read-only.
`define CFG_LEVEL_SENSITIVE_INTERRUPTS
//
// USER INSTRUCTION
//
// Enable support for the user opcode.
//`define CFG_USER_ENABLED
//
// MEMORY MANAGEMENT UNIT
//
// Enable instruction and data translation lookaside buffers and
// restricted user mode.
//`define CFG_MMU_ENABLED
//
// CACHE
//
// Instruction cache
`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h00000000
`define CFG_ICACHE_LIMIT 32'h7fffffff
// Data cache
`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h00000000
`define CFG_DCACHE_LIMIT 32'h7fffffff
//
// DEBUG OPTION
//
// Globally enable debugging
//`define CFG_DEBUG_ENABLED
// Enable the hardware JTAG debugging interface.
// Note: to use this, there must be a special JTAG module for your
// device. At the moment, there is only support for the
// Spartan-6.
//`define CFG_JTAG_ENABLED
// JTAG UART is a communication channel which uses JTAG to transmit
// and receive bytes to and from the host computer.
//`define CFG_JTAG_UART_ENABLED
// Enable reading and writing to the memory and writing CSRs using
// the JTAG interface.
//`define CFG_HW_DEBUG_ENABLED
// Number of hardware watchpoints, max. 4
//`define CFG_WATCHPOINTS 32'h4
// Enable hardware breakpoints
//`define CFG_ROM_DEBUG_ENABLED
// Number of hardware breakpoints, max. 4
//`define CFG_BREAKPOINTS 32'h4
// Put the processor into debug mode by an external signal. That is,
// raise a breakpoint exception. This is useful if you have a debug
// monitor and a serial line and you want to trap into the monitor on a
// BREAK symbol on the serial line.
//`define CFG_EXTERNAL_BREAK_ENABLED
//
// REGISTER FILE
//
// The following option explicitly infers block RAM for the register
// file. There is extra logic to avoid parallel writes and reads.
// Normally, if your synthesizer is smart enough, this should not be
// necessary because it will automatically infer block RAM for you.
//`define CFG_EBR_POSEDGE_REGISTER_FILE
// Explicitly infers block RAM, too. But it uses two different clocks,
// one being shifted by 180deg, for the read and write port. Therefore,
// no additional logic to avoid the parallel write/reads.
//`define CFG_EBR_NEGEDGE_REGISTER_FILE
//
// MISCELLANEOUS
//
// Exceptions on wishbone bus errors
//`define CFG_BUS_ERRORS_ENABLED
// Enable the cycle counter
`define CFG_CYCLE_COUNTER_ENABLED
// Embedded instruction ROM using on-chip block RAM
//`define CFG_IROM_ENABLED
//`define CFG_IROM_INIT_FILE "NONE"
//`define CFG_IROM_BASE_ADDRESS 32'h10000000
//`define CFG_IROM_LIMIT 32'h10000fff
// Embedded data RAM using on-chip block RAM
//`define CFG_DRAM_ENABLED
//`define CFG_DRAM_INIT_FILE "NONE"
//`define CFG_DRAM_BASE_ADDRESS 32'h20000000
//`define CFG_DRAM_LIMIT 32'h20000fff
// Trace unit
//`define CFG_TRACE_ENABLED
// Resolve unconditional branches already in the X stage (UNTESTED!)
//`define CFG_FAST_UNCONDITIONAL_BRANCH
// log2 function
// If your simulator/synthesizer does not support the $clog2 system
// function you can use a constant function instead.
function integer clog2;
input integer value;
begin
value = value - 1;
for (clog2 = 0; value > 0; clog2 = clog2 + 1)
value = value >> 1;
end
endfunction
`define CLOG2 clog2
//`define CLOG2 $clog2
`endif
`ifdef LM32_CONFIG_V
`else
`define LM32_CONFIG_V
//
// EXCEPTION VECTORS BASE ADDRESS
//
// Base address for exception vectors
`define CFG_EBA_RESET 32'h00000000
// Base address for the debug exception vectors. If the DC_RE flag is
// set or the at_debug signal is asserted (see CFG_ALTERNATE_EBA) this
// will also be used for normal exception vectors.
`define CFG_DEBA_RESET 32'h10000000
// Enable exception vector remapping by external signal
//`define CFG_ALTERNATE_EBA
//
// ALU OPTIONS
//
// Enable sign-extension instructions
`define CFG_SIGN_EXTEND_ENABLED
// Shifter
// You may either enable the piplined or the multi-cycle barrel
// shifter. The multi-cycle shifter will stall the pipeline until
// the result is available after 32 cycles.
// If both options are disabled, only "right shift by one bit" is
// available.
`define CFG_MC_BARREL_SHIFT_ENABLED
//`define CFG_PL_BARREL_SHIFT_ENABLED
// Multiplier
// The multiplier is available either in a multi-cycle version or
// in a pipelined one. The multi-cycle multiplier stalls the pipe
// for 32 cycles. If both options are disabled, multiply operations
// are not supported.
`define CFG_MC_MULTIPLY_ENABLED
//`define CFG_PL_MULTIPLY_ENABLED
// Enable the multi-cycle divider. Stalls the pipe until the result
// is ready after 32 cycles. If disabled, the divide operation is not
// supported.
`define CFG_MC_DIVIDE_ENABLED
//
// INTERRUPTS
//
// Enable support for 32 hardware interrupts
`define CFG_INTERRUPTS_ENABLED
// Enable level-sensitive interrupts. The interrupt line status is
// reflected in the IP register, which is then read-only.
`define CFG_LEVEL_SENSITIVE_INTERRUPTS
//
// USER INSTRUCTION
//
// Enable support for the user opcode.
//`define CFG_USER_ENABLED
//
// MEMORY MANAGEMENT UNIT
//
// Enable instruction and data translation lookaside buffers and
// restricted user mode.
//`define CFG_MMU_ENABLED
//
// CACHE
//
// Instruction cache
`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 128
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h00000000
`define CFG_ICACHE_LIMIT 32'h7fffffff
// Data cache
//`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h00000000
`define CFG_DCACHE_LIMIT 32'h7fffffff
//
// DEBUG OPTION
//
// Globally enable debugging
//`define CFG_DEBUG_ENABLED
// Enable the hardware JTAG debugging interface.
// Note: to use this, there must be a special JTAG module for your
// device. At the moment, there is only support for the
// Spartan-6.
//`define CFG_JTAG_ENABLED
// JTAG UART is a communication channel which uses JTAG to transmit
// and receive bytes to and from the host computer.
//`define CFG_JTAG_UART_ENABLED
// Enable reading and writing to the memory and writing CSRs using
// the JTAG interface.
//`define CFG_HW_DEBUG_ENABLED
// Number of hardware watchpoints, max. 4
//`define CFG_WATCHPOINTS 32'h4
// Enable hardware breakpoints
//`define CFG_ROM_DEBUG_ENABLED
// Number of hardware breakpoints, max. 4
//`define CFG_BREAKPOINTS 32'h4
// Put the processor into debug mode by an external signal. That is,
// raise a breakpoint exception. This is useful if you have a debug
// monitor and a serial line and you want to trap into the monitor on a
// BREAK symbol on the serial line.
//`define CFG_EXTERNAL_BREAK_ENABLED
//
// REGISTER FILE
//
// The following option explicitly infers block RAM for the register
// file. There is extra logic to avoid parallel writes and reads.
// Normally, if your synthesizer is smart enough, this should not be
// necessary because it will automatically infer block RAM for you.
//`define CFG_EBR_POSEDGE_REGISTER_FILE
// Explicitly infers block RAM, too. But it uses two different clocks,
// one being shifted by 180deg, for the read and write port. Therefore,
// no additional logic to avoid the parallel write/reads.
//`define CFG_EBR_NEGEDGE_REGISTER_FILE
//
// MISCELLANEOUS
//
// Exceptions on wishbone bus errors
//`define CFG_BUS_ERRORS_ENABLED
// Enable the cycle counter
`define CFG_CYCLE_COUNTER_ENABLED
// Embedded instruction ROM using on-chip block RAM
//`define CFG_IROM_ENABLED
//`define CFG_IROM_INIT_FILE "NONE"
//`define CFG_IROM_BASE_ADDRESS 32'h10000000
//`define CFG_IROM_LIMIT 32'h10000fff
// Embedded data RAM using on-chip block RAM
//`define CFG_DRAM_ENABLED
//`define CFG_DRAM_INIT_FILE "NONE"
//`define CFG_DRAM_BASE_ADDRESS 32'h20000000
//`define CFG_DRAM_LIMIT 32'h20000fff
// Trace unit
//`define CFG_TRACE_ENABLED
// Resolve unconditional branches already in the X stage (UNTESTED!)
//`define CFG_FAST_UNCONDITIONAL_BRANCH
// log2 function
// If your simulator/synthesizer does not support the $clog2 system
// function you can use a constant function instead.
function integer clog2;
input integer value;
begin
value = value - 1;
for (clog2 = 0; value > 0; clog2 = clog2 + 1)
value = value >> 1;
end
endfunction
`define CLOG2 clog2
//`define CLOG2 $clog2
`endif
`ifdef LM32_CONFIG_V
`else
`define LM32_CONFIG_V
//
// EXCEPTION VECTORS BASE ADDRESS
//
// Base address for exception vectors
`define CFG_EBA_RESET 32'h00000000
// Base address for the debug exception vectors. If the DC_RE flag is
// set or the at_debug signal is asserted (see CFG_ALTERNATE_EBA) this
// will also be used for normal exception vectors.
`define CFG_DEBA_RESET 32'h10000000
// Enable exception vector remapping by external signal
//`define CFG_ALTERNATE_EBA
//
// ALU OPTIONS
//
// Enable sign-extension instructions
`define CFG_SIGN_EXTEND_ENABLED
// Shifter
// You may either enable the piplined or the multi-cycle barrel
// shifter. The multi-cycle shifter will stall the pipeline until
// the result is available after 32 cycles.
// If both options are disabled, only "right shift by one bit" is
// available.
`define CFG_MC_BARREL_SHIFT_ENABLED
//`define CFG_PL_BARREL_SHIFT_ENABLED
// Multiplier
// The multiplier is available either in a multi-cycle version or
// in a pipelined one. The multi-cycle multiplier stalls the pipe
// for 32 cycles. If both options are disabled, multiply operations
// are not supported.
`define CFG_MC_MULTIPLY_ENABLED
//`define CFG_PL_MULTIPLY_ENABLED
// Enable the multi-cycle divider. Stalls the pipe until the result
// is ready after 32 cycles. If disabled, the divide operation is not
// supported.
`define CFG_MC_DIVIDE_ENABLED
//
// INTERRUPTS
//
// Enable support for 32 hardware interrupts
`define CFG_INTERRUPTS_ENABLED
// Enable level-sensitive interrupts. The interrupt line status is
// reflected in the IP register, which is then read-only.
`define CFG_LEVEL_SENSITIVE_INTERRUPTS
//
// USER INSTRUCTION
//
// Enable support for the user opcode.
//`define CFG_USER_ENABLED
//
// MEMORY MANAGEMENT UNIT
//
// Enable instruction and data translation lookaside buffers and
// restricted user mode.
//`define CFG_MMU_ENABLED
//
// CACHE
//
// Instruction cache
//`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h00000000
`define CFG_ICACHE_LIMIT 32'h7fffffff
// Data cache
//`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h00000000
`define CFG_DCACHE_LIMIT 32'h7fffffff
//
// DEBUG OPTION
//
// Globally enable debugging
//`define CFG_DEBUG_ENABLED
// Enable the hardware JTAG debugging interface.
// Note: to use this, there must be a special JTAG module for your
// device. At the moment, there is only support for the
// Spartan-6.
//`define CFG_JTAG_ENABLED
// JTAG UART is a communication channel which uses JTAG to transmit
// and receive bytes to and from the host computer.
//`define CFG_JTAG_UART_ENABLED
// Enable reading and writing to the memory and writing CSRs using
// the JTAG interface.
//`define CFG_HW_DEBUG_ENABLED
// Number of hardware watchpoints, max. 4
//`define CFG_WATCHPOINTS 32'h4
// Enable hardware breakpoints
//`define CFG_ROM_DEBUG_ENABLED
// Number of hardware breakpoints, max. 4
//`define CFG_BREAKPOINTS 32'h4
// Put the processor into debug mode by an external signal. That is,
// raise a breakpoint exception. This is useful if you have a debug
// monitor and a serial line and you want to trap into the monitor on a
// BREAK symbol on the serial line.
//`define CFG_EXTERNAL_BREAK_ENABLED
//
// REGISTER FILE
//
// The following option explicitly infers block RAM for the register
// file. There is extra logic to avoid parallel writes and reads.
// Normally, if your synthesizer is smart enough, this should not be
// necessary because it will automatically infer block RAM for you.
//`define CFG_EBR_POSEDGE_REGISTER_FILE
// Explicitly infers block RAM, too. But it uses two different clocks,
// one being shifted by 180deg, for the read and write port. Therefore,
// no additional logic to avoid the parallel write/reads.
//`define CFG_EBR_NEGEDGE_REGISTER_FILE
//
// MISCELLANEOUS
//
// Exceptions on wishbone bus errors
//`define CFG_BUS_ERRORS_ENABLED
// Enable the cycle counter
`define CFG_CYCLE_COUNTER_ENABLED
// Embedded instruction ROM using on-chip block RAM
//`define CFG_IROM_ENABLED
//`define CFG_IROM_INIT_FILE "NONE"
//`define CFG_IROM_BASE_ADDRESS 32'h10000000
//`define CFG_IROM_LIMIT 32'h10000fff
// Embedded data RAM using on-chip block RAM
//`define CFG_DRAM_ENABLED
//`define CFG_DRAM_INIT_FILE "NONE"
//`define CFG_DRAM_BASE_ADDRESS 32'h20000000
//`define CFG_DRAM_LIMIT 32'h20000fff
// Trace unit
//`define CFG_TRACE_ENABLED
// Resolve unconditional branches already in the X stage (UNTESTED!)
//`define CFG_FAST_UNCONDITIONAL_BRANCH
// log2 function
// If your simulator/synthesizer does not support the $clog2 system
// function you can use a constant function instead.
function integer clog2;
input integer value;
begin
value = value - 1;
for (clog2 = 0; value > 0; clog2 = clog2 + 1)
value = value >> 1;
end
endfunction
`define CLOG2 clog2
//`define CLOG2 $clog2
`endif
LatticeMico32
=============
LatticeMico32 is a soft processor originally developed by Lattice
Semiconductor [1]. It was released under an open IP core license.
This is a fork of the original sources distributed by Lattice. It includes
new features, bugfixes and support for other FPGA devices. All additional
features are BSD-licensed.
Please note that this is only the processor core, not a complete SoC.
Original Features
=================
* 32-bit RISC architecture
* Six stage pipeline
* Two Wishbone bus interfaces for instruction and data
* 32 external interrupts
* 32 general purpose registers
* Instruction and data caches
* Embedded instruction ROM and data RAM support
Added Features
==============
* MMU support
* Non-privileged user-mode support
* JTAG support for Xilinx Spartan-6 devices
* Test bench (using Icarus Verilog [3])
* Replaced device specific primitives with generic verilog modules
* Unit tests shared with QEMU
Reference Manual
================
You can find the reference manual at [2].
Getting Started
===============
This repository provides all you need to simulate programs with the system
test bench. Try it, by typing
make sim_hello_world
in the test/ directory.
For an example of a larger project which uses this core, see MiSoC [4].
References
==========
[1] http://www.latticesemi.com
[2] http://www.latticesemi.com/documents/doc20890x45.pdf
[3] http://iverilog.icarus.com
[4] http://github.com/milkymist/misoc
DOCS=mmu.html
RM ?= rm -f
all: $(DOCS)
%.html: %.rst
rst2html $< >$@
clean:
$(RM) $(DOCS)
.PHONY: clean
/*
* LatticeMico32
* JTAG Registers
*
* Copyright (C) 2010 Michael Walle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
module jtag_cores (
input [7:0] reg_d,
input [2:0] reg_addr_d,
output reg_update,
output [7:0] reg_q,
output [2:0] reg_addr_q,
output jtck,
output jrstn
);
wire tck;
wire tdi;
wire tdo;
wire shift;
wire update;
wire reset;
jtag_tap jtag_tap (
.tck(tck),
.tdi(tdi),
.tdo(tdo),
.shift(shift),
.update(update),
.reset(reset)
);
reg [10:0] jtag_shift;
reg [10:0] jtag_latched;
always @(posedge tck or posedge reset)
begin
if(reset)
jtag_shift <= 11'b0;
else begin
if(shift)
jtag_shift <= {tdi, jtag_shift[10:1]};
else
jtag_shift <= {reg_d, reg_addr_d};
end
end
assign tdo = jtag_shift[0];
always @(posedge reg_update or posedge reset)
begin
if(reset)
jtag_latched <= 11'b0;
else
jtag_latched <= jtag_shift;
end
assign reg_update = update;
assign reg_q = jtag_latched[10:3];
assign reg_addr_q = jtag_latched[2:0];
assign jtck = tck;
assign jrstn = ~reset;
endmodule
/*
* LatticeMico32
* JTAG Test Access Port For Xilinx Sparan-6 Devices
*
* Copyright (C) 2010 Michael Walle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
module jtag_tap(
output tck,
output tdi,
input tdo,
output shift,
output update,
output reset
);
wire g_shift;
wire g_update;
assign shift = g_shift & sel;
assign update = g_update & sel;
BSCAN_SPARTAN6 #(
.JTAG_CHAIN(1)
) bscan (
.CAPTURE(),
.DRCK(tck),
.RESET(reset),
.RUNTEST(),
.SEL(sel),
.SHIFT(g_shift),
.TCK(),
.TDI(tdi),
.TMS(),
.UPDATE(g_update),
.TDO(tdo)
);
endmodule
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_adder.v
// Title : Integer adder / subtractor with comparison flag generation
// Dependencies : lm32_include.v
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_adder (
// ----- Inputs -------
adder_op_x,
adder_op_x_n,
operand_0_x,
operand_1_x,
// ----- Outputs -------
adder_result_x,
adder_carry_n_x,
adder_overflow_x
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input adder_op_x; // Operating to perform, 0 for addition, 1 for subtraction
input adder_op_x_n; // Inverted version of adder_op_x
input [`LM32_WORD_RNG] operand_0_x; // Operand to add, or subtract from
input [`LM32_WORD_RNG] operand_1_x; // Opearnd to add, or subtract by
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] adder_result_x; // Result of addition or subtraction
wire [`LM32_WORD_RNG] adder_result_x;
output adder_carry_n_x; // Inverted carry
wire adder_carry_n_x;
output adder_overflow_x; // Indicates if overflow occured, only valid for subtractions
reg adder_overflow_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire a_sign; // Sign (i.e. positive or negative) of operand 0
wire b_sign; // Sign of operand 1
wire result_sign; // Sign of result
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
lm32_addsub addsub (
// ----- Inputs -----
.DataA (operand_0_x),
.DataB (operand_1_x),
.Cin (adder_op_x),
.Add_Sub (adder_op_x_n),
// ----- Ouputs -----
.Result (adder_result_x),
.Cout (adder_carry_n_x)
);
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Extract signs of operands and result
assign a_sign = operand_0_x[`LM32_WORD_WIDTH-1];
assign b_sign = operand_1_x[`LM32_WORD_WIDTH-1];
assign result_sign = adder_result_x[`LM32_WORD_WIDTH-1];
// Determine whether an overflow occured when performing a subtraction
always @(*)
begin
// +ve - -ve = -ve -> overflow
// -ve - +ve = +ve -> overflow
if ( (!a_sign & b_sign & result_sign)
|| (a_sign & !b_sign & !result_sign)
)
adder_overflow_x = `TRUE;
else
adder_overflow_x = `FALSE;
end
endmodule
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_addsub.v
// Title : PMI adder/subtractor.
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_addsub (
// ----- Inputs -------
DataA,
DataB,
Cin,
Add_Sub,
// ----- Outputs -------
Result,
Cout
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input [31:0] DataA;
input [31:0] DataB;
input Cin;
input Add_Sub;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [31:0] Result;
wire [31:0] Result;
output Cout;
wire Cout;
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
// Modified for Milkymist: removed non-portable instantiated block
wire [32:0] tmp_addResult = DataA + DataB + Cin;
wire [32:0] tmp_subResult = DataA - DataB - !Cin;
assign Result = (Add_Sub == 1) ? tmp_addResult[31:0] : tmp_subResult[31:0];
assign Cout = (Add_Sub == 1) ? tmp_addResult[32] : !tmp_subResult[32];
endmodule
`ifdef LM32_CONFIG_V
`else
`define LM32_CONFIG_V
//
// EXCEPTION VECTORS BASE ADDRESS
//
// Base address for exception vectors
`define CFG_EBA_RESET 32'h00000000
// Base address for the debug exception vectors. If the DC_RE flag is
// set or the at_debug signal is asserted (see CFG_ALTERNATE_EBA) this
// will also be used for normal exception vectors.
`define CFG_DEBA_RESET 32'h00000000
// Enable exception vector remapping by external signal
//`define CFG_ALTERNATE_EBA
//
// ALU OPTIONS
//
// Enable sign-extension instructions
`define CFG_SIGN_EXTEND_ENABLED
// Shifter
// You may either enable the piplined or the multi-cycle barrel
// shifter. The multi-cycle shifter will stall the pipeline until
// the result is available after 32 cycles.
// If both options are disabled, only "right shift by one bit" is
// available.
//`define CFG_MC_BARREL_SHIFT_ENABLED
`define CFG_PL_BARREL_SHIFT_ENABLED
// Multiplier
// The multiplier is available either in a multi-cycle version or
// in a pipelined one. The multi-cycle multiplier stalls the pipe
// for 32 cycles. If both options are disabled, multiply operations
// are not supported.
//`define CFG_MC_MULTIPLY_ENABLED
`define CFG_PL_MULTIPLY_ENABLED
// Enable the multi-cycle divider. Stalls the pipe until the result
// is ready after 32 cycles. If disabled, the divide operation is not
// supported.
`define CFG_MC_DIVIDE_ENABLED
//
// INTERRUPTS
//
// Enable support for 32 hardware interrupts
`define CFG_INTERRUPTS_ENABLED
// Enable level-sensitive interrupts. The interrupt line status is
// reflected in the IP register, which is then read-only.
//`define CFG_LEVEL_SENSITIVE_INTERRUPTS
//
// USER INSTRUCTION
//
// Enable support for the user opcode.
//`define CFG_USER_ENABLED
//
// MEMORY MANAGEMENT UNIT
//
// Enable instruction and data translation lookaside buffers and
// restricted user mode.
//`define CFG_MMU_ENABLED
//
// CACHE
//
// Instruction cache
`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h00000000
`define CFG_ICACHE_LIMIT 32'h7fffffff
// Data cache
`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h00000000
`define CFG_DCACHE_LIMIT 32'h7fffffff
//
// DEBUG OPTION
//
// Globally enable debugging
//`define CFG_DEBUG_ENABLED
// Enable the hardware JTAG debugging interface.
// Note: to use this, there must be a special JTAG module for your
// device. At the moment, there is only support for the
// Spartan-6.
//`define CFG_JTAG_ENABLED
// JTAG UART is a communication channel which uses JTAG to transmit
// and receive bytes to and from the host computer.
//`define CFG_JTAG_UART_ENABLED
// Enable reading and writing to the memory and writing CSRs using
// the JTAG interface.
//`define CFG_HW_DEBUG_ENABLED
// Number of hardware watchpoints, max. 4
//`define CFG_WATCHPOINTS 32'h4
// Enable hardware breakpoints
//`define CFG_ROM_DEBUG_ENABLED
// Number of hardware breakpoints, max. 4
//`define CFG_BREAKPOINTS 32'h4
// Put the processor into debug mode by an external signal. That is,
// raise a breakpoint exception. This is useful if you have a debug
// monitor and a serial line and you want to trap into the monitor on a
// BREAK symbol on the serial line.
//`define CFG_EXTERNAL_BREAK_ENABLED
//
// REGISTER FILE
//
// The following option explicitly infers block RAM for the register
// file. There is extra logic to avoid parallel writes and reads.
// Normally, if your synthesizer is smart enough, this should not be
// necessary because it will automatically infer block RAM for you.
//`define CFG_EBR_POSEDGE_REGISTER_FILE
// Explicitly infers block RAM, too. But it uses two different clocks,
// one being shifted by 180deg, for the read and write port. Therefore,
// no additional logic to avoid the parallel write/reads.
//`define CFG_EBR_NEGEDGE_REGISTER_FILE
//
// MISCELLANEOUS
//
// Exceptions on wishbone bus errors
//`define CFG_BUS_ERRORS_ENABLED
// Enable the cycle counter
`define CFG_CYCLE_COUNTER_ENABLED
// Embedded instruction ROM using on-chip block RAM
//`define CFG_IROM_ENABLED
//`define CFG_IROM_INIT_FILE "NONE"
//`define CFG_IROM_BASE_ADDRESS 32'h10000000
//`define CFG_IROM_LIMIT 32'h10000fff
// Embedded data RAM using on-chip block RAM
//`define CFG_DRAM_ENABLED
//`define CFG_DRAM_INIT_FILE "NONE"
//`define CFG_DRAM_BASE_ADDRESS 32'h20000000
//`define CFG_DRAM_LIMIT 32'h20000fff
// Trace unit
//`define CFG_TRACE_ENABLED
// Resolve unconditional branches already in the X stage (UNTESTED!)
//`define CFG_FAST_UNCONDITIONAL_BRANCH
// log2 function
// If your simulator/synthesizer does not support the $clog2 system
// function you can use a constant function instead.
//function integer clog2;
// input integer value;
// begin
// value = value - 1;
// for (clog2 = 0; value > 0; clog2 = clog2 + 1)
// value = value >> 1;
// end
//endfunction
//
//`define CLOG2 clog2
`define CLOG2 $clog2
`endif
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* LatticeMico32
* True dual-ported RAM
*
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_dp_ram (
// ----- Inputs -------
clk_a,
clk_b,
ce_a,
ce_b,
addr_a,
addr_b,
di_a,
di_b,
we_a,
we_b,
// ----- Outputs -------
do_a,
do_b
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter data_width = 1; // Width of the data ports
parameter address_width = 1; // Width of the address ports
parameter init_file = "NONE"; // Initialization file
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_a; // Clock port A
input clk_b; // Clock port B
input ce_a; // Clock enable port A
input ce_b; // Clock enable port B
input [address_width-1:0] addr_a; // Read/write address port A
input [address_width-1:0] addr_b; // Read/write address port B
input [data_width-1:0] di_a; // Data input port A
input [data_width-1:0] di_b; // Data input port B
input we_a; // Write enable port A
input we_b; // Write enable port B
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [data_width-1:0] do_a; // Data output port A
wire [data_width-1:0] do_a;
output [data_width-1:0] do_b; // Data output port B
wire [data_width-1:0] do_b;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [data_width-1:0] mem[0:(1<<address_width)-1];
reg [address_width-1:0] ra_a; // Registered read address port A
reg [address_width-1:0] ra_b; // Registered read address port B
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Read ports
assign do_a = mem[ra_a];
assign do_b = mem[ra_b];
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Write ports
always @(posedge clk_a)
if ((ce_a == `TRUE) && (we_a == `TRUE))
mem[addr_a] <= di_a;
always @(posedge clk_b)
if ((ce_b == `TRUE) && (we_b == `TRUE))
mem[addr_b] <= di_b;
// Register read addresses for use on next cycle
always @(posedge clk_a)
if (ce_a == `TRUE)
ra_a <= addr_a;
always @(posedge clk_b)
if (ce_b == `TRUE)
ra_b <= addr_b;
/////////////////////////////////////////////////////
// Initialization
/////////////////////////////////////////////////////
generate
if (init_file != "NONE")
begin
initial $readmemh(init_file, mem);
end
endgenerate
endmodule
/*
* LatticeMico32
* Data Translation Lookaside Buffer
*
* Copyright (c) 2011-2012 Yann Sionneau <yann.sionneau@gmail.com>
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
`include "lm32_include.v"
`ifdef CFG_MMU_ENABLED
`define LM32_DTLB_STATE_RNG 1:0
`define LM32_DTLB_STATE_CHECK 2'b01
`define LM32_DTLB_STATE_FLUSH 2'b10
`define LM32_DTLB_OFFSET_RNG offset_msb:offset_lsb
`define LM32_DTLB_IDX_RNG index_msb:index_lsb
`define LM32_DTLB_VPFN_RNG vpfn_msb:vpfn_lsb
`define LM32_DTLB_TAG_RNG tag_msb:tag_lsb
`define LM32_DTLB_ADDR_RNG (index_width-1):0
`define LM32_DTLB_DATA_WIDTH (vpfn_width+tag_width+3) // +3 for valid, ci, ro
`define LM32_DTLB_DATA_RNG (`LM32_DTLB_DATA_WIDTH-1):0
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_dtlb (
// ----- Inputs -------
clk_i,
rst_i,
enable,
stall_x,
stall_m,
address_x,
address_m,
load_d,
store_d,
load_q_x,
store_q_x,
load_q_m,
store_q_m,
tlbpaddr,
tlbvaddr,
update,
flush,
invalidate,
// ----- Outputs -----
physical_load_store_address_m,
stall_request,
miss_vfn,
miss_x,
fault_x,
cache_inhibit_x
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter entries = 1024; // Number of entries in DTLB
parameter page_size = 4096; // DTLB page size
localparam offset_width = `CLOG2(page_size);
localparam index_width = `CLOG2(entries);
localparam offset_lsb = 0;
localparam offset_msb = (offset_lsb+offset_width-1);
localparam index_lsb = (offset_msb+1);
localparam index_msb = (index_lsb+index_width-1);
localparam tag_lsb = (index_msb+1);
localparam tag_msb = (`LM32_WORD_WIDTH-1);
localparam tag_width = (tag_msb-tag_lsb+1);
localparam vpfn_lsb = (offset_msb+1);
localparam vpfn_msb = (`LM32_WORD_WIDTH-1);
localparam vpfn_width = (vpfn_msb-vpfn_lsb+1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input enable; // Data TLB enable
input stall_x; // Stall X stage
input stall_m; // Stall M stage
input [`LM32_WORD_RNG] address_x; // X stage load/store address
input [`LM32_WORD_RNG] address_m; // M stage load/store address
input load_d; // Load instruction in D stage
input store_d; // Store instruction in D stage
input load_q_x; // Load instruction in X stage
input store_q_x; // Store instruction in X stage
input load_q_m; // Load instruction in M stage
input store_q_m; // Store instruction in M stage
input [`LM32_WORD_RNG] tlbpaddr;
input [`LM32_WORD_RNG] tlbvaddr;
input update;
input flush;
input invalidate;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] physical_load_store_address_m;
wire [`LM32_WORD_RNG] physical_load_store_address_m;
output stall_request;
wire stall_request;
output [`LM32_WORD_RNG] miss_vfn;
wire [`LM32_WORD_RNG] miss_vfn;
output miss_x;
wire miss_x;
output fault_x;
wire fault_x;
output cache_inhibit_x;
wire cache_inhibit_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire [`LM32_DTLB_ADDR_RNG] read_address;
wire [`LM32_DTLB_ADDR_RNG] write_address;
wire [`LM32_DTLB_DATA_RNG] write_data;
wire [`LM32_DTLB_DATA_RNG] tlbe;
wire [`LM32_DTLB_DATA_RNG] tlbe_inval;
wire [`LM32_DTLB_TAG_RNG] tlbe_tag_x;
wire [`LM32_DTLB_VPFN_RNG] tlbe_pfn_x;
wire tlbe_valid_x;
wire tlbe_ro_x;
wire tlbe_ci_x;
wire checking;
wire flushing;
wire write_port_enable;
reg [`LM32_DTLB_STATE_RNG] state; // Current state of FSM
reg [`LM32_DTLB_ADDR_RNG] flush_set;
reg [`LM32_DTLB_VPFN_RNG] tlbe_pfn_m;
reg lookup;
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
lm32_ram
#(
// ----- Parameters -------
.data_width (`LM32_DTLB_DATA_WIDTH),
.address_width (index_width)
// Modified for Milkymist: removed non-portable RAM parameters
) data_ram
(
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (read_address),
.enable_read (lookup),
.write_address (write_address),
.enable_write (`TRUE),
.write_enable (write_port_enable),
.write_data (write_data),
// ----- Outputs -------
.read_data ({tlbe_pfn_x, tlbe_tag_x, tlbe_ci_x, tlbe_ro_x, tlbe_valid_x})
);
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Compute address to use to index into the DTLB data memory
assign read_address = address_x[`LM32_DTLB_IDX_RNG];
// tlb_update_address will receive data from a CSR register
assign write_address = (flushing == `TRUE)
? flush_set
: tlbvaddr[`LM32_DTLB_IDX_RNG];
assign write_port_enable = (update == `TRUE) || (invalidate == `TRUE) || (flushing == `TRUE);
assign physical_load_store_address_m = (enable == `FALSE)
? address_m
: {tlbe_pfn_m, address_m[`LM32_DTLB_OFFSET_RNG]};
assign tlbe = {
tlbpaddr[`LM32_DTLB_VPFN_RNG], // pfn
tlbvaddr[`LM32_DTLB_TAG_RNG], // tag
tlbpaddr[2], // cache inhibit
tlbpaddr[1], // read only
`TRUE}; // valid
assign tlbe_inval = {{`LM32_DTLB_DATA_WIDTH-1{1'b0}}, `FALSE};
assign write_data = ((invalidate == `TRUE) || (flushing)) ? tlbe_inval : tlbe;
assign tlbe_match = ({tlbe_tag_x, tlbe_valid_x} == {address_x[`LM32_DTLB_TAG_RNG], `TRUE});
assign miss_vfn = {address_x[`LM32_DTLB_VPFN_RNG], {offset_width{1'b0}}};
assign miss_x = ((enable == `TRUE) && ((load_q_x == `TRUE) || (store_q_x == `TRUE)) && (tlbe_match == `FALSE) && (lookup == `FALSE));
assign cache_inhibit_x = ((enable == `TRUE) && (tlbe_ci_x == `TRUE));
assign fault_x = ((enable == `TRUE) && (store_q_x == `TRUE) && (tlbe_match == `TRUE) && (tlbe_ro_x == `TRUE));
assign checking = state[0];
assign flushing = state[1];
assign stall_request = (flushing == `TRUE) || (lookup == `TRUE);
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Lookup logic
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
lookup <= `FALSE;
else
begin
if ((enable == `TRUE) && (stall_x == `FALSE) && ((load_d == `TRUE) || (store_d == `TRUE)))
lookup <= `TRUE;
else
lookup <= `FALSE;
end
end
// X/M stage registers
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
tlbe_pfn_m <= {vpfn_width{1'bx}};
else if (stall_m == `FALSE)
tlbe_pfn_m <= tlbe_pfn_x;
end
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
flush_set <= {index_width{1'b1}};
state <= `LM32_DTLB_STATE_FLUSH;
end
else
begin
case (state)
`LM32_DTLB_STATE_CHECK:
begin
if (flush == `TRUE) begin
flush_set <= {index_width{1'b1}};
state <= `LM32_DTLB_STATE_FLUSH;
end
end
`LM32_DTLB_STATE_FLUSH:
begin
if (flush_set == {index_width{1'b0}})
state <= `LM32_DTLB_STATE_CHECK;
flush_set <= flush_set - 1'b1;
end
endcase
end
end
endmodule
`endif
/*
* LatticeMico32
* Instruction Translation Lookaside Buffer
*
* Copyright (c) 2011-2012 Yann Sionneau <yann.sionneau@gmail.com>
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
`include "lm32_include.v"
`ifdef CFG_MMU_ENABLED
`define LM32_ITLB_CTRL_FLUSH 5'h1
`define LM32_ITLB_CTRL_UPDATE 5'h2
`define LM32_TLB_CTRL_INVALIDATE_ENTRY 5'h10
`define LM32_ITLB_STATE_RNG 1:0
`define LM32_ITLB_STATE_CHECK 2'b01
`define LM32_ITLB_STATE_FLUSH 2'b10
`define LM32_ITLB_OFFSET_RNG offset_msb:offset_lsb
`define LM32_ITLB_IDX_RNG index_msb:index_lsb
`define LM32_ITLB_VPFN_RNG vpfn_msb:vpfn_lsb
`define LM32_ITLB_TAG_RNG tag_msb:tag_lsb
`define LM32_ITLB_ADDR_RNG (index_width-1):0
`define LM32_ITLB_DATA_WIDTH (vpfn_width+tag_width+1)
`define LM32_ITLB_DATA_RNG (`LM32_ITLB_DATA_WIDTH-1):0
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_itlb (
// ----- Inputs -------
clk_i,
rst_i,
enable,
stall_a,
stall_f,
stall_d,
stall_x,
pc_a,
pc_f,
pc_x,
read_enable_f,
tlbpaddr,
tlbvaddr,
update,
flush,
invalidate,
// ----- Outputs -------
physical_pc_f,
stall_request,
miss_vfn,
miss_f,
miss_x
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter entries = 1024; // Number of entires in ITLB
parameter page_size = 4096; // ITLB page size
localparam offset_width = (`CLOG2(page_size)-2);
localparam index_width = `CLOG2(entries);
localparam offset_lsb = 2;
localparam offset_msb = (offset_lsb+offset_width-1);
localparam index_lsb = (offset_msb+1);
localparam index_msb = (index_lsb+index_width-1);
localparam tag_lsb = (index_msb+1);
localparam tag_msb = (`LM32_WORD_WIDTH-1);
localparam tag_width = (tag_msb-tag_lsb+1);
localparam vpfn_lsb = (offset_msb+1);
localparam vpfn_msb = (`LM32_WORD_WIDTH-1);
localparam vpfn_width = (vpfn_msb-vpfn_lsb+1);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input enable; // Instruction TLB enable
input stall_a; // Stall instruction in A stage
input stall_f; // Stall instruction in F stage
input stall_d; // Stall instruction in D stage
input stall_x; // Stall instruction in X stage
input [`LM32_PC_RNG] pc_a; // Address of instruction in A stage
input [`LM32_PC_RNG] pc_f; // Address of instruction in F stage
input [`LM32_PC_RNG] pc_x; // Address of instruction in X stage
input read_enable_f; // Indicates if cache access is valid
input [`LM32_WORD_RNG] tlbpaddr;
input [`LM32_WORD_RNG] tlbvaddr;
input update;
input flush;
input invalidate;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_PC_RNG] physical_pc_f;
reg [`LM32_PC_RNG] physical_pc_f;
output stall_request;
wire stall_request;
output [`LM32_WORD_RNG] miss_vfn;
wire [`LM32_WORD_RNG] miss_vfn;
output miss_f;
wire miss_f;
output miss_x;
reg miss_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
wire [`LM32_ITLB_ADDR_RNG] read_address;
wire [`LM32_ITLB_ADDR_RNG] write_address;
wire read_port_enable;
wire write_port_enable;
wire [`LM32_ITLB_DATA_RNG] write_data;
reg [`LM32_ITLB_STATE_RNG] state;
reg [`LM32_ITLB_ADDR_RNG] flush_set;
wire [`LM32_ITLB_TAG_RNG] tlbe_tag_f;
wire [`LM32_ITLB_VPFN_RNG] tlbe_pfn_f;
wire tlbe_valid_f;
reg miss_d;
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
lm32_ram
#(
// ----- Parameters -------
.data_width (`LM32_ITLB_DATA_WIDTH),
.address_width (index_width)
// Modified for Milkymist: removed non-portable RAM parameters
) data_ram
(
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (read_address),
.enable_read (read_port_enable),
.write_address (write_address),
.enable_write (`TRUE),
.write_enable (write_port_enable),
.write_data (write_data),
// ----- Outputs -------
.read_data ({tlbe_pfn_f, tlbe_tag_f, tlbe_valid_f})
);
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Compute address to use to index into the ITLB memory
assign read_address = pc_a[`LM32_ITLB_IDX_RNG];
assign write_address = (flushing == `TRUE) ? flush_set : tlbvaddr[`LM32_ITLB_IDX_RNG];
assign read_port_enable = (stall_a == `FALSE);
assign write_port_enable = (update == `TRUE) || (invalidate == `TRUE) || (flushing == `TRUE);
assign write_data = ((invalidate == `TRUE) || (flushing == `TRUE))
? {{`LM32_ITLB_DATA_WIDTH-1{1'b0}}, `FALSE}
: {tlbpaddr[`LM32_ITLB_VPFN_RNG], tlbvaddr[`LM32_ITLB_TAG_RNG], `TRUE};
assign tlbe_match_f = ({tlbe_tag_f, tlbe_valid_f} == {pc_f[`LM32_ITLB_TAG_RNG], `TRUE});
assign miss_vfn = {pc_x[`LM32_ITLB_VPFN_RNG], {offset_width{1'b0}}, 2'b0};
assign miss_f = (enable == `TRUE) && (tlbe_match_f == `FALSE) && (stall_f == `FALSE);
assign flushing = state[1];
assign stall_request = (flushing == `TRUE);
always @(*)
begin
if (enable == `TRUE)
begin
if (tlbe_match_f == `TRUE)
physical_pc_f = {tlbe_pfn_f, pc_f[`LM32_ITLB_OFFSET_RNG]};
else
physical_pc_f = {`LM32_PC_WIDTH{1'b0}};
end
else
physical_pc_f = pc_f;
end
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
miss_d <= `FALSE;
miss_x <= `FALSE;
end
else
begin
if (stall_d == `FALSE)
miss_d <= miss_f;
if (stall_x == `FALSE)
miss_x <= miss_d;
end
end
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
flush_set <= {index_width{1'b1}};
state <= `LM32_ITLB_STATE_FLUSH;
end
else
begin
case (state)
`LM32_ITLB_STATE_CHECK:
begin
if (flush == `TRUE)
begin
flush_set <= {index_width{1'b1}};
state <= `LM32_ITLB_STATE_FLUSH;
end
end
`LM32_ITLB_STATE_FLUSH:
begin
if (flush_set == {index_width{1'b0}})
state <= `LM32_ITLB_STATE_CHECK;
flush_set <= flush_set - 1'b1;
end
endcase
end
end
endmodule
`endif
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_logic_op.v
// Title : Logic operations (and / or / not etc)
// Dependencies : lm32_include.v
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_logic_op (
// ----- Inputs -------
logic_op_x,
operand_0_x,
operand_1_x,
// ----- Outputs -------
logic_result_x
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input [`LM32_LOGIC_OP_RNG] logic_op_x;
input [`LM32_WORD_RNG] operand_0_x;
input [`LM32_WORD_RNG] operand_1_x;
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] logic_result_x;
reg [`LM32_WORD_RNG] logic_result_x;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
integer logic_idx;
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
always @(*)
begin
for(logic_idx = 0; logic_idx < `LM32_WORD_WIDTH; logic_idx = logic_idx + 1)
logic_result_x[logic_idx] = logic_op_x[{operand_1_x[logic_idx], operand_0_x[logic_idx]}];
end
endmodule
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_multiplier.v
// Title : Pipelined multiplier.
// Dependencies : lm32_include.v
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_multiplier (
// ----- Inputs -----
clk_i,
rst_i,
stall_x,
stall_m,
operand_0,
operand_1,
// ----- Ouputs -----
result
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_x; // Stall instruction in X stage
input stall_m; // Stall instruction in M stage
input [`LM32_WORD_RNG] operand_0; // Muliplicand
input [`LM32_WORD_RNG] operand_1; // Multiplier
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] result; // Product of multiplication
reg [`LM32_WORD_RNG] result;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [`LM32_WORD_RNG] muliplicand;
reg [`LM32_WORD_RNG] multiplier;
reg [`LM32_WORD_RNG] product;
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
muliplicand <= {`LM32_WORD_WIDTH{1'b0}};
multiplier <= {`LM32_WORD_WIDTH{1'b0}};
product <= {`LM32_WORD_WIDTH{1'b0}};
result <= {`LM32_WORD_WIDTH{1'b0}};
end
else
begin
if (stall_x == `FALSE)
begin
muliplicand <= operand_0;
multiplier <= operand_1;
end
if (stall_m == `FALSE)
product <= muliplicand * multiplier;
result <= product;
end
end
endmodule
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_ram.v
// Title : Pseudo dual-port RAM.
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : Options added to select EBRs (True-DP, Psuedo-DP, DQ, or
// : Distributed RAM).
// Version : 3.2
// : EBRs use SYNC resets instead of ASYNC resets.
// Version : 3.5
// : Added read-after-write hazard resolution when using true
// : dual-port EBRs
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_ram (
// ----- Inputs -------
read_clk,
write_clk,
reset,
enable_read,
read_address,
enable_write,
write_address,
write_data,
write_enable,
// ----- Outputs -------
read_data
);
/*----------------------------------------------------------------------
Parameters
----------------------------------------------------------------------*/
parameter data_width = 1; // Width of the data ports
parameter address_width = 1; // Width of the address ports
parameter init_file = "NONE"; // Initialization file
/*----------------------------------------------------------------------
Inputs
----------------------------------------------------------------------*/
input read_clk; // Read clock
input write_clk; // Write clock
input reset; // Reset
input enable_read; // Access enable
input [address_width-1:0] read_address; // Read/write address
input enable_write; // Access enable
input [address_width-1:0] write_address;// Read/write address
input [data_width-1:0] write_data; // Data to write to specified address
input write_enable; // Write enable
/*----------------------------------------------------------------------
Outputs
----------------------------------------------------------------------*/
output [data_width-1:0] read_data; // Data read from specified addess
wire [data_width-1:0] read_data;
/*----------------------------------------------------------------------
Internal nets and registers
----------------------------------------------------------------------*/
reg [data_width-1:0] mem[0:(1<<address_width)-1]; // The RAM
reg [address_width-1:0] ra; // Registered read address
/*----------------------------------------------------------------------
Combinational Logic
----------------------------------------------------------------------*/
// Read port
assign read_data = mem[ra];
/*----------------------------------------------------------------------
Sequential Logic
----------------------------------------------------------------------*/
// Write port
always @(posedge write_clk)
if ((write_enable == `TRUE) && (enable_write == `TRUE))
mem[write_address] <= write_data;
// Register read address for use on next cycle
always @(posedge read_clk)
if (enable_read)
ra <= read_address;
/*----------------------------------------------------------------------
Initialization
----------------------------------------------------------------------*/
generate
if (init_file != "NONE")
begin
initial $readmemh(init_file, mem);
end
endgenerate
endmodule
// ==================================================================
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_shifter.v
// Title : Barrel shifter
// Dependencies : lm32_include.v
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_shifter (
// ----- Inputs -------
clk_i,
rst_i,
stall_x,
direction_x,
sign_extend_x,
operand_0_x,
operand_1_x,
// ----- Outputs -------
shifter_result_m
);
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
input rst_i; // Reset
input stall_x; // Stall instruction in X stage
input direction_x; // Direction to shift
input sign_extend_x; // Whether shift is arithmetic (1'b1) or logical (1'b0)
input [`LM32_WORD_RNG] operand_0_x; // Operand to shift
input [`LM32_WORD_RNG] operand_1_x; // Operand that specifies how many bits to shift by
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [`LM32_WORD_RNG] shifter_result_m; // Result of shift
wire [`LM32_WORD_RNG] shifter_result_m;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg direction_m;
reg [`LM32_WORD_RNG] left_shift_result;
reg [`LM32_WORD_RNG] right_shift_result;
reg [`LM32_WORD_RNG] left_shift_operand;
wire [`LM32_WORD_RNG] right_shift_operand;
wire fill_value;
wire [`LM32_WORD_RNG] right_shift_in;
integer shift_idx_0;
integer shift_idx_1;
/////////////////////////////////////////////////////
// Combinational Logic
/////////////////////////////////////////////////////
// Select operands - To perform a left shift, we reverse the bits and perform a right shift
always @(*)
begin
for (shift_idx_0 = 0; shift_idx_0 < `LM32_WORD_WIDTH; shift_idx_0 = shift_idx_0 + 1)
left_shift_operand[`LM32_WORD_WIDTH-1-shift_idx_0] = operand_0_x[shift_idx_0];
end
assign right_shift_operand = direction_x == `LM32_SHIFT_OP_LEFT ? left_shift_operand : operand_0_x;
// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
assign fill_value = (sign_extend_x == `TRUE) && (direction_x == `LM32_SHIFT_OP_RIGHT)
? operand_0_x[`LM32_WORD_WIDTH-1]
: 1'b0;
// Determine bits to shift in for right shift or rotate
assign right_shift_in = {`LM32_WORD_WIDTH{fill_value}};
// Reverse bits to get left shift result
always @(*)
begin
for (shift_idx_1 = 0; shift_idx_1 < `LM32_WORD_WIDTH; shift_idx_1 = shift_idx_1 + 1)
left_shift_result[`LM32_WORD_WIDTH-1-shift_idx_1] = right_shift_result[shift_idx_1];
end
// Select result
assign shifter_result_m = direction_m == `LM32_SHIFT_OP_LEFT ? left_shift_result : right_shift_result;
/////////////////////////////////////////////////////
// Sequential Logic
/////////////////////////////////////////////////////
// Perform right shift
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
right_shift_result <= {`LM32_WORD_WIDTH{1'b0}};
direction_m <= `FALSE;
end
else
begin
if (stall_x == `FALSE)
begin
right_shift_result <= {right_shift_in, right_shift_operand} >> operand_1_x[`LM32_SHIFT_RNG];
direction_m <= direction_x;
end
end
end
endmodule
CROSS_COMPILE ?= lm32-elf-
# extra plusargs for simulation
# eg. EXTRA_PLUSARGS = "+dump=dump.vcd"
EXTRA_PLUSARGS ?=
# enable additional debug output
# eg. EXTRA_DEFINES = "-DTB_ENABLE_WB_TRACES"
EXTRA_DEFINES ?=
CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
# in case make does not have this already defined
RM ?= rm -f
LDFLAGS = -Tlinker.ld -fno-builtin -nostdlib -lgcc
RTL ?= ../rtl
SOURCES = tb_lm32_system.v lm32_config.v
SOURCES += $(RTL)/lm32_adder.v $(RTL)/lm32_addsub.v $(RTL)/lm32_cpu.v
SOURCES += $(RTL)/lm32_dcache.v $(RTL)/lm32_debug.v $(RTL)/lm32_decoder.v
SOURCES += $(RTL)/lm32_dp_ram.v $(RTL)/lm32_icache.v
SOURCES += $(RTL)/lm32_instruction_unit.v $(RTL)/lm32_interrupt.v
SOURCES += $(RTL)/lm32_jtag.v $(RTL)/lm32_load_store_unit.v
SOURCES += $(RTL)/lm32_logic_op.v $(RTL)/lm32_mc_arithmetic.v
SOURCES += $(RTL)/lm32_multiplier.v $(RTL)/lm32_ram.v $(RTL)/lm32_shifter.v
SOURCES += $(RTL)/lm32_itlb.v $(RTL)/lm32_dtlb.v
SOURCES += $(RTL)/lm32_top.v
all: tb_lm32_system
sim_%: %.vh tb_lm32_system
@vvp tb_lm32_system +prog=$< $(EXTRA_PLUSARGS)
trace_%: %.vh tb_lm32_system
@vvp tb_lm32_system +trace=trace_$*.txt +prog=$< $(EXTRA_PLUSARGS)
%.elf:
$(CC) $(LDFLAGS) -o $@ $^
%.vh: %.elf
$(OBJCOPY) -O verilog $< $@
clean:
$(RM) tb_lm32_system *.vcd *.elf *.vh trace*.txt
tb_lm32_system: $(SOURCES)
iverilog -I. -I$(RTL) -o $@ $(SOURCES) $(EXTRA_DEFINES)
unittest:
$(MAKE) -C unittests check
.PHONY: clean unittest
hello_world.elf: crt.S hello_world.c
pipe1.elf: pipe1.S
.globl _start
.text
_start:
xor r0, r0, r0
mvhi sp, hi(_fstack)
ori sp, sp, lo(_fstack)
mv fp,r0
mvhi r1, hi(_fbss)
ori r1, r1, lo(_fbss)
mvhi r2, hi(_ebss)
ori r2, r2, lo(_ebss)
1:
bge r1, r2, 2f
sw (r1+0), r0
addi r1, r1, 4
bi 1b
2:
calli main
mvhi r1, 0xdead
ori r2, r0, 0xbeef
sw (r1+0), r2
void putc(char c)
{
char *tx = (char*)0xff000000;
*tx = c;
}
void puts(char *s)
{
while (*s) putc(*s++);
}
void main(void)
{
puts("Hello World\n");
}
OUTPUT_FORMAT("elf32-lm32")
ENTRY(_start)
__DYNAMIC = 0;
MEMORY {
pmem : ORIGIN = 0x00000000, LENGTH = 0x8000
dmem : ORIGIN = 0x00008000, LENGTH = 0x8000
}
SECTIONS
{
.text :
{
_ftext = .;
*(.text .stub .text.* .gnu.linkonce.t.*)
_etext = .;
} > pmem
.rodata :
{
. = ALIGN(4);
_frodata = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
_erodata = .;
} > dmem
.data :
{
. = ALIGN(4);
_fdata = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
_gp = ALIGN(16);
*(.sdata .sdata.* .gnu.linkonce.s.*)
_edata = .;
} > dmem
.bss :
{
. = ALIGN(4);
_fbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
_end = .;
} > dmem
}
PROVIDE(_fstack = ORIGIN(dmem) + LENGTH(dmem) - 4);
`ifdef LM32_CONFIG_V
`else
`define LM32_CONFIG_V
`define CFG_EBA_RESET 32'h0
`define CFG_DEBA_RESET 32'h0
`define CFG_PL_MULTIPLY_ENABLED
`define CFG_PL_BARREL_SHIFT_ENABLED
`define CFG_SIGN_EXTEND_ENABLED
`define CFG_MC_DIVIDE_ENABLED
`define CFG_EBR_POSEDGE_REGISTER_FILE
`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h0
`define CFG_ICACHE_LIMIT 32'h7fffffff
`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h0
`define CFG_DCACHE_LIMIT 32'h7fffffff
// Enable Debugging
//`define CFG_JTAG_ENABLED
//`define CFG_JTAG_UART_ENABLED
`define CFG_DEBUG_ENABLED
//`define CFG_HW_DEBUG_ENABLED
`define CFG_ROM_DEBUG_ENABLED
`define CFG_BREAKPOINTS 32'h4
`define CFG_WATCHPOINTS 32'h4
`define CFG_EXTERNAL_BREAK_ENABLED
`define CFG_GDBSTUB_ENABLED
// Enable MMU
`define CFG_MMU_ENABLED
`define CLOG2 $clog2
`endif
.globl _start
.text
_start:
xor r0, r0, r0
mvi r1, 10
addi r2, r1, 1
addi r3, r2, 1
muli r4, r1, 10
add r5, r4, r4
mvhi r1, 0xdead
ori r2, r0, 0xbeef
sw (r1+0), r2
/*
* LatticeMico32
* System Test Bench
*
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
`include "lm32_include.v"
module soc();
integer i;
reg sys_rst;
reg sys_clk;
reg [31:0] interrupt;
reg i_ack;
wire [31:0] i_adr;
wire i_cyc;
wire [31:0] i_dat;
wire i_stb;
reg d_ack;
wire [31:0] d_adr;
wire d_cyc;
wire [31:0] d_dat_i;
wire [31:0] d_dat_o;
wire [3:0] d_sel;
wire d_stb;
lm32_top lm32(
.clk_i(sys_clk),
.rst_i(sys_rst),
.interrupt(interrupt),
.I_ACK_I(i_ack),
.I_ADR_O(i_adr),
.I_BTE_O(),
.I_CTI_O(),
.I_CYC_O(i_cyc),
.I_DAT_I(i_dat),
.I_DAT_O(),
.I_ERR_I(1'b0),
.I_LOCK_O(),
.I_RTY_I(1'b0),
.I_SEL_O(),
.I_STB_O(i_stb),
.I_WE_O(),
.D_ACK_I(d_ack),
.D_ADR_O(d_adr),
.D_BTE_O(),
.D_CTI_O(),
.D_CYC_O(d_cyc),
.D_DAT_I(d_dat_i),
.D_DAT_O(d_dat_o),
.D_ERR_I(1'b0),
.D_LOCK_O(),
.D_RTY_I(1'b0),
.D_SEL_O(d_sel),
.D_STB_O(d_stb),
.D_WE_O(d_we)
);
// clock
initial sys_clk = 1'b0;
always #5 sys_clk = ~sys_clk;
// reset
initial begin
sys_rst = 1'b1;
#20
sys_rst = 1'b0;
end
// memory
reg [7:0] mem[0:65536];
initial begin
for(i=0;i<65536;i=i+1)
mem[i] = 8'b0;
end
wire [31:0] dmem_dat_i;
reg [31:0] dmem_dat_o;
wire [13:0] dmem_adr;
wire [3:0] dmem_we;
always @(posedge sys_clk) begin
if(dmem_we[0]) mem[{dmem_adr, 2'b11}] <= dmem_dat_i[7:0];
if(dmem_we[1]) mem[{dmem_adr, 2'b10}] <= dmem_dat_i[15:8];
if(dmem_we[2]) mem[{dmem_adr, 2'b01}] <= dmem_dat_i[23:16];
if(dmem_we[3]) mem[{dmem_adr, 2'b00}] <= dmem_dat_i[31:24];
dmem_dat_o[7:0] <= mem[{dmem_adr, 2'b11}];
dmem_dat_o[15:8] <= mem[{dmem_adr, 2'b10}];
dmem_dat_o[23:16] <= mem[{dmem_adr, 2'b01}];
dmem_dat_o[31:24] <= mem[{dmem_adr, 2'b00}];
end
reg [31:0] pmem_dat_o;
wire [13:0] pmem_adr;
always @(posedge sys_clk) begin
pmem_dat_o[7:0] <= mem[{pmem_adr, 2'b11}];
pmem_dat_o[15:8] <= mem[{pmem_adr, 2'b10}];
pmem_dat_o[23:16] <= mem[{pmem_adr, 2'b01}];
pmem_dat_o[31:24] <= mem[{pmem_adr, 2'b00}];
end
// uart
always @(posedge sys_clk) begin
if(d_cyc & d_stb & d_we & d_ack)
if(d_adr == 32'hff000000)
$write("%c", d_dat_o[7:0]);
end
// wishbone interface for instruction bus
always @(posedge sys_clk) begin
if(sys_rst)
i_ack <= 1'b0;
else begin
i_ack <= 1'b0;
if(i_cyc & i_stb & ~i_ack)
i_ack <= 1'b1;
end
end
assign i_dat = pmem_dat_o;
assign pmem_adr = i_adr[15:2];
task dump_processor_state;
begin
$display("Processor state:");
$display(" PSW=%08x", lm32.cpu.psw);
$display(" IE=%08x IP=%08x IM=%08x",
lm32.cpu.interrupt_unit.ie,
lm32.cpu.interrupt_unit.ip,
lm32.cpu.interrupt_unit.im
);
for(i=0; i<32; i=i+1) begin
if(i%4 == 0)
$write(" ");
$write("r%02d=%08x ", i, lm32.cpu.reg_0.mem[i]);
if((i+1)%4 == 0)
$write("\n");
end
end
endtask
// QEMU test core
reg [15:0] testname_adr;
reg [8*32:0] testname;
reg testname_end;
always @(posedge sys_clk) begin
if(d_cyc & d_stb & d_we & d_ack)
begin
if(d_adr == 32'hffff0000)
$finish;
else if(d_adr == 32'hffff0004) begin
// is there any better way to do this?
testname_end = 1'b0;
for(i=0; i<32; i=i+1) begin
testname = testname << 8;
if(testname_end == 1'b0) begin
testname[7:0] = mem[testname_adr+i];
if(mem[testname_adr+i] == 8'b0)
testname_end = 1'b1;
end else
testname[7:0] = 8'b0;
end
$display("TC %-32s %s", testname, (|d_dat_o) ? "FAILED" : "OK");
if(|d_dat_o)
dump_processor_state();
end
else if(d_adr == 32'hffff0008)
testname_adr <= d_dat_o[15:0];
end
end
// wishbone interface for data bus
always @(posedge sys_clk) begin
if(sys_rst)
d_ack <= 1'b0;
else begin
d_ack <= 1'b0;
if(d_cyc & d_stb & ~d_ack)
d_ack <= 1'b1;
end
end
assign d_dat_i = dmem_dat_o;
assign dmem_dat_i = d_dat_o;
assign dmem_adr = d_adr[15:2];
assign dmem_we = {4{d_cyc & d_stb & d_we & ~|d_adr[31:16]}} & d_sel;
// interrupts
initial interrupt <= 32'b0;
// simulation end request
always @(posedge sys_clk) begin
if(d_cyc & d_stb & d_we & d_ack)
if(d_adr == 32'hdead0000 && d_dat_o == 32'hbeef)
$finish;
end
// traces
`ifdef TB_ENABLE_WB_TRACES
always @(posedge sys_clk) begin
if(i_cyc & i_stb & i_ack)
$display("i load @%08x %08x", i_adr, i_dat);
if(d_cyc & d_stb & ~d_we & d_ack)
$display("d load @%08x %08x", d_adr, d_dat_o);
if(d_cyc & d_stb & d_we & d_ack)
$display("d store @%08x %08x", d_adr, d_dat_o);
end
`endif
`ifdef TB_ENABLE_TLB_TRACES
always @(posedge sys_clk)
begin
if (lm32.cpu.instruction_unit.itlb.write_port_enable)
$display("itlb write @%04x 0x%08x",
lm32.cpu.instruction_unit.itlb.write_address,
lm32.cpu.instruction_unit.itlb.write_data);
if (lm32.cpu.load_store_unit.dtlb.write_port_enable)
$display("dtlb write @%04x 0x%08x",
lm32.cpu.instruction_unit.itlb.write_address,
lm32.cpu.instruction_unit.itlb.write_data);
end
`endif
// dump signals
reg [256*8:0] vcdfile;
initial begin
if($value$plusargs("dump=%s", vcdfile)) begin
$dumpfile(vcdfile);
$dumpvars(0, soc);
end
end
// init memory
reg [256*8:0] prog;
initial begin
if(! $value$plusargs("prog=%s", prog)) begin
$display("ERROR: please specify +prog=<file>.vh to start.");
$finish;
end
end
initial $readmemh(prog, mem);
// trace pipeline
reg [256*8:0] tracefile;
integer trace_started;
integer trace_enabled;
integer cycle;
integer tracefd;
initial begin
if($value$plusargs("trace=%s", tracefile)) begin
trace_enabled = 1;
cycle = 0;
tracefd = $fopen(tracefile);
trace_started = 0;
end else
trace_enabled = 0;
end
`ifdef CFG_ICACHE_ENABLED
assign icache_ready = lm32.cpu.instruction_unit.icache.state != 1;
`else
assign icache_ready = `TRUE;
`endif
`ifdef CFG_DCACHE_ENABLED
assign dcache_ready = lm32.cpu.load_store_unit.dcache.state != 1;
`else
assign dcache_ready = `TRUE;
`endif
always @(posedge sys_clk) begin
// wait until icache and dcache init is done
if(!trace_started && icache_ready && dcache_ready)
trace_started = 1;
if(trace_enabled && trace_started) begin
$fwrite(tracefd, "%-d ", cycle);
`ifdef CFG_ICACHE_ENABLED
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_a, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.valid_a);
`endif
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_f, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.kill_f);
$fwrite(tracefd, "%1d ", lm32.cpu.valid_f);
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_d, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.kill_d);
$fwrite(tracefd, "%1d ", lm32.cpu.valid_d);
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_x, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.kill_x);
$fwrite(tracefd, "%1d ", lm32.cpu.valid_x);
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_m, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.kill_m);
$fwrite(tracefd, "%1d ", lm32.cpu.valid_m);
$fwrite(tracefd, "%x ", {lm32.cpu.instruction_unit.pc_w, 2'b00});
$fwrite(tracefd, "%1d ", lm32.cpu.kill_w);
$fwrite(tracefd, "%1d ", lm32.cpu.valid_w);
$fwrite(tracefd, "\n");
cycle = cycle + 1;
end
end
endmodule
CROSS_COMPILE ?= lm32-elf-
CC = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)as
AS = $(CC) -x assembler
SIZE = $(CROSS_COMPILE)size
LD = $(CC)
OBJCOPY = $(CROSS_COMPILE)objcopy
# in case make does not have this already defined
RM ?= rm -f
LDFLAGS = -Tlinker.ld -nostdlib -lgcc
ASFLAGS += -Wa,-I,.
CRT = crt.o
TESTCASES += test_add.elf
TESTCASES += test_addi.elf
TESTCASES += test_and.elf
TESTCASES += test_andhi.elf
TESTCASES += test_andi.elf
TESTCASES += test_b.elf
TESTCASES += test_be.elf
TESTCASES += test_bg.elf
TESTCASES += test_bge.elf
TESTCASES += test_bgeu.elf
TESTCASES += test_bgu.elf
TESTCASES += test_bi.elf
TESTCASES += test_bne.elf
TESTCASES += test_break.elf
TESTCASES += test_bret.elf
TESTCASES += test_call.elf
TESTCASES += test_calli.elf
TESTCASES += test_cmpe.elf
TESTCASES += test_cmpei.elf
TESTCASES += test_cmpg.elf
TESTCASES += test_cmpgi.elf
TESTCASES += test_cmpge.elf
TESTCASES += test_cmpgei.elf
TESTCASES += test_cmpgeu.elf
TESTCASES += test_cmpgeui.elf
TESTCASES += test_cmpgu.elf
TESTCASES += test_cmpgui.elf
TESTCASES += test_cmpne.elf
TESTCASES += test_cmpnei.elf
TESTCASES += test_divu.elf
TESTCASES += test_eret.elf
TESTCASES += test_lb.elf
TESTCASES += test_lbu.elf
TESTCASES += test_lh.elf
TESTCASES += test_lhu.elf
TESTCASES += test_lw.elf
TESTCASES += test_mmu.elf
TESTCASES += test_modu.elf
TESTCASES += test_mul.elf
TESTCASES += test_muli.elf
TESTCASES += test_nor.elf
TESTCASES += test_nori.elf
TESTCASES += test_or.elf
TESTCASES += test_ori.elf
TESTCASES += test_orhi.elf
#TESTCASES += test_rcsr.elf
TESTCASES += test_ret.elf
TESTCASES += test_sb.elf
TESTCASES += test_scall.elf
TESTCASES += test_sextb.elf
TESTCASES += test_sexth.elf
TESTCASES += test_sh.elf
TESTCASES += test_sl.elf
TESTCASES += test_sli.elf
TESTCASES += test_sr.elf
TESTCASES += test_sri.elf
TESTCASES += test_sru.elf
TESTCASES += test_srui.elf
TESTCASES += test_sub.elf
TESTCASES += test_sw.elf
#TESTCASES += test_wcsr.elf
TESTCASES += test_xnor.elf
TESTCASES += test_xnori.elf
TESTCASES += test_xor.elf
TESTCASES += test_xori.elf
# auto generated test_mmu with NOPs inserted
TESTCASES += test_mmu_nop1.elf
TESTCASES += test_mmu_nop2.elf
TESTCASES += test_mmu_nop3.elf
all: build
test_mmu_nop1.S: test_mmu.S
@sed 's|##NOPS##|nop|' $< > $@
test_mmu_nop2.S: test_mmu.S
@sed 's|##NOPS##|nop;nop|' $< > $@
test_mmu_nop3.S: test_mmu.S
@sed 's|##NOPS##|nop;nop;nop|' $< > $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.S
$(AS) $(ASFLAGS) -c $< -o $@
%.elf: %.o macros.inc $(CRT)
$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
%.vh: %.elf
$(OBJCOPY) -O verilog $< $@
build: $(CRT) $(TESTCASES) $(TESTCASES:.elf=.vh)
check: $(TESTCASES:.elf=.vh)
@$(MAKE) -C .. tb_lm32_system
@for case in $(TESTCASES:.elf=.vh); do \
echo -e "\nRunning test case $$case"; \
vvp ../tb_lm32_system +prog=$$case; \
done
check_%: test_%.vh
@$(MAKE) -C .. tb_lm32_system
vvp ../tb_lm32_system +prog=$<
clean:
$(RM) $(TESTCASES) $(TESTCASES:.elf=.vh) $(CRT) *nop?.S tb_lm32.vcd
.include "macros.inc"
.text
.global _start
_start:
_reset_handler:
xor r0, r0, r0
mvhi r1, hi(_start)
ori r1, r1, lo(_start)
wcsr eba, r1
wcsr deba, r1
bi _main
nop
nop
_breakpoint_handler:
ori r25, r25, 1
addi ra, ba, 4
ret
nop
nop
nop
nop
nop
_instruction_bus_error_handler:
ori r25, r25, 2
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
_watchpoint_handler:
ori r25, r25, 4
addi ra, ba, 4
ret
nop
nop
nop
nop
nop
_data_bus_error_handler:
ori r25, r25, 8
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
_divide_by_zero_handler:
ori r25, r25, 16
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
_interrupt_handler:
ori r25, r25, 32
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
_system_call_handler:
ori r25, r25, 64
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
_itlb_miss_handler:
ori r25, r25, 128
rcsr r24, TLBVADDR
ret
nop
nop
nop
nop
nop
_dtlb_miss_handler:
ori r25, r25, 256
rcsr r24, TLBVADDR
addi ra, ea, 4
ret
nop
nop
nop
nop
_dtlb_fault_handler:
ori r25, r25, 512
rcsr r24, TLBVADDR
addi ra, ea, 4
ret
nop
nop
nop
nop
_privilege_exception_handler:
ori r25, r25, 1024
addi ra, ea, 4
ret
nop
nop
nop
nop
nop
OUTPUT_FORMAT("elf32-lm32")
ENTRY(_start)
__DYNAMIC = 0;
MEMORY {
pmem : ORIGIN = 0x00000000, LENGTH = 0x8000
dmem : ORIGIN = 0x00008000, LENGTH = 0x8000
}
SECTIONS
{
.text :
{
_ftext = .;
*(.text .stub .text.* .gnu.linkonce.t.*)
_etext = .;
} > pmem
.rodata :
{
. = ALIGN(4);
_frodata = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
_erodata = .;
} > dmem
.data :
{
. = ALIGN(4);
_fdata = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
_gp = ALIGN(16);
*(.sdata .sdata.* .gnu.linkonce.s.*)
_edata = .;
} > dmem
.bss :
{
. = ALIGN(4);
_fbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
_end = .;
} > dmem
}
PROVIDE(_fstack = ORIGIN(dmem) + LENGTH(dmem) - 4);
.macro test_name name
.data
tn_\name:
.asciz "\name"
.text
mvhi r13, hi(tn_\name)
ori r13, r13, lo(tn_\name)
sw (r12+8), r13
_\name:
.endm
.macro load reg val
mvhi \reg, hi(\val)
ori \reg, \reg, lo(\val)
.endm
.macro tc_pass
mvi r13, 0
sw (r12+4), r13
.endm
.macro tc_fail
mvi r13, 1
sw (r12+4), r13
.endm
.macro check_r3 val
mvhi r13, hi(\val)
ori r13, r13, lo(\val)
be r3, r13, 991f
tc_fail
bi 992f
991:
tc_pass
992:
.endm
.macro check_reg reg val
mvhi r13, hi(\val)
ori r13, r13, lo(\val)
be \reg, r13, 991f
tc_fail
bi 992f
991:
tc_pass
992:
.endm
.macro check_mem adr val
mvhi r13, hi(\adr)
ori r13, r13, lo(\adr)
mvhi r14, hi(\val)
ori r14, r14, lo(\val)
lw r13, (r13+0)
be r13, r14, 991f
tc_fail
bi 992f
991:
tc_pass
992:
.endm
.macro check_excp excp
andi r13, r25, \excp
mv r25, r0
bne r13, r0, 991f
tc_fail
bi 992f
991:
tc_pass
992:
.endm
.macro check_csr csr val
mvhi r13, hi(\val)
ori r13, r13, lo(\val)
rcsr r14, \csr
be r13, r14, 991f
tc_fail
bi 992f
991:
tc_pass
992:
.endm
.macro start
.global _main
.text
_main:
mvhi r12, hi(0xffff0000) # base address of test block
ori r12, r12, lo(0xffff0000)
.endm
.macro end
sw (r12+0), r0
1:
bi 1b
.endm
# base +
# 0 ctrl
# 4 pass/fail
# 8 ptr to test name
.include "macros.inc"
start
test_name ADD_1
mvi r1, 0
mvi r2, 0
add r3, r1, r2
check_r3 0
test_name ADD_2
mvi r1, 0
mvi r2, 1
add r3, r1, r2
check_r3 1
test_name ADD_3
mvi r1, 1
mvi r2, 0
add r3, r1, r2
check_r3 1
test_name ADD_4
mvi r1, 1
mvi r2, -1
add r3, r1, r2
check_r3 0
test_name ADD_5
mvi r1, -1
mvi r2, 1
add r3, r1, r2
check_r3 0
test_name ADD_6
mvi r1, -1
mvi r2, 0
add r3, r1, r2
check_r3 -1
test_name ADD_7
mvi r1, 0
mvi r2, -1
add r3, r1, r2
check_r3 -1
test_name ADD_8
mvi r3, 2
add r3, r3, r3
check_r3 4
test_name ADD_9
mvi r1, 4
mvi r3, 2
add r3, r1, r3
check_r3 6
test_name ADD_10
mvi r1, 4
mvi r3, 2
add r3, r3, r1
check_r3 6
test_name ADD_11
mvi r1, 4
add r3, r1, r1
check_r3 8
test_name ADD_12
load r1 0x12345678
load r2 0xabcdef97
add r3, r1, r2
check_r3 0xbe02460f
end
.include "macros.inc"
start
test_name ADDI_1
mvi r1, 0
addi r3, r1, 0
check_r3 0
test_name ADDI_2
mvi r1, 0
addi r3, r1, 1
check_r3 1
test_name ADDI_3
mvi r1, 1
addi r3, r1, 0
check_r3 1
test_name ADDI_4
mvi r1, 1
addi r3, r1, -1
check_r3 0
test_name ADDI_5
mvi r1, -1
addi r3, r1, 1
check_r3 0
test_name ADDI_6
mvi r1, -1
addi r3, r1, 0
check_r3 -1
test_name ADDI_7
mvi r1, 0
addi r3, r1, -1
check_r3 -1
test_name ADDI_8
mvi r3, 4
addi r3, r3, 4
check_r3 8
test_name ADDI_9
mvi r3, 4
addi r3, r3, -4
check_r3 0
test_name ADDI_10
mvi r3, 4
addi r3, r3, -5
check_r3 -1
end
.include "macros.inc"
start
test_name AND_1
mvi r1, 0
mvi r2, 0
and r3, r1, r2
check_r3 0
test_name AND_2
mvi r1, 0
mvi r2, 1
and r3, r1, r2
check_r3 0
test_name AND_3
mvi r1, 1
mvi r2, 1
and r3, r1, r2
check_r3 1
test_name AND_4
mvi r3, 7
and r3, r3, r3
check_r3 7
test_name AND_5
mvi r1, 7
and r3, r1, r1
check_r3 7
test_name AND_6
mvi r1, 7
mvi r3, 0
and r3, r1, r3
check_r3 0
test_name AND_7
load r1 0xaa55aa55
load r2 0x55aa55aa
and r3, r1, r2
check_r3 0
end
.include "macros.inc"
start
test_name ANDHI_1
mvi r1, 0
andhi r3, r1, 0
check_r3 0
test_name ANDHI_2
mvi r1, 1
andhi r3, r1, 1
check_r3 0
test_name ANDHI_3
load r1 0x000f0000
andhi r3, r1, 1
check_r3 0x00010000
test_name ANDHI_4
load r1 0xffffffff
andhi r3, r1, 0xffff
check_r3 0xffff0000
test_name ANDHI_5
load r1 0xffffffff
andhi r3, r1, 0
check_r3 0
test_name ANDHI_6
load r3 0x55aaffff
andhi r3, r3, 0xaaaa
check_r3 0x00aa0000
end
.include "macros.inc"
start
test_name ANDI_1
mvi r1, 0
andi r3, r1, 0
check_r3 0
test_name ANDI_2
mvi r1, 1
andi r3, r1, 1
check_r3 1
test_name ANDI_3
load r1 0x000f0000
andi r3, r1, 1
check_r3 0
test_name ANDI_4
load r1 0xffffffff
andi r3, r1, 0xffff
check_r3 0xffff
test_name ANDI_5
load r1 0xffffffff
andi r3, r1, 0
check_r3 0
test_name ANDI_6
load r3 0xffff55aa
andi r3, r3, 0xaaaa
check_r3 0x000000aa
end
.include "macros.inc"
start
test_name B_1
load r1 jump
b r1
tc_fail
end
jump:
tc_pass
end
.include "macros.inc"
start
test_name BE_1
mvi r1, 0
mvi r2, 0
be r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BE_2
mvi r1, 1
mvi r2, 0
be r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BE_3
mvi r1, 0
mvi r2, 1
be r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
bi 2f
1:
tc_pass
bi 3f
2:
test_name BE_4
mvi r1, 1
mvi r2, 1
be r1, r2, 1b
tc_fail
3:
end
.include "macros.inc"
start
test_name BG_1
mvi r1, 0
mvi r2, 0
bg r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BG_2
mvi r1, 1
mvi r2, 0
bg r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BG_3
mvi r1, 0
mvi r2, 1
bg r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BG_4
mvi r1, 0
mvi r2, -1
bg r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BG_5
mvi r1, -1
mvi r2, 0
bg r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BG_6
mvi r1, -1
mvi r2, -1
bg r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
bi 2f
1:
tc_pass
bi 3f
2:
test_name BG_7
mvi r1, 1
mvi r2, 0
bg r1, r2, 1b
tc_fail
3:
end
.include "macros.inc"
start
test_name BGE_1
mvi r1, 0
mvi r2, 0
bge r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGE_2
mvi r1, 1
mvi r2, 0
bge r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGE_3
mvi r1, 0
mvi r2, 1
bge r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGE_4
mvi r1, 0
mvi r2, -1
bge r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGE_5
mvi r1, -1
mvi r2, 0
bge r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGE_6
mvi r1, -1
mvi r2, -1
bge r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
bi 2f
1:
tc_pass
bi 3f
2:
test_name BGE_7
mvi r1, 1
mvi r2, 0
bge r1, r2, 1b
tc_fail
3:
end
.include "macros.inc"
start
test_name BGEU_1
mvi r1, 0
mvi r2, 0
bgeu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGEU_2
mvi r1, 1
mvi r2, 0
bgeu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGEU_3
mvi r1, 0
mvi r2, 1
bgeu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGEU_4
mvi r1, 0
mvi r2, -1
bgeu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGEU_5
mvi r1, -1
mvi r2, 0
bgeu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGEU_6
mvi r1, -1
mvi r2, -1
bgeu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
bi 2f
1:
tc_pass
bi 3f
2:
test_name BGEU_7
mvi r1, 1
mvi r2, 0
bgeu r1, r2, 1b
tc_fail
3:
end
.include "macros.inc"
start
test_name BGU_1
mvi r1, 0
mvi r2, 0
bgu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGU_2
mvi r1, 1
mvi r2, 0
bgu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGU_3
mvi r1, 0
mvi r2, 1
bgu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGU_4
mvi r1, 0
mvi r2, -1
bgu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BGU_5
mvi r1, -1
mvi r2, 0
bgu r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BGU_6
mvi r1, -1
mvi r2, -1
bgu r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
bi 2f
1:
tc_pass
bi 3f
2:
test_name BGU_7
mvi r1, 1
mvi r2, 0
bgu r1, r2, 1b
tc_fail
3:
end
.include "macros.inc"
start
test_name BI_1
bi jump
tc_fail
end
jump_back:
tc_pass
end
jump:
tc_pass
test_name BI_2
bi jump_back
tc_fail
end
.include "macros.inc"
start
test_name BNE_1
mvi r1, 0
mvi r2, 0
bne r1, r2, 1f
tc_pass
bi 2f
1:
tc_fail
2:
test_name BNE_2
mvi r1, 1
mvi r2, 0
bne r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
test_name BNE_3
mvi r1, 0
mvi r2, 1
bne r1, r2, 1f
tc_fail
bi 2f
1:
tc_pass
2:
bi 2f
1:
tc_fail
bi 3f
2:
test_name BNE_4
mvi r1, 1
mvi r2, 1
bne r1, r2, 1b
tc_pass
3:
end
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment